aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-10-08 13:15:52 +0000
committermarha <marha@users.sourceforge.net>2009-10-08 13:15:52 +0000
commita0c4815433ccd57322f4f7703ca35e9ccfa59250 (patch)
treef5213802ec12adb86ec3136001c1c29fe5343700 /mesalib/src
parentc73dc01b6de45612b24dc2dd34fba24d81ebf46c (diff)
downloadvcxsrv-a0c4815433ccd57322f4f7703ca35e9ccfa59250.tar.gz
vcxsrv-a0c4815433ccd57322f4f7703ca35e9ccfa59250.tar.bz2
vcxsrv-a0c4815433ccd57322f4f7703ca35e9ccfa59250.zip
Added MesaLib-7.6
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/Makefile40
-rw-r--r--mesalib/src/glu/Makefile40
-rw-r--r--mesalib/src/glu/glu.pc.in13
-rw-r--r--mesalib/src/glu/sgi/Makefile149
-rw-r--r--mesalib/src/glu/sgi/Makefile.mgw230
-rw-r--r--mesalib/src/glu/sgi/Makefile.win149
-rw-r--r--mesalib/src/glu/sgi/dummy.cc4
-rw-r--r--mesalib/src/glu/sgi/glu.def88
-rw-r--r--mesalib/src/glu/sgi/glu.exports118
-rw-r--r--mesalib/src/glu/sgi/glu.exports.darwin59
-rw-r--r--mesalib/src/glu/sgi/include/gluos.h72
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierEval.cc260
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierEval.h48
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.cc206
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.h104
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc610
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h120
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glcurveval.cc402
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glcurveval.h157
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glimports.h42
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glinterface.cc469
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glrenderer.cc301
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glrenderer.h146
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.cc1293
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.h404
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/incurveeval.cc206
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/insurfeval.cc2064
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/mystdio.h60
-rw-r--r--mesalib/src/glu/sgi/libnurbs/interface/mystdlib.h57
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arc.cc347
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arc.h133
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arcsorter.cc172
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arcsorter.h73
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arctess.cc611
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/arctess.h66
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/backend.cc589
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/backend.h113
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.cc138
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.h62
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.cc232
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.h90
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/bezierarc.h51
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/bin.cc166
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/bin.h121
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/bufpool.cc110
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/bufpool.h141
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/cachingeval.cc78
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/cachingeval.h51
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/ccw.cc565
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.cc440
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.h72
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/curve.cc198
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/curve.h70
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/curvelist.cc110
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/curvelist.h62
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/curvesub.cc103
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/dataTransform.cc209
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/dataTransform.h59
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/defines.h50
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/displaylist.cc82
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/displaylist.h78
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/displaymode.h40
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/flist.cc118
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/flist.h59
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/flistsorter.cc81
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/flistsorter.h53
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/gridline.h46
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/gridtrimvertex.h89
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/gridvertex.h48
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/hull.cc165
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/hull.h69
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/intersect.cc665
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/jarcloc.h87
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/knotvector.cc139
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/knotvector.h62
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mapdesc.cc841
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mapdesc.h271
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mapdescv.cc243
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/maplist.cc117
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/maplist.h81
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mesher.cc486
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mesher.h83
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc397
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/monotonizer.cc260
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/monotonizer.h64
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/myassert.h51
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mycode.cc67
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mymath.h68
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mysetjmp.h85
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/mystring.h56
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/nurbsconsts.h120
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc537
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/nurbstess.cc691
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/nurbstess.h172
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/patch.cc504
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/patch.h94
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/patchlist.cc170
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/patchlist.h92
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/pwlarc.h78
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/quilt.cc276
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/quilt.h92
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/reader.cc146
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/reader.h132
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/renderhints.cc133
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/renderhints.h60
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/simplemath.h50
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/slicer.cc1300
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/slicer.h84
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/sorter.cc139
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/sorter.h51
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/splitarcs.cc293
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/subdivider.cc910
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/subdivider.h200
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/tobezier.cc687
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimline.cc223
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimline.h103
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimregion.cc114
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimregion.h84
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimvertex.h63
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.cc119
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.h57
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/types.h47
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/uarray.cc72
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/uarray.h55
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/varray.cc144
-rw-r--r--mesalib/src/glu/sgi/libnurbs/internals/varray.h68
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h40
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc848
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h171
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h42
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc293
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h137
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc934
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h103
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc299
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h41
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc1482
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h184
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h60
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h57
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc162
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h54
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc836
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h97
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc734
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h68
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc90
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h47
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc190
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h109
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc77
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h42
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc196
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h82
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc371
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h86
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc844
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h138
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc644
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h117
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc1030
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h67
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc2427
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h184
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc179
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h71
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc282
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h61
-rw-r--r--mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h34
-rw-r--r--mesalib/src/glu/sgi/libtess/README446
-rw-r--r--mesalib/src/glu/sgi/libtess/alg-outline228
-rw-r--r--mesalib/src/glu/sgi/libtess/dict-list.h100
-rw-r--r--mesalib/src/glu/sgi/libtess/dict.c111
-rw-r--r--mesalib/src/glu/sgi/libtess/dict.h100
-rw-r--r--mesalib/src/glu/sgi/libtess/geom.c264
-rw-r--r--mesalib/src/glu/sgi/libtess/geom.h84
-rw-r--r--mesalib/src/glu/sgi/libtess/memalloc.c55
-rw-r--r--mesalib/src/glu/sgi/libtess/memalloc.h54
-rw-r--r--mesalib/src/glu/sgi/libtess/mesh.c789
-rw-r--r--mesalib/src/glu/sgi/libtess/mesh.h266
-rw-r--r--mesalib/src/glu/sgi/libtess/normal.c253
-rw-r--r--mesalib/src/glu/sgi/libtess/normal.h45
-rw-r--r--mesalib/src/glu/sgi/libtess/priorityq-heap.c252
-rw-r--r--mesalib/src/glu/sgi/libtess/priorityq-heap.h107
-rw-r--r--mesalib/src/glu/sgi/libtess/priorityq-sort.h117
-rw-r--r--mesalib/src/glu/sgi/libtess/priorityq.c260
-rw-r--r--mesalib/src/glu/sgi/libtess/priorityq.h117
-rw-r--r--mesalib/src/glu/sgi/libtess/render.c498
-rw-r--r--mesalib/src/glu/sgi/libtess/render.h52
-rw-r--r--mesalib/src/glu/sgi/libtess/sweep.c1357
-rw-r--r--mesalib/src/glu/sgi/libtess/sweep.h77
-rw-r--r--mesalib/src/glu/sgi/libtess/tess.c628
-rw-r--r--mesalib/src/glu/sgi/libtess/tess.h165
-rw-r--r--mesalib/src/glu/sgi/libtess/tessmono.c201
-rw-r--r--mesalib/src/glu/sgi/libtess/tessmono.h71
-rw-r--r--mesalib/src/glu/sgi/libutil/error.c83
-rw-r--r--mesalib/src/glu/sgi/libutil/glue.c93
-rw-r--r--mesalib/src/glu/sgi/libutil/gluint.h48
-rw-r--r--mesalib/src/glu/sgi/libutil/mipmap.c8931
-rw-r--r--mesalib/src/glu/sgi/libutil/project.c359
-rw-r--r--mesalib/src/glu/sgi/libutil/quad.c1155
-rw-r--r--mesalib/src/glu/sgi/libutil/registry.c91
-rw-r--r--mesalib/src/mesa/Makefile166
-rw-r--r--mesalib/src/mesa/Makefile.mgw235
-rw-r--r--mesalib/src/mesa/depend0
-rw-r--r--mesalib/src/mesa/descrip.mms27
-rw-r--r--mesalib/src/mesa/drivers/Makefile29
-rw-r--r--mesalib/src/mesa/drivers/common/descrip.mms42
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.c353
-rw-r--r--mesalib/src/mesa/drivers/common/driverfuncs.h37
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c1638
-rw-r--r--mesalib/src/mesa/drivers/common/meta.h81
-rw-r--r--mesalib/src/mesa/drivers/dri/Makefile55
-rw-r--r--mesalib/src/mesa/drivers/dri/Makefile.template99
-rw-r--r--mesalib/src/mesa/drivers/dri/common/depthtmp.h270
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_metaops.c298
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_metaops.h81
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.c957
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.h555
-rw-r--r--mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c217
-rw-r--r--mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h78
-rw-r--r--mesalib/src/mesa/drivers/dri/common/extension_helper.h6609
-rw-r--r--mesalib/src/mesa/drivers/dri/common/memops.h17
-rw-r--r--mesalib/src/mesa/drivers/dri/common/mmio.h62
-rw-r--r--mesalib/src/mesa/drivers/dri/common/mmx.h560
-rw-r--r--mesalib/src/mesa/drivers/dri/common/spantmp.h338
-rw-r--r--mesalib/src/mesa/drivers/dri/common/spantmp2.h686
-rw-r--r--mesalib/src/mesa/drivers/dri/common/spantmp_common.h81
-rw-r--r--mesalib/src/mesa/drivers/dri/common/stenciltmp.h245
-rw-r--r--mesalib/src/mesa/drivers/dri/common/texmem.c1347
-rw-r--r--mesalib/src/mesa/drivers/dri/common/texmem.h333
-rw-r--r--mesalib/src/mesa/drivers/dri/common/utils.c839
-rw-r--r--mesalib/src/mesa/drivers/dri/common/utils.h147
-rw-r--r--mesalib/src/mesa/drivers/dri/common/vblank.c434
-rw-r--r--mesalib/src/mesa/drivers/dri/common/vblank.h75
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlconfig.c1008
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlconfig.h124
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool.h98
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile96
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/de.po240
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/es.po219
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/fr.po225
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/nl.po230
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/options.h568
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/sv.po226
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h249
-rw-r--r--mesalib/src/mesa/drivers/dri/dri.pc.in11
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/Makefile24
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast.c754
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h144
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_span.c439
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h328
-rw-r--r--mesalib/src/mesa/drivers/windows/fx/fxopengl.def955
-rw-r--r--mesalib/src/mesa/drivers/windows/fx/fxwgl.c1307
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/colors.h29
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/mesa.def979
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wgl.c707
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wmesa.c1681
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wmesadef.h43
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/ddlog.c192
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/ddlog.h109
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c2214
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h281
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglglobals.c149
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglglobals.h198
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglmacros.h91
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglpf.c620
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglpf.h77
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c2964
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h127
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dll_main.c817
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/dllmain.h64
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_debug_clip.c39
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_debug_norm.c39
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_debug_xform.c41
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_dispatch.c73
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c279
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h90
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/gldlame8.c181
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/opengl32.def488
-rw-r--r--mesalib/src/mesa/drivers/windows/gldirect/pixpack.h108
-rw-r--r--mesalib/src/mesa/drivers/windows/icd/icd.c347
-rw-r--r--mesalib/src/mesa/drivers/windows/icd/icdlist.h336
-rw-r--r--mesalib/src/mesa/drivers/windows/icd/mesa.def108
-rw-r--r--mesalib/src/mesa/gl.pc.in12
-rw-r--r--mesalib/src/mesa/glapi/dispatch.h3985
-rw-r--r--mesalib/src/mesa/glapi/glapi.c650
-rw-r--r--mesalib/src/mesa/glapi/glapi.h171
-rw-r--r--mesalib/src/mesa/glapi/glapi_getproc.c592
-rw-r--r--mesalib/src/mesa/glapi/glapioffsets.h1218
-rw-r--r--mesalib/src/mesa/glapi/glapitable.h837
-rw-r--r--mesalib/src/mesa/glapi/glapitemp.h6921
-rw-r--r--mesalib/src/mesa/glapi/glprocs.h2353
-rw-r--r--mesalib/src/mesa/glapi/glthread.c326
-rw-r--r--mesalib/src/mesa/glapi/glthread.h333
-rw-r--r--mesalib/src/mesa/main/accum.c108
-rw-r--r--mesalib/src/mesa/main/accum.h62
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.c1319
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.h42
-rw-r--r--mesalib/src/mesa/main/api_exec.c925
-rw-r--r--mesalib/src/mesa/main/api_exec.h37
-rw-r--r--mesalib/src/mesa/main/api_loopback.c1657
-rw-r--r--mesalib/src/mesa/main/api_loopback.h37
-rw-r--r--mesalib/src/mesa/main/api_noop.c1000
-rw-r--r--mesalib/src/mesa/main/api_noop.h50
-rw-r--r--mesalib/src/mesa/main/api_validate.c300
-rw-r--r--mesalib/src/mesa/main/api_validate.h55
-rw-r--r--mesalib/src/mesa/main/arrayobj.c572
-rw-r--r--mesalib/src/mesa/main/arrayobj.h83
-rw-r--r--mesalib/src/mesa/main/attrib.c1501
-rw-r--r--mesalib/src/mesa/main/attrib.h60
-rw-r--r--mesalib/src/mesa/main/bitset.h122
-rw-r--r--mesalib/src/mesa/main/blend.c592
-rw-r--r--mesalib/src/mesa/main/blend.h83
-rw-r--r--mesalib/src/mesa/main/bufferobj.c1678
-rw-r--r--mesalib/src/mesa/main/bufferobj.h172
-rw-r--r--mesalib/src/mesa/main/buffers.c502
-rw-r--r--mesalib/src/mesa/main/buffers.h56
-rw-r--r--mesalib/src/mesa/main/clear.c184
-rw-r--r--mesalib/src/mesa/main/clear.h44
-rw-r--r--mesalib/src/mesa/main/clip.c159
-rw-r--r--mesalib/src/mesa/main/clip.h49
-rw-r--r--mesalib/src/mesa/main/colormac.h222
-rw-r--r--mesalib/src/mesa/main/colortab.c1102
-rw-r--r--mesalib/src/mesa/main/colortab.h100
-rw-r--r--mesalib/src/mesa/main/compiler.h484
-rw-r--r--mesalib/src/mesa/main/config.h323
-rw-r--r--mesalib/src/mesa/main/context.c1672
-rw-r--r--mesalib/src/mesa/main/context.h308
-rw-r--r--mesalib/src/mesa/main/convolve.c1427
-rw-r--r--mesalib/src/mesa/main/convolve.h114
-rw-r--r--mesalib/src/mesa/main/cpuinfo.c109
-rw-r--r--mesalib/src/mesa/main/cpuinfo.h47
-rw-r--r--mesalib/src/mesa/main/dd.h1195
-rw-r--r--mesalib/src/mesa/main/debug.c440
-rw-r--r--mesalib/src/mesa/main/debug.h72
-rw-r--r--mesalib/src/mesa/main/depth.c162
-rw-r--r--mesalib/src/mesa/main/depth.h62
-rw-r--r--mesalib/src/mesa/main/depthstencil.c655
-rw-r--r--mesalib/src/mesa/main/depthstencil.h56
-rw-r--r--mesalib/src/mesa/main/descrip.mms258
-rw-r--r--mesalib/src/mesa/main/dispatch.c96
-rw-r--r--mesalib/src/mesa/main/dlist.c9402
-rw-r--r--mesalib/src/mesa/main/dlist.h96
-rw-r--r--mesalib/src/mesa/main/dlopen.c101
-rw-r--r--mesalib/src/mesa/main/dlopen.h42
-rw-r--r--mesalib/src/mesa/main/drawpix.c311
-rw-r--r--mesalib/src/mesa/main/drawpix.h49
-rw-r--r--mesalib/src/mesa/main/enable.c1407
-rw-r--r--mesalib/src/mesa/main/enable.h57
-rw-r--r--mesalib/src/mesa/main/enums.c5201
-rw-r--r--mesalib/src/mesa/main/enums.h61
-rw-r--r--mesalib/src/mesa/main/eval.c962
-rw-r--r--mesalib/src/mesa/main/eval.h128
-rw-r--r--mesalib/src/mesa/main/execmem.c155
-rw-r--r--mesalib/src/mesa/main/extensions.c675
-rw-r--r--mesalib/src/mesa/main/extensions.h86
-rw-r--r--mesalib/src/mesa/main/fbobject.c2103
-rw-r--r--mesalib/src/mesa/main/fbobject.h146
-rw-r--r--mesalib/src/mesa/main/feedback.c536
-rw-r--r--mesalib/src/mesa/main/feedback.h83
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c1672
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.h40
-rw-r--r--mesalib/src/mesa/main/fog.c188
-rw-r--r--mesalib/src/mesa/main/fog.h66
-rw-r--r--mesalib/src/mesa/main/framebuffer.c961
-rw-r--r--mesalib/src/mesa/main/framebuffer.h85
-rw-r--r--mesalib/src/mesa/main/get.c7419
-rw-r--r--mesalib/src/mesa/main/get.h62
-rw-r--r--mesalib/src/mesa/main/getstring.c271
-rw-r--r--mesalib/src/mesa/main/glheader.h88
-rw-r--r--mesalib/src/mesa/main/hash.c530
-rw-r--r--mesalib/src/mesa/main/hash.h69
-rw-r--r--mesalib/src/mesa/main/hint.c149
-rw-r--r--mesalib/src/mesa/main/hint.h57
-rw-r--r--mesalib/src/mesa/main/histogram.c1078
-rw-r--r--mesalib/src/mesa/main/histogram.h83
-rw-r--r--mesalib/src/mesa/main/image.c5820
-rw-r--r--mesalib/src/mesa/main/image.h328
-rw-r--r--mesalib/src/mesa/main/imports.c1231
-rw-r--r--mesalib/src/mesa/main/imports.h630
-rw-r--r--mesalib/src/mesa/main/light.c1427
-rw-r--r--mesalib/src/mesa/main/light.h146
-rw-r--r--mesalib/src/mesa/main/lines.c118
-rw-r--r--mesalib/src/mesa/main/lines.h48
-rw-r--r--mesalib/src/mesa/main/macros.h695
-rw-r--r--mesalib/src/mesa/main/matrix.c793
-rw-r--r--mesalib/src/mesa/main/matrix.h112
-rw-r--r--mesalib/src/mesa/main/mfeatures.h86
-rw-r--r--mesalib/src/mesa/main/mipmap.c1794
-rw-r--r--mesalib/src/mesa/main/mipmap.h64
-rw-r--r--mesalib/src/mesa/main/mm.c278
-rw-r--r--mesalib/src/mesa/main/mm.h93
-rw-r--r--mesalib/src/mesa/main/mtypes.h3139
-rw-r--r--mesalib/src/mesa/main/multisample.c61
-rw-r--r--mesalib/src/mesa/main/multisample.h38
-rw-r--r--mesalib/src/mesa/main/pixel.c845
-rw-r--r--mesalib/src/mesa/main/pixel.h80
-rw-r--r--mesalib/src/mesa/main/pixelstore.c286
-rw-r--r--mesalib/src/mesa/main/pixelstore.h50
-rw-r--r--mesalib/src/mesa/main/points.c263
-rw-r--r--mesalib/src/mesa/main/points.h57
-rw-r--r--mesalib/src/mesa/main/polygon.c322
-rw-r--r--mesalib/src/mesa/main/polygon.h66
-rw-r--r--mesalib/src/mesa/main/queryobj.c576
-rw-r--r--mesalib/src/mesa/main/queryobj.h71
-rw-r--r--mesalib/src/mesa/main/rastpos.c508
-rw-r--r--mesalib/src/mesa/main/rastpos.h193
-rw-r--r--mesalib/src/mesa/main/rbadaptors.c577
-rw-r--r--mesalib/src/mesa/main/rbadaptors.h40
-rw-r--r--mesalib/src/mesa/main/readpix.c210
-rw-r--r--mesalib/src/mesa/main/readpix.h42
-rw-r--r--mesalib/src/mesa/main/renderbuffer.c2209
-rw-r--r--mesalib/src/mesa/main/renderbuffer.h112
-rw-r--r--mesalib/src/mesa/main/scissor.c99
-rw-r--r--mesalib/src/mesa/main/scissor.h46
-rw-r--r--mesalib/src/mesa/main/shaders.c728
-rw-r--r--mesalib/src/mesa/main/shaders.h236
-rw-r--r--mesalib/src/mesa/main/shared.c374
-rw-r--r--mesalib/src/mesa/main/shared.h37
-rw-r--r--mesalib/src/mesa/main/simple_list.h202
-rw-r--r--mesalib/src/mesa/main/state.c718
-rw-r--r--mesalib/src/mesa/main/state.h49
-rw-r--r--mesalib/src/mesa/main/stencil.c590
-rw-r--r--mesalib/src/mesa/main/stencil.h80
-rw-r--r--mesalib/src/mesa/main/syncobj.c409
-rw-r--r--mesalib/src/mesa/main/syncobj.h70
-rw-r--r--mesalib/src/mesa/main/texcompress.c362
-rw-r--r--mesalib/src/mesa/main/texcompress.h74
-rw-r--r--mesalib/src/mesa/main/texcompress_fxt1.c1724
-rw-r--r--mesalib/src/mesa/main/texcompress_s3tc.c761
-rw-r--r--mesalib/src/mesa/main/texenv.c1078
-rw-r--r--mesalib/src/mesa/main/texenv.h63
-rw-r--r--mesalib/src/mesa/main/texenvprogram.c1579
-rw-r--r--mesalib/src/mesa/main/texenvprogram.h35
-rw-r--r--mesalib/src/mesa/main/texformat.c1989
-rw-r--r--mesalib/src/mesa/main/texformat.h293
-rw-r--r--mesalib/src/mesa/main/texformat_tmp.h1474
-rw-r--r--mesalib/src/mesa/main/texgen.c339
-rw-r--r--mesalib/src/mesa/main/texgen.h62
-rw-r--r--mesalib/src/mesa/main/texgetimage.c581
-rw-r--r--mesalib/src/mesa/main/texgetimage.h55
-rw-r--r--mesalib/src/mesa/main/teximage.c3660
-rw-r--r--mesalib/src/mesa/main/teximage.h260
-rw-r--r--mesalib/src/mesa/main/texobj.c1237
-rw-r--r--mesalib/src/mesa/main/texobj.h118
-rw-r--r--mesalib/src/mesa/main/texparam.c1285
-rw-r--r--mesalib/src/mesa/main/texparam.h63
-rw-r--r--mesalib/src/mesa/main/texrender.c567
-rw-r--r--mesalib/src/mesa/main/texrender.h15
-rw-r--r--mesalib/src/mesa/main/texstate.c823
-rw-r--r--mesalib/src/mesa/main/texstate.h91
-rw-r--r--mesalib/src/mesa/main/texstore.c3925
-rw-r--r--mesalib/src/mesa/main/texstore.h231
-rw-r--r--mesalib/src/mesa/main/varray.c1187
-rw-r--r--mesalib/src/mesa/main/varray.h186
-rw-r--r--mesalib/src/mesa/main/version.h53
-rw-r--r--mesalib/src/mesa/main/viewport.c180
-rw-r--r--mesalib/src/mesa/main/viewport.h52
-rw-r--r--mesalib/src/mesa/main/vsnprintf.c165
-rw-r--r--mesalib/src/mesa/main/vtxfmt.c195
-rw-r--r--mesalib/src/mesa/main/vtxfmt.h43
-rw-r--r--mesalib/src/mesa/main/vtxfmt_tmp.h542
-rw-r--r--mesalib/src/mesa/math/descrip.mms47
-rw-r--r--mesalib/src/mesa/math/m_clip_tmp.h243
-rw-r--r--mesalib/src/mesa/math/m_copy_tmp.h86
-rw-r--r--mesalib/src/mesa/math/m_debug.h42
-rw-r--r--mesalib/src/mesa/math/m_debug_clip.c371
-rw-r--r--mesalib/src/mesa/math/m_debug_norm.c383
-rw-r--r--mesalib/src/mesa/math/m_debug_util.h320
-rw-r--r--mesalib/src/mesa/math/m_debug_xform.c339
-rw-r--r--mesalib/src/mesa/math/m_dotprod_tmp.h102
-rw-r--r--mesalib/src/mesa/math/m_eval.c461
-rw-r--r--mesalib/src/mesa/math/m_eval.h103
-rw-r--r--mesalib/src/mesa/math/m_matrix.c1642
-rw-r--r--mesalib/src/mesa/math/m_matrix.h210
-rw-r--r--mesalib/src/mesa/math/m_norm_tmp.h390
-rw-r--r--mesalib/src/mesa/math/m_trans_tmp.h281
-rw-r--r--mesalib/src/mesa/math/m_translate.c751
-rw-r--r--mesalib/src/mesa/math/m_translate.h122
-rw-r--r--mesalib/src/mesa/math/m_vector.c185
-rw-r--r--mesalib/src/mesa/math/m_vector.h92
-rw-r--r--mesalib/src/mesa/math/m_xform.c128
-rw-r--r--mesalib/src/mesa/math/m_xform.h166
-rw-r--r--mesalib/src/mesa/math/m_xform_tmp.h810
-rw-r--r--mesalib/src/mesa/osmesa.pc.in12
-rw-r--r--mesalib/src/mesa/shader/Makefile7
-rw-r--r--mesalib/src/mesa/shader/arbprogparse.c212
-rw-r--r--mesalib/src/mesa/shader/arbprogparse.h41
-rw-r--r--mesalib/src/mesa/shader/arbprogram.c1042
-rw-r--r--mesalib/src/mesa/shader/arbprogram.h152
-rw-r--r--mesalib/src/mesa/shader/atifragshader.c759
-rw-r--r--mesalib/src/mesa/shader/atifragshader.h123
-rw-r--r--mesalib/src/mesa/shader/descrip.mms95
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar.c3178
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar.h103
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar_crt.c64
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar_crt.h20
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar_mesa.c87
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar_mesa.h43
-rw-r--r--mesalib/src/mesa/shader/grammar/grammar_syn.h202
-rw-r--r--mesalib/src/mesa/shader/hash_table.c163
-rw-r--r--mesalib/src/mesa/shader/hash_table.h117
-rw-r--r--mesalib/src/mesa/shader/lex.yy.c3574
-rw-r--r--mesalib/src/mesa/shader/nvfragparse.c1582
-rw-r--r--mesalib/src/mesa/shader/nvfragparse.h43
-rw-r--r--mesalib/src/mesa/shader/nvprogram.c890
-rw-r--r--mesalib/src/mesa/shader/nvprogram.h113
-rw-r--r--mesalib/src/mesa/shader/nvvertparse.c1455
-rw-r--r--mesalib/src/mesa/shader/nvvertparse.h45
-rw-r--r--mesalib/src/mesa/shader/prog_cache.c206
-rw-r--r--mesalib/src/mesa/shader/prog_cache.h55
-rw-r--r--mesalib/src/mesa/shader/prog_execute.c1757
-rw-r--r--mesalib/src/mesa/shader/prog_execute.h85
-rw-r--r--mesalib/src/mesa/shader/prog_instruction.c352
-rw-r--r--mesalib/src/mesa/shader/prog_instruction.h439
-rw-r--r--mesalib/src/mesa/shader/prog_noise.c638
-rw-r--r--mesalib/src/mesa/shader/prog_noise.h34
-rw-r--r--mesalib/src/mesa/shader/prog_optimize.c832
-rw-r--r--mesalib/src/mesa/shader/prog_optimize.h45
-rw-r--r--mesalib/src/mesa/shader/prog_parameter.c750
-rw-r--r--mesalib/src/mesa/shader/prog_parameter.h174
-rw-r--r--mesalib/src/mesa/shader/prog_parameter_layout.c217
-rw-r--r--mesalib/src/mesa/shader/prog_parameter_layout.h42
-rw-r--r--mesalib/src/mesa/shader/prog_print.c1019
-rw-r--r--mesalib/src/mesa/shader/prog_print.h94
-rw-r--r--mesalib/src/mesa/shader/prog_statevars.c1120
-rw-r--r--mesalib/src/mesa/shader/prog_statevars.h145
-rw-r--r--mesalib/src/mesa/shader/prog_uniform.c165
-rw-r--r--mesalib/src/mesa/shader/prog_uniform.h92
-rw-r--r--mesalib/src/mesa/shader/program.c889
-rw-r--r--mesalib/src/mesa/shader/program.h129
-rw-r--r--mesalib/src/mesa/shader/program_lexer.l489
-rw-r--r--mesalib/src/mesa/shader/program_parse.tab.c5249
-rw-r--r--mesalib/src/mesa/shader/program_parse.tab.h207
-rw-r--r--mesalib/src/mesa/shader/program_parse.y2379
-rw-r--r--mesalib/src/mesa/shader/program_parse_extra.c117
-rw-r--r--mesalib/src/mesa/shader/program_parser.h266
-rw-r--r--mesalib/src/mesa/shader/programopt.c575
-rw-r--r--mesalib/src/mesa/shader/programopt.h45
-rw-r--r--mesalib/src/mesa/shader/shader_api.c2154
-rw-r--r--mesalib/src/mesa/shader/shader_api.h100
-rw-r--r--mesalib/src/mesa/shader/slang/descrip.mms68
-rw-r--r--mesalib/src/mesa/shader/slang/library/Makefile81
-rw-r--r--mesalib/src/mesa/shader/slang/library/gc_to_bin.c85
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_120_core.gc1978
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_120_core_gc.h764
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_builtin_120_common.gc200
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h108
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc30
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h5
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_common_builtin.gc1873
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_common_builtin_gc.h872
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_core.gc2619
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_core_gc.h869
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_fragment_builtin.gc235
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h110
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_directives.syn405
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_directives_syn.h250
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_expression.syn265
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_expression_syn.h179
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_version.syn122
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_pp_version_syn.h69
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_shader.syn1716
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_shader_syn.h866
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_version.syn118
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_vertex_builtin.gc190
-rw-r--r--mesalib/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h109
-rw-r--r--mesalib/src/mesa/shader/slang/library/syn_to_c.c72
-rw-r--r--mesalib/src/mesa/shader/slang/slang_builtin.c895
-rw-r--r--mesalib/src/mesa/shader/slang/slang_builtin.h54
-rw-r--r--mesalib/src/mesa/shader/slang/slang_codegen.c5319
-rw-r--r--mesalib/src/mesa/shader/slang/slang_codegen.h72
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile.c2825
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile.h100
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_function.c262
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_function.h92
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_operation.c332
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_operation.h226
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_struct.c174
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_struct.h66
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_variable.c247
-rw-r--r--mesalib/src/mesa/shader/slang/slang_compile_variable.h90
-rw-r--r--mesalib/src/mesa/shader/slang/slang_emit.c2518
-rw-r--r--mesalib/src/mesa/shader/slang/slang_emit.h51
-rw-r--r--mesalib/src/mesa/shader/slang/slang_ir.c497
-rw-r--r--mesalib/src/mesa/shader/slang/slang_ir.h279
-rw-r--r--mesalib/src/mesa/shader/slang/slang_label.c104
-rw-r--r--mesalib/src/mesa/shader/slang/slang_label.h45
-rw-r--r--mesalib/src/mesa/shader/slang/slang_link.c898
-rw-r--r--mesalib/src/mesa/shader/slang/slang_link.h37
-rw-r--r--mesalib/src/mesa/shader/slang/slang_log.c134
-rw-r--r--mesalib/src/mesa/shader/slang/slang_log.h57
-rw-r--r--mesalib/src/mesa/shader/slang/slang_mem.c243
-rw-r--r--mesalib/src/mesa/shader/slang/slang_mem.h55
-rw-r--r--mesalib/src/mesa/shader/slang/slang_preprocess.c1406
-rw-r--r--mesalib/src/mesa/shader/slang/slang_preprocess.h41
-rw-r--r--mesalib/src/mesa/shader/slang/slang_print.c883
-rw-r--r--mesalib/src/mesa/shader/slang/slang_print.h29
-rw-r--r--mesalib/src/mesa/shader/slang/slang_simplify.c526
-rw-r--r--mesalib/src/mesa/shader/slang/slang_simplify.h50
-rw-r--r--mesalib/src/mesa/shader/slang/slang_storage.c316
-rw-r--r--mesalib/src/mesa/shader/slang/slang_storage.h139
-rw-r--r--mesalib/src/mesa/shader/slang/slang_typeinfo.c1138
-rw-r--r--mesalib/src/mesa/shader/slang/slang_typeinfo.h239
-rw-r--r--mesalib/src/mesa/shader/slang/slang_utility.c228
-rw-r--r--mesalib/src/mesa/shader/slang/slang_utility.h100
-rw-r--r--mesalib/src/mesa/shader/slang/slang_vartable.c362
-rw-r--r--mesalib/src/mesa/shader/slang/slang_vartable.h42
-rw-r--r--mesalib/src/mesa/shader/symbol_table.c350
-rw-r--r--mesalib/src/mesa/shader/symbol_table.h55
-rw-r--r--mesalib/src/mesa/sources.mak375
-rw-r--r--mesalib/src/mesa/swrast/descrip.mms82
-rw-r--r--mesalib/src/mesa/swrast/s_aaline.c524
-rw-r--r--mesalib/src/mesa/swrast/s_aaline.h38
-rw-r--r--mesalib/src/mesa/swrast/s_aalinetemp.h274
-rw-r--r--mesalib/src/mesa/swrast/s_aatriangle.c417
-rw-r--r--mesalib/src/mesa/swrast/s_aatriangle.h38
-rw-r--r--mesalib/src/mesa/swrast/s_aatritemp.h383
-rw-r--r--mesalib/src/mesa/swrast/s_accum.c599
-rw-r--r--mesalib/src/mesa/swrast/s_accum.h37
-rw-r--r--mesalib/src/mesa/swrast/s_alpha.c160
-rw-r--r--mesalib/src/mesa/swrast/s_alpha.h38
-rw-r--r--mesalib/src/mesa/swrast/s_atifragshader.c604
-rw-r--r--mesalib/src/mesa/swrast/s_atifragshader.h37
-rw-r--r--mesalib/src/mesa/swrast/s_bitmap.c228
-rw-r--r--mesalib/src/mesa/swrast/s_blend.c1002
-rw-r--r--mesalib/src/mesa/swrast/s_blend.h41
-rw-r--r--mesalib/src/mesa/swrast/s_blit.c615
-rw-r--r--mesalib/src/mesa/swrast/s_clear.c344
-rw-r--r--mesalib/src/mesa/swrast/s_context.c957
-rw-r--r--mesalib/src/mesa/swrast/s_context.h348
-rw-r--r--mesalib/src/mesa/swrast/s_copypix.c932
-rw-r--r--mesalib/src/mesa/swrast/s_depth.c1429
-rw-r--r--mesalib/src/mesa/swrast/s_depth.h55
-rw-r--r--mesalib/src/mesa/swrast/s_drawpix.c898
-rw-r--r--mesalib/src/mesa/swrast/s_feedback.c140
-rw-r--r--mesalib/src/mesa/swrast/s_feedback.h50
-rw-r--r--mesalib/src/mesa/swrast/s_fog.c330
-rw-r--r--mesalib/src/mesa/swrast/s_fog.h44
-rw-r--r--mesalib/src/mesa/swrast/s_fragprog.c269
-rw-r--r--mesalib/src/mesa/swrast/s_fragprog.h38
-rw-r--r--mesalib/src/mesa/swrast/s_imaging.c196
-rw-r--r--mesalib/src/mesa/swrast/s_lines.c307
-rw-r--r--mesalib/src/mesa/swrast/s_lines.h41
-rw-r--r--mesalib/src/mesa/swrast/s_linetemp.h421
-rw-r--r--mesalib/src/mesa/swrast/s_logic.c246
-rw-r--r--mesalib/src/mesa/swrast/s_logic.h43
-rw-r--r--mesalib/src/mesa/swrast/s_masking.c134
-rw-r--r--mesalib/src/mesa/swrast/s_masking.h42
-rw-r--r--mesalib/src/mesa/swrast/s_points.c598
-rw-r--r--mesalib/src/mesa/swrast/s_points.h39
-rw-r--r--mesalib/src/mesa/swrast/s_readpix.c620
-rw-r--r--mesalib/src/mesa/swrast/s_span.c1795
-rw-r--r--mesalib/src/mesa/swrast/s_span.h226
-rw-r--r--mesalib/src/mesa/swrast/s_spantemp.h235
-rw-r--r--mesalib/src/mesa/swrast/s_stencil.c1245
-rw-r--r--mesalib/src/mesa/swrast/s_stencil.h52
-rw-r--r--mesalib/src/mesa/swrast/s_texcombine.c710
-rw-r--r--mesalib/src/mesa/swrast/s_texcombine.h35
-rw-r--r--mesalib/src/mesa/swrast/s_texfilter.c3266
-rw-r--r--mesalib/src/mesa/swrast/s_texfilter.h38
-rw-r--r--mesalib/src/mesa/swrast/s_texstore.c601
-rw-r--r--mesalib/src/mesa/swrast/s_triangle.c1150
-rw-r--r--mesalib/src/mesa/swrast/s_triangle.h50
-rw-r--r--mesalib/src/mesa/swrast/s_trispan.h31
-rw-r--r--mesalib/src/mesa/swrast/s_tritemp.h979
-rw-r--r--mesalib/src/mesa/swrast/s_zoom.c477
-rw-r--r--mesalib/src/mesa/swrast/s_zoom.h59
-rw-r--r--mesalib/src/mesa/swrast/swrast.h292
-rw-r--r--mesalib/src/mesa/swrast_setup/descrip.mms42
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_context.c317
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_context.h46
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_triangle.c317
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_triangle.h38
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_tritmp.h266
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_vb.h38
-rw-r--r--mesalib/src/mesa/swrast_setup/swrast_setup.h61
-rw-r--r--mesalib/src/mesa/tnl/descrip.mms68
-rw-r--r--mesalib/src/mesa/tnl/t_context.c231
-rw-r--r--mesalib/src/mesa/tnl/t_context.h551
-rw-r--r--mesalib/src/mesa/tnl/t_draw.c451
-rw-r--r--mesalib/src/mesa/tnl/t_pipeline.c215
-rw-r--r--mesalib/src/mesa/tnl/t_pipeline.h74
-rw-r--r--mesalib/src/mesa/tnl/t_rasterpos.c505
-rw-r--r--mesalib/src/mesa/tnl/t_vb_cliptmp.h320
-rw-r--r--mesalib/src/mesa/tnl/t_vb_cull.c97
-rw-r--r--mesalib/src/mesa/tnl/t_vb_fog.c277
-rw-r--r--mesalib/src/mesa/tnl/t_vb_light.c362
-rw-r--r--mesalib/src/mesa/tnl/t_vb_lighttmp.h824
-rw-r--r--mesalib/src/mesa/tnl/t_vb_normals.c189
-rw-r--r--mesalib/src/mesa/tnl/t_vb_points.c114
-rw-r--r--mesalib/src/mesa/tnl/t_vb_program.c563
-rw-r--r--mesalib/src/mesa/tnl/t_vb_render.c347
-rw-r--r--mesalib/src/mesa/tnl/t_vb_rendertmp.h486
-rw-r--r--mesalib/src/mesa/tnl/t_vb_texgen.c611
-rw-r--r--mesalib/src/mesa/tnl/t_vb_texmat.c130
-rw-r--r--mesalib/src/mesa/tnl/t_vb_vertex.c264
-rw-r--r--mesalib/src/mesa/tnl/t_vertex.c564
-rw-r--r--mesalib/src/mesa/tnl/t_vertex.h181
-rw-r--r--mesalib/src/mesa/tnl/t_vertex_generic.c1155
-rw-r--r--mesalib/src/mesa/tnl/t_vertex_sse.c684
-rw-r--r--mesalib/src/mesa/tnl/t_vp_build.c60
-rw-r--r--mesalib/src/mesa/tnl/t_vp_build.h42
-rw-r--r--mesalib/src/mesa/tnl/tnl.h100
-rw-r--r--mesalib/src/mesa/vbo/descrip.mms62
-rw-r--r--mesalib/src/mesa/vbo/vbo.h142
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib.h107
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib_tmp.h486
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.c273
-rw-r--r--mesalib/src/mesa/vbo/vbo_context.h114
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec.c97
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec.h179
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_api.c838
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_array.c965
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_draw.c413
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_eval.c254
-rw-r--r--mesalib/src/mesa/vbo/vbo_rebase.c223
-rw-r--r--mesalib/src/mesa/vbo/vbo_save.c110
-rw-r--r--mesalib/src/mesa/vbo/vbo_save.h184
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c1238
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_draw.c290
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_loopback.c191
-rw-r--r--mesalib/src/mesa/vbo/vbo_split.c161
-rw-r--r--mesalib/src/mesa/vbo/vbo_split.h72
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_copy.c616
-rw-r--r--mesalib/src/mesa/vbo/vbo_split_inplace.c271
727 files changed, 341361 insertions, 0 deletions
diff --git a/mesalib/src/Makefile b/mesalib/src/Makefile
new file mode 100644
index 000000000..4f65da0e3
--- /dev/null
+++ b/mesalib/src/Makefile
@@ -0,0 +1,40 @@
+# src/Makefile
+
+TOP = ..
+
+include $(TOP)/configs/current
+
+SUBDIRS = $(SRC_DIRS)
+
+
+default: message $(TOP)/$(LIB_DIR) subdirs
+
+
+message:
+ @echo "Making sources for" $(CONFIG_NAME)
+
+
+subdirs:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1; \
+ fi \
+ done
+
+install: $(TOP)/$(LIB_DIR)
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) install) || exit 1 ; \
+ fi \
+ done
+
+$(TOP)/$(LIB_DIR):
+ -@test -d $(TOP)/$(LIB_DIR) || mkdir -p $(TOP)/$(LIB_DIR)
+
+
+clean:
+ -@for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) clean) ; \
+ fi \
+ done
diff --git a/mesalib/src/glu/Makefile b/mesalib/src/glu/Makefile
new file mode 100644
index 000000000..b26826597
--- /dev/null
+++ b/mesalib/src/glu/Makefile
@@ -0,0 +1,40 @@
+# src/glu/Makefile
+
+TOP = ../..
+
+include $(TOP)/configs/current
+
+
+SUBDIRS = $(GLU_DIRS)
+
+
+default: $(TOP)/configs/current
+ @for dir in $(SUBDIRS) ; do \
+ (cd $$dir && $(MAKE)) || exit 1 ; \
+ done
+
+# GLU pkg-config file
+pcedit = sed \
+ -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \
+ -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \
+ -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \
+ -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
+ -e 's,@GLU_PC_REQ@,$(GLU_PC_REQ),' \
+ -e 's,@GLU_PC_REQ_PRIV@,$(GLU_PC_REQ_PRIV),' \
+ -e 's,@GLU_PC_LIB_PRIV@,$(GLU_PC_LIB_PRIV),' \
+ -e 's,@GLU_PC_CFLAGS@,$(GLU_PC_CFLAGS),' \
+ -e 's,@GLU_LIB@,$(GLU_LIB),'
+glu.pc: glu.pc.in
+ $(pcedit) $< > $@
+
+install: glu.pc
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GLU_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -m 644 glu.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+clean:
+ -@for dir in $(SUBDIRS) ; do \
+ (cd $$dir && $(MAKE) clean) ; \
+ done
+ -rm -f *.pc
diff --git a/mesalib/src/glu/glu.pc.in b/mesalib/src/glu/glu.pc.in
new file mode 100644
index 000000000..f7d910982
--- /dev/null
+++ b/mesalib/src/glu/glu.pc.in
@@ -0,0 +1,13 @@
+prefix=@INSTALL_DIR@
+exec_prefix=${prefix}
+libdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+
+Name: glu
+Description: Mesa OpenGL Utility library
+Requires: @GLU_PC_REQ@
+Requires.private: @GLU_PC_REQ_PRIV@
+Version: @VERSION@
+Libs: -L${libdir} -l@GLU_LIB@
+Libs.private: @GLU_PC_LIB_PRIV@
+Cflags: -I${includedir} @GLU_PC_CFLAGS@
diff --git a/mesalib/src/glu/sgi/Makefile b/mesalib/src/glu/sgi/Makefile
new file mode 100644
index 000000000..20c3bed0c
--- /dev/null
+++ b/mesalib/src/glu/sgi/Makefile
@@ -0,0 +1,149 @@
+# src/glu/sgi/Makefile
+
+.SUFFIXES : .cc
+
+TOP = ../../..
+
+include $(TOP)/configs/current
+
+GLU_MAJOR = 1
+GLU_MINOR = 3
+GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
+
+INCDIRS = -I$(TOP)/include -Iinclude -Iinternals -Ilibnurbs/internals -Ilibnurbs/interface -Ilibnurbs/nurbtess
+
+C_SOURCES = \
+ libutil/error.c \
+ libutil/glue.c \
+ libutil/mipmap.c \
+ libutil/project.c \
+ libutil/quad.c \
+ libutil/registry.c \
+ libtess/dict.c \
+ libtess/geom.c \
+ libtess/memalloc.c \
+ libtess/mesh.c \
+ libtess/normal.c \
+ libtess/priorityq.c \
+ libtess/render.c \
+ libtess/sweep.c \
+ libtess/tess.c \
+ libtess/tessmono.c
+
+CC_SOURCES = \
+ libnurbs/interface/bezierEval.cc \
+ libnurbs/interface/bezierPatch.cc \
+ libnurbs/interface/bezierPatchMesh.cc \
+ libnurbs/interface/glcurveval.cc \
+ libnurbs/interface/glinterface.cc \
+ libnurbs/interface/glrenderer.cc \
+ libnurbs/interface/glsurfeval.cc \
+ libnurbs/interface/incurveeval.cc \
+ libnurbs/interface/insurfeval.cc \
+ libnurbs/internals/arc.cc \
+ libnurbs/internals/arcsorter.cc \
+ libnurbs/internals/arctess.cc \
+ libnurbs/internals/backend.cc \
+ libnurbs/internals/basiccrveval.cc \
+ libnurbs/internals/basicsurfeval.cc \
+ libnurbs/internals/bin.cc \
+ libnurbs/internals/bufpool.cc \
+ libnurbs/internals/cachingeval.cc \
+ libnurbs/internals/ccw.cc \
+ libnurbs/internals/coveandtiler.cc \
+ libnurbs/internals/curve.cc \
+ libnurbs/internals/curvelist.cc \
+ libnurbs/internals/curvesub.cc \
+ libnurbs/internals/dataTransform.cc \
+ libnurbs/internals/displaylist.cc \
+ libnurbs/internals/flist.cc \
+ libnurbs/internals/flistsorter.cc \
+ libnurbs/internals/hull.cc \
+ libnurbs/internals/intersect.cc \
+ libnurbs/internals/knotvector.cc \
+ libnurbs/internals/mapdesc.cc \
+ libnurbs/internals/mapdescv.cc \
+ libnurbs/internals/maplist.cc \
+ libnurbs/internals/mesher.cc \
+ libnurbs/internals/monoTriangulationBackend.cc \
+ libnurbs/internals/monotonizer.cc \
+ libnurbs/internals/mycode.cc \
+ libnurbs/internals/nurbsinterfac.cc \
+ libnurbs/internals/nurbstess.cc \
+ libnurbs/internals/patch.cc \
+ libnurbs/internals/patchlist.cc \
+ libnurbs/internals/quilt.cc \
+ libnurbs/internals/reader.cc \
+ libnurbs/internals/renderhints.cc \
+ libnurbs/internals/slicer.cc \
+ libnurbs/internals/sorter.cc \
+ libnurbs/internals/splitarcs.cc \
+ libnurbs/internals/subdivider.cc \
+ libnurbs/internals/tobezier.cc \
+ libnurbs/internals/trimline.cc \
+ libnurbs/internals/trimregion.cc \
+ libnurbs/internals/trimvertpool.cc \
+ libnurbs/internals/uarray.cc \
+ libnurbs/internals/varray.cc \
+ libnurbs/nurbtess/directedLine.cc \
+ libnurbs/nurbtess/gridWrap.cc \
+ libnurbs/nurbtess/monoChain.cc \
+ libnurbs/nurbtess/monoPolyPart.cc \
+ libnurbs/nurbtess/monoTriangulation.cc \
+ libnurbs/nurbtess/partitionX.cc \
+ libnurbs/nurbtess/partitionY.cc \
+ libnurbs/nurbtess/polyDBG.cc \
+ libnurbs/nurbtess/polyUtil.cc \
+ libnurbs/nurbtess/primitiveStream.cc \
+ libnurbs/nurbtess/quicksort.cc \
+ libnurbs/nurbtess/rectBlock.cc \
+ libnurbs/nurbtess/sampleComp.cc \
+ libnurbs/nurbtess/sampleCompBot.cc \
+ libnurbs/nurbtess/sampleCompRight.cc \
+ libnurbs/nurbtess/sampleCompTop.cc \
+ libnurbs/nurbtess/sampleMonoPoly.cc \
+ libnurbs/nurbtess/sampledLine.cc \
+ libnurbs/nurbtess/searchTree.cc
+
+SOURCES = $(C_SOURCES) $(CC_SOURCES)
+
+C_OBJECTS = $(C_SOURCES:.c=.o)
+CC_OBJECTS = $(CC_SOURCES:.cc=.o)
+OBJECTS = $(C_OBJECTS) $(CC_OBJECTS)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCDIRS) $(CFLAGS) -DNDEBUG -DLIBRARYBUILD $< -o $@
+
+.cc.o:
+ $(CXX) -c $(INCDIRS) $(CXXFLAGS) -DNDEBUG -DLIBRARYBUILD $< -o $@
+
+
+##### TARGETS #####
+
+default:
+ @if [ "${CONFIG_NAME}" = "beos" ] ; then \
+ echo "$(GLU_LIB_NAME) not build under BeOS, but integrated into ${GL_LIB_NAME}." ; \
+ exit 0 ; \
+ else \
+ $(MAKE) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) || exit 1 ; \
+ fi
+
+$(TOP)/$(LIB_DIR):
+ -mkdir $(TOP)/$(LIB_DIR)
+
+# Make the library:
+$(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME): $(OBJECTS)
+ $(MKLIB) -o $(GLU_LIB) -linker '$(CXX)' -ldflags '$(LDFLAGS)' \
+ -major $(GLU_MAJOR) -minor $(GLU_MINOR) -patch $(GLU_TINY) \
+ -cplusplus $(MKLIB_OPTIONS) -install $(TOP)/$(LIB_DIR) \
+ -exports glu.exports -id $(INSTALL_LIB_DIR)/lib$(GLU_LIB).$(GLU_MAJOR).dylib \
+ $(GLU_LIB_DEPS) $(OBJECTS)
+
+
+clean:
+ -rm -f *.o */*.o */*/*.o
+ -rm -f *.lo */*.lo */*/*.lo
+ -rm -f *.la */*.la */*/*.la
diff --git a/mesalib/src/glu/sgi/Makefile.mgw b/mesalib/src/glu/sgi/Makefile.mgw
new file mode 100644
index 000000000..d00d97a3b
--- /dev/null
+++ b/mesalib/src/glu/sgi/Makefile.mgw
@@ -0,0 +1,230 @@
+# Mesa 3-D graphics library
+# Version: 5.1
+#
+# Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# MinGW core makefile v1.4 for Mesa
+#
+# Copyright (C) 2002 - Daniel Borca
+# Email : dborca@users.sourceforge.net
+# Web : http://www.geocities.com/dborca
+
+# MinGW core-glu makefile updated for Mesa 7.0
+#
+# Updated : by Heromyth, on 2007-7-21
+# Email : zxpmyth@yahoo.com.cn
+# Bugs : 1) All the default settings work fine. But the setting X86=1 can't work.
+# The others havn't been tested yet.
+# 2) The generated DLLs are *not* compatible with the ones built
+# with the other compilers like VC8, especially for GLUT.
+# 3) Although more tests are needed, it can be used individually!
+
+#
+# Available options:
+#
+# Environment variables:
+# CFLAGS
+#
+# GLIDE path to Glide3 SDK; used with FX.
+# default = $(TOP)/glide3
+# FX=1 build for 3dfx Glide3. Note that this disables
+# compilation of most WMesa code and requires fxMesa.
+# As a consequence, you'll need the Win32 Glide3
+# library to build any application.
+# default = no
+# ICD=1 build the installable client driver interface
+# (windows opengl driver interface)
+# default = no
+# X86=1 optimize for x86 (if possible, use MMX, SSE, 3DNow).
+# default = no
+#
+# Targets:
+# all: build GL
+# clean: remove object files
+#
+
+
+
+.PHONY: all clean
+.INTERMEDIATE: x86/gen_matypes.exe
+.SUFFIXES: .rc .res
+
+# Set this to the prefix of your build tools, i.e. mingw32-
+TOOLS_PREFIX = mingw32-
+
+TOP = ../../..
+LIBDIR = $(TOP)/lib
+
+LIB_NAME = glu32
+DLL_EXT = .dll
+IMP_EXT = .a
+LIB_PRE = lib
+STRIP = -s
+
+AR = ar
+ARFLAGS = crus
+DLLTOOL = dlltool
+
+GLU_DLL = $(LIB_NAME)$(DLL_EXT)
+GLU_IMP = $(LIB_PRE)$(LIB_NAME)$(IMP_EXT)
+GLU_DEF = $(LIB_NAME).def
+
+LDLIBS = -L$(LIBDIR) -lopengl32
+LDFLAGS = $(STRIP) -shared -fPIC -Wl,--kill-at
+
+CFLAGS += -DBUILD_GLU32 -D_DLL
+
+
+CC = $(TOOLS_PREFIX)gcc
+CFLAGS += -DNDEBUG -DLIBRARYBUILD -I$(TOP)/include -Iinclude
+CXX = $(TOOLS_PREFIX)g++
+CXXFLAGS = $(CFLAGS) -Ilibnurbs/internals -Ilibnurbs/interface -Ilibnurbs/nurbtess
+
+AR = ar
+ARFLAGS = crus
+
+UNLINK = del $(subst /,\,$(1))
+ifneq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
+UNLINK = $(RM) $(1)
+endif
+ifneq ($(wildcard $(addsuffix /rm,$(subst :, ,$(PATH)))),)
+UNLINK = $(RM) $(1)
+endif
+
+C_SOURCES = \
+ libutil/error.c \
+ libutil/glue.c \
+ libutil/mipmap.c \
+ libutil/project.c \
+ libutil/quad.c \
+ libutil/registry.c \
+ libtess/dict.c \
+ libtess/geom.c \
+ libtess/memalloc.c \
+ libtess/mesh.c \
+ libtess/normal.c \
+ libtess/priorityq.c \
+ libtess/render.c \
+ libtess/sweep.c \
+ libtess/tess.c \
+ libtess/tessmono.c
+
+CC_SOURCES = \
+ libnurbs/interface/bezierEval.cc \
+ libnurbs/interface/bezierPatch.cc \
+ libnurbs/interface/bezierPatchMesh.cc \
+ libnurbs/interface/glcurveval.cc \
+ libnurbs/interface/glinterface.cc \
+ libnurbs/interface/glrenderer.cc \
+ libnurbs/interface/glsurfeval.cc \
+ libnurbs/interface/incurveeval.cc \
+ libnurbs/interface/insurfeval.cc \
+ libnurbs/internals/arc.cc \
+ libnurbs/internals/arcsorter.cc \
+ libnurbs/internals/arctess.cc \
+ libnurbs/internals/backend.cc \
+ libnurbs/internals/basiccrveval.cc \
+ libnurbs/internals/basicsurfeval.cc \
+ libnurbs/internals/bin.cc \
+ libnurbs/internals/bufpool.cc \
+ libnurbs/internals/cachingeval.cc \
+ libnurbs/internals/ccw.cc \
+ libnurbs/internals/coveandtiler.cc \
+ libnurbs/internals/curve.cc \
+ libnurbs/internals/curvelist.cc \
+ libnurbs/internals/curvesub.cc \
+ libnurbs/internals/dataTransform.cc \
+ libnurbs/internals/displaylist.cc \
+ libnurbs/internals/flist.cc \
+ libnurbs/internals/flistsorter.cc \
+ libnurbs/internals/hull.cc \
+ libnurbs/internals/intersect.cc \
+ libnurbs/internals/knotvector.cc \
+ libnurbs/internals/mapdesc.cc \
+ libnurbs/internals/mapdescv.cc \
+ libnurbs/internals/maplist.cc \
+ libnurbs/internals/mesher.cc \
+ libnurbs/internals/monoTriangulationBackend.cc \
+ libnurbs/internals/monotonizer.cc \
+ libnurbs/internals/mycode.cc \
+ libnurbs/internals/nurbsinterfac.cc \
+ libnurbs/internals/nurbstess.cc \
+ libnurbs/internals/patch.cc \
+ libnurbs/internals/patchlist.cc \
+ libnurbs/internals/quilt.cc \
+ libnurbs/internals/reader.cc \
+ libnurbs/internals/renderhints.cc \
+ libnurbs/internals/slicer.cc \
+ libnurbs/internals/sorter.cc \
+ libnurbs/internals/splitarcs.cc \
+ libnurbs/internals/subdivider.cc \
+ libnurbs/internals/tobezier.cc \
+ libnurbs/internals/trimline.cc \
+ libnurbs/internals/trimregion.cc \
+ libnurbs/internals/trimvertpool.cc \
+ libnurbs/internals/uarray.cc \
+ libnurbs/internals/varray.cc \
+ libnurbs/nurbtess/directedLine.cc \
+ libnurbs/nurbtess/gridWrap.cc \
+ libnurbs/nurbtess/monoChain.cc \
+ libnurbs/nurbtess/monoPolyPart.cc \
+ libnurbs/nurbtess/monoTriangulation.cc \
+ libnurbs/nurbtess/partitionX.cc \
+ libnurbs/nurbtess/partitionY.cc \
+ libnurbs/nurbtess/polyDBG.cc \
+ libnurbs/nurbtess/polyUtil.cc \
+ libnurbs/nurbtess/primitiveStream.cc \
+ libnurbs/nurbtess/quicksort.cc \
+ libnurbs/nurbtess/rectBlock.cc \
+ libnurbs/nurbtess/sampleComp.cc \
+ libnurbs/nurbtess/sampleCompBot.cc \
+ libnurbs/nurbtess/sampleCompRight.cc \
+ libnurbs/nurbtess/sampleCompTop.cc \
+ libnurbs/nurbtess/sampleMonoPoly.cc \
+ libnurbs/nurbtess/sampledLine.cc \
+ libnurbs/nurbtess/searchTree.cc
+
+SOURCES = $(C_SOURCES) $(CC_SOURCES)
+
+OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+.cc.o:
+ $(CXX) -o $@ $(CXXFLAGS) -c $<
+
+
+all: $(LIBDIR) $(LIBDIR)/$(GLU_DLL) $(LIBDIR)/$(GLU_IMP)
+
+$(LIBDIR):
+ mkdir -p $(LIBDIR)
+
+$(LIBDIR)/$(GLU_DLL) $(LIBDIR)/$(GLU_IMP): $(OBJECTS)
+ $(CXX) $(LDFLAGS) -o $(LIBDIR)/$(GLU_DLL) $^ $(LDLIBS)
+ $(DLLTOOL) --as=as --dllname $(LIB_NAME) --output-def $(LIBDIR)/$(GLU_DEF) $^
+ $(DLLTOOL) --as=as -k --dllname $(LIB_NAME) --output-lib $(LIBDIR)/$(GLU_IMP) --def $(LIBDIR)/$(GLU_DEF)
+
+
+clean:
+ -$(call UNLINK,libutil/*.o)
+ -$(call UNLINK,libtess/*.o)
+ -$(call UNLINK,libnurbs/interface/*.o)
+ -$(call UNLINK,libnurbs/internals/*.o)
+ -$(call UNLINK,libnurbs/nurbtess/*.o)
diff --git a/mesalib/src/glu/sgi/Makefile.win b/mesalib/src/glu/sgi/Makefile.win
new file mode 100644
index 000000000..9321732ef
--- /dev/null
+++ b/mesalib/src/glu/sgi/Makefile.win
@@ -0,0 +1,149 @@
+# Makefile for Win32
+
+!include <win32.mak>
+
+.SUFFIXES : .cc
+
+TOP = ..
+
+GLU_SRCS_CC = \
+ libnurbs\interface\bezierEval.cc \
+ libnurbs\interface\bezierPatch.cc \
+ libnurbs\interface\bezierPatchMesh.cc \
+ libnurbs\interface\glcurveval.cc \
+ libnurbs\interface\glinterface.cc \
+ libnurbs\interface\glrenderer.cc \
+ libnurbs\interface\glsurfeval.cc \
+ libnurbs\interface\incurveeval.cc \
+ libnurbs\interface\insurfeval.cc \
+ libnurbs\internals\arc.cc \
+ libnurbs\internals\arcsorter.cc \
+ libnurbs\internals\arctess.cc \
+ libnurbs\internals\backend.cc \
+ libnurbs\internals\basiccrveval.cc \
+ libnurbs\internals\basicsurfeval.cc \
+ libnurbs\internals\bin.cc \
+ libnurbs\internals\bufpool.cc \
+ libnurbs\internals\cachingeval.cc \
+ libnurbs\internals\ccw.cc \
+ libnurbs\internals\coveandtiler.cc \
+ libnurbs\internals\curve.cc \
+ libnurbs\internals\curvelist.cc \
+ libnurbs\internals\curvesub.cc \
+ libnurbs\internals\dataTransform.cc \
+ libnurbs\internals\displaylist.cc \
+ libnurbs\internals\flist.cc \
+ libnurbs\internals\flistsorter.cc \
+ libnurbs\internals\hull.cc \
+ libnurbs\internals\intersect.cc \
+ libnurbs\internals\knotvector.cc \
+ libnurbs\internals\mapdesc.cc \
+ libnurbs\internals\mapdescv.cc \
+ libnurbs\internals\maplist.cc \
+ libnurbs\internals\mesher.cc \
+ libnurbs\internals\monoTriangulationBackend.cc \
+ libnurbs\internals\monotonizer.cc \
+ libnurbs\internals\mycode.cc \
+ libnurbs\internals\nurbsinterfac.cc \
+ libnurbs\internals\nurbstess.cc \
+ libnurbs\internals\patch.cc \
+ libnurbs\internals\patchlist.cc \
+ libnurbs\internals\quilt.cc \
+ libnurbs\internals\reader.cc \
+ libnurbs\internals\renderhints.cc \
+ libnurbs\internals\slicer.cc \
+ libnurbs\internals\sorter.cc \
+ libnurbs\internals\splitarcs.cc \
+ libnurbs\internals\subdivider.cc \
+ libnurbs\internals\tobezier.cc \
+ libnurbs\internals\trimline.cc \
+ libnurbs\internals\trimregion.cc \
+ libnurbs\internals\trimvertpool.cc \
+ libnurbs\internals\uarray.cc \
+ libnurbs\internals\varray.cc \
+ libnurbs\nurbtess\directedLine.cc \
+ libnurbs\nurbtess\gridWrap.cc \
+ libnurbs\nurbtess\monoChain.cc \
+ libnurbs\nurbtess\monoPolyPart.cc \
+ libnurbs\nurbtess\monoTriangulation.cc \
+ libnurbs\nurbtess\partitionX.cc \
+ libnurbs\nurbtess\partitionY.cc \
+ libnurbs\nurbtess\polyDBG.cc \
+ libnurbs\nurbtess\polyUtil.cc \
+ libnurbs\nurbtess\primitiveStream.cc \
+ libnurbs\nurbtess\quicksort.cc \
+ libnurbs\nurbtess\rectBlock.cc \
+ libnurbs\nurbtess\sampleComp.cc \
+ libnurbs\nurbtess\sampleCompBot.cc \
+ libnurbs\nurbtess\sampleCompRight.cc \
+ libnurbs\nurbtess\sampleCompTop.cc \
+ libnurbs\nurbtess\sampleMonoPoly.cc \
+ libnurbs\nurbtess\sampledLine.cc \
+ libnurbs\nurbtess\searchTree.cc
+
+GLU_SRCS = \
+ libtess\dict.c \
+ libtess\geom.c \
+ libtess\memalloc.c \
+ libtess\mesh.c \
+ libtess\normal.c \
+ libtess\priorityq.c \
+ libtess\render.c \
+ libtess\sweep.c \
+ libtess\tess.c \
+ libtess\tessmono.c \
+ libutil\error.c \
+ libutil\glue.c \
+ libutil\mipmap.c \
+ libutil\project.c \
+ libutil\quad.c \
+ libutil\registry.c
+
+SRCS = $(GLU_SRCS)
+
+all : gludll
+
+!include "$(TOP)/mesawin32.mak"
+
+gludll : $(GLUDLL)
+
+CFLAGS = $(cvarsdll) $(CFLAGS) -D_OPENGL32_ -Iinclude -DBUILD_GL32 -DLIBRARYBUILD
+LFLAGS = $(dlllflags) $(lcommon) $(LFLAGS)
+
+LIBS = ../lib/$(MESALIB) winmm.lib $(guilibsdll)
+
+OBJS = $(GLU_SRCS_CC:.cc=.obj) $(GLU_SRCS:.c=.obj)
+NURBSINC = -Ilibnurbs\interface -Ilibnurbs\internals -Ilibnurbs\nurbtess
+CFLAGS = $(CFLAGS) $(NURBSINC)
+
+$(GLUDLL): $(OBJS) glu.def
+ $(link) $(LFLAGS) -out:$(GLUDLL) -def:glu.def $(OBJS) $(LIBS)
+ @echo "copying Mesa GLU dynamic link library to library directory..."
+ -copy $(GLUDLL) $(TOP)\lib
+ @echo "copying Mesa GLU import library to library directory..."
+ -copy $(GLULIB) $(TOP)\lib
+
+install : $(GLUDLL) $(GLULIB)
+ @echo "copying Mesa GLU dynamic link library to system directory..."
+ -copy $(GLUDLL) $(DLLINSTALL)
+ @echo "copying Mesa GLU header files to include directory..."
+ -copy ..\..\include\GL\glu.h $(INCLUDEINSTALL)
+ @echo "copying Mesa GLU import library to system library directory..."
+ -copy $(GLULIB) $(LIBINSTALL)
+
+clean ::
+ @del /f libtess\*.obj libutil\*.obj
+ @del /f libnurbs\interface\*.obj libnurbs\internals\*.obj
+ @del /f libnurbs\nurbtess\*.obj
+
+# override default inference rule with one that writes the object to
+# the same subdir as the c file.
+
+.c.obj :
+ $(cc) $(CFLAGS) -I. $< /Fo$*.obj
+
+# /TP is needed for C++ files because MS compiler
+# does not recognize .cc as a C++ file.
+
+.cc.obj :
+ $(cc) $(CFLAGS) -I. $< /TP /Fo$*.obj
diff --git a/mesalib/src/glu/sgi/dummy.cc b/mesalib/src/glu/sgi/dummy.cc
new file mode 100644
index 000000000..bd905a260
--- /dev/null
+++ b/mesalib/src/glu/sgi/dummy.cc
@@ -0,0 +1,4 @@
+/*
+ * This file contains nothing. It's just there so there's at least a single
+ * source file for libGLU.la in this directory.
+ */
diff --git a/mesalib/src/glu/sgi/glu.def b/mesalib/src/glu/sgi/glu.def
new file mode 100644
index 000000000..0c8b02176
--- /dev/null
+++ b/mesalib/src/glu/sgi/glu.def
@@ -0,0 +1,88 @@
+;DESCRIPTION 'Mesa GLU (OpenGL work-alike) for Win32'
+VERSION 5.1
+;
+; Module definition file for GLU (GLU32.DLL)
+;
+; Note: The GLU functions use the STDCALL
+; function calling convention. Microsoft's
+; GLU32 uses this convention and so must the
+; Mesa GLU32 so that the Mesa DLL can be used
+; as a drop-in replacement.
+;
+; The linker exports STDCALL entry points with
+; 'decorated' names; e.g., _glBegin@0, where the
+; trailing number is the number of bytes of
+; parameter data pushed onto the stack. The
+; callee is responsible for popping this data
+; off the stack, usually via a RETF n instruction.
+;
+; However, the Microsoft GLU32.DLL does not export
+; the decorated names, even though the calling convention
+; is STDCALL. So, this module definition file is
+; needed to force the Mesa GLU32.DLL to export the
+; symbols in the same manner as the Microsoft DLL.
+; Were it not for this problem, this file would not
+; be needed (for the glu* functions) since the entry
+; points are compiled with dllexport declspec.
+;
+
+EXPORTS
+ gluBeginCurve
+ gluBeginPolygon
+ gluBeginSurface
+ gluBeginTrim
+ gluBuild1DMipmapLevels
+ gluBuild1DMipmaps
+ gluBuild2DMipmapLevels
+ gluBuild2DMipmaps
+ gluBuild3DMipmapLevels
+ gluBuild3DMipmaps
+ gluCheckExtension
+ gluCylinder
+ gluDeleteNurbsRenderer
+ gluDeleteQuadric
+ gluDeleteTess
+ gluDisk
+ gluEndCurve
+ gluEndPolygon
+ gluEndSurface
+ gluEndTrim
+ gluErrorString
+ gluGetNurbsProperty
+ gluGetString
+ gluGetTessProperty
+ gluLoadSamplingMatrices
+ gluLookAt
+ gluNewNurbsRenderer
+ gluNewQuadric
+ gluNewTess
+ gluNextContour
+ gluNurbsCallback
+ gluNurbsCallbackData
+ gluNurbsCallbackDataEXT
+ gluNurbsCurve
+ gluNurbsProperty
+ gluNurbsSurface
+ gluOrtho2D
+ gluPartialDisk
+ gluPerspective
+ gluPickMatrix
+ gluProject
+ gluPwlCurve
+ gluQuadricCallback
+ gluQuadricDrawStyle
+ gluQuadricNormals
+ gluQuadricOrientation
+ gluQuadricTexture
+ gluScaleImage
+ gluSphere
+ gluTessBeginContour
+ gluTessBeginPolygon
+ gluTessCallback
+ gluTessEndContour
+ gluTessEndPolygon
+ gluTessNormal
+ gluTessProperty
+ gluTessVertex
+ gluUnProject
+ gluUnProject4
diff --git a/mesalib/src/glu/sgi/glu.exports b/mesalib/src/glu/sgi/glu.exports
new file mode 100644
index 000000000..aeb727291
--- /dev/null
+++ b/mesalib/src/glu/sgi/glu.exports
@@ -0,0 +1,118 @@
+ gluBeginCurve
+ gluBeginPolygon
+ gluBeginSurface
+ gluBeginTrim
+ gluBuild1DMipmapLevels
+ gluBuild1DMipmaps
+ gluBuild2DMipmapLevels
+ gluBuild2DMipmaps
+ gluBuild3DMipmapLevels
+ gluBuild3DMipmaps
+ gluCheckExtension
+ gluCylinder
+ gluDeleteNurbsRenderer
+ gluDeleteQuadric
+ gluDeleteTess
+ gluDisk
+ gluEndCurve
+ gluEndPolygon
+ gluEndSurface
+ gluEndTrim
+ gluErrorString
+ gluGetNurbsProperty
+ gluGetString
+ gluGetTessProperty
+ gluLoadSamplingMatrices
+ gluLookAt
+ gluNewNurbsRenderer
+ gluNewQuadric
+ gluNewTess
+ gluNextContour
+ gluNurbsCallback
+ gluNurbsCallbackData
+ gluNurbsCallbackDataEXT
+ gluNurbsCurve
+ gluNurbsProperty
+ gluNurbsSurface
+ gluOrtho2D
+ gluPartialDisk
+ gluPerspective
+ gluPickMatrix
+ gluProject
+ gluPwlCurve
+ gluQuadricCallback
+ gluQuadricDrawStyle
+ gluQuadricNormals
+ gluQuadricOrientation
+ gluQuadricTexture
+ gluScaleImage
+ gluSphere
+ gluTessBeginContour
+ gluTessBeginPolygon
+ gluTessCallback
+ gluTessEndContour
+ gluTessEndPolygon
+ gluTessNormal
+ gluTessProperty
+ gluTessVertex
+ gluUnProject
+ gluUnProject4
+ mgluBeginCurve
+ mgluBeginPolygon
+ mgluBeginSurface
+ mgluBeginTrim
+ mgluBuild1DMipmapLevels
+ mgluBuild1DMipmaps
+ mgluBuild2DMipmapLevels
+ mgluBuild2DMipmaps
+ mgluBuild3DMipmapLevels
+ mgluBuild3DMipmaps
+ mgluCheckExtension
+ mgluCylinder
+ mgluDeleteNurbsRenderer
+ mgluDeleteQuadric
+ mgluDeleteTess
+ mgluDisk
+ mgluEndCurve
+ mgluEndPolygon
+ mgluEndSurface
+ mgluEndTrim
+ mgluErrorString
+ mgluGetNurbsProperty
+ mgluGetString
+ mgluGetTessProperty
+ mgluLoadSamplingMatrices
+ mgluLookAt
+ mgluNewNurbsRenderer
+ mgluNewQuadric
+ mgluNewTess
+ mgluNextContour
+ mgluNurbsCallback
+ mgluNurbsCallbackData
+ mgluNurbsCallbackDataEXT
+ mgluNurbsCurve
+ mgluNurbsProperty
+ mgluNurbsSurface
+ mgluOrtho2D
+ mgluPartialDisk
+ mgluPerspective
+ mgluPickMatrix
+ mgluProject
+ mgluPwlCurve
+ mgluQuadricCallback
+ mgluQuadricDrawStyle
+ mgluQuadricNormals
+ mgluQuadricOrientation
+ mgluQuadricTexture
+ mgluScaleImage
+ mgluSphere
+ mgluTessBeginContour
+ mgluTessBeginPolygon
+ mgluTessCallback
+ mgluTessEndContour
+ mgluTessEndPolygon
+ mgluTessNormal
+ mgluTessProperty
+ mgluTessVertex
+ mgluUnProject
+ mgluUnProject4
diff --git a/mesalib/src/glu/sgi/glu.exports.darwin b/mesalib/src/glu/sgi/glu.exports.darwin
new file mode 100644
index 000000000..4f56e36f3
--- /dev/null
+++ b/mesalib/src/glu/sgi/glu.exports.darwin
@@ -0,0 +1,59 @@
+_*gluBeginCurve
+_*gluBeginPolygon
+_*gluBeginSurface
+_*gluBeginTrim
+_*gluBuild1DMipmapLevels
+_*gluBuild1DMipmaps
+_*gluBuild2DMipmapLevels
+_*gluBuild2DMipmaps
+_*gluBuild3DMipmapLevels
+_*gluBuild3DMipmaps
+_*gluCheckExtension
+_*gluCylinder
+_*gluDeleteNurbsRenderer
+_*gluDeleteQuadric
+_*gluDeleteTess
+_*gluDisk
+_*gluEndCurve
+_*gluEndPolygon
+_*gluEndSurface
+_*gluEndTrim
+_*gluErrorString
+_*gluGetNurbsProperty
+_*gluGetString
+_*gluGetTessProperty
+_*gluLoadSamplingMatrices
+_*gluLookAt
+_*gluNewNurbsRenderer
+_*gluNewQuadric
+_*gluNewTess
+_*gluNextContour
+_*gluNurbsCallback
+_*gluNurbsCallbackData
+_*gluNurbsCallbackDataEXT
+_*gluNurbsCurve
+_*gluNurbsProperty
+_*gluNurbsSurface
+_*gluOrtho2D
+_*gluPartialDisk
+_*gluPerspective
+_*gluPickMatrix
+_*gluProject
+_*gluPwlCurve
+_*gluQuadricCallback
+_*gluQuadricDrawStyle
+_*gluQuadricNormals
+_*gluQuadricOrientation
+_*gluQuadricTexture
+_*gluScaleImage
+_*gluSphere
+_*gluTessBeginContour
+_*gluTessBeginPolygon
+_*gluTessCallback
+_*gluTessEndContour
+_*gluTessEndPolygon
+_*gluTessNormal
+_*gluTessProperty
+_*gluTessVertex
+_*gluUnProject
+_*gluUnProject4
diff --git a/mesalib/src/glu/sgi/include/gluos.h b/mesalib/src/glu/sgi/include/gluos.h
new file mode 100644
index 000000000..8eaa7a153
--- /dev/null
+++ b/mesalib/src/glu/sgi/include/gluos.h
@@ -0,0 +1,72 @@
+/*
+** gluos.h - operating system dependencies for GLU
+**
+*/
+#ifdef __VMS
+#ifdef __cplusplus
+#pragma message disable nocordel
+#pragma message disable codeunreachable
+#pragma message disable codcauunr
+#endif
+#endif
+
+#ifdef __WATCOMC__
+/* Disable *lots* of warnings to get a clean build. I can't be bothered fixing the
+ * code at the moment, as it is pretty ugly.
+ */
+#pragma warning 7 10
+#pragma warning 13 10
+#pragma warning 14 10
+#pragma warning 367 10
+#pragma warning 379 10
+#pragma warning 726 10
+#pragma warning 836 10
+#endif
+
+#ifdef BUILD_FOR_SNAP
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#elif defined(_WIN32)
+
+#include <stdlib.h> /* For _MAX_PATH definition */
+#include <stdio.h>
+#include <malloc.h>
+
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#define NOIME
+#define NOMINMAX
+
+#define _WIN32_WINNT 0x0400
+#ifndef STRICT
+ #define STRICT 1
+#endif
+
+#include <windows.h>
+
+/* Disable warnings */
+#pragma warning(disable : 4101)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1300
+#pragma comment(linker, "/OPT:NOWIN98")
+#endif
+
+#elif defined(__OS2__)
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#define WINGDIAPI
+
+#else
+
+/* Disable Microsoft-specific keywords */
+#define GLAPIENTRY
+#define WINGDIAPI
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.cc b/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.cc
new file mode 100644
index 000000000..b414f535f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.cc
@@ -0,0 +1,260 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <math.h>
+#include "bezierEval.h"
+
+#ifdef __WATCOMC__
+#pragma warning 14 10
+#endif
+
+#define TOLERANCE 0.0001
+
+#ifndef MAX_ORDER
+#define MAX_ORDER 16
+#endif
+
+#ifndef MAX_DIMENSION
+#define MAX_DIMENSION 4
+#endif
+
+static void normalize(float vec[3]);
+static void crossProduct(float x[3], float y[3], float ret[3]);
+#if 0 // UNUSED
+static void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[]);
+#endif
+
+static float binomialCoefficients[8][8] = {
+ {1,0,0,0,0,0,0,0},
+ {1,1,0,0,0,0,0,0},
+ {1,2,1,0,0,0,0,0},
+ {1,3,3,1,0,0,0,0},
+ {1,4,6,4,1,0,0,0},
+ {1,5,10,10,5,1,0,0},
+ {1,6,15,20,15,6,1,0},
+ {1,7,21,35,35,21,7,1}
+};
+
+void bezierCurveEval(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
+{
+ float uprime = (u-u0)/(u1-u0);
+ float *ctlptr = ctlpoints;
+ float oneMinusX = 1.0f-uprime;
+ float XPower = 1.0f;
+
+ int i,k;
+ for(k=0; k<dimension; k++)
+ retpoint[k] = (*(ctlptr + k));
+
+ for(i=1; i<order; i++){
+ ctlptr += stride;
+ XPower *= uprime;
+ for(k=0; k<dimension; k++) {
+ retpoint[k] = retpoint[k]*oneMinusX + ctlptr[k]* binomialCoefficients[order-1][i] * XPower;
+ }
+ }
+}
+
+
+#if 0 // UNUSED
+/*order = degree +1 >=1.
+ */
+void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
+{
+ float uprime = (u-u0)/(u1-u0);
+ float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
+ float* ctlptr = ctlpoints;
+ int r, i,j;
+ for(i=0; i<order; i++) {
+ for(j=0; j<dimension; j++)
+ buf[0][i][j] = ctlptr[j];
+ ctlptr += stride;
+ }
+ for(r=1; r<order; r++){
+ for(i=0; i<order-r; i++) {
+ for(j=0; j<dimension; j++)
+ buf[r][i][j] = (1-uprime)*buf[r-1][i][j] + uprime*buf[r-1][i+1][j];
+ }
+ }
+
+ for(j=0; j<dimension; j++)
+ retpoint[j] = buf[order-1][0][j];
+}
+#endif
+
+
+/*order = degree +1 >=1.
+ */
+void bezierCurveEvalDer(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
+{
+ int i,k;
+ float width = u1-u0;
+ float *ctlptr = ctlpoints;
+
+ float buf[MAX_ORDER][MAX_DIMENSION];
+ if(order == 1){
+ for(k=0; k<dimension; k++)
+ retDer[k]=0;
+ }
+ for(i=0; i<order-1; i++){
+ for(k=0; k<dimension; k++) {
+ buf[i][k] = (ctlptr[stride+k] - ctlptr[k])*(order-1)/width;
+ }
+ ctlptr += stride;
+ }
+
+ bezierCurveEval(u0, u1, order-1, (float*) buf, MAX_DIMENSION, dimension, u, retDer);
+}
+
+void bezierCurveEvalDerGen(int der, float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
+{
+ int i,k,r;
+ float *ctlptr = ctlpoints;
+ float width=u1-u0;
+ float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
+ if(der<0) der=0;
+ for(i=0; i<order; i++){
+ for(k=0; k<dimension; k++){
+ buf[0][i][k] = ctlptr[k];
+ }
+ ctlptr += stride;
+ }
+
+
+ for(r=1; r<=der; r++){
+ for(i=0; i<order-r; i++){
+ for(k=0; k<dimension; k++){
+ buf[r][i][k] = (buf[r-1][i+1][k] - buf[r-1][i][k])*(order-r)/width;
+ }
+ }
+ }
+
+ bezierCurveEval(u0, u1, order-der, (float *) (buf[der]), MAX_DIMENSION, dimension, u, retDer);
+}
+
+/*the Bezier bivarite polynomial is:
+ * sum[i:0,uorder-1][j:0,vorder-1] { ctlpoints[i*ustride+j*vstride] * B(i)*B(j)
+ * where B(i) and B(j) are basis functions
+ */
+void bezierSurfEvalDerGen(int uder, int vder, float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
+{
+ int i;
+ float newPoints[MAX_ORDER][MAX_DIMENSION];
+
+ for(i=0; i<uorder; i++){
+
+ bezierCurveEvalDerGen(vder, v0, v1, vorder, ctlpoints+ustride*i, vstride, dimension, v, newPoints[i]);
+
+ }
+
+ bezierCurveEvalDerGen(uder, u0, u1, uorder, (float *) newPoints, MAX_DIMENSION, dimension, u, ret);
+}
+
+
+/*division by w is performed*/
+void bezierSurfEval(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
+{
+ bezierSurfEvalDerGen(0, 0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, ret);
+ if(dimension == 4) /*homogeneous*/{
+ ret[0] /= ret[3];
+ ret[1] /= ret[3];
+ ret[2] /= ret[3];
+ }
+}
+
+void bezierSurfEvalNormal(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float retNormal[])
+{
+ float partialU[4];
+ float partialV[4];
+ assert(dimension>=3 && dimension <=4);
+ bezierSurfEvalDerGen(1,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialU);
+ bezierSurfEvalDerGen(0,1, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialV);
+
+ if(dimension == 3){/*inhomogeneous*/
+ crossProduct(partialU, partialV, retNormal);
+
+ normalize(retNormal);
+
+ return;
+ }
+ else { /*homogeneous*/
+ float val[4]; /*the point coordinates (without derivative)*/
+ float newPartialU[MAX_DIMENSION];
+ float newPartialV[MAX_DIMENSION];
+ int i;
+ bezierSurfEvalDerGen(0,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, val);
+
+ for(i=0; i<=2; i++){
+ newPartialU[i] = partialU[i] * val[3] - val[i] * partialU[3];
+ newPartialV[i] = partialV[i] * val[3] - val[i] * partialV[3];
+ }
+ crossProduct(newPartialU, newPartialV, retNormal);
+ normalize(retNormal);
+ }
+}
+
+/*if size is 0, then nothing is done*/
+static void normalize(float vec[3])
+{
+ float size = (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+
+ if(size < TOLERANCE)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "Warning: in oglBSpline.c normal is 0\n");
+#endif
+ return;
+ }
+ else {
+ vec[0] = vec[0]/size;
+ vec[1] = vec[1]/size;
+ vec[2] = vec[2]/size;
+ }
+}
+
+
+static void crossProduct(float x[3], float y[3], float ret[3])
+{
+ ret[0] = x[1]*y[2] - y[1]*x[2];
+ ret[1] = x[2]*y[0] - y[2]*x[0];
+ ret[2] = x[0]*y[1] - y[0]*x[1];
+
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.h b/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.h
new file mode 100644
index 000000000..93e8c69d1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierEval.h
@@ -0,0 +1,48 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _BEZIEREVAL_H
+#define _BEZIEREVAL_H
+
+void bezierCurveEval(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[]);
+void bezierCurveEvalDer(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[]);
+void bezierCurveEvalDerGen(int der, float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[]);
+
+
+void bezierSurfEvalDerGen(int uder, int vder, float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[]);
+
+void bezierSurfEval(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[]);
+
+void bezierSurfEvalNormal(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float retNormal[]);
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.cc b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.cc
new file mode 100644
index 000000000..dbab3a1a2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.cc
@@ -0,0 +1,206 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/glu.h> /*for drawing bzier patch*/
+#include "bezierPatch.h"
+#include "bezierEval.h"
+
+/*
+ *allocate an instance of bezierPatch. The control points are unknown. But
+ *the space of this array is allocated with size of
+ * uorder*vorder*dimension
+ *
+ */
+bezierPatch* bezierPatchMake(float umin, float vmin, float umax, float vmax, int uorder, int vorder, int dimension)
+{
+ bezierPatch* ret = (bezierPatch*) malloc(sizeof(bezierPatch));
+ assert(ret);
+ ret->umin = umin;
+ ret->vmin = vmin;
+ ret->umax = umax;
+ ret->vmax = vmax;
+ ret->uorder = uorder;
+ ret->vorder = vorder;
+ ret->dimension = dimension;
+ ret->ctlpoints = (float*) malloc(sizeof(float) * dimension * uorder * vorder);
+ assert(ret->ctlpoints);
+
+ ret->next = NULL;
+
+ return ret;
+}
+
+bezierPatch* bezierPatchMake2(float umin, float vmin, float umax, float vmax, int uorder, int vorder, int dimension, int ustride, int vstride, float* ctlpoints)
+{
+ bezierPatch* ret = (bezierPatch*) malloc(sizeof(bezierPatch));
+ assert(ret);
+ ret->umin = umin;
+ ret->vmin = vmin;
+ ret->umax = umax;
+ ret->vmax = vmax;
+ ret->uorder = uorder;
+ ret->vorder = vorder;
+ ret->dimension = dimension;
+ ret->ctlpoints = (float*) malloc(sizeof(float) * dimension * uorder * vorder);
+ assert(ret->ctlpoints);
+
+ /*copy the control points there*/
+ int the_ustride = vorder * dimension;
+ int the_vstride = dimension;
+ for(int i=0; i<uorder; i++)
+ for(int j=0; j<vorder; j++)
+ for(int k=0; k<dimension; k++)
+ ret->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
+
+ ret->next = NULL;
+
+ return ret;
+}
+
+/*
+ *deallocate the space as allocated by Make
+ */
+void bezierPatchDelete(bezierPatch *b)
+{
+ free(b->ctlpoints);
+ free(b);
+}
+
+/*delete the whole linked list
+ */
+void bezierPatchDeleteList(bezierPatch *b)
+{
+ bezierPatch *temp;
+ while (b != NULL) {
+ temp = b;
+ b = b->next;
+ bezierPatchDelete(temp);
+ }
+}
+
+bezierPatch* bezierPatchInsert(bezierPatch *list, bezierPatch *b)
+{
+ b->next = list;
+ return b;
+}
+
+/*print the data stored in this patch*/
+void bezierPatchPrint(bezierPatch *b)
+{
+ printf("bezierPatch:\n");
+ printf("umin,umax=(%f,%f), (vmin, vmax)=(%f,%f)\n", b->umin, b->umax, b->vmin, b->vmax);
+ printf("uorder=%i, vorder=%i\n", b->uorder, b->vorder);
+ printf("idmension = %i\n", b->dimension);
+}
+
+/*print the whole list*/
+void bezierPatchPrintList(bezierPatch *list)
+{
+ bezierPatch* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ bezierPatchPrint(temp);
+}
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[])
+{
+ if( u >= b->umin && u<= b->umax
+ && v >= b->vmin && v<= b->vmax)
+ {
+
+ bezierSurfEval(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+ }
+ else if(b->next != NULL)
+ bezierPatchEval(b->next, u,v, ret);
+ else
+ bezierSurfEval(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+}
+
+/*the returned normal is normlized
+ */
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float ret[])
+{
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+ if( u >= b->umin && u<= b->umax
+ && v >= b->vmin && v<= b->vmax)
+ {
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+ }
+ else if(b->next != NULL)
+ bezierPatchEvalNormal(b->next, u,v, ret);
+ else
+ bezierSurfEvalNormal(b->umin, b->umax, b->uorder, b->vmin, b->vmax, b->vorder, b->dimension, b->ctlpoints, b->dimension * b->vorder, b->dimension, u, v, ret);
+
+}
+
+void bezierPatchDraw(bezierPatch *bpatch, int u_reso, int v_reso)
+{
+ if(bpatch->dimension == 3)
+ glMap2f(GL_MAP2_VERTEX_3, bpatch->umin, bpatch->umax, 3*bpatch->vorder, bpatch->uorder, bpatch->vmin, bpatch->vmax,3, bpatch->vorder, (GLfloat*) bpatch->ctlpoints);
+ else
+ glMap2f(GL_MAP2_VERTEX_4, bpatch->umin, bpatch->umax, 4*bpatch->vorder, bpatch->uorder, bpatch->vmin, bpatch->vmax,3, bpatch->vorder, (GLfloat*) bpatch->ctlpoints);
+
+ glMapGrid2f(u_reso, bpatch->umin, bpatch->umax,
+ v_reso, bpatch->vmin, bpatch->vmax);
+ glEvalMesh2(GL_LINE, 0, u_reso, 0, v_reso);
+}
+
+void bezierPatchListDraw(bezierPatch *list, int u_reso, int v_reso)
+{
+ bezierPatch *temp;
+glEnable(GL_LIGHTING);
+glEnable(GL_LIGHT0);
+glEnable(GL_MAP2_VERTEX_3);
+glEnable(GL_AUTO_NORMAL);
+glEnable(GL_NORMALIZE);
+glColor3f(1,0,0);
+#ifdef DEBUG
+printf("mapmap\n");
+#endif
+
+
+ for(temp = list; temp != NULL; temp = temp->next)
+ bezierPatchDraw(temp, u_reso, v_reso);
+}
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.h b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.h
new file mode 100644
index 000000000..981183afa
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatch.h
@@ -0,0 +1,104 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _BEZIERPATCH_H
+#define _BEZIERPATCH_H
+
+typedef struct bezierPatch{
+ float umin, vmin, umax, vmax;
+ int uorder; /*order= degree + 1*/
+ int vorder;
+
+ /*
+ *the control points are stored in a one dimensional array.
+ *the surface is defined as:
+ * s(u,v) = sum_{i,j} P(i,j) * B_i(u) * B_j(v).
+ *where P(i,j) are the control points, B_i(.) are Bezier
+ *basis functions.
+ *Each control point can have dimension 3 or 4: (x,y,z,w).
+ *The components of P(i,j) are stored in a one dimensional
+ *array:
+ * ctlpoints[]
+ *in the order of:
+ * P[0,0], P[0,1], ..., P[0,vorder-1],
+ * P[1,0], P[1,1], ..., P[1,vorder-1],
+ * ...
+ * P[uorder-1,0], P[uorder-1,1], ..., P[uorder-1,vorder-1].
+ */
+ int dimension;
+ float* ctlpoints;
+
+ /*
+ *in case we have to manage multiple bezierPatches.
+ */
+ struct bezierPatch *next;
+
+} bezierPatch;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bezierPatch* bezierPatchMake(float umin, float vmin, float umax, float vmax, int urder, int vorder, int dimension);
+
+bezierPatch* bezierPatchMake2(float umin, float vmin, float umax, float vmax, int urder, int vorder, int dimension, int ustride, int vstride, float *ctlpoints);
+
+
+bezierPatch* bezierPatchInsert(bezierPatch *list, bezierPatch *b);
+
+void bezierPatchDelete(bezierPatch *b);
+
+void bezierPatchDeleteList(bezierPatch *b);
+
+void bezierPatchPrint(bezierPatch *b);
+
+void bezierPatchPrintList(bezierPatch *list);
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[]);
+
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float retNormal[]);
+
+void bezierPatchEval(bezierPatch *b, float u, float v, float ret[]);
+
+void bezierPatchEvalNormal(bezierPatch *b, float u, float v, float ret[]);
+
+
+void bezierPatchDraw(bezierPatch *bpatch, int u_reso, int v_reso);
+
+void bezierPatchListDraw(bezierPatch *list, int u_reso, int v_reso);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc
new file mode 100644
index 000000000..ac7ff84fc
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.cc
@@ -0,0 +1,610 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+#include "bezierEval.h"
+#include "bezierPatchMesh.h"
+
+static int isDegenerate(float A[2], float B[2], float C[2]);
+
+void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips)
+{
+ int i,j,k;
+ k=0;
+ /*k is the index of the first component of the current vertex*/
+ for(i=0; i<num_strips; i++)
+ {
+ glBegin(type_array[i]);
+ for(j=0; j<length_array[i]; j++)
+ {
+ glNormal3fv(normal_array+k);
+ glVertex3fv(vertex_array+k);
+ k += 3;
+ }
+ glEnd();
+ }
+}
+
+void bezierPatchMeshListDelDeg(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshDelDeg(temp);
+ }
+}
+
+void bezierPatchMeshListDelete(bezierPatchMesh *list)
+{
+ if(list == NULL) return;
+ bezierPatchMeshListDelete(list->next);
+ bezierPatchMeshDelete(list);
+}
+
+
+
+
+bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list)
+{
+ bezierPatchMesh* ret=NULL;
+ bezierPatchMesh* temp;
+ bezierPatchMesh* nextone;
+ for(temp = list; temp != NULL; temp = nextone)
+ {
+ nextone = temp->next;
+ ret=bezierPatchMeshListInsert(ret, temp);
+ }
+ return ret;
+}
+
+/*maptype is either GL_MAP2_VERTEX_3 or GL_MAP2_VERTEX_4
+ */
+bezierPatchMesh *bezierPatchMeshMake(int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints, int size_UVarray, int size_length_array)
+{
+ int i,j,k;
+ int dimension;
+ int the_ustride;
+ int the_vstride;
+
+ if(maptype == GL_MAP2_VERTEX_3) dimension = 3;
+ else if (maptype==GL_MAP2_VERTEX_4) dimension = 4;
+ else {
+ fprintf(stderr, "error in inMap2f, maptype=%i is wrong, maptype,map is invalid\n", maptype);
+ return NULL;
+ }
+
+ bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
+ assert(ret);
+
+ ret->bpatch_normal = NULL;
+ ret->bpatch_color = NULL;
+ ret->bpatch_texcoord = NULL;
+ ret->bpatch = bezierPatchMake(umin, vmin, umax, vmax, uorder, vorder, dimension);
+
+ /*copy the control points there*/
+ the_ustride = vorder * dimension;
+ the_vstride = dimension;
+ for(i=0; i<uorder; i++)
+ for(j=0; j<vorder; j++)
+ for(k=0; k<dimension; k++)
+ ret->bpatch->ctlpoints[i * the_ustride + j*the_vstride+k] = ctlpoints[i*ustride+j*vstride+k];
+
+
+ ret->size_UVarray = size_UVarray;
+ ret->size_length_array = size_length_array;
+ ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
+ assert(ret->UVarray);
+ ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
+ assert(ret->length_array);
+ ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
+ assert(ret->type_array);
+
+ ret->index_UVarray = 0;
+ ret->index_length_array = 0;
+
+ ret->vertex_array = NULL;
+ ret->normal_array = NULL;
+ ret->color_array = NULL;
+ ret->texcoord_array = NULL;
+
+ ret->next = NULL;
+ return ret;
+}
+
+bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array)
+{
+ bezierPatchMesh *ret = (bezierPatchMesh*) malloc(sizeof(bezierPatchMesh));
+ assert(ret);
+
+ ret->bpatch = NULL;
+ ret->bpatch_normal = NULL;
+ ret->bpatch_color = NULL;
+ ret->bpatch_texcoord = NULL;
+
+ ret->size_UVarray = size_UVarray;
+ ret->size_length_array = size_length_array;
+ ret->UVarray = (float*) malloc(sizeof(float) * size_UVarray);
+ assert(ret->UVarray);
+ ret->length_array = (int *)malloc(sizeof(int) * size_length_array);
+ assert(ret->length_array);
+ ret->type_array = (GLenum *)malloc(sizeof(GLenum) * size_length_array);
+ assert(ret->type_array);
+
+ ret->index_UVarray = 0;
+ ret->index_length_array = 0;
+
+ ret->vertex_array = NULL;
+ ret->normal_array = NULL;
+ ret->color_array = NULL;
+ ret->texcoord_array = NULL;
+
+ ret->next = NULL;
+ return ret;
+}
+
+void bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints)
+{
+ switch(maptype){
+ case GL_MAP2_VERTEX_3:
+ bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_VERTEX_4:
+ bpm->bpatch = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4,ustride, vstride, ctlpoints );
+ break;
+ case GL_MAP2_NORMAL:
+ bpm->bpatch_normal = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_INDEX:
+ bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_COLOR_4:
+ bpm->bpatch_color = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 1, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 2, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 3, ustride, vstride, ctlpoints);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ bpm->bpatch_texcoord = bezierPatchMake2(umin, vmin, umax, vmax, uorder, vorder, 4, ustride, vstride, ctlpoints);
+ break;
+ default:
+ fprintf(stderr, "error in bezierPatchMeshPutPatch, maptype=%i is wrong, maptype,map is invalid\n", maptype);
+ }
+}
+
+
+/*delete everything including the arrays. So if you want to output the
+ *pointers of the arrays, you should not use this function to deallocate space.
+ *you should dealocate manually
+ */
+void bezierPatchMeshDelete(bezierPatchMesh *bpm)
+{
+ if(bpm->bpatch != NULL)
+ bezierPatchDelete(bpm->bpatch);
+ if(bpm->bpatch_normal != NULL)
+ bezierPatchDelete(bpm->bpatch_normal);
+ if(bpm->bpatch_color != NULL)
+ bezierPatchDelete(bpm->bpatch_color);
+ if(bpm->bpatch_texcoord != NULL)
+ bezierPatchDelete(bpm->bpatch_texcoord);
+
+ free(bpm->UVarray);
+ free(bpm->length_array);
+ free(bpm->vertex_array);
+ free(bpm->normal_array);
+ free(bpm->type_array);
+ free(bpm);
+}
+
+/*begin a strip
+ *type is the primitive type:
+ */
+void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type)
+{
+ bpm->counter = 0;
+ bpm->type = type;
+}
+
+/*signal the end of the current strip*/
+void bezierPatchMeshEndStrip(bezierPatchMesh *bpm)
+{
+ int i;
+
+ /*if there are no vertices in this strip, then nothing needs to be done*/
+ if(bpm->counter == 0) return;
+
+ /*if the length_array is full, it should be expanded*/
+ if(bpm->index_length_array >= bpm->size_length_array)
+ {
+ int *temp = (int*) malloc(sizeof(int) * (bpm->size_length_array*2 + 1));
+ assert(temp);
+ GLenum *temp_type = (GLenum*) malloc(sizeof(GLenum) * (bpm->size_length_array*2 + 1));
+ assert(temp_type);
+ /*update the size*/
+ bpm->size_length_array = bpm->size_length_array*2 + 1;
+
+ /*copy*/
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ temp[i] = bpm->length_array[i];
+ temp_type[i] = bpm->type_array[i];
+ }
+
+ /*deallocate old array*/
+ free(bpm->length_array);
+ free(bpm->type_array);
+
+ /*point to the new array which is twice as bigger*/
+ bpm->length_array = temp;
+ bpm->type_array = temp_type;
+ }
+ bpm->type_array[bpm->index_length_array] = bpm->type;
+ bpm->length_array[bpm->index_length_array++] = bpm->counter;
+
+}
+
+/*insert (u,v) */
+void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v)
+{
+ int i;
+ /*if the UVarray is full, it should be expanded*/
+ if(bpm->index_UVarray+1 >= bpm->size_UVarray)
+ {
+ float *temp = (float*) malloc(sizeof(float) * (bpm->size_UVarray * 2 + 2));
+ assert(temp);
+
+ /*update the size*/
+ bpm->size_UVarray = bpm->size_UVarray*2 + 2;
+
+ /*copy*/
+ for(i=0; i<bpm->index_UVarray; i++)
+ {
+ temp[i] = bpm->UVarray[i];
+ }
+
+ /*deallocate old array*/
+ free(bpm->UVarray);
+
+ /*pointing to the new arrays*/
+ bpm->UVarray = temp;
+ }
+ /*insert the new UV*/
+ bpm->UVarray[bpm->index_UVarray] = u;
+ bpm->index_UVarray++;
+ bpm->UVarray[bpm->index_UVarray] = v;
+ bpm->index_UVarray++;
+
+ /*update counter: one more vertex*/
+ bpm->counter++;
+
+
+}
+
+void bezierPatchMeshPrint(bezierPatchMesh *bpm)
+{
+ int i;
+ printf("the bezier patch is\n");
+ bezierPatchPrint(bpm->bpatch);
+ printf("index_length_array= %i\n", bpm->index_length_array);
+ printf("size_length_array =%i\n", bpm->size_length_array);
+ printf("index_UVarray =%i\n", bpm->index_UVarray);
+ printf("size_UVarray =%i\n", bpm->size_UVarray);
+ printf("UVarray is\n");
+ for(i=0; i<bpm->index_UVarray; i++)
+ printf("%f ", bpm->UVarray[i]);
+
+ printf("length_array is\n");
+ for(i=0; i<bpm->index_length_array; i++)
+ printf("%i ", bpm->length_array[i]);
+ printf("\n");
+
+}
+
+/*insert a new patch in front of the current linked list and return the new list*/
+bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm)
+{
+ bpm->next=list;
+ return bpm;
+}
+
+/*print all the patches*/
+void bezierPatchMeshListPrint(bezierPatchMesh* list)
+{
+ bezierPatchMesh *temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshPrint(temp);
+ }
+}
+
+int bezierPatchMeshListTotalStrips(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh *temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += temp->index_length_array;
+ }
+ return sum;
+}
+
+int bezierPatchMeshListTotalVert(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh *temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += temp->index_UVarray;
+ }
+ return sum/2;
+}
+
+int bezierPatchMeshListNumTriangles(bezierPatchMesh* list)
+{
+ int sum=0;
+ bezierPatchMesh* temp;
+ for(temp=list; temp != NULL; temp = temp->next)
+ {
+ sum += bezierPatchMeshNumTriangles(temp);
+ }
+ return sum;
+}
+
+int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm)
+{
+ int i;
+ int sum=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ switch(bpm->type_array[i])
+ {
+ case GL_TRIANGLES:
+ sum += bpm->length_array[i]/3;
+ break;
+ case GL_TRIANGLE_FAN:
+ if(bpm->length_array[i] > 2)
+ sum += bpm->length_array[i]-2;
+ break;
+ case GL_TRIANGLE_STRIP:
+ if(bpm->length_array[i] > 2)
+ sum += bpm->length_array[i]-2;
+ break;
+ case GL_QUAD_STRIP:
+ if(bpm->length_array[i]>2)
+ sum += (bpm->length_array[i]-2);
+ break;
+ default:
+ fprintf(stderr,"error in bezierPatchMeshListNumTriangles, type invalid\n");
+ }
+ }
+ return sum;
+}
+
+/*delete degenerate triangles*/
+void bezierPatchMeshDelDeg(bezierPatchMesh* bpm)
+{
+ if(bpm == NULL) return;
+ int i,j,k;
+ int *new_length_array;
+ GLenum *new_type_array;
+ int index_new_length_array;
+ float *new_UVarray;
+ int index_new_UVarray;
+
+ new_length_array = (int*)malloc(sizeof(int) * bpm->index_length_array);
+ assert(new_length_array);
+ new_type_array = (GLenum*)malloc(sizeof(GLenum) * bpm->index_length_array);
+ assert(new_length_array);
+ new_UVarray = (float*) malloc(sizeof(float) * bpm->index_UVarray);
+ assert(new_UVarray);
+
+ index_new_length_array = 0;
+ index_new_UVarray=0;
+ k=0;
+ for(i=0; i<bpm->index_length_array; i++){
+
+ /*(if not degenerate, we have to copy*/
+ if( (bpm->length_array[i] != 3) || (!isDegenerate(bpm->UVarray+k, bpm->UVarray+k+2, bpm->UVarray+k+4)))
+ {
+ for(j=0; j<2* bpm->length_array[i]; j++)
+ new_UVarray[index_new_UVarray++] = bpm->UVarray[k++];
+
+ new_length_array[index_new_length_array] = bpm->length_array[i];
+ new_type_array[index_new_length_array] = bpm->type_array[i];
+ index_new_length_array++;
+ }
+ else
+ {
+ k += 6;
+ }
+ }
+ free(bpm->UVarray);
+ free(bpm->length_array);
+ free(bpm->type_array);
+ bpm->UVarray=new_UVarray;
+ bpm->length_array=new_length_array;
+ bpm->type_array=new_type_array;
+ bpm->index_UVarray = index_new_UVarray;
+ bpm->index_length_array = index_new_length_array;
+
+}
+
+/*(u,v) to XYZ
+ *the xyz and normals are stored in vertex_array,
+ *and normal_array. the spaces of both are allocated here
+ */
+void bezierPatchMeshEval(bezierPatchMesh* bpm)
+{
+ int i,j,k,l;
+ float u,v;
+ float u0 = bpm->bpatch->umin;
+ float u1 = bpm->bpatch->umax;
+ int uorder = bpm->bpatch->uorder;
+ float v0 = bpm->bpatch->vmin;
+ float v1 = bpm->bpatch->vmax;
+ int vorder = bpm->bpatch->vorder;
+ int dimension = bpm->bpatch->dimension;
+ int ustride = dimension * vorder;
+ int vstride = dimension;
+ float *ctlpoints = bpm->bpatch->ctlpoints;
+
+ bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->vertex_array);
+ bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->normal_array);
+
+ k=0;
+ l=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+ bezierSurfEval(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->vertex_array+l);
+ bezierSurfEvalNormal(u0,u1,uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u,v, bpm->normal_array+l);
+ k += 2;
+ l += 3;
+ }
+ }
+}
+
+void bezierPatchMeshListEval(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshEval(temp);
+ }
+}
+
+void bezierPatchMeshDraw(bezierPatchMesh* bpm)
+{
+ int i,j,k;
+ k=0;
+ /*k is the index of the first component of the current vertex*/
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ glBegin(bpm->type_array[i]);
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ glNormal3fv(bpm->normal_array+k);
+ glVertex3fv(bpm->vertex_array+k);
+ k+= 3;
+ }
+ glEnd();
+ }
+}
+
+void bezierPatchMeshListDraw(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ bezierPatchMeshDraw(temp);
+ }
+}
+
+void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips)
+{
+ int i,j,k,l;
+ bezierPatchMesh *temp;
+ int total_num_vertices = bezierPatchMeshListTotalVert(list);
+ (*vertex_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
+ assert(*vertex_array);
+ (*normal_array) = (float *) malloc(sizeof(float) * total_num_vertices*3);
+ assert(*normal_array);
+
+ *num_strips = bezierPatchMeshListTotalStrips(list);
+
+ *length_array = (int*) malloc(sizeof(int) * (*num_strips));
+ assert(*length_array);
+
+ *type_array = (GLenum*) malloc(sizeof(GLenum) * (*num_strips));
+ assert(*type_array);
+
+ k=0;
+ l=0;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ int x=0;
+ for(i=0; i<temp->index_length_array; i++)
+ {
+ for(j=0; j<temp->length_array[i]; j++)
+ {
+ (*vertex_array)[k] = temp->vertex_array[x];
+ (*vertex_array)[k+1] = temp->vertex_array[x+1];
+ (*vertex_array)[k+2] = temp->vertex_array[x+2];
+
+ (*normal_array)[k] = temp->normal_array[x];
+ (*normal_array)[k+1] = temp->normal_array[x+1];
+ (*normal_array)[k+2] = temp->normal_array[x+2];
+
+ x += 3;
+ k += 3;
+ }
+ (*type_array)[l] = temp->type_array[i];
+ (*length_array)[l++] = temp->length_array[i];
+ }
+ }
+}
+
+
+
+static int isDegenerate(float A[2], float B[2], float C[2])
+{
+ if( (A[0] == B[0] && A[1]==B[1]) ||
+ (A[0] == C[0] && A[1]==C[1]) ||
+ (B[0] == C[0] && B[1]==C[1])
+ )
+ return 1;
+ else
+ return 0;
+}
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h
new file mode 100644
index 000000000..449329665
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/bezierPatchMesh.h
@@ -0,0 +1,120 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _BEZIERPATCHMESH_H
+#define _BEZIERPATCHMESH_H
+
+#include "bezierPatch.h"
+
+typedef struct bezierPatchMesh{
+ bezierPatch *bpatch; /*vertex*/
+ bezierPatch *bpatch_normal;
+ bezierPatch *bpatch_texcoord; /*s,t,r,q*/
+ bezierPatch *bpatch_color; /*RGBA*/
+
+ float *UVarray; /*all UV components of all vertices of all strips*/
+ int *length_array; /*[i] is the number of vertices in the ith strip*/
+ GLenum *type_array; /*[i] is the type of the ith primitive*/
+
+ /*to support dynamic insertion*/
+ int size_UVarray;
+ int index_UVarray;
+ int size_length_array;
+ int index_length_array;
+
+ int counter; /*track the current strip size*/
+ GLenum type; /*track the current type: 0: GL_TRIANGLES, 1: GL_TRIANGLE_STRIP*/
+
+ /*we eventually want to evaluate from (u,v) to (x,y,z) and draw them*/
+ float *vertex_array; /*each vertex contains three components*/
+ float *normal_array; /*each normal contains three components*/
+ float *color_array;
+ float *texcoord_array;
+
+ /*in case we need a linked list*/
+ struct bezierPatchMesh *next;
+} bezierPatchMesh;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+bezierPatchMesh *bezierPatchMeshMake(int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints, int size_UVarray, int size_length_array);
+
+/*initilize patches to be null*/
+bezierPatchMesh *bezierPatchMeshMake2(int size_UVarray, int size_length_array);
+
+void bezierPatchMeshPutPatch(bezierPatchMesh *bpm, int maptype, float umin, float umax, int ustride, int uorder, float vmin, float vmax, int vstride, int vorder, float *ctlpoints);
+
+void bezierPatchMeshDelete(bezierPatchMesh *bpm);
+
+void bezierPatchMeshBeginStrip(bezierPatchMesh *bpm, GLenum type);
+
+void bezierPatchMeshEndStrip(bezierPatchMesh *bpm);
+
+void bezierPatchMeshInsertUV(bezierPatchMesh *bpm, float u, float v);
+
+void bezierPatchMeshPrint(bezierPatchMesh *bpm);
+
+bezierPatchMesh* bezierPatchMeshListInsert(bezierPatchMesh* list, bezierPatchMesh* bpm);
+
+void bezierPatchMeshListPrint(bezierPatchMesh* list);
+
+int bezierPatchMeshListTotalStrips(bezierPatchMesh* list);
+
+int bezierPatchMeshListTotalVert(bezierPatchMesh* list);
+int bezierPatchMeshNumTriangles(bezierPatchMesh* bpm);
+int bezierPatchMeshListNumTriangles(bezierPatchMesh* list);
+
+void bezierPatchMeshDelDeg(bezierPatchMesh* bpm);
+
+
+void bezierPatchMeshEval(bezierPatchMesh* bpm);
+
+void bezierPatchMeshDraw(bezierPatchMesh* bpm);
+
+void bezierPatchMeshListDraw(bezierPatchMesh* list);
+void bezierPatchMeshListEval(bezierPatchMesh* list);
+void bezierPatchMeshListCollect(bezierPatchMesh* list, float **vertex_array, float **normal_array, int **length_array, GLenum **type_array, int *num_strips);
+
+void bezierPatchMeshListDelDeg(bezierPatchMesh* list);
+void bezierPatchMeshListDelete(bezierPatchMesh *list);
+bezierPatchMesh* bezierPatchMeshListReverse(bezierPatchMesh* list);
+void drawStrips(float *vertex_array, float *normal_array, int *length_array, GLenum *type_array, int num_strips);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.cc b/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.cc
new file mode 100644
index 000000000..b6591dba0
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.cc
@@ -0,0 +1,402 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glcurveval.c++
+ *
+ */
+
+/* Polynomial Evaluator Interface */
+
+#include "gluos.h"
+#include "glimports.h"
+#include "glrenderer.h"
+#include "glcurveval.h"
+#include "nurbsconsts.h"
+
+OpenGLCurveEvaluator::OpenGLCurveEvaluator(void)
+{
+ //no default callback functions
+ beginCallBackN = NULL;
+ endCallBackN = NULL;
+ vertexCallBackN = NULL;
+ normalCallBackN = NULL;
+ colorCallBackN = NULL;
+ texcoordCallBackN = NULL;
+ beginCallBackData = NULL;
+ endCallBackData = NULL;
+ vertexCallBackData = NULL;
+ normalCallBackData = NULL;
+ colorCallBackData = NULL;
+ texcoordCallBackData = NULL;
+
+ userData = NULL;
+
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ em_vertex.uprime = -1.0;
+ em_normal.uprime = -1.0;
+ em_color.uprime = -1.0;
+ em_texcoord.uprime = -1.0;
+ output_triangles = 0; // don't output triangles by default
+}
+
+OpenGLCurveEvaluator::~OpenGLCurveEvaluator(void)
+{
+}
+
+/* added nonsense to avoid the warning messages at compile time */
+void
+OpenGLCurveEvaluator::addMap(CurveMap *m)
+{
+ m = m;
+}
+
+void
+OpenGLCurveEvaluator::range1f(long type, REAL *from, REAL *to)
+{
+ type = type;
+ from = from;
+ to = to;
+}
+
+void
+OpenGLCurveEvaluator::domain1f(REAL ulo, REAL uhi)
+{
+ ulo = ulo;
+ uhi = uhi;
+}
+
+void
+OpenGLCurveEvaluator::bgnline(void)
+{
+ if(output_triangles)
+ beginCallBack(GL_LINE_STRIP, userData);
+ else
+ glBegin((GLenum) GL_LINE_STRIP);
+}
+
+void
+OpenGLCurveEvaluator::endline(void)
+{
+ if(output_triangles)
+ endCallBack(userData);
+ else
+ glEnd();
+}
+
+/*---------------------------------------------------------------------------
+ * disable - turn off a curve map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::disable(long type)
+{
+ glDisable((GLenum) type);
+}
+
+/*---------------------------------------------------------------------------
+ * enable - turn on a curve map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::enable(long type)
+{
+ glEnable((GLenum) type);
+}
+
+/*-------------------------------------------------------------------------
+ * mapgrid1f - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::mapgrid1f(long nu, REAL u0, REAL u1)
+{
+ if(output_triangles)
+ {
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = (int) nu;
+ }
+ else
+ glMapGrid1f((GLint) nu, (GLfloat) u0, (GLfloat) u1);
+}
+
+/*-------------------------------------------------------------------------
+ * bgnmap1 - preamble to curve definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::bgnmap1f(long)
+{
+ if(output_triangles)
+ {
+ //initialized so that no maps are set initially
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+ //no need to worry about gl states when doing callback
+ }
+ else
+ glPushAttrib((GLbitfield) GL_EVAL_BIT);
+}
+
+/*-------------------------------------------------------------------------
+ * endmap1 - postamble to a curve map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::endmap1f(void)
+{
+ if(output_triangles)
+ {
+
+ }
+ else
+ glPopAttrib();
+}
+
+/*-------------------------------------------------------------------------
+ * map1f - pass a desription of a curve map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLCurveEvaluator::map1f(
+ long type, /* map type */
+ REAL ulo, /* lower parametric bound */
+ REAL uhi, /* upper parametric bound */
+ long stride, /* distance to next point in REALS */
+ long order, /* parametric order */
+ REAL *pts /* control points */
+)
+{
+ if(output_triangles)
+ {
+ int dimension = 0;
+ int which = 0;
+ switch(type){
+ case GL_MAP1_VERTEX_3:
+ which = 0;
+ dimension = 3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ which=0;
+ dimension = 4;
+ break;
+ case GL_MAP1_INDEX:
+ which=2;
+ dimension = 1;
+ break;
+ case GL_MAP1_COLOR_4:
+ which=2;
+ dimension = 4;
+ break;
+ case GL_MAP1_NORMAL:
+ which=1;
+ dimension = 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ which=3;
+ dimension = 1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ which=3;
+ dimension = 2;
+ break;
+
+ case GL_MAP1_TEXTURE_COORD_3:
+ which=3;
+ dimension = 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ which=3;
+ dimension = 4;
+ break;
+ }
+ inMap1f(which, dimension, ulo, uhi, stride, order, pts);
+ }
+ else
+ glMap1f((GLenum) type, (GLfloat) ulo, (GLfloat) uhi, (GLint) stride,
+ (GLint) order, (const GLfloat *) pts);
+}
+
+/*-------------------------------------------------------------------------
+ * mapmesh1f - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::mapmesh1f(long style, long from, long to)
+{
+ if(output_triangles)
+ {
+ inMapMesh1f((int) from, (int) to);
+ }
+ else
+ {
+ switch(style) {
+ default:
+ case N_MESHFILL:
+ case N_MESHLINE:
+ glEvalMesh1((GLenum) GL_LINE, (GLint) from, (GLint) to);
+ break;
+ case N_MESHPOINT:
+ glEvalMesh1((GLenum) GL_POINT, (GLint) from, (GLint) to);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * evalpoint1i - evaluate a point on a curve
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::evalpoint1i(long i)
+{
+ glEvalPoint1((GLint) i);
+}
+
+/*-------------------------------------------------------------------------
+ * evalcoord1f - evaluate a point on a curve
+ *-------------------------------------------------------------------------
+ */
+void OpenGLCurveEvaluator::evalcoord1f(long, REAL u)
+{
+ glEvalCoord1f((GLfloat) u);
+}
+
+void
+#ifdef _WIN32
+OpenGLCurveEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)())
+#else
+OpenGLCurveEvaluator::putCallBack(GLenum which, _GLUfuncptr fn)
+#endif
+{
+ switch(which)
+ {
+ case GLU_NURBS_BEGIN:
+ beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn;
+ break;
+ case GLU_NURBS_END:
+ endCallBackN = (void (GLAPIENTRY *) (void)) fn;
+ break;
+ case GLU_NURBS_VERTEX:
+ vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_NORMAL:
+ normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_COLOR:
+ colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD:
+ texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_BEGIN_DATA:
+ beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn;
+ break;
+ case GLU_NURBS_END_DATA:
+ endCallBackData = (void (GLAPIENTRY *) (void*)) fn;
+ break;
+ case GLU_NURBS_VERTEX_DATA:
+ vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_NORMAL_DATA:
+ normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_COLOR_DATA:
+ colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ }
+}
+
+void
+OpenGLCurveEvaluator::beginCallBack(GLenum which, void *data)
+{
+ if(beginCallBackData)
+ beginCallBackData(which, data);
+ else if(beginCallBackN)
+ beginCallBackN(which);
+}
+
+void
+OpenGLCurveEvaluator::endCallBack(void *data)
+{
+ if(endCallBackData)
+ endCallBackData(data);
+ else if(endCallBackN)
+ endCallBackN();
+}
+
+void
+OpenGLCurveEvaluator::vertexCallBack(const GLfloat *vert, void* data)
+{
+ if(vertexCallBackData)
+ vertexCallBackData(vert, data);
+ else if(vertexCallBackN)
+ vertexCallBackN(vert);
+}
+
+
+void
+OpenGLCurveEvaluator::normalCallBack(const GLfloat *normal, void* data)
+{
+ if(normalCallBackData)
+ normalCallBackData(normal, data);
+ else if(normalCallBackN)
+ normalCallBackN(normal);
+}
+
+void
+OpenGLCurveEvaluator::colorCallBack(const GLfloat *color, void* data)
+{
+ if(colorCallBackData)
+ colorCallBackData(color, data);
+ else if(colorCallBackN)
+ colorCallBackN(color);
+}
+
+void
+OpenGLCurveEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data)
+{
+ if(texcoordCallBackData)
+ texcoordCallBackData(texcoord, data);
+ else if(texcoordCallBackN)
+ texcoordCallBackN(texcoord);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.h b/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.h
new file mode 100644
index 000000000..8fa493034
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glcurveval.h
@@ -0,0 +1,157 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glcurveval.h
+ *
+ */
+
+#ifndef __gluglcurveval_h_
+#define __gluglcurveval_h_
+
+#include "gluos.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "basiccrveval.h"
+
+class CurveMap;
+
+/*for internal evaluator callback stuff*/
+#ifndef IN_MAX_BEZIER_ORDER
+#define IN_MAX_BEZIER_ORDER 40 /*XXX should be bigger than machine order*/
+#endif
+
+#ifndef IN_MAX_DIMENSION
+#define IN_MAX_DIMENSION 4
+#endif
+
+typedef struct curveEvalMachine{
+ REAL uprime; //cached previously evaluated uprime
+ int k; //the dimension
+ REAL u1;
+ REAL u2;
+ int ustride;
+ int uorder;
+ REAL ctlpoints[IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+ REAL ucoeff[IN_MAX_BEZIER_ORDER];//cache the polynomial values
+} curveEvalMachine;
+
+class OpenGLCurveEvaluator : public BasicCurveEvaluator {
+public:
+ OpenGLCurveEvaluator(void);
+ virtual ~OpenGLCurveEvaluator(void);
+ void range1f(long, REAL *, REAL *);
+ void domain1f(REAL, REAL);
+ void addMap(CurveMap *);
+
+ void enable(long);
+ void disable(long);
+ void bgnmap1f(long);
+ void map1f(long, REAL, REAL, long, long, REAL *);
+ void mapgrid1f(long, REAL, REAL);
+ void mapmesh1f(long, long, long);
+ void evalpoint1i(long);
+ void evalcoord1f(long, REAL);
+ void endmap1f(void);
+
+ void bgnline(void);
+ void endline(void);
+
+ void put_vertices_call_back(int flag)
+ {
+ output_triangles = flag;
+ }
+#ifdef _WIN32
+ void putCallBack(GLenum which, void (GLAPIENTRY *fn)() );
+#else
+ void putCallBack(GLenum which, _GLUfuncptr fn );
+#endif
+ void set_callback_userData(void *data)
+ {
+ userData = data;
+ }
+
+/*------------------begin for curveEvalMachine------------*/
+curveEvalMachine em_vertex;
+curveEvalMachine em_normal;
+curveEvalMachine em_color;
+curveEvalMachine em_texcoord;
+int vertex_flag; //whether there is a vertex map or not
+int normal_flag; //whether there is a normal map or not
+int color_flag; //whether there is a color map or not
+int texcoord_flag; //whether there is a texture map or not
+
+REAL global_grid_u0;
+REAL global_grid_u1;
+int global_grid_nu;
+
+void inMap1f(int which, //0: vert, 1: norm, 2: color, 3: tex
+ int dimension,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL *ctlpoints);
+
+void inPreEvaluate(int order, REAL vprime, REAL *coeff);
+void inDoDomain1(curveEvalMachine *em, REAL u, REAL *retPoint);
+void inDoEvalCoord1(REAL u);
+void inMapMesh1f(int umin, int umax);
+
+void (GLAPIENTRY *beginCallBackN) (GLenum type);
+void (GLAPIENTRY *endCallBackN) (void);
+void (GLAPIENTRY *vertexCallBackN) (const GLfloat *vert);
+void (GLAPIENTRY *normalCallBackN) (const GLfloat *normal);
+void (GLAPIENTRY *colorCallBackN) (const GLfloat *color);
+void (GLAPIENTRY *texcoordCallBackN) (const GLfloat *texcoord);
+
+void (GLAPIENTRY *beginCallBackData) (GLenum type, void* data);
+void (GLAPIENTRY *endCallBackData) (void* data);
+void (GLAPIENTRY *vertexCallBackData) (const GLfloat *vert, void* data);
+void (GLAPIENTRY *normalCallBackData) (const GLfloat *normal, void* data);
+void (GLAPIENTRY *colorCallBackData) (const GLfloat *color, void* data);
+void (GLAPIENTRY *texcoordCallBackData) (const GLfloat *texcoord, void* data);
+
+void* userData; //the opaque pointer for Data callback functions
+void beginCallBack(GLenum type, void* data);
+void endCallBack(void* data);
+void vertexCallBack(const GLfloat *vert, void *data);
+void normalCallBack(const GLfloat *normal, void* data);
+void colorCallBack(const GLfloat *color, void* data);
+void texcoordCallBack(const GLfloat *texcoord, void* data);
+
+
+/*------------------end for curveEvalMachine------------*/
+
+private:
+ int output_triangles; //true 1; false 0
+};
+
+#endif /* __gluglcurveval_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glimports.h b/mesalib/src/glu/sgi/libnurbs/interface/glimports.h
new file mode 100644
index 000000000..6e69feb40
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glimports.h
@@ -0,0 +1,42 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glimports.h
+ *
+ */
+
+#ifndef __gluimports_h_
+#define __gluimports_h_
+
+#include "mystdlib.h"
+#include "mystdio.h"
+
+#endif /* __gluimports_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glinterface.cc b/mesalib/src/glu/sgi/libnurbs/interface/glinterface.cc
new file mode 100644
index 000000000..ba64bcd2d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glinterface.cc
@@ -0,0 +1,469 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "glrenderer.h"
+#include "nurbsconsts.h"
+
+//#define DOWN_LOAD_NURBS
+#ifdef DOWN_LOAD_NURBS
+
+#include "oglTrimNurbs.h"
+static int surfcount = 0;
+static oglTrimNurbs* otn = NULL;
+nurbSurf* tempNurb = NULL;
+oglTrimLoops* tempTrim = NULL;
+#endif
+
+
+//for LOD
+extern "C" {void glu_LOD_eval_list(GLUnurbs *nurb, int level);}
+
+void glu_LOD_eval_list(GLUnurbs *nurb, int level)
+{
+ nurb->LOD_eval_list(level);
+}
+
+GLUnurbs * GLAPIENTRY
+gluNewNurbsRenderer(void)
+{
+ GLUnurbs *t;
+
+ t = new GLUnurbs();
+ return t;
+}
+
+void GLAPIENTRY
+gluDeleteNurbsRenderer(GLUnurbs *r)
+{
+ delete r;
+}
+
+extern "C"
+void GLAPIENTRY
+
+gluDeleteNurbsTessellatorEXT(GLUnurbsObj *r)
+{
+ delete r;
+}
+
+void GLAPIENTRY
+gluBeginSurface(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+surfcount++;
+tempTrim = OTL_make(10,10);
+#endif
+ r->bgnsurface(0);
+}
+
+void GLAPIENTRY
+gluBeginCurve(GLUnurbs *r)
+{
+ r->bgncurve(0);
+}
+
+void GLAPIENTRY
+gluEndCurve(GLUnurbs *r)
+{
+ r->endcurve();
+}
+
+void GLAPIENTRY
+gluEndSurface(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+if(surfcount == 1)
+ otn = OTN_make(1);
+OTN_insert(otn, tempNurb, tempTrim);
+if(surfcount >= 1)
+{
+#ifdef DEBUG
+printf("write file\n");
+#endif
+OTN_write(otn, "out.otn");
+
+}
+#endif
+
+ r->endsurface();
+}
+
+void GLAPIENTRY
+gluBeginTrim(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_bgnTrim(tempTrim);
+#endif
+
+ r->bgntrim();
+}
+
+void GLAPIENTRY
+gluEndTrim(GLUnurbs *r)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_endTrim(tempTrim);
+#endif
+ r->endtrim();
+}
+
+void GLAPIENTRY
+gluPwlCurve(GLUnurbs *r, GLint count, INREAL array[],
+ GLint stride, GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_pwlCurve(tempTrim, count, array, stride, type);
+#endif
+
+ int realType;
+ switch(type) {
+ case GLU_MAP1_TRIM_2:
+ realType = N_P2D;
+ break;
+ case GLU_MAP1_TRIM_3:
+ realType = N_P2DR;
+ break;
+ default:
+ realType = type;
+ break;
+ }
+ r->pwlcurve(count, array, sizeof(INREAL) * stride, realType);
+}
+
+void GLAPIENTRY
+gluNurbsCurve(GLUnurbs *r, GLint nknots, INREAL knot[], GLint stride,
+ INREAL ctlarray[], GLint order, GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+OTL_nurbsCurve(tempTrim, nknots, knot, stride, ctlarray, order, type);
+#endif
+
+ int realType;
+
+ switch(type) {
+ case GLU_MAP1_TRIM_2:
+ realType = N_P2D;
+ break;
+ case GLU_MAP1_TRIM_3:
+ realType = N_P2DR;
+ break;
+ default:
+ realType = type;
+ break;
+ }
+
+ r->nurbscurve(nknots, knot, sizeof(INREAL) * stride, ctlarray, order,
+ realType);
+}
+
+void GLAPIENTRY
+gluNurbsSurface(GLUnurbs *r, GLint sknot_count, GLfloat *sknot,
+ GLint tknot_count, GLfloat *tknot,
+ GLint s_stride, GLint t_stride,
+ GLfloat *ctlarray, GLint sorder, GLint torder,
+ GLenum type)
+{
+#ifdef DOWN_LOAD_NURBS
+ {
+ int dimension;
+ switch(type){
+ case GL_MAP2_VERTEX_3:
+ dimension = 3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ dimension = 4;
+ break;
+ default:
+ fprintf(stderr, "error in glinterface.c++, type no implemented\n");
+ exit(1);
+ }
+tempNurb = nurbSurfMake(sknot_count, sknot,
+ tknot_count, tknot,
+ sorder, torder,
+ dimension,
+ ctlarray,
+ s_stride, t_stride);
+
+ }
+#endif
+
+ r->nurbssurface(sknot_count, sknot, tknot_count, tknot,
+ sizeof(INREAL) * s_stride, sizeof(INREAL) * t_stride,
+ ctlarray, sorder, torder, type);
+}
+
+void GLAPIENTRY
+gluLoadSamplingMatrices(GLUnurbs *r, const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4])
+{
+ r->useGLMatrices(modelMatrix, projMatrix, viewport);
+}
+
+void GLAPIENTRY
+gluNurbsProperty(GLUnurbs *r, GLenum property, GLfloat value)
+{
+ GLfloat nurbsValue;
+
+ switch (property) {
+ case GLU_AUTO_LOAD_MATRIX:
+ r->setautoloadmode(value);
+ return;
+
+ case GLU_CULLING:
+ if (value != 0.0) {
+ nurbsValue = N_CULLINGON;
+ } else {
+ nurbsValue = N_NOCULLING;
+ }
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_CULLING, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_CULLING, nurbsValue);
+ return;
+
+ case GLU_SAMPLING_METHOD:
+ if (value == GLU_PATH_LENGTH) {
+ nurbsValue = N_PATHLENGTH;
+ } else if (value == GLU_PARAMETRIC_ERROR) {
+ nurbsValue = N_PARAMETRICDISTANCE;
+ } else if (value == GLU_DOMAIN_DISTANCE) {
+ nurbsValue = N_DOMAINDISTANCE;
+ r->set_is_domain_distance_sampling(1); //optimzing untrimmed case
+
+ } else if (value == GLU_OBJECT_PARAMETRIC_ERROR) {
+ nurbsValue = N_OBJECTSPACE_PARA;
+ r->setautoloadmode( 0.0 );
+ r->setSamplingMatrixIdentity();
+ } else if (value == GLU_OBJECT_PATH_LENGTH) {
+ nurbsValue = N_OBJECTSPACE_PATH;
+ r->setautoloadmode( 0.0 );
+ r->setSamplingMatrixIdentity();
+ } else {
+ r->postError(GLU_INVALID_VALUE);
+ return;
+ }
+
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
+ return;
+
+ case GLU_SAMPLING_TOLERANCE:
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_PIXEL_TOLERANCE, value);
+ return;
+
+ case GLU_PARAMETRIC_TOLERANCE:
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_ERROR_TOLERANCE, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_ERROR_TOLERANCE, value);
+ return;
+
+
+ case GLU_DISPLAY_MODE:
+
+ if (value == GLU_FILL) {
+ nurbsValue = N_FILL;
+ } else if (value == GLU_OUTLINE_POLYGON) {
+ nurbsValue = N_OUTLINE_POLY;
+ } else if (value == GLU_OUTLINE_PATCH) {
+ nurbsValue = N_OUTLINE_PATCH;
+ } else {
+ r->postError(GLU_INVALID_VALUE);
+ return;
+ }
+ r->setnurbsproperty(N_DISPLAY, nurbsValue);
+
+ break;
+
+ case GLU_U_STEP:
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_S_STEPS, value);
+
+ //added for optimizing untrimmed case
+ r->set_domain_distance_u_rate(value);
+ break;
+
+ case GLU_V_STEP:
+ r->setnurbsproperty(GL_MAP1_VERTEX_3, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP1_VERTEX_4, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
+ r->setnurbsproperty(GL_MAP2_VERTEX_4, N_T_STEPS, value);
+
+ //added for optimizing untrimmed case
+ r->set_domain_distance_v_rate(value);
+ break;
+
+ case GLU_NURBS_MODE:
+ if(value == GLU_NURBS_RENDERER)
+ r->put_callbackFlag(0);
+ else if(value == GLU_NURBS_TESSELLATOR)
+ r->put_callbackFlag(1);
+ else
+ r->postError(GLU_INVALID_ENUM);
+ break;
+
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+void GLAPIENTRY
+gluGetNurbsProperty(GLUnurbs *r, GLenum property, GLfloat *value)
+{
+ GLfloat nurbsValue;
+
+ switch(property) {
+ case GLU_AUTO_LOAD_MATRIX:
+ if (r->getautoloadmode()) {
+ *value = GL_TRUE;
+ } else {
+ *value = GL_FALSE;
+ }
+ break;
+ case GLU_CULLING:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, &nurbsValue);
+ if (nurbsValue == N_CULLINGON) {
+ *value = GL_TRUE;
+ } else {
+ *value = GL_FALSE;
+ }
+ break;
+ case GLU_SAMPLING_METHOD:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, value);
+ if(*value == N_PATHLENGTH)
+ *value = GLU_PATH_LENGTH;
+ else if(*value == N_PARAMETRICDISTANCE)
+ *value = GLU_PARAMETRIC_ERROR;
+ else if(*value == N_DOMAINDISTANCE)
+ *value = GLU_DOMAIN_DISTANCE;
+ else if(*value == N_OBJECTSPACE_PATH)
+ *value = GLU_OBJECT_PATH_LENGTH;
+ else if(*value == N_OBJECTSPACE_PARA)
+ *value = GLU_OBJECT_PARAMETRIC_ERROR;
+ break;
+ case GLU_SAMPLING_TOLERANCE:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
+ break;
+ case GLU_PARAMETRIC_TOLERANCE:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
+ break;
+
+ case GLU_U_STEP:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
+ break;
+ case GLU_V_STEP:
+ r->getnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
+ break;
+ case GLU_DISPLAY_MODE:
+ r->getnurbsproperty(N_DISPLAY, &nurbsValue);
+ if (nurbsValue == N_FILL) {
+ *value = GLU_FILL;
+ } else if (nurbsValue == N_OUTLINE_POLY) {
+ *value = GLU_OUTLINE_POLYGON;
+ } else {
+ *value = GLU_OUTLINE_PATCH;
+ }
+ break;
+
+ case GLU_NURBS_MODE:
+ if(r->is_callback())
+ *value = GLU_NURBS_TESSELLATOR;
+ else
+ *value = GLU_NURBS_RENDERER;
+ break;
+
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+extern "C" void GLAPIENTRY
+gluNurbsCallback(GLUnurbs *r, GLenum which, _GLUfuncptr fn )
+{
+ switch (which) {
+ case GLU_NURBS_BEGIN:
+ case GLU_NURBS_END:
+ case GLU_NURBS_VERTEX:
+ case GLU_NURBS_NORMAL:
+ case GLU_NURBS_TEXTURE_COORD:
+ case GLU_NURBS_COLOR:
+ case GLU_NURBS_BEGIN_DATA:
+ case GLU_NURBS_END_DATA:
+ case GLU_NURBS_VERTEX_DATA:
+ case GLU_NURBS_NORMAL_DATA:
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ case GLU_NURBS_COLOR_DATA:
+ r->putSurfCallBack(which, fn);
+ break;
+
+ case GLU_NURBS_ERROR:
+ r->errorCallback = (void (APIENTRY *)( GLenum e )) fn;
+ break;
+ default:
+ r->postError(GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+extern "C"
+void GLAPIENTRY
+gluNurbsCallbackDataEXT(GLUnurbs* r, void* userData)
+{
+ r->setNurbsCallbackData(userData);
+}
+
+extern "C"
+void GLAPIENTRY
+gluNurbsCallbackData(GLUnurbs* r, void* userData)
+{
+ gluNurbsCallbackDataEXT(r,userData);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.cc b/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.cc
new file mode 100644
index 000000000..17123fbc6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.cc
@@ -0,0 +1,301 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include "glimports.h"
+#include "glrenderer.h"
+
+GLUnurbs::GLUnurbs()
+ : NurbsTessellator(curveEvaluator, surfaceEvaluator)
+{
+ redefineMaps();
+ defineMap(GL_MAP2_NORMAL, 0, 3);
+ defineMap(GL_MAP1_NORMAL, 0, 3);
+ defineMap(GL_MAP2_TEXTURE_COORD_1, 0, 1);
+ defineMap(GL_MAP1_TEXTURE_COORD_1, 0, 1);
+ defineMap(GL_MAP2_TEXTURE_COORD_2, 0, 2);
+ defineMap(GL_MAP1_TEXTURE_COORD_2, 0, 2);
+ defineMap(GL_MAP2_TEXTURE_COORD_3, 0, 3);
+ defineMap(GL_MAP1_TEXTURE_COORD_3, 0, 3);
+ defineMap(GL_MAP2_TEXTURE_COORD_4, 1, 4);
+ defineMap(GL_MAP1_TEXTURE_COORD_4, 1, 4);
+ defineMap(GL_MAP2_VERTEX_4, 1, 4);
+ defineMap(GL_MAP1_VERTEX_4, 1, 4);
+ defineMap(GL_MAP2_VERTEX_3, 0, 3);
+ defineMap(GL_MAP1_VERTEX_3, 0, 3);
+ defineMap(GL_MAP2_COLOR_4, 0, 4);
+ defineMap(GL_MAP1_COLOR_4, 0, 4);
+ defineMap(GL_MAP2_INDEX, 0, 1);
+ defineMap(GL_MAP1_INDEX, 0, 1);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMETHOD, (float) N_PATHLENGTH);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, (float) 50.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_PIXEL_TOLERANCE, (float) 50.0);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, (float) 0.50);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_ERROR_TOLERANCE, (float) 0.50);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_S_STEPS, (float) 100.0);
+
+ //added for optimizing untrimmed case
+ set_domain_distance_u_rate(100.0);
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, (float) 100.0);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_T_STEPS, (float) 100.0);
+
+ //added for optimizing untrimmed case
+ set_domain_distance_v_rate(100.0);
+ set_is_domain_distance_sampling(0); //since the default is path_length
+
+ //default autoloadmode is true
+ autoloadmode = 1;
+
+ //default callbackFlag is 0
+ callbackFlag = 0;
+
+ errorCallback = NULL;
+}
+
+void
+GLUnurbs::bgnrender(void)
+{
+ if (autoloadmode) {
+ loadGLMatrices();
+ }
+}
+
+void
+GLUnurbs::endrender(void)
+{
+}
+
+void
+GLUnurbs::errorHandler(int i)
+{
+ int gluError;
+
+ gluError = i + (GLU_NURBS_ERROR1 - 1);
+ postError( gluError );
+}
+
+void
+GLUnurbs::loadGLMatrices(void)
+{
+ GLfloat vmat[4][4];
+ GLint viewport[4];
+
+ grabGLMatrix((GLfloat (*)[4]) vmat);
+ loadCullingMatrix((GLfloat (*)[4]) vmat);
+ ::glGetIntegerv((GLenum) GL_VIEWPORT, (GLint *) viewport);
+ loadSamplingMatrix((const GLfloat (*)[4]) vmat, (const GLint *) viewport);
+}
+
+void
+GLUnurbs::useGLMatrices(const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4])
+{
+ GLfloat vmat[4][4];
+
+ multmatrix4d(vmat, (const GLfloat (*)[4]) modelMatrix,
+ (const GLfloat (*)[4]) projMatrix);
+ loadCullingMatrix((GLfloat (*)[4]) vmat);
+ loadSamplingMatrix((const GLfloat (*)[4]) vmat, (const GLint *) viewport);
+}
+
+/*--------------------------------------------------------------------------
+ * grabGLMatrix
+ *--------------------------------------------------------------------------
+ */
+
+void
+GLUnurbs::grabGLMatrix(GLfloat vmat[4][4])
+{
+ GLfloat m1[4][4], m2[4][4];
+
+ ::glGetFloatv((GLenum) GL_MODELVIEW_MATRIX, (GLfloat *) &(m1[0][0]));
+ ::glGetFloatv((GLenum) GL_PROJECTION_MATRIX, (GLfloat *) &(m2[0][0]));
+ multmatrix4d((GLfloat (*)[4]) vmat,
+ (const GLfloat (*)[4]) m1, (const GLfloat (*)[4]) m2);
+}
+
+//for object space tesselation: view independent
+void
+GLUnurbs::setSamplingMatrixIdentity( void )
+{
+ INREAL smat[4][4] = {
+ {1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}
+ };
+ const long rstride = sizeof(smat[0]) / sizeof(smat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+}
+
+
+void
+GLUnurbs::loadSamplingMatrix(const GLfloat vmat[4][4],
+ const GLint viewport[4])
+{
+
+ /* rescale the mapping to correspond to pixels in x/y */
+ REAL xsize = 0.5 * (REAL) (viewport[2]);
+ REAL ysize = 0.5 * (REAL) (viewport[3]);
+
+ INREAL smat[4][4];
+ smat[0][0] = vmat[0][0] * xsize;
+ smat[1][0] = vmat[1][0] * xsize;
+ smat[2][0] = vmat[2][0] * xsize;
+ smat[3][0] = vmat[3][0] * xsize;
+
+ smat[0][1] = vmat[0][1] * ysize;
+ smat[1][1] = vmat[1][1] * ysize;
+ smat[2][1] = vmat[2][1] * ysize;
+ smat[3][1] = vmat[3][1] * ysize;
+
+ smat[0][2] = 0.0;
+ smat[1][2] = 0.0;
+ smat[2][2] = 0.0;
+ smat[3][2] = 0.0;
+
+ smat[0][3] = vmat[0][3];
+ smat[1][3] = vmat[1][3];
+ smat[2][3] = vmat[2][3];
+ smat[3][3] = vmat[3][3];
+
+ const long rstride = sizeof(smat[0]) / sizeof(smat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMATRIX, &smat[0][0], rstride,
+ cstride);
+}
+
+void
+GLUnurbs::loadCullingMatrix(GLfloat vmat[4][4])
+{
+ INREAL cmat[4][4];
+
+ cmat[0][0] = vmat[0][0];
+ cmat[0][1] = vmat[0][1];
+ cmat[0][2] = vmat[0][2];
+ cmat[0][3] = vmat[0][3];
+
+ cmat[1][0] = vmat[1][0];
+ cmat[1][1] = vmat[1][1];
+ cmat[1][2] = vmat[1][2];
+ cmat[1][3] = vmat[1][3];
+
+ cmat[2][0] = vmat[2][0];
+ cmat[2][1] = vmat[2][1];
+ cmat[2][2] = vmat[2][2];
+ cmat[2][3] = vmat[2][3];
+
+ cmat[3][0] = vmat[3][0];
+ cmat[3][1] = vmat[3][1];
+ cmat[3][2] = vmat[3][2];
+ cmat[3][3] = vmat[3][3];
+
+ const long rstride = sizeof(cmat[0]) / sizeof(cmat[0][0]);
+ const long cstride = 1;
+
+ setnurbsproperty(GL_MAP2_VERTEX_3, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP2_VERTEX_4, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ //added for curves by zl
+ setnurbsproperty(GL_MAP1_VERTEX_3, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+ setnurbsproperty(GL_MAP1_VERTEX_4, N_CULLINGMATRIX, &cmat[0][0], rstride,
+ cstride);
+}
+
+/*---------------------------------------------------------------------
+ * A = B * MAT ; transform a 4d vector through a 4x4 matrix
+ *---------------------------------------------------------------------
+ */
+void
+GLUnurbs::transform4d(GLfloat A[4], GLfloat B[4], GLfloat mat[4][4])
+{
+
+ A[0] = B[0]*mat[0][0] + B[1]*mat[1][0] + B[2]*mat[2][0] + B[3]*mat[3][0];
+ A[1] = B[0]*mat[0][1] + B[1]*mat[1][1] + B[2]*mat[2][1] + B[3]*mat[3][1];
+ A[2] = B[0]*mat[0][2] + B[1]*mat[1][2] + B[2]*mat[2][2] + B[3]*mat[3][2];
+ A[3] = B[0]*mat[0][3] + B[1]*mat[1][3] + B[2]*mat[2][3] + B[3]*mat[3][3];
+}
+
+/*---------------------------------------------------------------------
+ * new = [left][right] ; multiply two matrices together
+ *---------------------------------------------------------------------
+ */
+void
+GLUnurbs::multmatrix4d (GLfloat n[4][4], const GLfloat left[4][4],
+ const GLfloat right[4][4])
+{
+ transform4d ((GLfloat *) n[0],(GLfloat *) left[0],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[1],(GLfloat *) left[1],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[2],(GLfloat *) left[2],(GLfloat (*)[4]) right);
+ transform4d ((GLfloat *) n[3],(GLfloat *) left[3],(GLfloat (*)[4]) right);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.h b/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.h
new file mode 100644
index 000000000..3b72d44d1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glrenderer.h
@@ -0,0 +1,146 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glrenderer.h
+ *
+ */
+
+#ifndef __gluglrenderer_h_
+#define __gluglrenderer_h_
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "nurbstess.h"
+#include "glsurfeval.h"
+#include "glcurveval.h"
+
+extern "C" {
+ typedef void (APIENTRY *errorCallbackType)( GLenum );
+}
+
+class GLUnurbs : public NurbsTessellator {
+
+public:
+ GLUnurbs( void );
+ void loadGLMatrices( void );
+ void useGLMatrices( const GLfloat modelMatrix[16],
+ const GLfloat projMatrix[16],
+ const GLint viewport[4] );
+ void setSamplingMatrixIdentity( void );
+
+ void errorHandler( int );
+ void bgnrender( void );
+ void endrender( void );
+ void setautoloadmode( INREAL value )
+ {
+
+ if (value) autoloadmode = GL_TRUE;
+ else autoloadmode = GL_FALSE;
+
+ }
+ GLboolean getautoloadmode( void ) { return autoloadmode; }
+
+ errorCallbackType errorCallback;
+ void postError( int which )
+ { if (errorCallback) (errorCallback)( (GLenum)which ); }
+#ifdef _WIN32
+ void putSurfCallBack(GLenum which, void (GLAPIENTRY *fn)() )
+#else
+ void putSurfCallBack(GLenum which, _GLUfuncptr fn )
+#endif
+ {
+ curveEvaluator.putCallBack(which, fn);
+ surfaceEvaluator.putCallBack(which, fn);
+ }
+
+ int get_vertices_call_back()
+ {
+ return surfaceEvaluator.get_vertices_call_back();
+ }
+
+ void put_vertices_call_back(int flag)
+ {
+ surfaceEvaluator.put_vertices_call_back(flag);
+ }
+
+ int get_callback_auto_normal()
+ {
+ return surfaceEvaluator.get_callback_auto_normal();
+ }
+
+ void put_callback_auto_normal(int flag)
+ {
+ surfaceEvaluator.put_callback_auto_normal(flag);
+ }
+
+ void setNurbsCallbackData(void* userData)
+ {
+ curveEvaluator.set_callback_userData(userData);
+ surfaceEvaluator.set_callback_userData(userData);
+ }
+
+
+ //for LOD
+ void LOD_eval_list(int level)
+ {
+ surfaceEvaluator.LOD_eval_list(level);
+ }
+
+ //NEWCALLBACK
+ int is_callback()
+ {
+ return callbackFlag;
+ }
+ void put_callbackFlag(int flag)
+ {
+ callbackFlag = flag;
+ surfaceEvaluator.put_vertices_call_back(flag);
+ curveEvaluator.put_vertices_call_back(flag);
+ }
+
+private:
+ GLboolean autoloadmode;
+ OpenGLSurfaceEvaluator surfaceEvaluator;
+ OpenGLCurveEvaluator curveEvaluator;
+
+ void loadSamplingMatrix( const GLfloat vmat[4][4],
+ const GLint viewport[4] );
+ void loadCullingMatrix( GLfloat vmat[4][4] );
+ static void grabGLMatrix( GLfloat vmat[4][4] );
+ static void transform4d( GLfloat A[4], GLfloat B[4],
+ GLfloat mat[4][4] );
+ static void multmatrix4d( GLfloat n[4][4], const GLfloat left[4][4],
+ const GLfloat right[4][4] );
+
+ int callbackFlag;
+};
+
+#endif /* __gluglrenderer_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.cc b/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.cc
new file mode 100644
index 000000000..b5bfab1e2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.cc
@@ -0,0 +1,1293 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * glsurfeval.c++
+ *
+ */
+
+/* Polynomial Evaluator Interface */
+#include "gluos.h"
+#include <stdio.h>
+#include "glimports.h"
+#include "glrenderer.h"
+#include "glsurfeval.h"
+#include "nurbsconsts.h"
+#include "bezierPatchMesh.h"
+
+
+//extern int surfcount;
+//int surfcount=0;
+
+/*#define USE_INTERNAL_EVAL*/ //use internal evaluator
+
+/*whether do evaluation or not*/
+/*#define NO_EVALUATION*/
+
+//#define USE_LOD //for LOD test, have to turn on USE_LOD in insurfeval.c++ too
+
+/*for statistics*/
+//#define STATISTICS
+#ifdef STATISTICS
+static int STAT_num_of_triangles=0;
+static int STAT_num_of_eval_vertices=0;
+static int STAT_num_of_quad_strips=0;
+#endif
+
+/*for output triangles*/
+/*#define OUTPUT_TRIANGLES*/
+
+
+/*#define FOR_CHRIS*/
+#ifdef FOR_CHRIS
+extern "C" { void evalUStripExt(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val);}
+
+extern "C" { void evalVStripExt(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val);
+ }
+#endif
+
+
+/**************begin for LOD_eval_list***********/
+void OpenGLSurfaceEvaluator::LOD_eval_list(int level)
+{
+ if(level == 0)
+ LOD_eval_level = 1;
+ else if(level == 1)
+ LOD_eval_level = 2;
+ else if(level == 2)
+ LOD_eval_level = 4;
+ else
+ LOD_eval_level = 8;
+
+ inBPMListEvalEM(global_bpm);
+}
+
+
+OpenGLSurfaceEvaluator::OpenGLSurfaceEvaluator()
+{
+ int i;
+
+ for (i=0; i<VERTEX_CACHE_SIZE; i++) {
+ vertexCache[i] = new StoredVertex;
+ }
+ tmeshing = 0;
+ which = 0;
+ vcount = 0;
+
+ global_uorder = 0;
+ global_vorder = 0;
+ global_uprime = -1.0;
+ global_vprime = -1.0;
+ global_vprime_BV = -1.0;
+ global_uprime_BU = -1.0;
+ global_uorder_BU = 0;
+ global_vorder_BU = 0;
+ global_uorder_BV = 0;
+ global_vorder_BV = 0;
+ global_baseData = NULL;
+
+ global_bpm = NULL;
+ output_triangles = 0; //don't output triangles by default
+
+ //no default callback functions
+ beginCallBackN = NULL;
+ endCallBackN = NULL;
+ vertexCallBackN = NULL;
+ normalCallBackN = NULL;
+ colorCallBackN = NULL;
+ texcoordCallBackN = NULL;
+ beginCallBackData = NULL;
+ endCallBackData = NULL;
+ vertexCallBackData = NULL;
+ normalCallBackData = NULL;
+ colorCallBackData = NULL;
+ texcoordCallBackData = NULL;
+
+ userData = NULL;
+
+ auto_normal_flag = 0;
+ callback_auto_normal = 0; //default of GLU_CALLBACK_AUTO_NORMAL is 0
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ em_vertex.uprime = -1.0;
+ em_vertex.vprime = -1.0;
+ em_normal.uprime = -1.0;
+ em_normal.vprime = -1.0;
+ em_color.uprime = -1.0;
+ em_color.vprime = -1.0;
+ em_texcoord.uprime = -1.0;
+ em_texcoord.vprime = -1.0;
+
+#ifdef USE_LOD
+ LOD_eval_level = 1;
+#endif
+}
+
+OpenGLSurfaceEvaluator::~OpenGLSurfaceEvaluator()
+{
+ for (int ii= 0; ii< VERTEX_CACHE_SIZE; ii++) {
+ delete vertexCache[ii];
+ vertexCache[ii]= 0;
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * disable - turn off a map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::disable(long type)
+{
+ glDisable((GLenum) type);
+}
+
+/*---------------------------------------------------------------------------
+ * enable - turn on a map
+ *---------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::enable(long type)
+{
+ glEnable((GLenum) type);
+}
+
+/*-------------------------------------------------------------------------
+ * mapgrid2f - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::mapgrid2f(long nu, REAL u0, REAL u1, long nv, REAL v0, REAL v1)
+{
+#ifdef USE_INTERNAL_EVAL
+ inMapGrid2f((int) nu, (REAL) u0, (REAL) u1, (int) nv,
+ (REAL) v0, (REAL) v1);
+#else
+
+ if(output_triangles)
+ {
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = nu;
+ global_grid_v0 = v0;
+ global_grid_v1 = v1;
+ global_grid_nv = nv;
+ }
+ else
+ glMapGrid2d((GLint) nu, (GLdouble) u0, (GLdouble) u1, (GLint) nv,
+ (GLdouble) v0, (GLdouble) v1);
+
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::polymode(long style)
+{
+ if(! output_triangles)
+ {
+ switch(style) {
+ default:
+ case N_MESHFILL:
+
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_FILL);
+ break;
+ case N_MESHLINE:
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_LINE);
+ break;
+ case N_MESHPOINT:
+ glPolygonMode((GLenum) GL_FRONT_AND_BACK, (GLenum) GL_POINT);
+ break;
+ }
+ }
+}
+
+void
+OpenGLSurfaceEvaluator::bgnline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_LINE_STRIP);
+ else
+ glBegin((GLenum) GL_LINE_STRIP);
+}
+
+void
+OpenGLSurfaceEvaluator::endline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::range2f(long type, REAL *from, REAL *to)
+{
+}
+
+void
+OpenGLSurfaceEvaluator::domain2f(REAL ulo, REAL uhi, REAL vlo, REAL vhi)
+{
+}
+
+void
+OpenGLSurfaceEvaluator::bgnclosedline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_LINE_LOOP);
+ else
+ glBegin((GLenum) GL_LINE_LOOP);
+}
+
+void
+OpenGLSurfaceEvaluator::endclosedline(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+
+
+
+
+void
+OpenGLSurfaceEvaluator::bgntmesh(void)
+{
+
+ tmeshing = 1;
+ which = 0;
+ vcount = 0;
+
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLES);
+ else
+ glBegin((GLenum) GL_TRIANGLES);
+
+}
+
+void
+OpenGLSurfaceEvaluator::swaptmesh(void)
+{
+ which = 1 - which;
+
+}
+
+void
+OpenGLSurfaceEvaluator::endtmesh(void)
+{
+ tmeshing = 0;
+
+
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::bgntfan(void)
+{
+
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_TRIANGLE_FAN);
+ else
+ glBegin((GLenum) GL_TRIANGLE_FAN);
+
+}
+void
+OpenGLSurfaceEvaluator::endtfan(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+}
+
+void
+OpenGLSurfaceEvaluator::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
+{
+#ifdef USE_INTERNAL_EVAL
+ inEvalUStrip(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+#else
+
+#ifdef FOR_CHRIS
+ evalUStripExt(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+ return;
+
+#endif
+ int i,j,k,l;
+ REAL leftMostV[2];
+
+ /*
+ *the algorithm works by scanning from left to right.
+ *leftMostV: the left most of the remaining verteces (on both upper and lower).
+ * it could an element of upperVerts or lowerVerts.
+ *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line
+ *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line
+ */
+
+ /*initialize i,j,and leftMostV
+ */
+ if(upper_val[0] <= lower_val[0])
+ {
+ i=1;
+ j=0;
+
+ leftMostV[0] = upper_val[0];
+ leftMostV[1] = v_upper;
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ leftMostV[0] = lower_val[0];
+ leftMostV[1] = v_lower;
+
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and leftMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ bgntfan();
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ while(j<n_lower){
+ coord2f(lower_val[j], v_lower);
+// glNormal3fv(lowerNormal[j]);
+// glVertex3fv(lowerXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ bgntfan();
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ coord2f(upper_val[k], v_upper);
+// glNormal3fv(upperNormal[k]);
+// glVertex3fv(upperXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+ if(upper_val[i] <= lower_val[j])
+ {
+ bgntfan();
+ coord2f(lower_val[j], v_lower);
+// glNormal3fv(lowerNormal[j]);
+// glVertex3fv(lowerXYZ[j]);
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+
+ while(k<n_upper)
+ {
+ if(upper_val[k] > lower_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ coord2f(upper_val[l], v_upper);
+// glNormal3fv(upperNormal[l]);
+// glVertex3fv(upperXYZ[l]);
+
+ }
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+ endtfan();
+
+ /*update i and leftMostV for next loop
+ */
+ i = k+1;
+
+ leftMostV[0] = upper_val[k];
+ leftMostV[1] = v_upper;
+// leftMostNormal = upperNormal[k];
+// leftMostXYZ = upperXYZ[k];
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ bgntfan();
+ coord2f(upper_val[i], v_upper);
+// glNormal3fv(upperNormal[i]);
+// glVertex3fv(upperXYZ[i]);
+
+ coord2f(leftMostV[0], leftMostV[1]);
+// glNormal3fv(leftMostNormal);
+// glVertex3fv(leftMostXYZ);
+
+
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]
+ */
+ k=j;
+ while(k< n_lower)
+ {
+ if(lower_val[k] >= upper_val[i])
+ break;
+ coord2f(lower_val[k], v_lower);
+// glNormal3fv(lowerNormal[k]);
+// glVertex3fv(lowerXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and leftMostV for next loop
+ */
+ j=k;
+ leftMostV[0] = lower_val[j-1];
+ leftMostV[1] = v_lower;
+
+// leftMostNormal = lowerNormal[j-1];
+// leftMostXYZ = lowerXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+// free(upperXYZ);
+// free(lowerXYZ);
+// free(upperNormal);
+// free(lowerNormal);
+#endif
+
+}
+
+
+void
+OpenGLSurfaceEvaluator::evalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
+{
+#ifdef USE_INTERNAL_EVAL
+ inEvalVStrip(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+#else
+
+#ifdef FOR_CHRIS
+ evalVStripExt(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+ return;
+
+#endif
+
+ int i,j,k,l;
+ REAL botMostV[2];
+ /*
+ *the algorithm works by scanning from bot to top.
+ *botMostV: the bot most of the remaining verteces (on both left and right).
+ * it could an element of leftVerts or rightVerts.
+ *i: leftVerts[i] is the first vertex to the top of botMostV on left line
+ *j: rightVerts[j] is the first vertex to the top of botMostV on rightline
+ */
+
+ /*initialize i,j,and botMostV
+ */
+ if(left_val[0] <= right_val[0])
+ {
+ i=1;
+ j=0;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and botMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ bgntfan();
+ coord2f(botMostV[0], botMostV[1]);
+ while(j<n_right){
+ coord2f(u_right, right_val[j]);
+// glNormal3fv(rightNormal[j]);
+// glVertex3fv(rightXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ bgntfan();
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+ for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ coord2f(u_left, left_val[k]);
+// glNormal3fv(leftNormal[k]);
+// glVertex3fv(leftXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
+ {
+ if(left_val[i] <= right_val[j])
+ {
+ bgntfan();
+ coord2f(u_right, right_val[j]);
+// glNormal3fv(rightNormal[j]);
+// glVertex3fv(rightXYZ[j]);
+
+ /*find the last k>=i such that
+ *leftverts[k][0] <= rightverts[j][0]
+ */
+ k=i;
+
+ while(k<n_left)
+ {
+ if(left_val[k] > right_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ coord2f(u_left, left_val[l]);
+// glNormal3fv(leftNormal[l]);
+// glVertex3fv(leftXYZ[l]);
+
+ }
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+ endtfan();
+
+ /*update i and botMostV for next loop
+ */
+ i = k+1;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[k];
+// botMostNormal = leftNormal[k];
+// botMostXYZ = leftXYZ[k];
+ }
+ else /*left_val[i] > right_val[j])*/
+ {
+ bgntfan();
+ coord2f(u_left, left_val[i]);
+// glNormal3fv(leftNormal[i]);
+// glVertex3fv(leftXYZ[i]);
+
+ coord2f(botMostV[0], botMostV[1]);
+// glNormal3fv(botMostNormal);
+// glVertex3fv(botMostXYZ);
+
+
+ /*find the last k>=j such that
+ *rightverts[k][0] < leftverts[i][0]
+ */
+ k=j;
+ while(k< n_right)
+ {
+ if(right_val[k] >= left_val[i])
+ break;
+ coord2f(u_right, right_val[k]);
+// glNormal3fv(rightNormal[k]);
+// glVertex3fv(rightXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and botMostV for next loop
+ */
+ j=k;
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[j-1];
+
+// botMostNormal = rightNormal[j-1];
+// botMostXYZ = rightXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+// free(leftXYZ);
+// free(leftNormal);
+// free(rightXYZ);
+// free(rightNormal);
+#endif
+}
+
+
+void
+OpenGLSurfaceEvaluator::bgnqstrip(void)
+{
+ if(output_triangles)
+ bezierPatchMeshBeginStrip(global_bpm, GL_QUAD_STRIP);
+ else
+ glBegin((GLenum) GL_QUAD_STRIP);
+
+#ifdef STATISTICS
+ STAT_num_of_quad_strips++;
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::endqstrip(void)
+{
+ if(output_triangles)
+ bezierPatchMeshEndStrip(global_bpm);
+ else
+ glEnd();
+
+}
+
+/*-------------------------------------------------------------------------
+ * bgnmap2f - preamble to surface definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::bgnmap2f(long)
+{
+ if(output_triangles)
+ {
+ /*deallocate the space which may has been
+ *allocated by global_bpm previously
+ */
+ if(global_bpm != NULL) {
+ bezierPatchMeshListDelete(global_bpm);
+ global_bpm = NULL;
+ }
+
+
+ /*
+ auto_normal_flag = 1; //always output normal in callback mode.
+ //we could have used the following code,
+ //but Inspector doesn't have gl context
+ //before it calls tessellator.
+ //this way is temporary.
+ */
+ //NEWCALLBACK
+ //if one of the two normal callback functions are set,
+ //then set
+ if(normalCallBackN != NULL ||
+ normalCallBackData != NULL)
+ auto_normal_flag = 1;
+ else
+ auto_normal_flag = 0;
+
+ //initialize so that no maps initially
+ vertex_flag = 0;
+ normal_flag = 0;
+ color_flag = 0;
+ texcoord_flag = 0;
+
+ /*
+ if(glIsEnabled(GL_AUTO_NORMAL) == GL_TRUE)
+ auto_normal_flag = 1;
+ else if (callback_auto_normal == 1)
+ auto_normal_flag = 1;
+ else
+ auto_normal_flag = 0;
+ */
+ glPushAttrib((GLbitfield) GL_EVAL_BIT);
+
+ }
+ else
+ {
+ glPushAttrib((GLbitfield) GL_EVAL_BIT);
+
+ /*to avoid side effect, we restor the opengl state for GL_POLYGON_MODE
+ */
+ glGetIntegerv(GL_POLYGON_MODE, gl_polygon_mode);
+ }
+
+}
+
+/*-------------------------------------------------------------------------
+ * endmap2f - postamble to a map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::endmap2f(void)
+{
+
+ if(output_triangles)
+ {
+ //bezierPatchMeshListDelDeg(global_bpm);
+
+ // bezierPatchMeshListEval(global_bpm);
+
+ //surfcount++;
+ //printf("surfcount=%i\n", surfcount);
+ //if(surfcount == 8) exit(0);
+
+ inBPMListEvalEM(global_bpm);
+
+
+
+/*
+ global_bpm = bezierPatchMeshListReverse(global_bpm);
+ {
+ float *vertex_array;
+ float *normal_array;
+ int *length_array;
+ int *type_array;
+ int num_strips;
+ bezierPatchMeshListCollect(global_bpm, &vertex_array, &normal_array, &length_array, &type_array, &num_strips);
+ drawStrips(vertex_array, normal_array, length_array, type_array, num_strips);
+ free(vertex_array);
+ free(normal_array);
+ free(length_array);
+ free(type_array);
+ }
+*/
+
+ //bezierPatchMeshListPrint(global_bpm);
+ //bezierPatchMeshListDraw(global_bpm);
+
+// printf("num triangles=%i\n", bezierPatchMeshListNumTriangles(global_bpm));
+
+#ifdef USE_LOD
+#else
+ bezierPatchMeshListDelete(global_bpm);
+ global_bpm = NULL;
+#endif
+ glPopAttrib();
+ }
+else
+ {
+#ifndef USE_LOD
+ glPopAttrib();
+#endif
+
+#ifdef STATISTICS
+ fprintf(stderr, "num_vertices=%i,num_triangles=%i,num_quads_strips=%i\n", STAT_num_of_eval_vertices,STAT_num_of_triangles,STAT_num_of_quad_strips);
+#endif
+
+ /*to restore the gl_polygon_mode
+ */
+#ifndef USE_LOD
+ glPolygonMode( GL_FRONT, (GLenum) gl_polygon_mode[0]);
+ glPolygonMode( GL_BACK, (GLenum) gl_polygon_mode[1]);
+#endif
+}
+
+}
+
+/*-------------------------------------------------------------------------
+ * map2f - pass a desription of a surface map
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::map2f(
+ long _type,
+ REAL _ulower, /* u lower domain coord */
+ REAL _uupper, /* u upper domain coord */
+ long _ustride, /* interpoint distance */
+ long _uorder, /* parametric order */
+ REAL _vlower, /* v lower domain coord */
+ REAL _vupper, /* v upper domain coord */
+ long _vstride, /* interpoint distance */
+ long _vorder, /* parametric order */
+ REAL *pts) /* control points */
+{
+#ifdef USE_INTERNAL_EVAL
+ inMap2f((int) _type, (REAL) _ulower, (REAL) _uupper,
+ (int) _ustride, (int) _uorder, (REAL) _vlower,
+ (REAL) _vupper, (int) _vstride, (int) _vorder,
+ (REAL *) pts);
+#else
+
+
+
+ if(output_triangles)
+ {
+ if(global_bpm == NULL)
+ global_bpm = bezierPatchMeshMake2(10,10);
+ if(
+ (global_bpm->bpatch == NULL &&
+ (_type == GL_MAP2_VERTEX_3 || _type == GL_MAP2_VERTEX_4))
+ ||
+ (global_bpm->bpatch_normal == NULL &&
+ (_type == GL_MAP2_NORMAL))
+ ||
+ (global_bpm->bpatch_color == NULL &&
+ (_type == GL_MAP2_INDEX || _type == GL_MAP2_COLOR_4))
+ ||
+ (global_bpm->bpatch_texcoord == NULL &&
+ (_type == GL_MAP2_TEXTURE_COORD_1 ||
+ _type == GL_MAP2_TEXTURE_COORD_2 ||
+ _type == GL_MAP2_TEXTURE_COORD_3 ||
+ _type == GL_MAP2_TEXTURE_COORD_4 )
+ ))
+ {
+ bezierPatchMeshPutPatch(global_bpm, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
+ }
+ else /*new surface patch (with multiple maps) starts*/
+ {
+ bezierPatchMesh *temp = bezierPatchMeshMake2(10,10);
+ bezierPatchMeshPutPatch(temp, (int) _type, _ulower, _uupper,(int) _ustride,(int) _uorder,_vlower, _vupper, (int) _vstride, (int) _vorder, pts);
+ global_bpm = bezierPatchMeshListInsert(global_bpm, temp);
+
+ /*
+ global_bpm = bezierPatchMeshListInsert(global_bpm,
+ bezierPatchMeshMake(
+ (int) _type, _ulower, _uupper,(int) _ustride, (int) _uorder, _vlower, _vupper, (int) _vstride, (int) _vorder, pts, 10, 10));
+ */
+ }
+ }
+ else /*not output triangles*/
+ {
+ glMap2f((GLenum) _type, (GLfloat) _ulower, (GLfloat) _uupper,
+ (GLint) _ustride, (GLint) _uorder, (GLfloat) _vlower,
+ (GLfloat) _vupper, (GLint) _vstride, (GLint) _vorder,
+ (const GLfloat *) pts);
+ }
+
+#endif
+}
+
+
+/*-------------------------------------------------------------------------
+ * mapmesh2f - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::mapmesh2f(long style, long umin, long umax, long vmin, long vmax)
+{
+#ifdef NO_EVALUATION
+return;
+#endif
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalMesh2((int)umin, (int)vmin, (int)umax, (int)vmax);
+#else
+
+
+
+if(output_triangles)
+{
+#ifdef USE_LOD
+ bezierPatchMeshBeginStrip(global_bpm, GL_POLYGON);
+ bezierPatchMeshInsertUV(global_bpm, global_grid_u0, global_grid_v0);
+ bezierPatchMeshInsertUV(global_bpm, global_grid_u1, global_grid_v1);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)global_grid_nu, (REAL)global_grid_nv);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)umin, (REAL)vmin);
+ bezierPatchMeshInsertUV(global_bpm, (REAL)umax, (REAL)vmax);
+ bezierPatchMeshEndStrip(global_bpm);
+
+#else
+
+ REAL du, dv;
+ long i,j;
+ if(global_grid_nu == 0 || global_grid_nv == 0)
+ return; /*no points need to be output*/
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+
+ if(global_grid_nu >= global_grid_nv){
+
+ for(i=umin; i<umax; i++){
+ REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
+
+ bgnqstrip();
+ for(j=vmax; j>=vmin; j--){
+ REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+
+ coord2f(u1, v1);
+ coord2f(u2, v1);
+ }
+ endqstrip();
+ }
+ }
+ else{
+
+ for(i=vmin; i<vmax; i++){
+ REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
+ REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
+
+ bgnqstrip();
+ for(j=umax; j>=umin; j--){
+ REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
+ coord2f(u1, v2);
+ coord2f(u1, v1);
+ }
+ endqstrip();
+ }
+ }
+#endif
+}
+else
+{
+ switch(style) {
+ default:
+ case N_MESHFILL:
+ glEvalMesh2((GLenum) GL_FILL, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ case N_MESHLINE:
+ glEvalMesh2((GLenum) GL_LINE, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ case N_MESHPOINT:
+ glEvalMesh2((GLenum) GL_POINT, (GLint) umin, (GLint) umax,
+ (GLint) vmin, (GLint) vmax);
+ break;
+ }
+ }
+
+#endif
+
+#ifdef STATISTICS
+ STAT_num_of_quad_strips += (umax-umin)*(vmax-vmin);
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * evalcoord2f - evaluate a point on a surface
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::evalcoord2f(long, REAL u, REAL v)
+{
+
+
+#ifdef NO_EVALUATION
+return;
+#endif
+
+
+ newtmeshvert(u, v);
+}
+
+/*-------------------------------------------------------------------------
+ * evalpoint2i - evaluate a grid point
+ *-------------------------------------------------------------------------
+ */
+void
+OpenGLSurfaceEvaluator::evalpoint2i(long u, long v)
+{
+#ifdef NO_EVALUATION
+return;
+#endif
+
+ newtmeshvert(u, v);
+}
+
+void
+OpenGLSurfaceEvaluator::point2i( long u, long v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalPoint2( (int)u, (int)v);
+#else
+
+
+if(output_triangles)
+{
+
+ REAL du, dv;
+ REAL fu,fv;
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+ fu = (u==global_grid_nu)? global_grid_u1:(global_grid_u0 + u*du);
+ fv = (v == global_grid_nv)? global_grid_v1: (global_grid_v0 +v*dv);
+ coord2f(fu,fv);
+}
+else
+ glEvalPoint2((GLint) u, (GLint) v);
+
+
+#endif
+
+#ifdef STATISTICS
+ STAT_num_of_eval_vertices++;
+#endif
+
+#endif
+
+}
+
+void
+OpenGLSurfaceEvaluator::coord2f( REAL u, REAL v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+#ifdef USE_INTERNAL_EVAL
+ inEvalCoord2f( u, v);
+#else
+
+
+if(output_triangles)
+ bezierPatchMeshInsertUV(global_bpm, u,v);
+else
+ glEvalCoord2f((GLfloat) u, (GLfloat) v);
+
+
+#endif
+
+
+#ifdef STATISTICS
+ STAT_num_of_eval_vertices++;
+#endif
+
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::newtmeshvert( long u, long v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+
+ if (tmeshing) {
+
+ if (vcount == 2) {
+ vertexCache[0]->invoke(this);
+ vertexCache[1]->invoke(this);
+ point2i( u, v);
+
+ } else {
+ vcount++;
+ }
+
+ vertexCache[which]->saveEvalPoint(u, v);
+ which = 1 - which;
+ } else {
+ point2i( u, v);
+ }
+#endif
+}
+
+void
+OpenGLSurfaceEvaluator::newtmeshvert( REAL u, REAL v )
+{
+#ifdef NO_EVALUATION
+return;
+#else
+ if (tmeshing) {
+
+
+ if (vcount == 2) {
+ vertexCache[0]->invoke(this);
+ vertexCache[1]->invoke(this);
+ coord2f(u,v);
+
+ } else {
+ vcount++;
+ }
+
+ vertexCache[which]->saveEvalCoord(u, v);
+ which = 1 - which;
+ } else {
+
+ coord2f( u, v);
+ }
+#endif
+
+}
+
+#ifdef _WIN32
+void OpenGLSurfaceEvaluator::putCallBack(GLenum which, void (GLAPIENTRY *fn)() )
+#else
+void OpenGLSurfaceEvaluator::putCallBack(GLenum which, _GLUfuncptr fn )
+#endif
+{
+ switch(which)
+ {
+ case GLU_NURBS_BEGIN:
+ beginCallBackN = (void (GLAPIENTRY *) (GLenum)) fn;
+ break;
+ case GLU_NURBS_END:
+ endCallBackN = (void (GLAPIENTRY *) (void)) fn;
+ break;
+ case GLU_NURBS_VERTEX:
+ vertexCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_NORMAL:
+ normalCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_COLOR:
+ colorCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD:
+ texcoordCallBackN = (void (GLAPIENTRY *) (const GLfloat*)) fn;
+ break;
+ case GLU_NURBS_BEGIN_DATA:
+ beginCallBackData = (void (GLAPIENTRY *) (GLenum, void*)) fn;
+ break;
+ case GLU_NURBS_END_DATA:
+ endCallBackData = (void (GLAPIENTRY *) (void*)) fn;
+ break;
+ case GLU_NURBS_VERTEX_DATA:
+ vertexCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_NORMAL_DATA:
+ normalCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_COLOR_DATA:
+ colorCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+ case GLU_NURBS_TEXTURE_COORD_DATA:
+ texcoordCallBackData = (void (GLAPIENTRY *) (const GLfloat*, void*)) fn;
+ break;
+
+ }
+}
+
+
+void
+OpenGLSurfaceEvaluator::beginCallBack(GLenum which, void *data)
+{
+ if(beginCallBackData)
+ beginCallBackData(which, data);
+ else if(beginCallBackN)
+ beginCallBackN(which);
+}
+
+void
+OpenGLSurfaceEvaluator::endCallBack(void *data)
+{
+ if(endCallBackData)
+ endCallBackData(data);
+ else if(endCallBackN)
+ endCallBackN();
+}
+
+void
+OpenGLSurfaceEvaluator::vertexCallBack(const GLfloat *vert, void* data)
+{
+ if(vertexCallBackData)
+ vertexCallBackData(vert, data);
+ else if(vertexCallBackN)
+ vertexCallBackN(vert);
+}
+
+
+void
+OpenGLSurfaceEvaluator::normalCallBack(const GLfloat *normal, void* data)
+{
+ if(normalCallBackData)
+ normalCallBackData(normal, data);
+ else if(normalCallBackN)
+ normalCallBackN(normal);
+}
+
+void
+OpenGLSurfaceEvaluator::colorCallBack(const GLfloat *color, void* data)
+{
+ if(colorCallBackData)
+ colorCallBackData(color, data);
+ else if(colorCallBackN)
+ colorCallBackN(color);
+}
+
+void
+OpenGLSurfaceEvaluator::texcoordCallBack(const GLfloat *texcoord, void* data)
+{
+ if(texcoordCallBackData)
+ texcoordCallBackData(texcoord, data);
+ else if(texcoordCallBackN)
+ texcoordCallBackN(texcoord);
+}
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.h b/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.h
new file mode 100644
index 000000000..1567c6b09
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/glsurfeval.h
@@ -0,0 +1,404 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glsurfeval.h
+ *
+ */
+
+#ifndef __gluglsurfeval_h_
+#define __gluglsurfeval_h_
+
+#include "basicsurfeval.h"
+#include "bezierPatchMesh.h" //in case output triangles
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+class SurfaceMap;
+class OpenGLSurfaceEvaluator;
+class StoredVertex;
+
+#define TYPECOORD 1
+#define TYPEPOINT 2
+
+/* Cache up to 3 vertices from tmeshes */
+#define VERTEX_CACHE_SIZE 3
+
+/*for internal evaluator callback stuff*/
+#ifndef IN_MAX_BEZIER_ORDER
+#define IN_MAX_BEZIER_ORDER 40 /*XXX should be bigger than machine order*/
+#endif
+
+#ifndef IN_MAX_DIMENSION
+#define IN_MAX_DIMENSION 4
+#endif
+
+typedef struct surfEvalMachine{
+ REAL uprime;//cached previusly evaluated uprime.
+ REAL vprime;
+ int k; /*the dimension*/
+ REAL u1;
+ REAL u2;
+ int ustride;
+ int uorder;
+ REAL v1;
+ REAL v2;
+ int vstride;
+ int vorder;
+ REAL ctlPoints[IN_MAX_BEZIER_ORDER*IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+ REAL ucoeff[IN_MAX_BEZIER_ORDER]; /*cache the polynomial values*/
+ REAL vcoeff[IN_MAX_BEZIER_ORDER];
+ REAL ucoeffDeriv[IN_MAX_BEZIER_ORDER]; /*cache the polynomial derivatives*/
+ REAL vcoeffDeriv[IN_MAX_BEZIER_ORDER];
+} surfEvalMachine;
+
+
+
+class StoredVertex {
+public:
+ StoredVertex() { type = 0; }
+ ~StoredVertex(void) {}
+ void saveEvalCoord(REAL x, REAL y)
+ {coord[0] = x; coord[1] = y; type = TYPECOORD; }
+ void saveEvalPoint(long x, long y)
+ {point[0] = x; point[1] = y; type = TYPEPOINT; }
+ void invoke(OpenGLSurfaceEvaluator *eval);
+
+private:
+ int type;
+ REAL coord[2];
+ long point[2];
+};
+
+class OpenGLSurfaceEvaluator : public BasicSurfaceEvaluator {
+public:
+ OpenGLSurfaceEvaluator();
+ virtual ~OpenGLSurfaceEvaluator( void );
+ void polymode( long style );
+ void range2f( long, REAL *, REAL * );
+ void domain2f( REAL, REAL, REAL, REAL );
+ void addMap( SurfaceMap * ) { }
+
+ void enable( long );
+ void disable( long );
+ void bgnmap2f( long );
+ void map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long, REAL * );
+ void mapgrid2f( long, REAL, REAL, long, REAL, REAL );
+ void mapmesh2f( long, long, long, long, long );
+ void evalcoord2f( long, REAL, REAL );
+ void evalpoint2i( long, long );
+ void endmap2f( void );
+
+ void bgnline( void );
+ void endline( void );
+ void bgnclosedline( void );
+ void endclosedline( void );
+ void bgntmesh( void );
+ void swaptmesh( void );
+ void endtmesh( void );
+ void bgnqstrip( void );
+ void endqstrip( void );
+
+ void bgntfan( void );
+ void endtfan( void );
+ void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val);
+ void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val);
+
+ void coord2f( REAL, REAL );
+ void point2i( long, long );
+
+ void newtmeshvert( REAL, REAL );
+ void newtmeshvert( long, long );
+
+#ifdef _WIN32
+ void putCallBack(GLenum which, void (GLAPIENTRY *fn)() );
+#else
+ void putCallBack(GLenum which, _GLUfuncptr fn );
+#endif
+
+ int get_vertices_call_back()
+ {
+ return output_triangles;
+ }
+ void put_vertices_call_back(int flag)
+ {
+ output_triangles = flag;
+ }
+
+ void put_callback_auto_normal(int flag)
+ {
+ callback_auto_normal = flag;
+ }
+
+ int get_callback_auto_normal()
+ {
+ return callback_auto_normal;
+ }
+
+ void set_callback_userData(void* data)
+ {
+ userData = data;
+ }
+
+ /**************begin for LOD_eval_list***********/
+ void LOD_eval_list(int level);
+
+
+
+
+private:
+ StoredVertex *vertexCache[VERTEX_CACHE_SIZE];
+ int tmeshing;
+ int which;
+ int vcount;
+
+ GLint gl_polygon_mode[2];/*to save and restore so that
+ *no side effect
+ */
+ bezierPatchMesh *global_bpm; //for output triangles
+ int output_triangles; //true 1 or false 0
+
+
+
+ void (GLAPIENTRY *beginCallBackN) (GLenum type);
+ void (GLAPIENTRY *endCallBackN) (void);
+ void (GLAPIENTRY *vertexCallBackN) (const GLfloat *vert);
+ void (GLAPIENTRY *normalCallBackN) (const GLfloat *normal);
+ void (GLAPIENTRY *colorCallBackN) (const GLfloat *color);
+ void (GLAPIENTRY *texcoordCallBackN) (const GLfloat *texcoord);
+
+ void (GLAPIENTRY *beginCallBackData) (GLenum type, void* data);
+ void (GLAPIENTRY *endCallBackData) (void* data);
+ void (GLAPIENTRY *vertexCallBackData) (const GLfloat *vert, void* data);
+ void (GLAPIENTRY *normalCallBackData) (const GLfloat *normal, void* data);
+ void (GLAPIENTRY *colorCallBackData) (const GLfloat *color, void* data);
+ void (GLAPIENTRY *texcoordCallBackData) (const GLfloat *texcoord, void* data);
+
+ void beginCallBack (GLenum type, void* data);
+ void endCallBack (void* data);
+ void vertexCallBack (const GLfloat *vert, void* data);
+ void normalCallBack (const GLfloat *normal, void* data);
+ void colorCallBack (const GLfloat *color, void* data);
+ void texcoordCallBack (const GLfloat *texcoord, void* data);
+
+
+ void* userData; //the opaque pointer for Data callback functions.
+
+ /*LOD evaluation*/
+ void LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
+ int level);
+ void LOD_eval(int num_vert, REAL* verts, int type, int level);
+
+ int LOD_eval_level; //set by LOD_eval_list()
+
+ /*************begin for internal evaluators*****************/
+
+ /*the following global variables are only defined in this file.
+ *They are used to cache the precomputed Bezier polynomial values.
+ *These calues may be used consecutively in which case we don't have
+ *recompute these values again.
+ */
+ int global_uorder; /*store the uorder in the previous evaluation*/
+ int global_vorder; /*store the vorder in the previous evaluation*/
+ REAL global_uprime;
+ REAL global_vprime;
+ REAL global_vprime_BV;
+ REAL global_uprime_BU;
+ int global_uorder_BV; /*store the uorder in the previous evaluation*/
+ int global_vorder_BV; /*store the vorder in the previous evaluation*/
+ int global_uorder_BU; /*store the uorder in the previous evaluation*/
+ int global_vorder_BU; /*store the vorder in the previous evaluation*/
+
+ REAL global_ucoeff[IN_MAX_BEZIER_ORDER]; /*cache the polynomial values*/
+ REAL global_vcoeff[IN_MAX_BEZIER_ORDER];
+ REAL global_ucoeffDeriv[IN_MAX_BEZIER_ORDER]; /*cache the polynomial derivatives*/
+ REAL global_vcoeffDeriv[IN_MAX_BEZIER_ORDER];
+
+ REAL global_BV[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_PBV[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_BU[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL global_PBU[IN_MAX_BEZIER_ORDER][IN_MAX_DIMENSION];
+ REAL* global_baseData;
+
+ int global_ev_k; /*the dimension*/
+ REAL global_ev_u1;
+ REAL global_ev_u2;
+ int global_ev_ustride;
+ int global_ev_uorder;
+ REAL global_ev_v1;
+ REAL global_ev_v2;
+ int global_ev_vstride;
+ int global_ev_vorder;
+ REAL global_ev_ctlPoints[IN_MAX_BEZIER_ORDER*IN_MAX_BEZIER_ORDER*IN_MAX_DIMENSION];
+
+ REAL global_grid_u0;
+ REAL global_grid_u1;
+ int global_grid_nu;
+ REAL global_grid_v0;
+ REAL global_grid_v1;
+ int global_grid_nv;
+
+/*functions*/
+ void inDoDomain2WithDerivs(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL *retdu, REAL *retdv);
+ void inPreEvaluate(int order, REAL vprime, REAL *coeff);
+ void inPreEvaluateWithDeriv(int order, REAL vprime, REAL *coeff, REAL *coeffDeriv);
+ void inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv);
+ void inComputeNormal2(REAL *pu, REAL *pv, REAL *n);
+ void inDoEvalCoord2(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+ void inDoEvalCoord2NOGE(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+ void inMap2f(int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints);
+
+ void inMapGrid2f(int nu, REAL u0, REAL u1,
+ int nv, REAL v0, REAL v1);
+
+ void inEvalMesh2(int lowU, int lowV, int highU, int highV);
+ void inEvalPoint2(int i, int j);
+ void inEvalCoord2f(REAL u, REAL v);
+
+void inEvalULine(int n_points, REAL v, REAL* u_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3]);
+
+void inEvalVLine(int n_points, REAL u, REAL* v_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3]);
+
+void inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ );
+void inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val);
+
+void inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData);
+void inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData);
+void inPreEvaluateBV_intfac(REAL v )
+ {
+ inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
+ }
+
+void inPreEvaluateBU_intfac(REAL u)
+ {
+ inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
+ }
+
+void inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv);
+
+void inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv);
+
+
+void inDoEvalCoord2NOGE_BV(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+
+void inDoEvalCoord2NOGE_BU(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal);
+
+void inBPMEval(bezierPatchMesh* bpm);
+void inBPMListEval(bezierPatchMesh* list);
+
+/*-------------begin for surfEvalMachine -------------*/
+surfEvalMachine em_vertex;
+surfEvalMachine em_normal;
+surfEvalMachine em_color;
+surfEvalMachine em_texcoord;
+
+int auto_normal_flag; //whether to output normla or not in callback
+ //determined by GL_AUTO_NORMAL and callback_auto_normal
+int callback_auto_normal; //GLU_CALLBACK_AUTO_NORMAL_EXT
+int vertex_flag;
+int normal_flag;
+int color_flag;
+int texcoord_flag;
+
+void inMap2fEM(int which, //0:vert,1:norm,2:color,3:tex
+ int dimension,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints);
+
+void inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint, REAL *retdu, REAL *retdv);
+void inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint);
+ void inDoEvalCoord2EM(REAL u, REAL v);
+
+void inBPMEvalEM(bezierPatchMesh* bpm);
+void inBPMListEvalEM(bezierPatchMesh* list);
+
+/*-------------end for surfEvalMachine -------------*/
+
+
+ /*************end for internal evaluators*****************/
+
+};
+
+inline void StoredVertex::invoke(OpenGLSurfaceEvaluator *eval)
+{
+ switch(type) {
+ case TYPECOORD:
+ eval->coord2f(coord[0], coord[1]);
+ break;
+ case TYPEPOINT:
+ eval->point2i(point[0], point[1]);
+ break;
+ default:
+ break;
+ }
+}
+
+#endif /* __gluglsurfeval_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/incurveeval.cc b/mesalib/src/glu/sgi/libnurbs/interface/incurveeval.cc
new file mode 100644
index 000000000..96ea8896a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/incurveeval.cc
@@ -0,0 +1,206 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glcurveval.h"
+
+
+/*
+ *compute the Bezier polynomials C[n,j](v) for all j at v with
+ *return values stored in coeff[], where
+ * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
+ * j=0,1,2,...,n.
+ *order : n+1
+ *vprime: v
+ *coeff : coeff[j]=C[n,j](v), this array store the returned values.
+ *The algorithm is a recursive scheme:
+ * C[0,0]=1;
+ * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluate
+ */
+void OpenGLCurveEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ return;
+ }
+
+ oneMinusvprime = 1-vprime;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ if (order == 2) return;
+
+ for (i = 2; i < order; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+}
+
+void OpenGLCurveEvaluator::inMap1f(int which, //0: vert, 1: norm, 2: color, 3: tex
+ int k, //dimension
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL *ctlpoints)
+{
+ int i,x;
+ curveEvalMachine *temp_em;
+ switch(which){
+ case 0: //vertex
+ vertex_flag = 1;
+ temp_em = &em_vertex;
+ break;
+ case 1: //normal
+ normal_flag = 1;
+ temp_em = &em_normal;
+ break;
+ case 2: //color
+ color_flag = 1;
+ temp_em = &em_color;
+ break;
+ default:
+ texcoord_flag = 1;
+ temp_em = &em_texcoord;
+ break;
+ }
+
+ REAL *data = temp_em->ctlpoints;
+ temp_em->uprime = -1; //initialized
+ temp_em->k = k;
+ temp_em->u1 = ulower;
+ temp_em->u2 = uupper;
+ temp_em->ustride = ustride;
+ temp_em->uorder = uorder;
+ /*copy the control points*/
+ for(i=0; i<uorder; i++){
+ for(x=0; x<k; x++){
+ data[x] = ctlpoints[x];
+ }
+ ctlpoints += ustride;
+ data += k;
+ }
+}
+
+void OpenGLCurveEvaluator::inDoDomain1(curveEvalMachine *em, REAL u, REAL *retPoint)
+{
+ int j, row;
+ REAL the_uprime;
+ REAL *data;
+
+ if(em->u2 == em->u1)
+ return;
+ the_uprime = (u-em->u1) / (em->u2-em->u1);
+ /*use already cached values if possible*/
+ if(em->uprime != the_uprime){
+ inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
+ em->uprime = the_uprime;
+ }
+
+ for(j=0; j<em->k; j++){
+ data = em->ctlpoints+j;
+ retPoint[j] = 0.0;
+ for(row=0; row<em->uorder; row++)
+ {
+ retPoint[j] += em->ucoeff[row] * (*data);
+ data += em->k;
+ }
+ }
+}
+
+void OpenGLCurveEvaluator::inDoEvalCoord1(REAL u)
+{
+ REAL temp_vertex[4];
+ REAL temp_normal[3];
+ REAL temp_color[4];
+ REAL temp_texcoord[4];
+ if(texcoord_flag) //there is a texture map
+ {
+ inDoDomain1(&em_texcoord, u, temp_texcoord);
+ texcoordCallBack(temp_texcoord, userData);
+ }
+#ifdef DEBUG
+printf("color_flag = %i\n", color_flag);
+#endif
+ if(color_flag) //there is a color map
+ {
+ inDoDomain1(&em_color, u, temp_color);
+ colorCallBack(temp_color, userData);
+ }
+ if(normal_flag) //there is a normal map
+ {
+ inDoDomain1(&em_normal, u, temp_normal);
+ normalCallBack(temp_normal, userData);
+ }
+ if(vertex_flag)
+ {
+ inDoDomain1(&em_vertex, u, temp_vertex);
+ vertexCallBack(temp_vertex, userData);
+ }
+}
+
+void OpenGLCurveEvaluator::inMapMesh1f(int umin, int umax)
+{
+ REAL du, u;
+ int i;
+ if(global_grid_nu == 0)
+ return; //no points to output
+ du = (global_grid_u1 - global_grid_u0) / (REAL) global_grid_nu;
+ bgnline();
+ for(i=umin; i<= umax; i++){
+ u = (i==global_grid_nu)? global_grid_u1: global_grid_u0 + i*du;
+ inDoEvalCoord1(u);
+ }
+ endline();
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/insurfeval.cc b/mesalib/src/glu/sgi/libnurbs/interface/insurfeval.cc
new file mode 100644
index 000000000..9d0c82a91
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/insurfeval.cc
@@ -0,0 +1,2064 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+#include <math.h>
+#include <assert.h>
+
+#include "glsurfeval.h"
+
+//extern int surfcount;
+
+//#define CRACK_TEST
+
+#define AVOID_ZERO_NORMAL
+
+#ifdef AVOID_ZERO_NORMAL
+#define myabs(x) ((x>0)? x: (-x))
+#define MYZERO 0.000001
+#define MYDELTA 0.001
+#endif
+
+//#define USE_LOD
+#ifdef USE_LOD
+//#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
+#define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)
+
+static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
+ REAL& u, REAL& v)
+{
+ REAL a,a1,b,b1;
+
+ a = ((REAL) j) / ((REAL) pow2_level);
+ a1 = 1-a;
+
+ if(j != 0)
+ {
+ b = ((REAL) k) / ((REAL)j);
+ b1 = 1-b;
+ }
+ REAL x,y,z;
+ x = a1;
+ if(j==0)
+ {
+ y=0; z=0;
+ }
+ else{
+ y = b1*a;
+ z = b *a;
+ }
+
+ u = x*A[0] + y*B[0] + z*C[0];
+ v = x*A[1] + y*B[1] + z*C[1];
+}
+
+void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2],
+ int level)
+{
+ int k,j;
+ int pow2_level;
+ /*compute 2^level*/
+ pow2_level = 1;
+
+ for(j=0; j<level; j++)
+ pow2_level *= 2;
+ for(j=0; j<=pow2_level-1; j++)
+ {
+ REAL u,v;
+
+/* beginCallBack(GL_TRIANGLE_STRIP);*/
+glBegin(GL_TRIANGLE_STRIP);
+ LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+
+ for(k=0; k<=j; k++)
+ {
+ LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+
+ LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);
+
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+ inDoEvalCoord2EM(u,v);
+#endif
+ }
+// endCallBack();
+glEnd();
+ }
+}
+
+void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
+ int level
+ )
+{
+ int i,k;
+ switch(type){
+ case GL_TRIANGLE_STRIP:
+ case GL_QUAD_STRIP:
+ for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
+ {
+ LOD_triangle(verts+k-4, verts+k-2, verts+k,
+ level
+ );
+ LOD_triangle(verts+k-2, verts+k+2, verts+k,
+ level
+ );
+ }
+ if(num_vert % 2 ==1)
+ {
+ LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
+ level
+ );
+ }
+ break;
+ case GL_TRIANGLE_FAN:
+ for(i=1, k=2; i<=num_vert-2; i++, k+=2)
+ {
+ LOD_triangle(verts,verts+k, verts+k+2,
+ level
+ );
+ }
+ break;
+
+ default:
+ fprintf(stderr, "typy not supported in LOD_\n");
+ }
+}
+
+
+#endif //USE_LOD
+
+//#define GENERIC_TEST
+#ifdef GENERIC_TEST
+extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
+extern int temp_signal;
+
+static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
+{
+ float r=2.0;
+ float Ox = 0.5*(xmin+xmax);
+ float Oy = 0.5*(ymin+ymax);
+ float Oz = 0.5*(zmin+zmax);
+ float nx = cos(v) * sin(u);
+ float ny = sin(v) * sin(u);
+ float nz = cos(u);
+ float x= Ox+r * nx;
+ float y= Oy+r * ny;
+ float z= Oz+r * nz;
+
+ temp_normal[0] = nx;
+ temp_normal[1] = ny;
+ temp_normal[2] = nz;
+ temp_vertex[0] = x;
+ temp_vertex[1] = y;
+ temp_vertex[2] = z;
+
+// glNormal3f(nx,ny,nz);
+// glVertex3f(x,y,z);
+}
+
+static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
+{
+ float r=2.0;
+ float Ox = 0.5*(xmin+xmax);
+ float Oy = 0.5*(ymin+ymax);
+ float Oz = 0.5*(zmin+zmax);
+ float nx = cos(v);
+ float ny = sin(v);
+ float nz = 0;
+ float x= Ox+r * nx;
+ float y= Oy+r * ny;
+ float z= Oz - 2*u;
+
+ temp_normal[0] = nx;
+ temp_normal[1] = ny;
+ temp_normal[2] = nz;
+ temp_vertex[0] = x;
+ temp_vertex[1] = y;
+ temp_vertex[2] = z;
+
+/*
+ glNormal3f(nx,ny,nz);
+ glVertex3f(x,y,z);
+*/
+}
+
+#endif //GENERIC_TEST
+
+void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ inBPMEval(temp);
+ }
+}
+
+void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
+{
+ int i,j,k,l;
+ float u,v;
+
+ int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
+ int vstride = bpm->bpatch->dimension;
+ inMap2f(
+ (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
+ bpm->bpatch->umin,
+ bpm->bpatch->umax,
+ ustride,
+ bpm->bpatch->uorder,
+ bpm->bpatch->vmin,
+ bpm->bpatch->vmax,
+ vstride,
+ bpm->bpatch->vorder,
+ bpm->bpatch->ctlpoints);
+
+ bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3+1); /*in case the origional dimenion is 4, then we need 4 space to pass to evaluator.*/
+ assert(bpm->vertex_array);
+ bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
+ assert(bpm->normal_array);
+#ifdef CRACK_TEST
+if( global_ev_u1 ==2 && global_ev_u2 == 3
+ && global_ev_v1 ==2 && global_ev_v2 == 3)
+{
+REAL vertex[4];
+REAL normal[4];
+#ifdef DEBUG
+printf("***number 1\n");
+#endif
+
+beginCallBack(GL_QUAD_STRIP, NULL);
+inEvalCoord2f(3.0, 3.0);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(3.0, 2.7);
+inEvalCoord2f(2.0, 2.7);
+inEvalCoord2f(3.0, 2.0);
+inEvalCoord2f(2.0, 2.0);
+endCallBack(NULL);
+
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 2.7);
+endCallBack(NULL);
+
+}
+
+/*
+if( global_ev_u1 ==2 && global_ev_u2 == 3
+ && global_ev_v1 ==1 && global_ev_v2 == 2)
+{
+#ifdef DEBUG
+printf("***number 2\n");
+#endif
+beginCallBack(GL_QUAD_STRIP);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 1.0);
+inEvalCoord2f(3.0, 2.0);
+inEvalCoord2f(3.0, 1.0);
+endCallBack();
+}
+*/
+if( global_ev_u1 ==1 && global_ev_u2 == 2
+ && global_ev_v1 ==2 && global_ev_v2 == 3)
+{
+#ifdef DEBUG
+printf("***number 3\n");
+#endif
+beginCallBack(GL_QUAD_STRIP, NULL);
+inEvalCoord2f(2.0, 3.0);
+inEvalCoord2f(1.0, 3.0);
+inEvalCoord2f(2.0, 2.3);
+inEvalCoord2f(1.0, 2.3);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(1.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inEvalCoord2f(2.0, 2.3);
+inEvalCoord2f(2.0, 2.0);
+inEvalCoord2f(2.0, 3.0);
+endCallBack(NULL);
+
+}
+return;
+#endif
+
+ k=0;
+ l=0;
+
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+ beginCallBack(bpm->type_array[i], userData);
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+ inDoEvalCoord2NOGE(u,v,
+ bpm->vertex_array+l,
+ bpm->normal_array+l);
+
+ normalCallBack(bpm->normal_array+l, userData);
+ vertexCallBack(bpm->vertex_array+l, userData);
+
+ k += 2;
+ l += 3;
+ }
+ endCallBack(userData);
+ }
+}
+
+void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
+{
+ REAL du, dv;
+ REAL point[4];
+ REAL normal[3];
+ REAL u,v;
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+ u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+ inDoEvalCoord2(u,v,point,normal);
+}
+
+void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
+{
+
+ REAL point[4];
+ REAL normal[3];
+ inDoEvalCoord2(u,v,point, normal);
+}
+
+
+
+/*define a grid. store the values into the global variabls:
+ * global_grid_*
+ *These values will be used later by evaluating functions
+ */
+void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
+ int nv, REAL v0, REAL v1)
+{
+ global_grid_u0 = u0;
+ global_grid_u1 = u1;
+ global_grid_nu = nu;
+ global_grid_v0 = v0;
+ global_grid_v1 = v1;
+ global_grid_nv = nv;
+}
+
+void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
+{
+ REAL du, dv;
+ int i,j;
+ REAL point[4];
+ REAL normal[3];
+ if(global_grid_nu == 0 || global_grid_nv == 0)
+ return; /*no points need to be output*/
+ du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
+ dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
+
+ if(global_grid_nu >= global_grid_nv){
+ for(i=lowU; i<highU; i++){
+ REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
+ REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
+
+ bgnqstrip();
+ for(j=highV; j>=lowV; j--){
+ REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
+
+ inDoEvalCoord2(u1, v1, point, normal);
+ inDoEvalCoord2(u2, v1, point, normal);
+ }
+ endqstrip();
+ }
+ }
+
+ else{
+ for(i=lowV; i<highV; i++){
+ REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
+ REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
+
+ bgnqstrip();
+ for(j=highU; j>=lowU; j--){
+ REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);
+ inDoEvalCoord2(u1, v2, point, normal);
+ inDoEvalCoord2(u1, v1, point, normal);
+ }
+ endqstrip();
+ }
+ }
+
+}
+
+void OpenGLSurfaceEvaluator::inMap2f(int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints)
+{
+ int i,j,x;
+ REAL *data = global_ev_ctlPoints;
+
+
+
+ if(k == GL_MAP2_VERTEX_3) k=3;
+ else if (k==GL_MAP2_VERTEX_4) k =4;
+ else {
+ printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
+ return;
+ }
+
+ global_ev_k = k;
+ global_ev_u1 = ulower;
+ global_ev_u2 = uupper;
+ global_ev_ustride = ustride;
+ global_ev_uorder = uorder;
+ global_ev_v1 = vlower;
+ global_ev_v2 = vupper;
+ global_ev_vstride = vstride;
+ global_ev_vorder = vorder;
+
+ /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
+ for (i=0; i<uorder; i++) {
+ for (j=0; j<vorder; j++) {
+ for (x=0; x<k; x++) {
+ data[x] = ctlPoints[x];
+ }
+ ctlPoints += vstride;
+ data += k;
+ }
+ ctlPoints += ustride - vstride * vorder;
+ }
+
+}
+
+
+/*
+ *given a point p with homegeneous coordiante (x,y,z,w),
+ *let pu(x,y,z,w) be its partial derivative vector with
+ *respect to u
+ *and pv(x,y,z,w) be its partial derivative vector with repect to v.
+ *This function returns the partial derivative vectors of the
+ *inhomegensous coordinates, i.e.,
+ * (x/w, y/w, z/w) with respect to u and v.
+ */
+void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *pv)
+{
+ pu[0] = pu[0]*p[3] - pu[3]*p[0];
+ pu[1] = pu[1]*p[3] - pu[3]*p[1];
+ pu[2] = pu[2]*p[3] - pu[3]*p[2];
+
+ pv[0] = pv[0]*p[3] - pv[3]*p[0];
+ pv[1] = pv[1]*p[3] - pv[3]*p[1];
+ pv[2] = pv[2]*p[3] - pv[3]*p[2];
+}
+
+/*compute the cross product of pu and pv and normalize.
+ *the normal is returned in retNormal
+ * pu: dimension 3
+ * pv: dimension 3
+ * n: return normal, of dimension 3
+ */
+void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
+{
+ REAL mag;
+
+ n[0] = pu[1]*pv[2] - pu[2]*pv[1];
+ n[1] = pu[2]*pv[0] - pu[0]*pv[2];
+ n[2] = pu[0]*pv[1] - pu[1]*pv[0];
+
+ mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
+
+ if (mag > 0.0) {
+ n[0] /= mag;
+ n[1] /= mag;
+ n[2] /= mag;
+ }
+}
+
+
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+ /*output this vertex*/
+/* inMeshStreamInsert(global_ms, retPoint, retNormal);*/
+
+
+
+ glNormal3fv(retNormal);
+ glVertex3fv(retPoint);
+
+
+
+
+ #ifdef DEBUG
+ printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
+ #endif
+
+
+
+}
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+// inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
+ inDoDomain2WithDerivsBU(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+}
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+// inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
+
+ inDoDomain2WithDerivsBV(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+}
+
+
+/*Compute point and normal
+ *see the head of inDoDomain2WithDerivs
+ *for the meaning of the arguments
+ */
+void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
+ REAL *retPoint, REAL *retNormal)
+{
+
+ REAL du[4];
+ REAL dv[4];
+
+
+ assert(global_ev_k>=3 && global_ev_k <= 4);
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
+
+
+#ifdef AVOID_ZERO_NORMAL
+
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = global_ev_u1;
+ REAL u2 = global_ev_u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
+ }
+ if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = global_ev_v1;
+ REAL v2 = global_ev_v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(global_ev_k){
+ case 3:
+ inComputeNormal2(du, dv, retNormal);
+ break;
+ case 4:
+ inComputeFirstPartials(retPoint, du, dv);
+ inComputeNormal2(du, dv, retNormal);
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ retPoint[0] /= retPoint[3];
+ retPoint[1] /= retPoint[3];
+ retPoint[2] /= retPoint[3];
+ break;
+ }
+// glNormal3fv(retNormal);
+// glVertex3fv(retPoint);
+}
+
+void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
+{
+ int j,row,col;
+ REAL p, pdv;
+ REAL *data;
+
+ if(global_vprime != vprime || global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vprime = vprime;
+ global_vorder = vorder;
+ }
+
+ for(j=0; j<k; j++){
+ data = baseData+j;
+ for(row=0; row<uorder; row++){
+ p = global_vcoeff[0] * (*data);
+ pdv = global_vcoeffDeriv[0] * (*data);
+ data += k;
+ for(col = 1; col < vorder; col++){
+ p += global_vcoeff[col] * (*data);
+ pdv += global_vcoeffDeriv[col] * (*data);
+ data += k;
+ }
+ global_BV[row][j] = p;
+ global_PBV[row][j] = pdv;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
+{
+ int j,row,col;
+ REAL p, pdu;
+ REAL *data;
+
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uprime = uprime;
+ global_uorder = uorder;
+ }
+
+ for(j=0; j<k; j++){
+ data = baseData+j;
+ for(col=0; col<vorder; col++){
+ data = baseData+j + k*col;
+ p = global_ucoeff[0] * (*data);
+ pdu = global_ucoeffDeriv[0] * (*data);
+ data += k*uorder;
+ for(row = 1; row < uorder; row++){
+ p += global_ucoeff[row] * (*data);
+ pdu += global_ucoeffDeriv[row] * (*data);
+ data += k * uorder;
+ }
+ global_BU[col][j] = p;
+ global_PBU[col][j] = pdu;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv)
+{
+ int j, col;
+
+ REAL vprime;
+
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+
+ vprime = (v - v1) / (v2 - v1);
+
+
+ if(global_vprime != vprime || global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vprime = vprime;
+ global_vorder = vorder;
+ }
+
+
+ for(j=0; j<k; j++)
+ {
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (col = 0; col < vorder; col++) {
+ retPoint[j] += global_BU[col][j] * global_vcoeff[col];
+ retdu[j] += global_PBU[col][j] * global_vcoeff[col];
+ retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL* retdu, REAL *retdv)
+{
+ int j, row;
+ REAL uprime;
+
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+ uprime = (u - u1) / (u2 - u1);
+
+
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uprime = uprime;
+ global_uorder = uorder;
+ }
+
+
+ for(j=0; j<k; j++)
+ {
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < uorder; row++) {
+ retPoint[j] += global_BV[row][j] * global_ucoeff[row];
+ retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
+ retdv[j] += global_PBV[row][j] * global_ucoeff[row];
+ }
+ }
+}
+
+
+/*
+ *given a Bezier surface, and parameter (u,v), compute the point in the object space,
+ *and the normal
+ *k: the dimension of the object space: usually 2,3,or 4.
+ *u,v: the paramter pair.
+ *u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
+ *v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
+ *baseData: contrl points. arranged as: (u,v,k).
+ *retPoint: the computed point (one point) with dimension k.
+ *retdu: the computed partial derivative with respect to u.
+ *retdv: the computed partial derivative with respect to v.
+ */
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
+ REAL u1, REAL u2, int uorder,
+ REAL v1, REAL v2, int vorder,
+ REAL *baseData,
+ REAL *retPoint, REAL *retdu, REAL *retdv)
+{
+ int j, row, col;
+ REAL uprime;
+ REAL vprime;
+ REAL p;
+ REAL pdv;
+ REAL *data;
+
+ if((u2 == u1) || (v2 == v1))
+ return;
+ uprime = (u - u1) / (u2 - u1);
+ vprime = (v - v1) / (v2 - v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(global_uprime != uprime || global_uorder != uorder) {
+ inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
+ global_uorder = uorder;
+ global_uprime = uprime;
+ }
+ if (global_vprime != vprime ||
+ global_vorder != vorder) {
+ inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
+ global_vorder = vorder;
+ global_vprime = vprime;
+ }
+
+ for (j = 0; j < k; j++) {
+ data=baseData+j;
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = global_vcoeff[0] * (*data);
+ pdv = global_vcoeffDeriv[0] * (*data);
+ data += k;
+ for (col = 1; col < vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += global_vcoeff[col] * (*data);
+ pdv += global_vcoeffDeriv[col] * (*data);
+ data += k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += global_ucoeff[row] * p;
+ retdu[j] += global_ucoeffDeriv[row] * p;
+ retdv[j] += global_ucoeff[row] * pdv;
+ }
+ }
+}
+
+
+/*
+ *compute the Bezier polynomials C[n,j](v) for all j at v with
+ *return values stored in coeff[], where
+ * C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
+ * j=0,1,2,...,n.
+ *order : n+1
+ *vprime: v
+ *coeff : coeff[j]=C[n,j](v), this array store the returned values.
+ *The algorithm is a recursive scheme:
+ * C[0,0]=1;
+ * C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluate
+ */
+void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ return;
+ }
+
+ oneMinusvprime = 1-vprime;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ if (order == 2) return;
+
+ for (i = 2; i < order; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+}
+
+/*
+ *compute the Bezier polynomials C[n,j](v) and derivatives for all j at v with
+ *return values stored in coeff[] and coeffDeriv[].
+ *see the head of function inPreEvaluate for the definition of C[n,j](v)
+ *and how to compute the values.
+ *The algorithm to compute the derivative is:
+ * dC[0,0](v) = 0.
+ * dC[n,j](v) = n*(dC[n-1,j-1](v) - dC[n-1,j](v)).
+ *
+ *This code is copied from opengl/soft/so_eval.c:PreEvaluateWidthDeriv
+ */
+void OpenGLSurfaceEvaluator::inPreEvaluateWithDeriv(int order, REAL vprime,
+ REAL *coeff, REAL *coeffDeriv)
+{
+ int i, j;
+ REAL oldval, temp;
+ REAL oneMinusvprime;
+
+ oneMinusvprime = 1-vprime;
+ /*
+ * Minor optimization
+ * Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to
+ * their i==1 loop values to avoid the initialization and the i==1 loop.
+ */
+ if (order == 1) {
+ coeff[0] = 1.0;
+ coeffDeriv[0] = 0.0;
+ return;
+ } else if (order == 2) {
+ coeffDeriv[0] = -1.0;
+ coeffDeriv[1] = 1.0;
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ return;
+ }
+ coeff[0] = oneMinusvprime;
+ coeff[1] = vprime;
+ for (i = 2; i < order - 1; i++) {
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+ }
+ coeffDeriv[0] = -coeff[0];
+ /*
+ ** Minor optimization:
+ ** Would make this a "for (j=1; j<order-1; j++)" loop, but it is always
+ ** executed at least once, so this is more efficient.
+ */
+ j=1;
+ do {
+ coeffDeriv[j] = coeff[j-1] - coeff[j];
+ j++;
+ } while (j < order - 1);
+ coeffDeriv[j] = coeff[j-1];
+
+ oldval = coeff[0] * vprime;
+ coeff[0] = oneMinusvprime * coeff[0];
+ for (j = 1; j < i; j++) {
+ temp = oldval;
+ oldval = coeff[j] * vprime;
+ coeff[j] = temp + oneMinusvprime * coeff[j];
+ }
+ coeff[j] = oldval;
+}
+
+void OpenGLSurfaceEvaluator::inEvalULine(int n_points, REAL v, REAL* u_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3])
+{
+ int i,k;
+ REAL temp[4];
+inPreEvaluateBV_intfac(v);
+
+ for(i=0,k=0; i<n_points; i++, k += stride)
+ {
+ inDoEvalCoord2NOGE_BV(u_vals[k],v,temp, ret_normals[i]);
+
+ ret_points[i][0] = temp[0];
+ ret_points[i][1] = temp[1];
+ ret_points[i][2] = temp[2];
+
+ }
+
+}
+
+void OpenGLSurfaceEvaluator::inEvalVLine(int n_points, REAL u, REAL* v_vals,
+ int stride, REAL ret_points[][3], REAL ret_normals[][3])
+{
+ int i,k;
+ REAL temp[4];
+inPreEvaluateBU_intfac(u);
+ for(i=0,k=0; i<n_points; i++, k += stride)
+ {
+ inDoEvalCoord2NOGE_BU(u, v_vals[k], temp, ret_normals[i]);
+ ret_points[i][0] = temp[0];
+ ret_points[i][1] = temp[1];
+ ret_points[i][2] = temp[2];
+ }
+}
+
+
+/*triangulate a strip bounded by two lines which are parallel to U-axis
+ *upperVerts: the verteces on the upper line
+ *lowerVertx: the verteces on the lower line
+ *n_upper >=1
+ *n_lower >=1
+ */
+void OpenGLSurfaceEvaluator::inEvalUStrip(int n_upper, REAL v_upper, REAL* upper_val, int n_lower, REAL v_lower, REAL* lower_val)
+{
+ int i,j,k,l;
+ REAL leftMostV[2];
+ typedef REAL REAL3[3];
+
+ REAL3* upperXYZ = (REAL3*) malloc(sizeof(REAL3)*n_upper);
+ assert(upperXYZ);
+ REAL3* upperNormal = (REAL3*) malloc(sizeof(REAL3) * n_upper);
+ assert(upperNormal);
+ REAL3* lowerXYZ = (REAL3*) malloc(sizeof(REAL3)*n_lower);
+ assert(lowerXYZ);
+ REAL3* lowerNormal = (REAL3*) malloc(sizeof(REAL3) * n_lower);
+ assert(lowerNormal);
+
+ inEvalULine(n_upper, v_upper, upper_val, 1, upperXYZ, upperNormal);
+ inEvalULine(n_lower, v_lower, lower_val, 1, lowerXYZ, lowerNormal);
+
+
+
+ REAL* leftMostXYZ;
+ REAL* leftMostNormal;
+
+ /*
+ *the algorithm works by scanning from left to right.
+ *leftMostV: the left most of the remaining verteces (on both upper and lower).
+ * it could an element of upperVerts or lowerVerts.
+ *i: upperVerts[i] is the first vertex to the right of leftMostV on upper line *j: lowerVerts[j] is the first vertex to the right of leftMostV on lower line */
+
+ /*initialize i,j,and leftMostV
+ */
+ if(upper_val[0] <= lower_val[0])
+ {
+ i=1;
+ j=0;
+
+ leftMostV[0] = upper_val[0];
+ leftMostV[1] = v_upper;
+ leftMostXYZ = upperXYZ[0];
+ leftMostNormal = upperNormal[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ leftMostV[0] = lower_val[0];
+ leftMostV[1] = v_lower;
+
+ leftMostXYZ = lowerXYZ[0];
+ leftMostNormal = lowerNormal[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and leftMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ bgntfan();
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ while(j<n_lower){
+ glNormal3fv(lowerNormal[j]);
+ glVertex3fv(lowerXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ bgntfan();
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ for(k=n_upper-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ glNormal3fv(upperNormal[k]);
+ glVertex3fv(upperXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+ if(upper_val[i] <= lower_val[j])
+ {
+ bgntfan();
+
+ glNormal3fv(lowerNormal[j]);
+ glVertex3fv(lowerXYZ[j]);
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+
+ while(k<n_upper)
+ {
+ if(upper_val[k] > lower_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ glNormal3fv(upperNormal[l]);
+ glVertex3fv(upperXYZ[l]);
+
+ }
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+ endtfan();
+
+ /*update i and leftMostV for next loop
+ */
+ i = k+1;
+
+ leftMostV[0] = upper_val[k];
+ leftMostV[1] = v_upper;
+ leftMostNormal = upperNormal[k];
+ leftMostXYZ = upperXYZ[k];
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ bgntfan();
+ glNormal3fv(upperNormal[i]);
+ glVertex3fv(upperXYZ[i]);
+
+ glNormal3fv(leftMostNormal);
+ glVertex3fv(leftMostXYZ);
+
+
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]
+ */
+ k=j;
+ while(k< n_lower)
+ {
+ if(lower_val[k] >= upper_val[i])
+ break;
+ glNormal3fv(lowerNormal[k]);
+ glVertex3fv(lowerXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and leftMostV for next loop
+ */
+ j=k;
+ leftMostV[0] = lower_val[j-1];
+ leftMostV[1] = v_lower;
+
+ leftMostNormal = lowerNormal[j-1];
+ leftMostXYZ = lowerXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+ free(upperXYZ);
+ free(lowerXYZ);
+ free(upperNormal);
+ free(lowerNormal);
+}
+
+/*triangulate a strip bounded by two lines which are parallel to V-axis
+ *leftVerts: the verteces on the left line
+ *rightVertx: the verteces on the right line
+ *n_left >=1
+ *n_right >=1
+ */
+void OpenGLSurfaceEvaluator::inEvalVStrip(int n_left, REAL u_left, REAL* left_val, int n_right, REAL u_right, REAL* right_val)
+{
+ int i,j,k,l;
+ REAL botMostV[2];
+ typedef REAL REAL3[3];
+
+ REAL3* leftXYZ = (REAL3*) malloc(sizeof(REAL3)*n_left);
+ assert(leftXYZ);
+ REAL3* leftNormal = (REAL3*) malloc(sizeof(REAL3) * n_left);
+ assert(leftNormal);
+ REAL3* rightXYZ = (REAL3*) malloc(sizeof(REAL3)*n_right);
+ assert(rightXYZ);
+ REAL3* rightNormal = (REAL3*) malloc(sizeof(REAL3) * n_right);
+ assert(rightNormal);
+
+ inEvalVLine(n_left, u_left, left_val, 1, leftXYZ, leftNormal);
+ inEvalVLine(n_right, u_right, right_val, 1, rightXYZ, rightNormal);
+
+
+
+ REAL* botMostXYZ;
+ REAL* botMostNormal;
+
+ /*
+ *the algorithm works by scanning from bot to top.
+ *botMostV: the bot most of the remaining verteces (on both left and right).
+ * it could an element of leftVerts or rightVerts.
+ *i: leftVerts[i] is the first vertex to the top of botMostV on left line
+ *j: rightVerts[j] is the first vertex to the top of botMostV on rightline */
+
+ /*initialize i,j,and botMostV
+ */
+ if(left_val[0] <= right_val[0])
+ {
+ i=1;
+ j=0;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[0];
+ botMostXYZ = leftXYZ[0];
+ botMostNormal = leftNormal[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[0];
+
+ botMostXYZ = rightXYZ[0];
+ botMostNormal = rightNormal[0];
+ }
+
+ /*the main loop.
+ *the invariance is that:
+ *at the beginning of each loop, the meaning of i,j,and botMostV are
+ *maintained
+ */
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ bgntfan();
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ while(j<n_right){
+ glNormal3fv(rightNormal[j]);
+ glVertex3fv(rightXYZ[j]);
+ j++;
+
+ }
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ bgntfan();
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ for(k=n_left-1; k>=i; k--) /*reverse order for two-side lighting*/
+ {
+ glNormal3fv(leftNormal[k]);
+ glVertex3fv(leftXYZ[k]);
+ }
+
+ endtfan();
+ }
+ break; /*exit the main loop*/
+ }
+ else /* case3: neither is empty, plus the botMostV, there is at least one triangle to output*/
+ {
+ if(left_val[i] <= right_val[j])
+ {
+ bgntfan();
+
+ glNormal3fv(rightNormal[j]);
+ glVertex3fv(rightXYZ[j]);
+
+ /*find the last k>=i such that
+ *leftverts[k][0] <= rightverts[j][0]
+ */
+ k=i;
+
+ while(k<n_left)
+ {
+ if(left_val[k] > right_val[j])
+ break;
+ k++;
+
+ }
+ k--;
+
+
+ for(l=k; l>=i; l--)/*the reverse is for two-side lighting*/
+ {
+ glNormal3fv(leftNormal[l]);
+ glVertex3fv(leftXYZ[l]);
+
+ }
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+ endtfan();
+
+ /*update i and botMostV for next loop
+ */
+ i = k+1;
+
+ botMostV[0] = u_left;
+ botMostV[1] = left_val[k];
+ botMostNormal = leftNormal[k];
+ botMostXYZ = leftXYZ[k];
+ }
+ else /*left_val[i] > right_val[j])*/
+ {
+ bgntfan();
+ glNormal3fv(leftNormal[i]);
+ glVertex3fv(leftXYZ[i]);
+
+ glNormal3fv(botMostNormal);
+ glVertex3fv(botMostXYZ);
+
+
+ /*find the last k>=j such that
+ *rightverts[k][0] < leftverts[i][0]
+ */
+ k=j;
+ while(k< n_right)
+ {
+ if(right_val[k] >= left_val[i])
+ break;
+ glNormal3fv(rightNormal[k]);
+ glVertex3fv(rightXYZ[k]);
+
+ k++;
+ }
+ endtfan();
+
+ /*update j and botMostV for next loop
+ */
+ j=k;
+ botMostV[0] = u_right;
+ botMostV[1] = right_val[j-1];
+
+ botMostNormal = rightNormal[j-1];
+ botMostXYZ = rightXYZ[j-1];
+ }
+ }
+ }
+ //clean up
+ free(leftXYZ);
+ free(rightXYZ);
+ free(leftNormal);
+ free(rightNormal);
+}
+
+/*-----------------------begin evalMachine-------------------*/
+void OpenGLSurfaceEvaluator::inMap2fEM(int which, int k,
+ REAL ulower,
+ REAL uupper,
+ int ustride,
+ int uorder,
+ REAL vlower,
+ REAL vupper,
+ int vstride,
+ int vorder,
+ REAL *ctlPoints)
+{
+ int i,j,x;
+ surfEvalMachine *temp_em;
+ switch(which){
+ case 0: //vertex
+ vertex_flag = 1;
+ temp_em = &em_vertex;
+ break;
+ case 1: //normal
+ normal_flag = 1;
+ temp_em = &em_normal;
+ break;
+ case 2: //color
+ color_flag = 1;
+ temp_em = &em_color;
+ break;
+ default:
+ texcoord_flag = 1;
+ temp_em = &em_texcoord;
+ break;
+ }
+
+ REAL *data = temp_em->ctlPoints;
+
+ temp_em->uprime = -1;//initilized
+ temp_em->vprime = -1;
+
+ temp_em->k = k;
+ temp_em->u1 = ulower;
+ temp_em->u2 = uupper;
+ temp_em->ustride = ustride;
+ temp_em->uorder = uorder;
+ temp_em->v1 = vlower;
+ temp_em->v2 = vupper;
+ temp_em->vstride = vstride;
+ temp_em->vorder = vorder;
+
+ /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
+ for (i=0; i<uorder; i++) {
+ for (j=0; j<vorder; j++) {
+ for (x=0; x<k; x++) {
+ data[x] = ctlPoints[x];
+ }
+ ctlPoints += vstride;
+ data += k;
+ }
+ ctlPoints += ustride - vstride * vorder;
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsEM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint, REAL *retdu, REAL *retdv)
+{
+ int j, row, col;
+ REAL the_uprime;
+ REAL the_vprime;
+ REAL p;
+ REAL pdv;
+ REAL *data;
+
+ if((em->u2 == em->u1) || (em->v2 == em->v1))
+ return;
+ the_uprime = (u - em->u1) / (em->u2 - em->u1);
+ the_vprime = (v - em->v1) / (em->v2 - em->v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(em->uprime != the_uprime) {
+ inPreEvaluateWithDeriv(em->uorder, the_uprime, em->ucoeff, em->ucoeffDeriv);
+ em->uprime = the_uprime;
+ }
+ if (em->vprime != the_vprime) {
+ inPreEvaluateWithDeriv(em->vorder, the_vprime, em->vcoeff, em->vcoeffDeriv);
+ em->vprime = the_vprime;
+ }
+
+ for (j = 0; j < em->k; j++) {
+ data=em->ctlPoints+j;
+ retPoint[j] = retdu[j] = retdv[j] = 0.0;
+ for (row = 0; row < em->uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = em->vcoeff[0] * (*data);
+ pdv = em->vcoeffDeriv[0] * (*data);
+ data += em->k;
+ for (col = 1; col < em->vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += em->vcoeff[col] * (*data);
+ pdv += em->vcoeffDeriv[col] * (*data);
+ data += em->k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += em->ucoeff[row] * p;
+ retdu[j] += em->ucoeffDeriv[row] * p;
+ retdv[j] += em->ucoeff[row] * pdv;
+ }
+ }
+}
+
+void OpenGLSurfaceEvaluator::inDoDomain2EM(surfEvalMachine *em, REAL u, REAL v,
+ REAL *retPoint)
+{
+ int j, row, col;
+ REAL the_uprime;
+ REAL the_vprime;
+ REAL p;
+ REAL *data;
+
+ if((em->u2 == em->u1) || (em->v2 == em->v1))
+ return;
+ the_uprime = (u - em->u1) / (em->u2 - em->u1);
+ the_vprime = (v - em->v1) / (em->v2 - em->v1);
+
+ /* Compute coefficients for values and derivs */
+
+ /* Use already cached values if possible */
+ if(em->uprime != the_uprime) {
+ inPreEvaluate(em->uorder, the_uprime, em->ucoeff);
+ em->uprime = the_uprime;
+ }
+ if (em->vprime != the_vprime) {
+ inPreEvaluate(em->vorder, the_vprime, em->vcoeff);
+ em->vprime = the_vprime;
+ }
+
+ for (j = 0; j < em->k; j++) {
+ data=em->ctlPoints+j;
+ retPoint[j] = 0.0;
+ for (row = 0; row < em->uorder; row++) {
+ /*
+ ** Minor optimization.
+ ** The col == 0 part of the loop is extracted so we don't
+ ** have to initialize p and pdv to 0.
+ */
+ p = em->vcoeff[0] * (*data);
+ data += em->k;
+ for (col = 1; col < em->vorder; col++) {
+ /* Incrementally build up p, pdv value */
+ p += em->vcoeff[col] * (*data);
+ data += em->k;
+ }
+ /* Use p, pdv value to incrementally add up r, du, dv */
+ retPoint[j] += em->ucoeff[row] * p;
+ }
+ }
+}
+
+
+void OpenGLSurfaceEvaluator::inDoEvalCoord2EM(REAL u, REAL v)
+{
+ REAL temp_vertex[5];
+ REAL temp_normal[3];
+ REAL temp_color[4];
+ REAL temp_texcoord[4];
+
+ if(texcoord_flag)
+ {
+ inDoDomain2EM(&em_texcoord, u,v, temp_texcoord);
+ texcoordCallBack(temp_texcoord, userData);
+ }
+ if(color_flag)
+ {
+ inDoDomain2EM(&em_color, u,v, temp_color);
+ colorCallBack(temp_color, userData);
+ }
+
+ if(normal_flag) //there is a normla map
+ {
+ inDoDomain2EM(&em_normal, u,v, temp_normal);
+ normalCallBack(temp_normal, userData);
+
+ if(vertex_flag)
+ {
+ inDoDomain2EM(&em_vertex, u,v,temp_vertex);
+ if(em_vertex.k == 4)
+ {
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ }
+ temp_vertex[3]=u;
+ temp_vertex[4]=v;
+ vertexCallBack(temp_vertex, userData);
+ }
+ }
+ else if(auto_normal_flag) //no normal map but there is a normal callbackfunctin
+ {
+ REAL du[4];
+ REAL dv[4];
+
+ /*compute homegeneous point and partial derivatives*/
+ inDoDomain2WithDerivsEM(&em_vertex, u,v,temp_vertex,du,dv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+
+#ifdef AVOID_ZERO_NORMAL
+ if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
+ {
+
+ REAL tempdu[4];
+ REAL tempdata[4];
+ REAL u1 = em_vertex.u1;
+ REAL u2 = em_vertex.u2;
+ if(u-MYDELTA*(u2-u1) < u1)
+ u = u+ MYDELTA*(u2-u1);
+ else
+ u = u-MYDELTA*(u2-u1);
+ inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, tempdu, dv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+ }
+ else if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
+ {
+ REAL tempdv[4];
+ REAL tempdata[4];
+ REAL v1 = em_vertex.v1;
+ REAL v2 = em_vertex.v2;
+ if(v-MYDELTA*(v2-v1) < v1)
+ v = v+ MYDELTA*(v2-v1);
+ else
+ v = v-MYDELTA*(v2-v1);
+ inDoDomain2WithDerivsEM(&em_vertex,u,v, tempdata, du, tempdv);
+
+ if(em_vertex.k ==4)
+ inComputeFirstPartials(temp_vertex, du, dv);
+ }
+#endif
+
+ /*compute normal*/
+ switch(em_vertex.k){
+ case 3:
+
+ inComputeNormal2(du, dv, temp_normal);
+ break;
+ case 4:
+
+// inComputeFirstPartials(temp_vertex, du, dv);
+ inComputeNormal2(du, dv, temp_normal);
+
+ /*transform the homegeneous coordinate of retPoint into inhomogenous one*/
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ break;
+ }
+ normalCallBack(temp_normal, userData);
+ temp_vertex[3] = u;
+ temp_vertex[4] = v;
+ vertexCallBack(temp_vertex, userData);
+
+ }/*end if auto_normal*/
+ else //no normal map, and no normal callback function
+ {
+ if(vertex_flag)
+ {
+ inDoDomain2EM(&em_vertex, u,v,temp_vertex);
+ if(em_vertex.k == 4)
+ {
+ temp_vertex[0] /= temp_vertex[3];
+ temp_vertex[1] /= temp_vertex[3];
+ temp_vertex[2] /= temp_vertex[3];
+ }
+ temp_vertex[3] = u;
+ temp_vertex[4] = v;
+ vertexCallBack(temp_vertex, userData);
+ }
+ }
+}
+
+
+void OpenGLSurfaceEvaluator::inBPMEvalEM(bezierPatchMesh* bpm)
+{
+ int i,j,k;
+ float u,v;
+
+ int ustride;
+ int vstride;
+
+#ifdef USE_LOD
+ if(bpm->bpatch != NULL)
+ {
+ bezierPatch* p=bpm->bpatch;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+
+ glMap2f( (p->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+
+
+/*
+ inMap2fEM(0, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+*/
+ }
+#else
+
+ if(bpm->bpatch != NULL){
+ bezierPatch* p = bpm->bpatch;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(0, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_normal != NULL){
+ bezierPatch* p = bpm->bpatch_normal;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(1, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_color != NULL){
+ bezierPatch* p = bpm->bpatch_color;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(2, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+ if(bpm->bpatch_texcoord != NULL){
+ bezierPatch* p = bpm->bpatch_texcoord;
+ ustride = p->dimension * p->vorder;
+ vstride = p->dimension;
+ inMap2fEM(3, p->dimension,
+ p->umin,
+ p->umax,
+ ustride,
+ p->uorder,
+ p->vmin,
+ p->vmax,
+ vstride,
+ p->vorder,
+ p->ctlpoints);
+ }
+#endif
+
+
+ k=0;
+ for(i=0; i<bpm->index_length_array; i++)
+ {
+#ifdef USE_LOD
+ if(bpm->type_array[i] == GL_POLYGON) //a mesh
+ {
+ GLfloat *temp = bpm->UVarray+k;
+ GLfloat u0 = temp[0];
+ GLfloat v0 = temp[1];
+ GLfloat u1 = temp[2];
+ GLfloat v1 = temp[3];
+ GLint nu = (GLint) ( temp[4]);
+ GLint nv = (GLint) ( temp[5]);
+ GLint umin = (GLint) ( temp[6]);
+ GLint vmin = (GLint) ( temp[7]);
+ GLint umax = (GLint) ( temp[8]);
+ GLint vmax = (GLint) ( temp[9]);
+
+ glMapGrid2f(LOD_eval_level*nu, u0, u1, LOD_eval_level*nv, v0, v1);
+ glEvalMesh2(GL_FILL, LOD_eval_level*umin, LOD_eval_level*umax, LOD_eval_level*vmin, LOD_eval_level*vmax);
+ }
+ else
+ {
+ LOD_eval(bpm->length_array[i], bpm->UVarray+k, bpm->type_array[i],
+ 0
+ );
+ }
+ k+= 2*bpm->length_array[i];
+
+#else //undef USE_LOD
+
+#ifdef CRACK_TEST
+if( bpm->bpatch->umin == 2 && bpm->bpatch->umax == 3
+ && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
+{
+REAL vertex[4];
+REAL normal[4];
+#ifdef DEBUG
+printf("***number ****1\n");
+#endif
+
+beginCallBack(GL_QUAD_STRIP, NULL);
+inDoEvalCoord2EM(3.0, 3.0);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(3.0, 2.7);
+inDoEvalCoord2EM(2.0, 2.7);
+inDoEvalCoord2EM(3.0, 2.0);
+inDoEvalCoord2EM(2.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(2.0, 2.7);
+endCallBack(NULL);
+
+}
+if( bpm->bpatch->umin == 1 && bpm->bpatch->umax == 2
+ && bpm->bpatch->vmin ==2 && bpm->bpatch->vmax == 3)
+{
+#ifdef DEBUG
+printf("***number 3\n");
+#endif
+beginCallBack(GL_QUAD_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 3.0);
+inDoEvalCoord2EM(1.0, 3.0);
+inDoEvalCoord2EM(2.0, 2.3);
+inDoEvalCoord2EM(1.0, 2.3);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(1.0, 2.0);
+endCallBack(NULL);
+
+beginCallBack(GL_TRIANGLE_STRIP, NULL);
+inDoEvalCoord2EM(2.0, 2.3);
+inDoEvalCoord2EM(2.0, 2.0);
+inDoEvalCoord2EM(2.0, 3.0);
+endCallBack(NULL);
+
+}
+return;
+#endif //CRACK_TEST
+
+ beginCallBack(bpm->type_array[i], userData);
+
+ for(j=0; j<bpm->length_array[i]; j++)
+ {
+ u = bpm->UVarray[k];
+ v = bpm->UVarray[k+1];
+#ifdef USE_LOD
+ LOD_EVAL_COORD(u,v);
+// glEvalCoord2f(u,v);
+#else
+
+#ifdef GENERIC_TEST
+ float temp_normal[3];
+ float temp_vertex[3];
+ if(temp_signal == 0)
+ {
+ gTessVertexSphere(u,v, temp_normal, temp_vertex);
+//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
+ normalCallBack(temp_normal, userData);
+ vertexCallBack(temp_vertex, userData);
+ }
+ else if(temp_signal == 1)
+ {
+ gTessVertexCyl(u,v, temp_normal, temp_vertex);
+//printf("normal=(%f,%f,%f)\n", temp_normal[0], temp_normal[1], temp_normal[2])//printf("veretx=(%f,%f,%f)\n", temp_vertex[0], temp_vertex[1], temp_vertex[2]);
+ normalCallBack(temp_normal, userData);
+ vertexCallBack(temp_vertex, userData);
+ }
+ else
+#endif //GENERIC_TEST
+
+ inDoEvalCoord2EM(u,v);
+
+#endif //USE_LOD
+
+ k += 2;
+ }
+ endCallBack(userData);
+
+#endif //USE_LOD
+ }
+}
+
+void OpenGLSurfaceEvaluator::inBPMListEvalEM(bezierPatchMesh* list)
+{
+ bezierPatchMesh* temp;
+ for(temp = list; temp != NULL; temp = temp->next)
+ {
+ inBPMEvalEM(temp);
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/mystdio.h b/mesalib/src/glu/sgi/libnurbs/interface/mystdio.h
new file mode 100644
index 000000000..5ab49effd
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/mystdio.h
@@ -0,0 +1,60 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdio.h
+ *
+ */
+
+#ifndef __glumystdio_h_
+#define __glumystdio_h_
+
+#ifdef STANDALONE
+inline void _glu_dprintf( const char *, ... ) { }
+#endif
+
+#ifdef LIBRARYBUILD
+#ifndef NDEBUG
+#include <stdio.h>
+#define _glu_dprintf printf
+#else
+inline void _glu_dprintf( const char *, ... ) { }
+#endif
+#endif
+
+#ifdef GLBUILD
+inline void _glu_dprintf( const char *, ... ) { }
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* __glumystdio_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/interface/mystdlib.h b/mesalib/src/glu/sgi/libnurbs/interface/mystdlib.h
new file mode 100644
index 000000000..ab7a3b273
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/interface/mystdlib.h
@@ -0,0 +1,57 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdlib.h
+ *
+ */
+
+#ifndef __glumystdlib_h_
+#define __glumystdlib_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#ifdef LIBRARYBUILD
+#include <stdlib.h>
+#endif
+
+#ifdef GLBUILD
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#endif /* __glumystdlib_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arc.cc b/mesalib/src/glu/sgi/libnurbs/internals/arc.cc
new file mode 100644
index 000000000..b85139de9
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arc.cc
@@ -0,0 +1,347 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arc.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arc.h"
+#include "bin.h"
+#include "bezierarc.h"
+#include "pwlarc.h"
+#include "simplemath.h"
+
+/* local preprocessor definitions */
+#define ZERO 0.00001/*0.000001*/
+
+const int Arc::bezier_tag = (1<<13);
+const int Arc::arc_tag = (1<<3);
+const int Arc::tail_tag = (1<<6);
+
+/*--------------------------------------------------------------------------
+ * makeSide - attach a pwl arc to an arc and mark it as a border arc
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::makeSide( PwlArc *pwl, arc_side side )
+{
+ assert( pwl != 0);
+ assert( pwlArc == 0 );
+ assert( pwl->npts > 0 );
+ assert( pwl->pts != 0);
+ pwlArc = pwl;
+ clearbezier();
+ setside( side );
+}
+
+
+/*--------------------------------------------------------------------------
+ * numpts - count number of points on arc loop
+ *--------------------------------------------------------------------------
+ */
+
+int
+Arc::numpts( void )
+{
+ Arc_ptr jarc = this;
+ int npts = 0;
+ do {
+ npts += jarc->pwlArc->npts;
+ jarc = jarc->next;
+ } while( jarc != this );
+ return npts;
+}
+
+/*--------------------------------------------------------------------------
+ * markverts - mark each point with id of arc
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::markverts( void )
+{
+ Arc_ptr jarc = this;
+
+ do {
+ TrimVertex *p = jarc->pwlArc->pts;
+ for( int i=0; i<jarc->pwlArc->npts; i++ )
+ p[i].nuid = jarc->nuid;
+ jarc = jarc->next;
+ } while( jarc != this );
+}
+
+/*--------------------------------------------------------------------------
+ * getextrema - find axis extrema on arc loop
+ *--------------------------------------------------------------------------
+ */
+
+void
+Arc::getextrema( Arc_ptr extrema[4] )
+{
+ REAL leftpt, botpt, rightpt, toppt;
+
+ extrema[0] = extrema[1] = extrema[2] = extrema[3] = this;
+
+ leftpt = rightpt = this->tail()[0];
+ botpt = toppt = this->tail()[1];
+
+ for( Arc_ptr jarc = this->next; jarc != this; jarc = jarc->next ) {
+ if ( jarc->tail()[0] < leftpt ||
+ (jarc->tail()[0] <= leftpt && jarc->rhead()[0]<=leftpt)) {
+ leftpt = jarc->pwlArc->pts->param[0];
+ extrema[1] = jarc;
+ }
+ if ( jarc->tail()[0] > rightpt ||
+ (jarc->tail()[0] >= rightpt && jarc->rhead()[0] >= rightpt)) {
+ rightpt = jarc->pwlArc->pts->param[0];
+ extrema[3] = jarc;
+ }
+ if ( jarc->tail()[1] < botpt ||
+ (jarc->tail()[1] <= botpt && jarc->rhead()[1] <= botpt )) {
+ botpt = jarc->pwlArc->pts->param[1];
+ extrema[2] = jarc;
+ }
+ if ( jarc->tail()[1] > toppt ||
+ (jarc->tail()[1] >= toppt && jarc->rhead()[1] >= toppt)) {
+ toppt = jarc->pwlArc->pts->param[1];
+ extrema[0] = jarc;
+ }
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ * show - print to the stdout the vertices of a pwl arc
+ *-------------------------------------------------------------------------
+ */
+
+void
+Arc::show()
+{
+#ifndef NDEBUG
+ _glu_dprintf( "\tPWLARC NP: %d FL: 1\n", pwlArc->npts );
+ for( int i = 0; i < pwlArc->npts; i++ ) {
+ _glu_dprintf( "\t\tVERTEX %f %f\n", pwlArc->pts[i].param[0],
+ pwlArc->pts[i].param[1] );
+ }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * print - print out the vertices of all pwl arcs on a loop
+ *-------------------------------------------------------------------------
+ */
+
+void
+Arc::print( void )
+{
+ Arc_ptr jarc = this;
+
+#ifndef NDEBUG
+ _glu_dprintf( "BGNTRIM\n" );
+#endif
+ do {
+ jarc->show( );
+ jarc = jarc->next;
+ } while (jarc != this);
+#ifndef NDEBUG
+ _glu_dprintf("ENDTRIM\n" );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * isDisconnected - check if tail of arc and head of prev meet
+ *-------------------------------------------------------------------------
+ */
+
+int
+Arc::isDisconnected( void )
+{
+ if( pwlArc == 0 ) return 0;
+ if( prev->pwlArc == 0 ) return 0;
+
+ REAL *p0 = tail();
+ REAL *p1 = prev->rhead();
+
+ if( ((p0[0] - p1[0]) > ZERO) || ((p1[0] - p0[0]) > ZERO) ||
+ ((p0[1] - p1[1]) > ZERO) || ((p1[1] - p0[1]) > ZERO) ) {
+#ifndef NDEBUG
+ _glu_dprintf( "x coord = %f %f %f\n", p0[0], p1[0], p0[0] - p1[0] );
+ _glu_dprintf( "y coord = %f %f %f\n", p0[1], p1[1], p0[1] - p1[1] );
+#endif
+ return 1;
+ } else {
+ /* average two points together */
+ p0[0] = p1[0] = (p1[0] + p0[0]) * 0.5;
+ p0[1] = p1[1] = (p1[1] + p0[1]) * 0.5;
+ return 0;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * neq_vert - assert that two 2D vertices are not equal
+ *-------------------------------------------------------------------------
+ */
+
+inline static int
+neq_vert( REAL *v1, REAL *v2 )
+{
+ return ((v1[0] != v2[0]) || (v1[1] != v2[1] )) ? 1 : 0;
+}
+
+/*-------------------------------------------------------------------------
+ * check - verify consistency of a loop, including
+ * 1) if pwl, no two consecutive vertices are identical
+ * 2) the circular link pointers are valid
+ * 3) the geometric info at the head and tail are consistent
+ *-------------------------------------------------------------------------
+ */
+
+int
+Arc::check( void )
+{
+ if( this == 0 ) return 1;
+ Arc_ptr jarc = this;
+ do {
+ assert( (jarc->pwlArc != 0) || (jarc->bezierArc != 0) );
+
+ if (jarc->prev == 0 || jarc->next == 0) {
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc:null next/prev pointer\n");
+ jarc->print( );
+#endif
+ return 0;
+ }
+
+ if (jarc->next->prev != jarc) {
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc: pointer linkage screwed up\n");
+ jarc->print( );
+#endif
+ return 0;
+ }
+
+ if( jarc->pwlArc ) {
+#ifndef NDEBUG
+ assert( jarc->pwlArc->npts >= 1 );
+ assert( jarc->pwlArc->npts < 100000 );
+/*
+ for( int i=0; i < jarc->pwlArc->npts-1; i++ )
+ assert( neq_vert( jarc->pwlArc->pts[i].param,
+ jarc->pwlArc->pts[i+1].param) );
+*/
+#endif
+ if( jarc->prev->pwlArc ) {
+ if( jarc->tail()[1] != jarc->prev->rhead()[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc: geometric linkage screwed up 1\n");
+ jarc->prev->show();
+ jarc->show();
+#endif
+ return 0;
+ }
+ if( jarc->tail()[0] != jarc->prev->rhead()[0] ) {
+
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc: geometric linkage screwed up 2\n");
+ jarc->prev->show();
+ jarc->show();
+#endif
+ return 0;
+ }
+ }
+ if( jarc->next->pwlArc ) {
+ if( jarc->next->tail()[0] != jarc->rhead()[0] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc: geometric linkage screwed up 3\n");
+ jarc->show();
+ jarc->next->show();
+#endif
+ return 0;
+ }
+ if( jarc->next->tail()[1] != jarc->rhead()[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "checkjarc: geometric linkage screwed up 4\n");
+ jarc->show();
+ jarc->next->show();
+#endif
+ return 0;
+ }
+ }
+ if( jarc->isbezier() ) {
+ assert( jarc->pwlArc->npts == 2 );
+ assert( (jarc->pwlArc->pts[0].param[0] == \
+ jarc->pwlArc->pts[1].param[0]) ||\
+ (jarc->pwlArc->pts[0].param[1] == \
+ jarc->pwlArc->pts[1].param[1]) );
+ }
+ }
+ jarc = jarc->next;
+ } while (jarc != this);
+ return 1;
+}
+
+
+#define TOL 0.00001
+
+inline long tooclose( REAL x, REAL y )
+{
+ return (glu_abs(x-y) < TOL) ? 1 : 0;
+}
+
+
+/*--------------------------------------------------------------------------
+ * append - append a jordan arc to a circularly linked list
+ *--------------------------------------------------------------------------
+ */
+
+Arc_ptr
+Arc::append( Arc_ptr jarc )
+{
+ if( jarc != 0 ) {
+ next = jarc->next;
+ prev = jarc;
+ next->prev = prev->next = this;
+ } else {
+ next = prev = this;
+ }
+ return this;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arc.h b/mesalib/src/glu/sgi/libnurbs/internals/arc.h
new file mode 100644
index 000000000..e986019c3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arc.h
@@ -0,0 +1,133 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * arc.h
+ *
+ */
+
+#ifndef __gluarc_h_
+#define __gluarc_h_
+
+#include "myassert.h"
+#include "bufpool.h"
+#include "mystdio.h"
+#include "types.h"
+#include "pwlarc.h"
+#include "trimvertex.h"
+
+class Bin;
+class Arc;
+struct BezierArc;
+
+typedef class Arc *Arc_ptr;
+
+enum arc_side { arc_none = 0, arc_right, arc_top, arc_left, arc_bottom };
+
+
+class Arc: public PooledObj { /* an arc, in two list, the trim list and bin */
+
+public:
+ static const int bezier_tag;
+ static const int arc_tag;
+ static const int tail_tag;
+ Arc_ptr prev; /* trim list pointer */
+ Arc_ptr next; /* trim list pointer */
+ Arc_ptr link; /* bin pointers */
+ BezierArc * bezierArc; /* associated bezier arc */
+ PwlArc * pwlArc; /* associated pwl arc */
+ long type; /* curve type */
+ long nuid;
+
+ inline Arc( Arc *, PwlArc * );
+ inline Arc( arc_side, long );
+
+ Arc_ptr append( Arc_ptr );
+ int check( void );
+ int isMonotone( void );
+ int isDisconnected( void );
+ int numpts( void );
+ void markverts( void );
+ void getextrema( Arc_ptr[4] );
+ void print( void );
+ void show( void );
+ void makeSide( PwlArc *, arc_side );
+ inline int isTessellated() { return pwlArc ? 1 : 0; }
+ inline long isbezier() { return type & bezier_tag; }
+ inline void setbezier() { type |= bezier_tag; }
+ inline void clearbezier() { type &= ~bezier_tag; }
+ inline long npts() { return pwlArc->npts; }
+ inline TrimVertex * pts() { return pwlArc->pts; }
+ inline REAL * tail() { return pwlArc->pts[0].param; }
+ inline REAL * head() { return next->pwlArc->pts[0].param; }
+ inline REAL * rhead() { return pwlArc->pts[pwlArc->npts-1].param; }
+ inline long ismarked() { return type & arc_tag; }
+ inline void setmark() { type |= arc_tag; }
+ inline void clearmark() { type &= (~arc_tag); }
+ inline void clearside() { type &= ~(0x7 << 8); }
+ inline void setside( arc_side s ) { clearside(); type |= (((long)s)<<8); }
+ inline arc_side getside() { return (arc_side) ((type>>8) & 0x7); }
+ inline int getitail() { return type & tail_tag; }
+ inline void setitail() { type |= tail_tag; }
+ inline void clearitail() { type &= (~tail_tag); }
+};
+
+/*--------------------------------------------------------------------------
+ * Arc - initialize a new Arc with the same type and uid of
+ * a given Arc and a given pwl arc
+ *--------------------------------------------------------------------------
+ */
+
+inline
+Arc::Arc( Arc *j, PwlArc *p )
+{
+ bezierArc = NULL;
+ pwlArc = p;
+ type = j->type;
+ nuid = j->nuid;
+}
+
+/*--------------------------------------------------------------------------
+ * Arc - initialize a new Arc with the same type and uid of
+ * a given Arc and a given pwl arc
+ *--------------------------------------------------------------------------
+ */
+
+inline
+Arc::Arc( arc_side side, long _nuid )
+{
+ bezierArc = NULL;
+ pwlArc = NULL;
+ type = 0;
+ setside( side );
+ nuid = _nuid;
+}
+
+#endif /* __gluarc_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.cc b/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.cc
new file mode 100644
index 000000000..1f85cb710
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.cc
@@ -0,0 +1,172 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arcsorter.c++
+ *
+ */
+
+#ifndef __gluarcsorter_c_
+#define __gluarcsorter_c_
+
+#include "glimports.h"
+#include "arc.h"
+#include "arcsorter.h"
+#include "subdivider.h"
+
+ArcSorter::ArcSorter(Subdivider &s) : Sorter( sizeof( Arc ** ) ), subdivider(s)
+{
+}
+
+int
+ArcSorter::qscmp( char *, char * )
+{
+ _glu_dprintf( "ArcSorter::qscmp: pure virtual called\n" );
+ return 0;
+}
+
+void
+ArcSorter::qsort( Arc **a, int n )
+{
+ Sorter::qsort( (void *) a, n );
+}
+
+void
+ArcSorter::qsexc( char *i, char *j )// i<-j, j<-i
+{
+ Arc **jarc1 = (Arc **) i;
+ Arc **jarc2 = (Arc **) j;
+ Arc *tmp = *jarc1;
+ *jarc1 = *jarc2;
+ *jarc2 = tmp;
+}
+
+void
+ArcSorter::qstexc( char *i, char *j, char *k )// i<-k, k<-j, j<-i
+{
+ Arc **jarc1 = (Arc **) i;
+ Arc **jarc2 = (Arc **) j;
+ Arc **jarc3 = (Arc **) k;
+ Arc *tmp = *jarc1;
+ *jarc1 = *jarc3;
+ *jarc3 = *jarc2;
+ *jarc2 = tmp;
+}
+
+
+ArcSdirSorter::ArcSdirSorter( Subdivider &s ) : ArcSorter(s)
+{
+}
+
+int
+ArcSdirSorter::qscmp( char *i, char *j )
+{
+ Arc *jarc1 = *(Arc **) i;
+ Arc *jarc2 = *(Arc **) j;
+
+ int v1 = (jarc1->getitail() ? 0 : (jarc1->pwlArc->npts - 1));
+ int v2 = (jarc2->getitail() ? 0 : (jarc2->pwlArc->npts - 1));
+
+ REAL diff = jarc1->pwlArc->pts[v1].param[1] -
+ jarc2->pwlArc->pts[v2].param[1];
+
+ if( diff < 0.0)
+ return -1;
+ else if( diff > 0.0)
+ return 1;
+ else {
+ if( v1 == 0 ) {
+ if( jarc2->tail()[0] < jarc1->tail()[0] ) {
+ return subdivider.ccwTurn_sl( jarc2, jarc1 ) ? 1 : -1;
+ } else {
+ return subdivider.ccwTurn_sr( jarc2, jarc1 ) ? -1 : 1;
+ }
+ } else {
+ if( jarc2->head()[0] < jarc1->head()[0] ) {
+ return subdivider.ccwTurn_sl( jarc1, jarc2 ) ? -1 : 1;
+ } else {
+ return subdivider.ccwTurn_sr( jarc1, jarc2 ) ? 1 : -1;
+ }
+ }
+ }
+}
+
+ArcTdirSorter::ArcTdirSorter( Subdivider &s ) : ArcSorter(s)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * ArcTdirSorter::qscmp -
+ * compare two axis monotone arcs that are incident
+ * to the line T == compare_value. Determine which of the
+ * two intersects that line with a LESSER S value. If
+ * jarc1 does, return 1. If jarc2 does, return -1.
+ *----------------------------------------------------------------------------
+ */
+int
+ArcTdirSorter::qscmp( char *i, char *j )
+{
+ Arc *jarc1 = *(Arc **) i;
+ Arc *jarc2 = *(Arc **) j;
+
+ int v1 = (jarc1->getitail() ? 0 : (jarc1->pwlArc->npts - 1));
+ int v2 = (jarc2->getitail() ? 0 : (jarc2->pwlArc->npts - 1));
+
+ REAL diff = jarc1->pwlArc->pts[v1].param[0] -
+ jarc2->pwlArc->pts[v2].param[0];
+
+ if( diff < 0.0)
+ return 1;
+ else if( diff > 0.0)
+ return -1;
+ else {
+ if( v1 == 0 ) {
+ if (jarc2->tail()[1] < jarc1->tail()[1]) {
+ return subdivider.ccwTurn_tl( jarc2, jarc1 ) ? 1 : -1;
+ } else {
+ return subdivider.ccwTurn_tr( jarc2, jarc1 ) ? -1 : 1;
+ }
+ } else {
+ if( jarc2->head()[1] < jarc1->head()[1] ) {
+ return subdivider.ccwTurn_tl( jarc1, jarc2 ) ? -1 : 1;
+ } else {
+ return subdivider.ccwTurn_tr( jarc1, jarc2 ) ? 1 : -1;
+ }
+ }
+ }
+}
+
+
+
+#endif /* __gluarcsorter_c_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.h b/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.h
new file mode 100644
index 000000000..d72dd1e86
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arcsorter.h
@@ -0,0 +1,73 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * arcsorter.h
+ *
+ */
+
+#ifndef __gluarcsorter_h_
+#define __gluarcsorter_h_
+
+#include "sorter.h"
+#include "arcsorter.h"
+
+class Arc;
+class Subdivider;
+
+class ArcSorter : private Sorter {
+public:
+ ArcSorter(Subdivider &);
+ void qsort( Arc **a, int n );
+protected:
+ virtual int qscmp( char *, char * );
+ Subdivider& subdivider;
+private:
+ void qsexc( char *i, char *j ); // i<-j, j<-i
+ void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+};
+
+
+class ArcSdirSorter : public ArcSorter {
+public:
+ ArcSdirSorter( Subdivider & );
+private:
+ int qscmp( char *, char * );
+};
+
+
+class ArcTdirSorter : public ArcSorter {
+public:
+ ArcTdirSorter( Subdivider & );
+private:
+ int qscmp( char *, char * );
+};
+
+#endif /* __gluarcsorter_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arctess.cc b/mesalib/src/glu/sgi/libnurbs/internals/arctess.cc
new file mode 100644
index 000000000..29e7cf4c0
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arctess.cc
@@ -0,0 +1,611 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * arctessellator.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arctess.h"
+#include "bufpool.h"
+#include "simplemath.h"
+#include "bezierarc.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+
+#define NOELIMINATION
+
+#define steps_function(large, small, rate) (max(1, 1+ (int) ((large-small)/rate)));
+
+/*-----------------------------------------------------------------------------
+ * ArcTessellator - construct an ArcTessellator
+ *-----------------------------------------------------------------------------
+ */
+
+ArcTessellator::ArcTessellator( TrimVertexPool& t, Pool& p )
+ : pwlarcpool(p), trimvertexpool(t)
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * ~ArcTessellator - destroy an ArcTessellator
+ *-----------------------------------------------------------------------------
+ */
+
+ArcTessellator::~ArcTessellator( void )
+{
+}
+
+/*-----------------------------------------------------------------------------
+ * bezier - construct a bezier arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::bezier( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2 )
+{
+ assert( arc != 0 );
+ assert( ! arc->isTessellated() );
+
+#ifndef NDEBUG
+ switch( arc->getside() ) {
+ case arc_left:
+ assert( s1 == s2 );
+ assert( t2 < t1 );
+ break;
+ case arc_right:
+ assert( s1 == s2 );
+ assert( t1 < t2 );
+ break;
+ case arc_top:
+ assert( t1 == t2 );
+ assert( s2 < s1 );
+ break;
+ case arc_bottom:
+ assert( t1 == t2 );
+ assert( s1 < s2 );
+ break;
+ case arc_none:
+ (void) abort();
+ break;
+ }
+#endif
+
+ TrimVertex *p = trimvertexpool.get(2);
+ arc->pwlArc = new(pwlarcpool) PwlArc( 2, p );
+ p[0].param[0] = s1;
+ p[0].param[1] = t1;
+ p[1].param[0] = s2;
+ p[1].param[1] = t2;
+ assert( (s1 == s2) || (t1 == t2) );
+ arc->setbezier();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwl_left - construct a left boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_left( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
+{
+ assert( t2 < t1 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+/* int nsteps = 1 + (int) ((t1 - t2) / rate ); */
+ int nsteps = steps_function(t1, t2, rate);
+
+
+ REAL stepsize = (t1 - t2) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = nsteps; i > 0; i-- ) {
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t2;
+ t2 += stepsize;
+ }
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t1;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_left );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl_right - construct a right boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_right( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
+{
+ assert( t1 < t2 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((t2 - t1) / rate ); */
+ int nsteps = steps_function(t2,t1,rate);
+ REAL stepsize = (t2 - t1) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t1;
+ t1 += stepsize;
+ }
+ newvert[i].param[0] = s;
+ newvert[i].param[1] = t2;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_right );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwl_top - construct a top boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_top( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
+{
+ assert( s2 < s1 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((s1 - s2) / rate ); */
+ int nsteps = steps_function(s1,s2,rate);
+ REAL stepsize = (s1 - s2) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = nsteps; i > 0; i-- ) {
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t;
+ s2 += stepsize;
+ }
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_top );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl_bottom - construct a bottom boundary pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl_bottom( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
+{
+ assert( s1 < s2 );
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+/* int nsteps = 1 + (int) ((s2 - s1) / rate ); */
+ int nsteps = steps_function(s2,s1,rate);
+ REAL stepsize = (s2 - s1) / (REAL) nsteps;
+
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ int i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t;
+ s1 += stepsize;
+ }
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t;
+
+ arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom );
+}
+
+/*-----------------------------------------------------------------------------
+ * pwl - construct a pwl arc and attach it to an arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::pwl( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2, REAL rate )
+{
+
+/* if(rate <= 0.06) rate = 0.06;*/
+
+ int snsteps = 1 + (int) (glu_abs(s2 - s1) / rate );
+ int tnsteps = 1 + (int) (glu_abs(t2 - t1) / rate );
+ int nsteps = max(1,max( snsteps, tnsteps ));
+
+ REAL sstepsize = (s2 - s1) / (REAL) nsteps;
+ REAL tstepsize = (t2 - t1) / (REAL) nsteps;
+ TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
+ long i;
+ for( i = 0; i < nsteps; i++ ) {
+ newvert[i].param[0] = s1;
+ newvert[i].param[1] = t1;
+ s1 += sstepsize;
+ t1 += tstepsize;
+ }
+ newvert[i].param[0] = s2;
+ newvert[i].param[1] = t2;
+
+ /* arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom ); */
+ arc->pwlArc = new(pwlarcpool) PwlArc( nsteps+1, newvert );
+
+ arc->clearbezier();
+ arc->clearside( );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * tessellateLinear - constuct a linear pwl arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::tessellateLinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
+{
+ assert( arc->pwlArc == NULL );
+ REAL s1, s2, t1, t2;
+
+ //we don't need to scale by arc_stepsize if the trim curve
+ //is piecewise linear. Reason: In pwl_right, pwl_left, pwl_top, pwl_left,
+ //and pwl, the nsteps is computed by deltaU (or V) /stepsize.
+ //The quantity deltaU/arc_stepsize doesn't have any meaning. And
+ //it causes problems: see bug 517641
+ REAL stepsize = geo_stepsize; /* * arc_stepsize*/;
+
+ BezierArc *b = arc->bezierArc;
+
+ if( isrational ) {
+ s1 = b->cpts[0] / b->cpts[2];
+ t1 = b->cpts[1] / b->cpts[2];
+ s2 = b->cpts[b->stride+0] / b->cpts[b->stride+2];
+ t2 = b->cpts[b->stride+1] / b->cpts[b->stride+2];
+ } else {
+ s1 = b->cpts[0];
+ t1 = b->cpts[1];
+ s2 = b->cpts[b->stride+0];
+ t2 = b->cpts[b->stride+1];
+ }
+ if( s1 == s2 )
+ if( t1 < t2 )
+ pwl_right( arc, s1, t1, t2, stepsize );
+ else
+ pwl_left( arc, s1, t1, t2, stepsize );
+ else if( t1 == t2 )
+ if( s1 < s2 )
+ pwl_bottom( arc, t1, s1, s2, stepsize );
+ else
+ pwl_top( arc, t1, s1, s2, stepsize );
+ else
+ pwl( arc, s1, s2, t1, t2, stepsize );
+}
+
+/*-----------------------------------------------------------------------------
+ * tessellateNonlinear - constuct a nonlinear pwl arc and attach it to an Arc
+ *-----------------------------------------------------------------------------
+ */
+
+void
+ArcTessellator::tessellateNonlinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
+{
+ assert( arc->pwlArc == NULL );
+
+ REAL stepsize = geo_stepsize * arc_stepsize;
+
+ BezierArc *bezierArc = arc->bezierArc;
+
+ REAL size; //bounding box size of the curve in UV
+ {
+ int i,j;
+ REAL min_u, min_v, max_u,max_v;
+ min_u = max_u = bezierArc->cpts[0];
+ min_v = max_v = bezierArc->cpts[1];
+ for(i=1, j=bezierArc->stride; i<bezierArc->order; i++, j+= bezierArc->stride)
+ {
+ if(bezierArc->cpts[j] < min_u)
+ min_u = bezierArc->cpts[j];
+ if(bezierArc->cpts[j] > max_u)
+ max_u = bezierArc->cpts[j];
+ if(bezierArc->cpts[j+1] < min_v)
+ min_v = bezierArc->cpts[j+1];
+ if(bezierArc->cpts[j+1] > max_v)
+ max_v = bezierArc->cpts[j+1];
+ }
+
+ size = max_u - min_u;
+ if(size < max_v - min_v)
+ size = max_v - min_v;
+ }
+
+ /*int nsteps = 1 + (int) (1.0/stepsize);*/
+
+ int nsteps = (int) (size/stepsize);
+ if(nsteps <=0)
+ nsteps=1;
+
+ TrimVertex *vert = trimvertexpool.get( nsteps+1 );
+ REAL dp = 1.0/nsteps;
+
+
+ arc->pwlArc = new(pwlarcpool) PwlArc();
+ arc->pwlArc->pts = vert;
+
+ if( isrational ) {
+ REAL pow_u[MAXORDER], pow_v[MAXORDER], pow_w[MAXORDER];
+ trim_power_coeffs( bezierArc, pow_u, 0 );
+ trim_power_coeffs( bezierArc, pow_v, 1 );
+ trim_power_coeffs( bezierArc, pow_w, 2 );
+
+ /* compute first point exactly */
+ REAL *b = bezierArc->cpts;
+ vert->param[0] = b[0]/b[2];
+ vert->param[1] = b[1]/b[2];
+
+ /* strength reduction on p = dp * step would introduce error */
+ int step;
+#ifndef NOELIMINATION
+ int ocanremove = 0;
+#endif
+ register long order = bezierArc->order;
+ for( step=1, ++vert; step<nsteps; step++, vert++ ) {
+ register REAL p = dp * step;
+ register REAL u = pow_u[0];
+ register REAL v = pow_v[0];
+ register REAL w = pow_w[0];
+ for( register int i = 1; i < order; i++ ) {
+ u = u * p + pow_u[i];
+ v = v * p + pow_v[i];
+ w = w * p + pow_w[i];
+ }
+ vert->param[0] = u/w;
+ vert->param[1] = v/w;
+#ifndef NOELIMINATION
+ REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]);
+ REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]);
+ int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
+ REAL ods=0.0, odt=0.0;
+
+ if( ocanremove && canremove ) {
+ REAL nds = ds + ods;
+ REAL ndt = dt + odt;
+ if( nds<geo_stepsize && ndt<geo_stepsize ) {
+ // remove previous point
+ --vert;
+ vert[0].param[0] = vert[1].param[0];
+ vert[0].param[1] = vert[1].param[1];
+ ods = nds;
+ odt = ndt;
+ ocanremove = 1;
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+#endif
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc->stride;
+ vert->param[0] = b[0]/b[2];
+ vert->param[1] = b[1]/b[2];
+
+ } else {
+ REAL pow_u[MAXORDER], pow_v[MAXORDER];
+ trim_power_coeffs( bezierArc, pow_u, 0 );
+ trim_power_coeffs( bezierArc, pow_v, 1 );
+
+ /* compute first point exactly */
+ REAL *b = bezierArc->cpts;
+ vert->param[0] = b[0];
+ vert->param[1] = b[1];
+
+ /* strength reduction on p = dp * step would introduce error */
+ int step;
+#ifndef NOELIMINATION
+ int ocanremove = 0;
+#endif
+ register long order = bezierArc->order;
+ for( step=1, ++vert; step<nsteps; step++, vert++ ) {
+ register REAL p = dp * step;
+ register REAL u = pow_u[0];
+ register REAL v = pow_v[0];
+ for( register int i = 1; i < bezierArc->order; i++ ) {
+ u = u * p + pow_u[i];
+ v = v * p + pow_v[i];
+ }
+ vert->param[0] = u;
+ vert->param[1] = v;
+#ifndef NOELIMINATION
+ REAL ds = glu_abs(vert[0].param[0] - vert[-1].param[0]);
+ REAL dt = glu_abs(vert[0].param[1] - vert[-1].param[1]);
+ int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
+ REAL ods=0.0, odt=0.0;
+
+ if( ocanremove && canremove ) {
+ REAL nds = ds + ods;
+ REAL ndt = dt + odt;
+ if( nds<geo_stepsize && ndt<geo_stepsize ) {
+ // remove previous point
+ --vert;
+ vert[0].param[0] = vert[1].param[0];
+ vert[0].param[1] = vert[1].param[1];
+ ods = nds;
+ odt = ndt;
+ ocanremove = 1;
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+ } else {
+ ocanremove = canremove;
+ ods = ds;
+ odt = dt;
+ }
+#endif
+ }
+
+ /* compute last point exactly */
+ b += (order - 1) * bezierArc->stride;
+ vert->param[0] = b[0];
+ vert->param[1] = b[1];
+ }
+ arc->pwlArc->npts = vert - arc->pwlArc->pts + 1;
+/*
+ for( TrimVertex *vt=pwlArc->pts; vt != vert-1; vt++ ) {
+ if( tooclose( vt[0].param[0], vt[1].param[0] ) )
+ vt[1].param[0] = vt[0].param[0];
+ if( tooclose( vt[0].param[1], vt[1].param[1] ) )
+ vt[1].param[1] = vt[0].param[1];
+ }
+*/
+}
+
+const REAL ArcTessellator::gl_Bernstein[][MAXORDER][MAXORDER] = {
+ {
+ {1, 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, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 1, 0, 0, 0, 0, 0, 0 },
+ {1, 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, 0, 0, 0, 0 }
+ },
+ {
+ {1, -2, 1, 0, 0, 0, 0, 0 },
+ {-2, 2, 0, 0, 0, 0, 0, 0 },
+ {1, 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, 3, -3, 1, 0, 0, 0, 0 },
+ {3, -6, 3, 0, 0, 0, 0, 0 },
+ {-3, 3, 0, 0, 0, 0, 0, 0 },
+ {1, 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, -4, 6, -4, 1, 0, 0, 0 },
+ {-4, 12, -12, 4, 0, 0, 0, 0 },
+ {6, -12, 6, 0, 0, 0, 0, 0 },
+ {-4, 4, 0, 0, 0, 0, 0, 0 },
+ {1, 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, 5, -10, 10, -5, 1, 0, 0 },
+ {5, -20, 30, -20, 5, 0, 0, 0 },
+ {-10, 30, -30, 10, 0, 0, 0, 0 },
+ {10, -20, 10, 0, 0, 0, 0, 0 },
+ {-5, 5, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {1, -6, 15, -20, 15, -6, 1, 0 },
+ {-6, 30, -60, 60, -30, 6, 0, 0 },
+ {15, -60, 90, -60, 15, 0, 0, 0 },
+ {-20, 60, -60, 20, 0, 0, 0, 0 },
+ {15, -30, 15, 0, 0, 0, 0, 0 },
+ {-6, 6, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 },
+ {0, 0, 0, 0, 0, 0, 0, 0 }
+ },
+ {
+ {-1, 7, -21, 35, -35, 21, -7, 1 },
+ {7, -42, 105, -140, 105, -42, 7, 0 },
+ {-21, 105, -210, 210, -105, 21, 0, 0 },
+ {35, -140, 210, -140, 35, 0, 0, 0 },
+ {-35, 105, -105, 35, 0, 0, 0, 0 },
+ {21, -42, 21, 0, 0, 0, 0, 0 },
+ {-7, 7, 0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0, 0, 0 }
+ }};
+
+
+/*-----------------------------------------------------------------------------
+ * trim_power_coeffs - compute power basis coefficients from bezier coeffients
+ *-----------------------------------------------------------------------------
+ */
+void
+ArcTessellator::trim_power_coeffs( BezierArc *bez_arc, REAL *p, int coord )
+{
+ register int stride = bez_arc->stride;
+ register int order = bez_arc->order;
+ register REAL *base = bez_arc->cpts + coord;
+
+ REAL const (*mat)[MAXORDER][MAXORDER] = &gl_Bernstein[order-1];
+ REAL const (*lrow)[MAXORDER] = &(*mat)[order];
+
+ /* WIN32 didn't like the following line within the for-loop */
+ REAL const (*row)[MAXORDER] = &(*mat)[0];
+ for( ; row != lrow; row++ ) {
+ register REAL s = 0.0;
+ register REAL *point = base;
+ register REAL const *mlast = *row + order;
+ for( REAL const *m = *row; m != mlast; m++, point += stride )
+ s += *(m) * (*point);
+ *(p++) = s;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/arctess.h b/mesalib/src/glu/sgi/libnurbs/internals/arctess.h
new file mode 100644
index 000000000..7802af90c
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/arctess.h
@@ -0,0 +1,66 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * arctess.h
+ *
+ */
+
+#ifndef __gluarctess_h_
+#define __gluarctess_h_
+
+#include "defines.h"
+#include "types.h"
+#include "arc.h"
+
+struct BezierArc;
+class Pool;
+class TrimVertexPool;
+
+class ArcTessellator {
+public:
+ ArcTessellator( TrimVertexPool&, Pool& );
+ ~ArcTessellator( void );
+ void bezier( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl( Arc_ptr, REAL, REAL, REAL, REAL, REAL );
+ void pwl_left( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_right( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_top( Arc_ptr, REAL, REAL, REAL, REAL );
+ void pwl_bottom( Arc_ptr, REAL, REAL, REAL, REAL );
+ void tessellateLinear( Arc_ptr, REAL, REAL, int );
+ void tessellateNonlinear( Arc_ptr, REAL, REAL, int );
+private:
+ static const REAL gl_Bernstein[][MAXORDER][MAXORDER];
+ Pool& pwlarcpool;
+ TrimVertexPool& trimvertexpool;
+ static void trim_power_coeffs( BezierArc *, REAL[MAXORDER], int );
+};
+
+#endif /* __gluarctess_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/backend.cc b/mesalib/src/glu/sgi/libnurbs/internals/backend.cc
new file mode 100644
index 000000000..88dc3f516
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/backend.cc
@@ -0,0 +1,589 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * backend.c++
+ *
+ */
+
+/* Bezier surface backend
+ - interprets display mode (wireframe,shaded,...)
+*/
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "backend.h"
+#include "basiccrveval.h"
+#include "basicsurfeval.h"
+#include "nurbsconsts.h"
+
+#define NOWIREFRAME
+
+
+/*-------------------------------------------------------------------------
+ * bgnsurf - preamble to surface definition and evaluations
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgnsurf( int wiretris, int wirequads, long nuid )
+{
+/*#ifndef NOWIREFRAME*/ //need this for old version
+ wireframetris = wiretris;
+ wireframequads = wirequads;
+/*#endif*/
+
+ /*in the spec, GLU_DISPLAY_MODE is either
+ * GLU_FILL
+ * GLU_OUTLINE_POLY
+ * GLU_OUTLINE_PATCH.
+ *In fact, GLU_FLL is has the same effect as
+ * set GL_FRONT_AND_BACK to be GL_FILL
+ * and GLU_OUTLINE_POLY is the same as set
+ * GL_FRONT_AND_BACK to be GL_LINE
+ *It is more efficient to do this once at the beginning of
+ *each surface than to do it for each primitive.
+ * The internal has more options: outline_triangle and outline_quad
+ *can be seperated. But since this is not in spec, and more importantly,
+ *this is not so useful, so we don't need to keep this option.
+ */
+
+ surfaceEvaluator.bgnmap2f( nuid );
+
+ if(wiretris)
+ surfaceEvaluator.polymode(N_MESHLINE);
+ else
+ surfaceEvaluator.polymode(N_MESHFILL);
+}
+
+void
+Backend::patch( REAL ulo, REAL uhi, REAL vlo, REAL vhi )
+{
+ surfaceEvaluator.domain2f( ulo, uhi, vlo, vhi );
+}
+
+void
+Backend::surfbbox( long type, REAL *from, REAL *to )
+{
+ surfaceEvaluator.range2f( type, from, to );
+}
+
+/*-------------------------------------------------------------------------
+ * surfpts - pass a desription of a surface map
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfpts(
+ long type, /* geometry, color, texture, normal */
+ REAL *pts, /* control points */
+ long ustride, /* distance to next point in u direction */
+ long vstride, /* distance to next point in v direction */
+ int uorder, /* u parametric order */
+ int vorder, /* v parametric order */
+ REAL ulo, /* u lower bound */
+ REAL uhi, /* u upper bound */
+ REAL vlo, /* v lower bound */
+ REAL vhi ) /* v upper bound */
+{
+ surfaceEvaluator.map2f( type,ulo,uhi,ustride,uorder,vlo,vhi,vstride,vorder,pts );
+ surfaceEvaluator.enable( type );
+}
+
+/*-------------------------------------------------------------------------
+ * surfgrid - define a lattice of points with origin and offset
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfgrid( REAL u0, REAL u1, long nu, REAL v0, REAL v1, long nv )
+{
+ surfaceEvaluator.mapgrid2f( nu, u0, u1, nv, v0, v1 );
+}
+
+/*-------------------------------------------------------------------------
+ * surfmesh - evaluate a mesh of points on lattice
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::surfmesh( long u, long v, long n, long m )
+{
+#ifndef NOWIREFRAME
+ if( wireframequads ) {
+ long v0, v1;
+ long u0f = u, u1f = u+n;
+ long v0f = v, v1f = v+m;
+ long parity = (u & 1);
+
+ for( v0 = v0f, v1 = v0f++ ; v0<v1f; v0 = v1, v1++ ) {
+ surfaceEvaluator.bgnline();
+ for( long u = u0f; u<=u1f; u++ ) {
+ if( parity ) {
+ surfaceEvaluator.evalpoint2i( u, v0 );
+ surfaceEvaluator.evalpoint2i( u, v1 );
+ } else {
+ surfaceEvaluator.evalpoint2i( u, v1 );
+ surfaceEvaluator.evalpoint2i( u, v0 );
+ }
+ parity = 1 - parity;
+ }
+ surfaceEvaluator.endline();
+ }
+ } else {
+ surfaceEvaluator.mapmesh2f( N_MESHFILL, u, u+n, v, v+m );
+ }
+#else
+ if( wireframequads ) {
+
+ surfaceEvaluator.mapmesh2f( N_MESHLINE, u, u+n, v, v+m );
+ } else {
+
+ surfaceEvaluator.mapmesh2f( N_MESHFILL, u, u+n, v, v+m );
+ }
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * endsurf - postamble to surface
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endsurf( void )
+{
+ surfaceEvaluator.endmap2f();
+}
+
+/***************************************/
+void
+Backend::bgntfan( void )
+{
+ surfaceEvaluator.bgntfan();
+/*
+ if(wireframetris)
+ surfaceEvaluator.polymode( N_MESHLINE );
+ else
+ surfaceEvaluator.polymode( N_MESHFILL );
+*/
+}
+
+void
+Backend::endtfan( void )
+{
+ surfaceEvaluator.endtfan();
+}
+
+void
+Backend::bgnqstrip( void )
+{
+ surfaceEvaluator.bgnqstrip();
+/*
+ if(wireframequads)
+ surfaceEvaluator.polymode( N_MESHLINE );
+ else
+ surfaceEvaluator.polymode( N_MESHFILL );
+*/
+}
+
+void
+Backend::endqstrip( void )
+{
+ surfaceEvaluator.endqstrip();
+}
+
+void
+Backend::evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ )
+{
+ surfaceEvaluator.evalUStrip(n_upper, v_upper, upper_val,
+ n_lower, v_lower, lower_val);
+}
+
+void
+Backend::evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val
+ )
+{
+ surfaceEvaluator.evalVStrip(n_left, u_left, left_val,
+ n_right, u_right, right_val);
+}
+
+/***************************************/
+
+
+/*-------------------------------------------------------------------------
+ * bgntmesh - preamble to a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgntmesh( const char * )
+{
+#ifndef NOWIREFRAME
+
+ meshindex = 0; /* I think these need to be initialized to zero */
+ npts = 0;
+
+ if( !wireframetris ) {
+ surfaceEvaluator.bgntmesh();
+ }
+#else
+
+ if( wireframetris ) {
+ surfaceEvaluator.bgntmesh();
+ surfaceEvaluator.polymode( N_MESHLINE );
+ } else {
+ surfaceEvaluator.bgntmesh();
+ surfaceEvaluator.polymode( N_MESHFILL );
+ }
+#endif
+}
+
+void
+Backend::tmeshvert( GridTrimVertex *v )
+{
+ if( v->isGridVert() ) {
+ tmeshvert( v->g );
+ } else {
+ tmeshvert( v->t );
+ }
+}
+
+void
+Backend::tmeshvertNOGE(TrimVertex *t)
+{
+// surfaceEvaluator.inDoEvalCoord2NOGE( t->param[0], t->param[1], temp, ttt);
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+//opt for a line with the same u.
+void
+Backend::tmeshvertNOGE_BU(TrimVertex *t)
+{
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE_BU( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+//opt for a line with the same v.
+void
+Backend::tmeshvertNOGE_BV(TrimVertex *t)
+{
+#ifdef USE_OPTTT
+ surfaceEvaluator.inDoEvalCoord2NOGE_BV( t->param[0], t->param[1], t->cache_point, t->cache_normal);
+#endif
+}
+
+void
+Backend::preEvaluateBU(REAL u)
+{
+ surfaceEvaluator.inPreEvaluateBU_intfac(u);
+}
+
+void
+Backend::preEvaluateBV(REAL v)
+{
+ surfaceEvaluator.inPreEvaluateBV_intfac(v);
+}
+
+
+/*-------------------------------------------------------------------------
+ * tmeshvert - evaluate a point on a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::tmeshvert( TrimVertex *t )
+{
+
+#ifndef NOWIREFRAME
+ const long nuid = t->nuid;
+#endif
+ const REAL u = t->param[0];
+ const REAL v = t->param[1];
+
+#ifndef NOWIREFRAME
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 0;
+ mesh[meshindex][3] = nuid;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ }
+#else
+
+ surfaceEvaluator.evalcoord2f( 0, u, v );
+//for uninitial memory read surfaceEvaluator.evalcoord2f( nuid, u, v );
+#endif
+}
+
+//the same as tmeshvert(trimvertex), for efficiency purpose
+void
+Backend::tmeshvert( REAL u, REAL v )
+{
+#ifndef NOWIREFRAME
+ const long nuid = 0;
+
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 0;
+ mesh[meshindex][3] = nuid;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalcoord2f( nuid, u, v );
+ }
+#else
+
+ surfaceEvaluator.evalcoord2f( 0, u, v );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * tmeshvert - evaluate a grid point of a triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::tmeshvert( GridVertex *g )
+{
+ const long u = g->gparam[0];
+ const long v = g->gparam[1];
+
+#ifndef NOWIREFRAME
+ npts++;
+ if( wireframetris ) {
+ if( npts >= 3 ) {
+ surfaceEvaluator.bgnclosedline();
+ if( mesh[0][2] == 0 )
+ surfaceEvaluator.evalcoord2f( (long) mesh[0][3], mesh[0][0], mesh[0][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[0][0], (long) mesh[0][1] );
+ if( mesh[1][2] == 0 )
+ surfaceEvaluator.evalcoord2f( (long) mesh[1][3], mesh[1][0], mesh[1][1] );
+ else
+ surfaceEvaluator.evalpoint2i( (long) mesh[1][0], (long) mesh[1][1] );
+ surfaceEvaluator.evalpoint2i( u, v );
+ surfaceEvaluator.endclosedline();
+ }
+ mesh[meshindex][0] = u;
+ mesh[meshindex][1] = v;
+ mesh[meshindex][2] = 1;
+ meshindex = (meshindex+1) % 2;
+ } else {
+ surfaceEvaluator.evalpoint2i( u, v );
+ }
+#else
+ surfaceEvaluator.evalpoint2i( u, v );
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * swaptmesh - perform a swap of the triangle mesh pointers
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::swaptmesh( void )
+{
+#ifndef NOWIREFRAME
+ if( wireframetris ) {
+ meshindex = 1 - meshindex;
+ } else {
+ surfaceEvaluator.swaptmesh();
+ }
+#else
+ surfaceEvaluator.swaptmesh();
+#endif
+}
+
+/*-------------------------------------------------------------------------
+ * endtmesh - postamble to triangle mesh
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endtmesh( void )
+{
+#ifndef NOWIREFRAME
+ if( ! wireframetris )
+ surfaceEvaluator.endtmesh();
+#else
+ surfaceEvaluator.endtmesh();
+/* surfaceEvaluator.polymode( N_MESHFILL );*/
+#endif
+}
+
+
+/*-------------------------------------------------------------------------
+ * bgnoutline - preamble to outlined rendering
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::bgnoutline( void )
+{
+ surfaceEvaluator.bgnline();
+}
+
+/*-------------------------------------------------------------------------
+ * linevert - evaluate a point on an outlined contour
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::linevert( TrimVertex *t )
+{
+ surfaceEvaluator.evalcoord2f( t->nuid, t->param[0], t->param[1] );
+}
+
+/*-------------------------------------------------------------------------
+ * linevert - evaluate a grid point of an outlined contour
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::linevert( GridVertex *g )
+{
+ surfaceEvaluator.evalpoint2i( g->gparam[0], g->gparam[1] );
+}
+
+/*-------------------------------------------------------------------------
+ * endoutline - postamble to outlined rendering
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::endoutline( void )
+{
+ surfaceEvaluator.endline();
+}
+
+/*-------------------------------------------------------------------------
+ * triangle - output a triangle
+ *-------------------------------------------------------------------------
+ */
+void
+Backend::triangle( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+/* bgntmesh( "spittriangle" );*/
+ bgntfan();
+ tmeshvert( a );
+ tmeshvert( b );
+ tmeshvert( c );
+ endtfan();
+/* endtmesh();*/
+}
+
+void
+Backend::bgncurv( void )
+{
+ curveEvaluator.bgnmap1f( 0 );
+}
+
+void
+Backend::segment( REAL ulo, REAL uhi )
+{
+ curveEvaluator.domain1f( ulo, uhi );
+}
+
+void
+Backend::curvpts(
+ long type, /* geometry, color, texture, normal */
+ REAL *pts, /* control points */
+ long stride, /* distance to next point */
+ int order, /* parametric order */
+ REAL ulo, /* lower parametric bound */
+ REAL uhi ) /* upper parametric bound */
+
+{
+ curveEvaluator.map1f( type, ulo, uhi, stride, order, pts );
+ curveEvaluator.enable( type );
+}
+
+void
+Backend::curvgrid( REAL u0, REAL u1, long nu )
+{
+ curveEvaluator.mapgrid1f( nu, u0, u1 );
+}
+
+void
+Backend::curvmesh( long from, long n )
+{
+ curveEvaluator.mapmesh1f( N_MESHFILL, from, from+n );
+}
+
+void
+Backend::curvpt(REAL u)
+{
+ curveEvaluator.evalcoord1f( 0, u );
+}
+
+void
+Backend::bgnline( void )
+{
+ curveEvaluator.bgnline();
+}
+
+void
+Backend::endline( void )
+{
+ curveEvaluator.endline();
+}
+
+void
+Backend::endcurv( void )
+{
+ curveEvaluator.endmap1f();
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/backend.h b/mesalib/src/glu/sgi/libnurbs/internals/backend.h
new file mode 100644
index 000000000..6840cb19e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/backend.h
@@ -0,0 +1,113 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * backend.h
+ *
+ */
+
+#ifndef __glubackend_h_
+#define __glubackend_h_
+
+#include "trimvertex.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+
+class BasicCurveEvaluator;
+class BasicSurfaceEvaluator;
+
+class Backend {
+private:
+ BasicCurveEvaluator& curveEvaluator;
+ BasicSurfaceEvaluator& surfaceEvaluator;
+public:
+ Backend( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e )
+ : curveEvaluator(c), surfaceEvaluator(e) {}
+
+ /* surface backend routines */
+ void bgnsurf( int, int, long );
+ void patch( REAL, REAL, REAL, REAL );
+ void surfpts( long, REAL *, long, long, int, int,
+ REAL, REAL, REAL, REAL );
+ void surfbbox( long, REAL *, REAL * );
+ void surfgrid( REAL, REAL, long, REAL, REAL, long );
+ void surfmesh( long, long, long, long );
+ void bgntmesh( const char * );
+ void endtmesh( void );
+ void swaptmesh( void );
+ void tmeshvert( GridTrimVertex * );
+ void tmeshvert( TrimVertex * );
+ void tmeshvert( GridVertex * );
+ void tmeshvert( REAL u, REAL v );
+ void linevert( TrimVertex * );
+ void linevert( GridVertex * );
+ void bgnoutline( void );
+ void endoutline( void );
+ void endsurf( void );
+ void triangle( TrimVertex*, TrimVertex*, TrimVertex* );
+
+ void bgntfan();
+ void endtfan();
+ void bgnqstrip();
+ void endqstrip();
+ void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ );
+ void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL v_right, REAL* right_val
+ );
+ void tmeshvertNOGE(TrimVertex *t);
+ void tmeshvertNOGE_BU(TrimVertex *t);
+ void tmeshvertNOGE_BV(TrimVertex *t);
+ void preEvaluateBU(REAL u);
+ void preEvaluateBV(REAL v);
+
+
+ /* curve backend routines */
+ void bgncurv( void );
+ void segment( REAL, REAL );
+ void curvpts( long, REAL *, long, int, REAL, REAL );
+ void curvgrid( REAL, REAL, long );
+ void curvmesh( long, long );
+ void curvpt( REAL );
+ void bgnline( void );
+ void endline( void );
+ void endcurv( void );
+private:
+#ifndef NOWIREFRAME
+ int wireframetris;
+ int wireframequads;
+ int npts;
+ REAL mesh[3][4];
+ int meshindex;
+#endif
+};
+
+#endif /* __glubackend_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.cc b/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.cc
new file mode 100644
index 000000000..cc473e4c2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.cc
@@ -0,0 +1,138 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basiccrveval.c++
+ *
+ */
+
+#include "mystdio.h"
+#include "types.h"
+#include "basiccrveval.h"
+
+void
+BasicCurveEvaluator::domain1f( REAL, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "domain1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::range1f( long , REAL *, REAL * )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "range1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::enable( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "enable\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::disable( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "disable\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::bgnmap1f( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnmap1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::map1f( long, REAL, REAL, long, long, REAL * )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "map1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::mapgrid1f( long, REAL, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "mapgrid1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::mapmesh1f( long, long, long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "mapmesh1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::evalcoord1f( long, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "evalcoord1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::endmap1f( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endmap1f\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::bgnline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnline\n" );
+#endif
+}
+
+void
+BasicCurveEvaluator::endline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endline\n" );
+#endif
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.h b/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.h
new file mode 100644
index 000000000..277dc8dc9
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/basiccrveval.h
@@ -0,0 +1,62 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * basiccurveeval.h
+ *
+ */
+
+#ifndef __glubasiccrveval_h_
+#define __glubasiccrveval_h_
+
+#include "types.h"
+#include "displaymode.h"
+#include "cachingeval.h"
+
+class BasicCurveEvaluator : public CachingEvaluator {
+public:
+ virtual ~BasicCurveEvaluator() { /* silence warning*/ }
+ virtual void domain1f( REAL, REAL );
+ virtual void range1f( long, REAL *, REAL * );
+
+ virtual void enable( long );
+ virtual void disable( long );
+ virtual void bgnmap1f( long );
+ virtual void map1f( long, REAL, REAL, long, long, REAL * );
+ virtual void mapgrid1f( long, REAL, REAL );
+ virtual void mapmesh1f( long, long, long );
+ virtual void evalcoord1f( long, REAL );
+ virtual void endmap1f( void );
+
+ virtual void bgnline( void );
+ virtual void endline( void );
+};
+
+#endif /* __glubasiccrveval_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.cc b/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.cc
new file mode 100644
index 000000000..fad5dd0ad
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.cc
@@ -0,0 +1,232 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * basicsurfaceevaluator.c++
+ *
+ */
+
+#include "mystdio.h"
+#include "types.h"
+#include "basicsurfeval.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+void
+BasicSurfaceEvaluator::domain2f( REAL, REAL, REAL, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "domain2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::polymode( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "polymode\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::range2f( long type, REAL *from, REAL *to )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "range2f type %ld, from (%g,%g), to (%g,%g)\n",
+ type, from[0], from[1], to[0], to[1] );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::enable( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "enable\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::disable( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "disable\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnmap2f( long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnmap2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endmap2f( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endmap2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long,
+ REAL * )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "map2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::mapgrid2f( long, REAL, REAL, long, REAL, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "mapgrid2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::mapmesh2f( long, long, long, long, long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "mapmesh2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::evalcoord2f( long, REAL, REAL )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "evalcoord2f\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::evalpoint2i( long, long )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "evalpoint2i\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnclosedline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnclosedline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endclosedline( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endclosedline\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgntfan( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgntfan\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endtfan( void )
+{
+}
+
+
+void
+BasicSurfaceEvaluator::bgntmesh( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgntmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::swaptmesh( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "swaptmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endtmesh( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endtmesh\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::bgnqstrip( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnqstrip\n" );
+#endif
+}
+
+void
+BasicSurfaceEvaluator::endqstrip( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endqstrip\n" );
+#endif
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.h b/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.h
new file mode 100644
index 000000000..8fe18a67f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/basicsurfeval.h
@@ -0,0 +1,90 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * basicsurfeval.h
+ *
+ */
+
+#ifndef __glubasicsurfeval_h_
+#define __glubasicsurfeval_h_
+
+#include "types.h"
+#include "displaymode.h"
+#include "cachingeval.h"
+
+class BasicSurfaceEvaluator : public CachingEvaluator {
+public:
+ virtual ~BasicSurfaceEvaluator() { /* silence warning*/ }
+ virtual void range2f( long, REAL *, REAL * );
+ virtual void domain2f( REAL, REAL, REAL, REAL );
+
+ virtual void enable( long );
+ virtual void disable( long );
+ virtual void bgnmap2f( long );
+ virtual void map2f( long, REAL, REAL, long, long,
+ REAL, REAL, long, long,
+ REAL * );
+ virtual void mapgrid2f( long, REAL, REAL, long, REAL, REAL );
+ virtual void mapmesh2f( long, long, long, long, long );
+ virtual void evalcoord2f( long, REAL, REAL );
+ virtual void evalpoint2i( long, long );
+ virtual void endmap2f( void );
+
+ virtual void polymode( long );
+ virtual void bgnline( void );
+ virtual void endline( void );
+ virtual void bgnclosedline( void );
+ virtual void endclosedline( void );
+ virtual void bgntmesh( void );
+ virtual void swaptmesh( void );
+ virtual void endtmesh( void );
+ virtual void bgnqstrip( void );
+ virtual void endqstrip( void );
+
+ virtual void bgntfan( void );
+ virtual void endtfan( void );
+
+ virtual void evalUStrip(int n_upper, REAL v_upper, REAL* upper_val,
+ int n_lower, REAL v_lower, REAL* lower_val
+ ) = 0;
+
+ virtual void evalVStrip(int n_left, REAL u_left, REAL* left_val,
+ int n_right, REAL u_right, REAL* right_val
+ ) = 0;
+ virtual void inDoEvalCoord2NOGE(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inDoEvalCoord2NOGE_BU(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inDoEvalCoord2NOGE_BV(REAL u, REAL v, REAL* ret_point, REAL* ret_normal) = 0;
+ virtual void inPreEvaluateBV_intfac(REAL v ) = 0;
+ virtual void inPreEvaluateBU_intfac(REAL u ) = 0;
+
+};
+
+#endif /* __glubasicsurfeval_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/bezierarc.h b/mesalib/src/glu/sgi/libnurbs/internals/bezierarc.h
new file mode 100644
index 000000000..4acfb0948
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/bezierarc.h
@@ -0,0 +1,51 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * bezierarc.h
+ *
+ */
+
+#ifndef __glubezierarc_h
+#define __glubezierarc_h
+
+#include "myassert.h"
+
+class Mapdesc;
+
+struct BezierArc : public PooledObj { /* a bezier arc */
+ REAL * cpts; /* control points of arc */
+ int order; /* order of arc */
+ int stride; /* REAL distance between points */
+ long type; /* curve type */
+ Mapdesc * mapdesc;
+};
+
+#endif /* __glubezierarc_h */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/bin.cc b/mesalib/src/glu/sgi/libnurbs/internals/bin.cc
new file mode 100644
index 000000000..54b406147
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/bin.cc
@@ -0,0 +1,166 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bin.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "bin.h"
+
+/*----------------------------------------------------------------------------
+ * Constructor and destructor
+ *----------------------------------------------------------------------------
+ */
+Bin::Bin()
+{
+ head = NULL;
+}
+
+Bin::~Bin()
+{
+ assert( head == NULL);
+}
+
+/*----------------------------------------------------------------------------
+ * remove_this_arc - remove given Arc_ptr from bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::remove_this_arc( Arc_ptr arc )
+{
+ Arc_ptr *j;
+ for( j = &(head); (*j != 0) && (*j != arc); j = &((*j)->link) );
+
+ if( *j != 0 ) {
+ if( *j == current )
+ current = (*j)->link;
+ *j = (*j)->link;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * numarcs - count number of arcs in bin
+ *----------------------------------------------------------------------------
+ */
+
+int
+Bin::numarcs()
+{
+ long count = 0;
+ for( Arc_ptr jarc = firstarc(); jarc; jarc = nextarc() )
+ count++;
+ return count;
+}
+
+/*----------------------------------------------------------------------------
+ * adopt - place an orphaned arcs into their new parents bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::adopt()
+{
+ markall();
+
+ Arc_ptr orphan;
+ while( (orphan = removearc()) != NULL ) {
+ for( Arc_ptr parent = orphan->next; parent != orphan; parent = parent->next ) {
+ if (! parent->ismarked() ) {
+ orphan->link = parent->link;
+ parent->link = orphan;
+ orphan->clearmark();
+ break;
+ }
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * show - print out descriptions of the arcs in the bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::show( char *name )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "%s\n", name );
+ for( Arc_ptr jarc = firstarc(); jarc; jarc = nextarc() )
+ jarc->show( );
+#endif
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * markall - mark all arcs with an identifying tag
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::markall()
+{
+ for( Arc_ptr jarc=firstarc(); jarc; jarc=nextarc() )
+ jarc->setmark();
+}
+
+/*----------------------------------------------------------------------------
+ * listBezier - print out all arcs that are untessellated border arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Bin::listBezier( void )
+{
+ for( Arc_ptr jarc=firstarc(); jarc; jarc=nextarc() ) {
+ if( jarc->isbezier( ) ) {
+ assert( jarc->pwlArc->npts == 2 );
+#ifndef NDEBUG
+ TrimVertex *pts = jarc->pwlArc->pts;
+ REAL s1 = pts[0].param[0];
+ REAL t1 = pts[0].param[1];
+ REAL s2 = pts[1].param[0];
+ REAL t2 = pts[1].param[1];
+ _glu_dprintf( "arc (%g,%g) (%g,%g)\n", s1, t1, s2, t2 );
+#endif
+ }
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/bin.h b/mesalib/src/glu/sgi/libnurbs/internals/bin.h
new file mode 100644
index 000000000..2f976eb9b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/bin.h
@@ -0,0 +1,121 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * bin.h
+ *
+ */
+
+#ifndef __glubin_h_
+#define __glubin_h_
+
+#include "myassert.h"
+#include "arc.h"
+#include "defines.h"
+
+class Bin
+{ /* a linked list of jordan arcs */
+private:
+ Arc_ptr head;/*first arc on list */
+ Arc_ptr current; /* current arc on list */
+public:
+ Bin();
+ ~Bin();
+ inline Arc_ptr firstarc( void );
+ inline Arc_ptr nextarc( void );
+ inline Arc_ptr removearc( void );
+ inline int isnonempty( void ) { return (head ? 1 : 0); }
+ inline void addarc( Arc_ptr );
+ void remove_this_arc( Arc_ptr );
+ int numarcs( void );
+ void adopt( void );
+ void markall( void );
+ void show( char * );
+ void listBezier( void );
+};
+
+/*----------------------------------------------------------------------------
+ * Bin::addarc - add an Arc_ptr to head of linked list of Arc_ptr
+ *----------------------------------------------------------------------------
+ */
+
+inline void
+Bin::addarc( Arc_ptr jarc )
+{
+ jarc->link = head;
+ head = jarc;
+}
+
+/*----------------------------------------------------------------------------
+ * Bin::removearc - remove first Arc_ptr from bin
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::removearc( void )
+{
+ Arc_ptr jarc = head;
+
+ if( jarc ) head = jarc->link;
+ return jarc;
+}
+
+
+/*----------------------------------------------------------------------------
+ * BinIter::nextarc - return current arc in bin and advance pointer to next arc
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::nextarc( void )
+{
+ Arc_ptr jarc = current;
+
+#ifdef DEBUG
+ assert( jarc->check() != 0 );
+#endif
+
+ if( jarc ) current = jarc->link;
+ return jarc;
+}
+
+/*----------------------------------------------------------------------------
+ * BinIter::firstarc - set current arc to first arc of bin advance to next arc
+ *----------------------------------------------------------------------------
+ */
+
+inline Arc_ptr
+Bin::firstarc( void )
+{
+ current = head;
+ return nextarc( );
+}
+
+#endif /* __glubin_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/bufpool.cc b/mesalib/src/glu/sgi/libnurbs/internals/bufpool.cc
new file mode 100644
index 000000000..8cc847ab2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/bufpool.cc
@@ -0,0 +1,110 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * bufpool.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "bufpool.h"
+
+
+/*-----------------------------------------------------------------------------
+ * Pool - allocate a new pool of buffers
+ *-----------------------------------------------------------------------------
+ */
+Pool::Pool( int _buffersize, int initpoolsize, const char *n )
+{
+ if((unsigned)_buffersize < sizeof(Buffer))
+ buffersize = sizeof(Buffer);
+ else
+ buffersize = _buffersize;
+ initsize = initpoolsize * buffersize;
+ nextsize = initsize;
+ name = n;
+ magic = is_allocated;
+ nextblock = 0;
+ curblock = 0;
+ freelist = 0;
+ nextfree = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * ~Pool - free a pool of buffers and the pool itself
+ *-----------------------------------------------------------------------------
+ */
+
+Pool::~Pool( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ while( nextblock ) {
+ delete [] blocklist[--nextblock];
+ blocklist[nextblock] = 0;
+ }
+ magic = is_free;
+}
+
+
+void Pool::grow( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+ curblock = new char[nextsize];
+ blocklist[nextblock++] = curblock;
+ nextfree = nextsize;
+ nextsize *= 2;
+}
+
+/*-----------------------------------------------------------------------------
+ * Pool::clear - free buffers associated with pool but keep pool
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Pool::clear( void )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ while( nextblock ) {
+ delete [] blocklist[--nextblock];
+ blocklist[nextblock] = 0;
+ }
+ curblock = 0;
+ freelist = 0;
+ nextfree = 0;
+ if( nextsize > initsize )
+ nextsize /= 2;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/bufpool.h b/mesalib/src/glu/sgi/libnurbs/internals/bufpool.h
new file mode 100644
index 000000000..0fa943375
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/bufpool.h
@@ -0,0 +1,141 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * bufpool.h
+ *
+ */
+
+#ifndef __glubufpool_h_
+#define __glubufpool_h_
+
+#include "gluos.h"
+#include "myassert.h"
+#include "mystdlib.h"
+
+#define NBLOCKS 32
+
+class Buffer {
+ friend class Pool;
+ Buffer * next; /* next buffer on free list */
+};
+
+class Pool {
+public:
+ Pool( int, int, const char * );
+ ~Pool( void );
+ inline void* new_buffer( void );
+ inline void free_buffer( void * );
+ void clear( void );
+
+private:
+ void grow( void );
+
+protected:
+ Buffer *freelist; /* linked list of free buffers */
+ char *blocklist[NBLOCKS]; /* blocks of malloced memory */
+ int nextblock; /* next free block index */
+ char *curblock; /* last malloced block */
+ int buffersize; /* bytes per buffer */
+ int nextsize; /* size of next block of memory */
+ int nextfree; /* byte offset past next free buffer */
+ int initsize;
+ enum Magic { is_allocated = 0xf3a1, is_free = 0xf1a2 };
+ const char *name; /* name of the pool */
+ Magic magic; /* marker for valid pool */
+};
+
+/*-----------------------------------------------------------------------------
+ * Pool::free_buffer - return a buffer to a pool
+ *-----------------------------------------------------------------------------
+ */
+
+inline void
+Pool::free_buffer( void *b )
+{
+ assert( (this != 0) && (magic == is_allocated) );
+
+ /* add buffer to singly connected free list */
+
+ ((Buffer *) b)->next = freelist;
+ freelist = (Buffer *) b;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Pool::new_buffer - allocate a buffer from a pool
+ *-----------------------------------------------------------------------------
+ */
+
+inline void *
+Pool::new_buffer( void )
+{
+ void *buffer;
+
+ assert( (this != 0) && (magic == is_allocated) );
+
+ /* find free buffer */
+
+ if( freelist ) {
+ buffer = (void *) freelist;
+ freelist = freelist->next;
+ } else {
+ if( ! nextfree )
+ grow( );
+ nextfree -= buffersize;;
+ buffer = (void *) (curblock + nextfree);
+ }
+ return buffer;
+}
+
+class PooledObj {
+public:
+ inline void * operator new( size_t, Pool & );
+ inline void * operator new( size_t, void *);
+ inline void * operator new( size_t s)
+ { return ::new char[s]; }
+ inline void operator delete( void * ) { assert( 0 ); }
+ inline void operator delete( void *, Pool & ) { assert( 0 ); }
+ inline void deleteMe( Pool & );
+};
+
+inline void *
+PooledObj::operator new( size_t, Pool& pool )
+{
+ return pool.new_buffer();
+}
+
+inline void
+PooledObj::deleteMe( Pool& pool )
+{
+ pool.free_buffer( (void *) this );
+}
+
+#endif /* __glubufpool_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.cc b/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.cc
new file mode 100644
index 000000000..3fab38c10
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.cc
@@ -0,0 +1,78 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * cachingeval.c++
+ *
+ */
+
+#include "cachingeval.h"
+
+int
+CachingEvaluator::canRecord( void )
+{
+ return 0;
+}
+
+int
+CachingEvaluator::canPlayAndRecord( void )
+{
+ return 0;
+}
+
+int
+CachingEvaluator::createHandle( int )
+{
+ return 0;
+}
+
+void
+CachingEvaluator::beginOutput( ServiceMode, int )
+{
+}
+
+void
+CachingEvaluator::endOutput( void )
+{
+}
+
+void
+CachingEvaluator::discardRecording( int )
+{
+}
+
+void
+CachingEvaluator::playRecording( int )
+{
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.h b/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.h
new file mode 100644
index 000000000..b390067a2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/cachingeval.h
@@ -0,0 +1,51 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * cachingeval.h
+ *
+ */
+
+#ifndef __glucachingval_h_
+#define __glucachingval_h_
+
+class CachingEvaluator {
+public:
+ virtual ~CachingEvaluator() { /* silence warning*/ }
+ enum ServiceMode { play, record, playAndRecord };
+ virtual int canRecord( void );
+ virtual int canPlayAndRecord( void );
+ virtual int createHandle( int handle );
+ virtual void beginOutput( ServiceMode, int handle );
+ virtual void endOutput( void );
+ virtual void discardRecording( int handle );
+ virtual void playRecording( int handle );
+};
+#endif /* __glucachingval_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/ccw.cc b/mesalib/src/glu/sgi/libnurbs/internals/ccw.cc
new file mode 100644
index 000000000..eb01b7781
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/ccw.cc
@@ -0,0 +1,565 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * ccw.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "subdivider.h"
+#include "types.h"
+#include "arc.h"
+#include "trimvertex.h"
+#include "simplemath.h"
+
+inline int
+Subdivider::bbox( TrimVertex *a, TrimVertex *b, TrimVertex *c, int p )
+{
+ return bbox( a->param[p], b->param[p], c->param[p],
+ a->param[1-p], b->param[1-p], c->param[1-p] );
+}
+
+int
+Subdivider::ccwTurn_sr( Arc_ptr j1, Arc_ptr j2 ) // dir = 1
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ _glu_dprintf( "arc_ccw_turn, p = %d\n", 0 );
+#endif
+
+ // the arcs lie on the line (0 == v1->param[0])
+ if( v1->param[0] == v1next->param[0] && v2->param[0] == v2next->param[0] )
+ return 0;
+
+ if( v2next->param[0] < v2->param[0] || v1next->param[0] < v1->param[0] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[1] < v2->param[1] )
+ return 0;
+ else if( v1->param[1] > v2->param[1] )
+ return 1;
+
+ while( 1 ) {
+ if( v1next->param[0] < v2next->param[0] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case a\n" );
+#endif
+ assert( v1->param[0] <= v1next->param[0] );
+ assert( v2->param[0] <= v1next->param[0] );
+ switch( bbox( v2, v2next, v1next, 1 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "decr\n" );
+#endif
+ v1 = v1next--;
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next->param[0] > v2next->param[0] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case b\n" );
+#endif
+ assert( v1->param[0] <= v2next->param[0] );
+ assert( v2->param[0] <= v2next->param[0] );
+ switch( bbox( v1, v1next, v2next, 1 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+#ifndef NDEBUG
+ _glu_dprintf( "case ab\n" );
+#endif
+ if( v1next->param[1] < v2next->param[1] )
+ return 0;
+ else if( v1next->param[1] > v2next->param[1] )
+ return 1;
+ else {
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_sl( Arc_ptr j1, Arc_ptr j2 ) // dir = 0
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ _glu_dprintf( "arc_ccw_turn, p = %d\n", 0 );
+#endif
+
+ // the arcs lie on the line (0 == v1->param[0])
+ if( v1->param[0] == v1next->param[0] && v2->param[0] == v2next->param[0] )
+ return 0;
+
+ if( v2next->param[0] > v2->param[0] || v1next->param[0] > v1->param[0] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[1] < v2->param[1] )
+ return 1;
+ else if( v1->param[1] > v2->param[1] )
+ return 0;
+
+ while( 1 ) {
+ if( v1next->param[0] > v2next->param[0] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case c\n" );
+#endif
+ assert( v1->param[0] >= v1next->param[0] );
+ assert( v2->param[0] >= v1next->param[0] );
+ switch( bbox( v2next, v2, v1next, 1 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v1 = v1next--;
+#ifdef DEBUG
+ _glu_dprintf( "decr\n" );
+#endif
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next->param[0] < v2next->param[0] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case d\n" );
+#endif
+ assert( v1->param[0] >= v2next->param[0] );
+ assert( v2->param[0] >= v2next->param[0] );
+ switch( bbox( v1next, v1, v2next, 1 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "case cd\n" );
+#endif
+ if( v1next->param[1] < v2next->param[1] )
+ return 1;
+ else if( v1next->param[1] > v2next->param[1] )
+ return 0;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_tr( Arc_ptr j1, Arc_ptr j2 ) // dir = 1
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ _glu_dprintf( "arc_ccw_turn, p = %d\n", 1 );
+#endif
+
+ // the arcs lie on the line (1 == v1->param[1])
+ if( v1->param[1] == v1next->param[1] && v2->param[1] == v2next->param[1] )
+ return 0;
+
+ if( v2next->param[1] < v2->param[1] || v1next->param[1] < v1->param[1] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[0] < v2->param[0] )
+ return 1;
+ else if( v1->param[0] > v2->param[0] )
+ return 0;
+
+ while( 1 ) {
+ if( v1next->param[1] < v2next->param[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case a\n" );
+#endif
+ assert( v1->param[1] <= v1next->param[1] );
+ assert( v2->param[1] <= v1next->param[1] );
+ switch( bbox( v2, v2next, v1next, 0 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "decr\n" );
+#endif
+ v1 = v1next--;
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else if( v1next->param[1] > v2next->param[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case b\n" );
+#endif
+ assert( v1->param[1] <= v2next->param[1] );
+ assert( v2->param[1] <= v2next->param[1] );
+ switch( bbox( v1, v1next, v2next, 0 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 ) {
+ return sgn;
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "case ab\n" );
+#endif
+ if( v1next->param[0] < v2next->param[0] )
+ return 1;
+ else if( v1next->param[0] > v2next->param[0] )
+ return 0;
+ else {
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ v2 = v2next++;
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+int
+Subdivider::ccwTurn_tl( Arc_ptr j1, Arc_ptr j2 )
+{
+ register TrimVertex *v1 = &j1->pwlArc->pts[j1->pwlArc->npts-1];
+ register TrimVertex *v1last = &j1->pwlArc->pts[0];
+ register TrimVertex *v2 = &j2->pwlArc->pts[0];
+ register TrimVertex *v2last = &j2->pwlArc->pts[j2->pwlArc->npts-1];
+ register TrimVertex *v1next = v1-1;
+ register TrimVertex *v2next = v2+1;
+ int sgn;
+
+ assert( v1 != v1last );
+ assert( v2 != v2last );
+
+#ifndef NDEBUG
+ _glu_dprintf( "arc_ccw_turn, p = %d\n", 1 );
+#endif
+
+ // the arcs lie on the line (1 == v1->param[1])
+ if( v1->param[1] == v1next->param[1] && v2->param[1] == v2next->param[1] )
+ return 0;
+
+ if( v2next->param[1] > v2->param[1] || v1next->param[1] > v1->param[1] )
+ ::mylongjmp( jumpbuffer, 28 );
+
+ if( v1->param[0] < v2->param[0] )
+ return 0;
+ else if( v1->param[0] > v2->param[0] )
+ return 1;
+
+ while( 1 ) {
+ if( v1next->param[1] > v2next->param[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case c\n" );
+#endif
+ assert( v1->param[1] >= v1next->param[1] );
+ assert( v2->param[1] >= v1next->param[1] );
+ switch( bbox( v2next, v2, v1next, 0 ) ) {
+ case -1:
+ return 0;
+ case 0:
+ sgn = ccw( v1next, v2, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v1 = v1next--;
+#ifdef DEBUG
+ _glu_dprintf( "decr\n" );
+#endif
+ if( v1 == v1last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 1;
+ }
+ } else if( v1next->param[1] < v2next->param[1] ) {
+#ifndef NDEBUG
+ _glu_dprintf( "case d\n" );
+ assert( v1->param[1] >= v2next->param[1] );
+ assert( v2->param[1] >= v2next->param[1] );
+#endif
+ switch( bbox( v1next, v1, v2next, 0 ) ) {
+ case -1:
+ return 1;
+ case 0:
+ sgn = ccw( v1next, v1, v2next );
+ if( sgn != -1 )
+ return sgn;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ break;
+ case 1:
+ return 0;
+ }
+ } else {
+#ifdef DEBUG
+ _glu_dprintf( "case cd\n" );
+#endif
+ if( v1next->param[0] < v2next->param[0] )
+ return 0;
+ else if( v1next->param[0] > v2next->param[0] )
+ return 1;
+ else {
+ v2 = v2next++;
+#ifdef DEBUG
+ _glu_dprintf( "incr\n" );
+#endif
+ if( v2 == v2last ) {
+#ifdef DEBUG
+ _glu_dprintf( "no good results\n" );
+#endif
+ return 0; // ill-conditioned, guess answer
+ }
+ }
+ }
+ }
+}
+
+
+#ifndef NDEBUG
+int
+Subdivider::bbox( register REAL sa, register REAL sb, register REAL sc,
+ register REAL ta, register REAL tb, register REAL tc )
+#else
+int
+Subdivider::bbox( register REAL sa, register REAL sb, register REAL sc,
+ register REAL , register REAL , register REAL )
+#endif
+{
+#ifndef NDEBUG
+ assert( tc >= ta );
+ assert( tc <= tb );
+#endif
+
+ if( sa < sb ) {
+ if( sc <= sa ) {
+ return -1;
+ } else if( sb <= sc ) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else if( sa > sb ) {
+ if( sc >= sa ) {
+ return 1;
+ } else if( sb >= sc ) {
+ return -1;
+ } else {
+ return 0;
+ }
+ } else {
+ if( sc > sa ) {
+ return 1;
+ } else if( sb > sc ) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * ccw - determine how three points are oriented by computing their
+ * determinant.
+ * Return 1 if the vertices are ccw oriented,
+ * 0 if they are cw oriented, or
+ * -1 if the computation is ill-conditioned.
+ *----------------------------------------------------------------------------
+ */
+int
+Subdivider::ccw( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+ REAL d = det3( a, b, c );
+ if( glu_abs(d) < 0.0001 ) return -1;
+ return (d < 0.0) ? 0 : 1;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.cc b/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.cc
new file mode 100644
index 000000000..ca5bf36b3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.cc
@@ -0,0 +1,440 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * coveandtiler.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "coveandtiler.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "uarray.h"
+#include "backend.h"
+
+
+const int CoveAndTiler::MAXSTRIPSIZE = 1000;
+
+CoveAndTiler::CoveAndTiler( Backend& b )
+ : backend( b )
+{ }
+
+CoveAndTiler::~CoveAndTiler( void )
+{ }
+
+inline void
+CoveAndTiler::output( GridVertex &gv )
+{
+ backend.tmeshvert( &gv );
+}
+
+inline void
+CoveAndTiler::output( TrimVertex *tv )
+{
+ backend.tmeshvert( tv );
+}
+
+inline void
+CoveAndTiler::output( GridTrimVertex& g )
+{
+ backend.tmeshvert( &g );
+}
+
+void
+CoveAndTiler::coveAndTile( void )
+{
+ long ustart = (top.ustart >= bot.ustart) ? top.ustart : bot.ustart;
+ long uend = (top.uend <= bot.uend) ? top.uend : bot.uend;
+ if( ustart <= uend ) {
+ tile( bot.vindex, ustart, uend );
+ if( top.ustart >= bot.ustart )
+ coveUpperLeft();
+ else
+ coveLowerLeft();
+
+ if( top.uend <= bot.uend )
+ coveUpperRight();
+ else
+ coveLowerRight();
+ } else {
+ TrimVertex blv, tlv, *bl, *tl;
+ GridTrimVertex bllv, tllv;
+ TrimVertex *lf = left.first();
+ TrimVertex *ll = left.last();
+ if( lf->param[0] >= ll->param[0] ) {
+ blv.param[0] = lf->param[0];
+ blv.param[1] = ll->param[1];
+ blv.nuid = 0; // XXX
+ assert( blv.param[1] == bot.vval );
+ bl = &blv;
+ tl = lf;
+ tllv.set( lf );
+ if( ll->param[0] > uarray.uarray[top.ustart-1] ) {
+ bllv.set( ll );
+ assert( ll->param[0] <= uarray.uarray[bot.ustart] );
+ } else {
+ bllv.set( top.ustart-1, bot.vindex );
+ }
+ coveUpperLeftNoGrid( bl );
+ } else {
+ tlv.param[0] = ll->param[0];
+ tlv.param[1] = lf->param[1];
+ tlv.nuid = 0; // XXX
+ assert( tlv.param[1] == top.vval );
+ tl = &tlv;
+ bl = ll;
+ bllv.set( ll );
+ if( lf->param[0] > uarray.uarray[bot.ustart-1] ) {
+ assert( lf->param[0] <= uarray.uarray[bot.ustart] );
+ tllv.set( lf );
+ } else {
+ tllv.set( bot.ustart-1, top.vindex );
+ }
+ coveLowerLeftNoGrid( tl );
+ }
+
+ TrimVertex brv, trv, *br, *tr;
+ GridTrimVertex brrv, trrv;
+ TrimVertex *rf = right.first();
+ TrimVertex *rl = right.last();
+
+ if( rf->param[0] <= rl->param[0] ) {
+ brv.param[0] = rf->param[0];
+ brv.param[1] = rl->param[1];
+ brv.nuid = 0; // XXX
+ assert( brv.param[1] == bot.vval );
+ br = &brv;
+ tr = rf;
+ trrv.set( rf );
+ if( rl->param[0] < uarray.uarray[top.uend+1] ) {
+ assert( rl->param[0] >= uarray.uarray[top.uend] );
+ brrv.set( rl );
+ } else {
+ brrv.set( top.uend+1, bot.vindex );
+ }
+ coveUpperRightNoGrid( br );
+ } else {
+ trv.param[0] = rl->param[0];
+ trv.param[1] = rf->param[1];
+ trv.nuid = 0; // XXX
+ assert( trv.param[1] == top.vval );
+ tr = &trv;
+ br = rl;
+ brrv.set( rl );
+ if( rf->param[0] < uarray.uarray[bot.uend+1] ) {
+ assert( rf->param[0] >= uarray.uarray[bot.uend] );
+ trrv.set( rf );
+ } else {
+ trrv.set( bot.uend+1, top.vindex );
+ }
+ coveLowerRightNoGrid( tr );
+ }
+
+ backend.bgntmesh( "doit" );
+ output(trrv);
+ output(tllv);
+ output( tr );
+ output( tl );
+ output( br );
+ output( bl );
+ output(brrv);
+ output(bllv);
+ backend.endtmesh();
+ }
+}
+
+void
+CoveAndTiler::tile( long vindex, long ustart, long uend )
+{
+ long numsteps = uend - ustart;
+
+ if( numsteps == 0 ) return;
+
+ if( numsteps > MAXSTRIPSIZE ) {
+ long umid = ustart + (uend - ustart) / 2;
+ tile( vindex, ustart, umid );
+ tile( vindex, umid, uend );
+ } else {
+ backend.surfmesh( ustart, vindex-1, numsteps, 1 );
+ }
+}
+
+void
+CoveAndTiler::coveUpperRight( void )
+{
+ GridVertex tgv( top.uend, top.vindex );
+ GridVertex gv( top.uend, bot.vindex );
+
+ right.first();
+ backend.bgntmesh( "coveUpperRight" );
+ output( right.next() );
+ output( tgv );
+ backend.swaptmesh();
+ output( gv );
+ coveUR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUpperRightNoGrid( TrimVertex* br )
+{
+ backend.bgntmesh( "coveUpperRight" );
+ output( right.first() );
+ output( right.next() );
+ backend.swaptmesh();
+ output( br );
+ coveUR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUR( )
+{
+ GridVertex gv( top.uend, bot.vindex );
+ TrimVertex *vert = right.next();
+ if( vert == NULL ) return;
+
+ assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.nextu() >= bot.uend ) {
+ for( ; vert; vert = right.next() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ } else while( 1 ) {
+ if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
+ output( vert );
+ backend.swaptmesh();
+ vert = right.next();
+ if( vert == NULL ) break;
+ } else {
+ backend.swaptmesh();
+ output( gv );
+ if( gv.nextu() == bot.uend ) {
+ for( ; vert; vert = right.next() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveUpperLeft( void )
+{
+ GridVertex tgv( top.ustart, top.vindex );
+ GridVertex gv( top.ustart, bot.vindex );
+
+ left.first();
+ backend.bgntmesh( "coveUpperLeft" );
+ output( tgv );
+ output( left.next() );
+ output( gv );
+ backend.swaptmesh();
+ coveUL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUpperLeftNoGrid( TrimVertex* bl )
+{
+ backend.bgntmesh( "coveUpperLeftNoGrid" );
+ output( left.first() );
+ output( left.next() );
+ output( bl );
+ backend.swaptmesh();
+ coveUL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveUL()
+{
+ GridVertex gv( top.ustart, bot.vindex );
+ TrimVertex *vert = left.next();
+ if( vert == NULL ) return;
+ assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.prevu() <= bot.ustart ) {
+ for( ; vert; vert = left.next() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ } else while( 1 ) {
+ if( vert->param[0] > uarray.uarray[gv.gparam[0]] ) {
+ backend.swaptmesh();
+ output( vert );
+ vert = left.next();
+ if( vert == NULL ) break;
+ } else {
+ output( gv );
+ backend.swaptmesh();
+ if( gv.prevu() == bot.ustart ) {
+ for( ; vert; vert = left.next() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveLowerLeft( void )
+{
+ GridVertex bgv( bot.ustart, bot.vindex );
+ GridVertex gv( bot.ustart, top.vindex );
+
+ left.last();
+ backend.bgntmesh( "coveLowerLeft" );
+ output( left.prev() );
+ output( bgv );
+ backend.swaptmesh();
+ output( gv );
+ coveLL();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLowerLeftNoGrid( TrimVertex* tl )
+{
+ backend.bgntmesh( "coveLowerLeft" );
+ output( left.last() );
+ output( left.prev() );
+ backend.swaptmesh();
+ output( tl );
+ coveLL( );
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLL()
+{
+ GridVertex gv( bot.ustart, top.vindex );
+ TrimVertex *vert = left.prev();
+ if( vert == NULL ) return;
+ assert( vert->param[0] <= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.prevu() <= top.ustart ) {
+ for( ; vert; vert = left.prev() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ } else while( 1 ) {
+ if( vert->param[0] > uarray.uarray[gv.gparam[0]] ){
+ output( vert );
+ backend.swaptmesh();
+ vert = left.prev();
+ if( vert == NULL ) break;
+ } else {
+ backend.swaptmesh();
+ output( gv );
+ if( gv.prevu() == top.ustart ) {
+ for( ; vert; vert = left.prev() ) {
+ output( vert );
+ backend.swaptmesh();
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+CoveAndTiler::coveLowerRight( void )
+{
+ GridVertex bgv( bot.uend, bot.vindex );
+ GridVertex gv( bot.uend, top.vindex );
+
+ right.last();
+ backend.bgntmesh( "coveLowerRight" );
+ output( bgv );
+ output( right.prev() );
+ output( gv );
+ backend.swaptmesh();
+ coveLR();
+ backend.endtmesh( );
+}
+
+void
+CoveAndTiler::coveLowerRightNoGrid( TrimVertex* tr )
+{
+ backend.bgntmesh( "coveLowerRIght" );
+ output( right.last() );
+ output( right.prev() );
+ output( tr );
+ backend.swaptmesh();
+ coveLR();
+ backend.endtmesh();
+}
+
+void
+CoveAndTiler::coveLR( )
+{
+ GridVertex gv( bot.uend, top.vindex );
+ TrimVertex *vert = right.prev();
+ if( vert == NULL ) return;
+ assert( vert->param[0] >= uarray.uarray[gv.gparam[0]] );
+
+ if( gv.nextu() >= top.uend ) {
+ for( ; vert; vert = right.prev() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ } else while( 1 ) {
+ if( vert->param[0] < uarray.uarray[gv.gparam[0]] ) {
+ backend.swaptmesh();
+ output( vert );
+ vert = right.prev();
+ if( vert == NULL ) break;
+ } else {
+ output( gv );
+ backend.swaptmesh();
+ if( gv.nextu() == top.uend ) {
+ for( ; vert; vert = right.prev() ) {
+ backend.swaptmesh();
+ output( vert );
+ }
+ break;
+ }
+ }
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.h b/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.h
new file mode 100644
index 000000000..d454202e6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/coveandtiler.h
@@ -0,0 +1,72 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * coveandtiler.h
+ *
+ */
+
+#ifndef __glucoveandtiler_h
+#define __glucoveandtiler_h
+
+#include "trimregion.h"
+#include "trimvertex.h"
+#include "gridvertex.h"
+
+class Backend;
+class GridTrimVertex;
+
+class CoveAndTiler : virtual public TrimRegion {
+public:
+ CoveAndTiler( Backend& );
+ ~CoveAndTiler( void );
+ void coveAndTile( void );
+private:
+ Backend& backend;
+ static const int MAXSTRIPSIZE;
+ void tile( long, long, long );
+ void coveLowerLeft( void );
+ void coveLowerRight( void );
+ void coveUpperLeft( void );
+ void coveUpperRight( void );
+ void coveUpperLeftNoGrid( TrimVertex * );
+ void coveUpperRightNoGrid( TrimVertex * );
+ void coveLowerLeftNoGrid( TrimVertex * );
+ void coveLowerRightNoGrid( TrimVertex * );
+ void coveLL( void );
+ void coveLR( void );
+ void coveUL( void );
+ void coveUR( void );
+ inline void output( GridTrimVertex& );
+ inline void output( GridVertex& );
+ inline void output( TrimVertex* );
+};
+
+#endif /* __glucoveandtiler_h */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/curve.cc b/mesalib/src/glu/sgi/libnurbs/internals/curve.cc
new file mode 100644
index 000000000..33e275264
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/curve.cc
@@ -0,0 +1,198 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curve.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mymath.h"
+#include "curve.h"
+#include "mapdesc.h"
+#include "types.h"
+#include "quilt.h"
+#include "nurbsconsts.h"
+
+/*--------------------------------------------------------------------------
+ * Curve::Curve - copy curve from quilt and transform control points
+ *--------------------------------------------------------------------------
+ */
+
+Curve::Curve( Quilt_ptr geo, REAL pta, REAL ptb, Curve *c )
+{
+ mapdesc = geo->mapdesc;
+ next = c;
+ needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
+ cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
+ order = geo->qspec[0].order;
+ stride = MAXCOORDS;
+
+ REAL *ps = geo->cpts;
+ Quiltspec_ptr qs = geo->qspec;
+ ps += qs->offset;
+ ps += qs->index * qs->order * qs->stride;
+
+ if( needsSampling )
+ mapdesc->xformSampling( ps, qs->order, qs->stride, spts, stride );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->xformCulling( ps, qs->order, qs->stride, cpts, stride );
+
+ /* set untrimmed curve range */
+ range[0] = qs->breakpoints[qs->index];
+ range[1] = qs->breakpoints[qs->index+1];
+ range[2] = range[1] - range[0];
+
+ if( range[0] != pta ) {
+ Curve lower( *this, pta, 0 );
+ lower.next = next;
+ *this = lower;
+ }
+ if( range[1] != ptb ) {
+ Curve lower( *this, ptb, 0 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Curve::Curve - subdivide a curve along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+Curve::Curve( Curve& upper, REAL value, Curve *c )
+{
+ Curve &lower = *this;
+
+ lower.next = c;
+ lower.mapdesc = upper.mapdesc;
+ lower.needsSampling = upper.needsSampling;
+ lower.order = upper.order;
+ lower.stride = upper.stride;
+ lower.cullval = upper.cullval;
+
+ REAL d = (value - upper.range[0]) / upper.range[2];
+
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, upper.stride, upper.order );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, upper.stride, upper.order );
+
+ lower.range[0] = upper.range[0];
+ lower.range[1] = value;
+ lower.range[2] = value - upper.range[0];
+ upper.range[0] = value;
+ upper.range[2] = upper.range[1] - value;
+}
+
+
+/*--------------------------------------------------------------------------
+ * Curve::clamp - clamp the sampling rate to a given maximum
+ *--------------------------------------------------------------------------
+ */
+
+void
+Curve::clamp( void )
+{
+ if( stepsize < minstepsize )
+ stepsize = mapdesc->clampfactor * minstepsize;
+}
+
+void
+Curve::setstepsize( REAL max )
+{
+ stepsize = ( max >= 1.0 ) ? (range[2] / max) : range[2];
+ minstepsize = stepsize;
+}
+
+void
+Curve::getstepsize( void )
+{
+ minstepsize= 0;
+
+ if( mapdesc->isConstantSampling() ) {
+ // fixed number of samples per patch in each direction
+ // maxrate is number of s samples per patch
+ setstepsize( mapdesc->maxrate );
+ } else if( mapdesc->isDomainSampling() ) {
+ // maxrate is number of s samples per unit s length of domain
+ setstepsize( mapdesc->maxrate * range[2] );
+ } else {
+ // upper bound on path length between sample points
+
+ assert( order <= MAXORDER );
+
+ /* points have been transformed, therefore they are homogeneous */
+ REAL tmp[MAXORDER][MAXCOORDS];
+ const int tstride = sizeof(tmp[0]) / sizeof(REAL);
+ int val = mapdesc->project( spts, stride, &tmp[0][0], tstride, order );
+
+ if( val == 0 ) {
+ // control points cross infinity, therefore derivatives are undefined
+ setstepsize( mapdesc->maxrate );
+ } else {
+ REAL t = mapdesc->getProperty( N_PIXEL_TOLERANCE );
+ if( mapdesc->isParametricDistanceSampling() ) {
+ REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 2, range[2] );
+ stepsize = (d > 0.0) ? sqrtf( 8.0 * t / d ) : range[2];
+ minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0;
+ } else if( mapdesc->isPathLengthSampling() ) {
+ // t is upper bound on path (arc) length
+ REAL d = mapdesc->calcPartialVelocity( &tmp[0][0], tstride, order, 1, range[2] );
+ stepsize = ( d > 0.0 ) ? (t / d) : range[2];
+ minstepsize = ( mapdesc->maxrate > 0.0 ) ? (range[2] / mapdesc->maxrate) : 0.0;
+ } else {
+ // control points cross infinity, therefore partials are undefined
+ setstepsize( mapdesc->maxrate );
+ }
+ }
+ }
+}
+
+int
+Curve::needsSamplingSubdivision( void )
+{
+ return ( stepsize < minstepsize ) ? 1 : 0;
+}
+
+int
+Curve::cullCheck( void )
+{
+ if( cullval == CULL_ACCEPT )
+ cullval = mapdesc->cullCheck( cpts, order, stride );
+ return cullval;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/curve.h b/mesalib/src/glu/sgi/libnurbs/internals/curve.h
new file mode 100644
index 000000000..0da81c721
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/curve.h
@@ -0,0 +1,70 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * curve.h
+ *
+ */
+
+#ifndef __glucurve_h_
+#define __glucurve_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Mapdesc;
+class Quilt;
+
+
+class Curve {
+public:
+friend class Curvelist;
+ Curve( Quilt *, REAL, REAL, Curve * );
+ Curve( Curve&, REAL, Curve * );
+ Curve * next;
+private:
+ Mapdesc * mapdesc;
+ int stride;
+ int order;
+ int cullval;
+ int needsSampling;
+ REAL cpts[MAXORDER*MAXCOORDS];
+ REAL spts[MAXORDER*MAXCOORDS];
+ REAL stepsize;
+ REAL minstepsize;
+ REAL range[3];
+
+ void clamp( void );
+ void setstepsize( REAL );
+ void getstepsize( void );
+ int cullCheck( void );
+ int needsSamplingSubdivision( void );
+};
+#endif /* __glucurve_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/curvelist.cc b/mesalib/src/glu/sgi/libnurbs/internals/curvelist.cc
new file mode 100644
index 000000000..872eb5816
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/curvelist.cc
@@ -0,0 +1,110 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curvelist.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "quilt.h"
+#include "curvelist.h"
+#include "curve.h"
+#include "nurbsconsts.h"
+#include "types.h"
+
+Curvelist::Curvelist( Quilt *quilts, REAL pta, REAL ptb )
+{
+ curve = 0;
+ for( Quilt *q = quilts; q; q = q->next )
+ curve = new Curve( q, pta, ptb, curve );
+ range[0] = pta;
+ range[1] = ptb;
+ range[2] = ptb - pta;
+}
+
+Curvelist::Curvelist( Curvelist &upper, REAL value )
+{
+ Curvelist &lower = *this;
+ curve = 0;
+ for( Curve *c = upper.curve; c; c = c->next )
+ curve = new Curve( *c, value, curve );
+
+ lower.range[0] = upper.range[0];
+ lower.range[1] = value;
+ lower.range[2] = value - upper.range[0];
+ upper.range[0] = value;
+ upper.range[2] = upper.range[1] - value;
+}
+
+Curvelist::~Curvelist()
+{
+ while( curve ) {
+ Curve *c = curve;
+ curve = curve->next;
+ delete c;
+ }
+}
+
+int
+Curvelist::cullCheck( void )
+{
+ for( Curve *c = curve; c; c = c->next )
+ if( c->cullCheck() == CULL_TRIVIAL_REJECT )
+ return CULL_TRIVIAL_REJECT;
+ return CULL_ACCEPT;
+}
+
+void
+Curvelist::getstepsize( void )
+{
+ stepsize = range[2];
+ Curve *c;
+ for( c = curve; c; c = c->next ) {
+ c->getstepsize();
+ c->clamp();
+ stepsize = ((c->stepsize < stepsize) ? c->stepsize : stepsize);
+ if( c->needsSamplingSubdivision() ) break;
+ }
+ needsSubdivision = ( c ) ? 1 : 0;
+}
+
+int
+Curvelist::needsSamplingSubdivision( void )
+{
+ return needsSubdivision;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/curvelist.h b/mesalib/src/glu/sgi/libnurbs/internals/curvelist.h
new file mode 100644
index 000000000..733a5115d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/curvelist.h
@@ -0,0 +1,62 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * curvelist.h
+ *
+ */
+
+#ifndef __glucurvelist_h_
+#define __glucurvelist_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Mapdesc;
+class Quilt;
+class Curve;
+
+class Curvelist
+{
+friend class Subdivider;
+public:
+ Curvelist( Quilt *, REAL, REAL );
+ Curvelist( Curvelist &, REAL );
+ ~Curvelist( void );
+ int cullCheck( void );
+ void getstepsize( void );
+ int needsSamplingSubdivision();
+private:
+ Curve *curve;
+ float range[3];
+ int needsSubdivision;
+ float stepsize;
+};
+#endif /* __glucurvelist_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/curvesub.cc b/mesalib/src/glu/sgi/libnurbs/internals/curvesub.cc
new file mode 100644
index 000000000..f85acc269
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/curvesub.cc
@@ -0,0 +1,103 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * curvesub.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "quilt.h"
+#include "curvelist.h"
+#include "curve.h"
+#include "nurbsconsts.h"
+
+/*--------------------------------------------------------------------------
+ * drawCurves - main curve rendering entry point
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::drawCurves( void )
+{
+ REAL from[1], to[1];
+ Flist bpts;
+ qlist->getRange( from, to, bpts );
+
+ renderhints.init( );
+
+ backend.bgncurv();
+ for( int i=bpts.start; i<bpts.end-1; i++ ) {
+ REAL pta, ptb;
+ pta = bpts.pts[i];
+ ptb = bpts.pts[i+1];
+
+ qlist->downloadAll( &pta, &ptb, backend );
+
+ Curvelist curvelist( qlist, pta, ptb );
+ samplingSplit( curvelist, renderhints.maxsubdivisions );
+ }
+ backend.endcurv();
+}
+
+
+/*--------------------------------------------------------------------------
+ * samplingSplit - recursively subdivide patch, cull check each subpatch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::samplingSplit( Curvelist& curvelist, int subdivisions )
+{
+ if( curvelist.cullCheck() == CULL_TRIVIAL_REJECT ) return;
+
+ curvelist.getstepsize();
+
+ if( curvelist.needsSamplingSubdivision() && (subdivisions > 0) ) {
+ REAL mid = ( curvelist.range[0] + curvelist.range[1] ) * 0.5;
+ Curvelist lowerlist( curvelist, mid );
+ samplingSplit( lowerlist, subdivisions-1 ); // lower
+ samplingSplit( curvelist, subdivisions-1 ); // upper
+ } else {
+ long nu = 1 + ((long) (curvelist.range[2] / curvelist.stepsize));
+ backend.curvgrid( curvelist.range[0], curvelist.range[1], nu );
+ backend.curvmesh( 0, nu );
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.cc b/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.cc
new file mode 100644
index 000000000..55c0fbb15
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.cc
@@ -0,0 +1,209 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "myassert.h"
+#include "nurbsconsts.h"
+#include "trimvertex.h"
+#include "dataTransform.h"
+
+extern directedLine* arcLoopToDLineLoop(Arc_ptr loop);
+
+#if 0 // UNUSED
+static directedLine* copy_loop(Arc_ptr loop, Real2* vertArray, int& index, directedLine dline_buf[], sampledLine sline_buf[], int& index_dline)
+{
+ directedLine *ret;
+ int old_index = index;
+ int i = index;
+ int j;
+ for(j=0; j<loop->pwlArc->npts-1; j++, i++)
+ {
+ vertArray[i][0] = loop->pwlArc->pts[j].param[0];
+ vertArray[i][1] = loop->pwlArc->pts[j].param[1];
+ }
+ loop->clearmark();
+
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc=jarc->next)
+ {
+ for(j=0; j<jarc->pwlArc->npts-1; j++, i++)
+ {
+ vertArray[i][0] = jarc->pwlArc->pts[j].param[0];
+ vertArray[i][1] = jarc->pwlArc->pts[j].param[1];
+ }
+ jarc->clearmark();
+ }
+ //copy the first vertex again
+ vertArray[i][0] = loop->pwlArc->pts[0].param[0];
+ vertArray[i][1] = loop->pwlArc->pts[0].param[1];
+ i++;
+ index=i;
+
+ directedLine* dline;
+ sampledLine* sline;
+ sline = &sline_buf[index_dline];
+ dline = &dline_buf[index_dline];
+ sline->init(2, &vertArray[old_index]);
+ dline->init(INCREASING, sline);
+ ret = dline;
+ index_dline++;
+
+ for(i=old_index+1; i<= index-2; i++)
+ {
+ sline = &sline_buf[index_dline];
+ dline = &dline_buf[index_dline];
+ sline->init(2, &vertArray[i]);
+ dline->init(INCREASING, sline);
+ ret->insert(dline);
+ index_dline++;
+ }
+ return ret;
+}
+#endif
+
+#if 0 // UNUSED
+static int num_edges(Bin& bin)
+{
+ int sum=0;
+ for(Arc_ptr jarc = bin.firstarc(); jarc; jarc=bin.nextarc())
+ sum += jarc->pwlArc->npts-1;
+ return sum;
+}
+#endif
+
+/*
+directedLine* bin_to_DLineLoops(Bin& bin)
+{
+ directedLine *ret=NULL;
+ directedLine *temp;
+
+ int numedges = num_edges(bin);
+ directedLine* dline_buf = new directedLine[numedges]; //not work for N32?
+ sampledLine* sline_buf=new sampledLine[numedges];
+
+ Real2* vertArray = new Real2[numedges*2];
+ int index = 0;
+ int index_dline = 0;
+ bin.markall();
+
+ for(Arc_ptr jarc = bin.firstarc(); jarc; jarc=bin.nextarc())
+ {
+ if(jarc->ismarked())
+ {
+ assert(jarc->check() != 0);
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while(jarc != jarchead);
+ temp=copy_loop(jarchead, vertArray, index, dline_buf, sline_buf, index_dline);
+ ret = temp->insertPolygon(ret);
+ }
+ }
+
+ return ret;
+}
+*/
+
+
+directedLine* bin_to_DLineLoops(Bin& bin)
+{
+ directedLine *ret=NULL;
+ directedLine *temp;
+ bin.markall();
+ for(Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc()){
+ if(jarc->ismarked()) {
+ assert(jarc->check() != 0);
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while(jarc != jarchead);
+ temp = arcLoopToDLineLoop(jarc);
+ ret = temp->insertPolygon(ret);
+ }
+ }
+ return ret;
+}
+
+directedLine* o_pwlcurve_to_DLines(directedLine* original, O_pwlcurve* pwl)
+{
+ directedLine* ret = original;
+ for(Int i=0; i<pwl->npts-1; i++)
+ {
+ sampledLine* sline = new sampledLine(2);
+ sline->setPoint(0, pwl->pts[i].param);
+ sline->setPoint(1, pwl->pts[i+1].param);
+ directedLine* dline = new directedLine(INCREASING, sline);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ }
+ return ret;
+}
+
+directedLine* o_curve_to_DLineLoop(O_curve* cur)
+{
+ directedLine *ret;
+ if(cur == NULL)
+ return NULL;
+ assert(cur->curvetype == ct_pwlcurve);
+ ret = o_pwlcurve_to_DLines(NULL, cur->curve.o_pwlcurve);
+ for(O_curve* temp = cur->next; temp != NULL; temp = temp->next)
+ {
+ assert(temp->curvetype == ct_pwlcurve);
+ ret = o_pwlcurve_to_DLines(ret, temp->curve.o_pwlcurve);
+ }
+ return ret;
+}
+
+directedLine* o_trim_to_DLineLoops(O_trim* trim)
+{
+ O_trim* temp;
+ directedLine *ret;
+ if(trim == NULL)
+ return NULL;
+ ret = o_curve_to_DLineLoop(trim->o_curve);
+
+ for(temp=trim->next; temp != NULL; temp = temp->next)
+ {
+ ret = ret->insertPolygon(o_curve_to_DLineLoop(temp->o_curve));
+ }
+ return ret;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.h b/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.h
new file mode 100644
index 000000000..7898df754
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/dataTransform.h
@@ -0,0 +1,59 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _DATA_TRANSFORM_H
+#define _DATA_TRANSFORM_H
+
+#include "reader.h"
+#include "directedLine.h"
+#include "bin.h"
+directedLine* bin_to_DLineLoops(Bin& bin);
+
+/*transform the pwlcurve into a number of directedline lines
+ *insert these directedlines into orignal which is supposed to be
+ *the part of the trimming loop obtained so far.
+ *return the updated trimkming loop.
+ */
+directedLine* o_pwlcurve_to_DLines(directedLine* original, O_pwlcurve* pwl);
+
+/*transform a trim loop (curve) into a directedLine loop
+ */
+directedLine* o_curve_to_DLineLoop(O_curve* curve);
+
+/*transform a list of trim loops (trim) into
+ *a list of polygons represented as directedLine*.
+ */
+directedLine* o_trim_to_DLineLoops(O_trim* trim);
+
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/defines.h b/mesalib/src/glu/sgi/libnurbs/internals/defines.h
new file mode 100644
index 000000000..32950d613
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/defines.h
@@ -0,0 +1,50 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * defines.h
+ *
+ */
+
+#ifndef __gludefines_h_
+#define __gludefines_h_
+
+/* culling constants */
+#define CULL_TRIVIAL_REJECT 0
+#define CULL_TRIVIAL_ACCEPT 1
+#define CULL_ACCEPT 2
+
+/* maximum order of a B-Spline */
+#define MAXORDER 24
+
+/* maximum dimension of any B-spline range space */
+#define MAXCOORDS 5
+
+#endif /* __gludefines_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/displaylist.cc b/mesalib/src/glu/sgi/libnurbs/internals/displaylist.cc
new file mode 100644
index 000000000..48593c637
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/displaylist.cc
@@ -0,0 +1,82 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * displaylist.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "nurbstess.h"
+#include "displaylist.h"
+
+
+DisplayList::DisplayList( NurbsTessellator *_nt ) :
+ dlnodePool( sizeof( Dlnode ), 1, "dlnodepool" )
+{
+ lastNode = &nodes;
+ nt = _nt;
+}
+
+DisplayList::~DisplayList( void )
+{
+ for( Dlnode *nextNode; nodes; nodes = nextNode ) {
+ nextNode = nodes->next;
+ if( nodes->cleanup != 0 ) (nt->*nodes->cleanup)( nodes->arg );
+ //nodes->deleteMe(dlnodePool);
+ }
+}
+
+void
+DisplayList::play( void )
+{
+ for( Dlnode *node = nodes; node; node = node->next )
+ if( node->work != 0 ) (nt->*node->work)( node->arg );
+}
+
+void
+DisplayList::endList( void )
+{
+ *lastNode = 0;
+}
+
+void
+DisplayList::append( PFVS work, void *arg, PFVS cleanup )
+{
+ Dlnode *node = new(dlnodePool) Dlnode( work, arg, cleanup );
+ *lastNode = node;
+ lastNode = &(node->next);
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/displaylist.h b/mesalib/src/glu/sgi/libnurbs/internals/displaylist.h
new file mode 100644
index 000000000..22cbec378
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/displaylist.h
@@ -0,0 +1,78 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * displaylist.h
+ *
+ */
+
+#ifndef __gludisplaylist_h_
+#define __gludisplaylist_h_
+
+#include "glimports.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "bufpool.h"
+
+class NurbsTessellator;
+
+typedef void (NurbsTessellator::*PFVS)( void * );
+
+struct Dlnode : public PooledObj {
+ Dlnode( PFVS, void *, PFVS );
+ PFVS work;
+ void * arg;
+ PFVS cleanup;
+ Dlnode * next;
+};
+
+inline
+Dlnode::Dlnode( PFVS _work, void *_arg, PFVS _cleanup )
+{
+ work = _work;
+ arg = _arg;
+ cleanup = _cleanup;
+}
+
+class DisplayList {
+public:
+ DisplayList( NurbsTessellator * );
+ ~DisplayList( void );
+ void play( void );
+ void append( PFVS work, void *arg, PFVS cleanup );
+ void endList( void );
+private:
+ Dlnode *nodes;
+ Pool dlnodePool;
+ Dlnode **lastNode;
+ NurbsTessellator *nt;
+};
+
+#endif /* __gludisplaylist_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/displaymode.h b/mesalib/src/glu/sgi/libnurbs/internals/displaymode.h
new file mode 100644
index 000000000..53968b2f1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/displaymode.h
@@ -0,0 +1,40 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef __gludisplaymode_h_
+#define __gludisplaymode_h_
+
+#define N_MESHFILL 0
+#define N_MESHLINE 1
+#define N_MESHPOINT 2
+
+#endif /* __gludisplaymode_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/flist.cc b/mesalib/src/glu/sgi/libnurbs/internals/flist.cc
new file mode 100644
index 000000000..d3162b9f5
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/flist.cc
@@ -0,0 +1,118 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flist.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "flist.h"
+
+/*----------------------------------------------------------------------------
+ * Flist::Flist - initialize a REAL number array
+ *----------------------------------------------------------------------------
+ */
+Flist::Flist( void )
+{
+ npts = 0;
+ pts = 0;
+ start = end = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::~Flist - free a REAL number array
+ *----------------------------------------------------------------------------
+ */
+Flist::~Flist( void )
+{
+ if( npts ) delete[] pts;
+}
+
+void
+Flist::add( REAL x )
+{
+ pts[end++] = x;
+ assert( end <= npts );
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::filter - remove duplicate numbers from array
+ *----------------------------------------------------------------------------
+ */
+void Flist::filter( void )
+{
+ sorter.qsort( pts, end );
+ start = 0;
+
+ int j = 0;
+ for( int i = 1; i < end; i++ ) {
+ if( pts[i] == pts[i-j-1] )
+ j++;
+ pts[i-j] = pts[i];
+ }
+ end -= j;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::grow - ensure that array is large enough
+ *----------------------------------------------------------------------------
+ */
+void Flist::grow( int maxpts )
+{
+ if( npts < maxpts ) {
+ if( npts ) delete[] pts;
+ npts = 2 * maxpts;
+ pts = new REAL[npts];
+ assert( pts != 0 );
+ }
+ start = end = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Flist::taper - ignore head and tail of array
+ *----------------------------------------------------------------------------
+ */
+void Flist::taper( REAL from, REAL to )
+{
+ while( pts[start] != from )
+ start++;
+
+ while( pts[end-1] != to )
+ end--;
+}
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/flist.h b/mesalib/src/glu/sgi/libnurbs/internals/flist.h
new file mode 100644
index 000000000..014273ebe
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/flist.h
@@ -0,0 +1,59 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * flist.h
+ *
+ */
+
+#ifndef __gluflist_h_
+#define __gluflist_h_
+
+#include "types.h"
+#include "flistsorter.h"
+
+class Flist {
+public:
+ REAL * pts; /* head of array */
+ int npts; /* number of points in array */
+ int start; /* first important point index */
+ int end; /* last important point index */
+
+ Flist( void );
+ ~Flist( void );
+ void add( REAL x );
+ void filter( void );
+ void grow( int);
+ void taper( REAL , REAL );
+protected:
+ FlistSorter sorter;
+};
+
+#endif /* __gluflist_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.cc b/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.cc
new file mode 100644
index 000000000..d49bdea3e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.cc
@@ -0,0 +1,81 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * flistsorter.c++
+ *
+ */
+
+#include "glimports.h"
+#include "flistsorter.h"
+
+FlistSorter::FlistSorter( void ) : Sorter( sizeof( REAL ) )
+{
+}
+
+void
+FlistSorter::qsort( REAL *p, int n )
+{
+ Sorter::qsort( (char *)p, n );
+}
+
+int
+FlistSorter::qscmp( char *i, char *j )
+{
+ REAL f0 = *(REAL *)i;
+ REAL f1 = *(REAL *)j;
+ return (f0 < f1) ? -1 : 1;
+}
+
+void
+FlistSorter::qsexc( char *i, char *j )
+{
+ REAL *f0 = (REAL *)i;
+ REAL *f1 = (REAL *)j;
+ REAL tmp = *f0;
+ *f0 = *f1;
+ *f1 = tmp;
+}
+
+void
+FlistSorter::qstexc( char *i, char *j, char *k )
+{
+ REAL *f0 = (REAL *)i;
+ REAL *f1 = (REAL *)j;
+ REAL *f2 = (REAL *)k;
+ REAL tmp = *f0;
+ *f0 = *f2;
+ *f2 = *f1;
+ *f1 = tmp;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.h b/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.h
new file mode 100644
index 000000000..65e6a572e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/flistsorter.h
@@ -0,0 +1,53 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * flistsorter.h
+ *
+ */
+
+#ifndef __gluflistsorter_h_
+#define __gluflistsorter_h_
+
+#include "sorter.h"
+#include "types.h"
+
+class FlistSorter : public Sorter {
+public:
+ FlistSorter(void);
+ virtual ~FlistSorter() { /* silence warning*/ }
+ void qsort( REAL *a, int n );
+
+protected:
+ virtual int qscmp( char *, char * );
+ virtual void qsexc( char *i, char *j ); // i<-j, j<-i
+ virtual void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+};
+#endif /* __gluflistsorter_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/gridline.h b/mesalib/src/glu/sgi/libnurbs/internals/gridline.h
new file mode 100644
index 000000000..1a92e3b13
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/gridline.h
@@ -0,0 +1,46 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * gridline.h
+ *
+ */
+
+#ifndef __glugridline_h_
+#define __glugridline_h_
+
+struct Gridline {
+ long v;
+ REAL vval;
+ long vindex;
+ long ustart;
+ long uend;
+ };
+#endif /* __glugridline_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/gridtrimvertex.h b/mesalib/src/glu/sgi/libnurbs/internals/gridtrimvertex.h
new file mode 100644
index 000000000..707f649d2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/gridtrimvertex.h
@@ -0,0 +1,89 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * gridtrimvertex.h
+ *
+ */
+
+#ifndef __glugridtrimvertex_h_
+#define __glugridtrimvertex_h_
+
+#include "mystdlib.h"
+#include "bufpool.h"
+#include "trimvertex.h"
+#include "gridvertex.h"
+
+class GridTrimVertex : public PooledObj
+{
+private:
+ TrimVertex dummyt;
+ GridVertex dummyg;
+public:
+ GridTrimVertex() { g = 0; t = 0; }
+ TrimVertex *t;
+ GridVertex *g;
+
+ inline void set( long, long );
+ inline void set( REAL, REAL );
+ inline void set( TrimVertex * );
+ inline void clear( void ) { t = 0; g = 0; };
+ inline int isGridVert() { return g ? 1 : 0 ; }
+ inline int isTrimVert() { return t ? 1 : 0 ; }
+ inline void output();
+};
+
+inline void
+GridTrimVertex::set( long x, long y )
+{
+ g = &dummyg;
+ dummyg.gparam[0] = x;
+ dummyg.gparam[1] = y;
+}
+
+inline void
+GridTrimVertex::set( REAL x, REAL y )
+{
+ g = 0;
+ t = &dummyt;
+ dummyt.param[0] = x;
+ dummyt.param[1] = y;
+ dummyt.nuid = 0;
+}
+
+inline void
+GridTrimVertex::set( TrimVertex *v )
+{
+ g = 0;
+ t = v;
+}
+
+typedef GridTrimVertex *GridTrimVertex_p;
+#endif /* __glugridtrimvertex_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/gridvertex.h b/mesalib/src/glu/sgi/libnurbs/internals/gridvertex.h
new file mode 100644
index 000000000..36a65c7bd
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/gridvertex.h
@@ -0,0 +1,48 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * gridvertex.h
+ *
+ */
+
+#ifndef __glugridvertex_h_
+#define __glugridvertex_h_
+
+struct GridVertex {
+ long gparam[2];
+ GridVertex( void ) {}
+ GridVertex( long u, long v ) { gparam[0] = u, gparam[1] = v; }
+ void set( long u, long v ) { gparam[0] = u, gparam[1] = v; }
+ long nextu() { return gparam[0]++; }
+ long prevu() { return gparam[0]--; }
+};
+
+#endif /* __glugridvertex_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/hull.cc b/mesalib/src/glu/sgi/libnurbs/internals/hull.cc
new file mode 100644
index 000000000..389ba66fb
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/hull.cc
@@ -0,0 +1,165 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * hull.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "hull.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "gridline.h"
+#include "trimline.h"
+#include "uarray.h"
+#include "trimregion.h"
+
+Hull::Hull( void )
+{}
+
+Hull::~Hull( void )
+{}
+
+/*----------------------------------------------------------------------
+ * Hull:init - this routine does the initialization needed before any
+ * calls to nextupper or nextlower can be made.
+ *----------------------------------------------------------------------
+ */
+void
+Hull::init( void )
+{
+ TrimVertex *lfirst = left.first();
+ TrimVertex *llast = left.last();
+ if( lfirst->param[0] <= llast->param[0] ) {
+ fakeleft.init( left.first() );
+ upper.left = &fakeleft;
+ lower.left = &left;
+ } else {
+ fakeleft.init( left.last() );
+ lower.left = &fakeleft;
+ upper.left = &left;
+ }
+ upper.left->last();
+ lower.left->first();
+
+ if( top.ustart <= top.uend ) {
+ upper.line = &top;
+ upper.index = top.ustart;
+ } else
+ upper.line = 0;
+
+ if( bot.ustart <= bot.uend ) {
+ lower.line = &bot;
+ lower.index = bot.ustart;
+ } else
+ lower.line = 0;
+
+ TrimVertex *rfirst = right.first();
+ TrimVertex *rlast = right.last();
+ if( rfirst->param[0] <= rlast->param[0] ) {
+ fakeright.init( right.last() );
+ lower.right = &fakeright;
+ upper.right = &right;
+ } else {
+ fakeright.init( right.first() );
+ upper.right = &fakeright;
+ lower.right = &right;
+ }
+ upper.right->first();
+ lower.right->last();
+}
+
+/*----------------------------------------------------------------------
+ * nextupper - find next vertex on upper hull of trim region.
+ * - if vertex is on trim curve, set vtop point to
+ * that vertex. if vertex is on grid, set vtop to
+ * point to temporary area and stuff coordinants into
+ * temporary vertex. Also, place grid coords in temporary
+ * grid vertex.
+ *----------------------------------------------------------------------
+ */
+GridTrimVertex *
+Hull::nextupper( GridTrimVertex *gv )
+{
+ if( upper.left ) {
+ gv->set( upper.left->prev() );
+ if( gv->isTrimVert() ) return gv;
+ upper.left = 0;
+ }
+
+ if( upper.line ) {
+ assert( upper.index <= upper.line->uend );
+ gv->set( uarray.uarray[upper.index], upper.line->vval );
+ gv->set( upper.index, upper.line->vindex );
+ if( upper.index++ == upper.line->uend ) upper.line = 0;
+ return gv;
+ }
+
+ if( upper.right ) {
+ gv->set( upper.right->next() );
+ if( gv->isTrimVert() ) return gv;
+ upper.right = 0;
+ }
+
+ return 0;
+}
+
+GridTrimVertex *
+Hull::nextlower( register GridTrimVertex *gv )
+{
+ if( lower.left ) {
+ gv->set( lower.left->next() );
+ if( gv->isTrimVert() ) return gv;
+ lower.left = 0;
+ }
+
+ if( lower.line ) {
+ gv->set( uarray.uarray[lower.index], lower.line->vval );
+ gv->set( lower.index, lower.line->vindex );
+ if( lower.index++ == lower.line->uend ) lower.line = 0;
+ return gv;
+ }
+
+ if( lower.right ) {
+ gv->set( lower.right->prev() );
+ if( gv->isTrimVert() ) return gv;
+ lower.right = 0;
+ }
+
+ return 0;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/hull.h b/mesalib/src/glu/sgi/libnurbs/internals/hull.h
new file mode 100644
index 000000000..dfe865267
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/hull.h
@@ -0,0 +1,69 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * hull.h
+ *
+ */
+
+#ifndef __gluhull_h_
+#define __gluhull_h_
+
+#include "trimline.h"
+#include "trimregion.h"
+#include "trimvertex.h"
+#include "gridtrimvertex.h"
+
+struct Gridline;
+class Uarray;
+
+class Hull : virtual public TrimRegion {
+public:
+ Hull( void );
+ ~Hull( void );
+ void init( void );
+ GridTrimVertex * nextlower( GridTrimVertex * );
+ GridTrimVertex * nextupper( GridTrimVertex * );
+private:
+ struct Side {
+ Trimline *left;
+ Gridline *line;
+ Trimline *right;
+ long index;
+ };
+
+ Side lower;
+ Side upper;
+ Trimline fakeleft;
+ Trimline fakeright;
+};
+
+
+#endif /* __gluhull_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/intersect.cc b/mesalib/src/glu/sgi/libnurbs/internals/intersect.cc
new file mode 100644
index 000000000..b39ea2121
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/intersect.cc
@@ -0,0 +1,665 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * intersect.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arc.h"
+#include "bin.h"
+#include "backend.h"
+#include "trimvertpool.h"
+
+/*#define NOTDEF*/
+
+enum i_result { INTERSECT_VERTEX, INTERSECT_EDGE };
+
+/* local functions */
+#ifndef NDEBUG // for asserts only
+static int arc_classify( Arc_ptr, int, REAL );
+#endif
+static enum i_result pwlarc_intersect( PwlArc *, int, REAL, int, int[3] );
+
+
+void
+Subdivider::partition( Bin & bin, Bin & left, Bin & intersections,
+ Bin & right, Bin & unknown, int param, REAL value )
+{
+ Bin headonleft, headonright, tailonleft, tailonright;
+
+ for( Arc_ptr jarc = bin.removearc(); jarc; jarc = bin.removearc() ) {
+
+ REAL tdiff = jarc->tail()[param] - value;
+ REAL hdiff = jarc->head()[param] - value;
+
+ if( tdiff > 0.0 ) {
+ if( hdiff > 0.0 ) {
+ right.addarc( jarc );
+ } else if( hdiff == 0.0 ) {
+ tailonright.addarc( jarc );
+ } else {
+ Arc_ptr jtemp;
+ switch( arc_split(jarc, param, value, 0) ) {
+ case 2:
+ tailonright.addarc( jarc );
+ headonleft.addarc( jarc->next );
+ break;
+ case 31:
+ assert( jarc->head()[param] > value );
+ right.addarc( jarc );
+ tailonright.addarc( jtemp = jarc->next );
+ headonleft.addarc( jtemp->next );
+ break;
+ case 32:
+ assert( jarc->head()[param] <= value );
+ tailonright .addarc( jarc );
+ headonleft.addarc( jtemp = jarc->next );
+ left.addarc( jtemp->next );
+ break;
+ case 4:
+ right.addarc( jarc );
+ tailonright.addarc( jtemp = jarc->next );
+ headonleft.addarc( jtemp = jtemp->next );
+ left.addarc( jtemp->next );
+ }
+ }
+ } else if( tdiff == 0.0 ) {
+ if( hdiff > 0.0 ) {
+ headonright.addarc( jarc );
+ } else if( hdiff == 0.0 ) {
+ unknown.addarc( jarc );
+ } else {
+ headonleft.addarc( jarc );
+ }
+ } else {
+ if( hdiff > 0.0 ) {
+ Arc_ptr jtemp;
+ switch( arc_split(jarc, param, value, 1) ) {
+ case 2:
+ tailonleft.addarc( jarc );
+ headonright.addarc( jarc->next );
+ break;
+ case 31:
+ assert( jarc->head()[param] < value );
+ left.addarc( jarc );
+ tailonleft.addarc( jtemp = jarc->next );
+ headonright.addarc( jtemp->next );
+ break;
+ case 32:
+ assert( jarc->head()[param] >= value );
+ tailonleft.addarc( jarc );
+ headonright.addarc( jtemp = jarc->next );
+ right.addarc( jtemp->next );
+ break;
+ case 4:
+ left.addarc( jarc );
+ tailonleft.addarc( jtemp = jarc->next );
+ headonright.addarc( jtemp = jtemp->next );
+ right.addarc( jtemp->next );
+ }
+ } else if( hdiff == 0.0 ) {
+ tailonleft.addarc( jarc );
+ } else {
+ left.addarc( jarc );
+ }
+ }
+ }
+ if( param == 0 ) {
+ classify_headonleft_s( headonleft, intersections, left, value );
+ classify_tailonleft_s( tailonleft, intersections, left, value );
+ classify_headonright_s( headonright, intersections, right, value );
+ classify_tailonright_s( tailonright, intersections, right, value );
+ } else {
+ classify_headonleft_t( headonleft, intersections, left, value );
+ classify_tailonleft_t( tailonleft, intersections, left, value );
+ classify_headonright_t( headonright, intersections, right, value );
+ classify_tailonright_t( tailonright, intersections, right, value );
+ }
+}
+
+inline static void
+vert_interp( TrimVertex *n, TrimVertex *l, TrimVertex *r, int p, REAL val )
+{
+ assert( val > l->param[p]);
+ assert( val < r->param[p]);
+
+ n->nuid = l->nuid;
+
+ n->param[p] = val;
+ if( l->param[1-p] != r->param[1-p] ) {
+ REAL ratio = (val - l->param[p]) / (r->param[p] - l->param[p]);
+ n->param[1-p] = l->param[1-p] +
+ ratio * (r->param[1-p] - l->param[1-p]);
+ } else {
+ n->param[1-p] = l->param[1-p];
+ }
+}
+
+int
+Subdivider::arc_split( Arc_ptr jarc, int param, REAL value, int dir )
+{
+ int maxvertex = jarc->pwlArc->npts;
+ Arc_ptr jarc1;
+ TrimVertex* v = jarc->pwlArc->pts;
+
+ int loc[3];
+ switch( pwlarc_intersect( jarc->pwlArc, param, value, dir, loc ) ) {
+
+ // When the parameter value lands on a vertex, life is sweet
+ case INTERSECT_VERTEX: {
+ jarc1 = new(arcpool) Arc( jarc, new( pwlarcpool) PwlArc( maxvertex-loc[1], &v[loc[1]] ) );
+ jarc->pwlArc->npts = loc[1] + 1;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+ return 2;
+ }
+
+ // When the parameter value intersects an edge, we have to
+ // interpolate a new vertex. There are special cases
+ // if the new vertex is adjacent to one or both of the
+ // endpoints of the arc.
+ case INTERSECT_EDGE: {
+ int i, j;
+ if( dir == 0 ) {
+ i = loc[0];
+ j = loc[2];
+ } else {
+ i = loc[2];
+ j = loc[0];
+ }
+
+#ifndef NOTDEF
+ // The split is between vertices at index j and i, in that
+ // order (j < i)
+
+ // JEB: This code is my idea of how to do the split without
+ // increasing the number of links. I'm doing this so that
+ // the is_rect routine can recognize rectangles created by
+ // subdivision. In exchange for simplifying the curve list,
+ // however, it costs in allocated space and vertex copies.
+
+ TrimVertex *newjunk = trimvertexpool.get(maxvertex -i+1 /*-j*/);
+ int k;
+ for(k=0; k<maxvertex-i; k++)
+ {
+ newjunk[k+1] = v[i+k];
+ newjunk[k+1].nuid = jarc->nuid;
+ }
+
+ TrimVertex *vcopy = trimvertexpool.get(maxvertex);
+ for(k=0; k<maxvertex; k++)
+ {
+ vcopy[k].param[0] = v[k].param[0];
+ vcopy[k].param[1] = v[k].param[1];
+ }
+ jarc->pwlArc->pts=vcopy;
+
+ v[i].nuid = jarc->nuid;
+ v[j].nuid = jarc->nuid;
+ vert_interp( &newjunk[0], &v[loc[0]], &v[loc[2]], param, value );
+
+ if( showingDegenerate() )
+ backend.triangle( &v[i], &newjunk[0], &v[j] );
+
+ vcopy[j+1].param[0]=newjunk[0].param[0];
+ vcopy[j+1].param[1]=newjunk[0].param[1];
+
+
+ jarc1 = new(arcpool) Arc( jarc,
+ new(pwlarcpool) PwlArc(maxvertex-i+1 , newjunk ) );
+
+ jarc->pwlArc->npts = j+2;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+
+ return 2;
+#endif //not NOTDEF
+ // JEB: This is the original version:
+#ifdef NOTDEF
+ Arc_ptr jarc2, jarc3;
+
+ TrimVertex *newjunk = trimvertexpool.get(3);
+ v[i].nuid = jarc->nuid;
+ v[j].nuid = jarc->nuid;
+ newjunk[0] = v[j];
+ newjunk[2] = v[i];
+ vert_interp( &newjunk[1], &v[loc[0]], &v[loc[2]], param, value );
+
+ if( showingDegenerate() )
+ backend.triangle( &newjunk[2], &newjunk[1], &newjunk[0] );
+
+ // New vertex adjacent to both endpoints
+ if (maxvertex == 2) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc->pwlArc->npts = 2;
+ jarc->pwlArc->pts = newjunk;
+ jarc1->next = jarc->next;
+ jarc1->next->prev = jarc1;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ assert(jarc->check() != 0);
+
+ return 2;
+
+ // New vertex adjacent to ending point of arc
+ } else if (maxvertex - j == 2) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk ) );
+ jarc2 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc->pwlArc->npts = maxvertex-1;
+ jarc2->next = jarc->next;
+ jarc2->next->prev = jarc2;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ assert(jarc->check() != 0);
+ return 31;
+
+ // New vertex adjacent to starting point of arc
+ } else if (i == 1) {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc2 = new(arcpool) Arc( jarc,
+ new(pwlarcpool) PwlArc( maxvertex-1, &jarc->pwlArc->pts[1] ) );
+ jarc->pwlArc->npts = 2;
+ jarc->pwlArc->pts = newjunk;
+ jarc2->next = jarc->next;
+ jarc2->next->prev = jarc2;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ assert(jarc->check() != 0);
+ return 32;
+
+ // It's somewhere in the middle
+ } else {
+ jarc1 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk ) );
+ jarc2 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( 2, newjunk+1 ) );
+ jarc3 = new(arcpool) Arc( jarc, new(pwlarcpool) PwlArc( maxvertex-i, v+i ) );
+ jarc->pwlArc->npts = j + 1;
+ jarc3->next = jarc->next;
+ jarc3->next->prev = jarc3;
+ jarc->next = jarc1;
+ jarc1->prev = jarc;
+ jarc1->next = jarc2;
+ jarc2->prev = jarc1;
+ jarc2->next = jarc3;
+ jarc3->prev = jarc2;
+ assert(jarc->check() != 0);
+ return 4;
+ }
+#endif // NOTDEF
+ }
+ default:
+ return -1; //picked -1 since it's not used
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * pwlarc_intersect - find intersection of pwlArc and isoparametric line
+ *----------------------------------------------------------------------------
+ */
+
+static enum i_result
+pwlarc_intersect(
+ PwlArc *pwlArc,
+ int param,
+ REAL value,
+ int dir,
+ int loc[3] )
+{
+ assert( pwlArc->npts > 0 );
+
+ if( dir ) {
+ TrimVertex *v = pwlArc->pts;
+ int imin = 0;
+ int imax = pwlArc->npts - 1;
+ assert( value > v[imin].param[param] );
+ assert( value < v[imax].param[param] );
+ while( (imax - imin) > 1 ) {
+ int imid = (imax + imin)/2;
+ if( v[imid].param[param] > value )
+ imax = imid;
+ else if( v[imid].param[param] < value )
+ imin = imid;
+ else {
+ loc[1] = imid;
+ return INTERSECT_VERTEX;
+ }
+ }
+ loc[0] = imin;
+ loc[2] = imax;
+ return INTERSECT_EDGE;
+ } else {
+ TrimVertex *v = pwlArc->pts;
+ int imax = 0;
+ int imin = pwlArc->npts - 1;
+ assert( value > v[imin].param[param] );
+ assert( value < v[imax].param[param] );
+ while( (imin - imax) > 1 ) {
+ int imid = (imax + imin)/2;
+ if( v[imid].param[param] > value )
+ imax = imid;
+ else if( v[imid].param[param] < value )
+ imin = imid;
+ else {
+ loc[1] = imid;
+ return INTERSECT_VERTEX;
+ }
+ }
+ loc[0] = imin;
+ loc[2] = imax;
+ return INTERSECT_EDGE;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * arc_classify - determine which side of a line a jarc lies
+ *----------------------------------------------------------------------------
+ */
+
+#ifndef NDEBUG // for asserts only
+static int
+arc_classify( Arc_ptr jarc, int param, REAL value )
+{
+ REAL tdiff, hdiff;
+ if( param == 0 ) {
+ tdiff = jarc->tail()[0] - value;
+ hdiff = jarc->head()[0] - value;
+ } else {
+ tdiff = jarc->tail()[1] - value;
+ hdiff = jarc->head()[1] - value;
+ }
+
+ if( tdiff > 0.0 ) {
+ if( hdiff > 0.0 ) {
+ return 0x11;
+ } else if( hdiff == 0.0 ) {
+ return 0x12;
+ } else {
+ return 0x10;
+ }
+ } else if( tdiff == 0.0 ) {
+ if( hdiff > 0.0 ) {
+ return 0x21;
+ } else if( hdiff == 0.0 ) {
+ return 0x22;
+ } else {
+ return 0x20;
+ }
+ } else {
+ if( hdiff > 0.0 ) {
+ return 0x01;
+ } else if( hdiff == 0.0 ) {
+ return 0x02;
+ } else {
+ return 0;
+ }
+ }
+}
+#endif
+
+void
+Subdivider::classify_tailonleft_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at left, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x02 );
+ j->clearitail();
+
+ REAL diff = j->next->head()[0] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_sl( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[1] > j->next->head()[1] )
+ in.addarc(j);
+ else
+ out.addarc(j);
+ }
+ }
+}
+
+void
+Subdivider::classify_tailonleft_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at left, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x02 );
+ j->clearitail();
+
+ REAL diff = j->next->head()[1] - val;
+ if( diff > 0.0 ) {
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if (j->next->tail()[0] > j->next->head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonleft_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at left */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x20 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[0] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_sl( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->prev->tail()[1] > j->prev->head()[1] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonleft_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at left */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x20 );
+ j->setitail();
+
+ REAL diff = j->prev->tail()[1] - val;
+ if( diff > 0.0 ) {
+ out.addarc( j );
+ } else if( diff < 0.0 ) {
+ if( ccwTurn_tl( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else {
+ if( j->prev->tail()[0] > j->prev->head()[0] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+
+void
+Subdivider::classify_tailonright_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at right, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x12);
+
+ j->clearitail();
+
+ REAL diff = j->next->head()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[1] > j->next->head()[1] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_tailonright_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail at right, head on line */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x12);
+
+ j->clearitail();
+
+ REAL diff = j->next->head()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j, j->next ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ in.addarc( j );
+ } else {
+ if( j->next->tail()[0] > j->next->head()[0] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonright_s( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at right */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 0, val ) == 0x21 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[0] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_sr( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ out.addarc( j );
+ } else {
+ if( j->prev->tail()[1] > j->prev->head()[1] )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ }
+ }
+}
+
+void
+Subdivider::classify_headonright_t( Bin& bin, Bin& in, Bin& out, REAL val )
+{
+ /* tail on line, head at right */
+ Arc_ptr j;
+
+ while( (j = bin.removearc()) != NULL ) {
+ assert( arc_classify( j, 1, val ) == 0x21 );
+
+ j->setitail();
+
+ REAL diff = j->prev->tail()[1] - val;
+ if( diff > 0.0 ) {
+ if( ccwTurn_tr( j->prev, j ) )
+ out.addarc( j );
+ else
+ in.addarc( j );
+ } else if( diff < 0.0 ) {
+ out.addarc( j );
+ } else {
+ if( j->prev->tail()[0] > j->prev->head()[0] )
+ in.addarc( j );
+ else
+ out.addarc( j );
+ }
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/jarcloc.h b/mesalib/src/glu/sgi/libnurbs/internals/jarcloc.h
new file mode 100644
index 000000000..5297036fa
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/jarcloc.h
@@ -0,0 +1,87 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * jarcloc.h
+ *
+ */
+
+#ifndef __glujarcloc_h_
+#define __glujarcloc_h_
+
+#include "arc.h"
+
+class Jarcloc {
+private:
+ Arc_ptr arc;
+ TrimVertex *p;
+ TrimVertex *plast;
+public:
+ inline void init( Arc_ptr a, long first, long last ) { arc = a; p=&a->pwlArc->pts[first]; plast = &a->pwlArc->pts[last]; }
+ inline TrimVertex * getnextpt( void );
+ inline TrimVertex * getprevpt( void );
+ inline void reverse();
+};
+
+inline void
+Jarcloc::reverse()
+{
+ if( plast == &arc->pwlArc->pts[0] )
+ plast = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ else
+ plast = &arc->pwlArc->pts[0];
+}
+
+inline TrimVertex *
+Jarcloc::getnextpt()
+{
+ assert( p <= plast );
+ if( p == plast ) {
+ arc = arc->next;
+ p = &arc->pwlArc->pts[0];
+ plast = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ assert( p < plast );
+ }
+ return p++;
+}
+
+inline TrimVertex *
+Jarcloc::getprevpt()
+{
+ assert( p >= plast );
+ if( p == plast ) {
+ arc = arc->prev;
+ p = &arc->pwlArc->pts[arc->pwlArc->npts - 1];
+ plast = &arc->pwlArc->pts[0];
+ assert( p > plast );
+ }
+ return p--;
+}
+#endif /* __glujarcloc_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/knotvector.cc b/mesalib/src/glu/sgi/libnurbs/internals/knotvector.cc
new file mode 100644
index 000000000..9eb5cbace
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/knotvector.cc
@@ -0,0 +1,139 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * knotvector.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "knotvector.h"
+#include "defines.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+void Knotvector::init( long _knotcount, long _stride, long _order, INREAL *_knotlist )
+{
+ knotcount = _knotcount;
+ stride = _stride;
+ order = _order;
+ knotlist = new Knot[_knotcount];
+ assert( knotlist != 0 );
+
+ for( int i = 0; i != _knotcount; i++ )
+ knotlist[i] = (Knot) _knotlist[i];
+}
+
+Knotvector::Knotvector( void )
+{
+ knotlist = 0;
+}
+
+Knotvector::~Knotvector( void )
+{
+ if( knotlist ) delete[] knotlist;
+}
+
+int Knotvector::validate( void )
+{
+ /* kindex is used as an array index so subtract one first,
+ * this propagates throughout the code so study carefully */
+ long kindex = knotcount-1;
+
+ if( order < 1 || order > MAXORDER ) {
+ // spline order un-supported
+ return( 1 );
+ }
+
+ if( knotcount < (2 * order) ) {
+ // too few knots
+ return( 2 );
+ }
+
+ if( identical( knotlist[kindex-(order-1)], knotlist[order-1]) ) {
+ // valid knot range is empty
+ return( 3 );
+ }
+
+ for( long i = 0; i < kindex; i++)
+ if( knotlist[i] > knotlist[i+1] ) {
+ // decreasing knot sequence
+ return( 4 );
+ }
+
+ /* check for valid multiplicity */
+
+ /* kindex is currently the index of the last knot.
+ * In the next loop it is decremented to ignore the last knot
+ * and the loop stops when kindex is 2 so as to ignore the first
+ * knot as well. These knots are not used in computing
+ * knot multiplicities.
+ */
+
+ long multi = 1;
+ for( ; kindex >= 1; kindex-- ) {
+ if( knotlist[kindex] - knotlist[kindex-1] < TOLERANCE ) {
+ multi++;
+ continue;
+ }
+ if ( multi > order ) {
+ // knot multiplicity greater than order of spline
+ return( 5 );
+ }
+ multi = 1;
+ }
+
+ if ( multi > order ) {
+ // knot multiplicity greater than order of spline
+ return( 5 );
+ }
+
+ return 0;
+}
+
+void Knotvector::show( const char *msg )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "%s\n", msg );
+ _glu_dprintf( "order = %ld, count = %ld\n", order, knotcount );
+
+ for( int i=0; i<knotcount; i++ )
+ _glu_dprintf( "knot[%d] = %g\n", i, knotlist[i] );
+#endif
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/knotvector.h b/mesalib/src/glu/sgi/libnurbs/internals/knotvector.h
new file mode 100644
index 000000000..85b162f6f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/knotvector.h
@@ -0,0 +1,62 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * knotvector.h
+ *
+ */
+
+#ifndef __gluknotvector_h_
+#define __gluknotvector_h_
+
+#include "types.h"
+
+struct Knotvector { /* a knot vector */
+ Knotvector( void );
+ ~Knotvector( void );
+ void init( long, long, long, INREAL * );
+ int validate( void );
+ void show( const char * );
+
+ long order; /* order of spline */
+ long knotcount; /* number of knots */
+ long stride; /* bytes between points */
+ Knot * knotlist; /* global knot vector */
+};
+
+/* tolerance to test knot coincidence */
+#define TOLERANCE 1.0e-5
+
+inline int
+identical( Knot x, Knot y )
+{
+ return ((x-y) < TOLERANCE) ? 1 : 0;
+}
+#endif /* __gluknotvector_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.cc b/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.cc
new file mode 100644
index 000000000..d59f8fd39
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.cc
@@ -0,0 +1,841 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mapdesc.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mystring.h"
+#include "mymath.h"
+#include "backend.h"
+#include "nurbsconsts.h"
+#include "mapdesc.h"
+
+Mapdesc::Mapdesc( long _type, int _israt, int _ncoords, Backend& b )
+ : backend( b )
+{
+ type = _type;
+ isrational = _israt;
+ ncoords = _ncoords;
+ hcoords = _ncoords + (_israt ? 0 : 1 );
+ inhcoords = _ncoords - (_israt ? 1 : 0 );
+ mask = ((1<<(inhcoords*2))-1);
+ next = 0;
+
+ assert( hcoords <= MAXCOORDS );
+ assert( inhcoords >= 1 );
+
+ pixel_tolerance = 1.0;
+ error_tolerance = 1.0;
+ bbox_subdividing = N_NOBBOXSUBDIVISION;
+ culling_method = N_NOCULLING;
+ sampling_method = N_NOSAMPLING;
+ clampfactor = N_NOCLAMPING;
+ minsavings = N_NOSAVINGSSUBDIVISION;
+ s_steps = 0.0;
+ t_steps = 0.0;
+ maxrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
+ maxsrate = ( s_steps < 0.0 ) ? 0.0 : s_steps;
+ maxtrate = ( t_steps < 0.0 ) ? 0.0 : t_steps;
+ identify( bmat );
+ identify( cmat );
+ identify( smat );
+ for( int i = 0; i != inhcoords; i++ )
+ bboxsize[i] = 1.0;
+}
+
+void
+Mapdesc::setBboxsize( INREAL *mat )
+{
+ for( int i = 0; i != inhcoords; i++ )
+ bboxsize[i] = (REAL) mat[i];
+}
+
+void
+Mapdesc::identify( REAL dest[MAXCOORDS][MAXCOORDS] )
+{
+ memset( dest, 0, sizeof( dest ) );
+ for( int i=0; i != hcoords; i++ )
+ dest[i][i] = 1.0;
+}
+
+void
+Mapdesc::surfbbox( REAL bb[2][MAXCOORDS] )
+{
+ backend.surfbbox( type, bb[0], bb[1] );
+}
+
+void
+Mapdesc::copy( REAL dest[MAXCOORDS][MAXCOORDS], long n, INREAL *src,
+ long rstride, long cstride )
+{
+ assert( n >= 0 );
+ for( int i=0; i != n; i++ )
+ for( int j=0; j != n; j++ )
+ dest[i][j] = src[i*rstride + j*cstride];
+}
+
+/*--------------------------------------------------------------------------
+ * copyPt - copy a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::copyPt( REAL *d, REAL *s )
+{
+ assert( hcoords > 0 );
+ switch( hcoords ) {
+ case 4:
+ d[3] = s[3];
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 3:
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 2:
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ case 1:
+ d[0] = s[0];
+ break;
+ case 5:
+ d[4] = s[4];
+ d[3] = s[3];
+ d[2] = s[2];
+ d[1] = s[1];
+ d[0] = s[0];
+ break;
+ default:
+ memcpy( d, s, hcoords * sizeof( REAL ) );
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * sumPt - compute affine combination of two homogeneous points
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::sumPt( REAL *dst, REAL *src1, REAL *src2, register REAL alpha, register REAL beta )
+{
+ assert( hcoords > 0 );
+ switch( hcoords ) {
+ case 4:
+ dst[3] = src1[3] * alpha + src2[3] * beta;
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 3:
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 2:
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 1:
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ case 5:
+ dst[4] = src1[4] * alpha + src2[4] * beta;
+ dst[3] = src1[3] * alpha + src2[3] * beta;
+ dst[2] = src1[2] * alpha + src2[2] * beta;
+ dst[1] = src1[1] * alpha + src2[1] * beta;
+ dst[0] = src1[0] * alpha + src2[0] * beta;
+ break;
+ default: {
+ for( int i = 0; i != hcoords; i++ )
+ dst[i] = src1[i] * alpha + src2[i] * beta;
+ }
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * clipbits - compute bit-vector indicating point/window position
+ * of a (transformed) homogeneous point
+ *--------------------------------------------------------------------------
+ */
+unsigned int
+Mapdesc::clipbits( REAL *p )
+{
+ assert( inhcoords >= 0 );
+ assert( inhcoords <= 3 );
+
+ register int nc = inhcoords;
+ register REAL pw = p[nc];
+ register REAL nw = -pw;
+ register unsigned int bits = 0;
+
+ if( pw == 0.0 ) return mask;
+
+ if( pw > 0.0 ) {
+ switch( nc ) {
+ case 3:
+ if( p[2] <= pw ) bits |= (1<<5);
+ if( p[2] >= nw ) bits |= (1<<4);
+ if( p[1] <= pw ) bits |= (1<<3);
+ if( p[1] >= nw ) bits |= (1<<2);
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ case 2:
+ if( p[1] <= pw ) bits |= (1<<3);
+ if( p[1] >= nw ) bits |= (1<<2);
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ case 1:
+ if( p[0] <= pw ) bits |= (1<<1);
+ if( p[0] >= nw ) bits |= (1<<0);
+ return bits;
+ default: {
+ int bit = 1;
+ for( int i=0; i<nc; i++ ) {
+ if( p[i] >= nw ) bits |= bit;
+ bit <<= 1;
+ if( p[i] <= pw ) bits |= bit;
+ bit <<= 1;
+ }
+ abort();
+ break;
+ }
+ }
+ } else {
+ switch( nc ) {
+ case 3:
+ if( p[2] <= nw ) bits |= (1<<5);
+ if( p[2] >= pw ) bits |= (1<<4);
+ if( p[1] <= nw ) bits |= (1<<3);
+ if( p[1] >= pw ) bits |= (1<<2);
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ case 2:
+ if( p[1] <= nw ) bits |= (1<<3);
+ if( p[1] >= pw ) bits |= (1<<2);
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ case 1:
+ if( p[0] <= nw ) bits |= (1<<1);
+ if( p[0] >= pw ) bits |= (1<<0);
+ return bits;
+ default: {
+ int bit = 1;
+ for( int i=0; i<nc; i++ ) {
+ if( p[i] >= pw ) bits |= bit;
+ bit <<= 1;
+ if( p[i] <= nw ) bits |= bit;
+ bit <<= 1;
+ }
+ abort();
+ break;
+ }
+ }
+ }
+ return bits;
+}
+
+/*--------------------------------------------------------------------------
+ * xformRational - transform a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformRational( Maxmatrix mat, REAL *d, REAL *s )
+{
+ assert( hcoords >= 0 );
+
+ if( hcoords == 3 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2];
+ } else if( hcoords == 4 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ REAL w = s[3];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+w*mat[3][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+w*mat[3][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+w*mat[3][2];
+ d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+w*mat[3][3];
+ } else {
+ for( int i=0; i != hcoords; i++ ) {
+ d[i] = 0;
+ for( int j = 0; j != hcoords; j++ )
+ d[i] += s[j] * mat[j][i];
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformNonrational - transform a inhomogeneous point to a homogeneous point
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformNonrational( Maxmatrix mat, REAL *d, REAL *s )
+{
+ if( inhcoords == 2 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ d[0] = x*mat[0][0]+y*mat[1][0]+mat[2][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+mat[2][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+mat[2][2];
+ } else if( inhcoords == 3 ) {
+ REAL x = s[0];
+ REAL y = s[1];
+ REAL z = s[2];
+ d[0] = x*mat[0][0]+y*mat[1][0]+z*mat[2][0]+mat[3][0];
+ d[1] = x*mat[0][1]+y*mat[1][1]+z*mat[2][1]+mat[3][1];
+ d[2] = x*mat[0][2]+y*mat[1][2]+z*mat[2][2]+mat[3][2];
+ d[3] = x*mat[0][3]+y*mat[1][3]+z*mat[2][3]+mat[3][3];
+ } else {
+ assert( inhcoords >= 0 );
+ for( int i=0; i != hcoords; i++ ) {
+ d[i] = mat[inhcoords][i];
+ for( int j = 0; j < inhcoords; j++ )
+ d[i] += s[j] * mat[j][i];
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformAndCullCheck - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description and
+ * check if they are either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::xformAndCullCheck(
+ REAL *pts, int uorder, int ustride, int vorder, int vstride )
+{
+ assert( uorder > 0 );
+ assert( vorder > 0 );
+
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
+ REAL *q = p;
+ for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
+ REAL cpts[MAXCOORDS];
+ xformCulling( cpts, q );
+ unsigned int bits = clipbits( cpts );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * cullCheck - check if a set of homogeneous transformed points are
+ * either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::cullCheck( REAL *pts, int uorder, int ustride, int vorder, int vstride )
+{
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + uorder * ustride; p != pend; p += ustride ) {
+ REAL *q = p;
+ for( REAL *qend = q + vorder * vstride; q != qend; q += vstride ) {
+ unsigned int bits = clipbits( q );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * cullCheck - check if a set of homogeneous transformed points are
+ * either completely inside, completely outside,
+ * or intersecting the viewing frustrum.
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::cullCheck( REAL *pts, int order, int stride )
+{
+ unsigned int inbits = mask;
+ unsigned int outbits = 0;
+
+ REAL *p = pts;
+ for( REAL *pend = p + order * stride; p != pend; p += stride ) {
+ unsigned int bits = clipbits( p );
+ outbits |= bits;
+ inbits &= bits;
+ if( ( outbits == (unsigned int)mask ) && ( inbits != (unsigned int)mask ) ) return CULL_ACCEPT;
+ }
+
+ if( outbits != (unsigned int)mask ) {
+ return CULL_TRIVIAL_REJECT;
+ } else if( inbits == (unsigned int)mask ) {
+ return CULL_TRIVIAL_ACCEPT;
+ } else {
+ return CULL_ACCEPT;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * xformSampling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into sampling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformSampling( REAL *pts, int order, int stride, REAL *sp, int outstride )
+{
+ xformMat( smat, pts, order, stride, sp, outstride );
+}
+
+void
+Mapdesc::xformBounding( REAL *pts, int order, int stride, REAL *sp, int outstride )
+{
+ xformMat( bmat, pts, order, stride, sp, outstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformCulling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into culling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformCulling( REAL *pts, int order, int stride, REAL *cp, int outstride )
+{
+ xformMat( cmat, pts, order, stride, cp, outstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformCulling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into culling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformCulling( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *cp, int outustride, int outvstride )
+{
+ xformMat( cmat, pts, uorder, ustride, vorder, vstride, cp, outustride, outvstride );
+}
+
+/*--------------------------------------------------------------------------
+ * xformSampling - transform a set of points that may be EITHER
+ * homogeneous or inhomogeneous depending on the map description
+ * into sampling space
+ *--------------------------------------------------------------------------
+ */
+void
+Mapdesc::xformSampling( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *sp, int outustride, int outvstride )
+{
+ xformMat( smat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
+}
+
+void
+Mapdesc::xformBounding( REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *sp, int outustride, int outvstride )
+{
+ xformMat( bmat, pts, uorder, ustride, vorder, vstride, sp, outustride, outvstride );
+}
+
+void
+Mapdesc::xformMat(
+ Maxmatrix mat,
+ REAL * pts,
+ int order,
+ int stride,
+ REAL * cp,
+ int outstride )
+{
+ if( isrational ) {
+ REAL *pend = pts + order * stride;
+ for( REAL *p = pts ; p != pend; p += stride ) {
+ xformRational( mat, cp, p );
+ cp += outstride;
+ }
+ } else {
+ REAL *pend = pts + order * stride;
+ for( REAL *p = pts ; p != pend; p += stride ) {
+ xformNonrational( mat, cp, p );
+ cp += outstride;
+ }
+ }
+}
+
+void
+Mapdesc::xformMat( Maxmatrix mat, REAL *pts,
+ int uorder, int ustride,
+ int vorder, int vstride,
+ REAL *cp, int outustride, int outvstride )
+{
+ if( isrational ) {
+ REAL *pend = pts + uorder * ustride;
+ for( REAL *p = pts ; p != pend; p += ustride ) {
+ REAL *cpts2 = cp;
+ REAL *qend = p + vorder * vstride;
+ for( REAL *q = p; q != qend; q += vstride ) {
+ xformRational( mat, cpts2, q );
+ cpts2 += outvstride;
+ }
+ cp += outustride;
+ }
+ } else {
+ REAL *pend = pts + uorder * ustride;
+ for( REAL *p = pts ; p != pend; p += ustride ) {
+ REAL *cpts2 = cp;
+ REAL *qend = p + vorder * vstride;
+ for( REAL *q = p; q != qend; q += vstride ) {
+ xformNonrational( mat, cpts2, q );
+ cpts2 += outvstride;
+ }
+ cp += outustride;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * subdivide - subdivide a curve along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+void
+Mapdesc::subdivide( REAL *src, REAL *dst, REAL v, int stride, int order )
+{
+ REAL mv = 1.0 - v;
+
+ for( REAL *send=src+stride*order; src!=send; send-=stride, dst+=stride ) {
+ copyPt( dst, src );
+ REAL *qpnt = src + stride;
+ for( REAL *qp=src; qpnt!=send; qp=qpnt, qpnt+=stride )
+ sumPt( qp, qp, qpnt, mv, v );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * subdivide - subdivide a patch along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+void
+Mapdesc::subdivide( REAL *src, REAL *dst, REAL v,
+ int so, int ss, int to, int ts )
+{
+ REAL mv = 1.0 - v;
+
+ for( REAL *slast = src+ss*so; src != slast; src += ss, dst += ss ) {
+ REAL *sp = src;
+ REAL *dp = dst;
+ for( REAL *send = src+ts*to; sp != send; send -= ts, dp += ts ) {
+ copyPt( dp, sp );
+ REAL *qp = sp;
+ for( REAL *qpnt = sp+ts; qpnt != send; qp = qpnt, qpnt += ts )
+ sumPt( qp, qp, qpnt, mv, v );
+ }
+ }
+}
+
+
+#define sign(x) ((x > 0) ? 1 : ((x < 0.0) ? -1 : 0))
+
+/*--------------------------------------------------------------------------
+ * project - project a set of homogeneous coordinates into inhomogeneous ones
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::project( REAL *src, int rstride, int cstride,
+ REAL *dest, int trstride, int tcstride,
+ int nrows, int ncols )
+{
+ int s = sign( src[inhcoords] );
+ REAL *rlast = src + nrows * rstride;
+ REAL *trptr = dest;
+ for( REAL *rptr=src; rptr != rlast; rptr+=rstride, trptr+=trstride ) {
+ REAL *clast = rptr + ncols * cstride;
+ REAL *tcptr = trptr;
+ for( REAL *cptr = rptr; cptr != clast; cptr+=cstride, tcptr+=tcstride ) {
+ REAL *coordlast = cptr + inhcoords;
+ if( sign( *coordlast ) != s ) return 0;
+ REAL *tcoord = tcptr;
+ for( REAL *coord = cptr; coord != coordlast; coord++, tcoord++ ) {
+ *tcoord = *coord / *coordlast;
+ }
+ }
+ }
+ return 1;
+}
+
+/*--------------------------------------------------------------------------
+ * project - project a set of homogeneous coordinates into inhomogeneous ones
+ *--------------------------------------------------------------------------
+ */
+int
+Mapdesc::project( REAL *src, int stride, REAL *dest, int tstride, int ncols )
+{
+ int s = sign( src[inhcoords] );
+
+ REAL *clast = src + ncols * stride;
+ for( REAL *cptr = src, *tcptr = dest; cptr != clast; cptr+=stride, tcptr+=tstride ) {
+ REAL *coordlast = cptr + inhcoords;
+ if( sign( *coordlast ) != s ) return 0;
+ for( REAL *coord = cptr, *tcoord = tcptr; coord != coordlast; coord++, tcoord++ )
+ *tcoord = *coord / *coordlast;
+ }
+
+ return 1;
+}
+
+int
+Mapdesc::bboxTooBig(
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols,
+ REAL bb[2][MAXCOORDS] )
+{
+ REAL bbpts[MAXORDER][MAXORDER][MAXCOORDS];
+ const int trstride = sizeof(bbpts[0]) / sizeof(REAL);
+ const int tcstride = sizeof(bbpts[0][0]) / sizeof(REAL);
+
+ // points have been transformed, therefore they are homogeneous
+ // project points
+ int val = project( p, rstride, cstride,
+ &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
+ if( val == 0 ) return -1;
+
+ // compute bounding box
+ bbox( bb, &bbpts[0][0][0], trstride, tcstride, nrows, ncols );
+
+ // find out if bounding box can't fit in unit cube
+ if( bbox_subdividing == N_BBOXROUND ) {
+ for( int k=0; k != inhcoords; k++ )
+ if( ceilf(bb[1][k]) - floorf(bb[0][k]) > bboxsize[k] ) return 1;
+ } else {
+ for( int k=0; k != inhcoords; k++ )
+ if( bb[1][k] - bb[0][k] > bboxsize[k] ) return 1;
+ }
+ return 0;
+}
+
+void
+Mapdesc::bbox(
+ REAL bb[2][MAXCOORDS],
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols )
+{
+ int k;
+ for( k=0; k != inhcoords; k++ )
+ bb[0][k] = bb[1][k] = p[k];
+
+ for( int i=0; i != nrows; i++ )
+ for( int j=0; j != ncols; j++ )
+ for( k=0; k != inhcoords; k++ ) {
+ REAL x = p[i*rstride + j*cstride + k];
+ if( x < bb[0][k] ) bb[0][k] = x;
+ else if( x > bb[1][k] ) bb[1][k] = x;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * calcVelocityRational - calculate upper bound on first partial derivative
+ * of a homogeneous set of points and bounds on each row of points.
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcVelocityRational( REAL *p, int stride, int ncols )
+{
+ REAL tmp[MAXORDER][MAXCOORDS];
+
+ assert( ncols <= MAXORDER );
+
+ const int tstride = sizeof(tmp[0]) / sizeof(REAL);
+
+ if( project( p, stride, &tmp[0][0], tstride, ncols ) ) {
+ return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
+ } else { /* XXX */
+ return calcPartialVelocity( &tmp[0][0], tstride, ncols, 1, 1.0 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * calcVelocityNonrational - calculate upper bound on first partial
+ * derivative of a inhomogeneous set of points.
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcVelocityNonrational( REAL *pts, int stride, int ncols )
+{
+ return calcPartialVelocity( pts, stride, ncols, 1, 1.0 );
+}
+
+int
+Mapdesc::isProperty( long property )
+{
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ case N_ERROR_TOLERANCE:
+ case N_CULLING:
+ case N_BBOX_SUBDIVIDING:
+ case N_S_STEPS:
+ case N_T_STEPS:
+ case N_SAMPLINGMETHOD:
+ case N_CLAMPFACTOR:
+ case N_MINSAVINGS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+REAL
+Mapdesc::getProperty( long property )
+{
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ return pixel_tolerance;
+ case N_ERROR_TOLERANCE:
+ return error_tolerance;
+ case N_CULLING:
+ return culling_method;
+ case N_BBOX_SUBDIVIDING:
+ return bbox_subdividing;
+ case N_S_STEPS:
+ return s_steps;
+ case N_T_STEPS:
+ return t_steps;
+ case N_SAMPLINGMETHOD:
+ return sampling_method;
+ case N_CLAMPFACTOR:
+ return clampfactor;
+ case N_MINSAVINGS:
+ return minsavings;
+ default:
+ abort();
+ return -1; //not necessary, needed to shut up compiler
+ }
+}
+
+void
+Mapdesc::setProperty( long property, REAL value )
+{
+
+ switch ( property ) {
+ case N_PIXEL_TOLERANCE:
+ pixel_tolerance = value;
+ break;
+ case N_ERROR_TOLERANCE:
+ error_tolerance = value;
+ break;
+ case N_CULLING:
+ culling_method = value;
+ break;
+ case N_BBOX_SUBDIVIDING:
+ if( value <= 0.0 ) value = N_NOBBOXSUBDIVISION;
+ bbox_subdividing = value;
+ break;
+ case N_S_STEPS:
+ if( value < 0.0 ) value = 0.0;
+ s_steps = value;
+ maxrate = ( value < 0.0 ) ? 0.0 : value;
+ maxsrate = ( value < 0.0 ) ? 0.0 : value;
+ break;
+ case N_T_STEPS:
+ if( value < 0.0 ) value = 0.0;
+ t_steps = value;
+ maxtrate = ( value < 0.0 ) ? 0.0 : value;
+ break;
+ case N_SAMPLINGMETHOD:
+ sampling_method = value;
+ break;
+ case N_CLAMPFACTOR:
+ if( value <= 0.0 ) value = N_NOCLAMPING;
+ clampfactor = value;
+ break;
+ case N_MINSAVINGS:
+ if( value <= 0.0 ) value = N_NOSAVINGSSUBDIVISION;
+ minsavings = value;
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.h b/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.h
new file mode 100644
index 000000000..6f06154f9
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mapdesc.h
@@ -0,0 +1,271 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mapdesc.h
+ *
+ */
+
+#ifndef __glumapdesc_h_
+#define __glumapdesc_h_
+
+#include "mystdio.h"
+#include "types.h"
+#include "defines.h"
+#include "bufpool.h"
+#include "nurbsconsts.h"
+
+typedef REAL Maxmatrix[MAXCOORDS][MAXCOORDS];
+
+class Backend;
+
+class Mapdesc : public PooledObj {
+ friend class Maplist;
+
+public:
+ Mapdesc( long, int, int, Backend & );
+ int isProperty( long );
+ REAL getProperty( long );
+ void setProperty( long, REAL );
+ int isConstantSampling( void );
+ int isDomainSampling( void );
+ int isRangeSampling( void );
+ int isSampling( void );
+ int isParametricDistanceSampling( void );
+ int isObjectSpaceParaSampling( void );
+ int isObjectSpacePathSampling( void );
+ int isSurfaceAreaSampling( void );
+ int isPathLengthSampling( void );
+ int isCulling( void );
+ int isBboxSubdividing( void );
+ long getType( void );
+
+ /* curve routines */
+ void subdivide( REAL *, REAL *, REAL, int, int );
+ int cullCheck( REAL *, int, int );
+ void xformBounding( REAL *, int, int, REAL *, int );
+ void xformCulling( REAL *, int, int, REAL *, int );
+ void xformSampling( REAL *, int, int, REAL *, int );
+ void xformMat( Maxmatrix, REAL *, int, int, REAL *, int );
+ REAL calcPartialVelocity ( REAL *, int, int, int, REAL );
+ int project( REAL *, int, REAL *, int, int );
+ REAL calcVelocityRational( REAL *, int, int );
+ REAL calcVelocityNonrational( REAL *, int, int );
+
+ /* surface routines */
+ void subdivide( REAL *, REAL *, REAL, int, int, int, int );
+ int cullCheck( REAL *, int, int, int, int );
+ void xformBounding( REAL *, int, int, int, int, REAL *, int, int );
+ void xformCulling( REAL *, int, int, int, int, REAL *, int, int );
+ void xformSampling( REAL *, int, int, int, int, REAL *, int, int );
+ void xformMat( Maxmatrix, REAL *, int, int, int, int, REAL *, int, int );
+ REAL calcPartialVelocity ( REAL *, REAL *, int, int, int, int, int, int, REAL, REAL, int );
+ int project( REAL *, int, int, REAL *, int, int, int, int);
+ void surfbbox( REAL bb[2][MAXCOORDS] );
+
+ int bboxTooBig( REAL *, int, int, int, int, REAL [2][MAXCOORDS] );
+ int xformAndCullCheck( REAL *, int, int, int, int );
+
+ void identify( REAL[MAXCOORDS][MAXCOORDS] );
+ void setBboxsize( INREAL *);
+ inline void setBmat( INREAL*, long, long );
+ inline void setCmat( INREAL*, long, long );
+ inline void setSmat( INREAL*, long, long );
+ inline int isRational( void );
+ inline int getNcoords( void );
+
+ REAL pixel_tolerance; /* pathlength sampling tolerance */
+ REAL error_tolerance; /* parametric error sampling tolerance*/
+ REAL object_space_error_tolerance; /* object space tess*/
+ REAL clampfactor;
+ REAL minsavings;
+ REAL maxrate;
+ REAL maxsrate;
+ REAL maxtrate;
+ REAL bboxsize[MAXCOORDS];
+
+private:
+ long type;
+ int isrational;
+ int ncoords;
+ int hcoords;
+ int inhcoords;
+ int mask;
+ Maxmatrix bmat;
+ Maxmatrix cmat;
+ Maxmatrix smat;
+ REAL s_steps; /* max samples in s direction */
+ REAL t_steps; /* max samples in t direction */
+ REAL sampling_method;
+ REAL culling_method; /* check for culling */
+ REAL bbox_subdividing;
+ Mapdesc * next;
+ Backend & backend;
+
+ void bbox( REAL [2][MAXCOORDS], REAL *, int, int, int, int );
+ REAL maxDifference( int, REAL *, int );
+ static void copy( Maxmatrix, long, INREAL *, long, long );
+
+ /* individual control point routines */
+ static void transform4d( float[4], float[4], float[4][4] );
+ static void multmatrix4d ( float[4][4], const float[4][4],
+ const float[4][4] );
+ void copyPt( REAL *, REAL * );
+ void sumPt( REAL *, REAL *, REAL *, REAL, REAL );
+ void xformSampling( REAL *, REAL * );
+ void xformCulling( REAL *, REAL * );
+ void xformRational( Maxmatrix, REAL *, REAL * );
+ void xformNonrational( Maxmatrix, REAL *, REAL * );
+ unsigned int clipbits( REAL * );
+};
+
+inline void
+Mapdesc::setBmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( bmat, hcoords, mat, rstride, cstride );
+}
+
+inline void
+Mapdesc::setCmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( cmat, hcoords, mat, rstride, cstride );
+}
+
+inline void
+Mapdesc::setSmat( INREAL *mat, long rstride, long cstride )
+{
+ copy( smat, hcoords, mat, rstride, cstride );
+}
+
+inline long
+Mapdesc::getType( void )
+{
+ return type;
+}
+
+inline void
+Mapdesc::xformCulling( REAL *d, REAL *s )
+{
+ if( isrational )
+ xformRational( cmat, d, s );
+ else
+ xformNonrational( cmat, d, s );
+}
+
+inline void
+Mapdesc::xformSampling( REAL *d, REAL *s )
+{
+ if( isrational )
+ xformRational( smat, d, s );
+ else
+ xformNonrational( smat, d, s );
+}
+
+inline int
+Mapdesc::isRational( void )
+{
+ return isrational ? 1 : 0;
+}
+
+inline int
+Mapdesc::getNcoords( void )
+{
+ return ncoords;
+}
+
+inline int
+Mapdesc::isConstantSampling( void )
+{
+ return ((sampling_method == N_FIXEDRATE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isDomainSampling( void )
+{
+ return ((sampling_method == N_DOMAINDISTANCE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isParametricDistanceSampling( void )
+{
+ return ((sampling_method == N_PARAMETRICDISTANCE) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isObjectSpaceParaSampling( void )
+{
+ return ((sampling_method == N_OBJECTSPACE_PARA) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isObjectSpacePathSampling( void )
+{
+ return ((sampling_method == N_OBJECTSPACE_PATH) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isSurfaceAreaSampling( void )
+{
+ return ((sampling_method == N_SURFACEAREA) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isPathLengthSampling( void )
+{
+ return ((sampling_method == N_PATHLENGTH) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isRangeSampling( void )
+{
+ return ( isParametricDistanceSampling() || isPathLengthSampling() ||
+ isSurfaceAreaSampling() ||
+ isObjectSpaceParaSampling() ||
+ isObjectSpacePathSampling());
+}
+
+inline int
+Mapdesc::isSampling( void )
+{
+ return isRangeSampling() || isConstantSampling() || isDomainSampling();
+}
+
+inline int
+Mapdesc::isCulling( void )
+{
+ return ((culling_method != N_NOCULLING) ? 1 : 0);
+}
+
+inline int
+Mapdesc::isBboxSubdividing( void )
+{
+ return ((bbox_subdividing != N_NOBBOXSUBDIVISION) ? 1 : 0);
+}
+#endif /* __glumapdesc_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mapdescv.cc b/mesalib/src/glu/sgi/libnurbs/internals/mapdescv.cc
new file mode 100644
index 000000000..35b38b141
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mapdescv.cc
@@ -0,0 +1,243 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mapdescv.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mystring.h"
+#include "mymath.h"
+#include "nurbsconsts.h"
+#include "mapdesc.h"
+
+/*--------------------------------------------------------------------------
+ * calcPartialVelocity - calculate maximum magnitude of a given partial
+ * derivative
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcPartialVelocity (
+ REAL *p,
+ int stride,
+ int ncols,
+ int partial,
+ REAL range )
+{
+ REAL tmp[MAXORDER][MAXCOORDS];
+ REAL mag[MAXORDER];
+
+ assert( ncols <= MAXORDER );
+
+ int j, k, t;
+ // copy inhomogeneous control points into temporary array
+ for( j=0; j != ncols; j++ )
+ for( k=0; k != inhcoords; k++ )
+ tmp[j][k] = p[j*stride + k];
+
+ for( t=0; t != partial; t++ )
+ for( j=0; j != ncols-t-1; j++ )
+ for( k=0; k != inhcoords; k++ )
+ tmp[j][k] = tmp[j+1][k] - tmp[j][k];
+
+ // compute magnitude and store in mag array
+ for( j=0; j != ncols-partial; j++ ) {
+ mag[j] = 0.0;
+ for( k=0; k != inhcoords; k++ )
+ mag[j] += tmp[j][k] * tmp[j][k];
+ }
+
+ // compute scale factor
+ REAL fac = 1;
+ REAL invt = 1.0 / range;
+ for( t = ncols-1; t != ncols-1-partial; t-- )
+ fac *= t * invt;
+
+ // compute max magnitude of all entries in array
+ REAL max = 0.0;
+ for( j=0; j != ncols-partial; j++ )
+ if( mag[j] > max ) max = mag[j];
+ max = fac * sqrtf( (float) max );
+
+ return max;
+}
+
+/*--------------------------------------------------------------------------
+ * calcPartialVelocity - calculate maximum magnitude of a given partial
+ * derivative
+ *--------------------------------------------------------------------------
+ */
+REAL
+Mapdesc::calcPartialVelocity (
+ REAL *dist,
+ REAL *p,
+ int rstride,
+ int cstride,
+ int nrows,
+ int ncols,
+ int spartial,
+ int tpartial,
+ REAL srange,
+ REAL trange,
+ int side )
+{
+ REAL tmp[MAXORDER][MAXORDER][MAXCOORDS];
+ REAL mag[MAXORDER][MAXORDER];
+
+ assert( nrows <= MAXORDER );
+ assert( ncols <= MAXORDER );
+
+ REAL *tp = &tmp[0][0][0];
+ REAL *mp = &mag[0][0];
+ const int istride = sizeof( tmp[0]) / sizeof( tmp[0][0][0] );
+ const int jstride = sizeof( tmp[0][0]) / sizeof( tmp[0][0][0] );
+ /*
+ const int kstride = sizeof( tmp[0][0][0]) / sizeof( tmp[0][0][0] );
+ */
+ const int mistride = sizeof( mag[0]) / sizeof( mag[0][0] );
+ const int mjstride = sizeof( mag[0][0]) / sizeof( mag[0][0] );
+ const int idist = nrows * istride;
+ const int jdist = ncols * jstride;
+ /*
+ const int kdist = inhcoords * kstride;
+ */
+ const int id = idist - spartial * istride;
+ const int jd = jdist - tpartial * jstride;
+
+ {
+ // copy control points
+ REAL *ti = tp;
+ REAL *qi = p;
+ REAL *til = tp + idist;
+ for( ; ti != til; ) {
+ REAL *tj = ti;
+ REAL *qj = qi;
+ REAL *tjl = ti + jdist;
+ for( ; tj != tjl; ) {
+ for( int k=0; k != inhcoords; k++ ) {
+ tj[k] = qj[k];
+ }
+ tj += jstride;
+ qj += cstride;
+ }
+ ti += istride;
+ qi += rstride;
+ }
+ }
+
+ {
+ // compute (s)-partial derivative control points
+ REAL *til = tp + idist - istride;
+ const REAL *till = til - ( spartial * istride );
+ for( ; til != till; til -= istride )
+ for( REAL *ti = tp; ti != til; ti += istride )
+ for( REAL *tj = ti, *tjl = tj + jdist; tj != tjl; tj += jstride )
+ for( int k=0; k != inhcoords; k++ )
+ tj[k] = tj[k+istride] - tj[k];
+ }
+
+ {
+ // compute (s,t)-partial derivative control points
+ REAL *tjl = tp + jdist - jstride;
+ const REAL *tjll = tjl - ( tpartial * jstride );
+ for( ; tjl != tjll; tjl -= jstride )
+ for( REAL *tj = tp; tj != tjl; tj += jstride )
+ for( REAL *ti = tj, *til = ti + id; ti != til; ti += istride )
+ for( int k=0; k != inhcoords; k++ )
+ ti[k] = ti[k+jstride] - ti[k];
+
+ }
+
+ REAL max = 0.0;
+ {
+ // compute magnitude and store in mag array
+ memset( (void *) mp, 0, sizeof( mag ) );
+ for( REAL *ti = tp, *mi = mp, *til = tp + id; ti != til; ti += istride, mi += mistride )
+ for( REAL *tj = ti, *mj = mi, *tjl = ti + jd; tj != tjl; tj += jstride, mj += mjstride ) {
+ for( int k=0; k != inhcoords; k++ )
+ *mj += tj[k] * tj[k];
+ if( *mj > max ) max = *mj;
+ }
+
+ }
+
+ int i, j;
+
+ // compute scale factor
+ REAL fac = 1.0;
+ {
+ REAL invs = 1.0 / srange;
+ REAL invt = 1.0 / trange;
+ for( int s = nrows-1, slast = s-spartial; s != slast; s-- )
+ fac *= s * invs;
+ for( int t = ncols-1, tlast = t-tpartial; t != tlast; t-- )
+ fac *= t * invt;
+ }
+
+ if( side == 0 ) {
+ // compute max magnitude of first and last column
+ dist[0] = 0.0;
+ dist[1] = 0.0;
+ for( i=0; i != nrows-spartial; i++ ) {
+ j = 0;
+ if( mag[i][j] > dist[0] ) dist[0] = mag[i][j];
+
+ j = ncols-tpartial-1;
+ if( mag[i][j] > dist[1] ) dist[1] = mag[i][j];
+ }
+ dist[0] = fac * sqrtf( dist[0] );
+ dist[1] = fac * sqrtf( dist[1] );
+ } else if( side == 1 ) {
+ // compute max magnitude of first and last row
+ dist[0] = 0.0;
+ dist[1] = 0.0;
+ for( j=0; j != ncols-tpartial; j++ ) {
+ i = 0;
+ if( mag[i][j] > dist[0] ) dist[0] = mag[i][j];
+
+ i = nrows-spartial-1;
+ if( mag[i][j] > dist[1] ) dist[1] = mag[i][j];
+ }
+ dist[0] = fac * sqrtf( dist[0] );
+ dist[1] = fac * sqrtf( dist[1] );
+ }
+
+ max = fac * sqrtf( (float) max );
+
+ return max;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/maplist.cc b/mesalib/src/glu/sgi/libnurbs/internals/maplist.cc
new file mode 100644
index 000000000..f944d1529
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/maplist.cc
@@ -0,0 +1,117 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * maplist.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mymath.h"
+#include "nurbsconsts.h"
+#include "maplist.h"
+#include "mapdesc.h"
+#include "backend.h"
+
+Maplist::Maplist( Backend& b )
+ : mapdescPool( sizeof( Mapdesc ), 10, "mapdesc pool" ),
+ backend( b )
+{
+ maps = 0; lastmap = &maps;
+}
+
+void
+Maplist::initialize( void )
+{
+ freeMaps();
+ define( N_P2D, 0, 2 );
+ define( N_P2DR, 1, 3 );
+}
+
+void
+Maplist::add( long type, int israt, int ncoords )
+{
+ *lastmap = new(mapdescPool) Mapdesc( type, israt, ncoords, backend );
+ lastmap = &((*lastmap)->next);
+}
+
+void
+Maplist::define( long type, int israt, int ncoords )
+{
+#ifndef NDEBUG // to avoid warning
+ Mapdesc *m = locate( type );
+ assert( m == NULL || ( m->isrational == israt && m->ncoords == ncoords ) );
+#endif
+ add( type, israt, ncoords );
+}
+
+void
+Maplist::remove( Mapdesc *m )
+{
+ for( Mapdesc **curmap = &maps; *curmap; curmap = &((*curmap)->next) ) {
+ if( *curmap == m ) {
+ *curmap = m->next;
+ m->deleteMe( mapdescPool );
+ return;
+ }
+ }
+ abort();
+}
+
+void
+Maplist::freeMaps( void )
+{
+ mapdescPool.clear();
+ maps = 0;
+ lastmap = &maps;
+}
+
+Mapdesc *
+Maplist::find( long type )
+{
+ Mapdesc *val = locate( type );
+ assert( val != 0 );
+ return val;
+}
+
+Mapdesc *
+Maplist::locate( long type )
+{
+ Mapdesc *m;
+ for( m = maps; m; m = m->next )
+ if( m->getType() == type ) break;
+ return m;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/maplist.h b/mesalib/src/glu/sgi/libnurbs/internals/maplist.h
new file mode 100644
index 000000000..49720e49b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/maplist.h
@@ -0,0 +1,81 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * maplist.h
+ *
+ */
+
+#ifndef __glumaplist_h_
+#define __glumaplist_h_
+
+#include "types.h"
+#include "defines.h"
+#include "bufpool.h"
+
+class Backend;
+class Mapdesc;
+
+class Maplist {
+public:
+ Maplist( Backend & );
+ void define( long, int, int );
+ inline void undefine( long );
+ inline int isMap( long );
+
+ void initialize( void );
+ Mapdesc * find( long );
+ Mapdesc * locate( long );
+
+private:
+ Pool mapdescPool;
+ Mapdesc * maps;
+ Mapdesc ** lastmap;
+ Backend & backend;
+
+ void add( long, int, int );
+ void remove( Mapdesc * );
+ void freeMaps( void );
+};
+
+inline int
+Maplist::isMap( long type )
+{
+ return (locate( type ) ? 1 : 0);
+}
+
+inline void
+Maplist::undefine( long type )
+{
+ Mapdesc *m = locate( type );
+ assert( m != 0 );
+ remove( m );
+}
+#endif /* __glumaplist_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mesher.cc b/mesalib/src/glu/sgi/libnurbs/internals/mesher.cc
new file mode 100644
index 000000000..9cc436adb
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mesher.cc
@@ -0,0 +1,486 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * mesher.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "gridvertex.h"
+#include "gridtrimvertex.h"
+#include "jarcloc.h"
+#include "gridline.h"
+#include "trimline.h"
+#include "uarray.h"
+#include "backend.h"
+#include "mesher.h"
+
+
+const float Mesher::ZERO = 0.0;
+
+Mesher::Mesher( Backend& b )
+ : backend( b ),
+ p( sizeof( GridTrimVertex ), 100, "GridTrimVertexPool" )
+{
+ stacksize = 0;
+ vdata = 0;
+ lastedge = 0; //needed to prevent purify UMR
+}
+
+Mesher::~Mesher( void )
+{
+ if( vdata ) delete[] vdata;
+}
+
+void
+Mesher::init( unsigned int npts )
+{
+ p.clear();
+ if( stacksize < npts ) {
+ stacksize = 2 * npts;
+ if( vdata ) delete[] vdata;
+ vdata = new GridTrimVertex_p[stacksize];
+ }
+}
+
+inline void
+Mesher::push( GridTrimVertex *gt )
+{
+ assert( itop+1 != (int)stacksize );
+ vdata[++itop] = gt;
+}
+
+inline void
+Mesher::pop( long )
+{
+}
+
+inline void
+Mesher::openMesh()
+{
+ backend.bgntmesh( "addedge" );
+}
+
+inline void
+Mesher::closeMesh()
+{
+ backend.endtmesh();
+}
+
+inline void
+Mesher::swapMesh()
+{
+ backend.swaptmesh();
+}
+
+inline void
+Mesher::clearStack()
+{
+ itop = -1;
+ last[0] = 0;
+}
+
+void
+Mesher::finishLower( GridTrimVertex *gtlower )
+{
+ for( push(gtlower);
+ nextlower( gtlower=new(p) GridTrimVertex );
+ push(gtlower) )
+ addLower();
+ addLast();
+}
+
+void
+Mesher::finishUpper( GridTrimVertex *gtupper )
+{
+ for( push(gtupper);
+ nextupper( gtupper=new(p) GridTrimVertex );
+ push(gtupper) )
+ addUpper();
+ addLast();
+}
+
+void
+Mesher::mesh( void )
+{
+ GridTrimVertex *gtlower, *gtupper;
+
+ Hull::init( );
+ nextupper( gtupper = new(p) GridTrimVertex );
+ nextlower( gtlower = new(p) GridTrimVertex );
+
+ clearStack();
+ openMesh();
+ push(gtupper);
+
+ nextupper( gtupper = new(p) GridTrimVertex );
+ nextlower( gtlower );
+
+ assert( gtupper->t && gtlower->t );
+
+ if( gtupper->t->param[0] < gtlower->t->param[0] ) {
+ push(gtupper);
+ lastedge = 1;
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
+ push(gtlower);
+ lastedge = 0;
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ } else {
+ if( lastedge == 0 ) {
+ push(gtupper);
+ lastedge = 1;
+ if( nextupper(gtupper=new(p) GridTrimVertex) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else {
+ push(gtlower);
+ lastedge = 0;
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ }
+ }
+
+ while ( 1 ) {
+ if( gtupper->t->param[0] < gtlower->t->param[0] ) {
+ push(gtupper);
+ addUpper();
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else if( gtupper->t->param[0] > gtlower->t->param[0] ) {
+ push(gtlower);
+ addLower();
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ } else {
+ if( lastedge == 0 ) {
+ push(gtupper);
+ addUpper();
+ if( nextupper( gtupper=new(p) GridTrimVertex ) == 0 ) {
+ finishLower(gtlower);
+ return;
+ }
+ } else {
+ push(gtlower);
+ addLower();
+ if( nextlower( gtlower=new(p) GridTrimVertex ) == 0 ) {
+ finishUpper(gtupper);
+ return;
+ }
+ }
+ }
+ }
+}
+
+inline int
+Mesher::isCcw( int ilast )
+{
+ REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
+ return (area < ZERO) ? 0 : 1;
+}
+
+inline int
+Mesher::isCw( int ilast )
+{
+ REAL area = det3( vdata[ilast]->t, vdata[itop-1]->t, vdata[itop-2]->t );
+ return (area > -ZERO) ? 0 : 1;
+}
+
+inline int
+Mesher::equal( int x, int y )
+{
+ return( last[0] == vdata[x] && last[1] == vdata[y] );
+}
+
+inline void
+Mesher::copy( int x, int y )
+{
+ last[0] = vdata[x]; last[1] = vdata[y];
+}
+
+inline void
+Mesher::move( int x, int y )
+{
+ vdata[x] = vdata[y];
+}
+
+inline void
+Mesher::output( int x )
+{
+ backend.tmeshvert( vdata[x] );
+}
+
+/*---------------------------------------------------------------------------
+ * addedge - addedge an edge to the triangulation
+ *
+ * This code has been re-written to generate large triangle meshes
+ * from a monotone polygon. Although smaller triangle meshes
+ * could be generated faster and with less code, larger meshes
+ * actually give better SYSTEM performance. This is because
+ * vertices are processed in the backend slower than they are
+ * generated by this code and any decrease in the number of vertices
+ * results in a decrease in the time spent in the backend.
+ *---------------------------------------------------------------------------
+ */
+
+void
+Mesher::addLast( )
+{
+ register int ilast = itop;
+
+ if( lastedge == 0 ) {
+ if( equal( 0, 1 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = 2; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ output( i );
+ swapMesh();
+ }
+ copy( 0, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( 0 );
+ for( register int i = 1; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ }
+ } else {
+ if( equal( 1, 0) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = 2; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else if( equal( ilast-1, ilast-2) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, 0 );
+ } else {
+ closeMesh(); openMesh();
+ output( 0 );
+ output( ilast );
+ for( register int i = 1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ }
+ }
+ closeMesh();
+ //for( register long k=0; k<=ilast; k++ ) pop( k );
+}
+
+void
+Mesher::addUpper( )
+{
+ register int ilast = itop;
+
+ if( lastedge == 0 ) {
+ if( equal( 0, 1 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = 2; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ output( i );
+ swapMesh();
+ }
+ copy( 0, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( 0 );
+ for( register int i = 1; i < ilast; i++ ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ }
+ lastedge = 1;
+ //for( register long k=0; k<ilast-1; k++ ) pop( k );
+ move( 0, ilast-1 );
+ move( 1, ilast );
+ itop = 1;
+ } else {
+ if( ! isCcw( ilast ) ) return;
+ do {
+ itop--;
+ } while( (itop > 1) && isCcw( ilast ) );
+
+ if( equal( ilast-1, ilast-2 ) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i=ilast-3; i>=itop-1; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, itop-1 );
+ } else if( equal( itop, itop-1 ) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = itop+1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast );
+ output( ilast-1 );
+ for( register int i=ilast-2; i>=itop-1; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, itop-1 );
+ }
+ //for( register int k=itop; k<ilast; k++ ) pop( k );
+ move( itop, ilast );
+ }
+}
+
+void
+Mesher::addLower()
+{
+ register int ilast = itop;
+
+ if( lastedge == 1 ) {
+ if( equal( 1, 0) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i = 2; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ } else if( equal( ilast-1, ilast-2) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i = ilast-3; i >= 0; i-- ) {
+ swapMesh();
+ output( i );
+ }
+ copy( ilast, 0 );
+ } else {
+ closeMesh(); openMesh();
+ output( 0 );
+ output( ilast );
+ for( register int i = 1; i < ilast; i++ ) {
+ output( i );
+ swapMesh();
+ }
+ copy( ilast-1, ilast );
+ }
+
+ lastedge = 0;
+ //for( register long k=0; k<ilast-1; k++ ) pop( k );
+ move( 0, ilast-1 );
+ move( 1, ilast );
+ itop = 1;
+ } else {
+ if( ! isCw( ilast ) ) return;
+ do {
+ itop--;
+ } while( (itop > 1) && isCw( ilast ) );
+
+ if( equal( ilast-2, ilast-1) ) {
+ swapMesh();
+ output( ilast );
+ for( register int i=ilast-3; i>=itop-1; i--) {
+ output( i );
+ swapMesh( );
+ }
+ copy( itop-1, ilast );
+ } else if( equal( itop-1, itop) ) {
+ output( ilast );
+ swapMesh();
+ for( register int i=itop+1; i<ilast; i++ ) {
+ swapMesh( );
+ output( i );
+ }
+ copy( ilast, ilast-1 );
+ } else {
+ closeMesh(); openMesh();
+ output( ilast-1 );
+ output( ilast );
+ for( register int i=ilast-2; i>=itop-1; i-- ) {
+ output( i );
+ swapMesh( );
+ }
+ copy( itop-1, ilast );
+ }
+ //for( register int k=itop; k<ilast; k++ ) pop( k );
+ move( itop, ilast );
+ }
+}
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mesher.h b/mesalib/src/glu/sgi/libnurbs/internals/mesher.h
new file mode 100644
index 000000000..bb65d0f1c
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mesher.h
@@ -0,0 +1,83 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mesher.h
+ *
+ */
+
+#ifndef __glumesher_h_
+#define __glumesher_h_
+
+#include "hull.h"
+
+class TrimRegion;
+class Backend;
+class Pool;
+// struct GridTrimVertex;
+
+
+class Mesher : virtual public TrimRegion, public Hull {
+public:
+ Mesher( Backend & );
+ ~Mesher( void );
+ void init( unsigned int );
+ void mesh( void );
+
+private:
+ static const float ZERO;
+ Backend& backend;
+
+ Pool p;
+ unsigned int stacksize;
+ GridTrimVertex ** vdata;
+ GridTrimVertex * last[2];
+ int itop;
+ int lastedge;
+
+ inline void openMesh( void );
+ inline void swapMesh( void );
+ inline void closeMesh( void );
+ inline int isCcw( int );
+ inline int isCw( int );
+ inline void clearStack( void );
+ inline void push( GridTrimVertex * );
+ inline void pop( long );
+ inline void move( int, int );
+ inline int equal( int, int );
+ inline void copy( int, int );
+ inline void output( int );
+ void addUpper( void );
+ void addLower( void );
+ void addLast( void );
+ void finishUpper( GridTrimVertex * );
+ void finishLower( GridTrimVertex * );
+};
+#endif /* __glumesher_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc b/mesalib/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc
new file mode 100644
index 000000000..2830cc743
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/monoTriangulationBackend.cc
@@ -0,0 +1,397 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "monoTriangulation.h"
+#include "polyUtil.h"
+#include "backend.h"
+#include "arc.h"
+
+void reflexChain::outputFan(Real v[2], Backend* backend)
+{
+ Int i;
+ /*
+ TrimVertex trimVert;
+ */
+ backend->bgntfan();
+
+ /*
+ trimVert.param[0]=v[0];
+ trimVert.param[1]=v[1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(v[0], v[1]);
+
+ if(isIncreasing) {
+ for(i=0; i<index_queue; i++)
+ {
+ /*
+ trimVert.param[0]=queue[i][0];
+ trimVert.param[1]=queue[i][1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(queue[i][0], queue[i][1]);
+ }
+ }
+ else {
+ for(i=index_queue-1; i>=0; i--)
+ {
+ /*
+ trimVert.param[0]=queue[i][0];
+ trimVert.param[1]=queue[i][1];
+ backend->tmeshvert(&trimVert);
+ */
+ backend->tmeshvert(queue[i][0], queue[i][1]);
+ }
+ }
+ backend->endtfan();
+}
+
+void reflexChain::processNewVertex(Real v[2], Backend* backend)
+{
+ Int i,j,k;
+ Int isReflex;
+ /*TrimVertex trimVert;*/
+ /*if there are at most one vertex in the queue, then simply insert
+ */
+ if(index_queue <=1){
+ insert(v);
+ return;
+ }
+
+ /*there are at least two vertices in the queue*/
+ j=index_queue-1;
+
+ for(i=j; i>=1; i--) {
+ if(isIncreasing) {
+ isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
+ }
+ else /*decreasing*/{
+ isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
+ }
+ if(isReflex) {
+ break;
+ }
+ }
+
+ /*
+ *if i<j then vertices: i+1--j are convex
+ * output triangle fan:
+ * v, and queue[i], i+1, ..., j
+ */
+ if(i<j)
+ {
+ backend->bgntfan();
+ /*
+ trimVert.param[0]=v[0];
+ trimVert.param[1]=v[1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(v[0], v[1]);
+
+ if(isIncreasing) {
+ for(k=i; k<=j; k++)
+ {
+ /*
+ trimVert.param[0]=queue[k][0];
+ trimVert.param[1]=queue[k][1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(queue[k][0], queue[k][1]);
+ }
+ }
+ else {
+ for(k=j; k>=i; k--)
+ {
+ /*
+ trimVert.param[0]=queue[k][0];
+ trimVert.param[1]=queue[k][1];
+ backend->tmeshvert(& trimVert);
+ */
+ backend->tmeshvert(queue[k][0], queue[k][1]);
+ }
+ }
+
+ backend->endtfan();
+ }
+
+ /*delete vertices i+1--j from the queue*/
+ index_queue = i+1;
+ /*finally insert v at the end of the queue*/
+ insert(v);
+
+}
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Backend* backend)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], backend);
+ monoTriangulationRec(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ backend);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], backend);
+ monoTriangulationRec(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ backend);
+ }
+ }/*end case neither is empty*/
+}
+
+
+void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ Arc_ptr tempV;
+ Arc_ptr topV;
+ Arc_ptr botV;
+ topV = botV = loop;
+ for(tempV = loop->next; tempV != loop; tempV = tempV->next)
+ {
+ if(compFun(topV->tail(), tempV->tail())<0) {
+ topV = tempV;
+ }
+ if(compFun(botV->tail(), tempV->tail())>0) {
+ botV = tempV;
+ }
+ }
+
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->pwlArc->npts-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->pwlArc->pts[i].param);
+ }
+ for(tempV = topV->next; tempV != botV; tempV = tempV->next)
+ {
+ for(i=0; i<=tempV->pwlArc->npts-2; i++){
+ inc_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->prev; tempV != botV; tempV = tempV->prev)
+ {
+ for(i=tempV->pwlArc->npts-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+ }
+ for(i=botV->pwlArc->npts-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->pwlArc->pts[i].param);
+ }
+
+ monoTriangulationRecFunBackend(topV->tail(), botV->tail(), &inc_chain, 0, &dec_chain, 0, compFun, backend);
+
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ Backend* backend)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, backend);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], backend);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, backend);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], backend);
+ monoTriangulationRecFunBackend(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ compFun,
+ backend);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, backend);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], backend);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], backend);
+ monoTriangulationRecFunBackend(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ compFun,
+ backend);
+ }
+ }/*end case neither is empty*/
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.cc b/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.cc
new file mode 100644
index 000000000..5845d310b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.cc
@@ -0,0 +1,260 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * monotonizer.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "arc.h"
+#include "arctess.h"
+#include "bezierarc.h"
+#include "bin.h"
+#include "mapdesc.h"
+#include "nurbsconsts.h"
+#include "subdivider.h"
+
+/*-----------------------------------------------------------------------------
+ * Subdivider::decompose - break all curves into monotone arcs
+ *-----------------------------------------------------------------------------
+ */
+int
+Subdivider::decompose( Bin& bin, REAL geo_stepsize )
+{
+ Arc_ptr jarc;
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( ! jarc->isTessellated() ) {
+ /* points have not been transformed, therefore they may be either
+ homogeneous or inhomogeneous */
+ tessellate( jarc, geo_stepsize );
+ if( jarc->isDisconnected() || jarc->next->isDisconnected() )
+ return 1;
+ }
+ }
+
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ monotonize( jarc, bin );
+ }
+
+#ifndef NDEBUG
+ for( jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ assert( isMonotone( jarc ) != 0 );
+ }
+#endif
+
+ return 0;
+}
+
+void
+Subdivider::tessellate( Arc_ptr jarc, REAL geo_stepsize )
+{
+ BezierArc *b = jarc->bezierArc;
+ Mapdesc *mapdesc = b->mapdesc;
+
+ if( mapdesc->isRational() ) {
+ REAL max = mapdesc->calcVelocityRational( b->cpts, b->stride, b->order );
+ REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
+ if( jarc->bezierArc->order != 2 )
+ arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 1 );
+ else {
+ arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 1 );
+ }
+ } else {
+ REAL max = mapdesc->calcVelocityNonrational( b->cpts, b->stride, b->order );
+ REAL arc_stepsize = (max > 1.0) ? (1.0/max) : 1.0;
+ if( jarc->bezierArc->order != 2 )
+ arctessellator.tessellateNonlinear( jarc, geo_stepsize, arc_stepsize, 0 );
+ else {
+ arctessellator.tessellateLinear( jarc, geo_stepsize, arc_stepsize, 0 );
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Subdivider::monotonize - break up a jordan arc into s,t-monotone
+ * components. This code will remove degenerate segments, including
+ * arcs of only a single point.
+ *-------------------------------------------------------------------------
+ */
+void
+Subdivider::monotonize( Arc_ptr jarc, Bin& bin )
+{
+ TrimVertex *firstvert = jarc->pwlArc->pts;
+ TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
+ long uid = jarc->nuid;
+ arc_side side = jarc->getside();
+ dir sdir = none;
+ dir tdir = none;
+ int degenerate = 1;
+
+ int nudegenerate;
+ int change;
+
+ TrimVertex *vert;
+ for( vert = firstvert; vert != lastvert; vert++ ) {
+
+ nudegenerate = 1;
+ change = 0;
+
+ /* check change relative to s axis, clear degenerate bit if needed */
+ REAL sdiff = vert[1].param[0] - vert[0].param[0];
+ if( sdiff == 0 ) {
+ if( sdir != same ) {
+ sdir = same;
+ change = 1;
+ }
+ } else if( sdiff < 0.0 ) {
+ if( sdir != down ) {
+ sdir = down;
+ change = 1;
+ }
+ nudegenerate = 0;
+ } else {
+ if( sdir != up ) {
+ sdir = up;
+ change = 1;
+ }
+ nudegenerate = 0;
+ }
+
+ /* check change relative to t axis, clear degenerate bit if needed */
+ REAL tdiff = vert[1].param[1] - vert[0].param[1];
+ if( tdiff == 0 ) {
+ if( tdir != same ) {
+ tdir = same;
+ change = 1;
+ }
+ } else if( tdiff < 0.0 ) {
+ if( tdir != down ) {
+ tdir = down;
+ change = 1;
+ }
+ nudegenerate = 0;
+ } else {
+ if( tdir != up ) {
+ tdir = up;
+ change = 1;
+ }
+ nudegenerate = 0;
+ }
+
+ if( change ) {
+ if( ! degenerate ) {
+ /* make last segment into separate pwl curve */
+ jarc->pwlArc->npts = vert - firstvert + 1;
+ jarc = (new(arcpool) Arc( side, uid ))->append( jarc );
+ jarc->pwlArc = new(pwlarcpool) PwlArc();
+ bin.addarc( jarc );
+ }
+ firstvert = jarc->pwlArc->pts = vert;
+ degenerate = nudegenerate;
+ }
+ }
+ jarc->pwlArc->npts = vert - firstvert + 1;
+
+ if( degenerate ) {
+ /* remove jarc from circularly linked list */
+ jarc->prev->next = jarc->next;
+ jarc->next->prev = jarc->prev;
+
+ assert( jarc->prev->check( ) != 0 );
+ assert( jarc->next->check( ) != 0 );
+
+ /* remove jarc from bin */
+ bin.remove_this_arc( jarc );
+
+ jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+ jarc->deleteMe( arcpool );
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Subdivider::isMonotone - return true if arc is monotone AND non-degenerate
+ *-------------------------------------------------------------------------
+ */
+int
+Subdivider::isMonotone( Arc_ptr jarc )
+{
+ TrimVertex *firstvert = jarc->pwlArc->pts;
+ TrimVertex *lastvert = firstvert + (jarc->pwlArc->npts - 1);
+
+ if( firstvert == lastvert ) return 1;
+
+ TrimVertex *vert = firstvert;
+ enum dir sdir;
+ enum dir tdir;
+
+ REAL diff = vert[1].param[0] - vert[0].param[0];
+ if( diff == 0.0 )
+ sdir = same;
+ else if( diff < 0.0 )
+ sdir = down;
+ else
+ sdir = up;
+
+ diff = vert[1].param[1] - vert[0].param[1];
+ if( diff == 0.0 )
+ tdir = same;
+ else if( diff < 0.0 )
+ tdir = down;
+ else
+ tdir = up;
+
+ if( (sdir == same) && (tdir == same) ) return 0;
+
+ for( ++vert ; vert != lastvert; vert++ ) {
+ diff = vert[1].param[0] - vert[0].param[0];
+ if( diff == 0.0 ) {
+ if( sdir != same ) return 0;
+ } else if( diff < 0.0 ) {
+ if( sdir != down ) return 0;
+ } else {
+ if( sdir != up ) return 0;
+ }
+
+ diff = vert[1].param[1] - vert[0].param[1];
+ if( diff == 0.0 ) {
+ if( tdir != same ) return 0;
+ } else if( diff < 0.0 ) {
+ if( tdir != down ) return 0;
+ } else {
+ if( tdir != up ) return 0;
+ }
+ }
+ return 1;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.h b/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.h
new file mode 100644
index 000000000..e951084ff
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/monotonizer.h
@@ -0,0 +1,64 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * monotonizer.h
+ *
+ */
+
+#ifndef __glumonotonizer_h_
+#define __glumonotonizer_h_
+
+#include "mysetjmp.h"
+#include "types.h"
+
+class Arc;
+class ArcTessellator;
+class Pool;
+class Bin;
+class PwlArcPool;
+class Mapdesc;
+
+class Monotonizer {
+ ArcTessellator& arctessellator;
+ Pool& arcpool;
+ Pool& pwlarcpool;
+ jmp_buf& nurbsJmpBuf;
+
+ enum dir { down, same, up, none };
+ void tessellate( Arc *, REAL );
+ void monotonize( Arc *, Bin & );
+ int isMonotone( Arc * );
+public:
+ Monotonizer( ArcTessellator& at, Pool& ap, Pool& p, jmp_buf& j )
+ : arctessellator(at), arcpool(ap), pwlarcpool(p), nurbsJmpBuf(j) {}
+ int decompose( Bin &, REAL );
+};
+#endif /* __glumonotonizer_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/myassert.h b/mesalib/src/glu/sgi/libnurbs/internals/myassert.h
new file mode 100644
index 000000000..cbd6006f5
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/myassert.h
@@ -0,0 +1,51 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * myassert.h
+ *
+ */
+
+#ifndef __glumyassert_h_
+#define __glumyassert_h_
+
+#ifdef STANDALONE
+#define assert(EX) ((void)0)
+#endif
+
+#ifdef LIBRARYBUILD
+#include <assert.h>
+#endif
+
+#ifdef GLBUILD
+#define assert(EX) ((void)0)
+#endif
+
+#endif /* __glumyassert_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mycode.cc b/mesalib/src/glu/sgi/libnurbs/internals/mycode.cc
new file mode 100644
index 000000000..3625cacd7
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mycode.cc
@@ -0,0 +1,67 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "mymath.h"
+
+#ifdef NEEDCEILF
+
+float ceilf( float x )
+{
+ if( x < 0 ) {
+ float nx = -x;
+ int ix = (int) nx;
+ return (float) -ix;
+ } else {
+ int ix = (int) x;
+ if( x == (float) ix ) return x;
+ return (float) (ix+1);
+ }
+}
+
+float floorf( float x )
+{
+ if( x < 0 ) {
+ float nx = -x;
+ int ix = (int) nx;
+ if( nx == (float) ix ) return x;
+ return (float) -(ix+1);
+ } else {
+ int ix = (int) x;
+ return (float) ix;
+ }
+}
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mymath.h b/mesalib/src/glu/sgi/libnurbs/internals/mymath.h
new file mode 100644
index 000000000..17ef7237f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mymath.h
@@ -0,0 +1,68 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mymath.h
+ *
+ */
+
+#ifndef __glumymath_h_
+#define __glumymath_h_
+
+#ifdef GLBUILD
+#define sqrtf gl_fsqrt
+#endif
+
+#if defined(GLBUILD) || defined(STANDALONE)
+#define M_SQRT2 1.41421356237309504880
+#define ceilf myceilf
+#define floorf myfloorf
+#define sqrtf sqrt
+extern "C" double sqrt(double);
+extern "C" float ceilf(float);
+extern "C" float floorf(float);
+#define NEEDCEILF
+#endif
+
+#ifdef LIBRARYBUILD
+#include <math.h>
+#endif
+
+#if !defined sqrtf
+# define sqrtf(x) ((float)sqrt(x))
+#endif
+#if !defined ceilf
+# define ceilf(x) ((float)ceil(x))
+#endif
+#if !defined floorf
+# define floorf(x) ((float)floor(x))
+#endif
+
+#endif /* __glumymath_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mysetjmp.h b/mesalib/src/glu/sgi/libnurbs/internals/mysetjmp.h
new file mode 100644
index 000000000..2a3f6a87b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mysetjmp.h
@@ -0,0 +1,85 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mysetjmp.h
+ *
+ */
+
+#ifndef __glumysetjmp_h_
+#define __glumysetjmp_h_
+
+#ifdef STANDALONE
+struct JumpBuffer;
+extern "C" JumpBuffer *newJumpbuffer( void );
+extern "C" void deleteJumpbuffer(JumpBuffer *);
+extern "C" void mylongjmp( JumpBuffer *, int );
+extern "C" int mysetjmp( JumpBuffer * );
+#endif
+
+#ifdef GLBUILD
+#define setjmp gl_setjmp
+#define longjmp gl_longjmp
+#endif
+
+#if defined(LIBRARYBUILD) || defined(GLBUILD)
+#include <setjmp.h>
+#include <stdlib.h>
+
+struct JumpBuffer {
+ jmp_buf buf;
+};
+
+inline JumpBuffer *
+newJumpbuffer( void )
+{
+ return (JumpBuffer *) malloc( sizeof( JumpBuffer ) );
+}
+
+inline void
+deleteJumpbuffer(JumpBuffer *jb)
+{
+ free( (void *) jb);
+}
+
+inline void
+mylongjmp( JumpBuffer *j, int code )
+{
+ ::longjmp( j->buf, code );
+}
+
+inline int
+mysetjmp( JumpBuffer *j )
+{
+ return setjmp( j->buf );
+}
+#endif
+
+#endif /* __glumysetjmp_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/mystring.h b/mesalib/src/glu/sgi/libnurbs/internals/mystring.h
new file mode 100644
index 000000000..d2952da89
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/mystring.h
@@ -0,0 +1,56 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystring.h
+ *
+ */
+
+#ifndef __glumystring_h_
+#define __glumystring_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void * memcpy(void *, const void *, size_t);
+extern "C" void * memset(void *, int, size_t);
+#endif
+
+#ifdef GLBUILD
+#define memcpy(a,b,c) bcopy(b,a,c)
+#define memset(a,b,c) bzero(a,c)
+extern "C" void bcopy(const void *, void *, int);
+extern "C" void bzero(void *, int);
+#endif
+
+#ifdef LIBRARYBUILD
+#include <string.h>
+#endif
+
+#endif /* __glumystring_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/nurbsconsts.h b/mesalib/src/glu/sgi/libnurbs/internals/nurbsconsts.h
new file mode 100644
index 000000000..acc5d7f31
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/nurbsconsts.h
@@ -0,0 +1,120 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * nurbsconsts.h
+ *
+ */
+
+#ifndef __glunurbsconsts_h_
+#define __glunurbsconsts_h_
+
+/* NURBS Properties - one set per map,
+ each takes a single INREAL arg */
+#define N_SAMPLING_TOLERANCE 1
+#define N_S_RATE 6
+#define N_T_RATE 7
+#define N_CLAMPFACTOR 13
+#define N_NOCLAMPING 0.0
+#define N_MINSAVINGS 14
+#define N_NOSAVINGSSUBDIVISION 0.0
+
+/* NURBS Properties - one set per map,
+ each takes an enumerated value */
+#define N_CULLING 2
+#define N_NOCULLING 0.0
+#define N_CULLINGON 1.0
+#define N_SAMPLINGMETHOD 10
+#define N_NOSAMPLING 0.0
+#define N_FIXEDRATE 3.0
+#define N_DOMAINDISTANCE 2.0
+#define N_PARAMETRICDISTANCE 5.0
+#define N_PATHLENGTH 6.0
+#define N_SURFACEAREA 7.0
+#define N_OBJECTSPACE_PARA 8.0
+#define N_OBJECTSPACE_PATH 9.0
+#define N_BBOX_SUBDIVIDING 17
+#define N_NOBBOXSUBDIVISION 0.0
+#define N_BBOXTIGHT 1.0
+#define N_BBOXROUND 2.0
+
+/* NURBS Rendering Properties - one set per renderer
+ each takes an enumerated value */
+#define N_DISPLAY 3
+#define N_FILL 1.0
+#define N_OUTLINE_POLY 2.0
+#define N_OUTLINE_TRI 3.0
+#define N_OUTLINE_QUAD 4.0
+#define N_OUTLINE_PATCH 5.0
+#define N_OUTLINE_PARAM 6.0
+#define N_OUTLINE_PARAM_S 7.0
+#define N_OUTLINE_PARAM_ST 8.0
+#define N_OUTLINE_SUBDIV 9.0
+#define N_OUTLINE_SUBDIV_S 10.0
+#define N_OUTLINE_SUBDIV_ST 11.0
+#define N_ISOLINE_S 12.0
+#define N_ERRORCHECKING 4
+#define N_NOMSG 0.0
+#define N_MSG 1.0
+
+/* GL 4.0 propeties not defined above */
+#ifndef N_PIXEL_TOLERANCE
+#define N_PIXEL_TOLERANCE N_SAMPLING_TOLERANCE
+#define N_ERROR_TOLERANCE 20
+#define N_SUBDIVISIONS 5
+#define N_TILES 8
+#define N_TMP1 9
+#define N_TMP2 N_SAMPLINGMETHOD
+#define N_TMP3 11
+#define N_TMP4 12
+#define N_TMP5 N_CLAMPFACTOR
+#define N_TMP6 N_MINSAVINGS
+#define N_S_STEPS N_S_RATE
+#define N_T_STEPS N_T_RATE
+#endif
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL matrix argument */
+#define N_CULLINGMATRIX 1
+#define N_SAMPLINGMATRIX 2
+#define N_BBOXMATRIX 3
+
+
+/* NURBS Rendering Properties - one set per map,
+ each takes an INREAL vector argument */
+#define N_BBOXSIZE 4
+
+/* type argument for trimming curves */
+#ifndef N_P2D
+#define N_P2D 0x8
+#define N_P2DR 0xd
+#endif
+
+#endif /* __glunurbsconsts_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc b/mesalib/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc
new file mode 100644
index 000000000..520bd419e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/nurbsinterfac.cc
@@ -0,0 +1,537 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbsinterfac.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "nurbsconsts.h"
+#include "nurbstess.h"
+#include "bufpool.h"
+#include "quilt.h"
+#include "displaylist.h"
+#include "knotvector.h"
+#include "mapdesc.h"
+
+#define THREAD( work, arg, cleanup ) \
+ if( dl ) {\
+ arg->save = 1;\
+ dl->append( (PFVS)&NurbsTessellator::work, (void *) arg, (PFVS)&NurbsTessellator::cleanup );\
+ } else {\
+ arg->save = 0;\
+ work( arg );\
+ }
+
+#define THREAD2( work ) \
+ if( dl ) {\
+ dl->append( (PFVS)&NurbsTessellator::work, 0, 0 );\
+ } else {\
+ work( );\
+ }
+
+NurbsTessellator::NurbsTessellator( BasicCurveEvaluator &c, BasicSurfaceEvaluator& e)
+ : maplist( backend ),
+ backend( c, e ),
+ subdivider( renderhints, backend ),
+ o_pwlcurvePool( sizeof( O_pwlcurve ), 32, "o_pwlcurvePool" ),
+ o_nurbscurvePool( sizeof( O_nurbscurve ), 32, "o_nurbscurvePool"),
+ o_curvePool( sizeof( O_curve ), 32, "o_curvePool" ),
+ o_trimPool( sizeof( O_trim ), 32, "o_trimPool" ),
+ o_surfacePool( sizeof( O_surface ), 1, "o_surfacePool" ),
+ o_nurbssurfacePool( sizeof( O_nurbssurface ), 4, "o_nurbssurfacePool" ),
+ propertyPool( sizeof( Property ), 32, "propertyPool" ),
+ quiltPool( sizeof( Quilt ), 32, "quiltPool" )
+{
+ dl = 0;
+ inSurface = 0;
+ inCurve = 0;
+ inTrim = 0;
+ playBack = 0;
+ jumpbuffer = newJumpbuffer();
+ subdivider.setJumpbuffer( jumpbuffer );
+}
+
+NurbsTessellator::~NurbsTessellator( void )
+{
+ if( inTrim ) {
+ do_nurbserror( 12 );
+ endtrim();
+ }
+
+ if( inSurface ) {
+ *nextNurbssurface = 0;
+ do_freeall();
+ }
+
+ if (jumpbuffer) {
+ deleteJumpbuffer(jumpbuffer);
+ jumpbuffer= 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * bgnsurface - allocate and initialize an o_surface structure
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgnsurface( long nuid )
+{
+ O_surface *o_surface = new(o_surfacePool) O_surface;
+ o_surface->nuid = nuid;
+ THREAD( do_bgnsurface, o_surface, do_freebgnsurface );
+}
+
+/*-----------------------------------------------------------------------------
+ * bgncurve - allocate an initialize an o_curve structure
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgncurve( long nuid )
+{
+ O_curve *o_curve = new(o_curvePool) O_curve;
+ o_curve->nuid = nuid;
+ THREAD( do_bgncurve, o_curve, do_freebgncurve );
+}
+/*-----------------------------------------------------------------------------
+ * endcurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::endcurve( void )
+{
+ THREAD2( do_endcurve );
+}
+
+/*-----------------------------------------------------------------------------
+ * endsurface - user level end of surface call
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::endsurface( void )
+{
+ THREAD2( do_endsurface );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * bgntrim - allocate and initialize a new trim loop structure (o_trim )
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::bgntrim( void )
+{
+ O_trim *o_trim = new(o_trimPool) O_trim;
+ THREAD( do_bgntrim, o_trim, do_freebgntrim );
+}
+
+/*-----------------------------------------------------------------------------
+ * endtrim -
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::endtrim( void )
+{
+ THREAD2( do_endtrim );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pwlcurve -
+ *
+ * count - number of points on curve
+ * array - array of points on curve
+ * byte_stride - distance between points in bytes
+ * type - valid data flag
+ *
+ * Client: Gl user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::pwlcurve( long count, INREAL array[], long byte_stride, long type )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if ( (type != N_P2D) && (type != N_P2DR) ) {
+ do_nurbserror( 22 );
+ isDataValid = 0;
+ return;
+ }
+ if( count < 0 ) {
+ do_nurbserror( 33 );
+ isDataValid = 0;
+ return;
+ }
+ if( byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+#ifdef NOTDEF
+ if( mapdesc->isRational() ) {
+ INREAL *p = array;
+ INREAL x = p[0]; INREAL y = p[1]; INREAL w = p[2];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ for( long i = 1; i != count; i++ ) {
+ if( p[0] == x && p[1] == y && p[2] == w ) break;
+ x = p[0]; y = p[1]; w = p[2];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ }
+ if( i != count ) {
+ do_nurbserror( 37 );
+ _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
+ isDataValid = 0;
+ return;
+ }
+ } else {
+ INREAL *p = array;
+ INREAL x = p[0]; INREAL y = p[1];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ for( long i = 1; i != count; i++ ) {
+ if( p[0] == x && p[1] == y ) break;
+ x = p[0]; y = p[1];
+ p = (INREAL *) (((char *) p) + byte_stride);
+ }
+ if( i != count ) {
+ do_nurbserror( 37 );
+ _glu_dprintf( "point %d (%f,%f)\n", i, x, y );
+ isDataValid = 0;
+ return;
+ }
+ }
+#endif
+
+ O_pwlcurve *o_pwlcurve = new(o_pwlcurvePool) O_pwlcurve( type, count, array, byte_stride, extTrimVertexPool.get((int)count) );
+ THREAD( do_pwlcurve, o_pwlcurve, do_freepwlcurve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * nurbscurve -
+ *
+ * Client: GL user
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::nurbscurve(
+ long nknots, /* number of p knots */
+ INREAL knot[], /* nondecreasing knot values in p */
+ long byte_stride, /* distance in bytes between control points */
+ INREAL ctlarray[], /* pointer to first control point */
+ long order, /* order of spline */
+ long type ) /* description of range space */
+{
+
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( ctlarray == 0 ) {
+ do_nurbserror( 36 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ Knotvector knots;
+
+ knots.init( nknots, byte_stride, order, knot );
+ if( do_check_knots( &knots, "curve" ) ) return;
+
+ O_nurbscurve *o_nurbscurve = new(o_nurbscurvePool) O_nurbscurve(type);
+ o_nurbscurve->bezier_curves = new(quiltPool) Quilt(mapdesc);
+ o_nurbscurve->bezier_curves->toBezier( knots,ctlarray, mapdesc->getNcoords() );
+
+ THREAD( do_nurbscurve, o_nurbscurve, do_freenurbscurve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * nurbssurface -
+ *
+ * Client: User routine
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::nurbssurface(
+ long sknot_count, /* number of s knots */
+ INREAL sknot[], /* nondecreasing knot values in s */
+ long tknot_count, /* number of t knots */
+ INREAL tknot[], /* nondecreasing knot values in t */
+ long s_byte_stride, /* s step size in memory bytes */
+ long t_byte_stride, /* t step size in memory bytes */
+ INREAL ctlarray[], /* pointer to first control point */
+ long sorder, /* order of the spline in s parameter */
+ long torder, /* order of the spline in t parameter */
+ long type) /* description of range space */
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( s_byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( t_byte_stride < 0 ) {
+ do_nurbserror( 34 );
+ isDataValid = 0;
+ return;
+ }
+
+ Knotvector sknotvector, tknotvector;
+
+ sknotvector.init( sknot_count, s_byte_stride, sorder, sknot );
+ if( do_check_knots( &sknotvector, "surface" ) ) return;
+
+ tknotvector.init( tknot_count, t_byte_stride, torder, tknot );
+ if( do_check_knots( &tknotvector, "surface" ) ) return;
+
+ O_nurbssurface *o_nurbssurface = new(o_nurbssurfacePool) O_nurbssurface(type);
+ o_nurbssurface->bezier_patches = new(quiltPool) Quilt(mapdesc);
+
+ o_nurbssurface->bezier_patches->toBezier( sknotvector, tknotvector,
+ ctlarray, mapdesc->getNcoords() );
+ THREAD( do_nurbssurface, o_nurbssurface, do_freenurbssurface );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::setnurbsproperty( long tag, INREAL value )
+{
+ if( ! renderhints.isProperty( tag ) ) {
+ do_nurbserror( 26 );
+ } else {
+ Property *prop = new(propertyPool) Property( tag, value );
+ THREAD( do_setnurbsproperty, prop, do_freenurbsproperty );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::setnurbsproperty( long type, long tag, INREAL value )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ return;
+ }
+
+ if( ! mapdesc->isProperty( tag ) ) {
+ do_nurbserror( 26 );
+ return;
+ }
+
+ Property *prop = new(propertyPool) Property( type, tag, value );
+ THREAD( do_setnurbsproperty2, prop, do_freenurbsproperty );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * getnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::getnurbsproperty( long tag, INREAL *value )
+{
+ if( renderhints.isProperty( tag ) ) {
+ *value = renderhints.getProperty( tag );
+ } else {
+ do_nurbserror( 26 );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * getnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::getnurbsproperty( long type, long tag, INREAL *value )
+{
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 )
+ do_nurbserror( 35 );
+
+ if( mapdesc->isProperty( tag ) ) {
+ *value = mapdesc->getProperty( tag );
+ } else {
+ do_nurbserror( 26 );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
+ *--------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat )
+{
+ // XXX - cannot be put in display list
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ } else if( purpose == N_BBOXSIZE ) {
+ mapdesc->setBboxsize( mat );
+ } else {
+#ifndef NDEBUG
+ _glu_dprintf( "ERRORRORRORR!!!\n");
+#endif
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * setnurbsproperty - accept a user supplied matrix as culling or sampling mat
+ *--------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::setnurbsproperty( long type, long purpose, INREAL *mat,
+ long rstride, long cstride )
+{
+ // XXX - cannot be put in display list
+ Mapdesc *mapdesc = maplist.locate( type );
+
+ if( mapdesc == 0 ) {
+ do_nurbserror( 35 );
+ isDataValid = 0;
+ } else if( purpose == N_CULLINGMATRIX ) {
+ mapdesc->setCmat( mat, rstride, cstride );
+ } else if( purpose == N_SAMPLINGMATRIX ) {
+ mapdesc->setSmat( mat, rstride, cstride );
+ } else if( purpose == N_BBOXMATRIX ) {
+ mapdesc->setBmat( mat, rstride, cstride );
+ } else {
+#ifndef NDEBUG
+ _glu_dprintf( "ERRORRORRORR!!!\n");
+#endif
+ }
+}
+
+void
+NurbsTessellator::redefineMaps( void )
+{
+ maplist.initialize();
+}
+
+void
+NurbsTessellator::defineMap( long type, long rational, long ncoords )
+{
+ maplist.define( type, (int) rational, (int) ncoords );
+}
+
+void
+NurbsTessellator::discardRecording( void *_dl )
+{
+ delete (DisplayList *) _dl;
+}
+
+void *
+NurbsTessellator::beginRecording( void )
+{
+ dl = new DisplayList( this );
+ return (void *) dl;
+}
+
+void
+NurbsTessellator::endRecording( void )
+{
+ dl->endList();
+ dl = 0;
+}
+
+void
+NurbsTessellator::playRecording( void *_dl )
+{
+ playBack = 1;
+ bgnrender();
+ ((DisplayList *)_dl)->play();
+ endrender();
+ playBack = 0;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.cc b/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.cc
new file mode 100644
index 000000000..68dfd95f3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.cc
@@ -0,0 +1,691 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * nurbstess.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "nurbsconsts.h"
+#include "nurbstess.h"
+#include "bufpool.h"
+#include "quilt.h"
+#include "knotvector.h"
+#include "mapdesc.h"
+#include "maplist.h"
+
+void
+NurbsTessellator::set_domain_distance_u_rate(REAL u_rate)
+{
+ subdivider.set_domain_distance_u_rate(u_rate);
+}
+
+void
+NurbsTessellator::set_domain_distance_v_rate(REAL v_rate)
+{
+ subdivider.set_domain_distance_v_rate(v_rate);
+}
+
+void
+NurbsTessellator::set_is_domain_distance_sampling(int flag)
+{
+ subdivider.set_is_domain_distance_sampling(flag);
+}
+
+void
+NurbsTessellator::resetObjects( void )
+{
+ subdivider.clear();
+}
+
+void
+NurbsTessellator::makeobj( int )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "makeobj\n" );
+#endif
+}
+
+void
+NurbsTessellator::closeobj( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "closeobj\n" );
+#endif
+}
+
+void
+NurbsTessellator::bgnrender( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "bgnrender\n" );
+#endif
+}
+
+void
+NurbsTessellator::endrender( void )
+{
+#ifndef NDEBUG
+ _glu_dprintf( "endrender\n" );
+#endif
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freebgnsurface - free o_surface structure
+ *
+ * Client: do_freeall(), bgnsurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freebgnsurface( O_surface *o_surface )
+{
+ o_surface->deleteMe( o_surfacePool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_bgnsurface - begin the display of a surface
+ *
+ * Client: bgnsurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgnsurface( O_surface *o_surface )
+{
+ if( inSurface ) {
+ do_nurbserror( 27 );
+ endsurface();
+ }
+ inSurface = 1;
+
+ if( ! playBack ) bgnrender();
+
+ isTrimModified = 0;
+ isSurfaceModified = 0;
+ isDataValid = 1;
+ numTrims = 0;
+ currentSurface = o_surface;
+ nextTrim = &( currentSurface->o_trim );
+ nextNurbssurface = &( currentSurface->o_nurbssurface );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_bgncurve - begin the display of a curve
+ *
+ * Client: bgncurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgncurve( O_curve *o_curve )
+{
+ if ( inCurve ) {
+ do_nurbserror( 6 );
+ endcurve();
+ }
+
+ inCurve = 1;
+ currentCurve = o_curve;
+ currentCurve->curvetype = ct_none;
+
+ if( inTrim ) {
+ if( *nextCurve != o_curve ) {
+ isCurveModified = 1;
+ *nextCurve = o_curve;
+ }
+ } else {
+ if( ! playBack ) bgnrender();
+ isDataValid = 1;
+ }
+ nextCurve = &(o_curve->next);
+ nextPwlcurve = &(o_curve->curve.o_pwlcurve);
+ nextNurbscurve = &(o_curve->curve.o_nurbscurve);
+}
+
+/*-----------------------------------------------------------------------------
+ * do_endcurve -
+ *
+ * Client: endcurve()
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_endcurve( void )
+{
+ if( ! inCurve ) {
+ do_nurbserror( 7 );
+ return;
+ }
+ inCurve = 0;
+
+ *nextCurve = 0;
+ if (currentCurve->curvetype == ct_nurbscurve)
+ *nextNurbscurve = 0;
+ else
+ *nextPwlcurve = 0;
+
+ if ( ! inTrim ) {
+ if( ! isDataValid ) {
+ do_freecurveall( currentCurve );
+ return;
+ }
+
+ int errval;
+ errval = ::mysetjmp( jumpbuffer );
+ if( errval == 0 ) {
+ if( currentCurve->curvetype == ct_nurbscurve ) {
+ subdivider.beginQuilts();
+ for( O_nurbscurve *n = currentCurve->curve.o_nurbscurve; n != 0; n = n->next )
+ subdivider.addQuilt( n->bezier_curves );
+ subdivider.endQuilts();
+ subdivider.drawCurves();
+ if( ! playBack ) endrender();
+ } else {
+ /* XXX */
+ if( ! playBack ) endrender();
+ /*do_draw_pwlcurve( currentCurve->curve.o_pwlcurve ) */;
+ do_nurbserror( 9 );
+ }
+ } else {
+ if( ! playBack ) endrender();
+ do_nurbserror( errval );
+ }
+ do_freecurveall( currentCurve );
+ resetObjects();
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * do_endsurface - mark end of surface, display surface, free immediate data
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_endsurface( void )
+{
+ if( inTrim ) {
+ do_nurbserror( 12 );
+ endtrim();
+ }
+
+ if( ! inSurface ) {
+ do_nurbserror( 13 );
+ return;
+ }
+ inSurface = 0;
+
+ *nextNurbssurface = 0;
+
+ if( ! isDataValid ) {
+ do_freeall( );
+ return;
+ }
+
+ if( *nextTrim != 0 ) {
+ isTrimModified = 1;
+ *nextTrim = 0;
+ }
+
+ int errval;
+
+ errval = ::mysetjmp( jumpbuffer );
+ if( errval == 0 ) {
+ if( numTrims > 0 ) {
+
+ subdivider.beginTrims();
+ for( O_trim *trim = currentSurface->o_trim; trim; trim = trim->next ) {
+ subdivider.beginLoop();
+ for( O_curve *curve = trim->o_curve; curve; curve = curve->next ) {
+ curve->used = 0;
+ assert( curve->curvetype != ct_none );
+ if (curve->curvetype == ct_pwlcurve) {
+ O_pwlcurve *c = curve->curve.o_pwlcurve;
+ subdivider.addArc( c->npts, c->pts, curve->nuid );
+ } else {
+ Quilt *quilt = curve->curve.o_nurbscurve->bezier_curves;
+ Quiltspec *qspec = quilt->qspec;
+ REAL *cpts = quilt->cpts + qspec->offset;
+ REAL *cptsend = cpts + (qspec->width * qspec->order * qspec->stride);
+ for( ; cpts != cptsend; cpts += qspec->order*qspec->stride )
+ subdivider.addArc( cpts, quilt, curve->nuid );
+ }
+ }
+ subdivider.endLoop();
+ }
+ subdivider.endTrims();
+ }
+
+ subdivider.beginQuilts();
+ for( O_nurbssurface *n = currentSurface->o_nurbssurface; n; n = n->next )
+ subdivider.addQuilt( n->bezier_patches );
+ subdivider.endQuilts();
+ subdivider.drawSurfaces( currentSurface->nuid );
+ if( ! playBack ) endrender();
+ } else {
+ if( ! playBack ) endrender();
+ do_nurbserror( errval );
+ }
+
+ do_freeall( );
+ resetObjects();
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freeall - free all data allocated in immediate mode
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freeall( void )
+{
+ for( O_trim *o_trim = currentSurface->o_trim; o_trim; ) {
+ O_trim *next_o_trim = o_trim->next;
+ for( O_curve *curve = o_trim->o_curve; curve; ) {
+ O_curve *next_o_curve = curve->next;
+ do_freecurveall( curve );
+ curve = next_o_curve;
+ }
+ if( o_trim->save == 0 ) do_freebgntrim( o_trim );
+ o_trim = next_o_trim;
+ }
+
+ O_nurbssurface *nurbss, *next_nurbss;
+ for( nurbss= currentSurface->o_nurbssurface; nurbss; nurbss = next_nurbss) {
+ next_nurbss = nurbss->next;
+ if( nurbss->save == 0 )
+ do_freenurbssurface( nurbss );
+ else
+ nurbss->used = 0;
+ }
+
+ if( currentSurface->save == 0 ) do_freebgnsurface( currentSurface );
+}
+
+void
+NurbsTessellator::do_freecurveall( O_curve *curve )
+{
+ assert( curve->curvetype != ct_none );
+
+ if( curve->curvetype == ct_nurbscurve ) {
+ O_nurbscurve *ncurve, *next_ncurve;
+ for( ncurve=curve->curve.o_nurbscurve; ncurve; ncurve=next_ncurve ) {
+ next_ncurve = ncurve->next;
+ if( ncurve->save == 0 )
+ do_freenurbscurve( ncurve );
+ else
+ ncurve->used = 0;
+ }
+ } else {
+ O_pwlcurve *pcurve, *next_pcurve;
+ for( pcurve=curve->curve.o_pwlcurve; pcurve; pcurve=next_pcurve ) {
+ next_pcurve = pcurve->next;
+ if( pcurve->save == 0 )
+ do_freepwlcurve( pcurve );
+ else
+ pcurve->used = 0;
+ }
+ }
+ if( curve->save == 0 )
+ do_freebgncurve( curve );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freebgntrim - free the space allocated for a trim loop
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freebgntrim( O_trim *o_trim )
+{
+ o_trim->deleteMe( o_trimPool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_bgntrim - link in a trim loop to the current trimmed surface description
+ *
+ * Client: bgntrim()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_bgntrim( O_trim *o_trim )
+{
+
+ if( ! inSurface ) {
+ do_nurbserror( 15 );
+ bgnsurface( 0 );
+ inSurface = 2;
+ }
+
+ if( inTrim ) {
+ do_nurbserror( 16 );
+ endtrim();
+ }
+ inTrim = 1;
+
+ if( *nextTrim != o_trim ) {
+ isTrimModified = 1;
+ *nextTrim = o_trim;
+ }
+
+ currentTrim = o_trim;
+ nextTrim = &(o_trim->next);
+ nextCurve = &(o_trim->o_curve);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_endtrim - mark the end of the current trim loop
+ *
+ * Client: endtrim()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_endtrim( void )
+{
+ if( ! inTrim ) {
+ do_nurbserror( 17 );
+ return;
+ }
+ inTrim = 0;
+
+ if( currentTrim->o_curve == 0 ) {
+ do_nurbserror( 18 );
+ isDataValid = 0;
+ }
+
+ numTrims++;
+
+ if( *nextCurve != 0 ) {
+ isTrimModified = 1;
+ *nextCurve = 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * do_freepwlcurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freepwlcurve( O_pwlcurve *o_pwlcurve )
+{
+ o_pwlcurve->deleteMe( o_pwlcurvePool );
+}
+
+void
+NurbsTessellator::do_freebgncurve( O_curve *o_curve )
+{
+ o_curve->deleteMe( o_curvePool );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_pwlcurve - link in pwl trim loop to the current surface description
+ *
+ * Client: pwlcurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_pwlcurve( O_pwlcurve *o_pwlcurve )
+{
+ if( ! inTrim ) {
+ do_nurbserror( 19 );
+ if( o_pwlcurve->save == 0 )
+ do_freepwlcurve(o_pwlcurve );
+ return;
+ }
+
+ if( ! inCurve ) {
+ bgncurve( 0 );
+ inCurve = 2;
+ }
+
+ if( o_pwlcurve->used ) {
+ do_nurbserror( 20 );
+ isDataValid = 0;
+ return;
+ } else
+ o_pwlcurve->used = 1;
+
+ if( currentCurve->curvetype == ct_none ) {
+ currentCurve->curvetype = ct_pwlcurve;
+ } else if( currentCurve->curvetype != ct_pwlcurve ) {
+ do_nurbserror( 21 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( *nextPwlcurve != o_pwlcurve ) {
+ isCurveModified = 1;
+ *nextPwlcurve = o_pwlcurve;
+ }
+ nextPwlcurve = &(o_pwlcurve->next);
+
+ if( o_pwlcurve->owner != currentCurve ) {
+ isCurveModified = 1;
+ o_pwlcurve->owner = currentCurve;
+ }
+
+ if( (inCurve == 2) )
+ endcurve();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbscurve -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_freenurbscurve( O_nurbscurve *o_nurbscurve )
+{
+ o_nurbscurve->bezier_curves->deleteMe( quiltPool );
+ o_nurbscurve->deleteMe( o_nurbscurvePool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_nurbscurve -
+ *
+ * Client: nurbscurve()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_nurbscurve( O_nurbscurve *o_nurbscurve )
+{
+ if ( ! inCurve ) {
+ bgncurve( 0 );
+ inCurve = 2;
+ }
+
+ if( o_nurbscurve->used ) {
+ /* error - curve was already called in current surface */
+ do_nurbserror( 23 );
+ isDataValid = 0;
+ return;
+ } else
+ o_nurbscurve->used = 1;
+
+ if( currentCurve->curvetype == ct_none ) {
+ currentCurve->curvetype = ct_nurbscurve;
+ } else if( currentCurve->curvetype != ct_nurbscurve ) {
+ do_nurbserror( 24 );
+ isDataValid = 0;
+ return;
+ }
+
+ if( *nextNurbscurve != o_nurbscurve ) {
+ isCurveModified = 1;
+ *nextNurbscurve = o_nurbscurve;
+ }
+
+ nextNurbscurve = &(o_nurbscurve->next);
+
+ if( o_nurbscurve->owner != currentCurve ) {
+ isCurveModified = 1;
+ o_nurbscurve->owner = currentCurve;
+ }
+
+ if( o_nurbscurve->owner == 0 )
+ isCurveModified = 1;
+
+ if( inCurve == 2 )
+ endcurve();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbssurface -
+ *
+ * Client:
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_freenurbssurface( O_nurbssurface *o_nurbssurface )
+{
+ o_nurbssurface->bezier_patches->deleteMe( quiltPool );
+ o_nurbssurface->deleteMe( o_nurbssurfacePool );
+}
+
+/*-----------------------------------------------------------------------------
+ * do_nurbssurface -
+ *
+ * Client: nurbssurface()
+ *-----------------------------------------------------------------------------
+ */
+void
+NurbsTessellator::do_nurbssurface( O_nurbssurface *o_nurbssurface )
+{
+ if( ! inSurface ) {
+ bgnsurface( 0 );
+ inSurface = 2;
+ }
+
+ if( o_nurbssurface->used ) {
+ /* error - surface was already called in current block */
+ do_nurbserror( 25 );
+ isDataValid = 0;
+ return;
+ } else
+ o_nurbssurface->used = 1;
+
+ if( *nextNurbssurface != o_nurbssurface ) {
+ isSurfaceModified = 1;
+ *nextNurbssurface = o_nurbssurface;
+ }
+
+ if( o_nurbssurface->owner != currentSurface ) {
+ isSurfaceModified = 1;
+ o_nurbssurface->owner = currentSurface;
+ }
+ nextNurbssurface = &(o_nurbssurface->next);
+
+ if( inSurface == 2 )
+ endsurface();
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_freenurbsproperty
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_freenurbsproperty( Property *prop )
+{
+ prop->deleteMe( propertyPool );
+}
+
+
+/*-----------------------------------------------------------------------------
+ * do_setnurbsproperty -
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+NurbsTessellator::do_setnurbsproperty( Property *prop )
+{
+ renderhints.setProperty( prop->tag, prop->value );
+ if( prop->save == 0 )
+ do_freenurbsproperty( prop );
+}
+
+void
+NurbsTessellator::do_setnurbsproperty2( Property *prop )
+{
+ Mapdesc *mapdesc = maplist.find( prop->type );
+
+ mapdesc->setProperty( prop->tag, prop->value );
+ if( prop->save == 0 )
+ do_freenurbsproperty( prop );
+}
+
+void
+NurbsTessellator::errorHandler( int )
+{
+}
+
+void
+NurbsTessellator::do_nurbserror( int msg )
+{
+ errorHandler( msg );
+}
+
+int
+NurbsTessellator::do_check_knots( Knotvector *knots, const char *msg )
+{
+ int status = knots->validate();
+ if( status ) {
+ do_nurbserror( status );
+ if( renderhints.errorchecking != N_NOMSG ) knots->show( msg );
+ }
+ return status;
+}
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.h b/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.h
new file mode 100644
index 000000000..a6869002f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/nurbstess.h
@@ -0,0 +1,172 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * nurbstess.h
+ *
+ */
+
+#ifndef __glunurbstess_h_
+#define __glunurbstess_h_
+
+#include "mysetjmp.h"
+#include "subdivider.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "maplist.h"
+#include "reader.h"
+#include "nurbsconsts.h"
+
+struct Knotvector;
+class Quilt;
+class DisplayList;
+class BasicCurveEvaluator;
+class BasicSurfaceEvaluator;
+
+class NurbsTessellator {
+public:
+ NurbsTessellator( BasicCurveEvaluator &c,
+ BasicSurfaceEvaluator &e );
+ virtual ~NurbsTessellator( void );
+
+ void getnurbsproperty( long, INREAL * );
+ void getnurbsproperty( long, long, INREAL * );
+ void setnurbsproperty( long, INREAL );
+ void setnurbsproperty( long, long, INREAL );
+ void setnurbsproperty( long, long, INREAL * );
+ void setnurbsproperty( long, long, INREAL *, long, long );
+
+ // called before a tessellation begins/ends
+ virtual void bgnrender( void );
+ virtual void endrender( void );
+
+ // called to make a display list of the output vertices
+ virtual void makeobj( int n );
+ virtual void closeobj( void );
+
+ // called when a error occurs
+ virtual void errorHandler( int );
+
+ void bgnsurface( long );
+ void endsurface( void );
+ void bgntrim( void );
+ void endtrim( void );
+ void bgncurve( long );
+ void endcurve( void );
+ void pwlcurve( long, INREAL[], long, long );
+ void nurbscurve( long, INREAL[], long, INREAL[], long, long );
+ void nurbssurface( long, INREAL[], long, INREAL[], long, long,
+ INREAL[], long, long, long );
+
+ void defineMap( long, long, long );
+ void redefineMaps( void );
+
+ // recording of input description
+ void discardRecording( void * );
+ void * beginRecording( void );
+ void endRecording( void );
+ void playRecording( void * );
+
+ //for optimizing untrimmed nurbs in the case of domain distance sampling
+ void set_domain_distance_u_rate(REAL u_rate);
+ void set_domain_distance_v_rate(REAL v_rate);
+ void set_is_domain_distance_sampling(int flag);
+
+
+protected:
+ Renderhints renderhints;
+ Maplist maplist;
+ Backend backend;
+
+private:
+
+ void resetObjects( void );
+ int do_check_knots( Knotvector *, const char * );
+ void do_nurbserror( int );
+ void do_bgncurve( O_curve * );
+ void do_endcurve( void );
+ void do_freeall( void );
+ void do_freecurveall( O_curve * );
+ void do_freebgntrim( O_trim * );
+ void do_freebgncurve( O_curve * );
+ void do_freepwlcurve( O_pwlcurve * );
+ void do_freenurbscurve( O_nurbscurve * );
+ void do_freenurbssurface( O_nurbssurface * );
+ void do_freebgnsurface( O_surface * );
+ void do_bgnsurface( O_surface * );
+ void do_endsurface( void );
+ void do_bgntrim( O_trim * );
+ void do_endtrim( void );
+ void do_pwlcurve( O_pwlcurve * );
+ void do_nurbscurve( O_nurbscurve * );
+ void do_nurbssurface( O_nurbssurface * );
+ void do_freenurbsproperty( Property * );
+ void do_setnurbsproperty( Property * );
+ void do_setnurbsproperty2( Property * );
+
+ Subdivider subdivider;
+ JumpBuffer* jumpbuffer;
+ Pool o_pwlcurvePool;
+ Pool o_nurbscurvePool;
+ Pool o_curvePool;
+ Pool o_trimPool;
+ Pool o_surfacePool;
+ Pool o_nurbssurfacePool;
+ Pool propertyPool;
+public:
+ Pool quiltPool;
+private:
+ TrimVertexPool extTrimVertexPool;
+
+ int inSurface; /* bgnsurface seen */
+ int inCurve; /* bgncurve seen */
+ int inTrim; /* bgntrim seen */
+ int isCurveModified; /* curve changed */
+ int isTrimModified; /* trim curves changed */
+ int isSurfaceModified; /* surface changed */
+ int isDataValid; /* all data is good */
+ int numTrims; /* valid trim regions */
+ int playBack;
+
+ O_trim** nextTrim; /* place to link o_trim */
+ O_curve** nextCurve; /* place to link o_curve */
+ O_nurbscurve** nextNurbscurve; /* place to link o_nurbscurve */
+ O_pwlcurve** nextPwlcurve; /* place to link o_pwlcurve */
+ O_nurbssurface** nextNurbssurface; /* place to link o_nurbssurface */
+
+ O_surface* currentSurface;
+ O_trim* currentTrim;
+ O_curve* currentCurve;
+
+ DisplayList *dl;
+
+};
+
+#endif /* __glunurbstess_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/patch.cc b/mesalib/src/glu/sgi/libnurbs/internals/patch.cc
new file mode 100644
index 000000000..808baa69e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/patch.cc
@@ -0,0 +1,504 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patch.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "mymath.h"
+#include "mystring.h"
+#include "patch.h"
+#include "mapdesc.h"
+#include "quilt.h"
+#include "nurbsconsts.h"
+#include "simplemath.h" //for glu_abs function in ::singleStep();
+
+
+/*--------------------------------------------------------------------------
+ * Patch - copy patch from quilt and transform control points
+ *--------------------------------------------------------------------------
+ */
+
+Patch::Patch( Quilt_ptr geo, REAL *pta, REAL *ptb, Patch *n )
+{
+/* pspec[i].range is uninit here */
+ mapdesc = geo->mapdesc;
+ cullval = mapdesc->isCulling() ? CULL_ACCEPT : CULL_TRIVIAL_ACCEPT;
+ notInBbox = mapdesc->isBboxSubdividing() ? 1 : 0;
+ needsSampling = mapdesc->isRangeSampling() ? 1 : 0;
+ pspec[0].order = geo->qspec[0].order;
+ pspec[1].order = geo->qspec[1].order;
+ pspec[0].stride = pspec[1].order * MAXCOORDS;
+ pspec[1].stride = MAXCOORDS;
+
+ /* transform control points to sampling and culling spaces */
+ REAL *ps = geo->cpts;
+ geo->select( pta, ptb );
+ ps += geo->qspec[0].offset;
+ ps += geo->qspec[1].offset;
+ ps += geo->qspec[0].index * geo->qspec[0].order * geo->qspec[0].stride;
+ ps += geo->qspec[1].index * geo->qspec[1].order * geo->qspec[1].stride;
+
+ if( needsSampling ) {
+ mapdesc->xformSampling( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ spts, pspec[0].stride, pspec[1].stride );
+ }
+
+ if( cullval == CULL_ACCEPT ) {
+ mapdesc->xformCulling( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ cpts, pspec[0].stride, pspec[1].stride );
+ }
+
+ if( notInBbox ) {
+ mapdesc->xformBounding( ps, geo->qspec[0].order, geo->qspec[0].stride,
+ geo->qspec[1].order, geo->qspec[1].stride,
+ bpts, pspec[0].stride, pspec[1].stride );
+ }
+
+ /* set scale range */
+ pspec[0].range[0] = geo->qspec[0].breakpoints[geo->qspec[0].index];
+ pspec[0].range[1] = geo->qspec[0].breakpoints[geo->qspec[0].index+1];
+ pspec[0].range[2] = pspec[0].range[1] - pspec[0].range[0];
+
+ pspec[1].range[0] = geo->qspec[1].breakpoints[geo->qspec[1].index];
+ pspec[1].range[1] = geo->qspec[1].breakpoints[geo->qspec[1].index+1];
+ pspec[1].range[2] = pspec[1].range[1] - pspec[1].range[0];
+
+ // may need to subdivide to match range of sub-patch
+ if( pspec[0].range[0] != pta[0] ) {
+ assert( pspec[0].range[0] < pta[0] );
+ Patch lower( *this, 0, pta[0], 0 );
+ *this = lower;
+ }
+
+ if( pspec[0].range[1] != ptb[0] ) {
+ assert( pspec[0].range[1] > ptb[0] );
+ Patch upper( *this, 0, ptb[0], 0 );
+ }
+
+ if( pspec[1].range[0] != pta[1] ) {
+ assert( pspec[1].range[0] < pta[1] );
+ Patch lower( *this, 1, pta[1], 0 );
+ *this = lower;
+ }
+
+ if( pspec[1].range[1] != ptb[1] ) {
+ assert( pspec[1].range[1] > ptb[1] );
+ Patch upper( *this, 1, ptb[1], 0 );
+ }
+ checkBboxConstraint();
+ next = n;
+}
+
+/*--------------------------------------------------------------------------
+ * Patch - subdivide a patch along an isoparametric line
+ *--------------------------------------------------------------------------
+ */
+
+Patch::Patch( Patch& upper, int param, REAL value, Patch *n )
+{
+ Patch& lower = *this;
+
+ lower.cullval = upper.cullval;
+ lower.mapdesc = upper.mapdesc;
+ lower.notInBbox = upper.notInBbox;
+ lower.needsSampling = upper.needsSampling;
+ lower.pspec[0].order = upper.pspec[0].order;
+ lower.pspec[1].order = upper.pspec[1].order;
+ lower.pspec[0].stride = upper.pspec[0].stride;
+ lower.pspec[1].stride = upper.pspec[1].stride;
+ lower.next = n;
+
+ /* reset scale range */
+ switch( param ) {
+ case 0: {
+ REAL d = (value-upper.pspec[0].range[0]) / upper.pspec[0].range[2];
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ if( notInBbox )
+ mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[1].order,
+ pspec[1].stride, pspec[0].order, pspec[0].stride );
+
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = value;
+ lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
+ upper.pspec[0].range[0] = value;
+ upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
+
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = upper.pspec[1].range[1];
+ lower.pspec[1].range[2] = upper.pspec[1].range[2];
+ break;
+ }
+ case 1: {
+ REAL d = (value-upper.pspec[1].range[0]) / upper.pspec[1].range[2];
+ if( needsSampling )
+ mapdesc->subdivide( upper.spts, lower.spts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ if( cullval == CULL_ACCEPT )
+ mapdesc->subdivide( upper.cpts, lower.cpts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ if( notInBbox )
+ mapdesc->subdivide( upper.bpts, lower.bpts, d, pspec[0].order,
+ pspec[0].stride, pspec[1].order, pspec[1].stride );
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = upper.pspec[0].range[1];
+ lower.pspec[0].range[2] = upper.pspec[0].range[2];
+
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = value;
+ lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
+ upper.pspec[1].range[0] = value;
+ upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
+ break;
+ }
+ }
+
+ // inherit bounding box
+ if( mapdesc->isBboxSubdividing() && ! notInBbox )
+ memcpy( lower.bb, upper.bb, sizeof( bb ) );
+
+ lower.checkBboxConstraint();
+ upper.checkBboxConstraint();
+}
+
+/*--------------------------------------------------------------------------
+ * clamp - clamp the sampling rate to a given maximum
+ *--------------------------------------------------------------------------
+ */
+
+void
+Patch::clamp( void )
+{
+ if( mapdesc->clampfactor != N_NOCLAMPING ) {
+ pspec[0].clamp( mapdesc->clampfactor );
+ pspec[1].clamp( mapdesc->clampfactor );
+ }
+}
+
+void
+Patchspec::clamp( REAL clampfactor )
+{
+ if( sidestep[0] < minstepsize )
+ sidestep[0] = clampfactor * minstepsize;
+ if( sidestep[1] < minstepsize )
+ sidestep[1] = clampfactor * minstepsize;
+ if( stepsize < minstepsize )
+ stepsize = clampfactor * minstepsize;
+}
+
+void
+Patch::checkBboxConstraint( void )
+{
+ if( notInBbox &&
+ mapdesc->bboxTooBig( bpts, pspec[0].stride, pspec[1].stride,
+ pspec[0].order, pspec[1].order, bb ) != 1 ) {
+ notInBbox = 0;
+ }
+}
+
+void
+Patch::bbox( void )
+{
+ if( mapdesc->isBboxSubdividing() )
+ mapdesc->surfbbox( bb );
+}
+
+/*--------------------------------------------------------------------------
+ * getstepsize - compute the sampling density across the patch
+ * and determine if patch needs to be subdivided
+ *--------------------------------------------------------------------------
+ */
+
+void
+Patch::getstepsize( void )
+{
+ pspec[0].minstepsize = pspec[1].minstepsize = 0;
+ pspec[0].needsSubdivision = pspec[1].needsSubdivision = 0;
+
+ if( mapdesc->isConstantSampling() ) {
+ // fixed number of samples per patch in each direction
+ // maxsrate is number of s samples per patch
+ // maxtrate is number of t samples per patch
+ pspec[0].getstepsize( mapdesc->maxsrate );
+ pspec[1].getstepsize( mapdesc->maxtrate );
+
+ } else if( mapdesc->isDomainSampling() ) {
+ // maxsrate is number of s samples per unit s length of domain
+ // maxtrate is number of t samples per unit t length of domain
+ pspec[0].getstepsize( mapdesc->maxsrate * pspec[0].range[2] );
+ pspec[1].getstepsize( mapdesc->maxtrate * pspec[1].range[2] );
+
+ } else if( ! needsSampling ) {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ } else {
+ // upper bound on path length between sample points
+ REAL tmp[MAXORDER][MAXORDER][MAXCOORDS];
+ const int trstride = sizeof(tmp[0]) / sizeof(REAL);
+ const int tcstride = sizeof(tmp[0][0]) / sizeof(REAL);
+
+ assert( pspec[0].order <= MAXORDER );
+
+ /* points have been transformed, therefore they are homogeneous */
+
+ int val = mapdesc->project( spts, pspec[0].stride, pspec[1].stride,
+ &tmp[0][0][0], trstride, tcstride,
+ pspec[0].order, pspec[1].order );
+ if( val == 0 ) {
+ // control points cross infinity, therefore partials are undefined
+ pspec[0].getstepsize( mapdesc->maxsrate );
+ pspec[1].getstepsize( mapdesc->maxtrate );
+ } else {
+ REAL t1 = mapdesc->getProperty( N_PIXEL_TOLERANCE );
+// REAL t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
+ pspec[0].minstepsize = ( mapdesc->maxsrate > 0.0 ) ?
+ (pspec[0].range[2] / mapdesc->maxsrate) : 0.0;
+ pspec[1].minstepsize = ( mapdesc->maxtrate > 0.0 ) ?
+ (pspec[1].range[2] / mapdesc->maxtrate) : 0.0;
+ if( mapdesc->isParametricDistanceSampling() ||
+ mapdesc->isObjectSpaceParaSampling() ) {
+
+ REAL t2;
+ t2 = mapdesc->getProperty( N_ERROR_TOLERANCE );
+
+ // t2 is upper bound on the distance between surface and tessellant
+ REAL ssv[2], ttv[2];
+ REAL ss = mapdesc->calcPartialVelocity( ssv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 2, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL st = mapdesc->calcPartialVelocity( 0, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 1, pspec[0].range[2], pspec[1].range[2], -1 );
+ REAL tt = mapdesc->calcPartialVelocity( ttv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 2, pspec[0].range[2], pspec[1].range[2], 1 );
+ //make sure that ss st and tt are nonnegative:
+ if(ss <0) ss = -ss;
+ if(st <0) st = -st;
+ if(tt <0) tt = -tt;
+
+ if( ss != 0.0 && tt != 0.0 ) {
+ /* printf( "ssv[0] %g ssv[1] %g ttv[0] %g ttv[1] %g\n",
+ ssv[0], ssv[1], ttv[0], ttv[1] ); */
+ REAL ttq = sqrtf( (float) ss );
+ REAL ssq = sqrtf( (float) tt );
+ REAL ds = sqrtf( 4 * t2 * ttq / ( ss * ttq + st * ssq ) );
+ REAL dt = sqrtf( 4 * t2 * ssq / ( tt * ssq + st * ttq ) );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
+ pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
+ pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
+ pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
+ pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
+ } else if( ss != 0.0 ) {
+ REAL x = pspec[1].range[2] * st;
+ REAL ds = ( sqrtf( x * x + 8.0 * t2 * ss ) - x ) / ss;
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ REAL scutoff = 2.0 * t2 / ( pspec[0].range[2] * pspec[0].range[2]);
+ pspec[0].sidestep[0] = (ssv[0] > scutoff) ? sqrtf( 2.0 * t2 / ssv[0] ) : pspec[0].range[2];
+ pspec[0].sidestep[1] = (ssv[1] > scutoff) ? sqrtf( 2.0 * t2 / ssv[1] ) : pspec[0].range[2];
+ pspec[1].singleStep();
+ } else if( tt != 0.0 ) {
+ REAL x = pspec[0].range[2] * st;
+ REAL dt = ( sqrtf( x * x + 8.0 * t2 * tt ) - x ) / tt;
+ pspec[0].singleStep();
+ REAL tcutoff = 2.0 * t2 / ( pspec[1].range[2] * pspec[1].range[2]);
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = (ttv[0] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[0] ) : pspec[1].range[2];
+ pspec[1].sidestep[1] = (ttv[1] > tcutoff) ? sqrtf( 2.0 * t2 / ttv[1] ) : pspec[1].range[2];
+ } else {
+ if( 4.0 * t2 > st * pspec[0].range[2] * pspec[1].range[2] ) {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ } else {
+ REAL area = 4.0 * t2 / st;
+ REAL ds = sqrtf( area * pspec[0].range[2] / pspec[1].range[2] );
+ REAL dt = sqrtf( area * pspec[1].range[2] / pspec[0].range[2] );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = pspec[0].range[2];
+ pspec[0].sidestep[1] = pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = pspec[1].range[2];
+ pspec[1].sidestep[1] = pspec[1].range[2];
+ }
+ }
+ } else if( mapdesc->isPathLengthSampling() ||
+ mapdesc->isObjectSpacePathSampling()) {
+ // t1 is upper bound on path length
+ REAL msv[2], mtv[2];
+ REAL ms = mapdesc->calcPartialVelocity( msv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL mt = mapdesc->calcPartialVelocity( mtv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 1, pspec[0].range[2], pspec[1].range[2], 1 );
+ REAL side_scale = 1.0;
+
+ if( ms != 0.0 ) {
+ if( mt != 0.0 ) {
+/* REAL d = t1 / ( ms * ms + mt * mt );*/
+/* REAL ds = mt * d;*/
+ REAL ds = t1 / (2.0*ms);
+/* REAL dt = ms * d;*/
+ REAL dt = t1 / (2.0*mt);
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (side_scale* t1 / msv[1]) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (side_scale*t1 / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].stepsize = ( t1 < ms * pspec[0].range[2] ) ? (t1 / ms) : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t1 ) ? (t1 / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t1 ) ? (t1 / msv[1]) : pspec[0].range[2];
+
+ pspec[1].singleStep();
+ }
+ } else {
+ if( mt != 0.0 ) {
+ pspec[0].singleStep();
+
+ pspec[1].stepsize = ( t1 < mt * pspec[1].range[2] ) ? (t1 / mt) : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t1 ) ? (t1 / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t1 ) ? (t1 / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+ }
+ } else if( mapdesc->isSurfaceAreaSampling() ) {
+ // t is the square root of area
+/*
+ REAL msv[2], mtv[2];
+ REAL ms = mapdesc->calcPartialVelocity( msv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 1, 0, pspec[0].range[2], pspec[1].range[2], 0 );
+ REAL mt = mapdesc->calcPartialVelocity( mtv, &tmp[0][0][0], trstride, tcstride, pspec[0].order, pspec[1].order, 0, 1, pspec[0].range[2], pspec[1].range[2], 1 );
+ if( ms != 0.0 && mt != 0.0 ) {
+ REAL d = 1.0 / (ms * mt);
+ t *= M_SQRT2;
+ REAL ds = t * sqrtf( d * pspec[0].range[2] / pspec[1].range[2] );
+ REAL dt = t * sqrtf( d * pspec[1].range[2] / pspec[0].range[2] );
+ pspec[0].stepsize = ( ds < pspec[0].range[2] ) ? ds : pspec[0].range[2];
+ pspec[0].sidestep[0] = ( msv[0] * pspec[0].range[2] > t ) ? (t / msv[0]) : pspec[0].range[2];
+ pspec[0].sidestep[1] = ( msv[1] * pspec[0].range[2] > t ) ? (t / msv[1]) : pspec[0].range[2];
+
+ pspec[1].stepsize = ( dt < pspec[1].range[2] ) ? dt : pspec[1].range[2];
+ pspec[1].sidestep[0] = ( mtv[0] * pspec[1].range[2] > t ) ? (t / mtv[0]) : pspec[1].range[2];
+ pspec[1].sidestep[1] = ( mtv[1] * pspec[1].range[2] > t ) ? (t / mtv[1]) : pspec[1].range[2];
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+*/
+ } else {
+ pspec[0].singleStep();
+ pspec[1].singleStep();
+ }
+ }
+ }
+
+#ifdef DEBUG
+ _glu_dprintf( "sidesteps %g %g %g %g, stepsize %g %g\n",
+ pspec[0].sidestep[0], pspec[0].sidestep[1],
+ pspec[1].sidestep[0], pspec[1].sidestep[1],
+ pspec[0].stepsize, pspec[1].stepsize );
+#endif
+
+ if( mapdesc->minsavings != N_NOSAVINGSSUBDIVISION ) {
+ REAL savings = 1./(pspec[0].stepsize * pspec[1].stepsize) ;
+ savings-= (2./( pspec[0].sidestep[0] + pspec[0].sidestep[1] )) *
+ (2./( pspec[1].sidestep[0] + pspec[1].sidestep[1] ));
+
+ savings *= pspec[0].range[2] * pspec[1].range[2];
+ if( savings > mapdesc->minsavings ) {
+ pspec[0].needsSubdivision = pspec[1].needsSubdivision = 1;
+ }
+ }
+
+ if( pspec[0].stepsize < pspec[0].minstepsize ) pspec[0].needsSubdivision = 1;
+ if( pspec[1].stepsize < pspec[1].minstepsize ) pspec[1].needsSubdivision = 1;
+ needsSampling = (needsSampling ? needsSamplingSubdivision() : 0);
+}
+
+void
+Patchspec::singleStep()
+{
+ stepsize = sidestep[0] = sidestep[1] = glu_abs(range[2]);
+}
+
+void
+Patchspec::getstepsize( REAL max ) // max is number of samples for entire patch
+{
+ stepsize = ( max >= 1.0 ) ? range[2] / max : range[2];
+ if (stepsize < 0.0) {
+ stepsize = -stepsize;
+ }
+ sidestep[0] = sidestep[1] = minstepsize = stepsize;
+}
+
+int
+Patch::needsSamplingSubdivision( void )
+{
+ return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0;
+}
+
+int
+Patch::needsNonSamplingSubdivision( void )
+{
+ return notInBbox;
+}
+
+int
+Patch::needsSubdivision( int param )
+{
+ return pspec[param].needsSubdivision;
+}
+
+int
+Patch::cullCheck( void )
+{
+ if( cullval == CULL_ACCEPT )
+ cullval = mapdesc->cullCheck( cpts, pspec[0].order, pspec[0].stride,
+ pspec[1].order, pspec[1].stride );
+ return cullval;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/patch.h b/mesalib/src/glu/sgi/libnurbs/internals/patch.h
new file mode 100644
index 000000000..324a25938
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/patch.h
@@ -0,0 +1,94 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * patch.h
+ *
+ */
+
+#ifndef __glupatch_h_
+#define __glupatch_h_
+
+#include "types.h"
+#include "defines.h"
+
+class Quilt;
+class Mapdesc;
+
+
+struct Pspec {
+ REAL range[3];
+ REAL sidestep[2];
+ REAL stepsize;
+ REAL minstepsize;
+ int needsSubdivision;
+};
+
+struct Patchspec : public Pspec {
+ int order;
+ int stride;
+ void clamp( REAL );
+ void getstepsize( REAL );
+ void singleStep( void );
+};
+
+class Patch {
+public:
+friend class Subdivider;
+friend class Quilt;
+friend class Patchlist;
+ Patch( Quilt *, REAL*, REAL *, Patch * );
+ Patch( Patch &, int, REAL, Patch * );
+ void bbox( void );
+ void clamp( void );
+ void getstepsize( void );
+ int cullCheck( void );
+ int needsSubdivision( int );
+ int needsSamplingSubdivision( void );
+ int needsNonSamplingSubdivision( void );
+
+ int get_uorder() {return pspec[0].order;}
+ int get_vorder() {return pspec[1].order;}
+
+private:
+
+ Mapdesc* mapdesc;
+ Patch* next;
+ int cullval;
+ int notInBbox;
+ int needsSampling;
+ REAL cpts[MAXORDER*MAXORDER*MAXCOORDS]; //culling pts
+ REAL spts[MAXORDER*MAXORDER*MAXCOORDS]; //sampling pts
+ REAL bpts[MAXORDER*MAXORDER*MAXCOORDS]; //bbox pts
+ Patchspec pspec[2];
+ void checkBboxConstraint( void );
+ REAL bb[2][MAXCOORDS];
+};
+#endif /* __glupatch_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/patchlist.cc b/mesalib/src/glu/sgi/libnurbs/internals/patchlist.cc
new file mode 100644
index 000000000..989d2dd00
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/patchlist.cc
@@ -0,0 +1,170 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * patchlist.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "quilt.h"
+#include "patchlist.h"
+#include "patch.h"
+#include "nurbsconsts.h"
+
+Patchlist::Patchlist( Quilt *quilts, REAL *pta, REAL *ptb )
+{
+ patch = 0;
+ for( Quilt *q = quilts; q; q = q->next )
+ patch = new Patch( q, pta, ptb, patch );
+ pspec[0].range[0] = pta[0];
+ pspec[0].range[1] = ptb[0];
+ pspec[0].range[2] = ptb[0] - pta[0];
+
+ pspec[1].range[0] = pta[1];
+ pspec[1].range[1] = ptb[1];
+ pspec[1].range[2] = ptb[1] - pta[1];
+}
+
+Patchlist::Patchlist( Patchlist &upper, int param, REAL value)
+{
+ Patchlist &lower = *this;
+ patch = 0;
+ for( Patch *p = upper.patch; p; p = p->next )
+ patch = new Patch( *p, param, value, patch );
+
+ if( param == 0 ) {
+ lower.pspec[0].range[0] = upper.pspec[0].range[0];
+ lower.pspec[0].range[1] = value;
+ lower.pspec[0].range[2] = value - upper.pspec[0].range[0];
+ upper.pspec[0].range[0] = value;
+ upper.pspec[0].range[2] = upper.pspec[0].range[1] - value;
+ lower.pspec[1] = upper.pspec[1];
+ } else {
+ lower.pspec[0] = upper.pspec[0];
+ lower.pspec[1].range[0] = upper.pspec[1].range[0];
+ lower.pspec[1].range[1] = value;
+ lower.pspec[1].range[2] = value - upper.pspec[1].range[0];
+ upper.pspec[1].range[0] = value;
+ upper.pspec[1].range[2] = upper.pspec[1].range[1] - value;
+ }
+}
+
+Patchlist::~Patchlist()
+{
+ while( patch ) {
+ Patch *p = patch;
+ patch = patch->next;
+ delete p;
+ }
+}
+
+int
+Patchlist::cullCheck( void )
+{
+ for( Patch *p = patch; p; p = p->next )
+ if( p->cullCheck() == CULL_TRIVIAL_REJECT )
+ return CULL_TRIVIAL_REJECT;
+ return CULL_ACCEPT;
+}
+
+void
+Patchlist::getRanges(REAL ranges[4])
+{
+ ranges[0] = pspec[0].range[0];
+ ranges[1] = pspec[0].range[1];
+ ranges[2] = pspec[1].range[0];
+ ranges[3] = pspec[1].range[1];
+}
+
+void
+Patchlist::getstepsize( void )
+{
+ pspec[0].stepsize = pspec[0].range[2];
+ pspec[0].sidestep[0] = pspec[0].range[2];
+ pspec[0].sidestep[1] = pspec[0].range[2];
+
+ pspec[1].stepsize = pspec[1].range[2];
+ pspec[1].sidestep[0] = pspec[1].range[2];
+ pspec[1].sidestep[1] = pspec[1].range[2];
+
+ for( Patch *p = patch; p; p = p->next ) {
+ p->getstepsize();
+ p->clamp();
+ pspec[0].stepsize = ((p->pspec[0].stepsize < pspec[0].stepsize) ? p->pspec[0].stepsize : pspec[0].stepsize);
+ pspec[0].sidestep[0] = ((p->pspec[0].sidestep[0] < pspec[0].sidestep[0]) ? p->pspec[0].sidestep[0] : pspec[0].sidestep[0]);
+ pspec[0].sidestep[1] = ((p->pspec[0].sidestep[1] < pspec[0].sidestep[1]) ? p->pspec[0].sidestep[1] : pspec[0].sidestep[1]);
+ pspec[1].stepsize = ((p->pspec[1].stepsize < pspec[1].stepsize) ? p->pspec[1].stepsize : pspec[1].stepsize);
+ pspec[1].sidestep[0] = ((p->pspec[1].sidestep[0] < pspec[1].sidestep[0]) ? p->pspec[1].sidestep[0] : pspec[1].sidestep[0]);
+ pspec[1].sidestep[1] = ((p->pspec[1].sidestep[1] < pspec[1].sidestep[1]) ? p->pspec[1].sidestep[1] : pspec[1].sidestep[1]);
+ }
+}
+
+void
+Patchlist::bbox( void )
+{
+ for( Patch *p = patch; p; p = p->next )
+ p->bbox();
+}
+
+int
+Patchlist::needsNonSamplingSubdivision( void )
+{
+ notInBbox = 0;
+ for( Patch *p = patch; p; p = p->next )
+ notInBbox |= p->needsNonSamplingSubdivision();
+ return notInBbox;
+}
+
+int
+Patchlist::needsSamplingSubdivision( void )
+{
+ pspec[0].needsSubdivision = 0;
+ pspec[1].needsSubdivision = 0;
+
+ for( Patch *p = patch; p; p = p->next ) {
+ pspec[0].needsSubdivision |= p->pspec[0].needsSubdivision;
+ pspec[1].needsSubdivision |= p->pspec[0].needsSubdivision;
+ }
+ return (pspec[0].needsSubdivision || pspec[1].needsSubdivision) ? 1 : 0;
+}
+
+int
+Patchlist::needsSubdivision( int param )
+{
+ return pspec[param].needsSubdivision;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/patchlist.h b/mesalib/src/glu/sgi/libnurbs/internals/patchlist.h
new file mode 100644
index 000000000..9bfc5b47a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/patchlist.h
@@ -0,0 +1,92 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * patchlist.h
+ *
+ */
+
+#ifndef __glupatchlist_h_
+#define __glupatchlist_h_
+
+#include "types.h"
+#include "defines.h"
+#include "patch.h"
+
+class Quilt;
+
+class Patchlist {
+friend class Subdivider;
+public:
+ Patchlist( Quilt *, REAL *, REAL * );
+ Patchlist( Patchlist &, int , REAL );
+ ~Patchlist();
+ void bbox();
+ int cullCheck( void );
+ void getstepsize( void );
+ int needsNonSamplingSubdivision( void );
+ int needsSamplingSubdivision( void );
+ int needsSubdivision( int );
+ REAL getStepsize( int );
+ void getRanges(REAL ranges[4]);
+
+ int get_uorder();
+ int get_vorder();
+private:
+ Patch *patch;
+ int notInBbox;
+ int needsSampling;
+ Pspec pspec[2];
+};
+
+inline REAL
+Patchlist::getStepsize( int param )
+{
+ return pspec[param].stepsize;
+}
+
+inline int
+Patchlist::get_uorder()
+{
+ return patch->get_uorder();
+
+}
+
+inline int
+ Patchlist::get_vorder()
+{
+ return patch->get_vorder();
+}
+
+
+
+
+
+#endif /* __glupatchlist_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/pwlarc.h b/mesalib/src/glu/sgi/libnurbs/internals/pwlarc.h
new file mode 100644
index 000000000..2e5175a6f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/pwlarc.h
@@ -0,0 +1,78 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * pwlarc.h
+ *
+ */
+
+#ifndef __glupwlarc_h_
+#define __glupwlarc_h_
+
+#include "myassert.h"
+#include "nurbsconsts.h"
+
+class TrimVertex;
+
+class PwlArc : public PooledObj { /* a piecewise-linear arc */
+public:
+ TrimVertex * pts; /* sample points */
+ int npts; /* number of sample points */
+ long type; /* curve type */
+ inline PwlArc( void );
+ inline PwlArc( int, TrimVertex * );
+ inline PwlArc( int, TrimVertex *, long );
+};
+
+inline
+PwlArc::PwlArc( void )
+{
+ type = N_P2D;
+ pts = 0;
+ npts = -1;
+}
+
+inline
+PwlArc::PwlArc( int _npts, TrimVertex *_pts )
+{
+ pts = _pts;
+ npts = _npts;
+ type = N_P2D;
+}
+
+inline
+PwlArc::PwlArc( int _npts, TrimVertex *_pts, long _type )
+{
+ pts = _pts;
+ npts = _npts;
+ type = _type;
+}
+
+#endif /* __glupwlarc_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/quilt.cc b/mesalib/src/glu/sgi/libnurbs/internals/quilt.cc
new file mode 100644
index 000000000..4fc58b747
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/quilt.cc
@@ -0,0 +1,276 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * quilt.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "quilt.h"
+#include "backend.h"
+#include "mapdesc.h"
+#include "flist.h"
+#include "knotvector.h"
+#include "patchlist.h"
+#include "math.h" //fglu_abs()
+#include "simplemath.h" //min()
+
+/* local preprocessor definitions */
+#define DEF_PATCH_STEPSIZE .4
+#define fsizeof(x) (sizeof(x)/sizeof(REAL))
+
+
+Quilt::Quilt( Mapdesc *_mapdesc )
+{
+ mapdesc = _mapdesc;
+}
+
+void
+Quilt::deleteMe( Pool& p )
+{
+ for( Quiltspec *q=qspec; q != eqspec; q++ ) {
+#if 1
+ if( q->breakpoints) delete[] q->breakpoints; q->breakpoints = 0;
+#else
+ if( q->breakpoints) {
+ delete[] q->breakpoints;
+ q->breakpoints = 0;
+printf("in here\n");
+ }
+#endif
+ }
+ if( cpts ) delete[] cpts;
+ cpts = 0;
+ PooledObj::deleteMe( p );
+}
+
+void
+Quilt::show( void )
+{
+#ifndef NDEBUG
+ int nc = mapdesc->getNcoords();
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[1].offset;
+ for( int i=0; i!= qspec[0].order * qspec[0].width; i++ ) {
+ for( int j = 0; j!= qspec[1].order * qspec[1].width; j++ ) {
+ for( int k=0; k < nc; k++ )
+ _glu_dprintf( "%g ", ps[i*qspec[0].stride + j*qspec[1].stride + k] );
+ _glu_dprintf( "\n" );
+ }
+ _glu_dprintf( "\n" );
+ }
+ _glu_dprintf( "\n" );
+#endif
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::select - find which map in each quilt contains the points
+ * pta and ptb with pta[i] < ptb[i]
+ *--------------------------------------------------------------------------
+ */
+
+void
+Quilt::select( REAL *pta, REAL *ptb )
+{
+ int dim = eqspec - qspec;
+ int i, j;
+ for( i=0; i<dim; i++) {
+ for( j=qspec[i].width-1; j>=0; j-- )
+ if( (qspec[i].breakpoints[j] <= pta[i] ) &&
+ (ptb[i] <= qspec[i].breakpoints[j+1] ) )
+ break;
+ assert( j != -1 );
+ qspec[i].index = j;
+ }
+}
+
+void
+Quilt::download( Backend &backend )
+{
+ if( getDimension() == 2 ) {
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[1].offset;
+ ps += qspec[0].index * qspec[0].order * qspec[0].stride;
+ ps += qspec[1].index * qspec[1].order * qspec[1].stride;
+ backend.surfpts( mapdesc->getType(), ps,
+ qspec[0].stride,
+ qspec[1].stride,
+ qspec[0].order,
+ qspec[1].order,
+ qspec[0].breakpoints[qspec[0].index],
+ qspec[0].breakpoints[qspec[0].index+1],
+ qspec[1].breakpoints[qspec[1].index],
+ qspec[1].breakpoints[qspec[1].index+1] );
+ } else {
+ REAL *ps = cpts;
+ ps += qspec[0].offset;
+ ps += qspec[0].index * qspec[0].order * qspec[0].stride;
+ backend.curvpts( mapdesc->getType(), ps,
+ qspec[0].stride,
+ qspec[0].order,
+ qspec[0].breakpoints[qspec[0].index],
+ qspec[0].breakpoints[qspec[0].index+1] );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::downloadAll - download each map that contains the current patch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Quilt::downloadAll( REAL *pta, REAL *ptb, Backend &backend )
+{
+ for( Quilt *m = this; m; m=m->next ) {
+ m->select( pta, ptb );
+ m->download( backend );
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Quilt::isCulled - determine if an entire quilt is trivially rejected.
+ *--------------------------------------------------------------------------
+ */
+
+int
+Quilt::isCulled( void )
+{
+ if( mapdesc->isCulling() )
+ return mapdesc->xformAndCullCheck( cpts + qspec[0].offset + qspec[1].offset,
+ qspec[0].order * qspec[0].width, qspec[0].stride,
+ qspec[1].order * qspec[1].width, qspec[1].stride );
+ else
+ return CULL_ACCEPT;
+}
+
+/*---------------------------------------------------------------------------
+ * Quilt::getRange - retrieve the valid paramater range of a set of quilts
+ *---------------------------------------------------------------------------
+ */
+void
+Quilt::getRange( REAL *from, REAL *to, Flist& slist, Flist &tlist )
+{
+ getRange( from, to, 0, slist );
+ getRange( from, to, 1, tlist );
+}
+
+/*---------------------------------------------------------------------------
+ * Quilt::getRange - retrieve the valid paramater range of a set of quilts
+ *---------------------------------------------------------------------------
+ */
+void
+Quilt::getRange( REAL *from, REAL *to, int i, Flist &list )
+{
+ Quilt *maps = this;
+ from[i] = maps->qspec[i].breakpoints[0];
+ to[i] = maps->qspec[i].breakpoints[maps->qspec[i].width];
+ int maxpts = 0;
+ Quilt_ptr m;
+ for( m=maps; m; m=m->next ) {
+ if( m->qspec[i].breakpoints[0] > from[i] )
+ from[i] = m->qspec[i].breakpoints[0];
+ if( m->qspec[i].breakpoints[m->qspec[i].width] < to[i] )
+ to[i] = m->qspec[i].breakpoints[m->qspec[i].width];
+ maxpts += m->qspec[i].width + 1;
+ }
+
+ list.grow( maxpts );
+
+ for( m=maps; m; m=m->next )
+ for( int j=0; j<=m->qspec[i].width; j++ ) {
+ list.add( m->qspec[i].breakpoints[j] );
+ }
+
+ list.filter( );
+ list.taper( from[i], to[i] );
+}
+
+void
+Quilt::getRange( REAL *from, REAL *to, Flist& slist )
+{
+ getRange( from, to, 0, slist );
+}
+
+void
+Quilt::findRates( Flist& slist, Flist& tlist, REAL rate[2] )
+{
+ findSampleRates( slist, tlist );
+ rate[0] = qspec[0].step_size;
+ rate[1] = qspec[1].step_size;
+
+ for( Quilt *q = next; q; q = q->next ) {
+ q->findSampleRates( slist, tlist );
+ if( q->qspec[0].step_size < rate[0] )
+ rate[0] = q->qspec[0].step_size;
+ if( q->qspec[1].step_size < rate[1] )
+ rate[1] = q->qspec[1].step_size;
+ }
+}
+
+void
+Quilt::findSampleRates( Flist& slist, Flist& tlist )
+{
+ qspec[0].step_size = DEF_PATCH_STEPSIZE *
+ (qspec[0].breakpoints[qspec[0].width] - qspec[0].breakpoints[0]);
+ qspec[1].step_size = DEF_PATCH_STEPSIZE *
+ (qspec[1].breakpoints[qspec[1].width] - qspec[1].breakpoints[0]);
+
+ for( int i = slist.start; i < slist.end-1; i++ ) {
+ for( int j = tlist.start; j < tlist.end-1; j++ ) {
+
+ REAL pta[2], ptb[2];
+ pta[0] = slist.pts[i];
+ ptb[0] = slist.pts[i+1];
+ pta[1] = tlist.pts[j];
+ ptb[1] = tlist.pts[j+1];
+ Patchlist patchlist( this, pta, ptb );
+ patchlist.getstepsize();
+
+ {
+ float edge_len_s = min(glu_abs(ptb[0]-pta[0]),1.0);
+ float edge_len_t = min(glu_abs(ptb[1]-pta[1]),1.0);
+
+ if( patchlist.getStepsize(0)/edge_len_s < qspec[0].step_size )
+ qspec[0].step_size = patchlist.getStepsize(0)/edge_len_s;
+ if( patchlist.getStepsize(1)/edge_len_t < qspec[1].step_size )
+ qspec[1].step_size = patchlist.getStepsize(1)/edge_len_t;
+ }
+ }
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/quilt.h b/mesalib/src/glu/sgi/libnurbs/internals/quilt.h
new file mode 100644
index 000000000..fe1e3309e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/quilt.h
@@ -0,0 +1,92 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * quilt.h
+ *
+ */
+
+#ifndef __gluquilt_h_
+#define __gluquilt_h_
+
+#include "defines.h"
+#include "bufpool.h"
+#include "types.h"
+
+class Backend;
+class Mapdesc;
+class Flist;
+struct Knotvector;
+
+/* constants for memory allocation of NURBS to Bezier conversion */
+#define MAXDIM 2
+
+struct Quiltspec { /* a specification for a dimension of a quilt */
+ int stride; /* words between points */
+ int width; /* number of segments */
+ int offset; /* words to first point */
+ int order; /* order */
+ int index; /* current segment number */
+ int bdry[2]; /* boundary edge flag */
+ REAL step_size;
+ Knot * breakpoints;
+};
+
+typedef Quiltspec *Quiltspec_ptr;
+
+class Quilt : public PooledObj { /* an array of bezier patches */
+public:
+ Quilt( Mapdesc * );
+ Mapdesc * mapdesc; /* map descriptor */
+ REAL * cpts; /* control points */
+ Quiltspec qspec[MAXDIM]; /* the dimensional data */
+ Quiltspec_ptr eqspec; /* qspec trailer */
+ Quilt *next; /* next quilt in linked list */
+
+public:
+ void deleteMe( Pool& );
+ void toBezier( Knotvector &, INREAL *, long );
+ void toBezier( Knotvector &, Knotvector &, INREAL *, long );
+ void select( REAL *, REAL * );
+ int getDimension( void ) { return eqspec - qspec; }
+ void download( Backend & );
+ void downloadAll( REAL *, REAL *, Backend & );
+ int isCulled( void );
+ void getRange( REAL *, REAL *, Flist&, Flist & );
+ void getRange( REAL *, REAL *, int, Flist & );
+ void getRange( REAL *, REAL *, Flist& );
+ void findRates( Flist& slist, Flist& tlist, REAL[2] );
+ void findSampleRates( Flist& slist, Flist& tlist );
+ void show();
+};
+
+typedef class Quilt *Quilt_ptr;
+
+#endif /* __gluquilt_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/reader.cc b/mesalib/src/glu/sgi/libnurbs/internals/reader.cc
new file mode 100644
index 000000000..6135eef60
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/reader.cc
@@ -0,0 +1,146 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * reader.c++
+ *
+ */
+
+#include <stdio.h>
+#include "glimports.h"
+#include "nurbsconsts.h"
+#include "reader.h"
+#include "trimvertex.h"
+#include "simplemath.h"
+
+//when read a pwlCurve, if two consecutive points are the same, then
+//eliminate one of them. This makes the tessellator more robust. The spec
+//assumes the application makes sure there are no redundant points.
+//but in Inspector, the trim curves seem to have redundant points a lot.
+//I guess other similar users may have the same problem.
+
+#define ELIMINATE_REDUNDANT_POINTS
+
+#ifdef ELIMINATE_REDUNDANT_POINTS
+#define equal(x,y) ( glu_abs(x-y) <= 0.00001)
+#endif
+
+#ifdef ELIMINATE_REDUNDANT_POINTS
+O_pwlcurve::O_pwlcurve( long _type, long count, INREAL *array, long byte_stride, TrimVertex *trimpts )
+{
+ next = 0;
+ used = 0;
+ owner = 0;
+ pts = trimpts;
+ npts = (int) count;
+ int i;
+
+ /* copy user data into internal trimming data structures */
+ switch( _type ) {
+ case N_P2D: {
+ TrimVertex *v = pts;
+ TrimVertex *prev = NULL;
+ int num = 0;
+ int doit;
+ for(i=0; i<count; i++) {
+ doit = 1;
+ if(prev != NULL)
+ {
+ if(equal(prev->param[0], array[0]) && equal(prev->param[1], array[1]))
+ {
+ doit = 0;
+ }
+ }
+
+ if(doit)
+ {
+ v->param[0] = (REAL) array[0];
+ v->param[1] = (REAL) array[1];
+ prev = v;
+ v++;
+ num++;
+ }
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ npts = num;
+ break;
+ }
+ case N_P2DR: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0] / (REAL) array[2];
+ v->param[1] = (REAL) array[1] / (REAL) array[2];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ }
+}
+#else
+O_pwlcurve::O_pwlcurve( long _type, long count, INREAL *array, long byte_stride, TrimVertex *trimpts )
+{
+ next = 0;
+ used = 0;
+ owner = 0;
+ pts = trimpts;
+ npts = (int) count;
+
+ /* copy user data into internal trimming data structures */
+ switch( _type ) {
+ case N_P2D: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0];
+ v->param[1] = (REAL) array[1];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ case N_P2DR: {
+ TrimVertex *v = pts;
+ for( TrimVertex *lastv = v + count; v != lastv; v++ ) {
+ v->param[0] = (REAL) array[0] / (REAL) array[2];
+ v->param[1] = (REAL) array[1] / (REAL) array[2];
+ array = (INREAL *) (((char *) array) + byte_stride);
+ }
+ break;
+ }
+ }
+}
+#endif
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/reader.h b/mesalib/src/glu/sgi/libnurbs/internals/reader.h
new file mode 100644
index 000000000..8a8dcebb5
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/reader.h
@@ -0,0 +1,132 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * reader.h
+ *
+ */
+
+#ifndef __glureader_h_
+#define __glureader_h_
+
+#include "bufpool.h"
+#include "types.h"
+
+enum Curvetype { ct_nurbscurve, ct_pwlcurve, ct_none };
+
+struct Property;
+struct O_surface;
+struct O_nurbssurface;
+struct O_trim;
+class O_pwlcurve;
+struct O_nurbscurve;
+struct O_curve;
+class Quilt;
+class TrimVertex;
+
+
+struct O_curve : public PooledObj {
+ union {
+ O_nurbscurve *o_nurbscurve;
+ O_pwlcurve *o_pwlcurve;
+ } curve;
+ Curvetype curvetype; /* arc type: pwl or nurbs */
+ O_curve * next; /* next arc in loop */
+ O_surface * owner; /* owning surface */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ long nuid;
+ O_curve() { next = 0; used = 0; owner = 0;
+ curve.o_pwlcurve = 0; }
+ };
+
+struct O_nurbscurve : public PooledObj {
+ Quilt *bezier_curves; /* array of bezier curves */
+ long type; /* range descriptor */
+ REAL tesselation; /* tesselation tolerance */
+ int method; /* tesselation method */
+ O_nurbscurve * next; /* next curve in list */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ O_curve * owner; /* owning curve */
+ O_nurbscurve( long _type )
+ { type = _type; owner = 0; next = 0; used = 0; }
+ };
+
+class O_pwlcurve : public PooledObj {
+public:
+ TrimVertex *pts; /* array of trim vertices */
+ int npts; /* number of trim vertices */
+ O_pwlcurve * next; /* next curve in list */
+ int used; /* curve called in cur surf */
+ int save; /* 1 if in display list */
+ O_curve * owner; /* owning curve */
+ O_pwlcurve( long, long, INREAL *, long, TrimVertex * );
+ };
+
+struct O_trim : public PooledObj {
+ O_curve *o_curve; /* closed trim loop */
+ O_trim * next; /* next loop along trim */
+ int save; /* 1 if in display list */
+ O_trim() { next = 0; o_curve = 0; }
+ };
+
+struct O_nurbssurface : public PooledObj {
+ Quilt * bezier_patches;/* array of bezier patches */
+ long type; /* range descriptor */
+ O_surface * owner; /* owning surface */
+ O_nurbssurface * next; /* next surface in chain */
+ int save; /* 1 if in display list */
+ int used; /* 1 if prev called in block */
+ O_nurbssurface( long _type )
+ { type = _type; owner = 0; next = 0; used = 0; }
+ };
+
+struct O_surface : public PooledObj {
+ O_nurbssurface * o_nurbssurface; /* linked list of surfaces */
+ O_trim * o_trim; /* list of trim loops */
+ int save; /* 1 if in display list */
+ long nuid;
+ O_surface() { o_trim = 0; o_nurbssurface = 0; }
+ };
+
+struct Property : public PooledObj {
+ long type;
+ long tag;
+ REAL value;
+ int save; /* 1 if in display list */
+ Property( long _type, long _tag, INREAL _value )
+ { type = _type; tag = _tag; value = (REAL) _value; }
+ Property( long _tag, INREAL _value )
+ { type = 0; tag = _tag; value = (REAL) _value; }
+ };
+
+class NurbsTessellator;
+#endif /* __glureader_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/renderhints.cc b/mesalib/src/glu/sgi/libnurbs/internals/renderhints.cc
new file mode 100644
index 000000000..a3aa62d42
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/renderhints.cc
@@ -0,0 +1,133 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * renderhints.c++
+ *
+ */
+
+#include "glimports.h"
+#include "mystdio.h"
+#include "renderhints.h"
+#include "defines.h"
+#include "nurbsconsts.h"
+
+
+/*--------------------------------------------------------------------------
+ * Renderhints::Renderhints - set all window specific options
+ *--------------------------------------------------------------------------
+ */
+Renderhints::Renderhints()
+{
+ display_method = N_FILL;
+ errorchecking = N_MSG;
+ subdivisions = 6.0;
+ tmp1 = 0.0;
+}
+
+void
+Renderhints::init( void )
+{
+ maxsubdivisions = (int) subdivisions;
+ if( maxsubdivisions < 0 ) maxsubdivisions = 0;
+
+
+ if( display_method == N_FILL ) {
+ wiretris = 0;
+ wirequads = 0;
+ } else if( display_method == N_OUTLINE_TRI ) {
+ wiretris = 1;
+ wirequads = 0;
+ } else if( display_method == N_OUTLINE_QUAD ) {
+ wiretris = 0;
+ wirequads = 1;
+ } else {
+ wiretris = 1;
+ wirequads = 1;
+ }
+}
+
+int
+Renderhints::isProperty( long property )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ case N_ERRORCHECKING:
+ case N_SUBDIVISIONS:
+ case N_TMP1:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+REAL
+Renderhints::getProperty( long property )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ return display_method;
+ case N_ERRORCHECKING:
+ return errorchecking;
+ case N_SUBDIVISIONS:
+ return subdivisions;
+ case N_TMP1:
+ return tmp1;
+ default:
+ abort();
+ return -1; //not necessary, needed to shut up compiler
+ }
+}
+
+void
+Renderhints::setProperty( long property, REAL value )
+{
+ switch ( property ) {
+ case N_DISPLAY:
+ display_method = value;
+ break;
+ case N_ERRORCHECKING:
+ errorchecking = value;
+ break;
+ case N_SUBDIVISIONS:
+ subdivisions = value;
+ break;
+ case N_TMP1: /* unused */
+ tmp1 = value;
+ break;
+ default:
+ abort();
+ break;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/renderhints.h b/mesalib/src/glu/sgi/libnurbs/internals/renderhints.h
new file mode 100644
index 000000000..444f649be
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/renderhints.h
@@ -0,0 +1,60 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * renderhints.h
+ *
+ */
+
+#ifndef __glurenderhints_h_
+#define __glurenderhints_h_
+
+#include "types.h"
+
+class Renderhints {
+public:
+ Renderhints( void );
+ void init( void );
+ int isProperty( long );
+ REAL getProperty( long );
+ void setProperty( long, REAL );
+
+ REAL display_method; /* display mode */
+ REAL errorchecking; /* activate error checking */
+ REAL subdivisions; /* maximum number of subdivisions per patch */
+ REAL tmp1; /* unused */
+
+ int displaydomain;
+ int maxsubdivisions;
+ int wiretris;
+ int wirequads;
+};
+
+#endif /* __glurenderhints_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/simplemath.h b/mesalib/src/glu/sgi/libnurbs/internals/simplemath.h
new file mode 100644
index 000000000..0a060c57e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/simplemath.h
@@ -0,0 +1,50 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * simplemath.h
+ *
+ */
+
+#ifndef __glusimplemath_h_
+#define __glusimplemath_h_
+
+/* simple inline routines */
+
+inline int
+max( int x, int y ) { return ( x < y ) ? y : x; }
+
+inline REAL
+min( REAL x, REAL y ) { return ( x > y ) ? y : x; }
+
+inline REAL
+glu_abs( REAL x ) { return ( x < 0.0 ) ? -x : x; }
+
+#endif /* __glusimplemath_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/slicer.cc b/mesalib/src/glu/sgi/libnurbs/internals/slicer.cc
new file mode 100644
index 000000000..27d2a650d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/slicer.cc
@@ -0,0 +1,1300 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * slicer.c++
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "glimports.h"
+#include "mystdio.h"
+#include "myassert.h"
+#include "bufpool.h"
+#include "slicer.h"
+#include "backend.h"
+#include "arc.h"
+#include "gridtrimvertex.h"
+#include "simplemath.h"
+#include "trimvertex.h"
+#include "varray.h"
+
+#include "polyUtil.h" //for area()
+
+//static int count=0;
+
+/*USE_OPTTT is initiated in trimvertex.h*/
+
+#ifdef USE_OPTTT
+ #include <GL/gl.h>
+#endif
+
+//#define USE_READ_FLAG //whether to use new or old tesselator
+ //if defined, it reads "flagFile",
+ // if the number is 1, then use new tess
+ // otherwise, use the old tess.
+ //if not defined, then use new tess.
+#ifdef USE_READ_FLAG
+static Int read_flag(char* name);
+Int newtess_flag = read_flag("flagFile");
+#endif
+
+//#define COUNT_TRIANGLES
+#ifdef COUNT_TRIANGLES
+Int num_triangles = 0;
+Int num_quads = 0;
+#endif
+
+#define max(a,b) ((a>b)? a:b)
+#define ZERO 0.00001 /*determing whether a loop is a rectngle or not*/
+#define equalRect(a,b) ((glu_abs(a-b) <= ZERO)? 1:0) //only used in tessellating a rectangle
+
+#if 0 // UNUSED
+static Int is_Convex(Arc_ptr loop)
+{
+ if(area(loop->tail(), loop->head(), loop->next->head()) <0 )
+ return 0;
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
+ {
+ if(area(jarc->tail(), jarc->head(), jarc->next->head()) < 0)
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+/******triangulate a monotone polygon**************/
+#include "monoTriangulation.h"
+#if 0 // UNUSED
+static int is_U_monotone(Arc_ptr loop)
+{
+ int n_changes=0;
+ int prev_sign;
+ int cur_sign;
+ Arc_ptr temp;
+
+ cur_sign = compV2InX(loop->head(), loop->tail());
+
+ n_changes = (compV2InX(loop->prev->head(), loop->prev->tail())
+ != cur_sign);
+
+ for(temp=loop->next; temp != loop; temp = temp->next)
+ {
+ prev_sign = cur_sign;
+ cur_sign = compV2InX(temp->head(), temp->tail());
+ if(cur_sign != prev_sign)
+ {
+#ifdef DEBUG
+ printf("***change signe\n");
+#endif
+ n_changes++;
+ }
+ }
+ if(n_changes == 2) return 1;
+ else
+ return 0;
+}
+#endif
+
+inline int compInY(REAL a[2], REAL b[2])
+{
+ if(a[1] < b[1])
+ return -1;
+ else if (a[1] > b[1])
+ return 1;
+ else if(a[0] > b[0])
+ return 1;
+ else return -1;
+}
+
+void monoTriangulationLoop(Arc_ptr loop, Backend& backend, primStream* pStream)
+{
+ int i;
+ //find the top, bottom, increasing and decreasing chain
+ //then call monoTrianulation
+ Arc_ptr jarc, temp;
+ Arc_ptr top;
+ Arc_ptr bot;
+ top = bot = loop;
+ if(compInY(loop->tail(), loop->prev->tail()) < 0)
+ {
+ //first find bot
+ for(temp = loop->next; temp != loop; temp = temp->next)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) > 0)
+ break;
+ }
+ bot = temp->prev;
+ //then find top
+ for(temp=loop->prev; temp != loop; temp = temp->prev)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) > 0)
+ break;
+ }
+ top = temp;
+ }
+ else //loop > loop->prev
+ {
+ for(temp=loop->next; temp != loop; temp = temp->next)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) < 0)
+ break;
+ }
+ top = temp->prev;
+ for(temp=loop->prev; temp != loop; temp = temp->prev)
+ {
+ if(compInY(temp->tail(), temp->prev->tail()) < 0)
+ break;
+ }
+ bot = temp;
+ }
+ //creat increase and decrease chains
+ vertexArray inc_chain(50); //this is a dynamci array
+ for(i=1; i<=top->pwlArc->npts-2; i++)
+ {
+ //the first vertex is the top which doesn't below to inc_chain
+ inc_chain.appendVertex(top->pwlArc->pts[i].param);
+ }
+ for(jarc=top->next; jarc != bot; jarc = jarc->next)
+ {
+ for(i=0; i<=jarc->pwlArc->npts-2; i++)
+ {
+ inc_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+
+ }
+ vertexArray dec_chain(50);
+ for(jarc = top->prev; jarc != bot; jarc = jarc->prev)
+ {
+ for(i=jarc->pwlArc->npts-2; i>=0; i--)
+ {
+ dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+ }
+ for(i=bot->pwlArc->npts-2; i>=1; i--)
+ {
+ dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
+ }
+
+ monoTriangulationRec(top->tail(), bot->tail(), &inc_chain, 0,
+ &dec_chain, 0, &backend);
+
+}
+
+/********tesselate a rectanlge (OPTIMIZATION**************/
+static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend);
+
+static Int is_rect(Arc_ptr loop)
+{
+ Int nlines =1;
+ for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
+ {
+ nlines++;
+ if(nlines == 5)
+ break;
+ }
+ if(nlines != 4)
+ return 0;
+
+
+/*
+printf("here1\n");
+printf("loop->tail=(%f,%f)\n", loop->tail()[0], loop->tail()[1]);
+printf("loop->head=(%f,%f)\n", loop->head()[0], loop->head()[1]);
+printf("loop->next->tail=(%f,%f)\n", loop->next->tail()[0], loop->next->tail()[1]);
+printf("loop->next->head=(%f,%f)\n", loop->next->head()[0], loop->next->head()[1]);
+if(fglu_abs(loop->tail()[0] - loop->head()[0])<0.000001)
+ printf("equal 1\n");
+if(loop->next->tail()[1] == loop->next->head()[1])
+ printf("equal 2\n");
+*/
+
+ if( (glu_abs(loop->tail()[0] - loop->head()[0])<=ZERO) &&
+ (glu_abs(loop->next->tail()[1] - loop->next->head()[1])<=ZERO) &&
+ (glu_abs(loop->prev->tail()[1] - loop->prev->head()[1])<=ZERO) &&
+ (glu_abs(loop->prev->prev->tail()[0] - loop->prev->prev->head()[0])<=ZERO)
+ )
+ return 1;
+ else if
+ ( (glu_abs(loop->tail()[1] - loop->head()[1]) <= ZERO) &&
+ (glu_abs(loop->next->tail()[0] - loop->next->head()[0]) <= ZERO) &&
+ (glu_abs(loop->prev->tail()[0] - loop->prev->head()[0]) <= ZERO) &&
+ (glu_abs(loop->prev->prev->tail()[1] - loop->prev->prev->head()[1]) <= ZERO)
+ )
+ return 1;
+ else
+ return 0;
+}
+
+
+//a line with the same u for opt
+#ifdef USE_OPTTT
+static void evalLineNOGE_BU(TrimVertex *verts, int n, Backend& backend)
+{
+ int i;
+ backend.preEvaluateBU(verts[0].param[0]);
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE_BU(&verts[i]);
+}
+#endif
+
+//a line with the same v for opt
+#ifdef USE_OPTTT
+static void evalLineNOGE_BV(TrimVertex *verts, int n, Backend& backend)
+{
+ int i;
+ backend.preEvaluateBV(verts[0].param[1]);
+
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE_BV(&verts[i]);
+}
+#endif
+
+#ifdef USE_OPTTT
+static void evalLineNOGE(TrimVertex *verts, int n, Backend& backend)
+{
+
+ if(verts[0].param[0] == verts[n-1].param[0]) //all u;s are equal
+ evalLineNOGE_BU(verts, n, backend);
+ else if(verts[0].param[1] == verts[n-1].param[1]) //all v's are equal
+ evalLineNOGE_BV(verts, n, backend);
+ else
+ {
+ int i;
+ for(i=0; i<n; i++)
+ backend.tmeshvertNOGE(&verts[i]);
+ }
+}
+#endif
+
+inline void OPT_OUTVERT(TrimVertex& vv, Backend& backend)
+{
+
+#ifdef USE_OPTTT
+ glNormal3fv(vv.cache_normal);
+ glVertex3fv(vv.cache_point);
+#else
+
+ backend.tmeshvert(&vv);
+
+#endif
+
+}
+
+static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend);
+
+static void triangulateRect(Arc_ptr loop, Backend& backend, int TB_or_LR, int ulinear, int vlinear)
+{
+ //we know the loop is a rectangle, but not sure which is top
+ Arc_ptr top, bot, left, right;
+ if(loop->tail()[1] == loop->head()[1])
+ {
+ if(loop->tail()[1] > loop->prev->prev->tail()[1])
+ {
+
+ top = loop;
+ }
+ else{
+
+ top = loop->prev->prev;
+ }
+ }
+ else
+ {
+ if(loop->tail()[0] > loop->prev->prev->tail()[0])
+ {
+ //loop is the right arc
+
+ top = loop->next;
+ }
+ else
+ {
+
+ top = loop->prev;
+ }
+ }
+ left = top->next;
+ bot = left->next;
+ right= bot->next;
+
+ //if u, v are both nonlinear, then if the
+ //boundary is tessellated dense, we also
+ //sample the inside to get a better tesslletant.
+ if( (!ulinear) && (!vlinear))
+ {
+ int nu = top->pwlArc->npts;
+ if(nu < bot->pwlArc->npts)
+ nu = bot->pwlArc->npts;
+ int nv = left->pwlArc->npts;
+ if(nv < right->pwlArc->npts)
+ nv = right->pwlArc->npts;
+/*
+ if(nu > 2 && nv > 2)
+ {
+ triangulateRectGen(top, nu-2, nv-2, backend);
+ return;
+ }
+*/
+ }
+
+ if(TB_or_LR == 1)
+ triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
+ else if(TB_or_LR == -1)
+ triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
+ else
+ {
+ Int maxPointsTB = top->pwlArc->npts + bot->pwlArc->npts;
+ Int maxPointsLR = left->pwlArc->npts + right->pwlArc->npts;
+
+ if(maxPointsTB < maxPointsLR)
+ triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
+ else
+ triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
+ }
+}
+
+static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend)
+{ //if(maxPointsTB >= maxPointsLR)
+ {
+
+ Int d, topd_left, topd_right, botd_left, botd_right, i,j;
+ d = left->npts /2;
+
+#ifdef USE_OPTTT
+ evalLineNOGE(top->pts, top->npts, backend);
+ evalLineNOGE(bot->pts, bot->npts, backend);
+ evalLineNOGE(left->pts, left->npts, backend);
+ evalLineNOGE(right->pts, right->npts, backend);
+#endif
+
+ if(top->npts == 2) {
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[0], backend);//the root
+ for(i=0; i<left->npts; i++){
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ for(i=1; i<= bot->npts-2; i++){
+ OPT_OUTVERT(bot->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[bot->npts-2], backend);
+ for(i=0; i<right->npts; i++){
+ OPT_OUTVERT(right->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ else if(bot->npts == 2) {
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[0], backend);//the root
+ for(i=0; i<right->npts; i++){
+ OPT_OUTVERT(right->pts[i], backend);
+ }
+ for(i=1; i<= top->npts-2; i++){
+ OPT_OUTVERT(top->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+ for(i=0; i<left->npts; i++){
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ else { //both top and bot have >=3 points
+
+ backend.bgntfan();
+
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+
+ for(i=0; i<=d; i++)
+ {
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+
+ backend.bgntfan();
+
+ OPT_OUTVERT(bot->pts[1], backend);
+
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+
+ for(i=d; i< left->npts; i++)
+ {
+ OPT_OUTVERT(left->pts[i], backend);
+ }
+ backend.endtfan();
+
+ d = right->npts/2;
+ //output only when d<right->npts-1 and
+ //
+ if(d<right->npts-1)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& top->pts[1]);
+ OPT_OUTVERT(top->pts[1], backend);
+ for(i=d; i< right->npts; i++)
+ {
+ // backend.tmeshvert(& right->pts[i]);
+
+ OPT_OUTVERT(right->pts[i], backend);
+
+ }
+ backend.endtfan();
+ }
+
+ backend.bgntfan();
+ // backend.tmeshvert(& bot->pts[bot->npts-2]);
+ OPT_OUTVERT( bot->pts[bot->npts-2], backend);
+ for(i=0; i<=d; i++)
+ {
+ // backend.tmeshvert(& right->pts[i]);
+ OPT_OUTVERT(right->pts[i], backend);
+
+ }
+
+ // backend.tmeshvert(& top->pts[1]);
+ OPT_OUTVERT(top->pts[1], backend);
+
+ backend.endtfan();
+
+
+ topd_left = top->npts-2;
+ topd_right = 1; //topd_left>= topd_right
+
+ botd_left = 1;
+ botd_right = bot->npts-2; //botd_left<= bot_dright
+
+
+ if(top->npts < bot->npts)
+ {
+ int delta=bot->npts - top->npts;
+ int u = delta/2;
+ botd_left = 1+ u;
+ botd_right = bot->npts-2-( delta-u);
+
+ if(botd_left >1)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& top->pts[top->npts-2]);
+ OPT_OUTVERT(top->pts[top->npts-2], backend);
+ for(i=1; i<= botd_left; i++)
+ {
+ // backend.tmeshvert(& bot->pts[i]);
+ OPT_OUTVERT(bot->pts[i] , backend);
+ }
+ backend.endtfan();
+ }
+ if(botd_right < bot->npts-2)
+ {
+ backend.bgntfan();
+ OPT_OUTVERT(top->pts[1], backend);
+ for(i=botd_right; i<= bot->npts-2; i++)
+ OPT_OUTVERT(bot->pts[i], backend);
+ backend.endtfan();
+ }
+ }
+ else if(top->npts> bot->npts)
+ {
+ int delta=top->npts-bot->npts;
+ int u = delta/2;
+ topd_left = top->npts-2 - u;
+ topd_right = 1+delta-u;
+
+ if(topd_left < top->npts-2)
+ {
+ backend.bgntfan();
+ // backend.tmeshvert(& bot->pts[1]);
+ OPT_OUTVERT(bot->pts[1], backend);
+ for(i=topd_left; i<= top->npts-2; i++)
+ {
+ // backend.tmeshvert(& top->pts[i]);
+ OPT_OUTVERT(top->pts[i], backend);
+ }
+ backend.endtfan();
+ }
+ if(topd_right > 1)
+ {
+ backend.bgntfan();
+ OPT_OUTVERT(bot->pts[bot->npts-2], backend);
+ for(i=1; i<= topd_right; i++)
+ OPT_OUTVERT(top->pts[i], backend);
+ backend.endtfan();
+ }
+ }
+
+ if(topd_left <= topd_right)
+ return;
+
+ backend.bgnqstrip();
+ for(j=botd_left, i=topd_left; i>=topd_right; i--,j++)
+ {
+ // backend.tmeshvert(& top->pts[i]);
+ // backend.tmeshvert(& bot->pts[j]);
+ OPT_OUTVERT(top->pts[i], backend);
+ OPT_OUTVERT(bot->pts[j], backend);
+ }
+ backend.endqstrip();
+
+ }
+ }
+}
+
+
+static void triangulateRectCenter(int n_ulines, REAL* u_val,
+ int n_vlines, REAL* v_val,
+ Backend& backend)
+{
+
+ // XXX this code was patched by Diego Santa Cruz <Diego.SantaCruz@epfl.ch>
+ // to fix a problem in which glMapGrid2f() was called with bad parameters.
+ // This has beens submitted to SGI but not integrated as of May 1, 2001.
+ if(n_ulines>1 && n_vlines>1) {
+ backend.surfgrid(u_val[0], u_val[n_ulines-1], n_ulines-1,
+ v_val[n_vlines-1], v_val[0], n_vlines-1);
+ backend.surfmesh(0,0,n_ulines-1,n_vlines-1);
+ }
+
+ return;
+
+ /*
+ for(i=0; i<n_vlines-1; i++)
+ {
+
+ backend.bgnqstrip();
+ for(j=0; j<n_ulines; j++)
+ {
+ trimVert.param[0] = u_val[j];
+ trimVert.param[1] = v_val[i+1];
+ backend.tmeshvert(& trimVert);
+
+ trimVert.param[1] = v_val[i];
+ backend.tmeshvert(& trimVert);
+ }
+ backend.endqstrip();
+
+ }
+ */
+}
+
+//it works for top, bot, left ad right, you need ot select correct arguments
+static void triangulateRectTopGen(Arc_ptr arc, int n_ulines, REAL* u_val, Real v, int dir, int is_u, Backend& backend)
+{
+
+ if(is_u)
+ {
+ int i,k;
+ REAL* upper_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
+ assert(upper_val);
+ if(dir)
+ {
+ for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
+ {
+ upper_val[k] = arc->pwlArc->pts[i].param[0];
+ }
+ backend.evalUStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[1],
+ upper_val,
+ n_ulines, v, u_val);
+ }
+ else
+ {
+ for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
+ {
+ upper_val[k] = arc->pwlArc->pts[i].param[0];
+
+ }
+
+ backend.evalUStrip(
+ n_ulines, v, u_val,
+ arc->pwlArc->npts, arc->pwlArc->pts[0].param[1], upper_val
+ );
+ }
+
+ free(upper_val);
+ return;
+ }
+ else //is_v
+ {
+ int i,k;
+ REAL* left_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
+ assert(left_val);
+ if(dir)
+ {
+ for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
+ {
+ left_val[k] = arc->pwlArc->pts[i].param[1];
+ }
+ backend.evalVStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[0],
+ left_val,
+ n_ulines, v, u_val);
+ }
+ else
+ {
+ for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
+ {
+ left_val[k] = arc->pwlArc->pts[i].param[1];
+ }
+ backend.evalVStrip(
+ n_ulines, v, u_val,
+ arc->pwlArc->npts, arc->pwlArc->pts[0].param[0], left_val
+ );
+ }
+ free(left_val);
+ return;
+ }
+
+ //the following is a different version of the above code. If you comment
+ //the above code, the following code will still work. The reason to leave
+ //the folliwng code here is purely for testing purpose.
+ /*
+ int i,j;
+ PwlArc* parc = arc->pwlArc;
+ int d1 = parc->npts-1;
+ int d2 = 0;
+ TrimVertex trimVert;
+ trimVert.nuid = 0;//????
+ REAL* temp_u_val = u_val;
+ if(dir ==0) //have to reverse u_val
+ {
+ temp_u_val = (REAL*) malloc(sizeof(REAL) * n_ulines);
+ assert(temp_u_val);
+ for(i=0; i<n_ulines; i++)
+ temp_u_val[i] = u_val[n_ulines-1-i];
+ }
+ u_val = temp_u_val;
+
+ if(parc->npts > n_ulines)
+ {
+ d1 = n_ulines-1;
+
+ backend.bgntfan();
+ if(is_u){
+ trimVert.param[0] = u_val[0];
+ trimVert.param[1] = v;
+ }
+ else
+ {
+ trimVert.param[1] = u_val[0];
+ trimVert.param[0] = v;
+ }
+
+ backend.tmeshvert(& trimVert);
+ for(i=d1; i< parc->npts; i++)
+ backend.tmeshvert(& parc->pts[i]);
+ backend.endtfan();
+
+
+ }
+ else if(parc->npts < n_ulines)
+ {
+ d2 = n_ulines-parc->npts;
+
+
+ backend.bgntfan();
+ backend.tmeshvert(& parc->pts[parc->npts-1]);
+ for(i=0; i<= d2; i++)
+ {
+ if(is_u){
+ trimVert.param[0] = u_val[i];
+ trimVert.param[1] = v;
+ }
+ else
+ {
+ trimVert.param[1] = u_val[i];
+ trimVert.param[0] = v;
+ }
+ backend.tmeshvert(&trimVert);
+ }
+ backend.endtfan();
+
+ }
+ if(d1>0){
+
+
+ backend.bgnqstrip();
+ for(i=d1, j=d2; i>=0; i--, j++)
+ {
+ backend.tmeshvert(& parc->pts[i]);
+
+ if(is_u){
+ trimVert.param[0] = u_val[j];
+ trimVert.param[1] = v;
+ }
+ else{
+ trimVert.param[1] = u_val[j];
+ trimVert.param[0] = v;
+ }
+ backend.tmeshvert(&trimVert);
+
+
+
+ }
+ backend.endqstrip();
+
+
+ }
+ if(dir == 0) //temp_u_val was mallocated
+ free(temp_u_val);
+ */
+}
+
+//n_ulines is the number of ulines inside, and n_vlines is the number of vlines
+//inside, different from meanings elsewhere!!!
+static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend)
+{
+
+ int i;
+ //we know the loop is a rectangle, but not sure which is top
+ Arc_ptr top, bot, left, right;
+
+ if(equalRect(loop->tail()[1] , loop->head()[1]))
+ {
+
+ if(loop->tail()[1] > loop->prev->prev->tail()[1])
+ {
+
+ top = loop;
+ }
+ else{
+
+ top = loop->prev->prev;
+ }
+ }
+ else
+ {
+ if(loop->tail()[0] > loop->prev->prev->tail()[0])
+ {
+ //loop is the right arc
+
+ top = loop->next;
+ }
+ else
+ {
+
+ top = loop->prev;
+ }
+ }
+
+ left = top->next;
+ bot = left->next;
+ right= bot->next;
+
+#ifdef COUNT_TRIANGLES
+ num_triangles += loop->pwlArc->npts +
+ left->pwlArc->npts +
+ bot->pwlArc->npts +
+ right->pwlArc->npts
+ + 2*n_ulines + 2*n_vlines
+ -8;
+ num_quads += (n_ulines-1)*(n_vlines-1);
+#endif
+/*
+ backend.surfgrid(left->tail()[0], right->tail()[0], n_ulines+1,
+ top->tail()[1], bot->tail()[1], n_vlines+1);
+// if(n_ulines>1 && n_vlines>1)
+ backend.surfmesh(0,0,n_ulines+1,n_vlines+1);
+return;
+*/
+ REAL* u_val=(REAL*) malloc(sizeof(REAL)*n_ulines);
+ assert(u_val);
+ REAL* v_val=(REAL*)malloc(sizeof(REAL) * n_vlines);
+ assert(v_val);
+ REAL u_stepsize = (right->tail()[0] - left->tail()[0])/( (REAL) n_ulines+1);
+ REAL v_stepsize = (top->tail()[1] - bot->tail()[1])/( (REAL) n_vlines+1);
+ Real temp=left->tail()[0]+u_stepsize;
+ for(i=0; i<n_ulines; i++)
+ {
+ u_val[i] = temp;
+ temp += u_stepsize;
+ }
+ temp = bot->tail()[1] + v_stepsize;
+ for(i=0; i<n_vlines; i++)
+ {
+ v_val[i] = temp;
+ temp += v_stepsize;
+ }
+
+ triangulateRectTopGen(top, n_ulines, u_val, v_val[n_vlines-1], 1,1, backend);
+ triangulateRectTopGen(bot, n_ulines, u_val, v_val[0], 0, 1, backend);
+ triangulateRectTopGen(left, n_vlines, v_val, u_val[0], 1, 0, backend);
+ triangulateRectTopGen(right, n_vlines, v_val, u_val[n_ulines-1], 0,0, backend);
+
+
+
+
+ //triangulate the center
+ triangulateRectCenter(n_ulines, u_val, n_vlines, v_val, backend);
+
+ free(u_val);
+ free(v_val);
+
+}
+
+
+
+
+/**********for reading newtess_flag from a file**********/
+#ifdef USE_READ_FLAG
+static Int read_flag(char* name)
+{
+ Int ret;
+ FILE* fp = fopen(name, "r");
+ if(fp == NULL)
+ {
+ fprintf(stderr, "can't open file %s\n", name);
+ exit(1);
+ }
+ fscanf(fp, "%i", &ret);
+ fclose(fp);
+ return ret;
+}
+#endif
+
+/***********nextgen tess****************/
+#include "sampleMonoPoly.h"
+directedLine* arcToDLine(Arc_ptr arc)
+{
+ int i;
+ Real vert[2];
+ directedLine* ret;
+ sampledLine* sline = new sampledLine(arc->pwlArc->npts);
+ for(i=0; i<arc->pwlArc->npts; i++)
+ {
+ vert[0] = arc->pwlArc->pts[i].param[0];
+ vert[1] = arc->pwlArc->pts[i].param[1];
+ sline->setPoint(i, vert);
+ }
+ ret = new directedLine(INCREASING, sline);
+ return ret;
+}
+
+/*an pwlArc may not be a straight line*/
+directedLine* arcToMultDLines(directedLine* original, Arc_ptr arc)
+{
+ directedLine* ret = original;
+ int is_linear = 0;
+ if(arc->pwlArc->npts == 2 )
+ is_linear = 1;
+ else if(area(arc->pwlArc->pts[0].param, arc->pwlArc->pts[1].param, arc->pwlArc->pts[arc->pwlArc->npts-1].param) == 0.0)
+ is_linear = 1;
+
+ if(is_linear)
+ {
+ directedLine *dline = arcToDLine(arc);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ return ret;
+ }
+ else /*not linear*/
+ {
+ for(Int i=0; i<arc->pwlArc->npts-1; i++)
+ {
+ Real vert[2][2];
+ vert[0][0] = arc->pwlArc->pts[i].param[0];
+ vert[0][1] = arc->pwlArc->pts[i].param[1];
+ vert[1][0] = arc->pwlArc->pts[i+1].param[0];
+ vert[1][1] = arc->pwlArc->pts[i+1].param[1];
+
+ sampledLine *sline = new sampledLine(2, vert);
+ directedLine *dline = new directedLine(INCREASING, sline);
+ if(ret == NULL)
+ ret = dline;
+ else
+ ret->insert(dline);
+ }
+ return ret;
+ }
+}
+
+
+
+directedLine* arcLoopToDLineLoop(Arc_ptr loop)
+{
+ directedLine* ret;
+
+ if(loop == NULL)
+ return NULL;
+ ret = arcToMultDLines(NULL, loop);
+//ret->printSingle();
+ for(Arc_ptr temp = loop->next; temp != loop; temp = temp->next){
+ ret = arcToMultDLines(ret, temp);
+//ret->printSingle();
+ }
+
+ return ret;
+}
+
+/*
+void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
+{
+ TrimVertex *trimVert = (TrimVertex*)malloc(sizeof(TrimVertex));
+ trimVert -> nuid = 0;//????
+
+ Real* u_values = grid->get_u_values();
+ Real* v_values = grid->get_v_values();
+
+ Int i,j,k,l;
+
+ for(l=0; l<rbArray->get_n_elements(); l++)
+ {
+ rectBlock* block = rbArray->get_element(l);
+ for(k=0, i=block->get_upGridLineIndex(); i>block->get_lowGridLineIndex(); i--, k++)
+ {
+
+ backend.bgnqstrip();
+ for(j=block->get_leftIndices()[k+1]; j<= block->get_rightIndices()[k+1]; j++)
+ {
+ trimVert->param[0] = u_values[j];
+ trimVert->param[1] = v_values[i];
+ backend.tmeshvert(trimVert);
+
+ trimVert->param[1] = v_values[i-1];
+ backend.tmeshvert(trimVert);
+
+ }
+ backend.endqstrip();
+
+ }
+ }
+
+ free(trimVert);
+}
+*/
+
+void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
+{
+ Int i,j,k;
+
+ Int n_vlines=grid->get_n_vlines();
+ //the reason to switch the position of v_max and v_min is because of the
+ //the orientation problem. glEvalMesh generates quad_strip clockwise, but
+ //we need counter-clockwise.
+ backend.surfgrid(grid->get_u_min(), grid->get_u_max(), grid->get_n_ulines()-1,
+ grid->get_v_max(), grid->get_v_min(), n_vlines-1);
+
+
+ for(j=0; j<rbArray->get_n_elements(); j++)
+ {
+ rectBlock* block = rbArray->get_element(j);
+ Int low = block->get_lowGridLineIndex();
+ Int high = block->get_upGridLineIndex();
+
+ for(k=0, i=high; i>low; i--, k++)
+ {
+ backend.surfmesh(block->get_leftIndices()[k+1], n_vlines-1-i, block->get_rightIndices()[k+1]-block->get_leftIndices()[k+1], 1);
+ }
+ }
+}
+
+
+void Slicer::evalStream(primStream* pStream)
+{
+ Int i,j,k;
+ k=0;
+/* TrimVertex X;*/
+ TrimVertex *trimVert =/*&X*/ (TrimVertex*)malloc(sizeof(TrimVertex));
+ trimVert -> nuid = 0;//???
+ Real* vertices = pStream->get_vertices(); //for efficiency
+ for(i=0; i<pStream->get_n_prims(); i++)
+ {
+
+ //ith primitive has #vertices = lengths[i], type=types[i]
+ switch(pStream->get_type(i)){
+ case PRIMITIVE_STREAM_FAN:
+
+ backend.bgntfan();
+
+ for(j=0; j<pStream->get_length(i); j++)
+ {
+ trimVert->param[0] = vertices[k];
+ trimVert->param[1] = vertices[k+1];
+ backend.tmeshvert(trimVert);
+
+// backend.tmeshvert(vertices[k], vertices[k+1]);
+ k += 2;
+ }
+ backend.endtfan();
+ break;
+
+ default:
+ fprintf(stderr, "evalStream: not implemented yet\n");
+ exit(1);
+
+ }
+ }
+ free(trimVert);
+}
+
+
+
+
+void Slicer::slice_new(Arc_ptr loop)
+{
+//count++;
+//if(count == 78) count=1;
+//printf("count=%i\n", count);
+//if( ! (4<= count && count <=4)) return;
+
+
+ Int num_ulines;
+ Int num_vlines;
+ Real uMin, uMax, vMin, vMax;
+ Real mydu, mydv;
+ uMin = uMax = loop->tail()[0];
+ vMin = vMax = loop->tail()[1];
+ mydu = (du>0)? du: -du;
+ mydv = (dv>0)? dv: -dv;
+
+ for(Arc_ptr jarc=loop->next; jarc != loop; jarc = jarc->next)
+ {
+
+ if(jarc->tail()[0] < uMin)
+ uMin = jarc->tail()[0];
+ if(jarc->tail()[0] > uMax)
+ uMax = jarc->tail()[0];
+ if(jarc->tail()[1] < vMin)
+ vMin = jarc->tail()[1];
+ if(jarc->tail()[1] > vMax)
+ vMax = jarc->tail()[1];
+ }
+
+ if (uMax == uMin)
+ return; // prevent divide-by-zero. Jon Perry. 17 June 2002
+
+ if(mydu > uMax - uMin)
+ num_ulines = 2;
+ else
+ {
+ num_ulines = 3 + (Int) ((uMax-uMin)/mydu);
+ }
+ if(mydv>=vMax-vMin)
+ num_vlines = 2;
+ else
+ {
+ num_vlines = 2+(Int)((vMax-vMin)/mydv);
+ }
+
+ Int isRect = is_rect(loop);
+
+ if(isRect && (num_ulines<=2 || num_vlines<=2))
+ {
+ if(vlinear)
+ triangulateRect(loop, backend, 1, ulinear, vlinear);
+ else if(ulinear)
+ triangulateRect(loop, backend, -1, ulinear, vlinear);
+ else
+ triangulateRect(loop, backend, 0, ulinear, vlinear);
+ }
+
+ else if(isRect)
+ {
+ triangulateRectGen(loop, num_ulines-2, num_vlines-2, backend);
+ }
+ else if( (num_ulines<=2 || num_vlines <=2) && ulinear)
+ {
+ monoTriangulationFunBackend(loop, compV2InY, &backend);
+ }
+ else if( (!ulinear) && (!vlinear) && (num_ulines == 2) && (num_vlines > 2))
+ {
+ monoTriangulationFunBackend(loop, compV2InY, &backend);
+ }
+ else
+ {
+ directedLine* poly = arcLoopToDLineLoop(loop);
+
+ gridWrap grid(num_ulines, num_vlines, uMin, uMax, vMin, vMax);
+ primStream pStream(20, 20);
+ rectBlockArray rbArray(20);
+
+ sampleMonoPoly(poly, &grid, ulinear, vlinear, &pStream, &rbArray);
+
+ evalStream(&pStream);
+
+ evalRBArray(&rbArray, &grid);
+
+#ifdef COUNT_TRIANGLES
+ num_triangles += pStream.num_triangles();
+ num_quads += rbArray.num_quads();
+#endif
+ poly->deleteSinglePolygonWithSline();
+ }
+
+#ifdef COUNT_TRIANGLES
+ printf("num_triangles=%i\n", num_triangles);
+ printf("num_quads = %i\n", num_quads);
+#endif
+}
+
+void Slicer::slice(Arc_ptr loop)
+{
+#ifdef USE_READ_FLAG
+ if(read_flag("flagFile"))
+ slice_new(loop);
+ else
+ slice_old(loop);
+
+#else
+ slice_new(loop);
+#endif
+
+}
+
+
+
+Slicer::Slicer( Backend &b )
+ : CoveAndTiler( b ), Mesher( b ), backend( b )
+{
+ ulinear = 0;
+ vlinear = 0;
+}
+
+Slicer::~Slicer()
+{
+}
+
+void
+Slicer::setisolines( int x )
+{
+ isolines = x;
+}
+
+void
+Slicer::setstriptessellation( REAL x, REAL y )
+{
+ assert(x > 0 && y > 0);
+ du = x;
+ dv = y;
+ setDu( du );
+}
+
+void
+Slicer::slice_old( Arc_ptr loop )
+{
+ loop->markverts();
+
+ Arc_ptr extrema[4];
+ loop->getextrema( extrema );
+
+ unsigned int npts = loop->numpts();
+ TrimRegion::init( npts, extrema[0] );
+
+ Mesher::init( npts );
+
+ long ulines = uarray.init( du, extrema[1], extrema[3] );
+//printf("ulines = %i\n", ulines);
+ Varray varray;
+ long vlines = varray.init( dv, extrema[0], extrema[2] );
+//printf("vlines = %i\n", vlines);
+ long botv = 0;
+ long topv;
+ TrimRegion::init( varray.varray[botv] );
+ getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
+
+ for( long quad=0; quad<varray.numquads; quad++ ) {
+ backend.surfgrid( uarray.uarray[0],
+ uarray.uarray[ulines-1],
+ ulines-1,
+ varray.vval[quad],
+ varray.vval[quad+1],
+ varray.voffset[quad+1] - varray.voffset[quad] );
+
+ for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
+ topv = botv++;
+ advance( topv - varray.voffset[quad],
+ botv - varray.voffset[quad],
+ varray.varray[botv] );
+ if( i == vlines )
+ getPts( extrema[2] );
+ else
+ getPts( backend );
+ getGridExtent();
+ if( isolines ) {
+ outline();
+ } else {
+ if( canTile() )
+ coveAndTile();
+ else
+ mesh();
+ }
+ }
+ }
+}
+
+
+void
+Slicer::outline( void )
+{
+ GridTrimVertex upper, lower;
+ Hull::init( );
+
+ backend.bgnoutline();
+ while( (nextupper( &upper )) ) {
+ if( upper.isGridVert() )
+ backend.linevert( upper.g );
+ else
+ backend.linevert( upper.t );
+ }
+ backend.endoutline();
+
+ backend.bgnoutline();
+ while( (nextlower( &lower )) ) {
+ if( lower.isGridVert() )
+ backend.linevert( lower.g );
+ else
+ backend.linevert( lower.t );
+ }
+ backend.endoutline();
+}
+
+
+void
+Slicer::outline( Arc_ptr jarc )
+{
+ jarc->markverts();
+
+ if( jarc->pwlArc->npts >= 2 ) {
+ backend.bgnoutline();
+ for( int j = jarc->pwlArc->npts-1; j >= 0; j-- )
+ backend.linevert( &(jarc->pwlArc->pts[j]) );
+ backend.endoutline();
+ }
+}
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/slicer.h b/mesalib/src/glu/sgi/libnurbs/internals/slicer.h
new file mode 100644
index 000000000..e1f5d22ff
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/slicer.h
@@ -0,0 +1,84 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * slicer.h
+ *
+ */
+
+#ifndef __gluslicer_h_
+#define __gluslicer_h_
+
+#include "trimregion.h"
+#include "mesher.h"
+#include "coveandtiler.h"
+#include "primitiveStream.h"
+#include "rectBlock.h"
+
+class Backend;
+class Arc;
+class TrimVertex;
+
+class Slicer : public CoveAndTiler, public Mesher {
+public:
+ Slicer( Backend & );
+ ~Slicer( void );
+ void slice( Arc_ptr );
+ void slice_old( Arc_ptr);
+ void slice_new( Arc_ptr );
+ void evalStream(primStream* );
+ void evalRBArray(rectBlockArray* rbArray, gridWrap* grid);
+
+ void outline( Arc_ptr );
+ void setstriptessellation( REAL, REAL );
+ void setisolines( int );
+
+ void set_ulinear(int ulinear_flag)
+ {
+ ulinear = ulinear_flag;
+ }
+ void set_vlinear(int vlinear_flag)
+ {
+ vlinear = vlinear_flag;
+ }
+private:
+ Backend& backend;
+ REAL oneOverDu;
+ REAL du, dv;
+ int isolines;
+
+ void outline( void );
+ void initGridlines( void );
+ void advanceGridlines( long );
+
+ int ulinear; //indicate whether uorder is 2 or not
+ int vlinear; //indicate whether vorder is 2 or not
+};
+#endif /* __gluslicer_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/sorter.cc b/mesalib/src/glu/sgi/libnurbs/internals/sorter.cc
new file mode 100644
index 000000000..7a7994149
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/sorter.cc
@@ -0,0 +1,139 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * sorter.c++
+ *
+ */
+
+#include "glimports.h"
+#include "sorter.h"
+#include "mystdio.h"
+
+Sorter::Sorter( int _es )
+{
+ es = _es;
+}
+
+void
+Sorter::qsort( void *a, int n )
+{
+ qs1( (char *)a, ((char *)a)+n*es);
+}
+
+int
+Sorter::qscmp( char *, char * )
+{
+ _glu_dprintf( "Sorter::qscmp: pure virtual called\n" );
+ return 0;
+}
+
+
+void
+Sorter::qsexc( char *, char * )
+{
+ _glu_dprintf( "Sorter::qsexc: pure virtual called\n" );
+}
+
+
+void
+Sorter::qstexc( char *, char *, char * )
+{
+ _glu_dprintf( "Sorter::qstexc: pure virtual called\n" );
+}
+
+void
+Sorter::qs1( char *a, char *l )
+{
+ char *i, *j;
+ char *lp, *hp;
+ int c;
+ unsigned int n;
+
+start:
+ if((n=l-a) <= (unsigned int)es)
+ return;
+ n = es * (n / (2*es));
+ hp = lp = a+n;
+ i = a;
+ j = l-es;
+ while(1) {
+ if(i < lp) {
+ if((c = qscmp(i, lp)) == 0) {
+ qsexc(i, lp -= es);
+ continue;
+ }
+ if(c < 0) {
+ i += es;
+ continue;
+ }
+ }
+
+loop:
+ if(j > hp) {
+ if((c = qscmp(hp, j)) == 0) {
+ qsexc(hp += es, j);
+ goto loop;
+ }
+ if(c > 0) {
+ if(i == lp) {
+ qstexc(i, hp += es, j);
+ i = lp += es;
+ goto loop;
+ }
+ qsexc(i, j);
+ j -= es;
+ i += es;
+ continue;
+ }
+ j -= es;
+ goto loop;
+ }
+
+ if(i == lp) {
+ if(lp-a >= l-hp) {
+ qs1(hp+es, l);
+ l = lp;
+ } else {
+ qs1(a, lp);
+ a = hp+es;
+ }
+ goto start;
+ }
+
+ qstexc(j, lp -= es, i);
+ j = hp -= es;
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/sorter.h b/mesalib/src/glu/sgi/libnurbs/internals/sorter.h
new file mode 100644
index 000000000..57ea12129
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/sorter.h
@@ -0,0 +1,51 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef __glusorter_h_
+#define __glusorter_h_
+
+class Sorter {
+public:
+ Sorter( int es );
+ virtual ~Sorter() { /* silence warning*/ }
+ void qsort( void *a, int n );
+
+protected:
+ virtual int qscmp( char *, char * );
+ virtual void qsexc( char *i, char *j ); // i<-j, j<-i
+ virtual void qstexc( char *i, char *j, char *k ); // i<-k, k<-j, j<-i
+
+private:
+ void qs1( char *, char * );
+ int es;
+};
+#endif /* __glusorter_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/splitarcs.cc b/mesalib/src/glu/sgi/libnurbs/internals/splitarcs.cc
new file mode 100644
index 000000000..1f79d543f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/splitarcs.cc
@@ -0,0 +1,293 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * splitarcs.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mysetjmp.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arcsorter.h"
+#include "arc.h"
+#include "bin.h"
+
+/* local preprocessor definitions */
+#define MAXARCS 10
+
+/*----------------------------------------------------------------------------
+ * Subdivider::split - split trim regions in source bin by line (param == value).
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::split( Bin& bin, Bin& left, Bin& right, int param, REAL value )
+{
+ Bin intersections, unknown;
+
+ partition( bin, left, intersections, right, unknown, param, value );
+
+ int count = intersections.numarcs();
+ if( count % 2 ) {
+#ifndef NDEBUG
+ left.show( "left" );
+ intersections.show( "intersections" );
+ right.show( "right" );
+#endif
+ ::mylongjmp( jumpbuffer, 29 );
+ }
+
+ Arc_ptr arclist[MAXARCS], *list;
+ if( count >= MAXARCS ) {
+ list = new Arc_ptr[count];
+ } else {
+ list = arclist;
+ }
+
+ Arc_ptr jarc, *last, *lptr;
+ for( last = list; (jarc=intersections.removearc()) != NULL; last++ )
+ *last = jarc;
+
+ if( param == 0 ) { /* sort into increasing t order */
+ ArcSdirSorter sorter(*this);
+ sorter.qsort( list, count );
+
+ //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_s);
+ for( lptr=list; lptr<last; lptr+=2 )
+ check_s ( lptr[0], lptr[1] );
+ for( lptr=list; lptr<last; lptr+=2 )
+ join_s ( left, right, lptr[0], lptr[1] );
+ for( lptr=list; lptr != last; lptr++ ) {
+ if( ((*lptr)->head()[0] <= value) && ((*lptr)->tail()[0] <= value) )
+ left.addarc( *lptr );
+ else
+ right.addarc( *lptr );
+ }
+ } else { /* sort into decreasing s order */
+ ArcTdirSorter sorter(*this);
+ sorter.qsort( list, count );
+ //::qsort ((void *)list, count, sizeof(Arc_ptr), (cmpfunc)compare_t);
+ for( lptr=list; lptr<last; lptr+=2 )
+ check_t ( lptr[0], lptr[1] );
+ for( lptr=list; lptr<last; lptr+=2 )
+ join_t ( left, right, lptr[0], lptr[1] );
+ for( lptr=list; lptr != last; lptr++ ) {
+ if( ((*lptr)->head()[1] <= value) && ((*lptr)->tail()[1] <= value) )
+ left.addarc( *lptr );
+ else
+ right.addarc( *lptr );
+ }
+ }
+
+ if( list != arclist ) delete[] list;
+ unknown.adopt();
+}
+
+
+void
+Subdivider::check_s( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ /* XXX - if these assertions fail, it is due to user error or
+ undersampling */
+ if( ! ( jarc1->tail()[0] < (jarc1)->head()[0] ) ) {
+#ifndef NDEBUG
+ _glu_dprintf( "s difference %f\n", (jarc1)->tail()[0] - (jarc1)->head()[0] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+
+ if( ! ( jarc2->tail()[0] > (jarc2)->head()[0] ) ) {
+#ifndef NDEBUG
+ _glu_dprintf( "s difference %f\n", (jarc2)->tail()[0] - (jarc2)->head()[0] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+}
+
+inline void
+Subdivider::link( Arc_ptr jarc1, Arc_ptr jarc2, Arc_ptr up, Arc_ptr down )
+{
+ up->nuid = down->nuid = 0; // XXX
+
+ up->next = jarc2;
+ down->next = jarc1;
+ up->prev = jarc1->prev;
+ down->prev = jarc2->prev;
+
+ down->next->prev = down;
+ up->next->prev = up;
+ down->prev->next = down;
+ up->prev->next = up;
+}
+
+inline void
+Subdivider::simple_link( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ Arc_ptr tmp = jarc2->prev;
+ jarc2->prev = jarc1->prev;
+ jarc1->prev = tmp;
+ jarc2->prev->next = jarc2;
+ jarc1->prev->next = jarc1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * join - add a pair of oppositely directed jordan arcs between two arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::join_s( Bin& left, Bin& right, Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0);
+ assert( jarc2->check( ) != 0);
+ assert( jarc1 != jarc2 );
+
+ if( ! jarc1->getitail() )
+ jarc1 = jarc1->next;
+
+ if( ! jarc2->getitail() )
+ jarc2 = jarc2->next;
+
+ REAL s = jarc1->tail()[0];
+ REAL t1 = jarc1->tail()[1];
+ REAL t2 = jarc2->tail()[1];
+
+ if( t1 == t2 ) {
+ simple_link( jarc1, jarc2 );
+ } else {
+ Arc_ptr newright = new(arcpool) Arc( arc_right, 0 );
+ Arc_ptr newleft = new(arcpool) Arc( arc_left, 0 );
+ assert( t1 < t2 );
+ if( isBezierArcType() ) {
+ arctessellator.bezier( newright, s, s, t1, t2 );
+ arctessellator.bezier( newleft, s, s, t2, t1 );
+ } else {
+ arctessellator.pwl_right( newright, s, t1, t2, stepsizes[0] );
+ arctessellator.pwl_left( newleft, s, t2, t1, stepsizes[2] );
+ }
+ link( jarc1, jarc2, newright, newleft );
+ left.addarc( newright );
+ right.addarc( newleft );
+ }
+
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0);
+ assert( jarc2->next->check( ) != 0);
+}
+
+void
+Subdivider::check_t( Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ /* XXX - if these assertions fail, it is due to user error or
+ undersampling */
+ if( ! ( jarc1->tail()[1] < (jarc1)->head()[1] ) ) {
+#ifndef NDEBUG
+ _glu_dprintf( "t difference %f\n", jarc1->tail()[1] - (jarc1)->head()[1] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+
+ if( ! ( jarc2->tail()[1] > (jarc2)->head()[1] ) ) {
+#ifndef NDEBUG
+ _glu_dprintf( "t difference %f\n", jarc2->tail()[1] - (jarc2)->head()[1] );
+#endif
+ ::mylongjmp( jumpbuffer, 28 );
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * join_t - add a pair of oppositely directed jordan arcs between two arcs
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::join_t( Bin& bottom, Bin& top, Arc_ptr jarc1, Arc_ptr jarc2 )
+{
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+ assert( jarc1 != jarc2 );
+
+ if( ! jarc1->getitail() )
+ jarc1 = jarc1->next;
+
+ if( ! jarc2->getitail() )
+ jarc2 = jarc2->next;
+
+ REAL s1 = jarc1->tail()[0];
+ REAL s2 = jarc2->tail()[0];
+ REAL t = jarc1->tail()[1];
+
+ if( s1 == s2 ) {
+ simple_link( jarc1, jarc2 );
+ } else {
+ Arc_ptr newtop = new(arcpool) Arc( arc_top, 0 );
+ Arc_ptr newbot = new(arcpool) Arc( arc_bottom, 0 );
+ assert( s1 > s2 );
+ if( isBezierArcType() ) {
+ arctessellator.bezier( newtop, s1, s2, t, t );
+ arctessellator.bezier( newbot, s2, s1, t, t );
+ } else {
+ arctessellator.pwl_top( newtop, t, s1, s2, stepsizes[1] );
+ arctessellator.pwl_bottom( newbot, t, s2, s1, stepsizes[3] );
+ }
+ link( jarc1, jarc2, newtop, newbot );
+ bottom.addarc( newtop );
+ top.addarc( newbot );
+ }
+
+ assert( jarc1->check( ) != 0 );
+ assert( jarc2->check( ) != 0 );
+ assert( jarc1->next->check( ) != 0 );
+ assert( jarc2->next->check( ) != 0 );
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/subdivider.cc b/mesalib/src/glu/sgi/libnurbs/internals/subdivider.cc
new file mode 100644
index 000000000..cc0b51470
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/subdivider.cc
@@ -0,0 +1,910 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * subdivider.cxx
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "subdivider.h"
+#include "arc.h"
+#include "bezierarc.h"
+#include "bin.h"
+#include "renderhints.h"
+#include "backend.h"
+#include "mapdesc.h"
+#include "quilt.h"
+#include "patchlist.h"
+#include "patch.h"
+#include "nurbsconsts.h"
+#include "trimvertpool.h"
+#include "simplemath.h"
+
+#include "polyUtil.h" //for function area()
+
+//#define PARTITION_TEST
+#ifdef PARTITION_TEST
+#include "partitionY.h"
+#include "monoTriangulation.h"
+#include "dataTransform.h"
+#include "monoChain.h"
+
+#endif
+
+
+#define OPTIMIZE_UNTRIMED_CASE
+
+
+Bin*
+Subdivider::makePatchBoundary( const REAL *from, const REAL *to )
+{
+ Bin* ret = new Bin();
+ REAL smin = from[0];
+ REAL smax = to[0];
+ REAL tmin = from[1];
+ REAL tmax = to[1];
+
+ pjarc = 0;
+
+ Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
+ arctessellator.bezier( jarc, smin, smax, tmin, tmin );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_right, 0 );
+ arctessellator.bezier( jarc, smax, smax, tmin, tmax );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_top, 0 );
+ arctessellator.bezier( jarc, smax, smin, tmax, tmax );
+ ret->addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_left, 0 );
+ arctessellator.bezier( jarc, smin, smin, tmax, tmin );
+ ret->addarc( jarc );
+ jarc->append( pjarc );
+
+ assert( jarc->check() != 0 );
+ return ret;
+}
+
+/*---------------------------------------------------------------------------
+ * Subdivider - construct a subdivider
+ *---------------------------------------------------------------------------
+ */
+
+Subdivider::Subdivider( Renderhints& r, Backend& b )
+ : slicer( b ),
+ arctessellator( trimvertexpool, pwlarcpool ),
+ arcpool( sizeof( Arc), 1, "arcpool" ),
+ bezierarcpool( sizeof( BezierArc ), 1, "Bezarcpool" ),
+ pwlarcpool( sizeof( PwlArc ), 1, "Pwlarcpool" ),
+ renderhints( r ),
+ backend( b )
+{
+}
+
+void
+Subdivider::setJumpbuffer( JumpBuffer *j )
+{
+ jumpbuffer = j;
+}
+
+/*---------------------------------------------------------------------------
+ * clear - reset all state after possible error condition
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::clear( void )
+{
+ trimvertexpool.clear();
+ arcpool.clear();
+ pwlarcpool.clear();
+ bezierarcpool.clear();
+}
+
+/*---------------------------------------------------------------------------
+ * ~Subdivider - destroy a subdivider
+ *---------------------------------------------------------------------------
+ */
+
+Subdivider::~Subdivider( void )
+{
+}
+
+/*---------------------------------------------------------------------------
+ * addArc - add a bezier arc to a trim loop and to a bin
+ *---------------------------------------------------------------------------
+ */
+void
+Subdivider::addArc( REAL *cpts, Quilt *quilt, long _nuid )
+{
+ BezierArc *bezierArc = new(bezierarcpool) BezierArc;
+ Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
+ jarc->pwlArc = 0;
+ jarc->bezierArc = bezierArc;
+ bezierArc->order = quilt->qspec->order;
+ bezierArc->stride = quilt->qspec->stride;
+ bezierArc->mapdesc = quilt->mapdesc;
+ bezierArc->cpts = cpts;
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+}
+
+/*---------------------------------------------------------------------------
+ * addArc - add a pwl arc to a trim loop and to a bin
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::addArc( int npts, TrimVertex *pts, long _nuid )
+{
+ Arc *jarc = new(arcpool) Arc( arc_none, _nuid );
+ jarc->pwlArc = new(pwlarcpool) PwlArc( npts, pts );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+}
+
+void
+Subdivider::beginQuilts( void )
+{
+ qlist = 0;
+}
+
+void
+Subdivider::addQuilt( Quilt *quilt )
+{
+ quilt->next = qlist;
+ qlist = quilt;
+}
+
+/*---------------------------------------------------------------------------
+ * drawSurfaces - main entry point for surface tessellation
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::drawSurfaces( long nuid )
+{
+ renderhints.init( );
+
+ if (qlist == NULL)
+ {
+ //initialbin could be nonempty due to some errors
+ freejarcs(initialbin);
+ return;
+ }
+
+ for( Quilt *q = qlist; q; q = q->next ) {
+ if( q->isCulled( ) == CULL_TRIVIAL_REJECT ) {
+ freejarcs( initialbin );
+ return;
+ }
+ }
+
+
+ REAL from[2], to[2];
+ qlist->getRange( from, to, spbrkpts, tpbrkpts );
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ //perform optimization only when the samplng method is
+ //DOMAIN_DISTANCE and the display methdo is either
+ //fill or outline_polygon.
+ int optimize = (is_domain_distance_sampling && (renderhints.display_method != N_OUTLINE_PATCH));
+#endif
+
+ if( ! initialbin.isnonempty() ) {
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ if(! optimize )
+ {
+
+ makeBorderTrim( from, to );
+ }
+#else
+ makeBorderTrim( from, to );
+#endif
+ } else {
+ REAL rate[2];
+ qlist->findRates( spbrkpts, tpbrkpts, rate );
+
+ if( decompose( initialbin, min(rate[0], rate[1]) ) )
+ mylongjmp( jumpbuffer, 31 );
+ }
+
+ backend.bgnsurf( renderhints.wiretris, renderhints.wirequads, nuid );
+
+#ifdef PARTITION_TEST
+ if( initialbin.isnonempty() && spbrkpts.end-2 == spbrkpts.start &&
+ tpbrkpts.end-2 == tpbrkpts.start)
+{
+ for(int i=spbrkpts.start; i<spbrkpts.end-1; i++){
+ for(int j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
+ Real pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[i];
+ ptb[0] = spbrkpts.pts[i+1];
+ pta[1] = tpbrkpts.pts[j];
+ ptb[1] = tpbrkpts.pts[j+1];
+ qlist->downloadAll(pta, ptb, backend);
+
+ directedLine *poly;
+
+ {
+
+ poly = bin_to_DLineLoops(initialbin);
+
+ poly=poly->deleteDegenerateLinesAllPolygons();
+
+ sampledLine* retSampledLines;
+//printf("before MC_partition\n");
+ poly = MC_partitionY(poly, &retSampledLines);
+//printf("after MC_partition\n");
+
+ }
+
+
+ {
+ primStream pStream(5000,5000);
+ directedLine* temp;
+
+ for(temp=poly; temp != NULL; temp=temp->getNextPolygon())
+
+ monoTriangulation(temp, &pStream);
+
+ slicer.evalStream(&pStream);
+
+ }
+ //need to clean up space
+ }
+ }
+ freejarcs( initialbin );
+ backend.endsurf();
+ return;
+
+ /*
+ printf("num_polygons=%i\n", poly->numPolygons());
+ printf("num_edges=%i\n", poly->numEdgesAllPolygons());
+ poly->writeAllPolygons("zloutputFile");
+ return;
+ {
+ primStream pStream(20,20);
+ for(directedLine* tempD = poly; tempD != NULL; tempD = tempD->getNextPolygon())
+ monoTriangulation(tempD, &pStream);
+ }
+ return;
+ */
+}
+#endif //PARTITION_TEST
+
+
+#ifdef OPTIMIZE_UNTRIMED_CASE
+ if( (!initialbin.isnonempty()) && optimize )
+ {
+ int i,j;
+ int num_u_steps;
+ int num_v_steps;
+ for(i=spbrkpts.start; i<spbrkpts.end-1; i++){
+ for(j=tpbrkpts.start; j<tpbrkpts.end-1; j++){
+ Real pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[i];
+ ptb[0] = spbrkpts.pts[i+1];
+ pta[1] = tpbrkpts.pts[j];
+ ptb[1] = tpbrkpts.pts[j+1];
+ qlist->downloadAll(pta, ptb, backend);
+
+ num_u_steps = (int) (domain_distance_u_rate * (ptb[0]-pta[0]));
+ num_v_steps = (int) (domain_distance_v_rate * (ptb[1]-pta[1]));
+
+ if(num_u_steps <= 0) num_u_steps = 1;
+ if(num_v_steps <= 0) num_v_steps = 1;
+
+ backend.surfgrid(pta[0], ptb[0], num_u_steps,
+ ptb[1], pta[1], num_v_steps);
+ backend.surfmesh(0,0,num_u_steps,num_v_steps);
+
+
+
+ continue;
+ /* the following is left for reference purpose, don't delete
+ {
+ Bin* tempSource;
+ Patchlist patchlist(qlist, pta, ptb);
+ patchlist.getstepsize();
+
+ tempSource=makePatchBoundary(pta, ptb);
+
+ tessellation(*tempSource, patchlist);
+
+ render(*tempSource);
+ delete tempSource;
+ }
+ */
+ }
+ }
+ }
+ else
+ subdivideInS( initialbin );
+#else
+
+ subdivideInS( initialbin );
+#endif
+
+ backend.endsurf();
+
+}
+
+void
+Subdivider::subdivideInS( Bin& source )
+{
+ if( renderhints.display_method == N_OUTLINE_PARAM ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ splitInS( source, spbrkpts.start, spbrkpts.end );
+ }
+}
+
+
+/*---------------------------------------------------------------------------
+ * splitInS - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::splitInS( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 0, spbrkpts.pts[i] );
+ splitInS( left, start, i );
+ splitInS( right, i+1, end );
+ } else {
+ if( start == spbrkpts.start || start == spbrkpts.end ) {
+ freejarcs( source );
+ } else if( renderhints.display_method == N_OUTLINE_PARAM_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypeBezier();
+ setNonDegenerate();
+ s_index = start;
+ splitInT( source, tpbrkpts.start, tpbrkpts.end );
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * splitInT - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::splitInT( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 1, tpbrkpts.pts[i] );
+ splitInT( left, start, i );
+ splitInT( right, i+1, end );
+ } else {
+ if( start == tpbrkpts.start || start == tpbrkpts.end ) {
+ freejarcs( source );
+ } else if( renderhints.display_method == N_OUTLINE_PARAM_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ t_index = start;
+ setArcTypeBezier();
+ setDegenerate();
+
+ REAL pta[2], ptb[2];
+ pta[0] = spbrkpts.pts[s_index-1];
+ pta[1] = tpbrkpts.pts[t_index-1];
+
+ ptb[0] = spbrkpts.pts[s_index];
+ ptb[1] = tpbrkpts.pts[t_index];
+ qlist->downloadAll( pta, ptb, backend );
+
+ Patchlist patchlist( qlist, pta, ptb );
+/*
+printf("-------samplingSplit-----\n");
+source.show("samplingSplit source");
+*/
+ samplingSplit( source, patchlist, renderhints.maxsubdivisions, 0 );
+ setNonDegenerate();
+ setArcTypeBezier();
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * samplingSplit - recursively subdivide patch, cull check each subpatch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::samplingSplit(
+ Bin& source,
+ Patchlist& patchlist,
+ int subdivisions,
+ int param )
+{
+ if( ! source.isnonempty() ) return;
+
+ if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT ) {
+ freejarcs( source );
+ return;
+ }
+
+ patchlist.getstepsize();
+
+ if( renderhints.display_method == N_OUTLINE_PATCH ) {
+ tessellation( source, patchlist );
+ outline( source );
+ freejarcs( source );
+ return;
+ }
+
+ //patchlist.clamp();
+
+ tessellation( source, patchlist );
+
+ if( patchlist.needsSamplingSubdivision() && (subdivisions > 0) ) {
+ if( ! patchlist.needsSubdivision( 0 ) )
+ param = 1;
+ else if( ! patchlist.needsSubdivision( 1 ) )
+ param = 0;
+ else
+ param = 1 - param;
+
+ Bin left, right;
+ REAL mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist( patchlist, param, mid );
+ samplingSplit( left, subpatchlist, subdivisions-1, param );
+ samplingSplit( right, patchlist, subdivisions-1, param );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ nonSamplingSplit( source, patchlist, subdivisions, param );
+ setDegenerate();
+ setArcTypeBezier();
+ }
+}
+
+void
+Subdivider::nonSamplingSplit(
+ Bin& source,
+ Patchlist& patchlist,
+ int subdivisions,
+ int param )
+{
+ if( patchlist.needsNonSamplingSubdivision() && (subdivisions > 0) ) {
+ param = 1 - param;
+
+ Bin left, right;
+ REAL mid = ( patchlist.pspec[param].range[0] +
+ patchlist.pspec[param].range[1] ) * 0.5;
+ split( source, left, right, param, mid );
+ Patchlist subpatchlist( patchlist, param, mid );
+ if( left.isnonempty() )
+ if( subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT )
+ freejarcs( left );
+ else
+ nonSamplingSplit( left, subpatchlist, subdivisions-1, param );
+ if( right.isnonempty() )
+ if( patchlist.cullCheck() == CULL_TRIVIAL_REJECT )
+ freejarcs( right );
+ else
+ nonSamplingSplit( right, patchlist, subdivisions-1, param );
+
+ } else {
+ // make bbox calls
+ patchlist.bbox();
+ backend.patch( patchlist.pspec[0].range[0], patchlist.pspec[0].range[1],
+ patchlist.pspec[1].range[0], patchlist.pspec[1].range[1] );
+
+ if( renderhints.display_method == N_OUTLINE_SUBDIV ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularS( source );
+ monosplitInS( source, smbrkpts.start, smbrkpts.end );
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * tessellation - set tessellation of interior and boundary of patch
+ *--------------------------------------------------------------------------
+ */
+
+void
+Subdivider::tessellation( Bin& bin, Patchlist &patchlist )
+{
+ // tessellate unsampled trim curves
+ tessellate( bin, patchlist.pspec[1].sidestep[1], patchlist.pspec[0].sidestep[1],
+ patchlist.pspec[1].sidestep[0], patchlist.pspec[0].sidestep[0] );
+
+ // set interior sampling rates
+ slicer.setstriptessellation( patchlist.pspec[0].stepsize, patchlist.pspec[1].stepsize );
+
+ //added by zl: set the order which will be used in slicer.c++
+ slicer.set_ulinear( (patchlist.get_uorder() == 2));
+ slicer.set_vlinear( (patchlist.get_vorder() == 2));
+
+ // set boundary sampling rates
+ stepsizes[0] = patchlist.pspec[1].stepsize;
+ stepsizes[1] = patchlist.pspec[0].stepsize;
+ stepsizes[2] = patchlist.pspec[1].stepsize;
+ stepsizes[3] = patchlist.pspec[0].stepsize;
+}
+
+/*---------------------------------------------------------------------------
+ * monosplitInS - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::monosplitInS( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 0, smbrkpts.pts[i] );
+ monosplitInS( left, start, i );
+ monosplitInS( right, i+1, end );
+ } else {
+ if( renderhints.display_method == N_OUTLINE_SUBDIV_S ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+ setArcTypePwl();
+ setDegenerate();
+ findIrregularT( source );
+ monosplitInT( source, tmbrkpts.start, tmbrkpts.end );
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * monosplitInT - split a patch and a bin by an isoparametric line
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::monosplitInT( Bin& source, int start, int end )
+{
+ if( source.isnonempty() ) {
+ if( start != end ) {
+ int i = start + (end - start) / 2;
+ Bin left, right;
+ split( source, left, right, 1, tmbrkpts.pts[i] );
+ monosplitInT( left, start, i );
+ monosplitInT( right, i+1, end );
+ } else {
+ if( renderhints.display_method == N_OUTLINE_SUBDIV_ST ) {
+ outline( source );
+ freejarcs( source );
+ } else {
+/*
+printf("*******render\n");
+source.show("source\n");
+*/
+ render( source );
+ freejarcs( source );
+ }
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * findIrregularS - determine points of non-monotonicity is s direction
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::findIrregularS( Bin& bin )
+{
+ assert( bin.firstarc()->check() != 0 );
+
+ smbrkpts.grow( bin.numarcs() );
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ REAL *a = jarc->prev->tail();
+ REAL *b = jarc->tail();
+ REAL *c = jarc->head();
+
+ if( b[1] == a[1] && b[1] == c[1] ) continue;
+
+ //corrected code
+ if((b[1]<=a[1] && b[1] <= c[1]) ||
+ (b[1]>=a[1] && b[1] >= c[1]))
+ {
+ //each arc (jarc, jarc->prev, jarc->next) is a
+ //monotone arc consisting of multiple line segements.
+ //it may happen that jarc->prev and jarc->next are the same,
+ //that is, jarc->prev and jarc form a closed loop.
+ //In such case, a and c will be the same.
+ if(a[0]==c[0] && a[1] == c[1])
+ {
+ if(jarc->pwlArc->npts >2)
+ {
+ c = jarc->pwlArc->pts[jarc->pwlArc->npts-2].param;
+ }
+ else
+ {
+ assert(jarc->prev->pwlArc->npts>2);
+ a = jarc->prev->pwlArc->pts[jarc->prev->pwlArc->npts-2].param;
+ }
+
+ }
+ if(area(a,b,c) < 0)
+ {
+ smbrkpts.add(b[0]);
+ }
+
+ }
+
+ /* old code,
+ if( b[1] <= a[1] && b[1] <= c[1] ) {
+ if( ! ccwTurn_tr( jarc->prev, jarc ) )
+ smbrkpts.add( b[0] );
+ } else if( b[1] >= a[1] && b[1] >= c[1] ) {
+ if( ! ccwTurn_tl( jarc->prev, jarc ) )
+ smbrkpts.add( b[0] );
+ }
+ */
+
+ }
+
+ smbrkpts.filter();
+}
+
+/*----------------------------------------------------------------------------
+ * findIrregularT - determine points of non-monotonicity in t direction
+ * where one arc is parallel to the s axis.
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::findIrregularT( Bin& bin )
+{
+ assert( bin.firstarc()->check() != 0 );
+
+ tmbrkpts.grow( bin.numarcs() );
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ REAL *a = jarc->prev->tail();
+ REAL *b = jarc->tail();
+ REAL *c = jarc->head();
+
+ if( b[0] == a[0] && b[0] == c[0] ) continue;
+
+ if( b[0] <= a[0] && b[0] <= c[0] ) {
+ if( a[1] != b[1] && b[1] != c[1] ) continue;
+ if( ! ccwTurn_sr( jarc->prev, jarc ) )
+ tmbrkpts.add( b[1] );
+ } else if ( b[0] >= a[0] && b[0] >= c[0] ) {
+ if( a[1] != b[1] && b[1] != c[1] ) continue;
+ if( ! ccwTurn_sl( jarc->prev, jarc ) )
+ tmbrkpts.add( b[1] );
+ }
+ }
+ tmbrkpts.filter( );
+}
+
+/*-----------------------------------------------------------------------------
+ * makeBorderTrim - if no user input trimming data then create
+ * a trimming curve around the boundaries of the Quilt. The curve consists of
+ * four Jordan arcs, one for each side of the Quilt, connected, of course,
+ * head to tail.
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::makeBorderTrim( const REAL *from, const REAL *to )
+{
+ REAL smin = from[0];
+ REAL smax = to[0];
+ REAL tmin = from[1];
+ REAL tmax = to[1];
+
+ pjarc = 0;
+
+ Arc_ptr jarc = new(arcpool) Arc( arc_bottom, 0 );
+ arctessellator.bezier( jarc, smin, smax, tmin, tmin );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_right, 0 );
+ arctessellator.bezier( jarc, smax, smax, tmin, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_top, 0 );
+ arctessellator.bezier( jarc, smax, smin, tmax, tmax );
+ initialbin.addarc( jarc );
+ pjarc = jarc->append( pjarc );
+
+ jarc = new(arcpool) Arc( arc_left, 0 );
+ arctessellator.bezier( jarc, smin, smin, tmax, tmin );
+ initialbin.addarc( jarc );
+ jarc->append( pjarc );
+
+ assert( jarc->check() != 0 );
+}
+
+/*----------------------------------------------------------------------------
+ * render - renders all monotone regions in a bin and frees the bin
+ *----------------------------------------------------------------------------
+ */
+
+void
+Subdivider::render( Bin& bin )
+{
+ bin.markall();
+
+#ifdef N_ISOLINE_S
+ slicer.setisolines( ( renderhints.display_method == N_ISOLINE_S ) ? 1 : 0 );
+#else
+ slicer.setisolines( 0 );
+#endif
+
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->ismarked() ) {
+ assert( jarc->check( ) != 0 );
+ Arc_ptr jarchead = jarc;
+ do {
+ jarc->clearmark();
+ jarc = jarc->next;
+ } while (jarc != jarchead);
+ slicer.slice( jarc );
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * outline - render the trimmed patch by outlining the boundary
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::outline( Bin& bin )
+{
+ bin.markall();
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->ismarked() ) {
+ assert( jarc->check( ) != 0 );
+ Arc_ptr jarchead = jarc;
+ do {
+ slicer.outline( jarc );
+ jarc->clearmark();
+ jarc = jarc->prev;
+ } while (jarc != jarchead);
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ * freejarcs - free all arcs in a bin
+ *---------------------------------------------------------------------------
+ */
+
+void
+Subdivider::freejarcs( Bin& bin )
+{
+ bin.adopt(); /* XXX - should not be necessary */
+
+ Arc_ptr jarc;
+ while( (jarc = bin.removearc()) != NULL ) {
+ if( jarc->pwlArc ) jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+ if( jarc->bezierArc) jarc->bezierArc->deleteMe( bezierarcpool ); jarc->bezierArc = 0;
+ jarc->deleteMe( arcpool );
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * tessellate - tessellate all Bezier arcs in a bin
+ * 1) only accepts linear Bezier arcs as input
+ * 2) the Bezier arcs are stored in the pwlArc structure
+ * 3) only vertical or horizontal lines work
+ * -- should
+ * 1) represent Bezier arcs in BezierArc structure
+ * (this requires a multitude of changes to the code)
+ * 2) accept high degree Bezier arcs (hard)
+ * 3) map the curve onto the surface to determine tessellation
+ * 4) work for curves of arbitrary geometry
+ *----------------------------------------------------------------------------
+ */
+
+
+void
+Subdivider::tessellate( Bin& bin, REAL rrate, REAL trate, REAL lrate, REAL brate )
+{
+ for( Arc_ptr jarc=bin.firstarc(); jarc; jarc=bin.nextarc() ) {
+ if( jarc->isbezier( ) ) {
+ assert( jarc->pwlArc->npts == 2 );
+ TrimVertex *pts = jarc->pwlArc->pts;
+ REAL s1 = pts[0].param[0];
+ REAL t1 = pts[0].param[1];
+ REAL s2 = pts[1].param[0];
+ REAL t2 = pts[1].param[1];
+
+ jarc->pwlArc->deleteMe( pwlarcpool ); jarc->pwlArc = 0;
+
+ switch( jarc->getside() ) {
+ case arc_left:
+ assert( s1 == s2 );
+ arctessellator.pwl_left( jarc, s1, t1, t2, lrate );
+ break;
+ case arc_right:
+ assert( s1 == s2 );
+ arctessellator.pwl_right( jarc, s1, t1, t2, rrate );
+ break;
+ case arc_top:
+ assert( t1 == t2 );
+ arctessellator.pwl_top( jarc, t1, s1, s2, trate );
+ break;
+ case arc_bottom:
+ assert( t1 == t2 );
+ arctessellator.pwl_bottom( jarc, t1, s1, s2, brate );
+ break;
+ case arc_none:
+ (void) abort();
+ break;
+ }
+ assert( ! jarc->isbezier() );
+ assert( jarc->check() != 0 );
+ }
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/subdivider.h b/mesalib/src/glu/sgi/libnurbs/internals/subdivider.h
new file mode 100644
index 000000000..4d5395181
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/subdivider.h
@@ -0,0 +1,200 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * subdivider.h
+ *
+ */
+
+#ifndef __glusubdivider_h_
+#define __glusubdivider_h_
+
+#include "mysetjmp.h"
+#include "bin.h"
+#include "flist.h"
+#include "slicer.h"
+#include "arctess.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+
+class Arc;
+class Pool;
+class Renderhints;
+class Quilt;
+class Patchlist;
+class Curvelist;
+struct JumpBuffer;
+
+class Subdivider {
+public:
+ Subdivider( Renderhints&, Backend& );
+ ~Subdivider( void );
+ void clear( void );
+
+ void beginTrims( void ) {}
+ void beginLoop( void );
+ void addArc( REAL *, Quilt *, long );
+ void addArc( int, TrimVertex *, long );
+ void endLoop( void ) {}
+ void endTrims( void ) {}
+
+ void beginQuilts( void );
+ void addQuilt( Quilt * );
+ void endQuilts( void ) {}
+
+ void drawCurves( void );
+ void drawSurfaces( long );
+
+ int ccwTurn_sl( Arc_ptr, Arc_ptr );
+ int ccwTurn_sr( Arc_ptr , Arc_ptr );
+ int ccwTurn_tl( Arc_ptr , Arc_ptr );
+ int ccwTurn_tr( Arc_ptr , Arc_ptr );
+
+ void setJumpbuffer( JumpBuffer * );
+
+ void set_domain_distance_u_rate(REAL u_rate)
+ {
+ domain_distance_u_rate = u_rate;
+ }
+ void set_domain_distance_v_rate(REAL v_rate)
+ {
+ domain_distance_v_rate = v_rate;
+ }
+ void set_is_domain_distance_sampling(int flag)
+ {
+ is_domain_distance_sampling = flag;
+ }
+
+private:
+ void classify_headonleft_s( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonleft_s( Bin &, Bin &, Bin &, REAL );
+ void classify_headonright_s( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonright_s( Bin &, Bin &, Bin &, REAL );
+ void classify_headonleft_t( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonleft_t( Bin &, Bin &, Bin &, REAL );
+ void classify_headonright_t( Bin &, Bin &, Bin &, REAL );
+ void classify_tailonright_t( Bin &, Bin &, Bin &, REAL );
+
+ enum dir { down, same, up, none };
+ void tessellate( Arc_ptr, REAL );
+ void monotonize( Arc_ptr , Bin & );
+ int isMonotone( Arc_ptr );
+ int decompose( Bin &, REAL );
+
+
+ Slicer slicer;
+ ArcTessellator arctessellator;
+ Pool arcpool;
+ Pool bezierarcpool;
+ Pool pwlarcpool;
+ TrimVertexPool trimvertexpool;
+
+ JumpBuffer* jumpbuffer;
+ Renderhints& renderhints;
+ Backend& backend;
+
+ Bin initialbin;
+ Arc_ptr pjarc;
+ int s_index;
+ int t_index;
+ Quilt * qlist;
+ Flist spbrkpts;
+ Flist tpbrkpts;
+ Flist smbrkpts;
+ Flist tmbrkpts;
+ REAL stepsizes[4];
+ int showDegenerate;
+ int isArcTypeBezier;
+
+ void samplingSplit( Curvelist&, int );
+
+ void subdivideInS( Bin& );
+ void splitInS( Bin&, int, int );
+ void splitInT( Bin&, int, int );
+ void samplingSplit( Bin&, Patchlist&, int, int );
+ void nonSamplingSplit( Bin&, Patchlist&, int, int );
+ void tessellation( Bin&, Patchlist& );
+ void monosplitInS( Bin&, int, int );
+ void monosplitInT( Bin&, int, int );
+
+ void outline( Bin & );
+ void freejarcs( Bin & );
+ void render( Bin & );
+ void split( Bin &, Bin &, Bin &, int, REAL );
+ void tessellate( Bin &, REAL, REAL, REAL, REAL );
+
+ inline void setDegenerate( void ) { showDegenerate = 1; }
+ inline void setNonDegenerate( void ) { showDegenerate = 0; }
+ inline int showingDegenerate( void ) { return showDegenerate; }
+ inline void setArcTypeBezier( void ) { isArcTypeBezier = 1; }
+ inline void setArcTypePwl( void ) { isArcTypeBezier = 0; }
+ inline int isBezierArcType( void ) { return isArcTypeBezier; }
+
+ void makeBorderTrim( const REAL *, const REAL * );
+ void split( Bin &, int, const REAL *, int, int );
+ void partition( Bin &, Bin &, Bin &, Bin &, Bin &, int, REAL );
+ void findIrregularS( Bin & );
+ void findIrregularT( Bin & );
+
+
+ inline int bbox( TrimVertex *, TrimVertex *, TrimVertex *, int );
+ static int bbox( REAL, REAL, REAL, REAL, REAL, REAL );
+ static int ccw( TrimVertex *, TrimVertex *, TrimVertex * );
+ void join_s( Bin &, Bin &, Arc_ptr, Arc_ptr );
+ void join_t( Bin &, Bin &, Arc_ptr , Arc_ptr );
+ int arc_split( Arc_ptr , int, REAL, int );
+ void check_s( Arc_ptr , Arc_ptr );
+ void check_t( Arc_ptr , Arc_ptr );
+ inline void link( Arc_ptr , Arc_ptr , Arc_ptr , Arc_ptr );
+ inline void simple_link( Arc_ptr , Arc_ptr );
+
+ Bin* makePatchBoundary( const REAL *from, const REAL *to );
+
+ /*in domain distance method, the tessellation is controled by two numbers:
+ *GLU_U_STEP: number of u-segments per unit u length of domain
+ *GLU_V_STEP: number of v-segments per unit v length of domain
+ *These two numbers are normally stored in mapdesc->maxs(t)rate.
+ *I (ZL) put these two numbers here so that I can optimize the untrimmed
+ *case in the case of domain distance sampling.
+ *These two numbers are set by set_domain_distance_u_rate() and ..._v_..().
+ */
+ REAL domain_distance_u_rate;
+ REAL domain_distance_v_rate;
+ int is_domain_distance_sampling;
+};
+
+inline void
+Subdivider::beginLoop( void )
+{
+ pjarc = 0;
+}
+
+
+#endif /* __glusubdivider_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/tobezier.cc b/mesalib/src/glu/sgi/libnurbs/internals/tobezier.cc
new file mode 100644
index 000000000..531f26bc7
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/tobezier.cc
@@ -0,0 +1,687 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * tobezier.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mystring.h"
+#include "quilt.h"
+#include "knotvector.h"
+
+/* local type definitions */
+struct Breakpt { /* breakpoints */
+ Knot value; /* value */
+ int multi; /* multiplicity */
+ int def; /* deficit */
+};
+
+struct Knotspec { /* knotvector format */
+ long order; /* order of spline */
+ Knot_ptr inkbegin; /* input knot sequence */
+ Knot_ptr inkend; /* location after last knot */
+ Knot_ptr outkbegin; /* in-process knot subsequence */
+ Knot_ptr outkend; /* location after last knot */
+ Knot_ptr kleft; /* */
+ Knot_ptr kright; /* */
+ Knot_ptr kfirst; /* */
+ Knot_ptr klast; /* */
+ Knot_ptr sbegin; /* conversion factor values */
+ Breakpt * bbegin; /* in-process breakpoints */
+ Breakpt * bend; /* last breakpoint */
+ int ncoords; /* coordinates per control point */
+ int prestride; /* stride between input points */
+ int poststride; /* stride between output points */
+ int preoffset; /* scaled point offset */
+ int postoffset; /* scaled point offset */
+ int prewidth; /* width of dimension */
+ int postwidth; /* width of dimension */
+ int istransformed; /* was dimension transformed */
+ Knotspec * next; /* next knotspec */
+ Knotspec * kspectotrans; /* knotspec in transformation direction */
+
+ Knotspec( void );
+ ~Knotspec( void );
+ void factors( void );
+ void insert( REAL * );
+ void preselect();
+ void select( void );
+ void copy( INREAL *, REAL * );
+ void breakpoints( void );
+ void knots( void );
+ void transform( REAL * );
+ void showpts( REAL * );
+
+ void pt_io_copy( REAL *, INREAL * );
+ void pt_oo_copy( REAL *, REAL * );
+ void pt_oo_sum( REAL*, REAL*, REAL*, Knot, Knot );
+};
+
+struct Splinespec { /* a non-uniform tensor element */
+ Splinespec( int );
+ ~Splinespec(void);
+ Knotspec *kspec; /* format of each param. dir. */
+ int dim; /* domain dimension */
+ REAL * outcpts; /* Bezier control points */
+
+ void kspecinit( Knotvector & );
+ void kspecinit( Knotvector &, Knotvector & );
+ void select( void );
+ void layout( long );
+ void setupquilt( Quilt_ptr );
+ void copy( INREAL * );
+ void transform( void );
+};
+
+/*-----------------------------------------------------------------------------
+ * Quilt::toBezier - convert from NURBS to rational Bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Quilt::toBezier(
+ Knotvector& knotvector, /* a knot vector */
+ INREAL *ctlpts, /* input contol points */
+ long ncoords ) /* number of coordinates per control point */
+{
+ Splinespec spline( 1 );
+ spline.kspecinit( knotvector );
+ spline.select();
+ spline.layout( ncoords );
+ spline.setupquilt( this );
+ spline.copy( ctlpts );
+ spline.transform();
+}
+
+void
+Quilt::toBezier(
+ Knotvector& sknotvector, /* a knot vector */
+ Knotvector& tknotvector, /* a knot vector */
+ INREAL *ctlpts, /* input contol points */
+ long ncoords ) /* number of coordinates per control point */
+{
+ Splinespec spline( 2 );
+ spline.kspecinit( sknotvector, tknotvector );
+ spline.select();
+ spline.layout( ncoords );
+ spline.setupquilt( this );
+ spline.copy( ctlpts );
+ spline.transform();
+}
+Splinespec::Splinespec( int dimen )
+{
+ dim = dimen;
+}
+
+Splinespec::~Splinespec( void )
+{
+ /* Note: do NOT delete 'outcpts' here since its address (not contents)
+ * is copied in 'cpts' in this file in function Splinespec::setupquilt().
+ * This block of memory will eventually be deleted in file quilt.c++ in
+ * function Quilt::deleteMe() through 'cpts' so do NOT delete it here!
+ */
+ Knotspec *ktrav= kspec; //start at beginning of list
+ while (ktrav != 0) { //any items to delete?
+ Knotspec *deleteThis= ktrav; //remember to delete this
+ ktrav= ktrav->next; //go to next item if any
+ delete deleteThis; //delete it
+ }
+} /* ~Splinespec() */
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::kspecinit - initialize Splinespec structure
+ *
+ * Client: Quilt::toBezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::kspecinit( Knotvector& knotvector )
+{
+ kspec = new Knotspec;
+ kspec->inkbegin = knotvector.knotlist;
+ kspec->inkend = knotvector.knotlist + knotvector.knotcount;
+ kspec->prestride = (int) knotvector.stride;
+ kspec->order = knotvector.order;
+ kspec->next = NULL;
+}
+
+void
+Splinespec::kspecinit( Knotvector& sknotvector, Knotvector& tknotvector )
+{
+ kspec = new Knotspec;
+ Knotspec *tkspec = new Knotspec;
+
+ kspec->inkbegin = sknotvector.knotlist;
+ kspec->inkend = sknotvector.knotlist + sknotvector.knotcount;
+ kspec->prestride = (int) sknotvector.stride;
+ kspec->order = sknotvector.order;
+ kspec->next = tkspec;
+
+ tkspec->inkbegin = tknotvector.knotlist;
+ tkspec->inkend = tknotvector.knotlist + tknotvector.knotcount;
+ tkspec->prestride = (int) tknotvector.stride;
+ tkspec->order = tknotvector.order;
+ tkspec->next = NULL;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::select - select the subsegments to copy
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::select( )
+{
+ for( Knotspec *knotspec = kspec; knotspec; knotspec = knotspec->next ) {
+ knotspec->preselect();
+ knotspec->select();
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::layout -
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::layout( long ncoords )
+{
+
+ long stride = ncoords;
+ for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next ) {
+ knotspec->poststride = (int) stride;
+ stride *= ((knotspec->bend-knotspec->bbegin)*knotspec->order + knotspec->postoffset);
+ knotspec->preoffset *= knotspec->prestride;
+ knotspec->prewidth *= knotspec->poststride;
+ knotspec->postwidth *= knotspec->poststride;
+ knotspec->postoffset *= knotspec->poststride;
+ knotspec->ncoords = (int) ncoords;
+ }
+ outcpts = new REAL[stride];
+ assert( outcpts != 0 );
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::copy - copy the control points of current subobject
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::copy( INREAL *incpts )
+{
+ kspec->copy( incpts, outcpts );
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::setupquilt - assign all quilt variables from knotspec
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::setupquilt( Quilt_ptr quilt )
+{
+ Quiltspec_ptr qspec = quilt->qspec;
+ quilt->eqspec = qspec + dim;
+ for( Knotspec *knotspec = kspec; knotspec; knotspec=knotspec->next, qspec++ ) {
+ qspec->stride = knotspec->poststride;
+ qspec->width = knotspec->bend - knotspec->bbegin;
+ qspec->order = (int) knotspec->order;
+ qspec->offset = knotspec->postoffset;
+ qspec->index = 0;
+ qspec->bdry[0] = (knotspec->kleft == knotspec->kfirst) ? 1 : 0;
+ qspec->bdry[1] = (knotspec->kright == knotspec->klast) ? 1 : 0;
+ qspec->breakpoints = new Knot[qspec->width+1];
+ Knot_ptr k = qspec->breakpoints;
+ for( Breakpt *bk = knotspec->bbegin; bk <= knotspec->bend; bk++ )
+ *(k++) = bk->value;
+ }
+ quilt->cpts = outcpts;
+ quilt->next = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Splinespec::transform - convert a spline to Bezier format
+ *
+ * Client: gl_quilt_to_bezier
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Splinespec::transform( void )
+{
+ Knotspec *knotspec;
+ for( knotspec = kspec; knotspec; knotspec=knotspec->next )
+ knotspec->istransformed = 0;
+
+ for( knotspec = kspec; knotspec; knotspec=knotspec->next ) {
+ for( Knotspec *kspec2 = kspec; kspec2; kspec2=kspec2->next )
+ kspec2->kspectotrans = knotspec;
+ kspec->transform( outcpts );
+ knotspec->istransformed = 1;
+ }
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::Knotspec - constuct a knot spec
+ *-----------------------------------------------------------------------------
+ */
+
+Knotspec::Knotspec( void )
+{
+ bbegin = 0;
+ sbegin = 0;
+ outkbegin = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::copy - copy the control points along minor direction
+ *
+ * Client: Splinespec::copy
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::copy( INREAL *inpt, REAL *outpt )
+{
+ inpt = (INREAL *) (((char *) inpt) + preoffset);
+
+ if( next ) {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
+ next->copy( inpt, outpt );
+ inpt = (INREAL *) (((char *) inpt) + prestride);
+ }
+ } else {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride ) {
+ pt_io_copy( outpt, inpt );
+ inpt = (INREAL *) (((char *) inpt) + prestride);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::showpts - print out points before transformation
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+void
+Knotspec::showpts( REAL *outpt )
+{
+ if( next ) {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
+ next->showpts( outpt );
+ } else {
+ for( REAL *lpt=outpt+prewidth; outpt != lpt; outpt += poststride )
+ _glu_dprintf( "show %g %g %g\n", outpt[0], outpt[1], outpt[2] );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::factors - precompute scale factors
+ * - overwrites knot vector, actual new knot vector is NOT produced
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::factors( void )
+{
+ Knot *mid = (outkend - 1) - order + bend->multi;
+ Knot_ptr fptr = sbegin;
+
+ for( Breakpt *bpt = bend; bpt >= bbegin; bpt-- ) {
+ mid -= bpt->multi; // last knot less than knot to insert
+ int def = bpt->def - 1; // number of knots to insert
+ if( def <= 0 ) continue;
+ Knot kv = bpt->value; // knot to insert
+
+ Knot *kf = (mid-def) + (order-1);
+ for( Knot *kl = kf + def; kl != kf; kl-- ) {
+ Knot *kh, *kt;
+ for( kt=kl, kh=mid; kt != kf; kh--, kt-- )
+ *(fptr++) = (kv - *kh) / (*kt - *kh);
+ *kl = kv;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::insert - convert subobject in direction of kspec into Bezier
+ *
+ * Client: Knotspec::transform
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::insert( REAL *p )
+{
+ Knot_ptr fptr = sbegin;
+ REAL *srcpt = p + prewidth - poststride;
+ REAL *dstpt = p + postwidth + postoffset - poststride;
+ Breakpt *bpt = bend;
+
+ for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride ) {
+ REAL *p1 = srcpt;
+ for( REAL *p2 = srcpt-poststride; p2 != pend; p1 = p2, p2 -= poststride ) {
+ pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
+ fptr++;
+ }
+ }
+
+ for( --bpt; bpt >= bbegin; bpt-- ) {
+
+ for( int multi = bpt->multi; multi > 0; multi-- ) {
+ pt_oo_copy( dstpt, srcpt );
+ dstpt -= poststride;
+ srcpt -= poststride;
+ }
+
+ for( REAL *pend = srcpt - poststride*bpt->def; srcpt != pend; pend +=poststride, dstpt-=poststride ) {
+ pt_oo_copy( dstpt, srcpt );
+ REAL *p1 = srcpt;
+
+ for( REAL *p2 = srcpt-poststride; p2 != pend; p1=p2, p2 -= poststride ) {
+ pt_oo_sum( p1, p1, p2, *fptr, 1.0-*fptr );
+ fptr++;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::preselect - initialize kspec for processing
+ *
+ * Client: Splinespec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::preselect( void )
+{
+ Knot kval;
+
+ /* position klast after last knot of "last" breakpoint */
+ for( klast = inkend - order, kval = *klast; klast != inkend; klast++ )
+ if( ! identical( *klast, kval ) ) break;
+
+ /* position kfirst after last knot of "first" breakpoint */
+ for( kfirst = inkbegin+order-1, kval= *kfirst; kfirst != inkend; kfirst++ )
+ if( ! identical( *kfirst, kval ) ) break;
+
+ /* compute multiplicity of first breakpoint */
+ Knot_ptr k;
+ for( k = kfirst - 1; k >= inkbegin; k-- )
+ if( ! identical( kval, *k ) ) break;
+ k++;
+
+ /* allocate space for breakpoints -
+ use worst case estimate on number of breakpoints */
+
+ bbegin = new Breakpt[(klast - kfirst)+1];
+ /* record multiplicity and value of first breakpoint */
+ bbegin->multi = kfirst - k;
+ bbegin->value = kval;
+ bend = bbegin;
+
+ kleft = kright = kfirst;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::select - Knotspec::select segments and precompute scale factors
+ *
+ * Client: Splinespec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::select( void )
+{
+ breakpoints();
+ knots();
+ factors();
+
+ preoffset = kleft - (inkbegin + order);
+ postwidth = (int)((bend - bbegin) * order);
+ prewidth = (int)((outkend - outkbegin) - order);
+ postoffset = (bbegin->def > 1) ? (bbegin->def-1) : 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::breakpoints - compute breakpoints for knotspec
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::breakpoints( void )
+{
+ Breakpt *ubpt = bbegin;
+ Breakpt *ubend = bend;
+ long nfactors = 0;
+
+ ubpt->value = ubend->value;
+ ubpt->multi = ubend->multi;
+
+ kleft = kright;
+
+ for( ; kright != klast; kright++ ) {
+ if ( identical(*kright,ubpt->value) ) {
+ (ubpt->multi)++;
+ } else {
+ ubpt->def = (int) (order - ubpt->multi);
+ nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
+ (++ubpt)->value = *kright;
+ ubpt->multi = 1;
+ }
+ }
+ ubpt->def = (int) (order - ubpt->multi);
+ nfactors += (ubpt->def * (ubpt->def - 1)) / 2;
+
+ bend = ubpt;
+
+ if( nfactors ) {
+ sbegin = new Knot[nfactors];
+ } else {
+ sbegin = NULL;
+ }
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::knots - copy relevant subsequence of knots into temporary area
+ *
+ * Client: Knotspec::select
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::knots( void )
+{
+ Knot_ptr inkpt = kleft - order;
+ Knot_ptr inkend = kright + bend->def;
+
+ /* allocate space for knots and factors */
+ outkbegin = new Knot[inkend-inkpt];
+ Knot_ptr outkpt;
+ for( outkpt = outkbegin; inkpt != inkend; inkpt++, outkpt++ )
+ *outkpt = *inkpt;
+
+ outkend = outkpt;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::transform - convert a spline along a given direction
+ *
+ * Client: Splienspec::transform
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::transform( REAL *p )
+{
+ if( next ) {
+ if( this == kspectotrans ) {
+ next->transform( p );
+ } else {
+ if( istransformed ) {
+ p += postoffset;
+ for( REAL *pend = p + postwidth; p != pend; p += poststride )
+ next->transform( p );
+ } else {
+ REAL *pend = p + prewidth;
+ for( ; p != pend; p += poststride )
+ next->transform( p );
+ }
+ }
+ } else {
+ if( this == kspectotrans ) {
+ insert( p );
+ } else {
+ if( istransformed ) {
+ p += postoffset;
+ for( REAL *pend = p + postwidth; p != pend; p += poststride )
+ kspectotrans->insert( p );
+ } else {
+ REAL *pend = p + prewidth;
+ for( ; p != pend; p += poststride )
+ kspectotrans->insert( p );
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * Knotspec::~Knotspec - free space alocated for knotspec
+ *-----------------------------------------------------------------------------
+ */
+
+Knotspec::~Knotspec( void )
+{
+ if( bbegin ) delete[] bbegin;
+ if( sbegin ) delete[] sbegin;
+ if( outkbegin ) delete[] outkbegin;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * pt_io_copy - make internal copy of input cntrl pt. of x coords
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_io_copy( REAL *topt, INREAL *frompt )
+{
+ switch( ncoords ) {
+ case 4:
+ topt[3] = (REAL) frompt[3];
+ case 3:
+ topt[2] = (REAL) frompt[2];
+ case 2:
+ topt[1] = (REAL) frompt[1];
+ case 1:
+ topt[0] = (REAL) frompt[0];
+ break;
+ default: {
+ for( int i = 0; i < ncoords; i++ )
+ *topt++ = (REAL) *frompt++;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * pt_oo_copy - make internal copy of internal cntrl pt. of x coords
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_oo_copy( REAL *topt, REAL *frompt )
+{
+ switch( ncoords ) {
+ case 4:
+ topt[3] = frompt[3];
+ case 3:
+ topt[2] = frompt[2];
+ case 2:
+ topt[1] = frompt[1];
+ case 1:
+ topt[0] = frompt[0];
+ break;
+ default:
+ memcpy( topt, frompt, ncoords * sizeof( REAL ) );
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * pt_oo_sum - compute affine combination of internal cntrl pts
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Knotspec::pt_oo_sum( REAL *x, REAL *y, REAL *z, Knot a, Knot b )
+{
+ switch( ncoords ) {
+ case 4:
+ x[3] = a * y[3] + b * z[3];
+ case 3:
+ x[2] = a * y[2] + b * z[2];
+ case 2:
+ x[1] = a * y[1] + b * z[1];
+ case 1:
+ x[0] = a * y[0] + b * z[0];
+ break;
+ default: {
+ for( int i = 0; i < ncoords; i++ )
+ *x++ = a * *y++ + b * *z++;
+ }
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimline.cc b/mesalib/src/glu/sgi/libnurbs/internals/trimline.cc
new file mode 100644
index 000000000..61f34cd38
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimline.cc
@@ -0,0 +1,223 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimline.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "trimline.h"
+#include "backend.h"
+
+Trimline::Trimline()
+{
+ size = 0; pts = 0; numverts = 0;
+ tinterp = &t; binterp = &b;
+}
+
+Trimline::~Trimline()
+{
+ if( pts ) delete[] pts;
+}
+
+void
+Trimline::init( TrimVertex *v )
+{
+ reset();
+ grow(1);
+ append(v);
+}
+
+inline void
+Trimline::grow( long npts )
+{
+ if( size < npts ) {
+ size = 2 * npts;
+ if( pts ) delete[] pts;
+ pts = new TrimVertex_p[size];
+ }
+}
+
+inline void
+Trimline::append( TrimVertex *v )
+{
+ assert( numverts != size );
+ pts[numverts++] = v;
+}
+
+void
+Trimline::init( long npts, Arc_ptr jarc, long last )
+{
+ jarcl.init( jarc, 0, last );
+ grow( npts + 2 );
+}
+
+inline void
+Trimline::swap()
+{
+ TrimVertex *tmp=tinterp;
+ tinterp=binterp;
+ binterp=tmp;
+}
+
+void
+Trimline::getNextPt()
+{
+ *binterp = *jarcl.getnextpt();
+}
+
+void
+Trimline::getPrevPt()
+{
+ *binterp = *jarcl.getprevpt();
+}
+
+/*----------------------------------------------------------------------
+ * getNextPts - make arrays of pointers to trim points on left and right
+ * hulls of trim strip.
+ *----------------------------------------------------------------------
+ */
+void
+Trimline::getNextPts( REAL vval, Backend& backend )
+{
+ reset(); swap(); append( tinterp );
+ assert( tinterp->param[1] >= vval );
+
+ register TrimVertex *p;
+ for( p=jarcl.getnextpt() ; p->param[1] >= vval; p=jarcl.getnextpt() ) {
+ append( p );
+ }
+
+ /* compute and copy pointer to final point on left hull */
+ if( interpvert( last(), p, binterp, vval ) ) {
+ binterp->nuid = p->nuid;
+ backend.triangle( p, binterp, last() );
+ append( binterp );
+ }
+ jarcl.reverse();
+ (void) jarcl.getprevpt(); /* reset jarcl to proper position */
+ jarcl.reverse();
+}
+
+void
+Trimline::getPrevPts( REAL vval, Backend& backend )
+{
+ reset(); swap(); append( tinterp );
+ assert( tinterp->param[1] >= vval );
+
+ register TrimVertex *q;
+ for( q=jarcl.getprevpt(); q->param[1] >= vval; q=jarcl.getprevpt() ) {
+ append( q );
+ }
+
+ /* compute and copy pointer to final point on right hull */
+ if( interpvert( q, last(), binterp, vval ) ) {
+ binterp->nuid = q->nuid;
+ backend.triangle( last(), binterp, q );
+ append( binterp );
+ }
+ jarcl.reverse();
+ (void) jarcl.getnextpt(); /* reset jarcl to proper position */
+ jarcl.reverse();
+}
+
+void
+Trimline::getNextPts( Arc_ptr botarc )
+{
+ reset(); swap(); append( tinterp );
+
+#ifndef NDEBUG
+ PwlArc *lastpwl = botarc->prev->pwlArc;
+ TrimVertex *lastpt1 = &lastpwl->pts[lastpwl->npts-1];
+#endif
+ TrimVertex *lastpt2 = botarc->pwlArc->pts;
+ register TrimVertex *p = jarcl.getnextpt();
+ for( append( p ); p != lastpt2; append( p ) ) {
+ assert( p != lastpt1 );
+ p = jarcl.getnextpt();
+ }
+}
+
+void
+Trimline::getPrevPts( Arc_ptr botarc )
+{
+ reset(); swap(); append( tinterp );
+
+ PwlArc *lastpwl = botarc->prev->pwlArc;
+ TrimVertex *lastpt1 = &lastpwl->pts[lastpwl->npts-1];
+#ifndef NDEBUG
+ TrimVertex *lastpt2 = botarc->pwlArc->pts;
+#endif
+
+ register TrimVertex *q = jarcl.getprevpt();
+ for( append( q ); q != lastpt1; append( q ) ) {
+ assert( q != lastpt2 );
+ q = jarcl.getprevpt();
+ }
+}
+
+
+long
+Trimline::interpvert( TrimVertex *a, TrimVertex *b, TrimVertex *c, REAL vval )
+{
+ REAL denom = a->param[1] - b->param[1];
+
+ if(denom != 0) {
+ if( vval == a->param[1] ) {
+ c->param[0] = a->param[0];
+ c->param[1] = a->param[1];
+ c->nuid = a->nuid;
+ return 0;
+ } else if( vval == b->param[1] ) {
+ c->param[0] = b->param[0];
+ c->param[1] = b->param[1];
+ c->nuid = b->nuid;
+ return 0;
+ } else {
+ REAL r = (a->param[1] - vval)/denom;
+ c->param[0] = a->param[0] - r * (a->param[0] - b->param[0]);
+ c->param[1] = vval;
+ return 1;
+ }
+ } else {
+ c->param[0] = a->param[0];
+ c->param[1] = a->param[1];
+ c->nuid = a->nuid;
+ return 0;
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimline.h b/mesalib/src/glu/sgi/libnurbs/internals/trimline.h
new file mode 100644
index 000000000..ecc884284
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimline.h
@@ -0,0 +1,103 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * trimline.h
+ *
+ */
+
+#ifndef __glutrimline_h_
+#define __glutrimline_h_
+
+class Arc;
+class Backend;
+
+#include "trimvertex.h"
+#include "jarcloc.h"
+
+
+class Trimline {
+private:
+ TrimVertex** pts;
+ long numverts;
+ long i;
+ long size;
+ Jarcloc jarcl;
+ TrimVertex t, b;
+ TrimVertex *tinterp, *binterp;
+ void reset( void ) { numverts = 0; }
+ inline void grow( long );
+ inline void swap( void );
+ inline void append( TrimVertex * );
+ static long interpvert( TrimVertex *, TrimVertex *, TrimVertex *, REAL );
+
+
+
+public:
+ Trimline();
+ ~Trimline();
+ void init( TrimVertex * );
+ void init( long, Arc_ptr, long );
+ void getNextPt( void );
+ void getPrevPt( void );
+ void getNextPts( REAL, Backend & );
+ void getPrevPts( REAL, Backend & );
+ void getNextPts( Arc_ptr );
+ void getPrevPts( Arc_ptr );
+ inline TrimVertex * next( void );
+ inline TrimVertex * prev( void );
+ inline TrimVertex * first( void );
+ inline TrimVertex * last( void );
+};
+
+inline TrimVertex *
+Trimline::next( void )
+{
+ if( i < numverts) return pts[i++]; else return 0;
+}
+
+inline TrimVertex *
+Trimline::prev( void )
+{
+ if( i >= 0 ) return pts[i--]; else return 0;
+}
+
+inline TrimVertex *
+Trimline::first( void )
+{
+ i = 0; return pts[i];
+}
+
+inline TrimVertex *
+Trimline::last( void )
+{
+ i = numverts; return pts[--i];
+}
+#endif /* __glutrimline_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimregion.cc b/mesalib/src/glu/sgi/libnurbs/internals/trimregion.cc
new file mode 100644
index 000000000..efe789356
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimregion.cc
@@ -0,0 +1,114 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimregion.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "trimregion.h"
+#include "backend.h"
+
+TrimRegion::TrimRegion( void )
+{
+}
+
+void
+TrimRegion::setDu( REAL du )
+{
+ oneOverDu = 1.0/du;
+}
+
+void
+TrimRegion::init( long npts, Arc_ptr extrema )
+{
+ left.init( npts, extrema, extrema->pwlArc->npts - 1 );
+ left.getNextPt();
+
+ right.init( npts, extrema, 0 );
+ right.getPrevPt();
+}
+
+void
+TrimRegion::getPts( Arc_ptr extrema )
+{
+ left.getNextPts( extrema );
+ right.getPrevPts( extrema );
+}
+
+void
+TrimRegion::getPts( Backend &backend )
+{
+ left.getNextPts( bot.vval, backend );
+ right.getPrevPts( bot.vval, backend );
+}
+
+void
+TrimRegion::getGridExtent( void )
+{
+ getGridExtent( left.last(), right.last() );
+}
+
+void
+TrimRegion::getGridExtent( TrimVertex *l, TrimVertex *r )
+{
+ bot.ustart = (long) ((l->param[0] - uarray.uarray[0])*oneOverDu);
+ if( l->param[0] >= uarray.uarray[bot.ustart] ) bot.ustart++;
+// if( l->param[0] > uarray.uarray[bot.ustart] ) bot.ustart++;
+ assert( l->param[0] <= uarray.uarray[bot.ustart] );
+ assert( l->param[0] >= uarray.uarray[bot.ustart-1] );
+
+ bot.uend = (long) ((r->param[0] - uarray.uarray[0])*oneOverDu);
+ if( uarray.uarray[bot.uend] >= r->param[0] ) bot.uend--;
+// if( uarray.uarray[bot.uend] > r->param[0] ) bot.uend--;
+ assert( r->param[0] >= uarray.uarray[bot.uend] );
+ assert( r->param[0] <= uarray.uarray[bot.uend+1] );
+}
+
+int
+TrimRegion::canTile( void )
+{
+ TrimVertex *lf = left.first();
+ TrimVertex *ll = left.last();
+ TrimVertex *l = ( ll->param[0] > lf->param[0] ) ? ll : lf;
+
+ TrimVertex *rf = right.first();
+ TrimVertex *rl = right.last();
+ TrimVertex *r = ( rl->param[0] < rf->param[0] ) ? rl : rf;
+ return (l->param[0] <= r->param[0]) ? 1 : 0;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimregion.h b/mesalib/src/glu/sgi/libnurbs/internals/trimregion.h
new file mode 100644
index 000000000..ee15d7b98
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimregion.h
@@ -0,0 +1,84 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * trimregion.h
+ *
+ */
+
+#ifndef __glutrimregion_h_
+#define __glutrimregion_h_
+
+#include "trimline.h"
+#include "gridline.h"
+#include "uarray.h"
+
+class Arc;
+class Backend;
+
+class TrimRegion {
+public:
+ TrimRegion();
+ Trimline left;
+ Trimline right;
+ Gridline top;
+ Gridline bot;
+ Uarray uarray;
+
+ void init( REAL );
+ void advance( REAL, REAL, REAL );
+ void setDu( REAL );
+ void init( long, Arc_ptr );
+ void getPts( Arc_ptr );
+ void getPts( Backend & );
+ void getGridExtent( TrimVertex *, TrimVertex * );
+ void getGridExtent( void );
+ int canTile( void );
+private:
+ REAL oneOverDu;
+};
+
+inline void
+TrimRegion::init( REAL vval )
+{
+ bot.vval = vval;
+}
+
+inline void
+TrimRegion::advance( REAL topVindex, REAL botVindex, REAL botVval )
+{
+ top.vindex = (long) topVindex;
+ bot.vindex = (long) botVindex;
+ top.vval = bot.vval;
+ bot.vval = botVval;
+ top.ustart = bot.ustart;
+ top.uend = bot.uend;
+}
+#endif /* __glutrimregion_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimvertex.h b/mesalib/src/glu/sgi/libnurbs/internals/trimvertex.h
new file mode 100644
index 000000000..2780b764a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimvertex.h
@@ -0,0 +1,63 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * trimvertex.h
+ *
+ */
+
+#ifndef __glutrimvertex_h_
+#define __glutrimvertex_h_
+
+#include "types.h"
+
+/*#define USE_OPTTT*/
+
+class TrimVertex { /* a vertex on a trim curve */
+public:
+ REAL param[2]; /* parametric space coords */
+#ifdef USE_OPTTT
+ REAL cache_point[4]; //only when USE_OPTTT is on in slicer.c++
+ REAL cache_normal[3];
+#endif
+ long nuid;
+};
+
+typedef class TrimVertex *TrimVertex_p;
+
+inline REAL
+det3( TrimVertex *a, TrimVertex *b, TrimVertex *c )
+{
+ return a->param[0] * (b->param[1]-c->param[1]) +
+ b->param[0] * (c->param[1]-a->param[1]) +
+ c->param[0] * (a->param[1]-b->param[1]);
+}
+
+#endif /* __glutrimvertex_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.cc b/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.cc
new file mode 100644
index 000000000..3e5bd7038
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.cc
@@ -0,0 +1,119 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * trimvertexpool.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "mystring.h"
+#include "trimvertex.h"
+#include "trimvertpool.h"
+#include "bufpool.h"
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::TrimVertexPool
+ *----------------------------------------------------------------------------
+ */
+TrimVertexPool::TrimVertexPool( void )
+ : pool( sizeof(TrimVertex)*3, 32, "Threevertspool" )
+{
+ // initialize array of pointers to vertex lists
+ nextvlistslot = 0;
+ vlistsize = INIT_VERTLISTSIZE;
+ vlist = new TrimVertex_p[vlistsize];
+}
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::~TrimVertexPool
+ *----------------------------------------------------------------------------
+ */
+TrimVertexPool::~TrimVertexPool( void )
+{
+ // free all arrays of TrimVertices vertices
+ while( nextvlistslot ) {
+ delete [] vlist[--nextvlistslot];
+ }
+
+ // reallocate space for array of pointers to vertex lists
+ if( vlist ) delete[] vlist;
+}
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::clear
+ *----------------------------------------------------------------------------
+ */
+void
+TrimVertexPool::clear( void )
+{
+ // reinitialize pool of 3 vertex arrays
+ pool.clear();
+
+ // free all arrays of TrimVertices vertices
+ while( nextvlistslot ) {
+ delete [] vlist[--nextvlistslot];
+ vlist[nextvlistslot] = 0;
+ }
+
+ // reallocate space for array of pointers to vertex lists
+ if( vlist ) delete[] vlist;
+ vlist = new TrimVertex_p[vlistsize];
+}
+
+
+/*----------------------------------------------------------------------------
+ * TrimVertexPool::get - allocate a vertex list
+ *----------------------------------------------------------------------------
+ */
+TrimVertex *
+TrimVertexPool::get( int n )
+{
+ TrimVertex *v;
+ if( n == 3 ) {
+ v = (TrimVertex *) pool.new_buffer();
+ } else {
+ if( nextvlistslot == vlistsize ) {
+ vlistsize *= 2;
+ TrimVertex_p *nvlist = new TrimVertex_p[vlistsize];
+ memcpy( nvlist, vlist, nextvlistslot * sizeof(TrimVertex_p) );
+ if( vlist ) delete[] vlist;
+ vlist = nvlist;
+ }
+ v = vlist[nextvlistslot++] = new TrimVertex[n];
+ }
+ return v;
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.h b/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.h
new file mode 100644
index 000000000..ebd3c04b1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/trimvertpool.h
@@ -0,0 +1,57 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * trimvertexpool.h
+ *
+ */
+
+#ifndef __glutrimvertpool_h_
+#define __glutrimvertpool_h_
+
+#include "bufpool.h"
+
+class TrimVertex;
+
+#define INIT_VERTLISTSIZE 200
+
+class TrimVertexPool {
+public:
+ TrimVertexPool( void );
+ ~TrimVertexPool( void );
+ void clear( void );
+ TrimVertex * get( int );
+private:
+ Pool pool;
+ TrimVertex ** vlist;
+ int nextvlistslot;
+ int vlistsize;
+};
+#endif /* __glutrimvertpool_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/types.h b/mesalib/src/glu/sgi/libnurbs/internals/types.h
new file mode 100644
index 000000000..8b59625cf
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/types.h
@@ -0,0 +1,47 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * types.h
+ *
+ */
+
+#ifndef __glutypes_h_
+#define __glutypes_h_
+
+//typedef double INREAL;
+#define INREAL float
+typedef float REAL;
+typedef void (*Pfvv)( void );
+typedef void (*Pfvf)( float * );
+typedef int (*cmpfunc)(const void *, const void *);
+typedef REAL Knot, *Knot_ptr;/* knot values */
+
+#endif /* __glutypes_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/uarray.cc b/mesalib/src/glu/sgi/libnurbs/internals/uarray.cc
new file mode 100644
index 000000000..f0e236437
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/uarray.cc
@@ -0,0 +1,72 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * uarray.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "uarray.h"
+#include "arc.h"
+
+Uarray::Uarray( void )
+{
+ uarray = 0;
+ size = 0;
+}
+
+Uarray::~Uarray( void )
+{
+ if( uarray ) delete[] uarray;
+}
+
+long
+Uarray::init( REAL delta, Arc_ptr lo, Arc_ptr hi )
+{
+ ulines = (long) ((hi->tail()[0] - lo->tail()[0])/delta) + 3;
+ if( size < ulines ) {
+ size = ulines * 2;
+ if( uarray ) delete[] uarray;
+ uarray = new REAL[size];
+ assert( uarray != 0);
+ }
+ uarray[0] = lo->tail()[0] - delta/2.0;
+ for( long i = 1 ; i != ulines; i++ )
+ uarray[i] = uarray[0] + i*delta;
+ return ulines;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/uarray.h b/mesalib/src/glu/sgi/libnurbs/internals/uarray.h
new file mode 100644
index 000000000..cc6fae1b7
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/uarray.h
@@ -0,0 +1,55 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * uarray.h
+ *
+ */
+
+#ifndef __gluuarray_h_
+#define __gluuarray_h_
+
+#include "types.h"
+
+class Arc;
+typedef class Arc *Arc_ptr;
+
+class Uarray {
+private:
+ long size;
+ long ulines;
+public:
+ Uarray();
+ ~Uarray();
+ long init( REAL, Arc_ptr, Arc_ptr );
+ REAL * uarray;
+};
+
+#endif /* __gluuarray_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/varray.cc b/mesalib/src/glu/sgi/libnurbs/internals/varray.cc
new file mode 100644
index 000000000..31cc73a9d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/varray.cc
@@ -0,0 +1,144 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+*/
+
+/*
+ * varray.c++
+ *
+ */
+
+#include "glimports.h"
+#include "myassert.h"
+#include "mystdio.h"
+#include "varray.h"
+#include "arc.h"
+#include "simplemath.h" // glu_abs()
+
+#define TINY 0.0001
+inline long sgn( REAL x )
+{
+ return (x < -TINY) ? -1 : ((x > TINY) ? 1 : 0 );
+}
+
+
+Varray::Varray( void )
+{
+ varray = 0;
+ size = 0;
+}
+
+Varray::~Varray( void )
+{
+ if( varray ) delete[] varray;
+}
+
+inline void
+Varray::update( Arc_ptr arc, long dir[2], REAL val )
+{
+ register long ds = sgn(arc->tail()[0] - arc->prev->tail()[0]);
+ register long dt = sgn(arc->tail()[1] - arc->prev->tail()[1]);
+
+ if( dir[0] != ds || dir[1] != dt ) {
+ dir[0] = ds;
+ dir[1] = dt;
+ append( val );
+ }
+}
+
+void
+Varray::grow( long guess )
+{
+ if( size < guess ) {
+ size = guess * 2;
+ if( varray ) delete[] varray;
+ varray = new REAL[size];
+ assert( varray != 0 );
+ }
+}
+
+long
+Varray::init( REAL delta, Arc_ptr toparc, Arc_ptr botarc )
+{
+ Arc_ptr left = toparc->next;
+ Arc_ptr right = toparc;
+ long ldir[2], rdir[2];
+
+ ldir[0] = sgn( left->tail()[0] - left->prev->tail()[0] );
+ ldir[1] = sgn( left->tail()[1] - left->prev->tail()[1] );
+ rdir[0] = sgn( right->tail()[0] - right->prev->tail()[0] );
+ rdir[1] = sgn( right->tail()[1] - right->prev->tail()[1] );
+
+ vval[0] = toparc->tail()[1];
+ numquads = 0;
+
+ while( 1 ) {
+ switch( sgn( left->tail()[1] - right->prev->tail()[1] ) ) {
+ case 1:
+ left = left->next;
+ update( left, ldir, left->prev->tail()[1] );
+ break;
+ case -1:
+ right = right->prev;
+ update( right, rdir, right->tail()[1] );
+ break;
+ case 0:
+ if( glu_abs(left->tail()[1] - botarc->tail()[1]) < TINY) goto end;
+ if( glu_abs(left->tail()[0]-right->prev->tail()[0]) < TINY &&
+ glu_abs(left->tail()[1]-right->prev->tail()[1]) < TINY) goto end;
+ left = left->next;
+ break;
+ }
+ }
+
+end:
+ append( botarc->tail()[1] );
+
+ grow( ((long) ((vval[0] - vval[numquads])/delta)) + numquads + 2 );
+
+ long i, index = 0;
+ for( i=0; i<numquads; i++ ) {
+ voffset[i] = index;
+ varray[index++] = vval[i];
+ REAL dist = vval[i] - vval[i+1];
+ if( dist > delta ) {
+ long steps = ((long) (dist/delta)) +1;
+ float deltav = - dist / (REAL) steps;
+ for( long j=1; j<steps; j++ )
+ varray[index++] = vval[i] + j * deltav;
+ }
+ }
+ voffset[i] = index;
+ varray[index] = vval[i];
+ return index;
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/internals/varray.h b/mesalib/src/glu/sgi/libnurbs/internals/varray.h
new file mode 100644
index 000000000..b12ff837c
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/internals/varray.h
@@ -0,0 +1,68 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * varray.h
+ *
+ */
+
+#ifndef __gluvarray_h_
+#define __gluvarray_h_
+
+#include "types.h"
+
+class Arc;
+
+class Varray {
+public:
+ Varray();
+ ~Varray();
+ long init( REAL, Arc *, Arc * );
+ REAL * varray;
+ REAL vval[1000];
+ long voffset[1000];
+ long numquads;
+
+private:
+ long size;
+ inline void update( Arc *, long[2], REAL );
+ void grow( long );
+ inline void append( REAL );
+};
+
+inline void
+Varray::append( REAL v )
+{
+ if( v != vval[numquads] )
+ vval[++numquads] = v;
+}
+
+
+#endif /* __gluvarray_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h
new file mode 100644
index 000000000..962921da1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/definitions.h
@@ -0,0 +1,40 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _DEFINITIONS_H
+#define _DEFINITIONS_H
+
+typedef float Real;
+typedef int Int;
+typedef Real Real2[2];
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
new file mode 100644
index 000000000..74450352d
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.cc
@@ -0,0 +1,848 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "quicksort.h"
+#include "directedLine.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 726 10
+#endif
+
+//we must return the newLine
+directedLine* directedLine::deleteChain(directedLine* begin, directedLine* end)
+{
+ if(begin->head()[0] == end->tail()[0] &&
+ begin->head()[1] == end->tail()[1]
+ )
+ {
+ directedLine *ret = begin->prev;
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+
+ return ret;
+ }
+
+ directedLine* newLine;
+ sampledLine* sline = new sampledLine(begin->head(), end->tail());
+ newLine = new directedLine(INCREASING, sline);
+ directedLine *p = begin->prev;
+ directedLine *n = end->next;
+ p->next = newLine;
+ n->prev = newLine;
+ newLine->prev = p;
+ newLine->next = n;
+
+ delete begin->sline;
+ delete end->sline;
+ delete begin;
+ delete end;
+ return newLine;
+}
+
+
+void directedLine::deleteSingleLine(directedLine* dline)
+{
+ //make sure that dline->prev->tail is the same as
+ //dline->next->head. This is for numerical erros.
+ //for example, if we delete a line which is almost degeneate
+ //within (epsilon), then we want to make that the polygon after deletion
+ //is still a valid polygon
+
+ dline->next->head()[0] = dline->prev->tail()[0];
+ dline->next->head()[1] = dline->prev->tail()[1];
+
+ dline->prev->next = dline->next;
+ dline->next->prev = dline->prev;
+
+ delete dline;
+
+}
+
+static Int myequal(Real a[2], Real b[2])
+{
+ /*
+ if(a[0]==b[0] && a[1] == b[1])
+ return 1;
+ else
+ return 0;
+ */
+
+
+ if(fabs(a[0]-b[0]) < 0.00001 &&
+ fabs(a[1]-b[1]) < 0.00001)
+ return 1;
+ else
+ return 0;
+
+}
+
+directedLine* directedLine::deleteDegenerateLines()
+{
+ //if there is only one edge or two edges, don't do anything
+ if(this->next == this)
+ return this;
+ if(this->next == this->prev)
+ return this;
+
+ //find a nondegenerate line
+ directedLine* temp;
+ directedLine* first = NULL;
+ if(! myequal(head(), tail()))
+ /*
+ if(head()[0] != tail()[0] ||
+ head()[1] != tail()[1])
+ */
+ first = this;
+ else
+ {
+ for(temp = this->next; temp != this; temp = temp->next)
+ {
+ /*
+ if(temp->head()[0] != temp->tail()[0] ||
+ temp->head()[1] != temp->tail()[1])
+ */
+ if(! myequal(temp->head(), temp->tail()))
+ {
+ first = temp;
+ break;
+ }
+
+ }
+ }
+
+ //if there are no non-degenerate lines, then we simply return NULL.
+ if(first == NULL)
+ {
+ deleteSinglePolygonWithSline();
+ return NULL;
+ }
+
+ directedLine* tempNext = NULL;
+ for(temp =first->next; temp != first; temp = tempNext)
+ {
+ tempNext = temp->getNext();
+/*
+ if(temp->head()[0] == temp->tail()[0] &&
+ temp->head()[1] == temp->tail()[1])
+*/
+
+ if(myequal(temp->head(), temp->tail()))
+ deleteSingleLine(temp);
+ }
+ return first;
+}
+
+directedLine* directedLine::deleteDegenerateLinesAllPolygons()
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+ ret = retEnd = temp->deleteDegenerateLines();
+
+ }
+ else
+ {
+ directedLine *newPolygon = temp->deleteDegenerateLines();
+ if(newPolygon != NULL)
+ {
+ retEnd->nextPolygon = temp->deleteDegenerateLines();
+ retEnd = retEnd->nextPolygon;
+ }
+ }
+ }
+ return ret;
+}
+
+directedLine* directedLine::cutIntersectionAllPoly(int &cutOccur)
+{
+ directedLine* temp;
+ directedLine *tempNext = NULL;
+ directedLine* ret= NULL;
+ directedLine* retEnd = NULL;
+ cutOccur = 0;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ int eachCutOccur=0;
+ tempNext = temp->nextPolygon;
+ temp->nextPolygon = NULL;
+ if(ret == NULL)
+ {
+
+ ret = retEnd = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ else
+ {
+
+ retEnd->nextPolygon = DBG_cutIntersectionPoly(temp, eachCutOccur);
+ retEnd = retEnd->nextPolygon;
+ if(eachCutOccur)
+ cutOccur = 1;
+ }
+ }
+ return ret;
+}
+
+
+void directedLine::deleteSinglePolygonWithSline()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp->sline;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonListWithSline()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygonWithSline();
+ }
+}
+
+void directedLine::deleteSinglePolygon()
+{
+ directedLine *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void directedLine::deletePolygonList()
+{
+ directedLine *temp, *tempNext;
+ for(temp=this; temp != NULL; temp=tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteSinglePolygon();
+ }
+}
+
+
+/*a loop by itself*/
+directedLine::directedLine(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+// prevPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+
+ rootLink = NULL;
+
+}
+
+void directedLine::init(short dir, sampledLine* sl)
+{
+ direction = dir;
+ sline = sl;
+}
+
+directedLine::directedLine()
+{
+ next = this;
+ prev = this;
+ nextPolygon = NULL;
+ rootBit = 0;/*important to initilzae to 0 meaning not root yet*/
+ rootLink = NULL;
+}
+
+directedLine::~directedLine()
+{
+}
+
+Real* directedLine::head()
+{
+
+ return (direction==INCREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+/*inline*/ Real* directedLine::getVertex(Int i)
+{
+ return (direction==INCREASING)? (sline->get_points())[i] : (sline->get_points())[sline->get_npoints() - 1 -i];
+}
+
+Real* directedLine::tail()
+{
+ return (direction==DECREASING)? (sline->get_points())[0] : (sline->get_points())[sline->get_npoints()-1];
+}
+
+ /*insert a new line between prev and this*/
+void directedLine::insert(directedLine* nl)
+{
+ nl->next = this;
+ nl->prev = prev;
+ prev->next = nl;
+ prev = nl;
+ nl->rootLink = this; /*assuming that 'this' is the root!!!*/
+}
+
+Int directedLine::numEdges()
+{
+ Int ret=0;
+ directedLine* temp;
+ if(next == this) return 1;
+
+ ret = 1;
+ for(temp = next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int directedLine::numEdgesAllPolygons()
+{
+ Int ret=0;
+ directedLine* temp;
+ for(temp=this; temp!= NULL; temp=temp->nextPolygon)
+ {
+ ret += temp->numEdges();
+ }
+ return ret;
+}
+
+/*return 1 if the double linked list forms a polygon.
+ */
+short directedLine::isPolygon()
+{
+ directedLine* temp;
+
+ /*a polygon contains at least 3 edges*/
+ if(numEdges() <=2) return 0;
+
+ /*check this edge*/
+ if(! isConnected()) return 0;
+
+ /*check all other edges*/
+ for(temp=next; temp != this; temp = temp->next){
+ if(!isConnected()) return 0;
+ }
+ return 1;
+}
+
+/*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+short directedLine::isConnected()
+{
+ if( (head()[0] == prev->tail()[0]) && (head()[1] == prev->tail()[1]))
+ return 1;
+ else
+ return 0;
+}
+
+Int compV2InY(Real A[2], Real B[2])
+{
+ if(A[1] < B[1]) return -1;
+ if(A[1] == B[1] && A[0] < B[0]) return -1;
+ if(A[1] == B[1] && A[0] == B[0]) return 0;
+ return 1;
+}
+
+Int compV2InX(Real A[2], Real B[2])
+{
+ if(A[0] < B[0]) return -1;
+ if(A[0] == B[0] && A[1] < B[1]) return -1;
+ if(A[0] == B[0] && A[1] == B[1]) return 0;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either y_1 < y_2
+ *or y_1 == y_2 && x_1 < x_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInY(directedLine* nl)
+{
+ if(head()[1] < nl->head()[1]) return -1;
+ if(head()[1] == nl->head()[1] && head()[0] < nl->head()[0]) return -1;
+ return 1;
+}
+
+/*compare two vertices NOT lines!
+ *A vertex is the head of a directed line.
+ *(x_1, y_1) <= (x_2, y_2) if
+ *either x_1 < x_2
+ *or x_1 == x_2 && y_1 < y_2.
+ *return -1 if this->head() <= nl->head(),
+ *return 1 otherwise
+ */
+Int directedLine::compInX(directedLine* nl)
+{
+ if(head()[0] < nl->head()[0]) return -1;
+ if(head()[0] == nl->head()[0] && head()[1] < nl->head()[1]) return -1;
+ return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY2(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+#ifdef NOT_USED
+static Int compInX(directedLine* v1, directedLine* v2)
+{
+ return v1->compInX(v2);
+}
+#endif
+
+/*sort all the vertices NOT the lines!
+ *a vertex is the head of a directed line
+ */
+directedLine** directedLine::sortAllPolygons()
+{
+ Int total_num_edges = 0;
+ directedLine** array = toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void *, void *)) compInY2);
+
+ return array;
+}
+
+void directedLine::printSingle()
+{
+ if(direction == INCREASING)
+ printf("direction is INCREASING\n");
+ else
+ printf("direction is DECREASING\n");
+ printf("head=%f,%f)\n", head()[0], head()[1]);
+ sline->print();
+}
+
+/*print one polygon*/
+void directedLine::printList()
+{
+ directedLine* temp;
+ printSingle();
+ for(temp = next; temp!=this; temp=temp->next)
+ temp->printSingle();
+}
+
+/*print all the polygons*/
+void directedLine::printAllPolygons()
+{
+ directedLine *temp;
+ for(temp = this; temp!=NULL; temp = temp->nextPolygon)
+ {
+ printf("polygon:\n");
+ temp->printList();
+ }
+}
+
+/*insert this polygon into the head of the old polygon List*/
+directedLine* directedLine::insertPolygon(directedLine* oldList)
+{
+ /*this polygon is a root*/
+ setRootBit();
+ if(oldList == NULL) return this;
+ nextPolygon = oldList;
+/* oldList->prevPolygon = this;*/
+ return this;
+}
+
+/*cutoff means delete. but we don't deallocate any space,
+ *so we use cutoff instead of delete
+ */
+directedLine* directedLine::cutoffPolygon(directedLine *p)
+{
+ directedLine* temp;
+ directedLine* prev_polygon = NULL;
+ if(p == NULL) return this;
+
+ for(temp=this; temp != p; temp = temp->nextPolygon)
+ {
+ if(temp == NULL)
+ {
+ fprintf(stderr, "in cutoffPolygon, not found\n");
+ exit(1);
+ }
+ prev_polygon = temp;
+ }
+
+/* prev_polygon = p->prevPolygon;*/
+
+ p->resetRootBit();
+ if(prev_polygon == NULL) /*this is the one to cutoff*/
+ return nextPolygon;
+ else {
+ prev_polygon->nextPolygon = p->nextPolygon;
+ return this;
+ }
+}
+
+Int directedLine::numPolygons()
+{
+ if(nextPolygon == NULL) return 1;
+ else return 1+nextPolygon->numPolygons();
+}
+
+
+/*let array[index ...] denote
+ *all the edges in this polygon
+ *return the next available index of array.
+ */
+Int directedLine::toArraySinglePolygon(directedLine** array, Int index)
+{
+ directedLine *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+/*the space is allocated. The caller is responsible for
+ *deallocate the space.
+ *total_num_edges is set to be the total number of edges of all polygons
+ */
+directedLine** directedLine::toArrayAllPolygons(Int& total_num_edges)
+{
+ total_num_edges=numEdgesAllPolygons();
+ directedLine** ret = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(ret);
+
+ directedLine *temp;
+ Int index = 0;
+ for(temp=this; temp != NULL; temp=temp->nextPolygon) {
+ index = temp->toArraySinglePolygon(ret, index);
+ }
+ return ret;
+}
+
+/*assume the polygon is a simple polygon, return
+ *the area enclosed by it.
+ *if thee order is counterclock wise, the area is positive.
+ */
+Real directedLine::polyArea()
+{
+ directedLine* temp;
+ Real ret=0.0;
+ Real x1,y1,x2,y2;
+ x1 = this->head()[0];
+ y1 = this->head()[1];
+ x2 = this->next->head()[0];
+ y2 = this->next->head()[1];
+ ret = -(x2*y1-x1*y2);
+ for(temp=this->next; temp!=this; temp = temp->next)
+ {
+ x1 = temp->head()[0];
+ y1 = temp->head()[1];
+ x2 = temp->next->head()[0];
+ y2 = temp->next->head()[1];
+ ret += -( x2*y1-x1*y2);
+ }
+ return Real(0.5)*ret;
+}
+
+/*******************split or combine polygons begin********************/
+/*conect a diagonal of a single simple polygon or two simple polygons.
+ *If the two vertices v1 (head) and v2 (head) are in the same simple polygon,
+ *then we actually split the simple polygon into two polygons.
+ *If instead two vertices velong to two difference polygons,
+ *then we combine the two polygons into one polygon.
+ *It is upto the caller to decide whether this is a split or a
+ *combination.
+ *
+ *Case Split:
+ *split a single simple polygon into two simple polygons by
+ *connecting a diagonal (two vertices).
+ *v1, v2: the two vertices are the head() of the two directedLines.
+ * this routine generates one new sampledLine which is returned in
+ *generatedLine,
+ *and it generates two directedLines returned in ret_p1 and ret_p2.
+ *ret_p1 and ret_p2 are used as the entry to the two new polygons.
+ *Notice the caller should not deallocate the space of v2 and v2 after
+ *calling this function, since all of the edges are connected to
+ *ret_p1 or ret_p2.
+ *
+ *combine:
+ *combine two simpolygons into one by connecting one diagonal.
+ *the returned polygon is returned in ret_p1.
+ */
+/*ARGSUSED*/
+void directedLine::connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+
+
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+
+
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline);
+
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+ *generatedLine = nsline;
+}
+
+//see the function connectDiangle
+/*ARGSUSED*/
+void directedLine::connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* polygonList )
+{
+ sampledLine *nsline = new sampledLine(2);
+ sampledLine *nsline2 = new sampledLine(2);
+
+ nsline->setPoint(0, v1->head());
+ nsline->setPoint(1, v2->head());
+ nsline2->setPoint(0, v1->head());
+ nsline2->setPoint(1, v2->head());
+
+ /*the increasing line is from v1 head to v2 head*/
+ directedLine* newLineInc = new directedLine(INCREASING, nsline);
+
+ directedLine* newLineDec = new directedLine(DECREASING, nsline2);
+
+ directedLine* v1Prev = v1->prev;
+ directedLine* v2Prev = v2->prev;
+
+ v1 ->prev = newLineDec;
+ v2Prev ->next = newLineDec;
+ newLineDec->next = v1;
+ newLineDec->prev = v2Prev;
+
+ v2 ->prev = newLineInc;
+ v1Prev ->next = newLineInc;
+ newLineInc->next = v2;
+ newLineInc->prev = v1Prev;
+
+ *ret_p1 = newLineDec;
+ *ret_p2 = newLineInc;
+
+}
+
+Int directedLine::samePolygon(directedLine* v1, directedLine* v2)
+{
+ if(v1 == v2) return 1;
+ directedLine *temp;
+ for(temp = v1->next; temp != v1; temp = temp->next)
+ {
+ if(temp == v2) return 1;
+ }
+ return 0;
+}
+
+directedLine* directedLine::findRoot()
+{
+ if(rootBit) return this;
+ directedLine* temp;
+ for(temp = next; temp != this; temp = temp->next)
+ if(temp -> rootBit ) return temp;
+ return NULL; /*should not happen*/
+}
+
+directedLine* directedLine::rootLinkFindRoot()
+{
+ directedLine* tempRoot;
+ directedLine* tempLink;
+ tempRoot = this;
+ tempLink = rootLink;
+ while(tempLink != NULL){
+ tempRoot = tempLink;
+ tempLink = tempRoot->rootLink;
+ }
+ return tempRoot;
+}
+
+/*******************split or combine polygons end********************/
+
+/*****************IO stuff begin*******************/
+
+/*format:
+ *#polygons
+ * #vertices
+ * vertices
+ * #vertices
+ * vertices
+ *...
+ */
+void directedLine::writeAllPolygons(char* filename)
+{
+ FILE* fp = fopen(filename, "w");
+ assert(fp);
+ Int nPolygons = numPolygons();
+ directedLine *root;
+ fprintf(fp, "%i\n", nPolygons);
+ for(root = this; root != NULL; root = root->nextPolygon)
+ {
+ directedLine *temp;
+ Int npoints=0;
+ npoints = root->get_npoints()-1;
+ for(temp = root->next; temp != root; temp=temp->next)
+ npoints += temp->get_npoints()-1;
+ fprintf(fp, "%i\n", npoints/*root->numEdges()*/);
+
+
+ for(Int i=0; i<root->get_npoints()-1; i++){
+ fprintf(fp, "%f ", root->getVertex(i)[0]);
+ fprintf(fp, "%f ", root->getVertex(i)[1]);
+ }
+
+ for(temp=root->next; temp != root; temp = temp->next)
+ {
+ for(Int i=0; i<temp->get_npoints()-1; i++){
+
+ fprintf(fp, "%f ", temp->getVertex(i)[0]);
+ fprintf(fp, "%f ", temp->getVertex(i)[1]);
+ }
+ fprintf(fp,"\n");
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+}
+
+directedLine* readAllPolygons(char* filename)
+{
+ Int i,j;
+ FILE* fp = fopen(filename, "r");
+ assert(fp);
+ Int nPolygons;
+ fscanf(fp, "%i", &nPolygons);
+ directedLine *ret = NULL;
+
+ for(i=0; i<nPolygons; i++)
+ {
+ Int nEdges;
+ fscanf(fp, "%i", &nEdges);
+ Real vert[2][2];
+ Real VV[2][2];
+ /*the first two vertices*/
+ fscanf(fp, "%f", &(vert[0][0]));
+ fscanf(fp, "%f", &(vert[0][1]));
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ VV[1][0] = vert[0][0];
+ VV[1][1] = vert[0][1];
+ sampledLine *sLine = new sampledLine(2, vert);
+ directedLine *thisPoly = new directedLine(INCREASING, sLine);
+thisPoly->rootLinkSet(NULL);
+
+ directedLine *dLine;
+ for(j=2; j<nEdges; j++)
+ {
+ vert[0][0]=vert[1][0];
+ vert[0][1]=vert[1][1];
+ fscanf(fp, "%f", &(vert[1][0]));
+ fscanf(fp, "%f", &(vert[1][1]));
+ sLine = new sampledLine(2,vert);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+ }
+
+ VV[0][0]=vert[1][0];
+ VV[0][1]=vert[1][1];
+ sLine = new sampledLine(2,VV);
+ dLine = new directedLine(INCREASING, sLine);
+dLine->rootLinkSet(thisPoly);
+ thisPoly->insert(dLine);
+
+ ret = thisPoly->insertPolygon(ret);
+ }
+ fclose(fp);
+ return ret;
+}
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h
new file mode 100644
index 000000000..4ed0128ca
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/directedLine.h
@@ -0,0 +1,171 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _DIRECTEDLINE_H
+#define _DIRECTEDLINE_H
+
+#include "definitions.h"
+#include "sampledLine.h"
+
+enum {INCREASING, DECREASING};
+
+class directedLine {
+ short direction; /*INCREASING or DECREASING*/
+ sampledLine* sline;
+ directedLine* next; /*double linked list*/
+ directedLine* prev; /*double linked list*/
+
+ /*in case we need a list of polygons each
+ *consisting of a double linked list
+ */
+ directedLine* nextPolygon;
+
+ /*optimization make cutoff polygon faster*/
+/* directedLine* prevPolygon;*/
+
+ Int rootBit; /*1 if this is a root of the polygon, set by setRootBit*/
+ /*and reset by resetRootBit()*/
+
+ directedLine* rootLink; /*fast root-finding*/
+
+
+
+public:
+ directedLine(short dir, sampledLine* sl);
+ directedLine();
+ ~directedLine();
+
+ void init(short dir, sampledLine* sl);
+
+ Real* head(); /*points[0] if INCREASING, points[n-1] otherwise*/
+ Real* tail(); /*points[n-1] if INCREASING, points[0] otherwise*/
+ Real* getVertex(Int i); /*points[i] if INCREASING, points[n-1-i] otherwise*/
+ Int get_npoints() {return sline->get_npoints();}
+ directedLine* getPrev() {return prev;}
+ directedLine* getNext() {return next;}
+ directedLine* getNextPolygon() {return nextPolygon;}
+ sampledLine* getSampledLine() {return sline;}
+
+ short getDirection(){return direction;}
+ void putDirection(short dir) {direction = dir;}
+ void putPrev(directedLine *p) {prev = p;}
+ void putNext(directedLine *p) {next = p;}
+
+ /*insert a new line between prev and this*/
+ void insert(directedLine* nl);
+
+ /*delete all the polygons following the link: nextPolygon.
+ *notice that sampledLine is not deleted. The caller is
+ *responsible for that
+ */
+ void deletePolygonList();
+ void deleteSinglePolygon();
+
+ void deleteSinglePolygonWithSline(); //also delete sanmpled line
+ void deletePolygonListWithSline(); //also delete sanmpled line
+
+ void deleteSingleLine(directedLine* dline);
+ directedLine* deleteDegenerateLines();
+ directedLine* deleteDegenerateLinesAllPolygons();
+ directedLine* cutIntersectionAllPoly(int& cutOccur);
+
+ /*check to see if the list forms a closed polygon
+ *return 1 if yes
+ */
+ short isPolygon();
+
+ Int compInY(directedLine* nl);
+ Int compInX(directedLine* nl);
+
+ /*return an array of pointers.
+ *the
+ */
+ directedLine** sortAllPolygons();
+
+ Int numEdges();
+ Int numEdgesAllPolygons();
+ Int numPolygons();
+
+ /*check if the head of this edge is connected to
+ *the tail of the prev
+ */
+ short isConnected();
+
+ Real polyArea();
+
+ void printSingle();
+ void printList();
+ void printAllPolygons();
+ void writeAllPolygons(char* filename);
+
+
+ /*insert a polygon: using nextPolygon*/
+ directedLine* insertPolygon(directedLine* newpolygon);
+ directedLine* cutoffPolygon(directedLine *p);
+
+ Int toArraySinglePolygon(directedLine** array, Int index);
+ directedLine** toArrayAllPolygons(Int& total_num_edges);
+
+ void connectDiagonal(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ sampledLine** generatedLine, directedLine* list);
+
+ /*generate two slines
+ */
+ void connectDiagonal_2slines(directedLine* v1, directedLine* v2,
+ directedLine** ret_p1,
+ directedLine** ret_p2,
+ directedLine* list);
+
+ Int samePolygon(directedLine* v1, directedLine* v2);
+ void setRootBit() {rootBit = 1;}
+ void resetRootBit() {rootBit = 0;}
+ directedLine* findRoot();
+
+ void rootLinkSet(directedLine* r) {rootLink = r;}
+ directedLine* rootLinkFindRoot();
+
+ //the chain from begin to end is deleted (the space is deallocated)
+ //and a new edge(which connectes the head of begin and the tail of end)
+ // is inserted. The new polygon is returned.
+ //notice that "this" is arbitrary
+ directedLine* deleteChain(directedLine* begin, directedLine* end);
+};
+
+directedLine* readAllPolygons(char* filename);
+
+extern Int compV2InY(Real A[2], Real B[2]);
+extern Int compV2InX(Real A[2], Real B[2]);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h
new file mode 100644
index 000000000..6e69feb40
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/glimports.h
@@ -0,0 +1,42 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * glimports.h
+ *
+ */
+
+#ifndef __gluimports_h_
+#define __gluimports_h_
+
+#include "mystdlib.h"
+#include "mystdio.h"
+
+#endif /* __gluimports_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
new file mode 100644
index 000000000..3c92039ba
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.cc
@@ -0,0 +1,293 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+#include "zlassert.h"
+#include "gridWrap.h"
+
+
+/*******************grid structure****************************/
+void gridWrap::print()
+{
+ printf("n_ulines = %i\n", n_ulines);
+ printf("n_vlines = %i\n", n_vlines);
+ printf("u_min=%f, umax=%f, vmin=%f, vmax=%f\n", u_min, u_max, v_min, v_max);
+}
+
+gridWrap::gridWrap(Int nUlines, Real* uvals,
+ Int nVlines, Real* vvals)
+{
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+
+ is_uniform = 0;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uvals[0];
+ u_max = uvals[nUlines-1];
+ v_min = vvals[0];
+ v_max = vvals[nVlines-1];
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ for(i=0; i<n_ulines; i++)
+ u_values[i] = uvals[i];
+ for(i=0; i<n_vlines; i++)
+ v_values[i] = vvals[i];
+}
+
+gridWrap::gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ )
+{
+ is_uniform = 1;
+ n_ulines = nUlines;
+ n_vlines = nVlines;
+ u_min = uMin;
+ u_max = uMax;
+ v_min = vMin;
+ v_max = vMax;
+ u_values = (Real*) malloc(sizeof(Real) * n_ulines);
+ assert(u_values);
+ v_values = (Real*) malloc(sizeof(Real) * n_vlines);
+ assert(v_values);
+
+ Int i;
+ assert(nUlines>=2);
+ assert(nVlines>=2);
+ Real du = (uMax-uMin)/(nUlines-1);
+ Real dv = (vMax-vMin)/(nVlines-1);
+
+ float tempu=uMin;
+ u_values[0] = tempu;
+ for(i=1; i<nUlines; i++)
+ {
+ tempu += du;
+ u_values[i] = tempu;
+ }
+ u_values[nUlines-1] = uMax;
+
+ float tempv=vMin;
+ v_values[0] = tempv;
+ for(i=1; i<nVlines; i++)
+ {
+ tempv += dv;
+ v_values[i] = tempv;
+ }
+ v_values[nVlines-1] = vMax;
+}
+
+gridWrap::~gridWrap()
+{
+ free(u_values);
+ free(v_values);
+}
+
+void gridWrap::draw()
+{
+ int i,j;
+ glBegin(GL_POINTS);
+ for(i=0; i<n_ulines; i++)
+ for(j=0; j<n_vlines; j++)
+ glVertex2f(get_u_value(i), get_v_value(j));
+ glEnd();
+}
+
+void gridWrap::outputFanWithPoint(Int v, Int uleft, Int uright, Real vert[2], primStream* pStream)
+{
+ Int i;
+ if(uleft >= uright)
+ return; //no triangles to output.
+
+ pStream->begin();
+ pStream->insert(vert);
+
+ assert(vert[1] != v_values[v]); //don't output degenerate triangles
+
+ if(vert[1] > v_values[v]) //vertex is above this grid line: notice the orientation
+ {
+ for(i=uleft; i<=uright; i++)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+ else //vertex is below the grid line
+ {
+ for(i=uright; i>= uleft; i--)
+ pStream->insert(u_values[i], v_values[v]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+
+
+/*each chain stores a number of consecutive
+ *V-lines within a grid.
+ *There is one grid vertex on each V-line.
+ * The total number of V-lines is:
+ * nVlines.
+ * with respect to the grid, the index of the first V-line is
+ * firstVlineIndex.
+ * So with respect to the grid, the index of the ith V-line is
+ * firstVlineIndex-i.
+ * the grid-index of the uline at the ith vline (recall that each vline has one grid point)
+ * is ulineIndices[i]. The u_value is cached in ulineValues[i], that is,
+ * ulineValues[i] = grid->get_u_value(ulineIndices[i])
+ */
+gridBoundaryChain::gridBoundaryChain(
+ gridWrap* gr,
+ Int first_vline_index,
+ Int n_vlines,
+ Int* uline_indices,
+ Int* inner_indices
+ )
+: grid(gr), firstVlineIndex(first_vline_index), nVlines(n_vlines)
+{
+ ulineIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(ulineIndices);
+
+ innerIndices = (Int*) malloc(sizeof(Int) * n_vlines);
+ assert(innerIndices);
+
+ vertices = (Real2*) malloc(sizeof(Real2) * n_vlines);
+ assert(vertices);
+
+
+
+ Int i;
+ for(i=0; i<n_vlines; i++){
+ ulineIndices[i] = uline_indices[i];
+ innerIndices[i] = inner_indices[i];
+ }
+
+ for(i=0; i<n_vlines; i++){
+ vertices[i][0] = gr->get_u_value(ulineIndices[i]);
+ vertices[i][1] = gr->get_v_value(first_vline_index-i);
+ }
+}
+
+void gridBoundaryChain::draw()
+{
+ Int i;
+ glBegin(GL_LINE_STRIP);
+ for(i=0; i<nVlines; i++)
+ {
+ glVertex2fv(vertices[i]);
+ }
+ glEnd();
+}
+
+void gridBoundaryChain::drawInner()
+{
+ Int i;
+ for(i=1; i<nVlines; i++)
+ {
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i-1) );
+ glVertex2f(grid->get_u_value(innerIndices[i]), get_v_value(i) );
+ glEnd();
+ }
+}
+
+Int gridBoundaryChain::lookfor(Real v, Int i1, Int i2)
+{
+ Int mid;
+ while(i1 < i2-1)
+ {
+ mid = (i1+i2)/2;
+ if(v > vertices[mid][1])
+ {
+ i2 = mid;
+ }
+ else
+ i1 = mid;
+ }
+ return i1;
+}
+
+/*output the fan of the right end between grid line i-1 and grid line i*/
+void gridBoundaryChain::rightEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i-1); j<= getUlineIndex(i); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i-1); j>= getUlineIndex(i); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ //otherside, the two are equal, so there is no fan to output
+}
+
+
+/*output the fan of the left end between grid line i-1 and grid line i*/
+void gridBoundaryChain::leftEndFan(Int i, primStream* pStream)
+{
+ Int j;
+ if(getUlineIndex(i) < getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i-1));
+ for(j=getUlineIndex(i); j<= getUlineIndex(i-1); j++)
+ pStream->insert(grid->get_u_value(j), get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(getUlineIndex(i) > getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(get_vertex(i));
+ for(j=getUlineIndex(i); j>= getUlineIndex(i-1); j--)
+ pStream->insert(grid->get_u_value(j), get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
new file mode 100644
index 000000000..b6428484f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/gridWrap.h
@@ -0,0 +1,137 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _GRIDWRAP_H
+#define _GRIDWRAP_H
+
+#include <stdio.h>
+#include "definitions.h"
+
+#include "primitiveStream.h"
+#include "zlassert.h"
+
+class gridWrap{
+ Int n_ulines;
+ Int n_vlines;
+ Real u_min, u_max;
+ Real v_min, v_max;
+
+ /*cache the coordinate values for efficiency.
+ *these are redundant information when
+ *the grid is uniform.
+ */
+ Real* u_values; /*size is n_ulines*/
+ Real* v_values; /*size is n_vlines*/
+
+ Int is_uniform;
+
+public:
+ //uniform grid constructor
+ gridWrap(Int nUlines, Int nVlines,
+ Real uMin, Real uMax,
+ Real vMin, Real vMax
+ );
+
+ //nonuniform grid constructor.
+ gridWrap(Int nUlines, Real *uvals,
+ Int nVlines, Real *vvlas
+ );
+ ~gridWrap();
+
+ void print();
+ Int get_n_ulines() {return n_ulines;}
+ Int get_n_vlines() {return n_vlines;}
+ Real get_u_min() {return u_min;}
+ Real get_u_max() {return u_max;}
+ Real get_v_min() {return v_min;}
+ Real get_v_max() {return v_max;}
+
+ Real get_u_value(Int i)
+ {
+ assert(i<n_ulines);
+ /*if(i>=n_ulines){printf("ERROR, n_ulines=%i,i=%i\n",n_ulines,i);exit(0);}*/
+ return u_values[i];}
+ Real get_v_value(Int j) {return v_values[j];}
+
+ Real* get_u_values() {return u_values;}
+ Real* get_v_values() {return v_values;}
+
+ void outputFanWithPoint(Int v, Int uleft, Int uright,
+ Real vert[2], primStream* pStream);
+
+ void draw();
+
+ Int isUniform() {return is_uniform;}
+};
+
+class gridBoundaryChain{
+ gridWrap* grid;
+ Int firstVlineIndex;
+ Int nVlines;
+ Int* ulineIndices; /*each v line has a boundary*/
+ Int* innerIndices; /*the segment of the vertical gridline from */
+ /*(innerIndices[i], i) to (innerIndices[i+1], i-1) */
+ /*is inside the polygon: i=1,...,nVlines-1*/
+
+ Real2* vertices; /*one grid point at each grid V-line, cached for efficiency*/
+
+public:
+ gridBoundaryChain(gridWrap* gr, Int first_vline_index, Int n_vlines, Int* uline_indices, Int* inner_indices);
+
+ ~gridBoundaryChain()
+ {
+ free(innerIndices);
+ free(ulineIndices);
+ free(vertices);
+ }
+
+ /*i indexes the vlines in this chain.
+ */
+ Int getVlineIndex(Int i) {return firstVlineIndex-i;}
+ Int getUlineIndex(Int i) {return ulineIndices[i];}
+ Real get_u_value(Int i) {return vertices[i][0];}
+ Real get_v_value(Int i) {return vertices[i][1];}
+ Int get_nVlines() {return nVlines;}
+ Int getInnerIndex(Int i) {return innerIndices[i];}
+ Real getInner_u_value(Int i) {return grid->get_u_value(innerIndices[i]);}
+
+ Real* get_vertex(Int i) {return vertices[i];}
+ gridWrap* getGrid() {return grid;}
+ void leftEndFan(Int i, primStream* pStream);
+ void rightEndFan(Int i, primStream* pStream);
+
+ Int lookfor(Real v, Int i1, Int i2); //find i in [i1,i2] so that vertices[i][1]>= v > vertices[i+1][1]
+ void draw();
+ void drawInner();
+};
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
new file mode 100644
index 000000000..814bf32fa
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.cc
@@ -0,0 +1,934 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoChain.h"
+#include "quicksort.h"
+#include "searchTree.h"
+#include "polyUtil.h"
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+extern Int isCusp(directedLine *v);
+extern Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices);
+
+//for debug purpose only
+#if 0 // UNUSED
+static void drawDiagonals(Int num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i;
+ for(i=0; i<num_diagonals; i++)
+ {
+ glBegin(GL_LINE);
+ glVertex2fv(diagonal_vertices[2*i]->head());
+ glVertex2fv(diagonal_vertices[2*i+1]->head());
+ glEnd();
+ }
+}
+#endif
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*0.5 : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+}
+
+//compare the heads of the two chains
+static int compChainHeadInY(monoChain* mc1, monoChain* mc2)
+{
+ return compV2InY(mc1->getHead()->head(), mc2->getHead()->head());
+}
+
+monoChain::monoChain(directedLine* cHead, directedLine* cTail)
+{
+ chainHead = cHead;
+ chainTail = cTail;
+ next = this;
+ prev = this;
+
+ nextPolygon = NULL;
+
+ //compute bounding box
+ directedLine* temp;
+ minX = maxX = chainTail->head()[0];
+ minY = maxY = chainTail->head()[1];
+
+ for(temp=chainHead; temp!=cTail; temp = temp->getNext())
+ {
+ if(temp->head()[0] < minX)
+ minX = temp->head()[0];
+ if(temp->head()[0] > maxX)
+ maxX = temp->head()[0];
+
+ if(temp->head()[1] < minY)
+ minY = temp->head()[1];
+ if(temp->head()[1] > maxY)
+ maxY = temp->head()[1];
+ }
+
+ //check whether the chain is increasing or decreasing
+ if(chainHead->compInY(chainTail) <0)
+ isIncrease = 1;
+ else
+ isIncrease = 0;
+
+ //initilize currrent, this is used for accelerating search
+ if(isIncrease)
+ current = chainHead;
+ else
+ current = chainTail;
+
+ isKey = 0;
+}
+
+//insert a new line between prev and this
+void monoChain::insert(monoChain* nc)
+{
+ nc->next = this;
+ nc->prev = prev;
+ prev->next = nc;
+ prev = nc;
+}
+
+void monoChain::deleteLoop()
+{
+ monoChain *temp, *tempNext;
+ prev->next = NULL;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+void monoChain::deleteLoopList()
+{
+ monoChain *temp, *tempNext;
+ for(temp=this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->nextPolygon;
+ temp->deleteLoop();
+ }
+}
+
+Int monoChain::toArraySingleLoop(monoChain** array, Int index)
+{
+ monoChain *temp;
+ array[index++] = this;
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ array[index++] = temp;
+ }
+ return index;
+}
+
+monoChain** monoChain::toArrayAllLoops(Int& num_chains)
+{
+ num_chains = numChainsAllLoops();
+ monoChain **ret = (monoChain**) malloc(sizeof(monoChain*) * num_chains);
+ assert(ret);
+ monoChain *temp;
+ Int index = 0;
+ for(temp = this; temp != NULL; temp=temp->nextPolygon){
+ index = temp->toArraySingleLoop(ret, index);
+ }
+ return ret;
+}
+
+Int monoChain::numChainsSingleLoop()
+{
+ Int ret=0;
+ monoChain* temp;
+ if(next == this) return 1;
+ ret = 1;
+ for(temp=next; temp != this; temp = temp->next)
+ ret++;
+ return ret;
+}
+
+Int monoChain::numChainsAllLoops()
+{
+ Int ret=0;
+ monoChain *temp;
+ for(temp =this; temp != NULL; temp = temp->nextPolygon)
+ ret += temp->numChainsSingleLoop();
+ return ret;
+}
+
+//update 'current'
+Real monoChain::chainIntersectHoriz(Real y)
+{
+ directedLine* temp;
+ if(isIncrease)
+ {
+ for(temp= current; temp != chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ }
+ else
+ {
+ for(temp = current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ }
+ return intersectHoriz(current->head()[0], current->head()[1], current->tail()[0], current->tail()[1], y);
+}
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop)
+{
+ directedLine *temp;
+ monoChain *ret=NULL;
+
+ //find the first cusp
+ directedLine *prevCusp=NULL;
+ directedLine *firstCusp;
+
+ if(isCusp(loop))
+ prevCusp = loop;
+ else
+ {
+ for(temp = loop->getNext(); temp != loop; temp = temp->getNext())
+ if(isCusp(temp))
+ break;
+ prevCusp = temp;
+ }
+ firstCusp = prevCusp;
+//printf("first cusp is (%f,%f), (%f,%f), (%f,%f)\n", prevCusp->getPrev()->head()[0], prevCusp->getPrev()->head()[1], prevCusp->head()[0], prevCusp->head()[1], prevCusp->tail()[0], prevCusp->tail()[1]);
+
+ for(temp = prevCusp->getNext(); temp != loop; temp = temp->getNext())
+ {
+ if(isCusp(temp))
+ {
+//printf("the cusp is (%f,%f), (%f,%f), (%f,%f)\n", temp->getPrev()->head()[0], temp->getPrev()->head()[1], temp->head()[0], temp->head()[1], temp->tail()[0], temp->tail()[1]);
+ if(ret == NULL)
+ {
+ ret = new monoChain(prevCusp, temp);
+ }
+ else
+ ret->insert(new monoChain(prevCusp, temp));
+ prevCusp = temp;
+ }
+ }
+ ret->insert(new monoChain(prevCusp, firstCusp));
+
+ return ret;
+}
+
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list)
+{
+ directedLine* temp;
+ monoChain* mc;
+ monoChain* mcEnd;
+ mc = directedLineLoopToMonoChainLoop(list);
+ mcEnd = mc;
+ for(temp = list->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoChain *newLoop = directedLineLoopToMonoChainLoop(temp);
+ mcEnd->setNextPolygon(newLoop);
+ mcEnd = newLoop;
+ }
+ return mc;
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = 0.5*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+Int compChains(monoChain* mc1, monoChain* mc2)
+{
+ Real y;
+ assert(mc1->isKey || mc2->isKey);
+ if(mc1->isKey)
+ y = mc1->keyY;
+ else
+ y = mc2->keyY;
+ directedLine *d1 = mc1->find(y);
+ directedLine *d2 = mc2->find(y);
+ mc2->find(y);
+// Real x1 = mc1->chainIntersectHoriz(y);
+// Real x2 = mc2->chainIntersectHoriz(y);
+ return compEdges(d1, d2);
+}
+
+//this function modifies current for efficiency
+directedLine* monoChain::find(Real y)
+{
+ directedLine *ret;
+ directedLine *temp;
+ assert(current->head()[1] <= y);
+ if(isIncrease)
+ {
+ assert(chainTail->head()[1] >=y);
+ for(temp=current; temp!=chainTail; temp = temp->getNext())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getPrev();
+ ret = current;
+ }
+ else
+ {
+ for(temp=current; temp != chainHead; temp = temp->getPrev())
+ {
+ if(temp->head()[1] > y)
+ break;
+ }
+ current = temp->getNext();
+ ret = temp;
+ }
+ return ret;
+}
+
+void monoChain::printOneChain()
+{
+ directedLine* temp;
+ for(temp = chainHead; temp != chainTail; temp = temp->getNext())
+ {
+ printf("(%f,%f) ", temp->head()[0], temp->head()[1]);
+ }
+ printf("(%f,%f) \n", chainTail->head()[0], chainTail->head()[1]);
+}
+
+void monoChain::printChainLoop()
+{
+ monoChain* temp;
+ this->printOneChain();
+ for(temp = next; temp != this; temp = temp->next)
+ {
+ temp->printOneChain();
+ }
+ printf("\n");
+}
+
+void monoChain::printAllLoops()
+{
+ monoChain* temp;
+ for(temp=this; temp != NULL; temp = temp->nextPolygon)
+ temp->printChainLoop();
+}
+
+//return 1 if error occures
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ Real keyY;
+ Int errOccur=0;
+//printf("enter MC_sweepY\n");
+//printf("nVertices=%i\n", nVertices);
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+//printf("nVertices=%i\n", nVertices);
+ for(i=0; i<nVertices; i++)
+ {
+ monoChain* vert = sortedVertices[i];
+ keyY = vert->getHead()->head()[1]; //the sweep line
+ directedLine *dline = vert->getHead();
+ directedLine *dlinePrev = dline->getPrev();
+ if(isBelow(dline, dline) && isBelow(dline, dlinePrev))
+ {
+//printf("case 1\n");
+ //this<v and prev < v
+ //delete both edges
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ treeNode* thisNode = TreeNodeFind(searchTree, vert, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ treeNode* prevNode = TreeNodeFind(searchTree, vert->getPrev(), (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1)//interior cusp
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+
+ directedLine* leftEdgeDline = ((monoChain* ) leftEdge->key)->find(keyY);
+
+
+
+ directedLine* rightEdgeDline = ((monoChain* ) rightEdge->key)->find(keyY);
+
+ ret_ranges[i] = sweepRangeMake(leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( dline, 1, dlinePrev, 1);
+ }
+
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+
+ }
+ else if(isAbove(dline, dline) && isAbove(dline, dlinePrev))
+ {
+//printf("case 2\n");
+ //insert both edges
+ treeNode* thisNode = TreeNodeMake(vert);
+ treeNode* prevNode = TreeNodeMake(vert->getPrev());
+
+ vert->isKey = 1;
+ vert->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, thisNode, (Int (*) (void *, void *))compChains);
+ vert->isKey = 0;
+
+ vert->getPrev()->isKey = 1;
+ vert->getPrev()->keyY = keyY;
+ searchTree = TreeNodeInsert(searchTree, prevNode, (Int (*) (void *, void *))compChains);
+ vert->getPrev()->isKey = 0;
+
+ if(cuspType(dline) == 1) //interior cusp
+ {
+//printf("cuspType is 1\n");
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ if(leftEdge == NULL || rightEdge == NULL)
+ {
+ errOccur = 1;
+ goto JUMP_HERE;
+ }
+//printf("leftEdge is %i, rightEdge is %i\n", leftEdge, rightEdge);
+ directedLine* leftEdgeDline = ((monoChain*) leftEdge->key)->find(keyY);
+ directedLine* rightEdgeDline = ((monoChain*) rightEdge->key)->find(keyY);
+ ret_ranges[i] = sweepRangeMake( leftEdgeDline, 1, rightEdgeDline, 1);
+ }
+ else //exterior cusp
+ {
+//printf("cuspType is not 1\n");
+ ret_ranges[i] = sweepRangeMake(dlinePrev, 1, dline, 1);
+ }
+ }
+ else
+ {
+//printf("%i,%i\n", isAbove(dline, dline), isAbove(dline, dlinePrev));
+ errOccur = 1;
+ goto JUMP_HERE;
+
+ fprintf(stderr, "error in MC_sweepY\n");
+ exit(1);
+ }
+ }
+
+ JUMP_HERE:
+ //finally clean up space: delete the search tree
+ TreeNodeDeleteWholeTree(searchTree);
+ return errOccur;
+}
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+ k=0;
+ //reset 'current' of all the monoChains
+ for(i=0; i<total_num_edges; i++)
+ sortedVertices[i]->resetCurrent();
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert = sortedVertices[i]->getHead();
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ //this is an upward interior cusp
+ diagonal_vertices[k++] = vert;
+
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+
+ directedLine* leftVert = leftEdge;
+ directedLine* rightVert = rightEdge->getNext();
+ assert(leftVert->head()[1] >= vert->head()[1]);
+ assert(rightVert->head()[1] >= vert->head()[1]);
+ directedLine* minVert = (leftVert->head()[1] <= rightVert->head()[1])?leftVert:rightVert;
+ Int found = 0;
+ for(j=i+1; j<total_num_edges; j++)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] > minVert->head()[1])
+ break;
+
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = minVert;
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ //downward interior cusp
+ diagonal_vertices[k++] = vert;
+ directedLine* leftEdge = ranges[i]->left;
+ directedLine* rightEdge = ranges[i]->right;
+ directedLine* leftVert = leftEdge->getNext();
+ directedLine* rightVert = rightEdge;
+ assert(leftVert->head()[1] <= vert->head()[1]);
+ assert(rightVert->head()[1] <= vert->head()[1]);
+ directedLine* maxVert = (leftVert->head()[1] > rightVert->head()[1])? leftVert:rightVert;
+ Int found=0;
+ for(j=i-1; j>=0; j--)
+ {
+ if(sortedVertices[j]->getHead()->head()[1] < maxVert->head()[1])
+ break;
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ diagonal_vertices[k++] = sortedVertices[j]->getHead();
+ else
+ diagonal_vertices[k++] = maxVert;
+ }
+ }
+ num_diagonals = k/2;
+}
+
+
+
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+//printf("enter mc_partitionY\n");
+ Int total_num_chains = 0;
+ monoChain* loopList = directedLineLoopListToMonoChainLoopList(polygons);
+ monoChain** array = loopList->toArrayAllLoops(total_num_chains);
+
+ if(total_num_chains<=2) //there is just one single monotone polygon
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return polygons;
+ }
+
+//loopList->printAllLoops();
+//printf("total_num_chains=%i\n", total_num_chains);
+ quicksort( (void**)array, 0, total_num_chains-1, (Int (*)(void*, void*))compChainHeadInY);
+//printf("after quicksort\n");
+
+ sweepRange** ranges = (sweepRange**)malloc(sizeof(sweepRange*) * (total_num_chains));
+ assert(ranges);
+
+ if(MC_sweepY(total_num_chains, array, ranges))
+ {
+ loopList->deleteLoopList();
+ free(array);
+ *retSampledLines = NULL;
+ return NULL;
+ }
+//printf("after MC_sweepY\n");
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_chains*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+//printf("before call MC_findDiagonales\n");
+
+ MC_findDiagonals(total_num_chains, array, ranges, num_diagonals, diagonal_vertices);
+//printf("after call MC_findDia, num_diagnla=%i\n", num_diagonals);
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+//drawDiagonals(num_diagonals, diagonal_vertices);
+//printf("diagoanls are \n");
+//for(i=0; i<num_diagonals; i++)
+// {
+// printf("(%f,%f)\n", diagonal_vertices[2*i]->head()[0], diagonal_vertices[2*i]->head()[1]);
+// printf("**(%f,%f)\n", diagonal_vertices[2*i+1]->head()[0], diagonal_vertices[2*i+1]->head()[1]);
+// }
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+// printf("first pass\n");
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+//printf("second pass: \n");
+
+// for(i=0; i<num_diagonals; i++)
+// printf("%i ", removedDiagonals[i]);
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+
+ //clean up
+ loopList->deleteLoopList();
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h
new file mode 100644
index 000000000..999f16319
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoChain.h
@@ -0,0 +1,103 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _MONO_CHAIN_H
+#define _MONO_CHAIN_H
+
+#include "directedLine.h"
+#include "partitionY.h"
+
+class monoChain;
+
+class monoChain{
+ directedLine* chainHead;
+ directedLine* chainTail;
+ monoChain* next;
+ monoChain* prev;
+ monoChain* nextPolygon; //a list of polygons
+
+ //cached informatin
+ //bounding box
+ Real minX, maxX, minY, maxY;
+ Int isIncrease;
+
+ //for efficiently comparing two chains
+
+ directedLine* current;
+
+public:
+ monoChain(directedLine* cHead, directedLine* cTail);
+ ~monoChain() {}
+
+ inline void setNext(monoChain* n) {next = n;}
+ inline void setPrev(monoChain* p) {prev = p;}
+ inline void setNextPolygon(monoChain* np) {nextPolygon = np;}
+ inline monoChain* getNext() {return next;}
+ inline monoChain* getPrev() {return prev;}
+ inline directedLine* getHead() {return chainHead;}
+ inline directedLine* getTail() {return chainTail;}
+
+ inline void resetCurrent() { current = ((isIncrease==1)? chainHead:chainTail);}
+
+ void deleteLoop();
+ void deleteLoopList();
+
+ //insert a new chain between prev and this
+ void insert(monoChain* nc);
+
+ Int numChainsSingleLoop();
+ Int numChainsAllLoops();
+ monoChain** toArrayAllLoops(Int& num_chains);
+ Int toArraySingleLoop(monoChain** array, Int index);
+
+ Int isKey;
+ Real keyY; //the current horizotal line
+ Real chainIntersectHoriz(Real y); //updates current incrementally for efficiency
+ directedLine* find(Real y);//find dline so that y intersects dline.
+
+ void printOneChain();
+ void printChainLoop();
+ void printAllLoops();
+
+};
+
+monoChain* directedLineLoopToMonoChainLoop(directedLine* loop);
+monoChain* directedLineLoopListToMonoChainLoopList(directedLine* list);
+Int MC_sweepY(Int nVertices, monoChain** sortedVertices, sweepRange** ret_ranges);
+
+void MC_findDiagonals(Int total_num_edges, monoChain** sortedVertices,
+ sweepRange** ranges, Int& num_diagonals,
+ directedLine** diagonal_vertices);
+
+directedLine* MC_partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
new file mode 100644
index 000000000..8391205bf
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.cc
@@ -0,0 +1,299 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+ *monoPolyPart.C
+ *
+ *To partition a v-monotone polygon into some uv-monotone polygons.
+ *The algorithm is different from the general monotone partition algorithm.
+ *while the general monotone partition algorithm works for this special case,
+ *but it is more expensive (O(nlogn)). The algorithm implemented here takes
+ *advantage of the fact that the input is a v-monotone polygon and it is
+ *conceptually simpler and computationally cheaper (a linear time algorithm).
+ *The algorithm is described in Zicheng Liu's paper
+ * "Quality-Oriented Linear Time Tessellation".
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "directedLine.h"
+#include "monoPolyPart.h"
+
+/*a vertex is u_maximal if both of its two neightbors are to the left of this
+ *vertex
+ */
+static Int is_u_maximal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == -1 &&
+ compV2InX(v->getNext()->head(), v->head()) == -1)
+ return 1;
+ else
+ return 0;
+}
+
+/*a vertex is u_minimal if both of its two neightbors are to the right of this
+ *vertex
+ */
+static Int is_u_minimal(directedLine* v)
+{
+ if (compV2InX(v->getPrev()->head(), v->head()) == 1 &&
+ compV2InX(v->getNext()->head(), v->head()) == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*poly: a v-monotone polygon
+ *return: a linked list of uv-monotone polygons.
+ */
+directedLine* monoPolyPart(directedLine* polygon)
+{
+ //handle special cases:
+ if(polygon == NULL)
+ return NULL;
+ if(polygon->getPrev() == polygon)
+ return polygon;
+ if(polygon->getPrev() == polygon->getNext())
+ return polygon;
+ if(polygon->getPrev()->getPrev() == polygon->getNext())
+ return polygon;
+
+ //find the top and bottom vertexes
+ directedLine *tempV, *topV, *botV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ //initilization
+ directedLine *A, *B, *C, *D, *G, *H;
+ //find A:the first u_maximal vertex on the left chain
+ //and C: the left most vertex between top and A
+ A = NULL;
+ C = topV;
+ for(tempV=topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+ if(A == NULL)
+ {
+ A = botV;
+ if(A->head()[0] < C->head()[0])
+ C = A;
+ }
+
+ //find B: the first u_minimal vertex on the right chain
+ //and D: the right most vertex between top and B
+ B = NULL;
+ D = topV;
+ for(tempV=topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(B == NULL)
+ {
+ B = botV;
+ if(B->head()[0] > D->head()[0])
+ D = B;
+ }
+
+ //error checking XXX
+ if(C->head()[0] >= D->head()[0])
+ return polygon;
+
+ //find G on the left chain that is right above B
+ for(tempV=topV; compV2InY(tempV->head(), B->head()) == 1; tempV=tempV->getNext());
+ G = tempV->getPrev();
+ //find H on the right chain that is right above A
+ for(tempV=topV; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+
+ //Main Loop
+ directedLine* ret = NULL;
+ directedLine* currentPolygon = polygon;
+ while(1)
+ {
+ //if both B and D are equal to botV, then this polygon is already
+ //u-monotone
+ if(A == botV && B == botV)
+ {
+ ret = currentPolygon->insertPolygon(ret);
+ return ret;
+ }
+ else //not u-monotone
+ {
+ directedLine *ret_p1, *ret_p2;
+ if(compV2InY(A->head(),B->head()) == 1) //A is above B
+ {
+ directedLine* E = NULL;
+ for(tempV = C; tempV != D; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] >= A->head()[0])
+ {
+ E = tempV;
+ break;
+ }
+ }
+
+ if(E == NULL)
+ E = D;
+ if(E->head()[0]> H->head()[0])
+ E = H;
+ //connect AE and output polygon ECA
+ polygon->connectDiagonal_2slines(A, E,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+
+ if(E == D)
+ D = ret_p1;
+ if(E == H)
+ H = ret_p1;
+ if(G->head()[1] >= A->head()[1])
+ G = A;
+ //update A to be the next u-maxiaml vertex on left chain
+ //and C the leftmost vertex between the old A and the new A
+ C = A;
+ for(tempV = A->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+
+ if(tempV->head()[0] < C->head()[0])
+ C = tempV;
+ if(is_u_maximal(tempV))
+ {
+ A = tempV;
+ break;
+ }
+ }
+
+ if(tempV == botV)
+ {
+ A = botV;
+ if(botV->head()[0] < C->head()[0])
+ C = botV;
+ }
+ //update H
+
+ if(A == botV)
+ H = botV;
+ else
+ {
+ for(tempV = H; compV2InY(tempV->head(), A->head()) == 1; tempV = tempV->getPrev());
+ H = tempV->getNext();
+ }
+
+ }
+ else //A is below B
+ {
+
+ directedLine* F = NULL;
+ for(tempV = D; tempV != C; tempV = tempV->getNext())
+ {
+ if(tempV->head()[0] <= B->head()[0])
+ {
+ F = tempV;
+ break;
+ }
+ }
+ if(F == NULL)
+ F = C;
+ if(F->head()[0] < G->head()[0])
+ F = G;
+
+ //connect FB
+ polygon->connectDiagonal_2slines(F, B,
+ &ret_p1,
+ &ret_p2,
+ NULL);
+ ret = ret_p2->insertPolygon(ret);
+ currentPolygon = ret_p1;
+ B = ret_p1;
+ if(H ->head()[1] >= B->head()[1])
+ H = ret_p1;
+
+ //update B to be the next u-minimal vertex on right chain
+ //and D the rightmost vertex between the old B and the new B
+ D = B;
+ for(tempV = B->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ if(tempV->head()[0] > D->head()[0])
+ D = tempV;
+ if(is_u_minimal(tempV))
+ {
+ B = tempV;
+ break;
+ }
+ }
+ if(tempV == botV)
+ {
+ B = botV;
+ if(botV->head()[0] > D->head()[0])
+ D = botV;
+ }
+ //update G
+ if(B == botV)
+ G = botV;
+ else
+ {
+ for(tempV = G; compV2InY(tempV->head(), B->head()) == 1; tempV = tempV->getNext());
+ G = tempV->getPrev();
+ }
+ } //end of A is below B
+ } //end not u-monotone
+ } //end of main loop
+}
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
new file mode 100644
index 000000000..6877a59c2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoPolyPart.h
@@ -0,0 +1,41 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+ *monoPolyPart.h
+ */
+
+#ifndef _MONO_POLY_PART_H
+#define _MONO_POLY_PART_H
+
+class directedLine;
+
+directedLine* monoPolyPart(directedLine* polygon);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
new file mode 100644
index 000000000..8e8d49dda
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.cc
@@ -0,0 +1,1482 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+
+#include "monoTriangulation.h"
+#include "polyUtil.h" /*for area*/
+#include "partitionX.h"
+#include "monoPolyPart.h"
+
+
+
+extern directedLine* polygonConvert(directedLine* polygon);
+
+/*poly is NOT deleted
+ */
+void monoTriangulationOpt(directedLine* poly, primStream* pStream)
+{
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ monoTriangulationFun(poly, compV2InY, pStream);
+ }
+
+ free(cusps);
+}
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream)
+{
+ Int i,j;
+ Int n_left = left_chain->getNumElements();
+ Int n_right = right_chain->getNumElements();
+ if(left_current>= n_left-1 ||
+ right_current>= n_right-1)
+ {
+ monoTriangulationRec(topVertex, botVertex, left_chain, left_current,
+ right_chain, right_current, pStream);
+ return;
+ }
+ //now both left and right have at least two vertices each.
+ Real left_v = left_chain->getVertex(left_current)[1];
+ Real right_v = right_chain->getVertex(right_current)[1];
+
+ if(left_v <= right_v) //first left vertex is below right
+ {
+ //find the last vertex of right which is above or equal to left
+ for(j=right_current; j<=n_right-1; j++)
+ {
+ if(right_chain->getVertex(j)[1] < left_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, left_chain->getVertex(left_current),
+ left_chain, left_current, left_current,
+ right_chain, right_current, j-1,
+ pStream);
+ monoTriangulationRecOpt(right_chain->getVertex(j-1),
+ botVertex,
+ left_chain, left_current,
+ right_chain, j,
+ pStream);
+ }
+ else //first right vertex is strictly below left
+ {
+ //find the last vertex of left which is strictly above right
+ for(i=left_current; i<=n_left-1; i++)
+ {
+ if(left_chain->getVertex(i)[1] <= right_v)
+ break;
+ }
+ monoTriangulationRecGen(topVertex, right_chain->getVertex(right_current),
+ left_chain, left_current, i-1,
+ right_chain, right_current, right_current,
+ pStream);
+ monoTriangulationRecOpt(left_chain->getVertex(i-1),
+ botVertex,
+ left_chain, i,
+ right_chain, right_current,
+ pStream);
+ }
+}
+
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_current), dec_chain->getVertex(dec_current));
+
+/*printf("**(%f,%f)\n", inc_chain->getArray()[0][0],inc_chain->getArray()[0][1]);*/
+ triangulateXYMonoTB(inc_end-inc_current+1, inc_chain->getArray()+inc_current, dec_end-dec_current+1, dec_chain->getArray()+dec_current, pStream);
+
+ pStream->triangle(botVertex, dec_chain->getVertex(dec_end), inc_chain->getVertex(inc_end));
+}
+
+
+/*n_left>=1
+ *n_right>=1
+ *the strip is going top to bottom. compared to the funtion
+ * triangulateXYmono()
+ */
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream)
+{
+
+
+ Int i,j,k,l;
+ Real* topMostV;
+
+ assert(n_left>=1 && n_right>=1);
+ if(leftVerts[0][1] >= rightVerts[0][1])
+ {
+ i=1;
+ j=0;
+ topMostV = leftVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ topMostV = rightVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_left) /*case1: no more in left*/
+ {
+
+ if(j<n_right-1) /*at least two vertices in right*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+ for(k=n_right-1; k>=j; k--)
+ pStream->insert(rightVerts[j]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+
+ }
+
+ break;
+ }
+ else if(j>= n_right) /*case2: no more in right*/
+ {
+
+ if(i<n_left-1) /*at least two vertices in left*/
+ {
+ pStream->begin();
+ pStream->insert(topMostV);
+
+ for(k=i; k<n_left; k++)
+ pStream->insert(leftVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the topMostV, there is at least one triangle to output*/
+ {
+
+ if(leftVerts[i][1] >= rightVerts[j][1])
+ {
+ pStream->begin();
+ pStream->insert(rightVerts[j]); /*the origin of this fan*/
+
+ pStream->insert(topMostV);
+
+ /*find the last k>=i such that
+ *leftverts[k][1] >= rightverts[j][1]
+ */
+ k=i;
+ while(k<n_left)
+ {
+ if(leftVerts[k][1] < rightVerts[j][1])
+ break;
+ k++;
+ }
+ k--;
+ for(l=i; l<=k; l++)
+ {
+ pStream->insert(leftVerts[l]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ topMostV = leftVerts[k];
+
+ }
+ else /*leftVerts[i][1] < rightVerts[j][1]*/
+ {
+ pStream->begin();
+ pStream->insert(leftVerts[i]);/*the origion of this fan*/
+
+ /*find the last k>=j such that
+ *rightverts[k][1] > leftverts[i][1]*/
+ k=j;
+ while(k< n_right)
+ {
+ if(rightVerts[k][1] <= leftVerts[i][1])
+ break;
+ k++;
+ }
+ k--;
+
+ for(l=k; l>= j; l--)
+ pStream->insert(rightVerts[l]);
+
+ pStream->insert(topMostV);
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k+1;
+ topMostV = rightVerts[j-1];
+ }
+ }
+ }
+}
+
+static int chainConvex(vertexArray* inc_chain, Int inc_current, Int inc_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(inc_current >= inc_end-1) return 1;
+ for(i=inc_current; i<= inc_end-2; i++)
+ {
+ if(area(inc_chain->getVertex(i), inc_chain->getVertex(i+1), inc_chain->getVertex(i+2)) <0)
+ return 0;
+ }
+ return 1;
+}
+
+static int chainConcave(vertexArray* dec_chain, Int dec_current, Int dec_end)
+{
+ Int i;
+ //if there are no more than 2 vertices, return 1
+ if(dec_current >= dec_end -1) return 1;
+ for(i=dec_current; i<=dec_end-2; i++)
+ {
+ if(area(dec_chain->getVertex(i), dec_chain->getVertex(i+1), dec_chain->getVertex(i+2)) >0)
+ return 0;
+ }
+ return 1;
+}
+
+void monoTriangulationRecGenInU(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+
+}
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Int i;
+ //copy this to a polygon: directedLine Lioop
+ sampledLine* sline;
+ directedLine* dline;
+ directedLine* poly;
+
+ if(inc_current <= inc_end) //at least one vertex in inc_chain
+ {
+ sline = new sampledLine(topVertex, inc_chain->getVertex(inc_current));
+ poly = new directedLine(INCREASING, sline);
+ for(i=inc_current; i<=inc_end-1; i++)
+ {
+ sline = new sampledLine(inc_chain->getVertex(i), inc_chain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(inc_chain->getVertex(inc_end), botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //inc_chian is empty
+ {
+ sline = new sampledLine(topVertex, botVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly = dline;
+ }
+
+ assert(poly != NULL);
+
+ if(dec_current <= dec_end) //at least on vertex in dec_Chain
+ {
+ sline = new sampledLine(botVertex, dec_chain->getVertex(dec_end));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ for(i=dec_end; i>dec_current; i--)
+ {
+ sline = new sampledLine(dec_chain->getVertex(i), dec_chain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ sline = new sampledLine(dec_chain->getVertex(dec_current), topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+ else //dec_chain is empty
+ {
+ sline = new sampledLine(botVertex, topVertex);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ {
+ Int n_cusps;
+ Int n_edges = poly->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*)*n_edges);
+ assert(cusps);
+ findInteriorCuspsX(poly, n_cusps, cusps);
+
+ if(n_cusps ==0) //u monotine
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else if(n_cusps == 1) // one interior cusp
+ {
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+ directedLine* other = findDiagonal_singleCuspX(new_polygon);
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(poly, compV2InX, pStream);
+ }
+ else
+ {
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+ }
+ }
+ else
+ {
+ //we need a general partitionX funtion (supposed to be in partitionX.C,
+ //not implemented yet. XXX
+ //monoTriangulationFun(poly, compV2InY, pStream);
+
+ directedLine* new_polygon = polygonConvert(poly);
+ directedLine* list = monoPolyPart(new_polygon);
+ for(directedLine* temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ monoTriangulationFun(temp, compV2InX, pStream);
+ }
+ //clean up
+ list->deletePolygonListWithSline();
+
+ }
+
+ free(cusps);
+ /*
+ if(numInteriorCuspsX(poly) == 0) //is u monotone
+ monoTriangulationFun(poly, compV2InX, pStream);
+ else //it is not u motone
+ monoTriangulationFun(poly, compV2InY, pStream);
+ */
+ //clean up space
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+ //apparently the following code is not reachable,
+ //it is for test purpose
+ if(inc_current > inc_end || dec_current>dec_end)
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+
+
+ if(
+ area(dec_chain->getVertex(dec_current),
+ topVertex,
+ inc_chain->getVertex(inc_current)) >=0
+ && chainConvex(inc_chain, inc_current, inc_end)
+ && chainConcave(dec_chain, dec_current, dec_end)
+ && area(inc_chain->getVertex(inc_end), botVertex, dec_chain->getVertex(dec_end)) >=0
+ )
+ {
+ monoTriangulationRecFunGen(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ compV2InX, pStream);
+ }
+ else
+ {
+ monoTriangulationRecGen(topVertex, botVertex, inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+/*if inc_current>inc_end, then inc_chain has no points to be considered
+ *same for dec_chain
+ */
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+
+ if(inc_current > inc_end && dec_current>dec_end)
+ return;
+ else if(inc_current>inc_end) /*no more vertices on inc_chain*/
+ {
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(100,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(100,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(100, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(100, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecGen(inc_array[i-1], botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, dec_current,dec_end,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+void monoTriangulationFun(directedLine* monoPolygon, Int (*compFun)(Real*, Real*), primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compFun(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compFun(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ if (!(0 == inc_chain.getNumElements() && 0 == dec_chain.getNumElements())) {
+ monoTriangulationRecFun(topV->head(), botV->head(), &inc_chain, 0,
+ &dec_chain, 0, compFun, pStream);
+ }
+}
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream)
+{
+ Int i;
+ /*find the top vertex, bottom vertex, inccreasing chain, and decreasing chain,
+ *then call monoTriangulationRec
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = monoPolygon;
+ for(tempV = monoPolygon->getNext(); tempV != monoPolygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+ /*creat increase and decrease chains*/
+ vertexArray inc_chain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ inc_chain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ inc_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray dec_chain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ dec_chain.appendVertex(tempV->getVertex(i));
+ }
+
+ monoTriangulationRec(topV->head(), botV->head(), &inc_chain, 0, &dec_chain, 0, pStream);
+
+}
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL);
+ Real** inc_array ;
+
+ if(inc_smallIndex > inc_largeIndex)
+ return; //no triangles
+ if(inc_smallIndex == inc_largeIndex)
+ {
+ if(is_increase_chain)
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), botVertex, topVertex);
+ else
+ pStream->triangle(inc_chain->getVertex(inc_smallIndex), topVertex, botVertex);
+ return;
+ }
+ Int i;
+
+ if(is_increase_chain && botVertex[1] == inc_chain->getVertex(inc_largeIndex)[1])
+ {
+ pStream->triangle(botVertex, inc_chain->getVertex(inc_largeIndex-1),
+ inc_chain->getVertex(inc_largeIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex,
+ inc_largeIndex-1,
+ is_increase_chain,
+ pStream);
+ return;
+ }
+ else if( (!is_increase_chain) && topVertex[1] == inc_chain->getVertex(inc_smallIndex)[1])
+ {
+ pStream->triangle(topVertex, inc_chain->getVertex(inc_smallIndex+1),
+ inc_chain->getVertex(inc_smallIndex));
+ monoTriangulation2(topVertex, botVertex, inc_chain, inc_smallIndex+1,
+ inc_largeIndex, is_increase_chain, pStream);
+ return ;
+ }
+
+ inc_array = inc_chain->getArray();
+
+ reflexChain rChain(20,is_increase_chain); /*1 means the chain is increasing*/
+
+ rChain.processNewVertex(topVertex, pStream);
+
+ for(i=inc_smallIndex; i<=inc_largeIndex; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ rChain.processNewVertex(botVertex, pStream);
+
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current> inc_end &&
+ dec_current> dec_end));
+ /*
+ Int inc_nVertices;
+ Int dec_nVertices;
+ */
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current> inc_end) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<=dec_end; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current> dec_end) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<=inc_end; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<=dec_end; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFunGen(dec_array[i-1], botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, i, dec_end,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<=inc_end; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFunGen(inc_array[i-1], botVertex,
+ inc_chain, i,inc_end,
+ dec_chain, dec_current,dec_end,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+/*if compFun == compV2InY, top to bottom: V-monotone
+ *if compFun == compV2InX, right to left: U-monotone
+ */
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compFun(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compFun(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRecFun(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ compFun,
+ pStream);
+ }
+ else /*compFun(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compFun(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRecFun(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ compFun,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream)
+{
+ assert( inc_chain != NULL && dec_chain != NULL);
+ assert( ! (inc_current>=inc_chain->getNumElements() &&
+ dec_current>=dec_chain->getNumElements()));
+ Int inc_nVertices;
+ Int dec_nVertices;
+ Real** inc_array ;
+ Real** dec_array ;
+ Int i;
+ assert( ! ( (inc_chain==NULL) && (dec_chain==NULL)));
+
+ if(inc_current>=inc_chain->getNumElements()) /*no more vertices on inc_chain*/
+ {
+
+ dec_array = dec_chain->getArray();
+ dec_nVertices = dec_chain->getNumElements();
+ reflexChain rChain(20,0);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the dec_chain*/
+ for(i=dec_current; i<dec_nVertices; i++){
+ rChain.processNewVertex(dec_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+
+ }
+ else if(dec_current>= dec_chain->getNumElements()) /*no more vertices on dec_chain*/
+ {
+ inc_array = inc_chain->getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ reflexChain rChain(20,1);
+ /*put the top vertex into the reflex chain*/
+ rChain.processNewVertex(topVertex, pStream);
+ /*process all the vertices on the inc_chain*/
+ for(i=inc_current; i<inc_nVertices; i++){
+ rChain.processNewVertex(inc_array[i], pStream);
+ }
+ /*process the bottom vertex*/
+ rChain.processNewVertex(botVertex, pStream);
+ }
+ else /*neither chain is empty*/
+ {
+ inc_array = inc_chain -> getArray();
+ dec_array = dec_chain -> getArray();
+ inc_nVertices= inc_chain->getNumElements();
+ dec_nVertices= dec_chain->getNumElements();
+ /*if top of inc_chain is 'lower' than top of dec_chain, process all the
+ *vertices on the dec_chain which are higher than top of inc_chain
+ */
+ if(compV2InY(inc_array[inc_current], dec_array[dec_current]) <= 0)
+ {
+
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=dec_current; i<dec_nVertices; i++)
+ {
+ if(compV2InY(inc_array[inc_current], dec_array[i]) <= 0)
+ rChain.processNewVertex(dec_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(inc_array[inc_current], pStream);
+ monoTriangulationRec(dec_array[i-1], botVertex,
+ inc_chain, inc_current,
+ dec_chain, i,
+ pStream);
+ }
+ else /*compV2InY(inc_array[inc_current], dec_array[dec_current]) > 0*/
+ {
+
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex, pStream);
+ for(i=inc_current; i<inc_nVertices; i++)
+ {
+ if(compV2InY(inc_array[i], dec_array[dec_current]) >0)
+ rChain.processNewVertex(inc_array[i], pStream);
+ else
+ break;
+ }
+ rChain.outputFan(dec_array[dec_current], pStream);
+ monoTriangulationRec(inc_array[i-1], botVertex,
+ inc_chain, i,
+ dec_chain, dec_current,
+ pStream);
+ }
+ }/*end case neither is empty*/
+}
+
+
+
+/* the name here assumes that the polygon is Y-monotone, but
+ *this function also works for X-monotone polygons.
+ * a monotne polygon consists of two extrem verteices: topVertex and botVertex, and
+ *two monotone chains: inc_chain, and dec_chain. The edges of the increasing chain (inc_chain)
+ *is ordered by following pointer: next, while the edges of the decreasing chain (dec_chain)
+ *is ordered by following pointer: prev
+ * inc_index index the vertex which is the toppest of the inc_chain which we are handling currently.
+ * dec_index index the vertex which is the toppest of the dec_chain which we are handling currently.
+ */
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream)
+{
+ Int i;
+ directedLine *temp, *oldtemp = NULL;
+ Int tempIndex, oldtempIndex = 0;
+
+ assert(inc_chain != NULL && dec_chain != NULL);
+
+ if(inc_chain == botVertex) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=dec_index; i< dec_chain->get_npoints(); i++){
+ rChain.processNewVertex(dec_chain->getVertex(i), pStream);
+ }
+ for(temp = dec_chain->getPrev(); temp != botVertex; temp = temp->getPrev())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else if(dec_chain==botVertex) {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex->getVertex(top_index), pStream);
+ for(i=inc_index; i< inc_chain->get_npoints(); i++){
+ rChain.processNewVertex(inc_chain->getVertex(i), pStream);
+ }
+ for(temp = inc_chain->getPrev(); temp != botVertex; temp = temp->getNext())
+ {
+ for(i=0; i<temp->get_npoints(); i++){
+ rChain.processNewVertex(temp->getVertex(i), pStream);
+ }
+ }
+ }
+ else /*neither reached the bottom*/{
+ if(compV2InY(inc_chain->getVertex(inc_index), dec_chain->getVertex(dec_index)) <=0) {
+ reflexChain rChain(20, 0);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = dec_chain;
+ tempIndex = dec_index;
+ while( compV2InY(inc_chain->getVertex(inc_index), temp->getVertex(tempIndex))<=0) {
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getPrev();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(inc_chain->getVertex(inc_index), pStream);
+ monoTriangulationRec(inc_chain, inc_index, temp, tempIndex, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ else /* >0*/ {
+ reflexChain rChain(20, 1);
+ rChain.processNewVertex(topVertex -> getVertex(top_index), pStream);
+ temp = inc_chain;
+ tempIndex = inc_index;
+ while( compV2InY(temp->getVertex(tempIndex), dec_chain->getVertex(dec_index))>0){
+ oldtemp = temp;
+ oldtempIndex = tempIndex;
+ rChain.processNewVertex(temp->getVertex(tempIndex), pStream);
+
+ if(tempIndex == temp->get_npoints()-1){
+ tempIndex = 0;
+ temp = temp->getNext();
+ }
+ else{
+ tempIndex++;
+ }
+ }
+ rChain.outputFan(dec_chain->getVertex(dec_index), pStream);
+ monoTriangulationRec(temp, tempIndex, dec_chain, dec_index, oldtemp, oldtempIndex, botVertex, pStream);
+ }
+ } /*end case neither reached the bottom*/
+}
+
+/***************************vertexArray begin here**********************************/
+vertexArray::vertexArray(Real2* vertices, Int nVertices)
+{
+ Int i;
+ size = index = nVertices;
+ array = (Real**) malloc(sizeof(Real*) * nVertices);
+ assert(array);
+ for(i=0; i<nVertices; i++)
+ {
+ array[i] = vertices[i];
+ array[i] = vertices[i];
+ }
+}
+
+vertexArray::vertexArray(Int s)
+{
+ size = s;
+ array = (Real**) malloc(sizeof(Real*) * s);
+ assert(array);
+ index = 0;
+}
+
+vertexArray::~vertexArray()
+{
+ free(array);
+}
+
+void vertexArray::appendVertex(Real* ptr)
+{
+ Int i;
+ if(index >= size){
+ Real** temp = (Real**) malloc(sizeof(Real*) * (2*size +1));
+ assert(temp);
+ for(i=0; i<index; i++)
+ temp[i] = array[i];
+ free(array);
+ array = temp;
+ size = 2*size+1;
+ }
+ array[index++] = ptr;
+}
+
+void vertexArray::print()
+{
+ printf("vertex Array:index=%i, size=%i\n", index, size);
+ for(Int i=0; i<index; i++)
+ {
+ printf("(%f,%f) ", array[i][0], array[i][1]);
+ }
+ printf("\n");
+}
+
+/*find the first i such that array[i][1] >= v
+ * and array[i+1][1] <v
+ * if index == 0 (the array is empty, return -1.
+ * if v is above all, return -1.
+ * if v is below all, return index-1.
+ */
+Int vertexArray::findIndexAbove(Real v)
+{
+ Int i;
+ if(index == 0)
+ return -1;
+ else if(array[0][1] < v)
+ return -1;
+ else
+ {
+ for(i=1; i<index; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i][1] <= v
+ * and array[i-1][1] > v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below all, return endIndex+1
+ * if v is above all, return startIndex.
+ */
+Int vertexArray::findIndexBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] > v)
+ return endIndex+1;
+ else //now array[endIndex][1] <= v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] > v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i<=endIndex such that array[i-1][1] >= v
+ * and array[i][1] < v
+ *if sartIndex>endIndex, then return endIndex+1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is below or equal to all, return endIndex+1
+ * if v is strictly above all, return startIndex.
+ */
+Int vertexArray::findIndexStrictBelowGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return endIndex+1;
+ else if(array[endIndex][1] >= v)
+ return endIndex+1;
+ else //now array[endIndex][1] < v
+ {
+ for(i=endIndex-1; i>=startIndex; i--)
+ {
+ if(array[i][1] >= v)
+ break;
+ }
+ return i+1;
+ }
+}
+
+/*find the first i>startIndex such that array[i-1][1] > v
+ * and array[i][1] >=v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is strictly above all, return startIndex-1
+ * if v is strictly below all, return endIndex.
+ */
+Int vertexArray::findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex)
+{
+
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+
+ for(i=startIndex; i<=endIndex; i++)
+ {
+ if(array[i][1] <= v)
+ break;
+ }
+ if(i>endIndex) // v is strictly below all
+ return endIndex;
+ else if(array[i][1] == v)
+ return i;
+ else
+ return i-1;
+ }
+
+}
+
+
+/*find the first i>=startIndex such that array[i][1] >= v
+ * and array[i+1][1] <v
+ *if sartIndex>endIndex, then return startIndex-1.
+ *otherwise, startIndex<=endIndex, it is assumed that
+ * 0<=startIndex<=endIndex<index.
+ * if v is above all, return startIndex-1
+ * if v is below all, return endIndex.
+ */
+Int vertexArray::findIndexAboveGen(Real v, Int startIndex, Int endIndex)
+{
+ Int i;
+ if(startIndex > endIndex)
+ return startIndex-1;
+ else if(array[startIndex][1] < v)
+ return startIndex-1;
+ else //now array[startIndex][1] >= v
+ {
+ for(i=startIndex+1; i<=endIndex; i++)
+ {
+ if(array[i][1] < v)
+ break;
+ }
+ return i-1;
+ }
+}
+
+Int vertexArray::findDecreaseChainFromEnd(Int begin, Int end)
+{
+ Int i = end;
+ Real prevU = array[i][0];
+ Real thisU;
+ for(i=end-1; i>=begin; i--){
+ thisU = array[i][0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ return i;
+}
+
+//if(V(start) == v, return start, other wise return the
+//last i so that V(i)==v
+Int vertexArray::skipEqualityFromStart(Real v, Int start, Int end)
+{
+ Int i;
+ if(array[start][1] != v)
+ return start;
+ //now array[start][1] == v
+ for(i=start+1; i<= end; i++)
+ if(array[i][1] != v)
+ break;
+ return i-1;
+}
+
+
+/***************************vertexArray end****************************************/
+
+
+
+/***************************relfex chain stuff begin here*****************************/
+
+reflexChain::reflexChain(Int size, Int is_increasing)
+{
+ queue = (Real2*) malloc(sizeof(Real2) * size);
+ assert(queue);
+ index_queue = 0;
+ size_queue = size;
+ isIncreasing = is_increasing;
+}
+
+reflexChain::~reflexChain()
+{
+ free(queue);
+}
+
+/*put (u,v) at the end of the queue
+ *pay attention to space
+ */
+void reflexChain::insert(Real u, Real v)
+{
+ Int i;
+ if(index_queue >= size_queue) {
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (2*size_queue+1));
+ assert(temp);
+
+ /*copy*/
+ for(i=0; i<index_queue; i++){
+ temp[i][0] = queue[i][0];
+ temp[i][1] = queue[i][1];
+ }
+
+ free(queue);
+ queue = temp;
+ size_queue = 2*size_queue + 1;
+ }
+
+ queue[index_queue][0] = u;
+ queue[index_queue][1] = v;
+ index_queue ++;
+}
+
+void reflexChain::insert(Real v[2])
+{
+ insert(v[0], v[1]);
+}
+
+/*
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+*/
+
+/*the chain is reflex, and the vertex v is
+ *on the other side of the chain, so that
+ *we can outout the fan with v as the
+ *the center
+ */
+void reflexChain::outputFan(Real v[2], primStream* pStream)
+{
+ Int i;
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(i=0; i<index_queue; i++)
+ pStream->insert(queue[i]);
+ }
+ else {
+ for(i=index_queue-1; i>=0; i--)
+ pStream->insert(queue[i]);
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+}
+
+void reflexChain::processNewVertex(Real v[2], primStream* pStream)
+{
+ Int i,j,k;
+ Int isReflex;
+ /*if there are at most one vertex in the queue, then simply insert
+ */
+ if(index_queue <=1){
+ insert(v);
+ return;
+ }
+
+ /*there are at least two vertices in the queue*/
+ j=index_queue-1;
+
+ for(i=j; i>=1; i--) {
+ if(isIncreasing) {
+ isReflex = (area(queue[i-1], queue[i], v) <= 0.0);
+ }
+ else /*decreasing*/{
+ isReflex = (area(v, queue[i], queue[i-1]) <= 0.0);
+ }
+ if(isReflex) {
+ break;
+ }
+ }
+
+ /*
+ *if i<j then vertices: i+1--j are convex
+ * output triangle fan:
+ * v, and queue[i], i+1, ..., j
+ */
+ if(i<j)
+ {
+ pStream->begin();
+ pStream->insert(v);
+ if(isIncreasing) {
+ for(k=i; k<=j; k++)
+ pStream->insert(queue[k]);
+ }
+ else {
+ for(k=j; k>=i; k--)
+ pStream->insert(queue[k]);
+ }
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ /*delete vertices i+1--j from the queue*/
+ index_queue = i+1;
+ /*finally insert v at the end of the queue*/
+ insert(v);
+
+}
+
+void reflexChain::print()
+{
+ Int i;
+ printf("reflex chain: isIncreasing=%i\n", isIncreasing);
+ for(i=0; i<index_queue; i++) {
+ printf("(%f,%f) ", queue[i][0], queue[i][1]);
+ }
+ printf("\n");
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
new file mode 100644
index 000000000..f78b8f402
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/monoTriangulation.h
@@ -0,0 +1,184 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _MONO_TRIANGULATION_H
+#define _MONO_TRIANGULATION_H
+
+#include "definitions.h"
+#include "primitiveStream.h"
+#include "directedLine.h"
+#include "arc.h"
+
+class Backend;
+
+class reflexChain{
+ Real2 *queue;
+ /*the order of the polygon vertices: either q[0],q[1].., or
+ * q[n-1], q[n-2], ..., q[0]
+ *this order determines the interior of the polygon, so it
+ *also used to determines whether a chain is reflex or convex
+ */
+ Int isIncreasing;
+ Int index_queue;
+ Int size_queue; /*allocated size*/
+
+public:
+ reflexChain(Int size, Int isIncreasing);
+ ~reflexChain();
+
+ void insert(Real u, Real v);
+ void insert(Real v[2]);
+
+ void processNewVertex(Real v[2], primStream* pStream);
+ void outputFan(Real v[2], primStream* pStream);
+
+ void processNewVertex(Real v[2], Backend* backend);
+ void outputFan(Real v[2], Backend* backend);
+
+ void print();
+};
+
+/*dynamic array of pointers to reals.
+ *Intended to store an array of (u,v).
+ *Notice that it doesn't allocate or dealocate the space
+ *for the (u,v) themselfs. So it assums that someone else
+ *is taking care of them, while this class only plays with
+ *the pointers.
+ */
+class vertexArray{
+ Real** array;
+ Int index;
+ Int size;
+public:
+ vertexArray(Int s);
+ vertexArray(Real vertices[][2], Int nVertices);
+ ~vertexArray();
+ void appendVertex(Real* ptr); /*the content (pointed by ptr is NOT copied*/
+ Real* getVertex(Int i) {return array[i];}
+ Real** getArray() {return array;}
+ Int getNumElements() {return index;}
+ Int findIndexAbove(Real v);
+ Int findIndexAboveGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexStrictBelowGen(Real v, Int startIndex, Int EndIndex);
+ Int findIndexFirstAboveEqualGen(Real v, Int startIndex, Int endIndex);
+ Int skipEqualityFromStart(Real v, Int start, Int end);
+ //return i such that fron [i+1, end] is strictly U-monotone (left to right
+ Int findDecreaseChainFromEnd(Int begin, Int end);
+ void print();
+};
+
+void monoTriangulation(directedLine* monoPolygon, primStream* pStream);
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ primStream* pStream);
+
+void monoTriangulationRec(directedLine* inc_chain, Int inc_index,
+ directedLine* dec_chain, Int dec_index,
+ directedLine* topVertex, Int top_index,
+ directedLine* botVertex,
+ primStream* pStream);
+
+/*the chain could be increasing or decreasing, although we use the
+ * name inc_chain.
+ *the argument is_increase_chain indicates whether this chain
+ *is increasing (left chain in V-monotone case) or decreaing (right chain
+ *in V-monotone case).
+ */
+void monoTriangulation2(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_smallIndex,
+ Int inc_largeIndex,
+ Int is_increase_chain,
+ primStream* pStream);
+void monoTriangulationRecGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecGenOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void triangulateXYMonoTB(Int n_left, Real** leftVerts,
+ Int n_right, Real** rightVerts,
+ primStream* pStream);
+
+void monoTriangulationRecGenTBOpt(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream);
+
+void monoTriangulationRecOpt(Real* topVertex, Real* botVertex,
+ vertexArray* left_chain, Int left_current,
+ vertexArray* right_chain, Int right_current,
+ primStream* pStream);
+
+void monoTriangulationRecFunGen(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+
+void monoTriangulationRecFun(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ primStream* pStream);
+void monoTriangulationFun(directedLine* monoPolygon,
+ Int (*compFun)(Real*, Real*), primStream* pStream);
+
+
+
+
+void monoTriangulationRec(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Backend* backend);
+
+void monoTriangulationFunBackend(Arc_ptr loop, Int (*compFun)(Real*, Real*), Backend* backend);
+
+void monoTriangulationRecFunBackend(Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current,
+ vertexArray* dec_chain, Int dec_current,
+ Int (*compFun)(Real*, Real*),
+ Backend* backend);
+
+void monoTriangulationOpt(directedLine* poly, primStream* pStream);
+
+#endif
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h
new file mode 100644
index 000000000..a394e0ff9
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdio.h
@@ -0,0 +1,60 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdio.h
+ *
+ */
+
+#ifndef __glumystdio_h_
+#define __glumystdio_h_
+
+#ifdef STANDALONE
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+
+#ifdef LIBRARYBUILD
+#ifndef NDEBUG
+#include <stdio.h>
+#define _glu_dprintf printf
+#else
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+#endif
+
+#ifdef GLBUILD
+inline void _glu_dprintf( char *, ... ) { }
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif /* __glumystdio_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
new file mode 100644
index 000000000..ab7a3b273
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/mystdlib.h
@@ -0,0 +1,57 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+/*
+ * mystdlib.h
+ *
+ */
+
+#ifndef __glumystdlib_h_
+#define __glumystdlib_h_
+
+#ifdef STANDALONE
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#ifdef LIBRARYBUILD
+#include <stdlib.h>
+#endif
+
+#ifdef GLBUILD
+typedef unsigned int size_t;
+extern "C" void abort( void );
+extern "C" void * malloc( size_t );
+extern "C" void free( void * );
+#endif
+
+#endif /* __glumystdlib_h_ */
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
new file mode 100644
index 000000000..e25e30b0f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.cc
@@ -0,0 +1,162 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "partitionX.h"
+
+#define CONCAVITY_ZERO 1.0e-6 //this number is used to test whether a vertex is concave (refelx)
+ //or not. The test needs to compute the area of the three adjacent
+ //vertices to see if the are is positive or negative.
+
+Int isCuspX(directedLine *v)
+{
+ //if v->prev <= v && v->next <= v
+ //|| v->prev >= v && v->next >= v
+ Real* T = v->head();
+ Real* P = v->getPrev()->head();
+ Real* N = v->getNext()->head();
+ if(
+ (compV2InX(T,P) != -1 &&
+ compV2InX(T,N) != -1
+ ) ||
+ (compV2InX(T,P) != 1 &&
+ compV2InX(T,N) != 1
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isReflexX(directedLine* v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ //scale them in case they are too small
+ Bx = 10*(B[0] - A[0]);
+ By = 10*(B[1] - A[1]);
+ Cx = 10*(C[0] - A[0]);
+ Cy = 10*(C[1] - A[1]);
+
+ if(Bx*Cy - Cx*By < -CONCAVITY_ZERO) return 1;
+ else return 0;
+}
+
+
+/*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspTypeX(directedLine *v)
+{
+ if(! isCuspX(v)) return 0;
+ else
+ {
+//printf("isCusp,%f,%f\n", v->head()[0], v->head()[1]);
+ if(isReflexX(v))
+ {
+// printf("isReflex\n");
+ return 1;
+ }
+ else
+ {
+// printf("not isReflex\n");
+ return 2;
+ }
+ }
+}
+
+Int numInteriorCuspsX(directedLine *polygon)
+{
+ directedLine *temp;
+ int ret = 0;
+ if(cuspTypeX(polygon) == 1)
+ ret++;
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ ret++;
+ return ret;
+}
+
+
+void findInteriorCuspsX(directedLine *polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps)
+{
+ directedLine *temp;
+ ret_n_interior_cusps = 0;
+ if(cuspTypeX(polygon) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = polygon;
+ }
+ for(temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ if(cuspTypeX(temp) == 1)
+ {
+ ret_interior_cusps[ret_n_interior_cusps++] = temp;
+ }
+}
+
+directedLine* findDiagonal_singleCuspX(directedLine* cusp)
+{
+ directedLine* temp;
+ Int is_minimal = ((compV2InX(cusp->head(), cusp->tail()) == -1)? 1:0);
+
+ if(is_minimal)
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == 1)
+ {
+ return temp;
+ }
+ }
+ else //is maxmal
+ for(temp = cusp->getNext(); temp != cusp; temp = temp->getNext())
+ {
+ if(compV2InX(cusp->head(), temp->head()) == -1)
+ {
+ return temp;
+ }
+ }
+ return NULL;
+}
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h
new file mode 100644
index 000000000..69f2b2df2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionX.h
@@ -0,0 +1,54 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _PARTITIONX_H
+#define _PARTITIONX_H
+
+#include "directedLine.h"
+
+Int isCuspX(directedLine *v);
+Int isReflexX(directedLine *v);
+Int cuspTypeX(directedLine *v);
+
+//assuming the array of ret_interior_cusps has been allocated
+void findInteriorCuspsX(directedLine* polygon, Int& ret_n_interior_cusps,
+ directedLine** ret_interior_cusps);
+
+Int numInteriorCuspsX(directedLine* polygon);
+
+/*a single polygon with a single cusp
+ *return the diagonal vertex corresponding to this cusp
+ */
+directedLine* findDiagonal_singleCuspX(directedLine* cusp);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
new file mode 100644
index 000000000..297c62997
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.cc
@@ -0,0 +1,836 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "zlassert.h"
+#include "partitionY.h"
+#include "searchTree.h"
+#include "quicksort.h"
+#include "polyUtil.h"
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+/*retrurn
+ *-1: if A < B (Ya<Yb) || (Ya==Yb)
+ * 0: if A == B
+ * 1: if A>B
+ */
+static Int compVertInY(Real A[2], Real B[2])
+{
+ if( (A[1] < B[1]) || (A[1]==B[1] && A[0]<B[0]))
+ return -1;
+ else if
+ ( A[1] == B[1] && A[0] == B[0]) return 0;
+ else
+ return 1;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1<= v, v2<=v.
+ */
+Int isBelow(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != 1
+ && compVertInY(e->tail(), vert) != 1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*v is a vertex: the head of en edge,
+ *e is an edge,
+ *return 1 if e is below v: assume v1 and v2 are the two endpoints of e:
+ * v1>= v, v2>=v.
+ */
+Int isAbove(directedLine *v, directedLine *e)
+{
+ Real* vert = v->head();
+ if( compVertInY(e->head(), vert) != -1
+ && compVertInY(e->tail(), vert) != -1
+ )
+ return 1;
+ else
+ return 0;
+}
+
+Int isCusp(directedLine *v)
+{
+ Real *A=v->getPrev()->head();
+ Real *B=v->head();
+ Real *C=v->tail();
+ if(A[1] < B[1] && B[1] < C[1])
+ return 0;
+ else if(A[1] > B[1] && B[1] > C[1])
+ return 0;
+ else if(A[1] < B[1] && C[1] < B[1])
+ return 1;
+ else if(A[1] > B[1] && C[1] > B[1])
+ return 1;
+
+ if(isAbove(v, v) && isAbove(v, v->getPrev()) ||
+ isBelow(v, v) && isBelow(v, v->getPrev()))
+ return 1;
+ else
+ return 0;
+}
+
+/*crossproduct is strictly less than 0*/
+Int isReflex(directedLine *v)
+{
+ Real* A = v->getPrev()->head();
+ Real* B = v->head();
+ Real* C = v->tail();
+ Real Bx,By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+
+ if(Bx*Cy - Cx*By < 0) return 1;
+ else return 0;
+}
+
+ /*return
+ *0: not-cusp
+ *1: interior cusp
+ *2: exterior cusp
+ */
+Int cuspType(directedLine *v)
+{
+ if(! isCusp(v)) return 0;
+ else if(isReflex(v)) return 1;
+ else
+ return 2;
+}
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType)
+{
+ sweepRange* ret = (sweepRange*)malloc(sizeof(sweepRange));
+ assert(ret);
+ ret->left = left;
+ ret->leftType = leftType;
+ ret->right = right;
+ ret->rightType = rightType;
+ return ret;
+}
+
+void sweepRangeDelete(sweepRange* range)
+{
+ free(range);
+}
+
+Int sweepRangeEqual(sweepRange* src1, sweepRange* src2)
+{
+ Int leftEqual;
+ Int rightEqual;
+
+
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->leftType == 0 && src2->leftType == 0));
+ if(src1->leftType == 0 && src2->leftType == 1){
+ if(src1->left == src2->left ||
+ src1->left->getPrev() == src2->left
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else if(src1->leftType == 1 && src2->leftType == 1){
+ if(src1->left == src2->left)
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+ else /*src1->leftType == 1 && src2->leftType == 0*/{
+ if(src1->left == src2->left ||
+ src1->left == src2->left->getPrev()
+ )
+ leftEqual = 1;
+ else
+ leftEqual = 0;
+ }
+
+ /*the same thing for right*/
+ /*The case when both are vertices should not happen*/
+ assert(! (src1->rightType == 0 && src2->rightType == 0));
+ if(src1->rightType == 0 && src2->rightType == 1){
+ if(src1->right == src2->right ||
+ src1->right->getPrev() == src2->right
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else if(src1->rightType == 1 && src2->rightType == 1){
+ if(src1->right == src2->right)
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+ else /*src1->rightType == 1 && src2->rightType == 0*/{
+ if(src1->right == src2->right ||
+ src1->right == src2->right->getPrev()
+ )
+ rightEqual = 1;
+ else
+ rightEqual = 0;
+ }
+
+ return (leftEqual == 1 || rightEqual == 1);
+}
+
+/*given (x_1, y_1) and (x_2, y_2), and y
+ *return x such that (x,y) is on the line
+ */
+inline/*static*/ Real intersectHoriz(Real x1, Real y1, Real x2, Real y2, Real y)
+{
+ return ((y2==y1)? (x1+x2)*Real(0.5) : x1 + ((y-y1)/(y2-y1)) * (x2-x1));
+/*
+ if(y2 == y1) return (x1+x2)*0.5;
+ else return x1 + ((y-y1)/(y2-y1)) * (x2-x1);
+*/
+}
+
+/*compare two edges of a polygon.
+ *edge A < edge B if there is a horizontal line so that the intersection
+ *with A is to the left of the intersection with B.
+ *This function is used in sweepY for the dynamic search tree insertion to
+ *order the edges.
+ * Implementation: (x_1,y_1) and (x_2, y_2)
+ */
+static Int compEdges(directedLine *e1, directedLine *e2)
+{
+ Real* head1 = e1->head();
+ Real* tail1 = e1->tail();
+ Real* head2 = e2->head();
+ Real* tail2 = e2->tail();
+/*
+ Real h10 = head1[0];
+ Real h11 = head1[1];
+ Real t10 = tail1[0];
+ Real t11 = tail1[1];
+ Real h20 = head2[0];
+ Real h21 = head2[1];
+ Real t20 = tail2[0];
+ Real t21 = tail2[1];
+*/
+ Real e1_Ymax, e1_Ymin, e2_Ymax, e2_Ymin;
+/*
+ if(h11>t11) {
+ e1_Ymax= h11;
+ e1_Ymin= t11;
+ }
+ else{
+ e1_Ymax = t11;
+ e1_Ymin = h11;
+ }
+
+ if(h21>t21) {
+ e2_Ymax= h21;
+ e2_Ymin= t21;
+ }
+ else{
+ e2_Ymax = t21;
+ e2_Ymin = h21;
+ }
+*/
+
+ if(head1[1]>tail1[1]) {
+ e1_Ymax= head1[1];
+ e1_Ymin= tail1[1];
+ }
+ else{
+ e1_Ymax = tail1[1];
+ e1_Ymin = head1[1];
+ }
+
+ if(head2[1]>tail2[1]) {
+ e2_Ymax= head2[1];
+ e2_Ymin= tail2[1];
+ }
+ else{
+ e2_Ymax = tail2[1];
+ e2_Ymin = head2[1];
+ }
+
+
+ /*Real e1_Ymax = max(head1[1], tail1[1]);*/ /*max(e1->head()[1], e1->tail()[1]);*/
+ /*Real e1_Ymin = min(head1[1], tail1[1]);*/ /*min(e1->head()[1], e1->tail()[1]);*/
+ /*Real e2_Ymax = max(head2[1], tail2[1]);*/ /*max(e2->head()[1], e2->tail()[1]);*/
+ /*Real e2_Ymin = min(head2[1], tail2[1]);*/ /*min(e2->head()[1], e2->tail()[1]);*/
+
+ Real Ymax = min(e1_Ymax, e2_Ymax);
+ Real Ymin = max(e1_Ymin, e2_Ymin);
+
+ Real y = Real(0.5)*(Ymax + Ymin);
+
+/* Real x1 = intersectHoriz(e1->head()[0], e1->head()[1], e1->tail()[0], e1->tail()[1], y);
+ Real x2 = intersectHoriz(e2->head()[0], e2->head()[1], e2->tail()[0], e2->tail()[1], y);
+*/
+/*
+ Real x1 = intersectHoriz(h10, h11, t10, t11, y);
+ Real x2 = intersectHoriz(h20, h21, t20, t21, y);
+*/
+ Real x1 = intersectHoriz(head1[0], head1[1], tail1[0], tail1[1], y);
+ Real x2 = intersectHoriz(head2[0], head2[1], tail2[0], tail2[1], y);
+
+ if(x1<= x2) return -1;
+ else return 1;
+}
+
+/*used by sort precedures
+ */
+static Int compInY(directedLine* v1, directedLine* v2)
+{
+ return v1->compInY(v2);
+}
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices)
+{
+ Int i,j,k;
+
+ k=0;
+
+ for(i=0; i<total_num_edges; i++)
+ {
+ directedLine* vert =sortedVertices[i];
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+/*
+printf("find i=%i\n", i);
+printf("the vertex is\n");
+vert->printSingle();
+*/
+ if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge) && compEdges(prevEdge, thisEdge)<0)
+ {
+ /*this is an upward interior cusp*/
+ diagonal_vertices[k++] = vert;
+
+ for(j=i+1; j<total_num_edges; j++)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+ assert(j<total_num_edges);
+
+
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge) && compEdges(prevEdge, thisEdge)>0)
+ {
+ /*this is an downward interior cusp*/
+ diagonal_vertices[k++] = vert;
+ for(j=i-1; j>=0; j--)
+ if(sweepRangeEqual(ranges[i], ranges[j]))
+ {
+ diagonal_vertices[k++] = sortedVertices[j];
+ break;
+ }
+/* printf("j=%i\n", j);*/
+ assert(j>=0);
+
+
+
+ }
+ }
+ num_diagonals = k/2;
+}
+
+/*get rid of repeated diagonlas so that each diagonal appears only once in the array
+ */
+Int deleteRepeatDiagonals(Int num_diagonals, directedLine** diagonal_vertices, directedLine** new_vertices)
+{
+ Int i,k;
+ Int j,l;
+ Int index;
+ index=0;
+ for(i=0,k=0; i<num_diagonals; i++, k+=2)
+ {
+ Int isRepeated=0;
+ /*check the diagonla (diagonal_vertice[k], diagonal_vertices[k+1])
+ *is repeated or not
+ */
+ for(j=0,l=0; j<index; j++, l+=2)
+ {
+ if(
+ (diagonal_vertices[k] == new_vertices[l] &&
+ diagonal_vertices[k+1] == new_vertices[l+1]
+ )
+ ||
+ (
+ diagonal_vertices[k] == new_vertices[l+1] &&
+ diagonal_vertices[k+1] == new_vertices[l]
+ )
+ )
+ {
+ isRepeated=1;
+ break;
+ }
+ }
+ if(! isRepeated)
+ {
+ new_vertices[index+index] = diagonal_vertices[k];
+ new_vertices[index+index+1] = diagonal_vertices[k+1];
+ index++;
+ }
+ }
+ return index;
+}
+
+/*for debug only*/
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * total_num_edges);
+ assert(ranges);
+
+ sweepY(total_num_edges, array, ranges);
+
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges);
+ assert(diagonal_vertices);
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+ num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+ return diagonal_vertices;
+
+}
+
+
+/*partition into Y-monotone polygons*/
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines)
+{
+ Int total_num_edges = 0;
+ directedLine** array = polygons->toArrayAllPolygons(total_num_edges);
+
+ quicksort( (void**)array, 0, total_num_edges-1, (Int (*)(void*, void*)) compInY);
+
+ sweepRange** ranges = (sweepRange**) malloc(sizeof(sweepRange*) * (total_num_edges));
+ assert(ranges);
+
+
+
+ sweepY(total_num_edges, array, ranges);
+
+
+
+ /*the diagonal vertices are stored as:
+ *v0-v1: 1st diagonal
+ *v2-v3: 2nd diagonal
+ *v5-v5: 3rd diagonal
+ *...
+ */
+
+
+ Int num_diagonals;
+ /*number diagonals is < total_num_edges*total_num_edges*/
+ directedLine** diagonal_vertices = (directedLine**) malloc(sizeof(directedLine*) * total_num_edges*2/*total_num_edges*/);
+ assert(diagonal_vertices);
+
+
+
+ findDiagonals(total_num_edges, array, ranges, num_diagonals, diagonal_vertices);
+
+
+
+ directedLine* ret_polygons = polygons;
+ sampledLine* newSampledLines = NULL;
+ Int i,k;
+
+num_diagonals=deleteRepeatDiagonals(num_diagonals, diagonal_vertices, diagonal_vertices);
+
+
+
+ Int *removedDiagonals=(Int*)malloc(sizeof(Int) * num_diagonals);
+ for(i=0; i<num_diagonals; i++)
+ removedDiagonals[i] = 0;
+
+
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++,k+=2)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+/*
+ directedLine *root1 = v1->findRoot();
+ directedLine *root2 = v2->findRoot();
+ assert(root1);
+ assert(root2);
+*/
+
+directedLine* root1 = v1->rootLinkFindRoot();
+directedLine* root2 = v2->rootLinkFindRoot();
+
+ if(root1 != root2)
+ {
+
+ removedDiagonals[i] = 1;
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+
+
+
+ newSampledLines = generatedLine->insert(newSampledLines);
+/*
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+root1->rootLinkSet(ret_p1);
+root2->rootLinkSet(ret_p1);
+ret_p1->rootLinkSet(NULL);
+ret_p2->rootLinkSet(ret_p1);
+*/
+ ret_polygons = ret_polygons->cutoffPolygon(root2);
+
+
+
+root2->rootLinkSet(root1);
+ret_p1->rootLinkSet(root1);
+ret_p2->rootLinkSet(root1);
+
+ /*now that we have connected the diagonal v1 and v2,
+ *we have to check those unprocessed diagonals which
+ *have v1 or v2 as an end point. Notice that the head of v1
+ *has the same coodinates as the head of v2->prev, and the head of
+ *v2 has the same coordinate as the head of v1->prev.
+ *Suppose these is a diagonal (v1, x). If (v1,x) is still a valid
+ *diagonal, then x should be on the left hand side of the directed line: *v1->prev->head -- v1->head -- v1->tail. Otherwise, (v1,x) should be
+ *replaced by (v2->prev, x), that is, x is on the left of
+ * v2->prev->prev->head, v2->prev->head, v2->prev->tail.
+ */
+ Int ii, kk;
+ for(ii=0, kk=0; ii<num_diagonals; ii++, kk+=2)
+ if( removedDiagonals[ii]==0)
+ {
+ directedLine* d1=diagonal_vertices[kk];
+ directedLine* d2=diagonal_vertices[kk+1];
+ /*check d1, and replace diagonal_vertices[kk] if necessary*/
+ if(d1 == v1) {
+ /*check if d2 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v2->getPrev();
+ }
+ }
+ if(d1 == v2) {
+ /*check if d2 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d2->head()))
+ {
+/*
+ assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d2->head()));
+*/
+ diagonal_vertices[kk] = v1->getPrev();
+ }
+ }
+ /*check d2 and replace diagonal_vertices[k+1] if necessary*/
+ if(d2 == v1) {
+ /*check if d1 is to left of v1->prev->head:v1->head:v1->tail*/
+ if(! pointLeft2Lines(v1->getPrev()->head(),
+ v1->head(), v1->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v2->getPrev()->getPrev()->head(),
+ v2->getPrev()->head(),
+ v2->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v2->getPrev();
+ }
+ }
+ if(d2 == v2) {
+ /*check if d1 is to left of v2->prev->head:v2->head:v2->tail*/
+ if(! pointLeft2Lines(v2->getPrev()->head(),
+ v2->head(), v2->tail(), d1->head()))
+ {
+/* assert(pointLeft2Lines(v1->getPrev()->getPrev()->head(),
+ v1->getPrev()->head(),
+ v1->getPrev()->tail(), d1->head()));
+*/
+ diagonal_vertices[kk+1] = v1->getPrev();
+ }
+ }
+ }
+}/*end if (root1 not equal to root 2)*/
+}
+
+ /*second pass, now all diagoals should belong to the same polygon*/
+
+
+
+ for(i=0,k=0; i<num_diagonals; i++, k += 2)
+ if(removedDiagonals[i] == 0)
+ {
+
+
+ directedLine* v1=diagonal_vertices[k];
+ directedLine* v2=diagonal_vertices[k+1];
+
+
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ /*we ahve to determine whether v1 and v2 belong to the same polygon before
+ *their structure are modified by connectDiagonal().
+ */
+ directedLine *root1 = v1->findRoot();
+/*
+ directedLine *root2 = v2->findRoot();
+
+
+
+ assert(root1);
+ assert(root2);
+ assert(root1 == root2);
+ */
+ sampledLine* generatedLine;
+
+
+
+ v1->connectDiagonal(v1,v2, &ret_p1, &ret_p2, &generatedLine, ret_polygons);
+ newSampledLines = generatedLine->insert(newSampledLines);
+
+ ret_polygons = ret_polygons->cutoffPolygon(root1);
+
+ ret_polygons = ret_p1->insertPolygon(ret_polygons);
+
+ ret_polygons = ret_p2->insertPolygon(ret_polygons);
+
+
+
+ for(Int j=i+1; j<num_diagonals; j++)
+ {
+ if(removedDiagonals[j] ==0)
+ {
+
+ directedLine* temp1=diagonal_vertices[2*j];
+ directedLine* temp2=diagonal_vertices[2*j+1];
+ if(temp1==v1 || temp1==v2 || temp2==v1 || temp2==v2)
+ if(! temp1->samePolygon(temp1, temp2))
+ {
+ /*if temp1 and temp2 are in different polygons,
+ *then one of them must be v1 or v2.
+ */
+
+
+
+ assert(temp1==v1 || temp1 == v2 || temp2==v1 || temp2 ==v2);
+ if(temp1==v1)
+ {
+ diagonal_vertices[2*j] = v2->getPrev();
+ }
+ if(temp2==v1)
+ {
+ diagonal_vertices[2*j+1] = v2->getPrev();
+ }
+ if(temp1==v2)
+ {
+ diagonal_vertices[2*j] = v1->getPrev();
+ }
+ if(temp2==v2)
+ {
+ diagonal_vertices[2*j+1] = v1->getPrev();
+ }
+ }
+ }
+ }
+
+ }
+
+ /*clean up spaces*/
+ free(array);
+ free(ranges);
+ free(diagonal_vertices);
+ free(removedDiagonals);
+
+ *retSampledLines = newSampledLines;
+ return ret_polygons;
+}
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine** sortedVertices, sweepRange** ret_ranges)
+{
+ Int i;
+ /*for each vertex in the sorted list, update the binary search tree.
+ *and store the range information for each vertex.
+ */
+ treeNode* searchTree = NULL;
+ for(i=0; i<nVertices;i++)
+ {
+
+ directedLine* vert = sortedVertices[i];
+
+ directedLine* thisEdge = vert;
+ directedLine* prevEdge = vert->getPrev();
+
+ if(isBelow(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 1: this < v < prev
+ *the polygon is going down at v, the interior is to
+ *the right hand side.
+ * find the edge to the right of thisEdge for right range.
+ * delete thisEdge
+ * insert prevEdge
+ */
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ assert(thisNode);
+
+ treeNode* succ = TreeNodeSuccessor(thisNode);
+ assert(succ);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(prevEdge), ( Int (*) (void *, void *))compEdges);
+
+
+ ret_ranges[i] = sweepRangeMake(vert, 0, (directedLine*) (succ->key), 1);
+
+ }
+ else if(isAbove(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 2: this > v > prev
+ *the polygon is going up at v, the interior is to
+ *the left hand side.
+ * find the edge to the left of thisEdge for left range.
+ * delete prevEdge
+ * insert thisEdge
+ */
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ assert(prevNode);
+ treeNode* pred = TreeNodePredecessor(prevNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ searchTree = TreeNodeInsert(searchTree, TreeNodeMake(thisEdge), ( Int (*) (void *, void *))compEdges);
+ ret_ranges[i] = sweepRangeMake((directedLine*)(pred->key), 1, vert, 0);
+ }
+ else if(isAbove(vert, thisEdge) && isAbove(vert, prevEdge))
+ {
+
+ /*case 3: insert both edges*/
+ treeNode* thisNode = TreeNodeMake(thisEdge);
+ treeNode* prevNode = TreeNodeMake(prevEdge);
+ searchTree = TreeNodeInsert(searchTree, thisNode, ( Int (*) (void *, void *))compEdges);
+ searchTree = TreeNodeInsert(searchTree, prevNode, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)<0) /*interior cusp*/
+ {
+
+ treeNode* leftEdge = TreeNodePredecessor(thisNode);
+ treeNode* rightEdge = TreeNodeSuccessor(prevNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+
+ ret_ranges[i] = sweepRangeMake( prevEdge, 1, thisEdge, 1);
+ }
+ }
+ else if(isBelow(vert, thisEdge) && isBelow(vert, prevEdge))
+ {
+
+ /*case 4: delete both edges*/
+ treeNode* thisNode = TreeNodeFind(searchTree, thisEdge, ( Int (*) (void *, void *))compEdges);
+ treeNode* prevNode = TreeNodeFind(searchTree, prevEdge, ( Int (*) (void *, void *))compEdges);
+ if(compEdges(thisEdge, prevEdge)>0) /*interior cusp*/
+ {
+ treeNode* leftEdge = TreeNodePredecessor(prevNode);
+ treeNode* rightEdge = TreeNodeSuccessor(thisNode);
+ ret_ranges[i] = sweepRangeMake( (directedLine*) leftEdge->key, 1,
+ (directedLine*) rightEdge->key, 1
+ );
+ }
+ else /*exterior cusp*/
+ {
+ ret_ranges[i] = sweepRangeMake( thisEdge, 1, prevEdge, 1);
+ }
+ searchTree = TreeNodeDeleteSingleNode(searchTree, thisNode);
+ searchTree = TreeNodeDeleteSingleNode(searchTree, prevNode);
+ }
+ else
+ {
+ fprintf(stderr,"error in partitionY.C, invalid case\n");
+ printf("vert is\n");
+ vert->printSingle();
+ printf("thisEdge is\n");
+ thisEdge->printSingle();
+ printf("prevEdge is\n");
+ prevEdge->printSingle();
+
+ exit(1);
+ }
+ }
+
+ /*finaly clean up space: delete the search tree*/
+ TreeNodeDeleteWholeTree(searchTree);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h
new file mode 100644
index 000000000..8dda409de
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/partitionY.h
@@ -0,0 +1,97 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+ *partitionY.h:
+ *partition a polygon into a Y-monotone polygon:
+ * A polygon is Y-monotone if the boundary can be split into two polygon chains
+ *A and B such that each chain is Y-monotonic that is the intersection of any
+ *horizontal line intersects each chain has at most one connected componenets
+ * (empty, single point or a single line).
+ *
+ * A vertex is a cusp if both its ajacent vertices are either at or above v,
+ *or both at or below v. In addition, at least one of the ajacent verteces is
+ *strictly below or above v.
+ * A vertex is a relex vertex if the internals angle is strictly greater than
+ *180. In other words, if the the signed area is negative:
+ *(x1, y1), (x2, y2), (x3, y3) are the three vertices along a polygon, the
+ *order is such that left hand side is inside the polygon. Then (x2,y2) is
+ *reflex if:
+ * (x2-x1, y2-y1) cross (x3-x1, y3-y1) <0.
+ *A vertex is an interior cusp if it is a cusp and a reflex.
+ *A vertex is an exterior cusp if it is a cusp but not a reflex.
+ *
+ */
+
+#ifndef _PARTITIONY_H
+#define _PARTITIONY_H
+
+#include "directedLine.h"
+
+/*whether an edge is below a vertex*/
+Int isBelow(directedLine *v, directedLine *e);
+
+/*whether an edge is above a vertex*/
+Int isAbove(directedLine *v, directedLine *e);
+
+/*not-cusp,
+ *inerior cusp
+ *exterior cusp
+ */
+Int cuspType(directedLine *v);
+
+/*used in trapezoidalization*/
+typedef struct sweepRange{
+ directedLine *left;
+ Int leftType; /*either a vertex (leftType=0) or an edge (leftType =1) */
+ directedLine *right;
+ Int rightType; /*either a vertex (rightType=0) or an edge (rightType =1) */
+} sweepRange;
+
+sweepRange* sweepRangeMake(directedLine* left, Int leftType,
+ directedLine* right, Int rightType);
+
+void sweepRangeDelete(sweepRange* range);
+Int sweepRangeEqual(sweepRange* sr1, sweepRange* sr2);
+
+/*given a set of simple polygons where the interior
+ *is decided by left-hand principle,
+ *return a range (sight) for each vertex. This is called
+ *Trapezoidalization.
+ */
+void sweepY(Int nVertices, directedLine **sortedVerteces, sweepRange** ret_ranges);
+
+
+directedLine* partitionY(directedLine *polygons, sampledLine **retSampledLines);
+
+void findDiagonals(Int total_num_edges, directedLine** sortedVertices, sweepRange** ranges, Int& num_diagonals, directedLine** diagonal_vertices);
+
+directedLine** DBGfindDiagonals(directedLine *polygons, Int& num_diagonals);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
new file mode 100644
index 000000000..4d04df73f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.cc
@@ -0,0 +1,734 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "polyDBG.h"
+
+#ifdef __WATCOMC__
+#pragma warning 14 10
+#pragma warning 391 10
+#pragma warning 726 10
+#endif
+
+static Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+}
+
+Int DBG_isConvex(directedLine *poly)
+{
+ directedLine* temp;
+ if(area(poly->head(), poly->tail(), poly->getNext()->tail()) < 0.00000)
+ return 0;
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if(area(temp->head(), temp->tail(), temp->getNext()->tail()) < 0.00000)
+ return 0;
+ }
+ return 1;
+}
+
+Int DBG_is_U_monotone(directedLine* poly)
+{
+ Int n_changes = 0;
+ Int prev_sign;
+ Int cur_sign;
+ directedLine* temp;
+ cur_sign = compV2InX(poly->tail(), poly->head());
+
+ n_changes = (compV2InX(poly->getPrev()->tail(), poly->getPrev()->head())
+ != cur_sign);
+
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ prev_sign = cur_sign;
+ cur_sign = compV2InX(temp->tail(), temp->head());
+
+ if(cur_sign != prev_sign)
+ n_changes++;
+ }
+
+ if(n_changes ==2) return 1;
+ else return 0;
+}
+
+/*if u-monotone, and there is a long horizontal edge*/
+Int DBG_is_U_direction(directedLine* poly)
+{
+/*
+ if(! DBG_is_U_monotone(poly))
+ return 0;
+*/
+ Int V_count = 0;
+ Int U_count = 0;
+ directedLine* temp;
+ if( fabs(poly->head()[0] - poly->tail()[0]) <= fabs(poly->head()[1]-poly->tail()[1]))
+ V_count += poly->get_npoints();
+ else
+ U_count += poly->get_npoints();
+ /*
+ else if(poly->head()[1] == poly->tail()[1])
+ U_count += poly->get_npoints();
+ */
+ for(temp = poly->getNext(); temp != poly; temp = temp->getNext())
+ {
+ if( fabs(temp->head()[0] - temp->tail()[0]) <= fabs(temp->head()[1]-temp->tail()[1]))
+ V_count += temp->get_npoints();
+ else
+ U_count += temp->get_npoints();
+ /*
+ if(temp->head()[0] == temp->tail()[0])
+ V_count += temp->get_npoints();
+ else if(temp->head()[1] == temp->tail()[1])
+ U_count += temp->get_npoints();
+ */
+ }
+
+ if(U_count > V_count) return 1;
+ else return 0;
+}
+
+/*given two line segments, determine whether
+ *they intersect each other or not.
+ *return 1 if they do,
+ *return 0 otherwise
+ */
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2)
+{
+ if(l1->getNext() == l2)
+ {
+ if(area(l1->head(), l1->tail(), l2->tail()) == 0) //colinear
+ {
+ if( (l1->tail()[0] - l1->head()[0])*(l2->tail()[0]-l2->head()[0]) +
+ (l1->tail()[1] - l1->head()[1])*(l2->tail()[1]-l2->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else if(l1->getPrev() == l2)
+ {
+ if(area(l2->head(), l2->tail(), l1->tail()) == 0) //colinear
+ {
+ if( (l2->tail()[0] - l2->head()[0])*(l1->tail()[0]-l1->head()[0]) +
+ (l2->tail()[1] - l2->head()[1])*(l1->tail()[1]-l1->head()[1]) >=0)
+ return 0; //not intersect
+ else
+ return 1;
+ }
+ //else we use the normal code
+ }
+ else //the two edges are not connected
+ {
+ if((l1->head()[0] == l2->head()[0] &&
+ l1->head()[1] == l2->head()[1]) ||
+ (l1->tail()[0] == l2->tail()[0] &&
+ l1->tail()[1] == l2->tail()[1]))
+ return 1;
+
+ }
+
+
+ if(
+ (
+ area(l1->head(), l1->tail(), l2->head())
+ *
+ area(l1->head(), l1->tail(), l2->tail())
+ < 0
+ )
+ &&
+ (
+ area(l2->head(), l2->tail(), l1->head())
+ *area(l2->head(), l2->tail(), l1->tail())
+ < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*whether AB and CD intersect
+ *return 1 if they do
+ *retur 0 otheriwse
+ */
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2])
+{
+ if(
+ (
+ area(A, B, C) * area(A,B,D) <0
+ )
+ &&
+ (
+ area(C,D,A) * area(C,D,B) < 0
+ )
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/*determien whether (A,B) interesect chain[start] to [end]
+ */
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2])
+{
+ Int i;
+ for(i=start; i<=end-2; i++)
+ if(DBG_edgesIntersectGen(chain->getVertex(i), chain->getVertex(i+1), A, B))
+ return 1;
+
+ return 0;
+}
+
+/*determine whether a polygon intersect itself or not
+ *return 1 is it does,
+ * 0 otherwise
+ */
+Int DBG_polygonSelfIntersect(directedLine* poly)
+{
+ directedLine* temp1;
+ directedLine* temp2;
+ temp1=poly;
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+
+ }
+
+ for(temp1=poly->getNext(); temp1 != poly; temp1 = temp1->getNext())
+ for(temp2=temp1->getNext(); temp2 != temp1; temp2=temp2->getNext())
+ {
+ if(DBG_edgesIntersect(temp1, temp2))
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*check whether a line segment intersects a polygon
+ */
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly)
+{
+ directedLine* temp;
+ if(DBG_edgesIntersect(edge, poly))
+ return 1;
+ for(temp=poly->getNext(); temp != poly; temp=temp->getNext())
+ if(DBG_edgesIntersect(edge, temp))
+ return 1;
+ return 0;
+}
+
+/*check whether two polygons intersect
+ */
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2)
+{
+ directedLine* temp;
+ if(DBG_edgeIntersectPoly(p1, p2))
+ return 1;
+ for(temp=p1->getNext(); temp!= p1; temp = temp->getNext())
+ if(DBG_edgeIntersectPoly(temp, p2))
+ return 1;
+ return 0;
+}
+
+/*check whether there are polygons intersecting each other in
+ *a list of polygons
+ */
+Int DBG_polygonListIntersect(directedLine* pList)
+{
+ directedLine *temp;
+ for(temp=pList; temp != NULL; temp = temp->getNextPolygon())
+ if(DBG_polygonSelfIntersect(temp))
+ return 1;
+ directedLine* temp2;
+ for(temp=pList; temp!=NULL; temp=temp->getNextPolygon())
+ {
+ for(temp2=temp->getNextPolygon(); temp2 != NULL; temp2=temp2->getNextPolygon())
+ if(DBG_polygonsIntersect(temp, temp2))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+Int DBG_isCounterclockwise(directedLine* poly)
+{
+ return (poly->polyArea() > 0);
+}
+
+/*ray: v0 with direction (dx,dy).
+ *edge: v1-v2.
+ * the extra point v10[2] is given for the information at
+ *v1. Basically this edge is connectd to edge
+ * v10-v1. If v1 is on the ray,
+ * then we need v10 to determine whether this ray intersects
+ * the edge or not (that is, return 1 or return 0).
+ * If v1 is on the ray, then if v2 and v10 are on the same side of the ray,
+ * we return 0, otherwise return 1.
+ *For v2, if v2 is on the ray, we always return 0.
+ *Notice that v1 and v2 are not symmetric. So the edge is directed!!!
+ * The purpose for this convention is such that: a point is inside a polygon
+ * if and only if it intersets with odd number of edges.
+ */
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2])
+{
+/*
+if( (v1[1] >= v0[1] && v2[1]<= v0[1] )
+ ||(v2[1] >= v0[1] && v1[1]<= v0[1] )
+ )
+ printf("rayIntersectEdge, *********\n");
+*/
+
+ Real denom = (v2[0]-v1[0])*(-dy) - (v2[1]-v1[1]) * (-dx);
+ Real nomRay = (v2[0]-v1[0]) * (v0[1] - v1[1]) - (v2[1]-v1[1])*(v0[0]-v1[0]);
+ Real nomEdge = (v0[0]-v1[0]) * (-dy) - (v0[1]-v1[1])*(-dx);
+
+
+ /*if the ray is parallel to the edge, return 0: not intersect*/
+ if(denom == 0.0)
+ return 0;
+
+ /*if v0 is on the edge, return 0: not intersect*/
+ if(nomRay == 0.0)
+ return 0;
+
+ /*if v1 is on the positive ray, and the neighbor of v1 crosses the ray
+ *return 1: intersect
+ */
+ if(nomEdge == 0)
+ { /*v1 is on the positive or negative ray*/
+
+/*
+ printf("v1 is on the ray\n");
+*/
+
+ if(dx*(v1[0]-v0[0])>=0 && dy*(v1[1]-v0[1])>=0) /*v1 on positive ray*/
+ {
+ if(area(v0, v1, v10) * area(v0, v1, v2) >0)
+ return 0;
+ else
+ return 1;
+ }
+ else /*v1 on negative ray*/
+ return 0;
+ }
+
+ /*if v2 is on the ray, always return 0: not intersect*/
+ if(nomEdge == denom) {
+/* printf("v2 is on the ray\n");*/
+ return 0;
+ }
+
+ /*finally */
+ if(denom*nomRay>0 && denom*nomEdge>0 && nomEdge/denom <=1.0)
+ return 1;
+ return 0;
+}
+
+
+/*return the number of intersections*/
+Int DBG_rayIntersectPoly(Real v0[2], Real dx, Real dy, directedLine* poly)
+{
+ directedLine* temp;
+ Int count=0;
+ if(DBG_rayIntersectEdge(v0, dx, dy, poly->getPrev()->head(), poly->head(), poly->tail()))
+ count++;
+
+ for(temp=poly->getNext(); temp != poly; temp = temp->getNext())
+ if(DBG_rayIntersectEdge(v0, dx, dy, temp->getPrev()->head(), temp->head(), temp->tail()))
+ count++;
+/*printf("ray intersect poly: count=%i\n", count);*/
+ return count;
+}
+
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly)
+{
+/*
+printf("enter pointInsidePoly , v=(%f,%f)\n", v[0], v[1]);
+printf("the polygon is\n");
+poly->printList();
+*/
+ /*for debug purpose*/
+ assert( (DBG_rayIntersectPoly(v,1,0,poly) % 2 )
+ == (DBG_rayIntersectPoly(v,1,Real(0.1234), poly) % 2 )
+ );
+ if(DBG_rayIntersectPoly(v, 1, 0, poly) % 2 == 1)
+ return 1;
+ else
+ return 0;
+}
+
+/*return the number of polygons which contain thie polygon
+ * as a subset
+ */
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list)
+{
+ directedLine* temp;
+ Int count=0;
+/*
+printf("%i\n", DBG_pointInsidePoly(poly->head(),
+ list->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+ ->getNextPolygon()
+));
+*/
+
+ for(temp = list; temp != NULL; temp = temp->getNextPolygon())
+ {
+ if(poly != temp)
+ if(DBG_pointInsidePoly(poly->head(), temp))
+ count++;
+/* printf("count=%i\n", count);*/
+ }
+ return count;
+}
+
+void DBG_reverse(directedLine* poly)
+{
+ if(poly->getDirection() == INCREASING)
+ poly->putDirection(DECREASING);
+ else
+ poly->putDirection(INCREASING);
+
+ directedLine* oldNext = poly->getNext();
+ poly->putNext(poly->getPrev());
+ poly->putPrev(oldNext);
+
+ directedLine* temp;
+ for(temp=oldNext; temp!=poly; temp = oldNext)
+ {
+ if(temp->getDirection() == INCREASING)
+ temp->putDirection(DECREASING);
+ else
+ temp->putDirection(INCREASING);
+
+ oldNext = temp->getNext();
+ temp->putNext(temp->getPrev());
+ temp->putPrev(oldNext);
+ }
+ printf("reverse done\n");
+}
+
+Int DBG_checkConnectivity(directedLine *polygon)
+{
+ if(polygon == NULL) return 1;
+ directedLine* temp;
+ if(polygon->head()[0] != polygon->getPrev()->tail()[0] ||
+ polygon->head()[1] != polygon->getPrev()->tail()[1])
+ return 0;
+ for(temp=polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ if(temp->head()[0] != temp->getPrev()->tail()[0] ||
+ temp->head()[1] != temp->getPrev()->tail()[1])
+ return 0;
+ }
+ return 1;
+}
+
+/*print out error message.
+ *If it cannot modify the polygon list to make it satify the
+ *requirements, return 1.
+ *otherwise modify the polygon list, and return 0
+ */
+Int DBG_check(directedLine *polyList)
+{
+ directedLine* temp;
+ if(polyList == NULL) return 0;
+
+ /*if there are intersections, print out error message
+ */
+ if(DBG_polygonListIntersect(polyList))
+ {
+ fprintf(stderr, "DBG_check: there are self intersections, don't know to modify the polygons\n");
+ return 1;
+ }
+
+ /*check the connectivity of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+ if(! DBG_checkConnectivity(temp))
+ {
+ fprintf(stderr, "DBG_check, polygon not connected\n");
+ return 1;
+ }
+ }
+
+ /*check the orientation of each polygon*/
+ for(temp = polyList; temp!= NULL; temp = temp ->getNextPolygon())
+ {
+
+
+ Int correctDir;
+
+ if( DBG_enclosingPolygons(temp, polyList) % 2 == 0)
+ correctDir = 1; /*counterclockwise*/
+ else
+ correctDir = 0; /*clockwise*/
+
+ Int actualDir = DBG_isCounterclockwise(temp);
+
+ if(correctDir != actualDir)
+ {
+ fprintf(stderr, "DBG_check: polygon with incorrect orientations. reversed\n");
+
+ DBG_reverse(temp);
+ }
+
+ }
+ return 0;
+}
+
+/**************handle self intersections*****************/
+//determine whether e interects [begin, end] or not
+static directedLine* DBG_edgeIntersectChainD(directedLine *e,
+ directedLine *begin, directedLine *end)
+{
+ directedLine *temp;
+ for(temp=begin; temp != end; temp = temp->getNext())
+ {
+ if(DBG_edgesIntersect(e, temp))
+ return temp;
+ }
+ if(DBG_edgesIntersect(e, end))
+ return end;
+ return NULL;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur)
+{
+ directedLine *begin, *end, *next;
+ begin = polygon;
+ end = polygon;
+ cutOccur = 0;
+ while( (next = end->getNext()) != begin)
+ {
+ directedLine *interc = NULL;
+ if( (interc = DBG_edgeIntersectChainD(next, begin, end)))
+ {
+ int fixed = 0;
+ if(DBG_edgesIntersect(next, interc->getNext()))
+ {
+ //trying to fix it
+ Real buf[2];
+ int i;
+ Int n=5;
+ buf[0] = interc->tail()[0];
+ buf[1] = interc->tail()[1];
+
+ for(i=1; i<n; i++)
+ {
+ Real r = ((Real)i) / ((Real) n);
+ Real u = (1-r) * interc->head()[0] + r * interc->tail()[0];
+ Real v = (1-r) * interc->head()[1] + r * interc->tail()[1];
+ interc->tail()[0] = interc->getNext()->head()[0] = u;
+ interc->tail()[1] = interc->getNext()->head()[1] = v;
+ if( (! DBG_edgesIntersect(next, interc)) &&
+ (! DBG_edgesIntersect(next, interc->getNext())))
+ break; //we fixed it
+ }
+ if(i==n) // we didn't fix it
+ {
+ fixed = 0;
+ //back to original
+ interc->tail()[0] = interc->getNext()->head()[0] = buf[0];
+ interc->tail()[1] = interc->getNext()->head()[1] = buf[1];
+ }
+ else
+ {
+ fixed = 1;
+ }
+ }
+ if(fixed == 0)
+ {
+ cutOccur = 1;
+ begin->deleteSingleLine(next);
+
+ if(begin != end)
+ {
+ if(DBG_polygonSelfIntersect(begin))
+ {
+ directedLine* newEnd = end->getPrev();
+ begin->deleteSingleLine(end);
+ end = newEnd;
+ }
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ else
+ {
+ end = end->getNext();
+ }
+ }
+ return begin;
+}
+
+//given a polygon, cut the edges off and finally obtain a
+//a polygon without intersections. The cut-off edges are
+//dealloated. The new polygon is returned.
+#if 0 // UNUSED
+static directedLine* DBG_cutIntersectionPoly_notwork(directedLine *polygon)
+{
+ directedLine *crt;//current polygon
+ directedLine *begin;
+ directedLine *end;
+ directedLine *temp;
+ crt = polygon;
+ int find=0;
+ while(1)
+ {
+//printf("loop\n");
+ //if there are less than 3 edges, we should stop
+ if(crt->getPrev()->getPrev() == crt)
+ return NULL;
+
+ if(DBG_edgesIntersect(crt, crt->getNext()) ||
+ (crt->head()[0] == crt->getNext()->tail()[0] &&
+ crt->head()[1] == crt->getNext()->tail()[1])
+ )
+ {
+ find = 1;
+ crt=crt->deleteChain(crt, crt->getNext());
+ }
+ else
+ {
+ //now we know crt and crt->getNext do not intersect
+ begin = crt;
+ end = crt->getNext();
+//printf("begin=(%f,%f)\n", begin->head()[0], begin->head()[1]);
+//printf("end=(%f,%f)\n", end->head()[0], end->head()[1]);
+ for(temp=end->getNext(); temp!=begin; temp= temp->getNext())
+ {
+//printf("temp=(%f,%f)\n", temp->head()[0], temp->head()[1]);
+ directedLine *intersect = DBG_edgeIntersectChainD(temp, begin, end);
+ if(intersect != NULL)
+ {
+ crt = crt->deleteChain(intersect, temp);
+ find=1;
+ break; //the for loop
+ }
+ else
+ {
+ end = temp;
+ }
+ }
+ }
+ if(find == 0)
+ return crt;
+ else
+ find = 0; //go to next loop
+}
+}
+#endif
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list)
+{
+ directedLine* temp;
+ directedLine* tempNext=NULL;
+ directedLine* ret = NULL;
+ int cutOccur=0;
+ for(temp=list; temp != NULL; temp = tempNext)
+ {
+ directedLine *left;
+ tempNext = temp->getNextPolygon();
+
+ left = DBG_cutIntersectionPoly(temp, cutOccur);
+ if(left != NULL)
+ ret=left->insertPolygon(ret);
+ }
+ return ret;
+}
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList)
+{
+ directedLine *temp;
+ sampledLine* tempHead = NULL;
+ sampledLine* tempTail = NULL;
+ sampledLine* cHead = NULL;
+ sampledLine* cTail = NULL;
+
+ if(polygonList == NULL)
+ return NULL;
+
+ DBG_collectSampledLinesPoly(polygonList, cHead, cTail);
+
+ assert(cHead);
+ assert(cTail);
+ for(temp = polygonList->getNextPolygon(); temp != NULL; temp = temp->getNextPolygon())
+ {
+ DBG_collectSampledLinesPoly(temp, tempHead, tempTail);
+ cTail->insert(tempHead);
+ cTail = tempTail;
+ }
+ return cHead;
+}
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail)
+{
+ directedLine *temp;
+ retHead = NULL;
+ retTail = NULL;
+ if(polygon == NULL)
+ return;
+
+ retHead = retTail = polygon->getSampledLine();
+ for(temp = polygon->getNext(); temp != polygon; temp=temp->getNext())
+ {
+ retHead = temp->getSampledLine()->insert(retHead);
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
new file mode 100644
index 000000000..74843d888
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyDBG.h
@@ -0,0 +1,68 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _POLYDBG_H
+#define _POLYDBG_H
+
+#include "definitions.h"
+#include "directedLine.h"
+#include "monoTriangulation.h"
+
+Int DBG_edgesIntersectGen(Real A[2], Real B[2], Real C[2], Real D[2]);
+Int DBG_intersectChain(vertexArray* chain, Int start, Int end, Real A[2], Real B[2]);
+
+
+Int DBG_edgesIntersect(directedLine* l1, directedLine* l2);
+Int DBG_polygonSelfIntersect(directedLine* poly);
+Int DBG_edgeIntersectPoly(directedLine* edge, directedLine* poly);
+Int DBG_polygonsIntersect(directedLine* p1, directedLine* p2);
+Int DBG_polygonListIntersect(directedLine* pList);
+
+Int DBG_isCounterclockwise(directedLine* poly);
+Int DBG_rayIntersectEdge(Real v0[2], Real dx, Real dy, Real v10[2], Real v1[2], Real v2[2]);
+Int DBG_pointInsidePoly(Real v[2], directedLine* poly);
+Int DBG_enclosingPolygons(directedLine* poly, directedLine* list);
+void DBG_reverse(directedLine* poly);
+Int DBG_check(directedLine *polyList);
+
+Int DBG_isConvex(directedLine *poly);
+Int DBG_is_U_direction(directedLine *poly);
+Int DBG_is_U_monotone(directedLine* poly);
+
+directedLine* DBG_cutIntersectionAllPoly(directedLine* list);
+directedLine* DBG_cutIntersectionPoly(directedLine *polygon, int& cutOccur);
+
+sampledLine* DBG_collectSampledLinesAllPoly(directedLine *polygonList);
+
+void DBG_collectSampledLinesPoly(directedLine *polygon, sampledLine*& retHead, sampledLine*& retTail);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
new file mode 100644
index 000000000..f9a27f402
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.cc
@@ -0,0 +1,90 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "polyUtil.h"
+
+Real area(Real A[2], Real B[2], Real C[2])
+{
+ Real Bx, By, Cx, Cy;
+ Bx = B[0] - A[0];
+ By = B[1] - A[1];
+ Cx = C[0] - A[0];
+ Cy = C[1] - A[1];
+ return Bx*Cy - Cx*By;
+
+/* return (B[0]-A[0])*(C[1]-A[1]) - (C[0]-A[0])*(B[1]-A[1]);*/
+}
+
+/*given a directed line A->B, and a point P,
+ *determine whether P is to the left of AB.
+ *the line A->B (imagine it has beedn extended both
+ *end to the infinity) divides the plan into two
+ *half planes. When we walk from A to B, one
+ *half is to the left and the other half is to the right.
+ *return 1 if P is to the left.
+ *if P is on AB, 0 is returned.
+ */
+Int pointLeftLine(Real A[2], Real B[2], Real P[2])
+{
+ if(area(A, B, P) >0) return 1;
+ else return 0;
+}
+
+/*given two directed line: A -> B -> C, and another point P.
+ *determine whether P is to the left hand side of A->B->C.
+ *Think of BA and BC extended as two rays. So that the plane is
+ * divided into two parts. One part is to the left we walk from A
+ *to B and to C, the other part is to the right.
+ * In order for P to be the left, P must be either to the left
+ *of
+ */
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2])
+{
+ Int C_left_AB = (area(A, B, C)>0);
+ Int P_left_AB = (area(A, B, P)>0);
+ Int P_left_BC = (area(B, C, P)>0);
+
+ if(C_left_AB)
+ {
+ return (P_left_AB && P_left_BC);
+ }
+ else
+ return (P_left_AB || P_left_BC);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
new file mode 100644
index 000000000..1ca2ebcc0
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/polyUtil.h
@@ -0,0 +1,47 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _POLYUTIL_H
+#define _POLYUTIL_H
+
+#include "definitions.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+Real area(Real A[2], Real B[2], Real C[2]);
+
+Int pointLeftLine(Real A[2], Real B[2], Real P[2]);
+Int pointLeft2Lines(Real A[2], Real B[2], Real C[2], Real P[2]);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
new file mode 100644
index 000000000..26d05342f
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.cc
@@ -0,0 +1,190 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <GL/gl.h>
+
+#include "primitiveStream.h"
+
+Int primStream::num_triangles()
+{
+ Int i;
+ Int ret=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ ret += lengths[i]-2;
+ }
+ return ret;
+}
+
+
+
+/*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+void primStream::begin()
+{
+ counter = 0;
+}
+
+void primStream::insert(Real u, Real v)
+{
+ /*if the space cannot hold u and v,
+ *we have to expand the array
+ */
+ if(index_vertices+1 >= size_vertices) {
+ Real* temp = (Real*) malloc (sizeof(Real) * (2*size_vertices + 2));
+ assert(temp);
+
+ /*copy*/
+ for(Int i=0; i<index_vertices; i++)
+ temp[i] = vertices[i];
+
+ free(vertices);
+ vertices = temp;
+ size_vertices = 2*size_vertices + 2;
+ }
+
+ vertices[index_vertices++] = u;
+ vertices[index_vertices++] = v;
+ counter++;
+}
+
+/*the end of a primitive.
+ *increase index_lengths
+ */
+void primStream::end(Int type)
+{
+ Int i;
+ /*if there is no vertex in this primitive,
+ *nothing needs to be done
+ */
+ if(counter == 0) return ;
+
+ if(index_lengths >= size_lengths){
+ Int* temp = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(temp);
+ Int* tempTypes = (Int*) malloc(sizeof(Int) * (2*size_lengths + 2));
+ assert(tempTypes);
+
+ /*copy*/
+ for(i=0; i<index_lengths; i++){
+ temp[i] = lengths[i];
+ tempTypes[i] = types[i];
+ }
+
+ free(lengths);
+ free(types);
+ lengths = temp;
+ types = tempTypes;
+ size_lengths = 2*size_lengths + 2;
+ }
+ lengths[index_lengths] = counter;
+ types[index_lengths] = type;
+ index_lengths++;
+}
+
+void primStream::print()
+{
+ Int i,j,k;
+ printf("index_lengths=%i,size_lengths=%i\n", index_lengths, size_lengths);
+ printf("index_vertices=%i,size_vertices=%i\n", index_vertices, size_vertices);
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ if(types[i] == PRIMITIVE_STREAM_FAN)
+ printf("primitive-FAN:\n");
+ else
+ printf("primitive-STRIP:\n");
+ for(j=0; j<lengths[i]; j++)
+ {
+ printf("(%f,%f) ", vertices[k], vertices[k+1]);
+ k += 2;
+ }
+ printf("\n");
+ }
+}
+
+primStream::primStream(Int sizeLengths, Int sizeVertices)
+{
+ lengths = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(lengths);
+ types = (Int*)malloc (sizeof(Int) * sizeLengths);
+ assert(types);
+
+ vertices = (Real*) malloc(sizeof(Real) * sizeVertices);
+ assert(vertices);
+
+ index_lengths = 0;
+ index_vertices = 0;
+ size_lengths = sizeLengths;
+ size_vertices = sizeVertices;
+}
+
+primStream::~primStream()
+{
+ free(lengths);
+ free(types);
+ free(vertices);
+}
+
+void primStream::draw()
+{
+ Int i,j,k;
+ k=0;
+ for(i=0; i<index_lengths; i++)
+ {
+ switch(types[i]){
+ case PRIMITIVE_STREAM_FAN:
+ glBegin(GL_TRIANGLE_FAN);
+ break;
+ case PRIMITIVE_STREAM_STRIP:
+ glBegin(GL_TRIANGLE_STRIP);
+ break;
+ }
+
+ for(j=0; j<lengths[i]; j++){
+ glVertex2fv(vertices+k);
+ k += 2;
+ }
+ glEnd();
+ }
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
new file mode 100644
index 000000000..b4174f146
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/primitiveStream.h
@@ -0,0 +1,109 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+/*we do not use the constans GL_... so that this file is independent of
+ *<GL/gl.h>
+ */
+
+#ifndef _PRIMITIVE_STREAM_H
+#define _PRIMITIVE_STREAM_H
+
+enum {PRIMITIVE_STREAM_FAN, PRIMITIVE_STREAM_STRIP};
+
+#include "definitions.h"
+
+class primStream {
+ Int *lengths; /*length[i]=number of vertices of ith primitive*/
+ Int *types; /*each primive has a type: FAN or STREAM*/
+ Real *vertices; /*the size >= 2 * num_vertices, each vertex (u,v)*/
+
+ /*the following size information are used for dynamic arrays*/
+ Int index_lengths; /*the current available entry*/
+ Int size_lengths; /*the allocated size of the array: lengths*/
+ Int index_vertices;
+ Int size_vertices;
+
+ /*the vertex is inserted one by one. counter is used to
+ *count the number of vertices which have been inserted so far in
+ *the current primitive
+ */
+ Int counter;
+
+public:
+ primStream(Int sizeLengths, Int sizeVertices);
+ ~primStream();
+
+ Int get_n_prims() //num of primitives
+ {
+ return index_lengths;
+ }
+ Int get_type(Int i) //the type of ith primitive
+ {
+ return types[i];
+ }
+ Int get_length(Int i) //the length of the ith primitive
+ {
+ return lengths[i];
+ }
+ Real* get_vertices() {return vertices;}
+
+ /*the begining of inserting a new primitive.
+ *reset counter to be 0.
+ */
+ void begin();
+ void insert(Real u, Real v);
+ void insert(Real v[2]) {insert(v[0], v[1]);}
+ void end(Int type);
+
+ Int num_triangles();
+
+ void triangle(Real A[2], Real B[2], Real C[2])
+ {
+ begin();
+ insert(A);
+ insert(B);
+ insert(C);
+ end(PRIMITIVE_STREAM_FAN);
+ }
+ void print();
+ void draw(); /*using GL to draw the primitives*/
+};
+
+
+
+
+
+
+
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
new file mode 100644
index 000000000..9d0b290b3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.cc
@@ -0,0 +1,77 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static void swap(void *v[], int i, int j)
+{
+ void *temp;
+ temp = v[i];
+ v[i] = v[j];
+ v[j] = temp;
+}
+
+/*as an example to use this function to
+ *sort integers, you need to supply the function
+ *int comp(int *i1, int *i2)
+ *{
+ * if( *i1 < * i2) return -1;
+ * else return 1;
+ *}
+ *and an array of pointers to integers:
+ * int *v[100] (allocate space for where each v[i] points to).
+ *then you can call:
+ * quicksort( (void**)v, left, right, (int (*)(void *, void *))comp)
+ */
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *))
+{
+ int i, last;
+ if(left >= right) /*do nothing if array contains */
+ return; /*fewer than two elements*/
+
+ swap(v, left, (left+right)/2);
+ last = left;
+ for(i=left+1; i<=right; i++)
+ if((*comp)(v[i], v[left])<0)
+ swap(v, ++last, i);
+ swap(v, left, last);
+ quicksort(v, left, last-1, comp);
+ quicksort(v, last+1, right, comp);
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h
new file mode 100644
index 000000000..3a8dcd6a2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/quicksort.h
@@ -0,0 +1,42 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _QUICKSORT_H
+#define _QUICKSORT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void quicksort(void *v[], int left, int right,
+ int (*comp) (void *, void *));
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
new file mode 100644
index 000000000..f457b1573
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.cc
@@ -0,0 +1,196 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "zlassert.h"
+#include <GL/gl.h>
+
+#include "rectBlock.h"
+
+rectBlock::rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline)
+{
+ Int i;
+
+
+ upGridLineIndex = left->getVlineIndex(beginVline);
+
+ lowGridLineIndex = left->getVlineIndex(endVline);
+
+ Int n = upGridLineIndex-lowGridLineIndex+1; //number of grid lines
+ leftIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(leftIndices);
+ rightIndices = (Int*) malloc(sizeof(Int) * n);
+ assert(rightIndices);
+ for(i=0; i<n; i++)
+ {
+
+ leftIndices[i] = left->getInnerIndex(i+beginVline);
+ rightIndices[i] = right->getInnerIndex(i+beginVline);
+ }
+}
+
+
+rectBlock::~rectBlock()
+{
+ free(leftIndices);
+ free(rightIndices);
+}
+
+void rectBlock::print()
+{
+ Int i;
+ printf("block:\n");
+ for(i=upGridLineIndex; i >= lowGridLineIndex; i--)
+ {
+ printf("gridline %i, (%i,%i)\n", i, leftIndices[upGridLineIndex-i], rightIndices[upGridLineIndex-i]);
+ }
+}
+
+
+
+void rectBlock::draw(Real* u_values, Real* v_values)
+{
+ Int i,j,k;
+ //upgrid line to bot grid line
+#ifdef DEBUG
+printf("upGridLineIndex=%i, lowGridLineIndex=%i\n", upGridLineIndex, lowGridLineIndex);
+#endif
+ for(k=0, i=upGridLineIndex; i > lowGridLineIndex; i--, k++)
+ {
+ glBegin(GL_QUAD_STRIP);
+
+ for(j=leftIndices[k+1]; j<= rightIndices[k+1]; j++)
+ {
+ glVertex2f(u_values[j], v_values[i]);
+ glVertex2f(u_values[j], v_values[i-1]);
+ }
+ glEnd();
+ }
+}
+
+
+Int rectBlock::num_quads()
+{
+ Int ret=0;
+ Int k,i;
+ for(k=0, i=upGridLineIndex; i>lowGridLineIndex; i--, k++)
+ {
+ ret += (rightIndices[k+1]-leftIndices[k+1]);
+ }
+ return ret;
+}
+
+Int rectBlockArray::num_quads()
+{
+ Int ret=0;
+ for(Int i=0; i<n_elements; i++)
+ ret += array[i]->num_quads();
+ return ret;
+}
+
+rectBlockArray::rectBlockArray(Int s)
+{
+ Int i;
+ n_elements = 0;
+ size = s;
+ array = (rectBlock**) malloc(sizeof(rectBlock*) * s);
+ assert(array);
+//initialization
+ for(i=0; i<s; i++)
+ array[i] = NULL;
+}
+
+rectBlockArray::~rectBlockArray()
+{
+ Int i;
+ for(i=0; i<size; i++)
+ {
+ if(array[i] != NULL)
+ delete array[i];
+ }
+ free(array);
+}
+
+//put to the end of the array, check the size
+void rectBlockArray::insert(rectBlock* newBlock)
+{
+ Int i;
+ if(n_elements == size) //full
+ {
+ rectBlock** temp = (rectBlock**) malloc(sizeof(rectBlock) * (2*size+1));
+ assert(temp);
+ //initialization
+ for(i=0; i<2*size+1; i++)
+ temp[i] = NULL;
+
+ for(i=0; i<n_elements; i++)
+ temp[i] = array[i];
+
+ free(array);
+ array = temp;
+ size = 2*size + 1;
+ }
+
+ array[n_elements++] = newBlock;
+}
+
+void rectBlockArray::print()
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->print();
+}
+
+void rectBlockArray::draw(Real* u_values, Real* v_values)
+{
+ Int i;
+ for(i=0; i<n_elements; i++)
+ array[i]->draw(u_values, v_values);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
new file mode 100644
index 000000000..8dbd7eb81
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/rectBlock.h
@@ -0,0 +1,82 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _RECTBLOCK_H
+#define _RECTBLOCK_H
+
+#include "definitions.h"
+#include "gridWrap.h"
+
+class rectBlock{
+ Int upGridLineIndex;
+ Int lowGridLineIndex;
+ Int* leftIndices; //up to bottome
+ Int* rightIndices; //up to bottom
+public:
+ //the arrays are copies.
+ rectBlock(gridBoundaryChain* left, gridBoundaryChain* right, Int beginVline, Int endVline);
+ ~rectBlock(); //free the two arrays
+
+ Int get_upGridLineIndex() {return upGridLineIndex;}
+ Int get_lowGridLineIndex() {return lowGridLineIndex;}
+ Int* get_leftIndices() {return leftIndices;}
+ Int* get_rightIndices() {return rightIndices;}
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+class rectBlockArray{
+ rectBlock** array;
+ Int n_elements;
+ Int size;
+public:
+ rectBlockArray(Int s);
+ ~rectBlockArray();//delete avarything including the blocks
+
+ Int get_n_elements() {return n_elements;}
+ rectBlock* get_element(Int i) {return array[i];}
+ void insert(rectBlock* newBlock); //only take the pointer, not ther cotent
+
+ Int num_quads();
+
+ void print();
+ void draw(Real* u_values, Real* v_values);
+};
+
+
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
new file mode 100644
index 000000000..861c71bb3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.cc
@@ -0,0 +1,371 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "glimports.h"
+#include "sampleComp.h"
+#include "sampleCompTop.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ )
+{
+
+ sampleCompLeft(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex, rightEndIndex,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ pStream);
+
+
+ sampleCompRight(topVertex, botVertex,
+ leftChain,
+ leftStartIndex, leftEndIndex,
+ rightChain,
+ rightStartIndex,
+ rightEndIndex,
+ rightGridChain,
+ gridIndex1, gridIndex2,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ sampleCompTop(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+
+ sampleCompBot(botVertex,
+ leftChain,
+ leftEndIndex,
+ rightChain,
+ rightEndIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex2,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+
+ //the center
+
+ rbArray->insert(new rectBlock(leftGridChain, rightGridChain, gridIndex1, gridIndex2));
+
+
+}
+
+/*notice that we need rightChain because the
+ *corners could be on the rightChain.
+ *here comp means component.
+ */
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1 = 0, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i-1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ // v(gridMidIndex1) >= v(midindex1) > v(gridMidIndex1+1)
+ // v(gridMidIndex2-1) >= v(midIndex2) > v(gridMidIndex2) ??
+ midIndex1 = leftChain->findIndexBelowGen(
+ leftGridChain->get_v_value(gridIndex1),
+ leftStartIndex,
+ leftEndIndex);
+
+ midIndex2 = -1; /*initilization*/
+ if(midIndex1<= leftEndIndex && gridIndex1<gridIndex2)
+ if(leftChain->getVertex(midIndex1)[1] >= leftGridChain->get_v_value(gridIndex2))
+ {
+ midIndex2 = leftChain->findIndexAboveGen(
+ leftGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1 <= midIndex2.
+ leftEndIndex);
+ gridMidIndex1 = leftGridChain->lookfor(leftChain->getVertex(midIndex1)[1],
+ gridIndex1, gridIndex2);
+ gridMidIndex2 = 1+leftGridChain->lookfor(leftChain->getVertex(midIndex2)[1],
+ gridMidIndex1, gridIndex2);
+ }
+
+
+ /*to interprete the corner information*/
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerLeftStart;
+ Int cornerLeftEnd;
+ Int cornerRightUpEnd;
+ Int cornerRightDownStart;
+ if(up_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerTop = leftChain->getVertex(up_leftCornerIndex);
+ cornerLeftStart = up_leftCornerIndex+1;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else if(up_leftCornerWhere == 1) /*left corner is on top*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = -1; /*no right*/
+ }
+ else /*left corner is on right chain*/
+ {
+ cornerTop = topVertex;
+ cornerLeftStart = leftStartIndex;
+ cornerRightUpEnd = up_leftCornerIndex;
+ }
+
+ if(down_leftCornerWhere == 0) /*left corner is on left chain*/
+ {
+ cornerBot = leftChain->getVertex(down_leftCornerIndex);
+ cornerLeftEnd = down_leftCornerIndex-1;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else if(down_leftCornerWhere == 1) /*left corner is on bot*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = rightEndIndex+1; /*no right*/
+ }
+ else /*left corner is on the right chian*/
+ {
+ cornerBot = botVertex;
+ cornerLeftEnd = leftEndIndex;
+ cornerRightDownStart = down_leftCornerIndex;
+ }
+
+
+
+
+ /*sample*/
+ if(midIndex2 >= 0) /*there is a trim point inbewteen grid lines*/
+ {
+
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, leftChain->getVertex(midIndex1),
+ leftChain,
+ cornerLeftStart,
+ midIndex1-1,
+ leftGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ 0, //no right down section
+ -1,
+ pStream);
+
+ sampleLeftSingleTrimEdgeRegionGen(leftChain->getVertex(midIndex2),
+ cornerBot,
+ leftChain,
+ midIndex2+1,
+ cornerLeftEnd,
+ leftGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ rightChain,
+ 0, //no right up section
+ -1,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+
+
+ sampleLeftStripRecF(leftChain,
+ midIndex1,
+ midIndex2,
+ leftGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+ }
+ else
+ {
+ sampleLeftSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ leftChain,
+ cornerLeftStart,
+ cornerLeftEnd,
+ leftGridChain,
+ gridIndex1,
+ gridIndex2,
+ rightChain,
+ rightStartIndex,
+ cornerRightUpEnd,
+ cornerRightDownStart,
+ rightEndIndex,
+ pStream);
+ }
+}
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ /*creat an array to store all the up and down secments of the right chain,
+ *and the left end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,rightUpEnd - rightUpBegin+1)+
+ max(0,rightDownEnd - rightDownBegin+1));
+
+ /*append the vertices on the up section of thr right chain*/
+ for(i=rightUpBegin; i<= rightUpEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ /*append the vertices of the left extremal grid points,
+ *and at the same time, perform triangulation for the stair cases
+ */
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<=gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ /*then append all the vertices on the down section of the right chain*/
+ for(i=rightDownBegin; i<= rightDownEnd; i++)
+ vArray.appendVertex(rightChain->getVertex(i));
+
+ monoTriangulationRecGen(topVert, botVert,
+ leftChain, leftStart, leftEnd,
+ &vArray, 0, vArray.getNumElements()-1,
+ pStream);
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
new file mode 100644
index 000000000..a3c179025
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleComp.h
@@ -0,0 +1,86 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMP_H
+#define _SAMPLECOMP_H
+
+#include "sampleMonoPoly.h"
+#include "rectBlock.h"
+
+void sampleConnectedComp(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int botLeftIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleCompLeft(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* leftGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleLeftSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* rightChain,
+ Int rightUpBegin,
+ Int rightUpEnd,
+ Int rightDownBegin,
+ Int rightDownEnd,
+ primStream* pStream);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
new file mode 100644
index 000000000..e12f88bab
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.cc
@@ -0,0 +1,844 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+#include "sampleCompBot.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return: index_mono, index_pass
+//from [pass, mono] is strictly U-monotone
+//from [corner, pass] is <u
+// vertex[pass][0] >= u
+//if everybost is <u, then pass = end+1.
+//otherwise both mono and pass are meanng full and we have corner<=pass<=mono<=end
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+
+ assert(leftCorner <= leftEnd);
+ for(i=leftCorner; i<= leftEnd; i++)
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ ret_index_pass = i;
+ if(ret_index_pass <= leftEnd)
+ {
+ for(i=ret_index_pass; i< leftEnd; i++)
+ {
+ if(leftChain->getVertex(i+1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+
+}
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass)
+{
+ Int i;
+ assert(rightCorner <= rightEnd);
+ for(i=rightCorner; i<= rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+
+
+
+ ret_index_pass = i;
+
+ if(ret_index_pass <= rightEnd)
+ {
+ for(i=ret_index_pass; i< rightEnd; i++)
+ {
+ if(rightChain->getVertex(i+1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_mono = i;
+ }
+}
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexPass > rightCorner) //from corner to pass-1 is > u.
+ {
+ Real *tempBot;
+ if(segIndexPass <= rightEnd) //there is a point to the left of u
+ tempBot = rightChain->getVertex(segIndexPass);
+ else //nothing is to the left of u.
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ rightCorner,
+ segIndexPass-1,
+ 0, // a decrease chain
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= rightEnd) //segIndex pass and mono exist
+ {
+ //if there are grid points which are to the left of botVertex
+ //then we should use botVertex to form a fan with these points to
+ //optimize the triangulation
+ int do_optimize = 1;
+ if(botVertex[0] <= grid->get_u_value(leftU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that botVertex is the left most vertex on the chain
+ int i;
+ for(i=segIndexMono; i<=rightEnd; i++)
+ if(rightChain->getVertex(i)[0] <= botVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) <= botVertex[0]
+ //and grid->get_u_value(midU) > botVertex[0]
+ int midU = leftU;
+ while(grid->get_u_value(midU) <= botVertex[0])
+ {
+ midU++;
+ if(midU > rightU)
+ break;
+ }
+ midU--;
+
+ grid->outputFanWithPoint(gridV, leftU, midU, botVertex, pStream);
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, midU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(midU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ else //not optimize
+ {
+ stripOfFanRight(rightChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, botVertex, rightChain, segIndexMono, rightEnd, 0, pStream);
+ }
+ }
+ else //the botVertex forms a fan witht eh grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+}
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //if right chaain is empty, then there is only one bot vertex with
+ //one grid line
+ if(rightEnd<rightCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexMono, segIndexPass;
+ findBotRightSegment(rightChain,
+ rightEnd,
+ rightCorner,
+ grid->get_u_value(rightU),
+ segIndexMono,
+ segIndexPass);
+
+ sampleBotRightWithGridLinePost(botVertex,
+ rightChain,
+ rightEnd,
+ segIndexMono,
+ segIndexPass,
+ rightCorner,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //the possible section which is to the left of leftU
+ if(segIndexPass > leftCorner) //at least leftCorner is to the left of leftU
+ {
+ Real *tempBot;
+ if(segIndexPass <= leftEnd) //from corner to pass-1 is <u
+ tempBot = leftChain->getVertex(segIndexPass);
+ else //nothing is to the rigth of u
+ tempBot = botVertex;
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(leftU);
+ tempTop[1] = grid->get_v_value(gridV);
+ monoTriangulation2(tempTop, tempBot, leftChain, leftCorner, segIndexPass-1,
+ 1, //a increase chain,
+ pStream);
+ }
+ //the possible section which is strictly Umonotone
+ if(segIndexPass <= leftEnd) //segIndexpass and mono exist
+ {
+ stripOfFanLeft(leftChain, segIndexMono, segIndexPass, grid, gridV, leftU, rightU, pStream, 1);
+ Real tempTop[2];
+ tempTop[0] = grid->get_u_value(rightU);
+ tempTop[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, botVertex, leftChain, segIndexMono, leftEnd,
+ 1, //increase chain
+ pStream);
+ }
+ else //the botVertex forms a fan with the grid points
+ {
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ }
+
+}
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+
+ //if leftChain is empty, then there is only one botVertex with one grid line
+ if(leftEnd< leftCorner){
+ grid->outputFanWithPoint(gridV, leftU, rightU, botVertex, pStream);
+ return;
+ }
+
+ Int segIndexPass, segIndexMono;
+ findBotLeftSegment(leftChain, leftEnd, leftCorner, grid->get_u_value(leftU), segIndexMono, segIndexPass);
+
+ sampleBotLeftWithGridLinePost(botVertex,
+ leftChain,
+ leftEnd,
+ segIndexMono,
+ segIndexPass,
+ leftCorner,
+ grid,
+ gridV,
+ leftU, rightU, pStream);
+}
+
+//return 1 if separator exists, 0 otherwise
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftCorner)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightCorner)[0]*/;
+ if(leftChain->getVertex(leftCorner)[1] < rightChain->getVertex(rightCorner)[1])//leftlower
+ {
+ oldLeftI = leftCorner-1;
+ oldRightI = rightCorner;
+ leftMax = leftChain->getVertex(leftCorner)[0] - Real(1.0) ; //initilize to be left of leftCorner
+ rightMin = rightChain->getVertex(rightCorner)[0];
+ }
+ else //rightlower
+ {
+ oldLeftI = leftCorner;
+ oldRightI = rightCorner-1;
+ leftMax = leftChain->getVertex(leftCorner)[0];
+ rightMin = rightChain->getVertex(rightCorner)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain Index
+ //j: the curent working right chian index
+ //if(left(i) is lower than right(j), then the two chains above right(j) are separated.
+ //else the two chains below left(i) are separated.
+ i = leftCorner;
+ j = rightCorner;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+ if(i> leftEnd) //left chain is doen , go through remaining right chain
+ {
+ for(k=j+1; k<= rightEnd; k++)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above right(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(j > rightEnd) //right Chain is doen
+ {
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop, above left(k+1) is separated: oldLeftI, oldRightI
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] < rightChain->getVertex(j)[1]) //left lower
+ {
+
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax amd newLeftI
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j+1; k<= rightEnd; k++) //update rightMin and newRightI;
+ {
+ if(rightChain->getVertex(k)[1] < leftChain->getVertex(i)[1]) //right gets lower
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will he lower than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+
+ }
+ }
+ else //right lower
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i+1; k<= leftEnd; k++)
+ {
+ if(leftChain->getVertex(k)[1] < rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i=k; //nexct working i, since i will be lower than j next loop
+ if(leftMax >= rightMin) //there is conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRight I are the desired separator index notice that they are not
+ //necessarily valid
+ if(oldLeftI < leftCorner || oldRightI < rightCorner)
+ return 0; //no separator
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+
+ if(down_leftCornerWhere == 1 && down_rightCornerWhere == 1) //the bot is botVertex with possible grid points
+ {
+
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ botVertex,
+ pStream);
+ return;
+ }
+ else if(down_leftCornerWhere != 0)
+ {
+
+ Real* tempBot;
+ Int tempRightEnd;
+ if(down_leftCornerWhere == 1){
+ tempRightEnd = rightEnd;
+ tempBot = botVertex;
+ }
+ else
+ {
+ tempRightEnd = down_leftCornerIndex-1;
+ tempBot = rightChain->getVertex(down_leftCornerIndex);
+ }
+
+ sampleBotRightWithGridLine(tempBot,
+ rightChain,
+ tempRightEnd,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ }
+ else if(down_rightCornerWhere != 2)
+ {
+
+ Real* tempBot;
+ Int tempLeftEnd;
+ if(down_rightCornerWhere == 1){
+ tempLeftEnd = leftEnd;
+ tempBot = botVertex;
+ }
+ else //right corner is on left chain
+ {
+ tempLeftEnd = down_rightCornerIndex-1;
+ tempBot = leftChain->getVertex(down_rightCornerIndex);
+ }
+
+
+ sampleBotLeftWithGridLine(tempBot, leftChain, tempLeftEnd, down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+
+ }
+ else //down_leftCornereWhere == 0, down_rightCornerwhere == 2
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ return;
+
+#ifdef NOT_REACHABLE
+ //the following code is trying to do some optimization, but not quite working. so it is not reachable, but leave it here for reference
+ Int sep_left, sep_right;
+ if(findBotSeparator(leftChain, leftEnd, down_leftCornerIndex,
+ rightChain, rightEnd, down_rightCornerIndex,
+ sep_left, sep_right)
+ )//separator exiosts
+ {
+
+ if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))
+ {
+ Int gridSep;
+ Int segLeftMono, segLeftPass, segRightMono, segRightPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ findBotRightSegment(rightChain,
+ sep_right,
+ down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+ if(leftChain->getVertex(segLeftMono)[1] <= rightChain->getVertex(segRightMono)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftMono)[0])
+ gridSep--;
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightMono)[0])
+ gridSep++;
+ }
+
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ gridSep,
+ pStream);
+ sampleBotRightWithGridLinePost(rightChain->getVertex(segRightMono),
+ rightChain,
+ segRightMono-1,
+ segRightMono-1,
+ segRightPass,
+ down_rightCornerIndex,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+ Real tempTop[2];
+ tempTop[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempTop[1] = leftGridChain->get_v_value(gridIndex);
+ monoTriangulationRecGen(tempTop, botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+ }//end if both sides have vertices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex)) //left n right out
+
+ {
+ Int segLeftMono, segLeftPass;
+ findBotLeftSegment(leftChain,
+ sep_left,
+ down_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex),
+ segLeftMono,
+ segLeftPass);
+ assert(segLeftPass <= sep_left); //make sure there is a point to the right of u.
+ monoTriangulation2(leftGridChain->get_vertex(gridIndex),
+ leftChain->getVertex(segLeftPass),
+ leftChain,
+ down_leftCornerIndex,
+ segLeftPass-1,
+ 1, //a increase chain
+ pStream);
+ stripOfFanLeft(leftChain, segLeftMono, segLeftPass,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream,1 );
+/*
+ sampleBotLeftWithGridLinePost(leftChain->getVertex(segLeftMono),
+ leftChain,
+ segLeftMono-1,
+ segLeftMono-1,
+ segLeftPass,
+ down_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream);
+*/
+
+ monoTriangulationRecGen(rightGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, segLeftMono, leftEnd,
+ rightChain, down_rightCornerIndex, rightEnd,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex))//left out right in
+ {
+ Int segRightMono, segRightPass;
+ findBotRightSegment(rightChain, sep_right, down_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex),
+ segRightMono,
+ segRightPass);
+
+ assert(segRightPass <= sep_right); //make sure there is a point to the left of u.
+ monoTriangulation2(rightGridChain->get_vertex(gridIndex),
+ rightChain->getVertex(segRightPass),
+ rightChain,
+ down_rightCornerIndex,
+ segRightPass-1,
+ 0, // a decrease chain
+ pStream);
+
+ stripOfFanRight(rightChain, segRightMono, segRightPass,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex),
+ leftGridChain->getUlineIndex(gridIndex),
+ rightGridChain->getUlineIndex(gridIndex),
+ pStream, 1);
+
+
+ monoTriangulationRecGen(leftGridChain->get_vertex(gridIndex),
+ botVertex,
+ leftChain, down_leftCornerIndex, leftEnd,
+ rightChain, segRightMono, rightEnd,
+ pStream);
+
+ }//end left out right in
+ else //left out, right out
+ {
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+
+ }//end leftout right out
+ }//end if separator exists
+ else //no separator
+ {
+
+ sampleCompBotSimple(botVertex,
+ leftChain,
+ leftEnd,
+ rightChain,
+ rightEnd,
+ leftGridChain,
+ rightGridChain,
+ gridIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end id 0 2
+}//end if the functin
+
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algorithm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex);
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(down_rightCornerWhere != 0) //rightCorner is not on lef
+ ActualLeftEnd = leftEnd;
+ else
+ ActualLeftEnd = down_rightCornerIndex-1; //down_rightCornerIndex will be th actualBot
+
+ if(down_leftCornerWhere != 0) //left corner is not on let chian
+ ActualLeftStart = leftEnd+1; //meaning that there is no actual left section
+ else
+ ActualLeftStart = down_leftCornerIndex;
+
+ vertexArray ActualLeftChain(max(0, ActualLeftEnd - ActualLeftStart +1) + gridRightU - gridLeftU +1);
+
+ for(i=0; i<gridRightU - gridLeftU +1 ; i++)
+ ActualLeftChain.appendVertex(gridPoints[i]);
+ for(i=ActualLeftStart; i<= ActualLeftEnd; i++)
+ ActualLeftChain.appendVertex(leftChain->getVertex(i));
+
+ //determine ActualRightStart
+ if(down_rightCornerWhere != 2) //right is not on right
+ ActualRightStart = rightEnd +1; //meaning no section on right
+ else
+ ActualRightStart = down_rightCornerIndex;
+
+ //determine actualrightEnd
+ if(down_leftCornerWhere != 2) //left is not on right
+ {
+
+ ActualRightEnd = rightEnd;
+ }
+ else //left corner is on right
+ {
+ ActualRightEnd = down_leftCornerIndex-1; //down_leftCornerIndex will be the bot
+
+ }
+
+ //actual bot
+ if(down_rightCornerWhere == 2)
+ {
+ if(down_leftCornerWhere == 2)
+ ActualBot = rightChain->getVertex(down_leftCornerIndex);
+ else
+ ActualBot = botVertex;
+ }
+ else if(down_rightCornerWhere == 1) //right corner bot
+ ActualBot = botVertex;
+ else //down_rightCornerWhere == 0
+ ActualBot = leftChain->getVertex(down_rightCornerIndex);
+
+ ActualTop = gridPoints[0];
+/*
+printf("in bot simple, actual leftChain is \n");
+ActualLeftChain.print();
+printf("Actual Top = %f,%f\n", ActualTop[0],ActualTop[1]);
+printf("Actual Bot = %f,%f\n", ActualBot[0],ActualBot[1]);
+printf("Actual right start = %i, end=%i\n",ActualRightStart, ActualRightEnd);
+*/
+ if(rightChain->getVertex(ActualRightStart)[1] == ActualTop[1])
+ monoTriangulationRecGenOpt(rightChain->getVertex(ActualRightStart),
+ ActualBot,
+ &ActualLeftChain,
+ 0,
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart+1,
+ ActualRightEnd,
+ pStream);
+ else
+ monoTriangulationRecGenOpt(ActualTop, ActualBot,
+ &ActualLeftChain,
+ 1, //the first one is the top vertex
+ ActualLeftChain.getNumElements()-1,
+ rightChain,
+ ActualRightStart,
+ ActualRightEnd,
+ pStream);
+ free(gridPoints);
+}
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
new file mode 100644
index 000000000..7b982794c
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompBot.h
@@ -0,0 +1,138 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPBOT_H
+#define _SAMPLECOMPBOT_H
+
+#include "sampleMonoPoly.h"
+
+void findBotLeftSegment(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+void findBotRightSegment(vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Real u,
+ Int& ret_index_mono,
+ Int& ret_index_pass);
+
+
+void sampleBotRightWithGridLinePost(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotRightWithGridLine(Real* botVertex,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLinePost(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int segIndexMono,
+ Int segIndexPass,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+void sampleBotLeftWithGridLine(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream);
+
+
+Int findBotSeparator(vertexArray* leftChain,
+ Int leftEnd,
+ Int leftCorner,
+ vertexArray* rightChain,
+ Int rightEnd,
+ Int rightCorner,
+ Int& ret_sep_left,
+ Int& ret_sep_right);
+
+void sampleCompBot(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompBotSimple(Real* botVertex,
+ vertexArray* leftChain,
+ Int leftEnd,
+ vertexArray* rightChain,
+ Int rightEnd,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream);
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
new file mode 100644
index 000000000..d01e50018
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.cc
@@ -0,0 +1,644 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gluos.h"
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+#define min(a,b) ((a>b)? b:a)
+
+
+
+#ifdef NOT_TAKEOUT
+
+/*notice that we need leftChain because the
+ *corners could be on the leftChain.
+ */
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ Int down_rightCornerWhere,
+ Int down_rightCornerIndex,
+ primStream* pStream)
+{
+ /*find out whether there is a trim vertex which is
+ *inbetween the top and bot grid lines or not.
+ */
+ Int midIndex1;
+ Int midIndex2;
+ Int gridMidIndex1 = 0, gridMidIndex2 = 0;
+ //midIndex1: array[i] <= v, array[i+1] > v
+ //midIndex2: array[i] >= v, array[i+1] < v
+ midIndex1 = rightChain->findIndexBelowGen(rightGridChain->get_v_value(gridIndex1),
+ rightStartIndex,
+ rightEndIndex);
+ midIndex2 = -1; //initilization
+ if(midIndex1 <= rightEndIndex && gridIndex1 < gridIndex2)
+ if(rightChain->getVertex(midIndex1)[1] >= rightGridChain->get_v_value(gridIndex2))
+ {
+ //midIndex2 must exist:
+ midIndex2 = rightChain->findIndexAboveGen(rightGridChain->get_v_value(gridIndex2),
+ midIndex1, //midIndex1<=midIndex2
+ rightEndIndex);
+ //find gridMidIndex1 so that either it=gridIndex1 when the gridline is
+ // at the same height as trim vertex midIndex1, or it is the last one
+ //which is strictly above midIndex1.
+ {
+ Real temp = rightChain->getVertex(midIndex1)[1];
+ if(rightGridChain->get_v_value(gridIndex1) == temp)
+ gridMidIndex1 = gridIndex1;
+ else
+ {
+ gridMidIndex1 = gridIndex1;
+ while(rightGridChain->get_v_value(gridMidIndex1) > temp)
+ gridMidIndex1++;
+ gridMidIndex1--;
+ }
+ }//end of find gridMindIndex1
+ //find gridMidIndex2 so that it is the (first one below or equal
+ //midIndex) last one above or equal midIndex2
+ {
+ Real temp = rightChain->getVertex(midIndex2)[1];
+ for(gridMidIndex2 = gridMidIndex1+1; gridMidIndex2 <= gridIndex2; gridMidIndex2++)
+ if(rightGridChain->get_v_value(gridMidIndex2) <= temp)
+ break;
+
+ assert(gridMidIndex2 <= gridIndex2);
+ }//end of find gridMidIndex2
+ }
+
+
+
+ //to interprete the corner information
+ Real* cornerTop;
+ Real* cornerBot;
+ Int cornerRightStart;
+ Int cornerRightEnd;
+ Int cornerLeftUpEnd;
+ Int cornerLeftDownStart;
+ if(up_rightCornerWhere == 2) //right corner is on right chain
+ {
+ cornerTop = rightChain->getVertex(up_rightCornerIndex);
+ cornerRightStart = up_rightCornerIndex+1;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else if(up_rightCornerWhere == 1) //right corner is on top
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = -1; //no left
+ }
+ else //right corner is on left chain
+ {
+ cornerTop = topVertex;
+ cornerRightStart = rightStartIndex;
+ cornerLeftUpEnd = up_rightCornerIndex;
+ }
+
+ if(down_rightCornerWhere == 2) //right corner is on right chan
+ {
+ cornerBot = rightChain->getVertex(down_rightCornerIndex);
+ cornerRightEnd = down_rightCornerIndex-1;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else if (down_rightCornerWhere == 1) //right corner is at bot
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = leftEndIndex+1; //no left
+ }
+ else //right corner is on the left chain
+ {
+ cornerBot = botVertex;
+ cornerRightEnd = rightEndIndex;
+ cornerLeftDownStart = down_rightCornerIndex;
+ }
+
+ //sample
+ if(midIndex2 >= 0) //there is a trm point between grid lines
+ {
+
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, rightChain->getVertex(midIndex1),
+ rightChain,
+ cornerRightStart,
+ midIndex1-1,
+ rightGridChain,
+ gridIndex1,
+ gridMidIndex1,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ 0, //no left down section,
+ -1,
+ pStream);
+
+ sampleRightSingleTrimEdgeRegionGen(rightChain->getVertex(midIndex2),
+ cornerBot,
+ rightChain,
+ midIndex2+1,
+ cornerRightEnd,
+ rightGridChain,
+ gridMidIndex2,
+ gridIndex2,
+ leftChain,
+ 0, //no left up section
+ -1,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+
+ sampleRightStripRecF(rightChain,
+ midIndex1,
+ midIndex2,
+ rightGridChain,
+ gridMidIndex1,
+ gridMidIndex2,
+ pStream);
+
+ }
+ else
+ {
+ sampleRightSingleTrimEdgeRegionGen(cornerTop, cornerBot,
+ rightChain,
+ cornerRightStart,
+ cornerRightEnd,
+ rightGridChain,
+ gridIndex1,
+ gridIndex2,
+ leftChain,
+ leftStartIndex,
+ cornerLeftUpEnd,
+ cornerLeftDownStart,
+ leftEndIndex,
+ pStream);
+ }
+}
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVertex[2], Real botVertex[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBeginIndex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream)
+{
+ Int i,k;
+ /*creat an array to store all the up and down secments of the left chain,
+ *and the right end grid points
+ *
+ *although vertex array is a dynamic array, but to gain efficiency,
+ *it is better to initiliza the exact array size
+ */
+ vertexArray vArray(gridEndIndex-gridBeginIndex+1 +
+ max(0,leftUpEnd - leftUpBegin+1)+
+ max(0,leftDownEnd - leftDownBegin+1));
+ //append the vertices on the up section of the left chain
+ for(i=leftUpBegin; i<= leftUpEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+
+ //append the vertices of the right extremal grid points,
+ //and at the same time, perform triangulation for the stair cases
+ vArray.appendVertex(gridChain->get_vertex(gridBeginIndex));
+
+ for(k=1, i=gridBeginIndex+1; i<= gridEndIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ //output the fan of the grid points of the (i)th and (i-1)th grid line.
+ gridChain->rightEndFan(i, pStream);
+ }
+
+ //append all the vertices on the down section of the left chain
+ for(i=leftDownBegin; i<= leftDownEnd; i++)
+ vArray.appendVertex(leftChain->getVertex(i));
+ monoTriangulationRecGen(topVertex, botVertex,
+ &vArray, 0, vArray.getNumElements()-1,
+ rightChain, rightStart, rightEnd,
+ pStream);
+}
+
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,k;
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+ for(k=1, i=beginIndex+1; i<= endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+ //output the fan of the grid points of the (i)_th and i-1th gridLine
+ gridChain->rightEndFan(i, pStream);
+ }
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 1, //increase chain (to the left)
+ pStream);
+}
+
+
+/*the gridlines from rightGridChainStartIndex to
+ *rightGridChainEndIndex are assumed to form a
+ *connected componenet
+ *the trm vertex of topRightIndex is assumed to be below
+ *or equal the first gridLine, and the trm vertex of
+ *botRightIndex is assumed to be above or equal the last gridline
+ **there could be multipe trm vertices equal to the last gridline, but
+ **only one could be equal to top gridline. shape: ____| (recall that
+ **for left chain recF, we allow shape: |----
+ *if botRightIndex<topRightIndex, then no connected componenet exists, and
+ *no triangles are generated.
+ *Othewise, botRightIndex>= topRightIndex, there is at least one triangles to
+ *output
+ */
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ )
+{
+
+ //sstop conditionL: if topRightIndex > botRightIndex, then stop
+ if(topRightIndex > botRightIndex)
+ return;
+
+ //if there is only one grid line, return
+ if(rightGridChainStartIndex >= rightGridChainEndIndex)
+ return;
+
+
+ assert(rightChain->getVertex(topRightIndex)[1] <= rightGridChain->get_v_value(rightGridChainStartIndex) &&
+ rightChain->getVertex(botRightIndex)[1] >= rightGridChain->get_v_value(rightGridChainEndIndex));
+
+ //firstfind the first trim vertex which is strictly below the second top
+ //grid line: index1.
+ Real secondGridChainV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+ Int index1 = topRightIndex;
+ while(rightChain->getVertex(index1)[1] >= secondGridChainV){
+ index1++;
+ if(index1 > botRightIndex)
+ break;
+ }
+ //now rightChain->getVertex(index1-1)[1] >= secondGridChainV and
+ //rightChain->getVertex(index1)[1] < secondGridChainV and
+ //we should include index1-1 to perform a gridStep
+ index1--;
+
+ //now we have rightChain->getVertex(index1)[1] >= secondGridChainV, and
+ //rightChain->getVertex(index1+1)[1] < secondGridChainV
+ sampleRightOneGridStep(rightChain, topRightIndex, index1, rightGridChain, rightGridChainStartIndex, pStream);
+
+ //if rightChain->getVertex(index1)[1] ==secondGridChainV then we can
+ //recurvesively to the rest
+ if(rightChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+
+ sampleRightStripRecF(rightChain, index1, botRightIndex, rightGridChain, rightGridChainStartIndex+1, rightGridChainEndIndex, pStream);
+ }
+ else if(index1 < botRightIndex)
+ {
+ //otherwise, we have rightChain->getVertex(index1)[1] > secondV
+ //let the next trim vertex be nextTrimVertex, (which should be strictly
+ //below the second grid line). Find the last grid line index2 which is STRICTLY ABOVE
+ //nextTrimVertex.
+ //sample one trm edge region.
+ Real *uppervert, *lowervert;
+ uppervert = rightChain->getVertex(index1);
+ lowervert = rightChain->getVertex(index1+1); //okay since index1<botRightindex
+ Int index2 = rightGridChainStartIndex+1;
+ while(rightGridChain->get_v_value(index2) > lowervert[1])
+ {
+ index2++;
+ if(index2 > rightGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+ sampleRightSingleTrimEdgeRegion(uppervert, lowervert, rightGridChain, rightGridChainStartIndex+1, index2, pStream);
+
+ //recursion
+ sampleRightStripRecF(rightChain, index1+1, botRightIndex, rightGridChain, index2, rightGridChainEndIndex, pStream);
+ }
+}
+
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+ rightGridChain->rightEndFan(rightGridChainStartIndex+1, pStream);
+ monoTriangulation2(rightGridChain->get_vertex(rightGridChainStartIndex),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ beginRightIndex,
+ endRightIndex,
+ 0, //decrease chain
+ pStream);
+}
+
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream)
+{
+ if(checkMiddle(rightChain, beginRightIndex, endRightIndex,
+ rightGridChain->get_v_value(rightGridChainStartIndex),
+ rightGridChain->get_v_value(rightGridChainStartIndex+1))<0)
+ {
+ sampleRightOneGridStepNoMiddle(rightChain, beginRightIndex, endRightIndex, rightGridChain, rightGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygn
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = rightGridChain->getGrid();
+ float vert1[2];
+ float vert2[2];
+ Int i;
+
+ Int innerInd = rightGridChain->getInnerIndex(rightGridChainStartIndex+1);
+ Int upperInd = rightGridChain->getUlineIndex(rightGridChainStartIndex);
+ Int lowerInd = rightGridChain->getUlineIndex(rightGridChainStartIndex+1);
+ Real upperV = rightGridChain->get_v_value(rightGridChainStartIndex);
+ Real lowerV = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1]=vert2[1]=upperV;
+ for(i=upperInd;
+ i>innerInd;
+ i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segment
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert1[1]=upperV;
+ vert2[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1]=vert2[1]=lowerV;
+ for(i=innerInd; i<lowerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting lower grid to right chain
+ vert1[0]=grid->get_u_value(lowerInd);
+ sline = new sampledLine(vert1, rightChain->getVertex(endRightIndex));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+
+ //the right Chain
+ for(i=endRightIndex; i>beginRightIndex; i--)
+ {
+ sline = new sampledLine(rightChain->getVertex(i), rightChain->getVertex(i-1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting right chain with upper grid
+ vert2[1]=upperV;
+ vert2[0]=grid->get_u_value(upperInd);
+ sline = new sampledLine(rightChain->getVertex(beginRightIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //clean up
+ poly->deleteSinglePolygonWithSline();
+
+ return;
+ }
+
+ //this following code cannot be reached, but leave it for debuggig purpose.
+ Int i;
+ //find the maximal U-monotone chain of beginRightIndex, beginRightIndex+1,...
+ i=beginRightIndex;
+ Real prevU = rightChain->getVertex(i)[0];
+ for(i=beginRightIndex+1; i<= endRightIndex; i++){
+ Real thisU = rightChain->getVertex(i)[0];
+ if(thisU < prevU)
+ prevU = thisU;
+ else
+ break;
+ }
+ //from beginRightIndex to i-1 is strictly U-monotne
+ //if(i-1==beginRightIndex and the vertex of rightchain is on the first
+ //gridline, then we should use 2 vertices on the right chain. Of we only
+ //use one (begin), we would output degenrate triangles.
+ if(i-1 == beginRightIndex && rightChain->getVertex(beginRightIndex)[1] == rightGridChain->get_v_value(rightGridChainStartIndex))
+ i++;
+
+ Int j = endRightIndex -1;
+ if(rightGridChain->getInnerIndex(rightGridChainStartIndex+1) < rightGridChain->getUlineIndex(rightGridChainStartIndex+1))
+ {
+ j = rightChain->findDecreaseChainFromEnd(i-1/*beginRightIndex*/, endRightIndex);
+ Int temp = endRightIndex;
+ //now from j+1 to end is strictly U-monotone.
+ //if j+1 is on the last grid line, then we wat to skip to the vertex
+ //whcih is strictly above the second grid line. This vertex must exist
+ //since there is a middle vertex
+ if(j+1 == endRightIndex)
+ {
+ while(rightChain->getVertex(j+1)[1] == rightGridChain->get_v_value(rightGridChainStartIndex+1))
+ j--;
+
+ monoTriangulation2(rightChain->getVertex(j+1),
+ rightGridChain->get_vertex(rightGridChainStartIndex+1),
+ rightChain,
+ j+2,
+ endRightIndex,
+ 0, //a decrease chain
+ pStream);
+
+ temp = j+1;
+ }
+
+ stripOfFanRight(rightChain, temp, j+1, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex+1),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex+1),
+ pStream,
+ 0 //the grid line is below the trim line
+ );
+
+ }
+
+
+ stripOfFanRight(rightChain, i-1, beginRightIndex, rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(rightGridChainStartIndex),
+ rightGridChain->getInnerIndex(rightGridChainStartIndex+1),
+ rightGridChain->getUlineIndex(rightGridChainStartIndex),
+ pStream,
+ 1 //the grid line is above the trm lines
+ );
+
+ //monotone triangulate the remaining rightchain together with the
+ //two vertices on the two grid v-lines
+ Real vert[2][2];
+ vert[0][0] = vert[1][0] = rightGridChain->getInner_u_value(rightGridChainStartIndex+1);
+ vert[0][1] = rightGridChain->get_v_value(rightGridChainStartIndex);
+ vert[1][1] = rightGridChain->get_v_value(rightGridChainStartIndex+1);
+
+ monoTriangulation2(&vert[0][0],
+ &vert[1][0],
+ rightChain,
+ i-1,
+ j+1,
+ 0, ///a decreae chain
+ pStream);
+}
+
+#endif
+
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(! gridLineUp) /*trim line is above grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = rightChain->getVertex(i)[0];
+ trimVerts[k][1] = rightChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
new file mode 100644
index 000000000..4670b87ca
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompRight.h
@@ -0,0 +1,117 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPRIGHT_H
+#define _SAMPLECOMPRIGHT_H
+
+#define NOT_TAKEOUT
+
+#include "sampleMonoPoly.h"
+void stripOfFanRight(vertexArray* rightChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if grid line is above the trim lines */
+ );
+
+#ifdef NOT_TAKEOUT
+void sampleRightStripRecF(vertexArray* rightChain,
+ Int topRightIndex,
+ Int botRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ Int rightGridChainEndIndex,
+ primStream* pStream
+ );
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+//sampling the right area in between two grid lines
+//shape: _________|
+void sampleRightOneGridStep(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+void sampleRightSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+//the degenerate case of sampleRightOneGridStep
+void sampleRightOneGridStepNoMiddle(vertexArray* rightChain,
+ Int beginRightIndex,
+ Int endRightIndex,
+ gridBoundaryChain* rightGridChain,
+ Int rightGridChainStartIndex,
+ primStream* pStream);
+
+void sampleCompRight(Real* topVertex, Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex, Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex, Int rightEndIndex,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1, Int gridIndex2,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int down_leftCornerWhere,
+ Int down_leftCornerIndex,
+ primStream* pStream);
+
+void sampleRightSingleTrimEdgeRegionGen(Real topVert[2], Real botVert[2],
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridBoundaryChain* gridChain,
+ Int gridBegindex,
+ Int gridEndIndex,
+ vertexArray* leftChain,
+ Int leftUpBegin,
+ Int leftUpEnd,
+ Int leftDownBegin,
+ Int leftDownEnd,
+ primStream* pStream);
+#endif
+
+#endif
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
new file mode 100644
index 000000000..b7b929623
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.cc
@@ -0,0 +1,1030 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "zlassert.h"
+#include "sampleCompTop.h"
+#include "sampleCompRight.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+//return : index_small, and index_large,
+//from [small, large] is strictly U-monotne,
+//from [large+1, end] is <u
+//and vertex[large][0] is >= u
+//if eveybody is <u, the large = start-1.
+//otherwise both large and small are meaningful and we have start<=small<=large<=end
+void findTopLeftSegment(vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large
+ )
+{
+ Int i;
+ assert(leftStart <= leftEnd);
+ for(i=leftEnd; i>= leftStart; i--)
+ {
+ if(leftChain->getVertex(i)[0] >= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= leftStart)
+ {
+ for(i=ret_index_large; i>leftStart; i--)
+ {
+ if(leftChain->getVertex(i-1)[0] <= leftChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+void findTopRightSegment(vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ Real u,
+ Int& ret_index_small,
+ Int& ret_index_large)
+{
+ Int i;
+ assert(rightStart<=rightEnd);
+ for(i=rightEnd; i>=rightStart; i--)
+ {
+ if(rightChain->getVertex(i)[0] <= u)
+ break;
+ }
+ ret_index_large = i;
+ if(ret_index_large >= rightStart)
+ {
+ for(i=ret_index_large; i>rightStart;i--)
+ {
+ if(rightChain->getVertex(i-1)[0] >= rightChain->getVertex(i)[0])
+ break;
+ }
+ ret_index_small = i;
+ }
+}
+
+
+void sampleTopRightWithGridLinePost(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the right of rightU
+ if(segIndexLarge < rightEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= rightStart)
+ tempTop = rightChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+monoTriangulationRecGenOpt(tempTop, tempBot,
+ NULL, 1,0,
+ rightChain, segIndexLarge+1, rightEnd,
+ pStream);
+/*
+ monoTriangulation2(tempTop, tempBot,
+ rightChain,
+ segIndexLarge+1,
+ rightEnd,
+ 0, //a decrease chian
+ pStream);
+*/
+
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= rightStart)
+ {
+ stripOfFanRight(rightChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, rightChain, rightStart, segIndexSmall, 0, pStream);
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+void sampleTopRightWithGridLine(Real* topVertex,
+ vertexArray* rightChain,
+ Int rightStart,
+ Int rightEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ //if right chian is empty, then there is only one topVertex with one grid line
+ if(rightEnd < rightStart){
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+
+ Int segIndexSmall, segIndexLarge;
+ findTopRightSegment(rightChain,
+ rightStart,
+ rightEnd,
+ grid->get_u_value(rightU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopRightWithGridLinePost(topVertex, rightChain,
+ rightStart,
+ segIndexSmall,
+ segIndexLarge,
+ rightEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+void sampleTopLeftWithGridLinePost(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int segIndexSmall,
+ Int segIndexLarge,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream)
+{
+ //the possible section which is to the left of leftU
+
+ if(segIndexLarge < leftEnd)
+ {
+ Real *tempTop;
+ if(segIndexLarge >= leftStart)
+ tempTop = leftChain->getVertex(segIndexLarge);
+ else
+ tempTop = topVertex;
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(leftU);
+ tempBot[1] = grid->get_v_value(gridV);
+
+ monoTriangulation2(tempTop, tempBot,
+ leftChain,
+ segIndexLarge+1,
+ leftEnd,
+ 1, //a increase chian
+ pStream);
+ }
+
+ //the possible section which is strictly Umonotone
+ if(segIndexLarge >= leftStart)
+ {
+ //if there are grid points which are to the right of topV,
+ //then we should use topVertex to form a fan with these points to
+ //optimize the triangualtion
+ int do_optimize=1;
+ if(topVertex[0] >= grid->get_u_value(rightU))
+ do_optimize = 0;
+ else
+ {
+ //we also have to make sure that topVertex are the right most vertex
+ //on the chain.
+ int i;
+ for(i=leftStart; i<=segIndexSmall; i++)
+ if(leftChain->getVertex(i)[0] >= topVertex[0])
+ {
+ do_optimize = 0;
+ break;
+ }
+ }
+
+ if(do_optimize)
+ {
+ //find midU so that grid->get_u_value(midU) >= topVertex[0]
+ //and grid->get_u_value(midU-1) < topVertex[0]
+ int midU=rightU;
+ while(grid->get_u_value(midU) >= topVertex[0])
+ {
+ midU--;
+ if(midU < leftU)
+ break;
+ }
+ midU++;
+
+ grid->outputFanWithPoint(gridV, midU, rightU, topVertex, pStream);
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, midU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(midU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ else //not optimize
+ {
+
+ stripOfFanLeft(leftChain, segIndexLarge, segIndexSmall, grid, gridV, leftU, rightU, pStream, 0);
+ Real tempBot[2];
+ tempBot[0] = grid->get_u_value(rightU);
+ tempBot[1] = grid->get_v_value(gridV);
+ monoTriangulation2(topVertex, tempBot, leftChain, leftStart, segIndexSmall, 1, pStream);
+ }
+ }
+ else //the topVertex forms a fan with the grid points
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+}
+
+
+void sampleTopLeftWithGridLine(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStart,
+ Int leftEnd,
+ gridWrap* grid,
+ Int gridV,
+ Int leftU,
+ Int rightU,
+ primStream* pStream
+ )
+{
+ Int segIndexSmall, segIndexLarge;
+ //if left chain is empty, then there is only one top vertex with one grid
+ // line
+ if(leftEnd < leftStart) {
+ grid->outputFanWithPoint(gridV, leftU, rightU, topVertex, pStream);
+ return;
+ }
+ findTopLeftSegment(leftChain,
+ leftStart,
+ leftEnd,
+ grid->get_u_value(leftU),
+ segIndexSmall,
+ segIndexLarge
+ );
+ sampleTopLeftWithGridLinePost(topVertex,
+ leftChain,
+ leftStart,
+ segIndexSmall,
+ segIndexLarge,
+ leftEnd,
+ grid,
+ gridV,
+ leftU,
+ rightU,
+ pStream);
+}
+
+
+//return 1 if saprator exits, 0 otherwise
+Int findTopSeparator(vertexArray* leftChain,
+ Int leftStartIndex,
+ Int leftEndIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ Int rightEndIndex,
+ Int& ret_sep_left,
+ Int& ret_sep_right)
+{
+
+ Int oldLeftI, oldRightI, newLeftI, newRightI;
+ Int i,j,k;
+ Real leftMax /*= leftChain->getVertex(leftEndIndex)[0]*/;
+ Real rightMin /*= rightChain->getVertex(rightEndIndex)[0]*/;
+ if(leftChain->getVertex(leftEndIndex)[1] > rightChain->getVertex(rightEndIndex)[1]) //left higher
+ {
+ oldLeftI = leftEndIndex+1;
+ oldRightI = rightEndIndex;
+ leftMax = leftChain->getVertex(leftEndIndex)[0] - Real(1.0); //initilza to left of leftU
+ rightMin = rightChain->getVertex(rightEndIndex)[0];
+ }
+ else
+ {
+ oldLeftI = leftEndIndex;
+ oldRightI = rightEndIndex+1;
+ leftMax = leftChain->getVertex(leftEndIndex)[0];
+ rightMin = rightChain->getVertex(rightEndIndex)[0] + Real(1.0);
+ }
+
+ //i: the current working leftChain index,
+ //j: the current working rightChain index,
+ //if left(i) is higher than right(j), then the two chains beloew right(j) are separated.
+ //else the two chains below left(i) are separeated.
+ i=leftEndIndex;
+ j=rightEndIndex;
+ while(1)
+ {
+ newLeftI = oldLeftI;
+ newRightI = oldRightI;
+
+ if(i<leftStartIndex) //left chain is done, go through remining right chain.
+ {
+ for(k=j-1; k>= rightStartIndex; k--)
+ {
+ if(rightChain->getVertex(k)[0] > leftMax) //no conflict
+ {
+ //update oldRightI if necessary
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ oldRightI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for-loop. below right(k-1) is seperated: oldLeftI, oldRightI.
+ }
+ break; //the while loop
+ }
+ else if(j<rightStartIndex) //rightChain is done
+ {
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[0] < rightMin) //no conflict
+ {
+ //update oldLeftI if necessary
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ oldLeftI = k;
+ }
+ }
+ else //there is a conflict
+ break; //the for loop
+ }
+ break; //the while loop
+ }
+ else if(leftChain->getVertex(i)[1] > rightChain->getVertex(j)[1]) //left hgiher
+ {
+ if(leftChain->getVertex(i)[0] > leftMax) //update leftMax and newLeftI.
+ {
+ leftMax = leftChain->getVertex(i)[0];
+ newLeftI = i;
+ }
+ for(k=j-1; k>= rightStartIndex; k--) //update rightMin and newRightI.
+ {
+ if(rightChain->getVertex(k)[1] > leftChain->getVertex(i)[1])
+ break;
+ if(rightChain->getVertex(k)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(k)[0];
+ newRightI = k;
+ }
+ }
+ j = k; //next working j, since j will be higher than i in next loop
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ else //right higher
+ {
+ if(rightChain->getVertex(j)[0] < rightMin)
+ {
+ rightMin = rightChain->getVertex(j)[0];
+ newRightI = j;
+ }
+ for(k=i-1; k>= leftStartIndex; k--)
+ {
+ if(leftChain->getVertex(k)[1] > rightChain->getVertex(j)[1])
+ break;
+ if(leftChain->getVertex(k)[0] > leftMax)
+ {
+ leftMax = leftChain->getVertex(k)[0];
+ newLeftI = k;
+ }
+ }
+ i = k; //next working i, since i will be higher than j next loop
+
+ if(leftMax >= rightMin) //there is a conflict
+ break;
+ else //still no conflict
+ {
+ oldLeftI = newLeftI;
+ oldRightI = newRightI;
+ }
+ }
+ }//end of while loop
+ //now oldLeftI and oldRightI are the desired separeator index, notice that there are not necessarily valid
+ if(oldLeftI > leftEndIndex || oldRightI > rightEndIndex)
+ return 0;
+ else
+ {
+ ret_sep_left = oldLeftI;
+ ret_sep_right = oldRightI;
+ return 1;
+ }
+}
+
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ if(up_leftCornerWhere == 1 && up_rightCornerWhere == 1) //the top is topVertex with possible grid points
+ {
+ leftGridChain->getGrid()->outputFanWithPoint(leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ topVertex,
+ pStream);
+ return;
+ }
+
+ else if(up_leftCornerWhere != 0)
+ {
+ Real* tempTop;
+ Int tempRightStart;
+ if(up_leftCornerWhere == 1){
+ tempRightStart = rightStartIndex;
+ tempTop = topVertex;
+ }
+ else
+ {
+ tempRightStart = up_leftCornerIndex+1;
+ tempTop = rightChain->getVertex(up_leftCornerIndex);
+ }
+ sampleTopRightWithGridLine(tempTop, rightChain, tempRightStart, up_rightCornerIndex,
+ rightGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ }
+ else if(up_rightCornerWhere != 2)
+ {
+ Real* tempTop;
+ Int tempLeftStart;
+ if(up_rightCornerWhere == 1)
+ {
+ tempLeftStart = leftStartIndex;
+ tempTop = topVertex;
+ }
+ else //0
+ {
+ tempLeftStart = up_rightCornerIndex+1;
+ tempTop = leftChain->getVertex(up_rightCornerIndex);
+ }
+/*
+ sampleTopLeftWithGridLine(tempTop, leftChain, tempLeftStart, up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+*/
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else //up_leftCornerWhere == 0, up_rightCornerWhere == 2.
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ return;
+#ifdef NOT_REACHABLE //code is not reachable, for test purpose only
+ //the following code is trying to do some optimization, but not quite working, also see sampleCompBot.C:
+ Int sep_left, sep_right;
+ if(findTopSeparator(leftChain,
+ leftStartIndex,
+ up_leftCornerIndex,
+ rightChain,
+ rightStartIndex,
+ up_rightCornerIndex,
+ sep_left,
+ sep_right)
+ ) //separator exists
+ {
+
+ if( leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1) &&
+ rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int gridSep;
+ Int segLeftSmall, segLeftLarge, segRightSmall, segRightLarge;
+ Int valid=1; //whether the gridStep is valid or not.
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ if(leftChain->getVertex(segLeftSmall)[1] >= rightChain->getVertex(segRightSmall)[1])
+ {
+ gridSep = rightGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) > leftChain->getVertex(segLeftSmall)[0])
+ gridSep--;
+ if(segLeftSmall<segLeftLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) < leftChain->getVertex(segLeftSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+ else
+ {
+ gridSep = leftGridChain->getUlineIndex(gridIndex1);
+ while(leftGridChain->getGrid()->get_u_value(gridSep) < rightChain->getVertex(segRightSmall)[0])
+ gridSep++;
+ if(segRightSmall<segRightLarge)
+ if(leftGridChain->getGrid()->get_u_value(gridSep) > rightChain->getVertex(segRightSmall+1)[0])
+ {
+ valid = 0;
+ }
+ }
+
+ if(! valid)
+ {
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+ else
+ {
+ sampleTopLeftWithGridLinePost(leftChain->getVertex(segLeftSmall),
+ leftChain,
+ segLeftSmall+1,
+ segLeftSmall+1,
+ segLeftLarge,
+ up_leftCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ gridSep,
+ pStream);
+ sampleTopRightWithGridLinePost(rightChain->getVertex(segRightSmall),
+ rightChain,
+ segRightSmall+1,
+ segRightSmall+1,
+ segRightLarge,
+ up_rightCornerIndex,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ gridSep,
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream);
+ Real tempBot[2];
+ tempBot[0] = leftGridChain->getGrid()->get_u_value(gridSep);
+ tempBot[1] = leftGridChain->get_v_value(gridIndex1);
+ monoTriangulationRecGen(topVertex, tempBot,
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, segRightSmall,
+ pStream);
+ }
+ }//end if both sides have vetices inside the gridboundary points
+ else if(leftChain->getVertex(sep_left)[0] >= leftGridChain->get_u_value(gridIndex1)) //left is in, right is nout
+ {
+
+ Int segLeftSmall, segLeftLarge;
+ findTopLeftSegment(leftChain,
+ sep_left,
+ up_leftCornerIndex,
+ leftGridChain->get_u_value(gridIndex1),
+ segLeftSmall,
+ segLeftLarge);
+ assert(segLeftLarge >= sep_left);
+ monoTriangulation2(leftChain->getVertex(segLeftLarge),
+ leftGridChain->get_vertex(gridIndex1),
+ leftChain,
+ segLeftLarge+1,
+ up_leftCornerIndex,
+ 1, //a increase chain,
+ pStream);
+
+ stripOfFanLeft(leftChain, segLeftLarge, segLeftSmall,
+ leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, rightGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, segLeftSmall,
+ rightChain, rightStartIndex, up_rightCornerIndex,
+ pStream);
+ }//end left in right out
+ else if(rightChain->getVertex(sep_right)[0] <= rightGridChain->get_u_value(gridIndex1))
+ {
+ Int segRightSmall, segRightLarge;
+ findTopRightSegment(rightChain,
+ sep_right,
+ up_rightCornerIndex,
+ rightGridChain->get_u_value(gridIndex1),
+ segRightSmall,
+ segRightLarge);
+ assert(segRightLarge>=sep_right);
+ monoTriangulation2(rightChain->getVertex(segRightLarge),
+ rightGridChain->get_vertex(gridIndex1),
+ rightChain,
+ segRightLarge+1,
+ up_rightCornerIndex,
+ 0, //a decrease chain
+ pStream);
+ stripOfFanRight(rightChain, segRightLarge, segRightSmall,
+ rightGridChain->getGrid(),
+ rightGridChain->getVlineIndex(gridIndex1),
+ leftGridChain->getUlineIndex(gridIndex1),
+ rightGridChain->getUlineIndex(gridIndex1),
+ pStream, 0);
+
+
+ monoTriangulationRecGen(topVertex, leftGridChain->get_vertex(gridIndex1),
+ leftChain, leftStartIndex, up_leftCornerIndex,
+ rightChain, rightStartIndex,segRightSmall,
+ pStream);
+
+ }//end left out rigth in
+ else //left out , right out
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }//end leftout, right out
+ }//end if separator exixts.
+ else //no separator
+ {
+
+ sampleCompTopSimple(topVertex,
+ leftChain,
+ leftStartIndex,
+ rightChain,
+ rightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ gridIndex1,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ pStream);
+ }
+#endif
+ }//end if 0,2
+}//end if the function
+
+
+static void sampleCompTopSimpleOpt(gridWrap* grid,
+ Int gridV,
+ Real* topVertex, Real* botVertex,
+ vertexArray* inc_chain, Int inc_current, Int inc_end,
+ vertexArray* dec_chain, Int dec_current, Int dec_end,
+ primStream* pStream)
+{
+ if(gridV <= 0 || dec_end<dec_current || inc_end <inc_current)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ if(grid->get_v_value(gridV+1) >= topVertex[1])
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ return;
+ }
+ Int i,j,k;
+ Real currentV = grid->get_v_value(gridV+1);
+ if(inc_chain->getVertex(inc_end)[1] <= currentV &&
+ dec_chain->getVertex(dec_end)[1] < currentV)
+ {
+ //find i bottom up so that inc_chain[i]<= curentV and inc_chain[i-1] > currentV,
+ //find j botom up so that dec_chain[j] < currentV and dec_chain[j-1] >= currentV
+ for(i=inc_end; i >= inc_current; i--)
+ {
+ if(inc_chain->getVertex(i)[1] > currentV)
+ break;
+ }
+ i++;
+ for(j=dec_end; j >= dec_current; j--)
+ {
+ if(dec_chain->getVertex(j)[1] >= currentV)
+ break;
+ }
+ j++;
+ if(inc_chain->getVertex(i)[1] <= dec_chain->getVertex(j)[1])
+ {
+ //find the k so that dec_chain[k][1] < inc_chain[i][1]
+ for(k=j; k<=dec_end; k++)
+ {
+ if(dec_chain->getVertex(k)[1] < inc_chain->getVertex(i)[1])
+ break;
+ }
+ //we know that dec_chain[j][1] >= inc_chian[i][1]
+ //we know that dec_chain[k-1][1]>=inc_chain[i][1]
+ //we know that dec_chian[k][1] < inc_chain[i][1]
+ //find l in [j, k-1] so that dec_chain[l][0] 0 is closest to
+ // inc_chain[i]
+ int l;
+ Real tempI = Real(j);
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=j+1; l<= k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0])
+ <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(l)[0]);
+ tempI = (Real)l;
+ }
+ }
+ //inc_chain[i] and dec_chain[tempI] are connected.
+ monoTriangulationRecGenOpt(dec_chain->getVertex((int)tempI),
+ botVertex,
+ inc_chain, i, inc_end,
+ dec_chain, (int)(tempI+1), dec_end,
+ pStream);
+ //recursively do the rest
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, inc_chain->getVertex(i),
+ inc_chain, inc_current, i-1,
+ dec_chain, dec_current, (int)tempI,
+ pStream);
+ }
+ else
+ {
+ //find the k so that inc_chain[k][1] <= dec_chain[j][1]
+ for(k=i; k<=inc_end; k++)
+ {
+ if(inc_chain->getVertex(k)[1] <= dec_chain->getVertex(j)[1])
+ break;
+ }
+ //we know that inc_chain[i] > dec_chain[j]
+ //we know that inc_chain[k-1][1] > dec_chain[j][1]
+ //we know that inc_chain[k][1] <= dec_chain[j][1]
+ //so we find l between [i,k-1] so that
+ //inc_chain[l][0] is the closet to dec_chain[j][0]
+ int tempI = i;
+ int l;
+ Real tempMin = (Real)fabs(inc_chain->getVertex(i)[0] - dec_chain->getVertex(j)[0]);
+ for(l=i+1; l<=k-1; l++)
+ {
+ if(fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]) <= tempMin)
+ {
+ tempMin = (Real)fabs(inc_chain->getVertex(l)[0] - dec_chain->getVertex(j)[0]);
+ tempI = l;
+ }
+ }
+
+ //inc_chain[tempI] and dec_chain[j] are connected
+
+ monoTriangulationRecGenOpt(inc_chain->getVertex(tempI),
+ botVertex,
+ inc_chain, tempI+1, inc_end,
+ dec_chain, j, dec_end,
+ pStream);
+
+ //recurvesily do the rest
+ sampleCompTopSimpleOpt(grid, gridV+1,
+ topVertex, dec_chain->getVertex(j),
+ inc_chain, inc_current, tempI,
+ dec_chain, dec_current, j-1,
+ pStream);
+ }
+ }
+ else //go to the next higher gridV
+ {
+ sampleCompTopSimpleOpt(grid,
+ gridV+1,
+ topVertex, botVertex,
+ inc_chain, inc_current, inc_end,
+ dec_chain, dec_current, dec_end,
+ pStream);
+ }
+}
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream)
+{
+ //the plan is to use monotriangulation algortihm.
+ Int i,k;
+ Real* ActualTop;
+ Real* ActualBot;
+ Int ActualLeftStart, ActualLeftEnd;
+ Int ActualRightStart, ActualRightEnd;
+
+ //creat an array to store the points on the grid line
+ gridWrap* grid = leftGridChain->getGrid();
+ Int gridV = leftGridChain->getVlineIndex(gridIndex1);
+ Int gridLeftU = leftGridChain->getUlineIndex(gridIndex1);
+ Int gridRightU = rightGridChain->getUlineIndex(gridIndex1);
+
+ Real2* gridPoints = (Real2*) malloc(sizeof(Real2) * (gridRightU - gridLeftU +1));
+ assert(gridPoints);
+
+ for(k=0, i=gridRightU; i>= gridLeftU; i--, k++)
+ {
+ gridPoints[k][0] = grid->get_u_value(i);
+ gridPoints[k][1] = grid->get_v_value(gridV);
+ }
+
+ if(up_leftCornerWhere != 2)
+ ActualRightStart = rightStartIndex;
+ else
+ ActualRightStart = up_leftCornerIndex+1; //up_leftCornerIndex will be the ActualTop
+
+ if(up_rightCornerWhere != 2) //right corner is not on right chain
+ ActualRightEnd = rightStartIndex-1; //meaning that there is no actual rigth section
+ else
+ ActualRightEnd = up_rightCornerIndex;
+
+ vertexArray ActualRightChain(max(0, ActualRightEnd-ActualRightStart+1) + gridRightU-gridLeftU+1);
+
+ for(i=ActualRightStart; i<= ActualRightEnd; i++)
+ ActualRightChain.appendVertex(rightChain->getVertex(i));
+ for(i=0; i<gridRightU-gridLeftU+1; i++)
+ ActualRightChain.appendVertex(gridPoints[i]);
+
+ //determine ActualLeftEnd
+ if(up_leftCornerWhere != 0)
+ ActualLeftEnd = leftStartIndex-1;
+ else
+ ActualLeftEnd = up_leftCornerIndex;
+
+ if(up_rightCornerWhere != 0)
+ ActualLeftStart = leftStartIndex;
+ else
+ ActualLeftStart = up_rightCornerIndex+1; //up_rightCornerIndex will be the actual top
+
+ if(up_leftCornerWhere == 0)
+ {
+ if(up_rightCornerWhere == 0)
+ ActualTop = leftChain->getVertex(up_rightCornerIndex);
+ else
+ ActualTop = topVertex;
+ }
+ else if(up_leftCornerWhere == 1)
+ ActualTop = topVertex;
+ else //up_leftCornerWhere == 2
+ ActualTop = rightChain->getVertex(up_leftCornerIndex);
+
+ ActualBot = gridPoints[gridRightU - gridLeftU];
+
+
+
+
+ if(leftChain->getVertex(ActualLeftEnd)[1] == ActualBot[1])
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, leftChain->getVertex(ActualLeftEnd),
+ leftChain,
+ ActualLeftStart, ActualLeftEnd-1,
+ &ActualRightChain,
+ 0,
+ ActualRightChain.getNumElements()-1,
+ pStream);
+
+ }
+ else
+ {
+/*
+ monoTriangulationRecGenOpt(ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+*/
+
+ sampleCompTopSimpleOpt(grid, gridV,
+ ActualTop, ActualBot, leftChain,
+ ActualLeftStart, ActualLeftEnd,
+ &ActualRightChain,
+ 0, ActualRightChain.getNumElements()-2, //the last is the bot.
+ pStream);
+
+
+ }
+
+ free(gridPoints);
+
+}
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
new file mode 100644
index 000000000..95598d63a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleCompTop.h
@@ -0,0 +1,67 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLECOMPTOP_H
+#define _SAMPLECOMPTOP_H
+
+#include "sampleMonoPoly.h"
+
+void sampleCompTop(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+void sampleCompTopSimple(Real* topVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int up_leftCornerWhere,
+ Int up_leftCornerIndex,
+ Int up_rightCornerWhere,
+ Int up_rightCornerIndex,
+ primStream* pStream);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
new file mode 100644
index 000000000..051f24108
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.cc
@@ -0,0 +1,2427 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifndef max
+#define max(a,b) ((a>b)? a:b)
+#endif
+#ifndef min
+#define min(a,b) ((a>b)? b:a)
+#endif
+
+#include <GL/gl.h>
+
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampleMonoPoly.h"
+#include "sampleComp.h"
+#include "polyDBG.h"
+#include "partitionX.h"
+
+
+#define ZERO 0.00001
+
+//#define MYDEBUG
+
+//#define SHORTEN_GRID_LINE
+//see work/newtess/internal/test/problems
+
+
+/*split a polygon so that each vertex correcpond to one edge
+ *the head of the first edge of the returned plygon must be the head of the first
+ *edge of the origianl polygon. This is crucial for the code in sampleMonoPoly function
+ */
+ directedLine* polygonConvert(directedLine* polygon)
+{
+ int i;
+ directedLine* ret;
+ sampledLine* sline;
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(0));
+ sline->setPoint(1, polygon->getVertex(1));
+ ret=new directedLine(INCREASING, sline);
+ for(i=1; i<= polygon->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, polygon->getVertex(i));
+ sline->setPoint(1, polygon->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+
+ for(directedLine *temp = polygon->getNext(); temp != polygon; temp = temp->getNext())
+ {
+ for(i=0; i<= temp->get_npoints()-2; i++)
+ {
+ sline = new sampledLine(2);
+ sline->setPoint(0, temp->getVertex(i));
+ sline->setPoint(1, temp->getVertex(i+1));
+ ret->insert(new directedLine(INCREASING, sline));
+ }
+ }
+ return ret;
+}
+
+void triangulateConvexPolyVertical(directedLine* topV, directedLine* botV, primStream *pStream)
+{
+ Int i,j;
+ Int n_leftVerts;
+ Int n_rightVerts;
+ Real** leftVerts;
+ Real** rightVerts;
+ directedLine* tempV;
+ n_leftVerts = 0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ n_leftVerts += tempV->get_npoints();
+ }
+ n_rightVerts=0;
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ n_rightVerts += tempV->get_npoints();
+ }
+
+ Real2* temp_leftVerts = (Real2 *) malloc(sizeof(Real2) * n_leftVerts);
+ assert(temp_leftVerts);
+ Real2* temp_rightVerts = (Real2 *) malloc(sizeof(Real2) * n_rightVerts);
+ assert(temp_rightVerts);
+
+ leftVerts = (Real**) malloc(sizeof(Real2*) * n_leftVerts);
+ assert(leftVerts);
+ rightVerts = (Real**) malloc(sizeof(Real2*) * n_rightVerts);
+ assert(rightVerts);
+ for(i=0; i<n_leftVerts; i++)
+ leftVerts[i] = temp_leftVerts[i];
+ for(i=0; i<n_rightVerts; i++)
+ rightVerts[i] = temp_rightVerts[i];
+
+ i=0;
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ for(j=1; j<tempV->get_npoints(); j++)
+ {
+ leftVerts[i][0] = tempV->getVertex(j)[0];
+ leftVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_leftVerts = i;
+ i=0;
+ for(tempV = topV->getPrev(); tempV != botV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=1; j--)
+ {
+ rightVerts[i][0] = tempV->getVertex(j)[0];
+ rightVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ n_rightVerts = i;
+ triangulateXYMonoTB(n_leftVerts, leftVerts, n_rightVerts, rightVerts, pStream);
+ free(leftVerts);
+ free(rightVerts);
+ free(temp_leftVerts);
+ free(temp_rightVerts);
+}
+
+void triangulateConvexPolyHoriz(directedLine* leftV, directedLine* rightV, primStream *pStream)
+{
+ Int i,j;
+ Int n_lowerVerts;
+ Int n_upperVerts;
+ Real2 *lowerVerts;
+ Real2 *upperVerts;
+ directedLine* tempV;
+ n_lowerVerts=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ n_lowerVerts += tempV->get_npoints();
+ }
+ n_upperVerts=0;
+ for(tempV = rightV; tempV != leftV; tempV = tempV->getNext())
+ {
+ n_upperVerts += tempV->get_npoints();
+ }
+ lowerVerts = (Real2 *) malloc(sizeof(Real2) * n_lowerVerts);
+ assert(n_lowerVerts);
+ upperVerts = (Real2 *) malloc(sizeof(Real2) * n_upperVerts);
+ assert(n_upperVerts);
+ i=0;
+ for(tempV = leftV; tempV != rightV; tempV = tempV->getNext())
+ {
+ for(j=0; j<tempV->get_npoints(); j++)
+ {
+ lowerVerts[i][0] = tempV->getVertex(j)[0];
+ lowerVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ i=0;
+ for(tempV = leftV->getPrev(); tempV != rightV->getPrev(); tempV = tempV->getPrev())
+ {
+ for(j=tempV->get_npoints()-1; j>=0; j--)
+ {
+ upperVerts[i][0] = tempV->getVertex(j)[0];
+ upperVerts[i][1] = tempV->getVertex(j)[1];
+ i++;
+ }
+ }
+ triangulateXYMono(n_upperVerts, upperVerts, n_lowerVerts, lowerVerts, pStream);
+ free(lowerVerts);
+ free(upperVerts);
+}
+void triangulateConvexPoly(directedLine* polygon, Int ulinear, Int vlinear, primStream* pStream)
+{
+ /*find left, right, top , bot
+ */
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ directedLine* leftV;
+ directedLine* rightV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+ //find leftV
+ for(tempV = topV; tempV != botV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] >= tempV->head()[0])
+ break;
+ }
+ leftV = tempV;
+ //find rightV
+ for(tempV = botV; tempV != topV; tempV = tempV->getNext())
+ {
+ if(tempV->tail()[0] <= tempV->head()[0])
+ break;
+ }
+ rightV = tempV;
+ if(vlinear)
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else if(ulinear)
+ {
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+ else
+ {
+ if(DBG_is_U_direction(polygon))
+ {
+ triangulateConvexPolyHoriz( leftV, rightV, pStream);
+ }
+ else
+ triangulateConvexPolyVertical(topV, botV, pStream);
+ }
+}
+
+/*for debug purpose*/
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex)
+{
+ Real* leftCornerV;
+ Real* rightCornerV;
+ Real* bot_leftCornerV;
+ Real* bot_rightCornerV;
+
+ if(leftCornerWhere == 1)
+ leftCornerV = topV;
+ else if(leftCornerWhere == 0)
+ leftCornerV = leftChain->getVertex(leftCornerIndex);
+ else
+ leftCornerV = rightChain->getVertex(leftCornerIndex);
+
+ if(rightCornerWhere == 1)
+ rightCornerV = topV;
+ else if(rightCornerWhere == 0)
+ rightCornerV = leftChain->getVertex(rightCornerIndex);
+ else
+ rightCornerV = rightChain->getVertex(rightCornerIndex);
+
+ if(bot_leftCornerWhere == 1)
+ bot_leftCornerV = botV;
+ else if(bot_leftCornerWhere == 0)
+ bot_leftCornerV = leftChain->getVertex(bot_leftCornerIndex);
+ else
+ bot_leftCornerV = rightChain->getVertex(bot_leftCornerIndex);
+
+ if(bot_rightCornerWhere == 1)
+ bot_rightCornerV = botV;
+ else if(bot_rightCornerWhere == 0)
+ bot_rightCornerV = leftChain->getVertex(bot_rightCornerIndex);
+ else
+ bot_rightCornerV = rightChain->getVertex(bot_rightCornerIndex);
+
+ Real topGridV = leftGridChain->get_v_value(gridIndex1);
+ Real topGridU1 = leftGridChain->get_u_value(gridIndex1);
+ Real topGridU2 = rightGridChain->get_u_value(gridIndex1);
+ Real botGridV = leftGridChain->get_v_value(gridIndex2);
+ Real botGridU1 = leftGridChain->get_u_value(gridIndex2);
+ Real botGridU2 = rightGridChain->get_u_value(gridIndex2);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(leftCornerV);
+ glVertex2f(topGridU1, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(rightCornerV);
+ glVertex2f(topGridU2, topGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_leftCornerV);
+ glVertex2f(botGridU1, botGridV);
+ glEnd();
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(bot_rightCornerV);
+ glVertex2f(botGridU2, botGridV);
+ glEnd();
+
+
+}
+
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain)
+{
+ Int i;
+ directedLine* tempV;
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+}
+
+
+void findTopAndBot(directedLine* polygon, directedLine*& topV, directedLine*& botV)
+{
+ assert(polygon);
+ directedLine* tempV;
+ topV = botV = polygon;
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+ botV = tempV;
+ }
+ }
+}
+
+void findGridChains(directedLine* topV, directedLine* botV,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain)
+{
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+
+ if(botV->head()[1] < grid->get_v_min())
+ lastGridIndex = 0;
+ else
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ leftGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ rightGridChain = new gridBoundaryChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("*************enter find donw corner\n");
+printf("finddownCorner: v=%f, uleft=%f, uright=%f\n", v, uleft, uright);
+printf("(%i,%i,%i,%i)\n", leftChainStartIndex, leftChainEndIndex,rightChainStartIndex, rightChainEndIndex);
+printf("left chain is\n");
+leftChain->print();
+printf("right chain is\n");
+rightChain->print();
+#endif
+
+ assert(v > botVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexBelowGen(v, leftChainStartIndex, leftChainEndIndex);
+ index2 = rightChain->findIndexBelowGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2 <= rightChainEndIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1>leftChainEndIndex && index2 > rightChainEndIndex) /*no point below v on left chain or right chain*/
+ {
+
+ /*the botVertex is the only vertex below v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1>leftChainEndIndex ) /*index2 <= rightChainEndIndex*/
+ {
+
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+
+
+ //we consider whether we can use botVertex as left corner. First check
+ //if (leftGirdPoint, botVertex) interesects right chian or not.
+ if(DBG_intersectChain(rightChain, rightChainStartIndex,rightChainEndIndex,
+ leftGridPoint, botVertex))
+ {
+ ret_leftCornerWhere = 2;//right
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(botVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; //bot
+ else
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = tempI;
+ }
+ }
+ else if(index2> rightChainEndIndex) /*index1<=leftChainEndIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ /*find the vertex on the left chain with the maximum u,
+ *either this vertex or the botvertex can be used as the right corner
+ */
+
+ Int tempI;
+ //skip those points which are equal to v. (avoid degeneratcy)
+ for(tempI = index1; tempI <= leftChainEndIndex; tempI++)
+ if(leftChain->getVertex(tempI)[1] < v)
+ break;
+ if(tempI > leftChainEndIndex)
+ ret_rightCornerWhere = 1;
+ else
+ {
+ Real tempMax = leftChain->getVertex(tempI)[0];
+ for(i=tempI; i<= leftChainEndIndex; i++)
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+
+
+
+ //we consider whether we can use botVertex as a corner. So first we check
+ //whether (rightGridPoint, botVertex) interescts the left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, botVertex))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(botVertex[0] > tempMax)
+ {
+
+ ret_rightCornerWhere = 1;
+ }
+ else
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = tempI;
+ }
+ }
+
+ }
+ else /*index1<=leftChainEndIndex and index2 <=rightChainEndIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] >= rightChain->getVertex(index2)[1]) /*left point above right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left above the right point index2*/
+ for(i=index1+1; i<= leftChainEndIndex; i++)
+ {
+ if(leftChain->getVertex(i)[1] < rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //we consider if we can use rightChain(index2) as right corner
+ //we check if (rightChain(index2), rightGidPoint) intersecs left chain or not.
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1; //should use tempI???
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright
+ )
+ {
+
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left below right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right above the left poitn index1*/
+ for(i=index2+1; i<= rightChainEndIndex; i++)
+ {
+ if( rightChain->getVertex(i)[1] < leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+
+ //we consider if we can use leftchain(index1) as left corner.
+ //we check if (leftChain(index1) intersects right chian or not
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex, leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2;
+ ret_leftCornerIndex = index2; //should use tempI???
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+
+}
+
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_leftCornerIndex, /*useful when ret_leftCornerWhere == 0 or 2*/
+ Int& ret_rightCornerWhere, /*0: left chain, 1: topvertex, 2: rightchain*/
+ Int& ret_rightCornerIndex /*useful when ret_leftCornerWhere == 0 or 2*/
+ )
+{
+#ifdef MYDEBUG
+printf("***********enter findUpCorners\n");
+#endif
+
+ assert(v < topVertex[1]);
+ Real leftGridPoint[2];
+ leftGridPoint[0] = uleft;
+ leftGridPoint[1] = v;
+ Real rightGridPoint[2];
+ rightGridPoint[0] = uright;
+ rightGridPoint[1] = v;
+
+ Int i;
+ Int index1, index2;
+
+ index1 = leftChain->findIndexFirstAboveEqualGen(v, leftChainStartIndex, leftChainEndIndex);
+
+
+ index2 = rightChain->findIndexFirstAboveEqualGen(v, rightChainStartIndex, rightChainEndIndex);
+
+ if(index2>= leftChainStartIndex) //index2 was found above
+ index2 = rightChain->skipEqualityFromStart(v, index2, rightChainEndIndex);
+
+ if(index1<leftChainStartIndex && index2 <rightChainStartIndex) /*no point above v on left chain or right chain*/
+ {
+ /*the topVertex is the only vertex above v*/
+ ret_leftCornerWhere = 1;
+ ret_rightCornerWhere = 1;
+ }
+ else if(index1<leftChainStartIndex ) /*index2 >= rightChainStartIndex*/
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+
+ //find the minimum u on right top, either that, or top, or right[index2] is the left corner
+ Real tempMin = rightChain->getVertex(index2)[0];
+ Int tempI = index2;
+ for(i=index2-1; i>=rightChainStartIndex; i--)
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempMin = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ //chech whether (leftGridPoint, top) intersects rightchai,
+ //if yes, use right corner as left corner
+ //if not, use top or right[tempI] as left corner
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, topVertex))
+ {
+ ret_leftCornerWhere = 2; //rightChain
+ ret_leftCornerIndex = index2;
+ }
+ else if(topVertex[0] < tempMin)
+ ret_leftCornerWhere = 1; /*topvertex*/
+ else
+ {
+ ret_leftCornerWhere = 2; //right chain
+ ret_leftCornerIndex = tempI;
+ }
+
+ }
+ else if(index2< rightChainStartIndex) /*index1>=leftChainStartIndex*/
+ {
+ ret_leftCornerWhere = 0; /*left chain*/
+ ret_leftCornerIndex = index1;
+
+ //find the maximum u on the left top section. either that or topvertex, or left[index1] is the right corner
+ Real tempMax = leftChain->getVertex(index1)[0];
+ Int tempI = index1;
+
+ for(i=index1-1; i>=leftChainStartIndex; i--){
+
+ if(leftChain->getVertex(i)[0] > tempMax)
+ {
+
+ tempMax = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ }
+ //check whether (rightGridPoint, top) intersects leftChain or not
+ //if yes, we use leftCorner as the right corner
+ //if not, we use either top or left[tempI] as the right corner
+ if(DBG_intersectChain(leftChain, leftChainStartIndex,leftChainEndIndex,
+ rightGridPoint, topVertex))
+ {
+ ret_rightCornerWhere = 0; //left chan
+ ret_rightCornerIndex = index1;
+ }
+ else if(topVertex[0] > tempMax)
+ ret_rightCornerWhere = 1;//topVertex
+ else
+ {
+ ret_rightCornerWhere = 0;//left chain
+ ret_rightCornerIndex = tempI;
+ }
+ }
+ else /*index1>=leftChainStartIndex and index2 >=rightChainStartIndex*/
+ {
+ if(leftChain->getVertex(index1)[1] <= rightChain->getVertex(index2)[1]) /*left point below right point*/
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+
+ Real tempMax;
+ Int tempI;
+
+ tempI = index1;
+ tempMax = leftChain->getVertex(index1)[0];
+
+ /*find the maximum u for all the points on the left below the right point index2*/
+ for(i=index1-1; i>= leftChainStartIndex; i--)
+ {
+ if(leftChain->getVertex(i)[1] > rightChain->getVertex(index2)[1])
+ break;
+
+ if(leftChain->getVertex(i)[0]>tempMax)
+ {
+ tempI = i;
+ tempMax = leftChain->getVertex(i)[0];
+ }
+ }
+ //chek whether (rightChain(index2), rightGridPoint) intersects leftchian or not
+ if(DBG_intersectChain(leftChain, leftChainStartIndex, leftChainEndIndex, rightGridPoint, rightChain->getVertex(index2)))
+ {
+ ret_rightCornerWhere = 0;
+ ret_rightCornerIndex = index1;
+ }
+ else if(tempMax >= rightChain->getVertex(index2)[0] ||
+ tempMax >= uright)
+ {
+ ret_rightCornerWhere = 0; /*on left Chain*/
+ ret_rightCornerIndex = tempI;
+ }
+ else
+ {
+ ret_rightCornerWhere = 2; /*on right chain*/
+ ret_rightCornerIndex = index2;
+ }
+ }
+ else /*left above right*/
+ {
+ ret_rightCornerWhere = 2; /*on the right*/
+ ret_rightCornerIndex = index2;
+
+ Real tempMin;
+ Int tempI;
+
+ tempI = index2;
+ tempMin = rightChain->getVertex(index2)[0];
+
+ /*find the minimum u for all the points on the right below the left poitn index1*/
+ for(i=index2-1; i>= rightChainStartIndex; i--)
+ {
+ if( rightChain->getVertex(i)[1] > leftChain->getVertex(index1)[1])
+ break;
+ if(rightChain->getVertex(i)[0] < tempMin)
+ {
+ tempI = i;
+ tempMin = rightChain->getVertex(i)[0];
+ }
+ }
+ //check whether (leftGRidPoint,left(index1)) interesect right chain
+ if(DBG_intersectChain(rightChain, rightChainStartIndex, rightChainEndIndex,
+ leftGridPoint, leftChain->getVertex(index1)))
+ {
+ ret_leftCornerWhere = 2; //right
+ ret_leftCornerIndex = index2;
+ }
+ else if(tempMin <= leftChain->getVertex(index1)[0] ||
+ tempMin <= uleft)
+ {
+ ret_leftCornerWhere = 2; /* on right chain*/
+ ret_leftCornerIndex = tempI;
+ }
+ else
+ {
+ ret_leftCornerWhere = 0; /*on left chain*/
+ ret_leftCornerIndex = index1;
+ }
+ }
+ }
+#ifdef MYDEBUG
+printf("***********leave findUpCorners\n");
+#endif
+}
+
+//return 1 if neck exists, 0 othewise
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight)
+{
+/*
+printf("enter findNeckF, botleft, botright=%i,%i,gstartindex=%i\n",botLeftIndex,botRightIndex,gridStartIndex);
+printf("leftChain is\n");
+leftChain->print();
+printf("rightChain is\n");
+rightChain->print();
+*/
+
+ Int lowerGridIndex; //the grid below leftChain and rightChian vertices
+ Int i;
+ Int n_vlines = leftGridChain->get_nVlines();
+ Real v;
+ if(botLeftIndex >= leftChain->getNumElements() ||
+ botRightIndex >= rightChain->getNumElements())
+ return 0; //no neck exists
+
+ v=min(leftChain->getVertex(botLeftIndex)[1], rightChain->getVertex(botRightIndex)[1]);
+
+
+
+
+ for(i=gridStartIndex; i<n_vlines; i++)
+ if(leftGridChain->get_v_value(i) <= v &&
+ leftGridChain->getUlineIndex(i)<= rightGridChain->getUlineIndex(i))
+ break;
+
+ lowerGridIndex = i;
+
+ if(lowerGridIndex == n_vlines) //the two trm vertex are higher than all gridlines
+ return 0;
+ else
+ {
+ Int botLeft2, botRight2;
+/*
+printf("leftGridChain->get_v_)value=%f\n",leftGridChain->get_v_value(lowerGridIndex), botLeftIndex);
+printf("leftChain->get_vertex(0)=(%f,%f)\n", leftChain->getVertex(0)[0],leftChain->getVertex(0)[1]);
+printf("leftChain->get_vertex(1)=(%f,%f)\n", leftChain->getVertex(1)[0],leftChain->getVertex(1)[1]);
+printf("leftChain->get_vertex(2)=(%f,%f)\n", leftChain->getVertex(2)[0],leftChain->getVertex(2)[1]);
+*/
+ botLeft2 = leftChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botLeftIndex, leftChain->getNumElements()-1) -1 ;
+
+/*
+printf("botLeft2=%i\n", botLeft2);
+printf("leftChain->getNumElements=%i\n", leftChain->getNumElements());
+*/
+
+ botRight2 = rightChain->findIndexFirstAboveEqualGen(leftGridChain->get_v_value(lowerGridIndex), botRightIndex, rightChain->getNumElements()-1) -1;
+ if(botRight2 < botRightIndex) botRight2=botRightIndex;
+
+ if(botLeft2 < botLeftIndex) botLeft2 = botLeftIndex;
+
+ assert(botLeft2 >= botLeftIndex);
+ assert(botRight2 >= botRightIndex);
+ //find nectLeft so that it is th erightmost vertex on letChain
+
+ Int tempI = botLeftIndex;
+ Real temp = leftChain->getVertex(tempI)[0];
+ for(i=botLeftIndex+1; i<= botLeft2; i++)
+ if(leftChain->getVertex(i)[0] > temp)
+ {
+ temp = leftChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckLeft = tempI;
+
+ tempI = botRightIndex;
+ temp = rightChain->getVertex(tempI)[0];
+ for(i=botRightIndex+1; i<= botRight2; i++)
+ if(rightChain->getVertex(i)[0] < temp)
+ {
+ temp = rightChain->getVertex(i)[0];
+ tempI = i;
+ }
+ neckRight = tempI;
+ return 1;
+ }
+}
+
+
+
+/*find i>=botLeftIndex,j>=botRightIndex so that
+ *(leftChain[i], rightChain[j]) is a neck.
+ */
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ )
+{
+ assert(botLeftIndex < leftChain->getNumElements() &&
+ botRightIndex < rightChain->getNumElements());
+
+ /*now the neck exists for sure*/
+
+ if(leftChain->getVertex(botLeftIndex)[1] <= rightChain->getVertex(botRightIndex)[1]) //left below right
+ {
+
+ leftLastIndex = botLeftIndex;
+
+ /*find i so that rightChain[i][1] >= leftchainbotverte[1], and i+1<
+ */
+ rightLastIndex=rightChain->findIndexAboveGen(leftChain->getVertex(botLeftIndex)[1], botRightIndex+1, rightChain->getNumElements()-1);
+ }
+ else //left above right
+ {
+
+ rightLastIndex = botRightIndex;
+
+ leftLastIndex = leftChain->findIndexAboveGen(rightChain->getVertex(botRightIndex)[1],
+ botLeftIndex+1,
+ leftChain->getNumElements()-1);
+ }
+}
+
+
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k,isHoriz = 0;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that lastGridIndex<= firstGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vtail bigger than grid->...*/
+ directedLine* dLine = topEdge;
+ Real vtail = grid->get_v_value(firstGridIndex) + 1.0;
+ Real tempMaxU = grid->get_u_min();
+
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vtail > grid_v_value)
+ {
+ /*since the grid line is below the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vtail=dLine->tail()[1]) > grid_v_value){
+
+ tempMaxU = max(tempMaxU, dLine->tail()[0]);
+ dLine = dLine -> getNext();
+ }
+
+ if( fabs(dLine->head()[1] - vtail) < ZERO)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->head()[0] - dLine->tail()[0]) / (dLine->head()[1]-vtail);
+ }
+ }
+
+ if(isHoriz)
+ {
+ uinterc = max(dLine->head()[0], dLine->tail()[0]);
+ }
+ else
+ {
+ uinterc = slop * (grid_v_value - vtail) + dLine->tail()[0];
+ }
+
+ tempMaxU = max(tempMaxU, uinterc);
+
+ if(uinterc < uMin && uinterc >= uMin - ZERO)
+ uinterc = uMin;
+ if(uinterc > uMax && uinterc <= uMax + ZERO)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+ if(uinterc == uMax)
+ ret_indices[k] = n_ulines-1;
+ else
+ ret_indices[k] = (Int)(((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+ if(ret_indices[k] >= n_ulines)
+ ret_indices[k] = n_ulines-1;
+
+
+ ret_innerIndices[k] = (Int)(((tempMaxU-uMin)/(uMax - uMin)) * (n_ulines-1)) + 1;
+
+ /*reinitialize tempMaxU for next grdiLine*/
+ tempMaxU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]-1);
+ Real b = grid->get_u_value(ret_indices[k]);
+ assert(uintercBuf[k] >= a && uintercBuf < b);
+ if( (b-uintercBuf[k]) <= 0.2 * (b-a)) //interc is very close to b
+ {
+ ret_indices[k]++;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] < ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] < ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_innerIndices)
+{
+
+ Int i,k;
+ Int n_ulines = grid->get_n_ulines();
+ Real uMin = grid->get_u_min();
+ Real uMax = grid->get_u_max();
+ /*
+ Real vMin = grid->get_v_min();
+ Real vMax = grid->get_v_max();
+ */
+ Real slop = 0.0, uinterc;
+
+#ifdef SHORTEN_GRID_LINE
+ //uintercBuf stores all the interction u value for each grid line
+ //notice that firstGridIndex >= lastGridIndex
+ Real *uintercBuf = (Real *) malloc (sizeof(Real) * (firstGridIndex-lastGridIndex+1));
+ assert(uintercBuf);
+#endif
+
+ /*initialization to make vhead bigger than grid->v_value...*/
+ directedLine* dLine = topEdge->getPrev();
+ Real vhead = dLine->tail()[1];
+ Real tempMinU = grid->get_u_max();
+
+ /*for each grid line*/
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+
+ Real grid_v_value = grid->get_v_value(i);
+
+
+ /*check whether this grid line is below the current trim edge.*/
+ if(vhead >= grid_v_value)
+ {
+ /*since the grid line is below the tail of the trim edge, we
+ *find the trim edge which will contain the trim line
+ */
+ while( (vhead=dLine->head()[1]) > grid_v_value){
+ tempMinU = min(tempMinU, dLine->head()[0]);
+ dLine = dLine -> getPrev();
+ }
+
+ /*skip the equality in the case of degenerat case: horizontal */
+ while(dLine->head()[1] == grid_v_value)
+ dLine = dLine->getPrev();
+
+ assert( dLine->tail()[1] != dLine->head()[1]);
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-dLine->head()[1]);
+ /*
+ if(dLine->tail()[1] == vhead)
+ isHoriz = 1;
+ else
+ {
+ isHoriz = 0;
+ slop = (dLine->tail()[0] - dLine->head()[0]) / (dLine->tail()[1]-vhead);
+ }
+ */
+ }
+ uinterc = slop * (grid_v_value - dLine->head()[1]) + dLine->head()[0];
+
+ //in case unterc is outside of the grid due to floating point
+ if(uinterc < uMin)
+ uinterc = uMin;
+ else if(uinterc > uMax)
+ uinterc = uMax;
+
+#ifdef SHORTEN_GRID_LINE
+ uintercBuf[k] = uinterc;
+#endif
+
+ tempMinU = min(tempMinU, uinterc);
+
+ assert(uinterc >= uMin && uinterc <= uMax);
+
+ if(uinterc == uMin)
+ ret_indices[k] = 0;
+ else
+ ret_indices[k] = (int)ceil((((uinterc-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+/*
+if(ret_indices[k] >= grid->get_n_ulines())
+ {
+ printf("ERROR3\n");
+ exit(0);
+}
+if(ret_indices[k] < 0)
+ {
+ printf("ERROR4\n");
+ exit(0);
+}
+*/
+ ret_innerIndices[k] = (int)ceil ((((tempMinU-uMin)/(uMax - uMin)) * (n_ulines-1))) -1;
+
+ tempMinU = uinterc;
+ }
+#ifdef SHORTEN_GRID_LINE
+ //for each grid line, compare the left grid point with the
+ //intersection point. If the two points are too close, then
+ //we should move the grid point one grid to the right
+ //and accordingly we should update the inner index.
+ for(k=0, i=firstGridIndex; i>=lastGridIndex; i--, k++)
+ {
+ //check gridLine i
+ //check ret_indices[k]
+ Real a = grid->get_u_value(ret_indices[k]);
+ Real b = grid->get_u_value(ret_indices[k]+1);
+ assert(uintercBuf[k] > a && uintercBuf <= b);
+ if( (uintercBuf[k]-a) <= 0.2 * (b-a)) //interc is very close to a
+ {
+ ret_indices[k]--;
+ }
+
+ //check ret_innerIndices[k]
+ if(k>0)
+ {
+ if(ret_innerIndices[k] > ret_indices[k-1])
+ ret_innerIndices[k] = ret_indices[k-1];
+ if(ret_innerIndices[k] > ret_indices[k])
+ ret_innerIndices[k] = ret_indices[k];
+ }
+ }
+ //clean up
+ free(uintercBuf);
+#endif
+}
+
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream* pStream, rectBlockArray* rbArray)
+{
+/*
+{
+grid->print();
+polygon->writeAllPolygons("zloutputFile");
+exit(0);
+}
+*/
+
+if(grid->get_n_ulines() == 2 ||
+ grid->get_n_vlines() == 2)
+{
+ if(ulinear && grid->get_n_ulines() == 2)
+ {
+ monoTriangulationFun(polygon, compV2InY, pStream);
+ return;
+ }
+ else if(DBG_isConvex(polygon) && polygon->numEdges() >=4)
+ {
+ triangulateConvexPoly(polygon, ulinear, vlinear, pStream);
+ return;
+ }
+ else if(vlinear || DBG_is_U_direction(polygon))
+ {
+ Int n_cusps;//num interior cusps
+ Int n_edges = polygon->numEdges();
+ directedLine** cusps = (directedLine**) malloc(sizeof(directedLine*) * n_edges);
+ assert(cusps);
+ findInteriorCuspsX(polygon, n_cusps, cusps);
+
+ if(n_cusps == 0) //u_monotone
+ {
+
+ monoTriangulationFun(polygon, compV2InX, pStream);
+
+ free(cusps);
+ return;
+ }
+ else if(n_cusps == 1) //one interior cusp
+ {
+
+ directedLine* new_polygon = polygonConvert(cusps[0]);
+
+ directedLine* other = findDiagonal_singleCuspX( new_polygon);
+
+
+
+ //<other> should NOT be null unless there are self-intersecting
+ //trim curves. In that case, we don't want to core dump, instead,
+ //we triangulate anyway, and print out error message.
+ if(other == NULL)
+ {
+ monoTriangulationFun(polygon, compV2InX, pStream);
+ free(cusps);
+ return;
+ }
+
+ directedLine* ret_p1;
+ directedLine* ret_p2;
+
+ new_polygon->connectDiagonal_2slines(new_polygon, other,
+ &ret_p1,
+ &ret_p2,
+ new_polygon);
+
+ monoTriangulationFun(ret_p1, compV2InX, pStream);
+ monoTriangulationFun(ret_p2, compV2InX, pStream);
+
+ ret_p1->deleteSinglePolygonWithSline();
+ ret_p2->deleteSinglePolygonWithSline();
+
+ free(cusps);
+ return;
+ }
+ free(cusps);
+ }
+}
+
+ /*find the top and bottom of the polygon. It is supposed to be
+ *a V-monotone polygon
+ */
+
+ directedLine* tempV;
+ directedLine* topV;
+ directedLine* botV;
+ topV = botV = polygon;
+
+ for(tempV = polygon->getNext(); tempV != polygon; tempV = tempV->getNext())
+ {
+ if(compV2InY(topV->head(), tempV->head())<0) {
+
+ topV = tempV;
+ }
+ if(compV2InY(botV->head(), tempV->head())>0) {
+
+ botV = tempV;
+ }
+ }
+
+ /*find the first(top) and the last (bottom) grid line which intersect the
+ *this polygon
+ */
+ Int firstGridIndex; /*the index in the grid*/
+ Int lastGridIndex;
+ firstGridIndex = (Int) ((topV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1));
+ lastGridIndex = (Int) ((botV->head()[1] - grid->get_v_min()) / (grid->get_v_max() - grid->get_v_min()) * (grid->get_n_vlines()-1)) + 1;
+
+
+ /*find the interval inside the polygon for each gridline*/
+ Int *leftGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridIndices);
+ Int *rightGridIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridIndices);
+ Int *leftGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(leftGridInnerIndices);
+ Int *rightGridInnerIndices = (Int*) malloc(sizeof(Int) * (firstGridIndex - lastGridIndex +1));
+ assert(rightGridInnerIndices);
+
+ findLeftGridIndices(topV, firstGridIndex, lastGridIndex, grid, leftGridIndices, leftGridInnerIndices);
+
+ findRightGridIndices(topV, firstGridIndex, lastGridIndex, grid, rightGridIndices, rightGridInnerIndices);
+
+ gridBoundaryChain leftGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, leftGridIndices, leftGridInnerIndices);
+
+ gridBoundaryChain rightGridChain(grid, firstGridIndex, firstGridIndex-lastGridIndex+1, rightGridIndices, rightGridInnerIndices);
+
+
+
+// leftGridChain.draw();
+// leftGridChain.drawInner();
+// rightGridChain.draw();
+// rightGridChain.drawInner();
+ /*(1) determine the grid boundaries (left and right).
+ *(2) process polygon into two monotone chaines: use vertexArray
+ *(3) call sampleMonoPolyRec
+ */
+
+ /*copy the two chains into vertexArray datastructure*/
+ Int i;
+ vertexArray leftChain(20); /*this is a dynamic array*/
+ for(i=1; i<=topV->get_npoints()-2; i++) { /*the first vertex is the top vertex which doesn't belong to inc_chain*/
+ leftChain.appendVertex(topV->getVertex(i));
+ }
+ for(tempV = topV->getNext(); tempV != botV; tempV = tempV->getNext())
+ {
+ for(i=0; i<=tempV->get_npoints()-2; i++){
+ leftChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+
+ vertexArray rightChain(20);
+ for(tempV = topV->getPrev(); tempV != botV; tempV = tempV->getPrev())
+ {
+ for(i=tempV->get_npoints()-2; i>=0; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+ }
+ for(i=botV->get_npoints()-2; i>=1; i--){
+ rightChain.appendVertex(tempV->getVertex(i));
+ }
+
+ sampleMonoPolyRec(topV->head(),
+ botV->head(),
+ &leftChain,
+ 0,
+ &rightChain,
+ 0,
+ &leftGridChain,
+ &rightGridChain,
+ 0,
+ pStream,
+ rbArray);
+
+
+ /*cleanup space*/
+ free(leftGridIndices);
+ free(rightGridIndices);
+ free(leftGridInnerIndices);
+ free(rightGridInnerIndices);
+}
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray)
+{
+
+ /*find the first connected component, and the four corners.
+ */
+ Int index1, index2; /*the first and last grid line of the first connected component*/
+
+ if(topVertex[1] <= botVertex[1])
+ return;
+
+ /*find i so that the grid line is below the top vertex*/
+ Int i=gridStartIndex;
+ while (i < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->get_v_value(i) < topVertex[1])
+ break;
+ i++;
+ }
+
+ /*find the first connected component starting with i*/
+ /*find index1 so that left_uline_index <= right_uline_index, that is, this
+ *grid line contains at least one inner grid point
+ */
+ index1=i;
+ int num_skipped_grid_lines=0;
+ while(index1 < leftGridChain->get_nVlines())
+ {
+ if(leftGridChain->getUlineIndex(index1) <= rightGridChain->getUlineIndex(index1))
+ break;
+ num_skipped_grid_lines++;
+ index1++;
+ }
+
+
+
+ if(index1 >= leftGridChain->get_nVlines()) /*no grid line exists which has inner point*/
+ {
+ /*stop recursion, ...*/
+ /*monotone triangulate it...*/
+// printf("no grid line exists\n");
+/*
+ monoTriangulationRecOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+if(num_skipped_grid_lines <2)
+ {
+ monoTriangulationRecGenOpt(topVertex, botVertex, leftChain, leftStartIndex,
+ leftChain->getNumElements()-1,
+ rightChain, rightStartIndex,
+ rightChain->getNumElements()-1,
+ pStream);
+ }
+else
+ {
+ //the optimum way to triangulate is top-down since this polygon
+ //is narrow-long.
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+ }
+
+/*
+ monoTriangulationRec(topVertex, botVertex, leftChain, leftStartIndex,
+ rightChain, rightStartIndex, pStream);
+*/
+
+/* monoTriangulationRecGenTBOpt(topVertex, botVertex,
+ leftChain, leftStartIndex, leftChain->getNumElements()-1,
+ rightChain, rightStartIndex, rightChain->getNumElements()-1,
+ pStream);*/
+
+
+
+ }
+ else
+ {
+
+ /*find index2 so that left_inner_index <= right_inner_index holds until index2*/
+ index2=index1+1;
+ if(index2 < leftGridChain->get_nVlines())
+ while(leftGridChain->getInnerIndex(index2) <= rightGridChain->getInnerIndex(index2))
+ {
+ index2++;
+ if(index2 >= leftGridChain->get_nVlines())
+ break;
+ }
+
+ index2--;
+
+
+
+ /*the neck*/
+ Int neckLeftIndex;
+ Int neckRightIndex;
+
+ /*the four corners*/
+ Int up_leftCornerWhere;
+ Int up_leftCornerIndex;
+ Int up_rightCornerWhere;
+ Int up_rightCornerIndex;
+ Int down_leftCornerWhere;
+ Int down_leftCornerIndex;
+ Int down_rightCornerWhere;
+ Int down_rightCornerIndex;
+
+ Real* tempBotVertex; /*the bottom vertex for this component*/
+ Real* nextTopVertex=NULL; /*for the recursion*/
+ Int nextLeftStartIndex=0;
+ Int nextRightStartIndex=0;
+
+ /*find the points below the grid line index2 on both chains*/
+ Int botLeftIndex = leftChain->findIndexStrictBelowGen(
+ leftGridChain->get_v_value(index2),
+ leftStartIndex,
+ leftChain->getNumElements()-1);
+ Int botRightIndex = rightChain->findIndexStrictBelowGen(
+ rightGridChain->get_v_value(index2),
+ rightStartIndex,
+ rightChain->getNumElements()-1);
+ /*if either botLeftIndex>= numelements,
+ * or botRightIndex >= numelemnet,
+ *then there is no neck exists. the bottom vertex is botVertex,
+ */
+ if(! findNeckF(leftChain, botLeftIndex, rightChain, botRightIndex,
+ leftGridChain, rightGridChain, index2, neckLeftIndex, neckRightIndex))
+ /*
+ if(botLeftIndex == leftChain->getNumElements() ||
+ botRightIndex == rightChain->getNumElements())
+ */
+ {
+#ifdef MYDEBUG
+ printf("neck NOT exists, botRightIndex=%i\n", botRightIndex);
+#endif
+
+ tempBotVertex = botVertex;
+ nextTopVertex = botVertex;
+ botLeftIndex = leftChain->getNumElements()-1;
+ botRightIndex = rightChain->getNumElements()-1;
+ }
+ else /*neck exists*/
+ {
+#ifdef MYDEBUG
+ printf("neck exists\n");
+#endif
+
+ /*
+ findNeck(leftChain, botLeftIndex,
+ rightChain, botRightIndex,
+ neckLeftIndex,
+ neckRightIndex);
+ */
+#ifdef MYDEBUG
+printf("neck is found, neckLeftIndex=%i, neckRightIndex=%i\n", neckLeftIndex, neckRightIndex);
+glBegin(GL_LINES);
+glVertex2fv(leftChain->getVertex(neckLeftIndex));
+glVertex2fv(rightChain->getVertex(neckRightIndex));
+glEnd();
+#endif
+
+ if(leftChain->getVertex(neckLeftIndex)[1] <= rightChain->getVertex(neckRightIndex)[1])
+ {
+ tempBotVertex = leftChain->getVertex(neckLeftIndex);
+ botLeftIndex = neckLeftIndex-1;
+ botRightIndex = neckRightIndex;
+ nextTopVertex = rightChain->getVertex(neckRightIndex);
+ nextLeftStartIndex = neckLeftIndex;
+ nextRightStartIndex = neckRightIndex+1;
+ }
+ else
+ {
+ tempBotVertex = rightChain->getVertex(neckRightIndex);
+ botLeftIndex = neckLeftIndex;
+ botRightIndex = neckRightIndex-1;
+ nextTopVertex = leftChain->getVertex(neckLeftIndex);
+ nextLeftStartIndex = neckLeftIndex+1;
+ nextRightStartIndex = neckRightIndex;
+ }
+ }
+
+ findUpCorners(topVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index1),
+ leftGridChain->get_u_value(index1),
+ rightGridChain->get_u_value(index1),
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex);
+
+ findDownCorners(tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain->get_v_value(index2),
+ leftGridChain->get_u_value(index2),
+ rightGridChain->get_u_value(index2),
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+#ifdef MYDEBUG
+ printf("find corners done, down_leftwhere=%i, down_righwhere=%i,\n",down_leftCornerWhere, down_rightCornerWhere );
+ printf("find corners done, up_leftwhere=%i, up_righwhere=%i,\n",up_leftCornerWhere, up_rightCornerWhere );
+ printf("find corners done, up_leftindex=%i, up_righindex=%i,\n",up_leftCornerIndex, up_rightCornerIndex );
+ printf("find corners done, down_leftindex=%i, down_righindex=%i,\n",down_leftCornerIndex, down_rightCornerIndex );
+#endif
+
+/*
+ drawCorners(topVertex,
+ tempBotVertex,
+ leftChain,
+ rightChain,
+ leftGridChain,
+ rightGridChain,
+ index1,
+ index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex);
+*/
+
+
+ sampleConnectedComp(topVertex, tempBotVertex,
+ leftChain,
+ leftStartIndex, botLeftIndex,
+ rightChain,
+ rightStartIndex, botRightIndex,
+ leftGridChain,
+ rightGridChain,
+ index1, index2,
+ up_leftCornerWhere,
+ up_leftCornerIndex,
+ up_rightCornerWhere,
+ up_rightCornerIndex,
+ down_leftCornerWhere,
+ down_leftCornerIndex,
+ down_rightCornerWhere,
+ down_rightCornerIndex,
+ pStream,
+ rbArray
+ );
+
+ /*recursion*/
+
+ sampleMonoPolyRec(
+ nextTopVertex,
+ botVertex,
+ leftChain,
+ nextLeftStartIndex,
+ rightChain,
+ nextRightStartIndex,
+ leftGridChain,
+ rightGridChain,
+ index2+1,
+ pStream, rbArray);
+
+
+ }
+
+}
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ assert(leftChain->getVertex(topLeftIndex)[1] > leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(topLeftIndex+1)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex));
+ assert(leftChain->getVertex(botLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainEndIndex));
+ assert(leftChain->getVertex(botLeftIndex-1)[1] > leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*
+ *(1)find the last grid line which doesn'; pass below
+ * this first edge, sample this region: one trim edge and
+ * possily multiple grid lines.
+ */
+ Real *upperVert, *lowerVert; /*the end points of the first trim edge*/
+ upperVert = leftChain->getVertex(topLeftIndex);
+ lowerVert = leftChain->getVertex(topLeftIndex+1);
+
+ Int index = leftGridChainStartIndex;
+ while(leftGridChain->get_v_value(index) >= lowerVert[1]){
+ index++;
+ if(index > leftGridChainEndIndex)
+ break;
+ }
+ index--;
+
+ sampleLeftSingleTrimEdgeRegion(upperVert, lowerVert,
+ leftGridChain,
+ leftGridChainStartIndex,
+ index,
+ pStream);
+ sampleLeftStripRec(leftChain, topLeftIndex+1, botLeftIndex,
+ leftGridChain, index, leftGridChainEndIndex,
+ pStream);
+
+}
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex >= botLeftIndex, then stop.
+ */
+ if(topLeftIndex >= botLeftIndex)
+ return;
+
+ /*find the last trim vertex which is above the second top grid line:
+ * index1.
+ *and sampleLeftOneGridStep(leftchain, topLeftIndex, index1, leftGridChain,
+ * leftGridChainStartIndex).
+ * index1 could be equal to topLeftIndex.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+ assert(leftGridChainStartIndex < leftGridChainEndIndex);
+ Int index1 = topLeftIndex;
+ while(leftChain->getVertex(index1)[1] > secondGridChainV)
+ index1++;
+ index1--;
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*
+ * Let the next trim vertex be nextTrimVertIndex (which should be
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1);
+ Int index2 = leftGridChainStartIndex+1;
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /* sampleLeftStripRec(leftChain,
+ nextTrimVertIndex,
+ botLeftIndex,
+ leftGridChain,
+ index2,
+ leftGridChainEndIndex
+ )
+ *
+ */
+ sampleLeftStripRec(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+
+}
+
+
+/***************begin RecF***********************/
+/* the gridlines from leftGridChainStartIndex to
+ * leftGridChainEndIndex are assumed to form a
+ * connected component.
+ * the trim vertex of topLeftIndex is assumed to
+ * be below the first gridline, and the tim vertex
+ * of botLeftIndex is assumed to be above the last
+ * grid line.
+ * If botLeftIndex < topLeftIndex, then no connected componeent exists, and this funcion returns without
+ * outputing any triangles.
+ * Otherwise botLeftIndex >= topLeftIndex, there is at least one triangle to output.
+ */
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ )
+{
+ /*now top left trim vertex is below the top grid line.
+ */
+ /*stop condition: if topLeftIndex > botLeftIndex, then stop.
+ */
+ if(topLeftIndex > botLeftIndex)
+ return;
+
+ /*if there is only one grid Line, return.*/
+
+ if(leftGridChainStartIndex>=leftGridChainEndIndex)
+ return;
+
+
+ assert(leftChain->getVertex(topLeftIndex)[1] <= leftGridChain->get_v_value(leftGridChainStartIndex) &&
+ leftChain->getVertex(botLeftIndex)[1] >= leftGridChain->get_v_value(leftGridChainEndIndex));
+
+ /*firs find the first trim vertex which is below or equal to the second top grid line:
+ * index1.
+ */
+ Real secondGridChainV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+
+ Int index1 = topLeftIndex;
+
+ while(leftChain->getVertex(index1)[1] > secondGridChainV){
+ index1++;
+ if(index1>botLeftIndex)
+ break;
+ }
+
+ /*now leftChain->getVertex(index-1)[1] > secondGridChainV and
+ * leftChain->getVertex(index)[1] <= secondGridChainV
+ *If equality holds, then we should include the vertex index1, otherwise we include only index1-1, to
+ *perform sampleOneGridStep.
+ */
+ if(index1>botLeftIndex)
+ index1--;
+ else if(leftChain->getVertex(index1)[1] < secondGridChainV)
+ index1--;
+
+ /*now we have leftChain->getVertex(index1)[1] >= secondGridChainV, and
+ * leftChain->getVertex(index1+1)[1] <= secondGridChainV
+ */
+
+
+ sampleLeftOneGridStep(leftChain, topLeftIndex, index1, leftGridChain, leftGridChainStartIndex, pStream);
+
+
+ /*if leftChain->getVertex(index1)[1] == secondGridChainV, then we can recursively do the rest.
+ */
+ if(leftChain->getVertex(index1)[1] == secondGridChainV)
+ {
+
+ sampleLeftStripRecF(leftChain, index1, botLeftIndex,leftGridChain, leftGridChainStartIndex+1, leftGridChainEndIndex, pStream);
+ }
+ else if(index1 < botLeftIndex)
+ {
+
+ /* Otherwise, we have leftChain->getVertex(index1)[1] > secondGridChainV,
+ * let the next trim vertex be nextTrimVertIndex (which should be strictly
+ * below the second grid line).
+ * Find the last grid line index2 which is above nextTrimVert.
+ * sampleLeftSingleTrimEdgeRegion(uppervert[2], lowervert[2],
+ * leftGridChain, leftGridChainStartIndex+1, index2).
+ */
+ Real *uppervert, *lowervert;
+ uppervert = leftChain->getVertex(index1);
+ lowervert = leftChain->getVertex(index1+1); //okay since index1<botLeftIndex
+ Int index2 = leftGridChainStartIndex+1;
+
+
+ while(leftGridChain->get_v_value(index2) >= lowervert[1])
+ {
+ index2++;
+ if(index2 > leftGridChainEndIndex)
+ break;
+ }
+ index2--;
+
+
+ sampleLeftSingleTrimEdgeRegion(uppervert, lowervert, leftGridChain, leftGridChainStartIndex+1, index2, pStream);
+
+ /*recursion*/
+
+ sampleLeftStripRecF(leftChain, index1+1, botLeftIndex, leftGridChain, index2, leftGridChainEndIndex, pStream);
+ }
+
+}
+
+/***************End RecF***********************/
+
+/*sample the left area in between one trim edge and multiple grid lines.
+ * all the grid lines should be in between the two end poins of the
+ *trim edge.
+ */
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream)
+{
+ Int i,j,k;
+
+ vertexArray vArray(endIndex-beginIndex+1);
+ vArray.appendVertex(gridChain->get_vertex(beginIndex));
+
+ for(k=1, i=beginIndex+1; i<=endIndex; i++, k++)
+ {
+ vArray.appendVertex(gridChain->get_vertex(i));
+
+ /*output the fan of the grid points of the (i)th and (i-1)th grid line.
+ */
+ if(gridChain->getUlineIndex(i) < gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i-1));
+ for(j=gridChain->getUlineIndex(i); j<= gridChain->getUlineIndex(i-1); j++)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ else if(gridChain->getUlineIndex(i) > gridChain->getUlineIndex(i-1))
+ {
+ pStream->begin();
+ pStream->insert(gridChain->get_vertex(i));
+ for(j=gridChain->getUlineIndex(i); j>= gridChain->getUlineIndex(i-1); j--)
+ pStream->insert(gridChain->getGrid()->get_u_value(j), gridChain->get_v_value(i-1));
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+ /*otherwisem, the two are equal, so there is no fan to outout*/
+ }
+
+ monoTriangulation2(upperVert, lowerVert, &vArray, 0, endIndex-beginIndex,
+ 0, /*decreasing chain*/
+ pStream);
+}
+
+/*return i, such that from begin to i-1 the chain is strictly u-monotone.
+ */
+Int findIncreaseChainFromBegin(vertexArray* chain, Int begin ,Int end)
+{
+ Int i=begin;
+ Real prevU = chain->getVertex(i)[0];
+ Real thisU;
+ for(i=begin+1; i<=end; i++){
+ thisU = chain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ return i;
+}
+
+/*check whether there is a vertex whose v value is strictly
+ *inbetween vup vbelow
+ *if no middle exists return -1, else return the idnex.
+ */
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow)
+{
+ Int i;
+ for(i=begin; i<=end; i++)
+ {
+ if(chain->getVertex(i)[1] < vup && chain->getVertex(i)[1]>vbelow)
+ return i;
+ }
+ return -1;
+}
+
+/*the degenerat case of sampleLeftOneGridStep*/
+void sampleLeftOneGridStepNoMiddle(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream)
+{
+ /*since there is no middle, there is at most one point which is on the
+ *second grid line, there could be multiple points on the first (top)
+ *grid line.
+ */
+
+ leftGridChain->leftEndFan(leftGridChainStartIndex+1, pStream);
+
+ monoTriangulation2(leftGridChain->get_vertex(leftGridChainStartIndex),
+ leftGridChain->get_vertex(leftGridChainStartIndex+1),
+ leftChain,
+ beginLeftIndex,
+ endLeftIndex,
+ 1, //is increase chain.
+ pStream);
+}
+
+
+
+/*sampling the left area in between two grid lines.
+ */
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ )
+{
+ if(checkMiddle(leftChain, beginLeftIndex, endLeftIndex,
+ leftGridChain->get_v_value(leftGridChainStartIndex),
+ leftGridChain->get_v_value(leftGridChainStartIndex+1))<0)
+
+ {
+
+ sampleLeftOneGridStepNoMiddle(leftChain, beginLeftIndex, endLeftIndex, leftGridChain, leftGridChainStartIndex, pStream);
+ return;
+ }
+
+ //copy into a polygon
+ {
+ directedLine* poly = NULL;
+ sampledLine* sline;
+ directedLine* dline;
+ gridWrap* grid = leftGridChain->getGrid();
+ Real vert1[2];
+ Real vert2[2];
+ Int i;
+
+ Int innerInd = leftGridChain->getInnerIndex(leftGridChainStartIndex+1);
+ Int upperInd = leftGridChain->getUlineIndex(leftGridChainStartIndex);
+ Int lowerInd = leftGridChain->getUlineIndex(leftGridChainStartIndex+1);
+ Real upperV = leftGridChain->get_v_value(leftGridChainStartIndex);
+ Real lowerV = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ //the upper gridline
+ vert1[1] = vert2[1] = upperV;
+ for(i=innerInd; i>upperInd; i--)
+ {
+ vert1[0]=grid->get_u_value(i);
+ vert2[0]=grid->get_u_value(i-1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+ }
+
+ //the edge connecting upper grid with left chain
+ vert1[0] = grid->get_u_value(upperInd);
+ vert1[1] = upperV;
+ sline = new sampledLine(vert1, leftChain->getVertex(beginLeftIndex));
+ dline = new directedLine(INCREASING, sline);
+ if(poly == NULL)
+ poly = dline;
+ else
+ poly->insert(dline);
+
+ //the left chain
+ for(i=beginLeftIndex; i<endLeftIndex; i++)
+ {
+ sline = new sampledLine(leftChain->getVertex(i), leftChain->getVertex(i+1));
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the edge connecting left chain with lower gridline
+ vert2[0] = grid->get_u_value(lowerInd);
+ vert2[1] = lowerV;
+ sline = new sampledLine(leftChain->getVertex(endLeftIndex), vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+
+ //the lower grid line
+ vert1[1] = vert2[1] = lowerV;
+ for(i=lowerInd; i<innerInd; i++)
+ {
+ vert1[0] = grid->get_u_value(i);
+ vert2[0] = grid->get_u_value(i+1);
+ sline = new sampledLine(vert1, vert2);
+ dline = new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ }
+
+ //the vertical grid line segement
+ vert1[0]=vert2[0] = grid->get_u_value(innerInd);
+ vert2[1]=upperV;
+ vert1[1]=lowerV;
+ sline=new sampledLine(vert1, vert2);
+ dline=new directedLine(INCREASING, sline);
+ poly->insert(dline);
+ monoTriangulationOpt(poly, pStream);
+ //cleanup
+ poly->deleteSinglePolygonWithSline();
+ return;
+ }
+
+
+
+
+
+ Int i;
+ if(1/*leftGridChain->getUlineIndex(leftGridChainStartIndex) >=
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1)*/
+ ) /*the second grid line is beyond the first one to the left*/
+ {
+ /*find the maximal U-monotone chain
+ * of endLeftIndex, endLeftIndex-1, ...,
+ */
+ i=endLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=endLeftIndex-1; i>=beginLeftIndex; i--){
+ Real thisU = leftChain->getVertex(i)[0];
+ if( prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from endLeftIndex to i+1 is strictly U- monotone */
+ /*if i+1==endLeftIndex and the vertex and leftchain is on the second gridline, then
+ *we should use 2 vertices on the leftchain. If we only use one (endLeftIndex), then we
+ *we would output degenerate triangles
+ */
+ if(i+1 == endLeftIndex && leftChain->getVertex(endLeftIndex)[1] == leftGridChain->get_v_value(1+leftGridChainStartIndex))
+ i--;
+
+ Int j = beginLeftIndex/*endLeftIndex*/+1;
+
+
+ if(leftGridChain->getInnerIndex(leftGridChainStartIndex+1) > leftGridChain->getUlineIndex(leftGridChainStartIndex))
+ {
+ j = findIncreaseChainFromBegin(leftChain, beginLeftIndex, i+1/*endLeftIndex*/);
+
+ Int temp = beginLeftIndex;
+ /*now from begin to j-1 is strictly u-monotone*/
+ /*if j-1 is on the first grid line, then we want to skip to the vertex which is strictly
+ *below the grid line. This vertexmust exist since there is a 'corner turn' inbetween the two grid lines
+ */
+ if(j-1 == beginLeftIndex)
+ {
+ while(leftChain->getVertex(j-1)[1] == leftGridChain->get_v_value(leftGridChainStartIndex))
+ j++;
+
+ Real vert[2];
+ vert[0] = leftGridChain->get_u_value(leftGridChainStartIndex);
+ vert[1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+
+ monoTriangulation2(
+ vert/*leftChain->getVertex(beginLeftIndex)*/,
+ leftChain->getVertex(j-1),
+ leftChain,
+ beginLeftIndex,
+ j-2,
+ 1,
+ pStream //increase chain
+ );
+
+ temp = j-1;
+ }
+
+ stripOfFanLeft(leftChain, j-1, temp/*beginLeftIndex*/, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim line*/
+ );
+ }
+
+ stripOfFanLeft(leftChain, endLeftIndex, i+1, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ leftGridChain->getInnerIndex(leftGridChainStartIndex+1),
+ pStream,
+ 0 /*the grid line is below the trim lines*/
+ );
+
+ /*monotone triangulate the remaining left chain togther with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->getInner_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+// vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], /*top vertex */
+ &vert[1][0], /*bottom vertex*/
+ leftChain,
+ /*beginLeftIndex*/j-1,
+ i+1,
+ 1, /*an increasing chain*/
+ pStream);
+ }
+ else /*the second one is shorter than the first one to the left*/
+ {
+ /*find the maximal U-monotone chain of beginLeftIndex, beginLeftIndex+1,...,
+ */
+ i=beginLeftIndex;
+ Real prevU = leftChain->getVertex(i)[0];
+ for(i=beginLeftIndex+1; i<=endLeftIndex; i++){
+ Real thisU = leftChain->getVertex(i)[0];
+
+ if(prevU < thisU){
+ prevU = thisU;
+ }
+ else
+ break;
+ }
+ /*from beginLeftIndex to i-1 is strictly U-monotone*/
+
+
+ stripOfFanLeft(leftChain, i-1, beginLeftIndex, leftGridChain->getGrid(),
+ leftGridChain->getVlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex),
+ leftGridChain->getUlineIndex(leftGridChainStartIndex+1),
+ pStream,
+ 1 /*the grid line is above the trim lines*/
+ );
+ /*monotone triangulate the remaining left chain together with the
+ *two vertices on the two grid v-lines.
+ */
+ Real vert[2][2];
+ vert[0][0]=vert[1][0] = leftGridChain->get_u_value(leftGridChainStartIndex+1);
+ vert[0][1] = leftGridChain->get_v_value(leftGridChainStartIndex);
+ vert[1][1] = leftGridChain->get_v_value(leftGridChainStartIndex+1);
+
+ vertexArray right(vert, 2);
+
+ monoTriangulation2(
+ &vert[0][0], //top vertex
+ &vert[1][0], //bottom vertex
+ leftChain,
+ i-1,
+ endLeftIndex,
+ 1, /*an increase chain*/
+ pStream);
+
+ }
+}
+
+/*n_upper>=1
+ *n_lower>=1
+ */
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream)
+{
+ Int i,j,k,l;
+ Real* leftMostV;
+
+ assert(n_upper>=1 && n_lower>=1);
+ if(upperVerts[0][0] <= lowerVerts[0][0])
+ {
+ i=1;
+ j=0;
+ leftMostV = upperVerts[0];
+ }
+ else
+ {
+ i=0;
+ j=1;
+ leftMostV = lowerVerts[0];
+ }
+
+ while(1)
+ {
+ if(i >= n_upper) /*case1: no more in upper*/
+ {
+
+ if(j<n_lower-1) /*at least two vertices in lower*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+ while(j<n_lower){
+ pStream->insert(lowerVerts[j]);
+ j++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else if(j>= n_lower) /*case2: no more in lower*/
+ {
+
+ if(i<n_upper-1) /*at least two vertices in upper*/
+ {
+ pStream->begin();
+ pStream->insert(leftMostV);
+
+ for(k=n_upper-1; k>=i; k--)
+ pStream->insert(upperVerts[k]);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ }
+
+ break;
+ }
+ else /* case3: neither is empty, plus the leftMostV, there is at least one triangle to output*/
+ {
+
+ if(upperVerts[i][0] <= lowerVerts[j][0])
+ {
+ pStream->begin();
+ pStream->insert(lowerVerts[j]); /*the origin of this fan*/
+
+ /*find the last k>=i such that
+ *upperverts[k][0] <= lowerverts[j][0]
+ */
+ k=i;
+ while(k<n_upper)
+ {
+ if(upperVerts[k][0] > lowerVerts[j][0])
+ break;
+ k++;
+ }
+ k--;
+ for(l=k; l>=i; l--)/*the reverse is for two-face lighting*/
+ {
+ pStream->insert(upperVerts[l]);
+ }
+ pStream->insert(leftMostV);
+
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ //update i for next loop
+ i = k+1;
+ leftMostV = upperVerts[k];
+
+ }
+ else /*upperVerts[i][0] > lowerVerts[j][0]*/
+ {
+ pStream->begin();
+ pStream->insert(upperVerts[i]);/*the origion of this fan*/
+ pStream->insert(leftMostV);
+ /*find the last k>=j such that
+ *lowerverts[k][0] < upperverts[i][0]*/
+ k=j;
+ while(k< n_lower)
+ {
+ if(lowerVerts[k][0] >= upperVerts[i][0])
+ break;
+ pStream->insert(lowerVerts[k]);
+ k++;
+ }
+ pStream->end(PRIMITIVE_STREAM_FAN);
+ j=k;
+ leftMostV = lowerVerts[j-1];
+ }
+ }
+ }
+}
+
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp /*1 if the grid line is above the trim lines*/
+ )
+{
+ assert(largeIndex >= smallIndex);
+
+ Real grid_v_value;
+ grid_v_value = grid->get_v_value(vlineIndex);
+
+ Real2* trimVerts=(Real2*) malloc(sizeof(Real2)* (largeIndex-smallIndex+1));
+ assert(trimVerts);
+
+
+ Real2* gridVerts=(Real2*) malloc(sizeof(Real2)* (ulineLargeIndex-ulineSmallIndex+1));
+ assert(gridVerts);
+
+ Int k,i;
+ if(gridLineUp) /*trim line is below grid line, so trim vertices are going right when index increases*/
+ for(k=0, i=smallIndex; i<=largeIndex; i++, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+ else
+ for(k=0, i=largeIndex; i>=smallIndex; i--, k++)
+ {
+ trimVerts[k][0] = leftChain->getVertex(i)[0];
+ trimVerts[k][1] = leftChain->getVertex(i)[1];
+ }
+
+ for(k=0, i=ulineSmallIndex; i<= ulineLargeIndex; i++, k++)
+ {
+ gridVerts[k][0] = grid->get_u_value(i);
+ gridVerts[k][1] = grid_v_value;
+ }
+
+ if(gridLineUp)
+ triangulateXYMono(
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ largeIndex-smallIndex+1, trimVerts,
+ pStream);
+ else
+ triangulateXYMono(largeIndex-smallIndex+1, trimVerts,
+ ulineLargeIndex-ulineSmallIndex+1, gridVerts,
+ pStream);
+ free(trimVerts);
+ free(gridVerts);
+}
+
+
+
+
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
new file mode 100644
index 000000000..3a5fa6c91
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampleMonoPoly.h
@@ -0,0 +1,184 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLEMONOPOLY_H
+#define _SAMPLEMONOPOLY_H
+
+#include "monoTriangulation.h"
+#include "gridWrap.h"
+#include "rectBlock.h"
+
+
+void triangulateXYMono(Int n_upper, Real upperVerts[][2],
+ Int n_lower, Real lowerVerts[][2],
+ primStream* pStream);
+
+void stripOfFanLeft(vertexArray* leftChain,
+ Int largeIndex,
+ Int smallIndex,
+ gridWrap* grid,
+ Int vlineIndex,
+ Int ulineSmallIndex,
+ Int ulineLargeIndex,
+ primStream* pStream,
+ Int gridLineUp
+ );
+void sampleLeftOneGridStep(vertexArray* leftChain,
+ Int beginLeftIndex,
+ Int endLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ primStream* pStream
+ );
+
+void sampleLeftSingleTrimEdgeRegion(Real upperVert[2], Real lowerVert[2],
+ gridBoundaryChain* gridChain,
+ Int beginIndex,
+ Int endIndex,
+ primStream* pStream);
+
+void sampleLeftStripRec(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void sampleLeftStrip(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findLeftGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void findRightGridIndices(directedLine* topEdge, Int firstGridIndex, Int lastGridIndex, gridWrap* grid, Int* ret_indices, Int* ret_inner);
+
+void sampleMonoPoly(directedLine* polygon, gridWrap* grid, Int ulinear, Int vlinear, primStream *pStream, rectBlockArray* rbArray);
+
+void sampleMonoPolyRec(
+ Real* topVertex,
+ Real* botVertex,
+ vertexArray* leftChain,
+ Int leftStartIndex,
+ vertexArray* rightChain,
+ Int rightStartIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ primStream* pStream,
+ rectBlockArray* rbArray
+ );
+
+void sampleLeftStripRecF(vertexArray* leftChain,
+ Int topLeftIndex,
+ Int botLeftIndex,
+ gridBoundaryChain* leftGridChain,
+ Int leftGridChainStartIndex,
+ Int leftGridChainEndIndex,
+ primStream* pStream
+ );
+
+void findUpCorners(Real *topVertex,
+ vertexArray *leftChain,
+ Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain,
+ Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findDownCorners(Real *botVertex,
+ vertexArray *leftChain, Int leftChainStartIndex, Int leftChainEndIndex,
+ vertexArray *rightChain, Int rightChainStartIndex, Int rightChainEndIndex,
+ Real v,
+ Real uleft,
+ Real uright,
+ Int& ret_leftCornerWhere,
+ Int& ret_leftCornerIndex,
+ Int& ret_rightCornerWhere,
+ Int& ret_rightCornerIndex
+ );
+void findNeck(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ Int& leftLastIndex, /*left point of the neck*/
+ Int& rightLastIndex /*right point of the neck*/
+ );
+
+Int findNeckF(vertexArray *leftChain, Int botLeftIndex,
+ vertexArray *rightChain, Int botRightIndex,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridStartIndex,
+ Int& neckLeft,
+ Int& neckRight);
+
+void findTopAndBot(directedLine* polygon,
+ directedLine*& topV,
+ directedLine*& botV);
+void findGridChains(directedLine* top, directedLine* bot,
+ gridWrap* grid,
+ gridBoundaryChain*& leftGridChain,
+ gridBoundaryChain*& rightGridChain);
+void toVertexArrays(directedLine* topV, directedLine* botV, vertexArray& leftChain, vertexArray& rightChain);
+
+void drawCorners(
+ Real* topV, Real* botV,
+ vertexArray* leftChain,
+ vertexArray* rightChain,
+ gridBoundaryChain* leftGridChain,
+ gridBoundaryChain* rightGridChain,
+ Int gridIndex1,
+ Int gridIndex2,
+ Int leftCornerWhere,
+ Int leftCornerIndex,
+ Int rightCornerWhere,
+ Int rightCornerIndex,
+ Int bot_leftCornerWhere,
+ Int bot_leftCornerIndex,
+ Int bot_rightCornerWhere,
+ Int bot_rightCornerIndex);
+
+Int checkMiddle(vertexArray* chain, Int begin, Int end,
+ Real vup, Real vbelow);
+
+#endif
+
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
new file mode 100644
index 000000000..6253a7c09
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.cc
@@ -0,0 +1,179 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h> //for fabs()
+#include "glimports.h"
+#include "zlassert.h"
+#include "sampledLine.h"
+
+void sampledLine::setPoint(Int i, Real p[2])
+{
+ points[i][0]=p[0];
+ points[i][1]=p[1];
+}
+
+
+/*insert this single line in front of the oldList*/
+sampledLine* sampledLine::insert(sampledLine *oldList)
+{
+ next = oldList;
+ return this;
+}
+
+void sampledLine::deleteList()
+{
+ sampledLine *temp, *tempNext;
+ for(temp = this; temp != NULL; temp = tempNext)
+ {
+ tempNext = temp->next;
+ delete temp;
+ }
+}
+
+
+/*space of points[][2] is allocated*/
+sampledLine::sampledLine(Int n_points)
+{
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ next = NULL;
+}
+
+/*space of points[][2] is allocated and
+ *points are copied
+ */
+sampledLine::sampledLine(Int n_points, Real2 pts[])
+{
+ int i;
+ npoints = n_points;
+ points = (Real2*) malloc(sizeof(Real2) * n_points);
+ assert(points);
+ for(i=0; i<npoints; i++) {
+ points[i][0] = pts[i][0];
+ points[i][1] = pts[i][1];
+ }
+ next = NULL;
+}
+
+sampledLine::sampledLine(Real pt1[2], Real pt2[2])
+{
+ npoints = 2;
+ points = (Real2*) malloc(sizeof(Real2) * 2);
+ assert(points);
+ points[0][0] = pt1[0];
+ points[0][1] = pt1[1];
+ points[1][0] = pt2[0];
+ points[1][1] = pt2[1];
+ next = NULL;
+}
+
+//needs tp call init to setup
+sampledLine::sampledLine()
+{
+}
+
+//warning: ONLY pointer is copies!!!
+void sampledLine::init(Int n_points, Real2 *pts)
+{
+ npoints = n_points;
+ points = pts;
+}
+
+/*points[] is dealocated
+ */
+sampledLine::~sampledLine()
+{
+ free(points);
+}
+
+void sampledLine::print()
+{
+ int i;
+ printf("npoints=%i\n", npoints);
+
+ for(i=0; i<npoints; i++){
+ printf("(%f,%f)\n", points[i][0], points[i][1]);
+ }
+
+}
+
+void sampledLine::tessellate(Real u_reso, Real v_reso)
+{
+ int i;
+
+ Int nu, nv, n;
+ nu = 1+(Int) (fabs((points[npoints-1][0] - points[0][0])) * u_reso);
+ nv = 1+(Int) (fabs((points[npoints-1][1] - points[0][1])) * v_reso);
+
+ if(nu > nv) n = nu;
+ else
+ n = nv;
+ if(n<1)
+ n = 1;
+ //du dv could be negative
+ Real du = (points[npoints-1][0] - points[0][0])/n;
+ Real dv = (points[npoints-1][1] - points[0][1])/n;
+ Real2 *temp = (Real2*) malloc(sizeof(Real2) * (n+1));
+ assert(temp);
+
+ Real u,v;
+ for(i=0, u=points[0][0], v=points[0][1]; i<n; i++, u+=du, v+=dv)
+ {
+ temp[i][0] = u;
+ temp[i][1] = v;
+ }
+ temp[n][0] = points[npoints-1][0];
+ temp[n][1] = points[npoints-1][1];
+
+ free(points);
+
+ npoints = n+1;
+ points = temp;
+
+}
+
+void sampledLine::tessellateAll(Real u_reso, Real v_reso)
+{
+ sampledLine* temp;
+ for(temp = this; temp != NULL; temp = temp->next)
+ {
+ temp->tessellate(u_reso, v_reso);
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
new file mode 100644
index 000000000..2cc726948
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/sampledLine.h
@@ -0,0 +1,71 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SAMPLEDLINE_H
+#define _SAMPLEDLINE_H
+
+#include "definitions.h"
+
+class sampledLine{
+ Int npoints;
+ Real2 *points;
+
+public:
+ sampledLine(Int n_points);
+ sampledLine(Int n_points, Real pts[][2]);
+ sampledLine(Real pt1[2], Real pt2[2]);
+ sampledLine(); //special, careful about memory
+ ~sampledLine();
+
+ void init(Int n_points, Real2 *pts);//special, careful about memory
+
+ void setPoint(Int i, Real p[2]) ;
+
+ sampledLine* insert(sampledLine *nline);
+ void deleteList();
+
+ Int get_npoints() {return npoints;}
+ Real2* get_points() {return points;}
+
+ //u_reso is number of segments (may not be integer) per unit u
+ void tessellate(Real u_reso, Real v_reso);//n segments
+ void tessellateAll(Real u_reso, Real v_reso);
+
+ void print();
+
+ sampledLine* next;
+};
+
+
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
new file mode 100644
index 000000000..1865755a4
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.cc
@@ -0,0 +1,282 @@
+/*
+** License Applicability. Except to the extent portions of this file are
+** made subject to an alternative license as permitted in the SGI Free
+** Software License B, Version 1.1 (the "License"), the contents of this
+** file are subject only to the provisions of the License. You may not use
+** this file except in compliance with the License. You may obtain a copy
+** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+**
+** http://oss.sgi.com/projects/FreeB
+**
+** Note that, as provided in the License, the Software is distributed on an
+** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+**
+** Original Code. The Original Code is: OpenGL Sample Implementation,
+** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+** Copyright in any portions created by third parties is as indicated
+** elsewhere herein. All Rights Reserved.
+**
+** Additional Notice Provisions: The application programming interfaces
+** established by SGI in conjunction with the Original Code are The
+** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+** Window System(R) (Version 1.3), released October 19, 1998. This software
+** was created using the OpenGL(R) version 1.2.1 Sample Implementation
+** published by SGI, but has not been independently verified as being
+** compliant with the OpenGL(R) version 1.2.1 Specification.
+**
+*/
+/*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "zlassert.h"
+
+#include "searchTree.h"
+
+#define max(a,b) ((a>b)? a:b)
+
+treeNode* TreeNodeMake(void *key)
+{
+ treeNode *ret = (treeNode*) malloc(sizeof(treeNode));
+ assert(ret);
+ ret->key = key;
+ ret->parent = NULL;
+ ret->left = NULL;
+ ret->right = NULL;
+ return ret;
+}
+
+void TreeNodeDeleteSingleNode(treeNode* node)
+{
+ free(node);
+}
+
+void TreeNodeDeleteWholeTree(treeNode* node)
+{
+ if(node == NULL) return;
+ TreeNodeDeleteWholeTree(node->left);
+ TreeNodeDeleteWholeTree(node->right);
+ TreeNodeDeleteSingleNode(node);
+}
+
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*))
+{
+ if(node ==NULL) return;
+ TreeNodePrint(node->left, keyPrint);
+ keyPrint(node->key);
+ TreeNodePrint(node->right, keyPrint);
+}
+
+int TreeNodeDepth(treeNode* root)
+{
+ if(root == NULL) return 0;
+ else{
+ int leftdepth = TreeNodeDepth(root->left);
+ int rightdepth = TreeNodeDepth(root->right);
+ return 1 + max(leftdepth, rightdepth);
+ }
+}
+
+/*return the node with the key.
+ *NULL is returned if not found
+ */
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*))
+{
+ if(tree == NULL)
+ return NULL;
+ if(key == tree->key)
+ return tree;
+ else if(compkey(key, tree->key) < 0)
+ return TreeNodeFind(tree->left, key, compkey);
+ else
+ return TreeNodeFind(tree->right, key, compkey);
+}
+
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*compkey) (void *, void *))
+{
+ treeNode *y = NULL;
+ treeNode *x = root;
+ /*going down the tree from the root.
+ *x traces the path, y is the parent of x.
+ */
+ while (x != NULL){
+ y = x;
+ if(compkey(newnode->key,x->key) < 0) /*if newnode < x*/
+ x = x->left;
+ else
+ x = x->right;
+ }
+
+ /*now y has the property that
+ * if newnode < y, then y->left is NULL
+ * if newnode > y, then y->right is NULL.
+ *So we want to isnert newnode to be the child of y
+ */
+ newnode->parent = y;
+ if(y == NULL)
+ return newnode;
+ else if( compkey(newnode->key, y->key) <0)
+ {
+ y->left = newnode;
+ }
+ else
+ {
+ y->right = newnode;
+ }
+
+ return root;
+}
+
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node)
+{
+ treeNode* y;
+ treeNode* x;
+ treeNode* ret;
+ if(node==NULL) return tree;
+
+ if(node->left == NULL || node->right == NULL) {
+
+ y = node;
+ if(y->left != NULL)
+ x = y->left;
+ else
+ x = y->right;
+
+ if( x != NULL)
+ x->parent = y->parent;
+
+ if(y->parent == NULL) /*y is the root which has at most one child x*/
+ ret = x;
+ else /*y is not the root*/
+ {
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ ret = tree;
+ }
+ }
+ else { /*node has two children*/
+
+ y = TreeNodeSuccessor(node);
+ assert(y->left == NULL);
+
+ if(y == node->right) /*y is the right child if node*/
+ {
+ y->parent = node->parent;
+ y->left = node->left;
+ node->left->parent = y;
+
+ }
+ else /*y != node->right*/
+ {
+ x = y->right;
+ if(x!= NULL)
+ x->parent = y->parent;
+
+ assert(y->parent != NULL);
+ if(y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ /*move y to the position of node*/
+ y->parent = node->parent;
+ y->left = node->left;
+ y->right = node->right;
+ node->left->parent = y;
+ node->right->parent = y;
+ }
+ if(node->parent != NULL) {
+ if(node->parent->left == node)
+ node->parent->left = y;
+ else
+ node->parent->right = y;
+ ret = tree; /*the root if the tree doesn't change*/
+ }
+ else /*node->parent is NULL: node is the root*/
+ ret = y;
+ }
+
+ /*finally free the node, and return the new root*/
+ TreeNodeDeleteSingleNode(node);
+ return ret;
+}
+
+
+/*the minimum node in the tree rooted by node
+ */
+treeNode* TreeNodeMinimum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->left != NULL) {
+ temp = temp->left;
+ }
+ return temp;
+}
+
+/*the maximum node in the tree rooted by node
+ */
+treeNode* TreeNodeMaximum(treeNode* node)
+{
+ treeNode* temp = node;
+ if(temp == NULL) return NULL;
+ while(temp->right != NULL) {
+ temp = temp->right;
+ }
+ return temp;
+}
+
+/*return the first node (in sorted order) which is to the right of this node
+ */
+treeNode* TreeNodeSuccessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->right != NULL)
+ return TreeNodeMinimum(node->right);
+ else{ /*node->right is NULL*/
+
+ /*find the first right-ancestor*/
+ treeNode *y = node->parent;
+ treeNode* x = node;
+ while(y != NULL && x == y->right) /*if y is a left parent of x*/
+ {
+
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
+
+/*return the first node (in sorted order) which is to the left of this node
+ */
+treeNode* TreeNodePredecessor(treeNode* node)
+{
+ if(node == NULL) return NULL;
+ if(node->left != NULL)
+ return TreeNodeMaximum(node->left);
+ else{ /*node->left is NULL*/
+ /*find the first left-ancestor*/
+ treeNode *y = node->parent;
+ treeNode *x = node;
+ while(y != NULL && x == y->left) /*if y is a right parent of x*/
+ {
+ x = y;
+ y = y->parent;
+ }
+ return y;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h
new file mode 100644
index 000000000..d5e33314b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/searchTree.h
@@ -0,0 +1,61 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+#ifndef _SEARCHTREE_H
+#define _SEARCHTREE_H
+
+typedef struct treeNode{
+ void *key;
+ struct treeNode* parent;
+ struct treeNode* left; /*children*/
+ struct treeNode* right;
+} treeNode;
+
+treeNode* TreeNodeMake(void *key);
+void TreeNodeDeleteSingleNode(treeNode* node);
+void TreeNodeDeleteWholeTree(treeNode* node);
+void TreeNodePrint(treeNode* node,
+ void (*keyPrint) (void*));
+int TreeNodeDepth(treeNode* root);
+treeNode* TreeNodeMinimum(treeNode* node);
+treeNode* TreeNodeMaximum(treeNode* node);
+treeNode* TreeNodePredecessor(treeNode* node);
+treeNode* TreeNodeSuccessor(treeNode* node);
+treeNode* TreeNodeFind(treeNode* tree, void* key,
+ int (*compkey) (void*, void*));
+
+treeNode* TreeNodeInsert(treeNode* root, treeNode* newnode,
+ int (*comp) (void *, void *));
+treeNode* TreeNodeDeleteSingleNode(treeNode* tree, treeNode* node);
+
+
+#endif
diff --git a/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h b/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h
new file mode 100644
index 000000000..b9c073257
--- /dev/null
+++ b/mesalib/src/glu/sgi/libnurbs/nurbtess/zlassert.h
@@ -0,0 +1,34 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+*/
+
+/*XXXblythe this file should be deleted*/
+#include <assert.h>
diff --git a/mesalib/src/glu/sgi/libtess/README b/mesalib/src/glu/sgi/libtess/README
new file mode 100644
index 000000000..66a6011e2
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/README
@@ -0,0 +1,446 @@
+/*
+*/
+
+General Polygon Tesselation
+---------------------------
+
+ This note describes a tesselator for polygons consisting of one or
+ more closed contours. It is backward-compatible with the current
+ OpenGL Utilities tesselator, and is intended to replace it. Here is
+ a summary of the major differences:
+
+ - input contours can be intersecting, self-intersecting, or degenerate.
+
+ - supports a choice of several winding rules for determining which parts
+ of the polygon are on the "interior". This makes it possible to do
+ CSG operations on polygons.
+
+ - boundary extraction: instead of tesselating the polygon, returns a
+ set of closed contours which separate the interior from the exterior.
+
+ - returns the output as a small number of triangle fans and strips,
+ rather than a list of independent triangles (when possible).
+
+ - output is available as an explicit mesh (a quad-edge structure),
+ in addition to the normal callback interface.
+
+ - the algorithm used is extremely robust.
+
+
+The interface
+-------------
+
+ The tesselator state is maintained in a "tesselator object".
+ These are allocated and destroyed using
+
+ GLUtesselator *gluNewTess( void );
+ void gluDeleteTess( GLUtesselator *tess );
+
+ Several tesselator objects may be used simultaneously.
+
+ Inputs
+ ------
+
+ The input contours are specified with the following routines:
+
+ void gluTessBeginPolygon( GLUtesselator *tess );
+ void gluTessBeginContour( GLUtesselator *tess );
+ void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data );
+ void gluTessEndContour( GLUtesselator *tess );
+ void gluTessEndPolygon( GLUtesselator *tess );
+
+ Within each BeginPolygon/EndPolygon pair, there can be zero or more
+ calls to BeginContour/EndContour. Within each contour, there are zero
+ or more calls to gluTessVertex(). The vertices specify a closed
+ contour (the last vertex of each contour is automatically linked to
+ the first).
+
+ "coords" give the coordinates of the vertex in 3-space. For useful
+ results, all vertices should lie in some plane, since the vertices
+ are projected onto a plane before tesselation. "data" is a pointer
+ to a user-defined vertex structure, which typically contains other
+ information such as color, texture coordinates, normal, etc. It is
+ used to refer to the vertex during rendering.
+
+ The library can be compiled in single- or double-precision; the type
+ GLUcoord represents either "float" or "double" accordingly. The GLU
+ version will be available in double-precision only. Compile with
+ GLU_TESS_API_FLOAT defined to get the single-precision version.
+
+ When EndPolygon is called, the tesselation algorithm determines
+ which regions are interior to the given contours, according to one
+ of several "winding rules" described below. The interior regions
+ are then tesselated, and the output is provided as callbacks.
+
+
+ Rendering Callbacks
+ -------------------
+
+ Callbacks are specified by the client using
+
+ void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)());
+
+ If "fn" is NULL, any previously defined callback is discarded.
+
+ The callbacks used to provide output are: /* which == */
+
+ void begin( GLenum type ); /* GLU_TESS_BEGIN */
+ void edgeFlag( GLboolean flag ); /* GLU_TESS_EDGE_FLAG */
+ void vertex( void *data ); /* GLU_TESS_VERTEX */
+ void end( void ); /* GLU_TESS_END */
+
+ Any of the callbacks may be left undefined; if so, the corresponding
+ information will not be supplied during rendering.
+
+ The "begin" callback indicates the start of a primitive; type is one
+ of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the
+ notes on "boundary extraction" below).
+
+ It is followed by any number of "vertex" callbacks, which supply the
+ vertices in the same order as expected by the corresponding glBegin()
+ call. After the last vertex of a given primitive, there is a callback
+ to "end".
+
+ If the "edgeFlag" callback is provided, no triangle fans or strips
+ will be used. When edgeFlag is called, if "flag" is GL_TRUE then each
+ vertex which follows begins an edge which lies on the polygon boundary
+ (ie. an edge which separates an interior region from an exterior one).
+ If "flag" is GL_FALSE, each vertex which follows begins an edge which lies
+ in the polygon interior. "edgeFlag" will be called before the first
+ call to "vertex".
+
+ Other Callbacks
+ ---------------
+
+ void mesh( GLUmesh *mesh ); /* GLU_TESS_MESH */
+
+ - Returns an explicit mesh, represented using the quad-edge structure
+ (Guibas/Stolfi '85). Other implementations of this interface might
+ use a different mesh structure, so this is available only only as an
+ SGI extension. When the mesh is no longer needed, it should be freed
+ using
+
+ void gluDeleteMesh( GLUmesh *mesh );
+
+ There is a brief description of this data structure in the include
+ file "mesh.h". For the full details, see L. Guibas and J. Stolfi,
+ Primitives for the manipulation of general subdivisions and the
+ computation of Voronoi diagrams, ACM Transactions on Graphics,
+ 4(2):74-123, April 1985. For an introduction, see the course notes
+ for CS348a, "Mathematical Foundations of Computer Graphics",
+ available at the Stanford bookstore (and taught during the fall
+ quarter).
+
+ void error( GLenum errno ); /* GLU_TESS_ERROR */
+
+ - errno is one of GLU_TESS_MISSING_BEGIN_POLYGON,
+ GLU_TESS_MISSING_END_POLYGON,
+ GLU_TESS_MISSING_BEGIN_CONTOUR,
+ GLU_TESS_MISSING_END_CONTOUR,
+ GLU_TESS_COORD_TOO_LARGE,
+ GLU_TESS_NEED_COMBINE_CALLBACK
+
+ The first four are obvious. The interface recovers from these
+ errors by inserting the missing call(s).
+
+ GLU_TESS_COORD_TOO_LARGE says that some vertex coordinate exceeded
+ the predefined constant GLU_TESS_MAX_COORD in absolute value, and
+ that the value has been clamped. (Coordinate values must be small
+ enough so that two can be multiplied together without overflow.)
+
+ GLU_TESS_NEED_COMBINE_CALLBACK says that the algorithm detected an
+ intersection between two edges in the input data, and the "combine"
+ callback (below) was not provided. No output will be generated.
+
+
+ void combine( GLUcoord coords[3], void *data[4], /* GLU_TESS_COMBINE */
+ GLUcoord weight[4], void **outData );
+
+ - When the algorithm detects an intersection, or wishes to merge
+ features, it needs to create a new vertex. The vertex is defined
+ as a linear combination of up to 4 existing vertices, referenced
+ by data[0..3]. The coefficients of the linear combination are
+ given by weight[0..3]; these weights always sum to 1.0. All vertex
+ pointers are valid even when some of the weights are zero.
+ "coords" gives the location of the new vertex.
+
+ The user must allocate another vertex, interpolate parameters
+ using "data" and "weights", and return the new vertex pointer in
+ "outData". This handle is supplied during rendering callbacks.
+ For example, if the polygon lies in an arbitrary plane in 3-space,
+ and we associate a color with each vertex, the combine callback might
+ look like this:
+
+ void myCombine( GLUcoord coords[3], VERTEX *d[4],
+ GLUcoord w[4], VERTEX **dataOut )
+ {
+ VERTEX *new = new_vertex();
+
+ new->x = coords[0];
+ new->y = coords[1];
+ new->z = coords[2];
+ new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r;
+ new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g;
+ new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b;
+ new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a;
+ *dataOut = new;
+ }
+
+ If the algorithm detects an intersection, then the "combine" callback
+ must be defined, and must write a non-NULL pointer into "dataOut".
+ Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no
+ output is generated. This is the only error that can occur during
+ tesselation and rendering.
+
+
+ Control over Tesselation
+ ------------------------
+
+ void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value );
+
+ Properties defined:
+
+ - GLU_TESS_WINDING_RULE. Possible values:
+
+ GLU_TESS_WINDING_ODD
+ GLU_TESS_WINDING_NONZERO
+ GLU_TESS_WINDING_POSITIVE
+ GLU_TESS_WINDING_NEGATIVE
+ GLU_TESS_WINDING_ABS_GEQ_TWO
+
+ The input contours parition the plane into regions. A winding
+ rule determines which of these regions are inside the polygon.
+
+ For a single contour C, the winding number of a point x is simply
+ the signed number of revolutions we make around x as we travel
+ once around C (where CCW is positive). When there are several
+ contours, the individual winding numbers are summed. This
+ procedure associates a signed integer value with each point x in
+ the plane. Note that the winding number is the same for all
+ points in a single region.
+
+ The winding rule classifies a region as "inside" if its winding
+ number belongs to the chosen category (odd, nonzero, positive,
+ negative, or absolute value of at least two). The current GLU
+ tesselator implements the "odd" rule. The "nonzero" rule is another
+ common way to define the interior. The other three rules are
+ useful for polygon CSG operations (see below).
+
+ - GLU_TESS_BOUNDARY_ONLY. Values: TRUE (non-zero) or FALSE (zero).
+
+ If TRUE, returns a set of closed contours which separate the
+ polygon interior and exterior (rather than a tesselation).
+ Exterior contours are oriented CCW with respect to the normal,
+ interior contours are oriented CW. The GLU_TESS_BEGIN callback
+ uses the type GL_LINE_LOOP for each contour.
+
+ - GLU_TESS_TOLERANCE. Value: a real number between 0.0 and 1.0.
+
+ This specifies a tolerance for merging features to reduce the size
+ of the output. For example, two vertices which are very close to
+ each other might be replaced by a single vertex. The tolerance
+ is multiplied by the largest coordinate magnitude of any input vertex;
+ this specifies the maximum distance that any feature can move as the
+ result of a single merge operation. If a single feature takes part
+ in several merge operations, the total distance moved could be larger.
+
+ Feature merging is completely optional; the tolerance is only a hint.
+ The implementation is free to merge in some cases and not in others,
+ or to never merge features at all. The default tolerance is zero.
+
+ The current implementation merges vertices only if they are exactly
+ coincident, regardless of the current tolerance. A vertex is
+ spliced into an edge only if the implementation is unable to
+ distinguish which side of the edge the vertex lies on.
+ Two edges are merged only when both endpoints are identical.
+
+
+ void gluTessNormal( GLUtesselator *tess,
+ GLUcoord x, GLUcoord y, GLUcoord z )
+
+ - Lets the user supply the polygon normal, if known. All input data
+ is projected into a plane perpendicular to the normal before
+ tesselation. All output triangles are oriented CCW with
+ respect to the normal (CW orientation can be obtained by
+ reversing the sign of the supplied normal). For example, if
+ you know that all polygons lie in the x-y plane, call
+ "gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons.
+
+ - If the supplied normal is (0,0,0) (the default value), the
+ normal is determined as follows. The direction of the normal,
+ up to its sign, is found by fitting a plane to the vertices,
+ without regard to how the vertices are connected. It is
+ expected that the input data lies approximately in plane;
+ otherwise projection perpendicular to the computed normal may
+ substantially change the geometry. The sign of the normal is
+ chosen so that the sum of the signed areas of all input contours
+ is non-negative (where a CCW contour has positive area).
+
+ - The supplied normal persists until it is changed by another
+ call to gluTessNormal.
+
+
+ Backward compatibility with the GLU tesselator
+ ----------------------------------------------
+
+ The preferred interface is the one described above. The following
+ routines are obsolete, and are provided only for backward compatibility:
+
+ typedef GLUtesselator GLUtriangulatorObj; /* obsolete name */
+
+ void gluBeginPolygon( GLUtesselator *tess );
+ void gluNextContour( GLUtesselator *tess, GLenum type );
+ void gluEndPolygon( GLUtesselator *tess );
+
+ "type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or
+ GLU_UNKNOWN. It is ignored by the current GLU tesselator.
+
+ GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined
+ as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END,
+ GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG.
+
+
+Polygon CSG operations
+----------------------
+
+ The features of the tesselator make it easy to find the union, difference,
+ or intersection of several polygons.
+
+ First, assume that each polygon is defined so that the winding number
+ is 0 for each exterior region, and 1 for each interior region. Under
+ this model, CCW contours define the outer boundary of the polygon, and
+ CW contours define holes. Contours may be nested, but a nested
+ contour must be oriented oppositely from the contour that contains it.
+
+ If the original polygons do not satisfy this description, they can be
+ converted to this form by first running the tesselator with the
+ GLU_TESS_BOUNDARY_ONLY property turned on. This returns a list of
+ contours satisfying the restriction above. By allocating two
+ tesselator objects, the callbacks from one tesselator can be fed
+ directly to the input of another.
+
+ Given two or more polygons of the form above, CSG operations can be
+ implemented as follows:
+
+ Union
+ Draw all the input contours as a single polygon. The winding number
+ of each resulting region is the number of original polygons
+ which cover it. The union can be extracted using the
+ GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules.
+ Note that with the nonzero rule, we would get the same result if
+ all contour orientations were reversed.
+
+ Intersection (two polygons at a time only)
+ Draw a single polygon using the contours from both input polygons.
+ Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO. (Since this
+ winding rule looks at the absolute value, reversing all contour
+ orientations does not change the result.)
+
+ Difference
+
+ Suppose we want to compute A \ (B union C union D). Draw a single
+ polygon consisting of the unmodified contours from A, followed by
+ the contours of B,C,D with the vertex order reversed (this changes
+ the winding number of the interior regions to -1). To extract the
+ result, use the GLU_TESS_WINDING_POSITIVE rule.
+
+ If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an
+ alternative to reversing the vertex order is to reverse the sign of
+ the supplied normal. For example in the x-y plane, call
+ gluTessNormal( tess, 0.0, 0.0, -1.0 ).
+
+
+Performance
+-----------
+
+ The tesselator is not intended for immediate-mode rendering; when
+ possible the output should be cached in a user structure or display
+ list. General polygon tesselation is an inherently difficult problem,
+ especially given the goal of extreme robustness.
+
+ The implementation makes an effort to output a small number of fans
+ and strips; this should improve the rendering performance when the
+ output is used in a display list.
+
+ Single-contour input polygons are first tested to see whether they can
+ be rendered as a triangle fan with respect to the first vertex (to
+ avoid running the full decomposition algorithm on convex polygons).
+ Non-convex polygons may be rendered by this "fast path" as well, if
+ the algorithm gets lucky in its choice of a starting vertex.
+
+ For best performance follow these guidelines:
+
+ - supply the polygon normal, if available, using gluTessNormal().
+ This represents about 10% of the computation time. For example,
+ if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1).
+
+ - render many polygons using the same tesselator object, rather than
+ allocating a new tesselator for each one. (In a multi-threaded,
+ multi-processor environment you may get better performance using
+ several tesselators.)
+
+
+Comparison with the GLU tesselator
+----------------------------------
+
+ On polygons which make it through the "fast path", the tesselator is
+ 3 to 5 times faster than the GLU tesselator.
+
+ On polygons which don't make it through the fast path (but which don't
+ have self-intersections or degeneracies), it is about 2 times slower.
+
+ On polygons with self-intersections or degeneraces, there is nothing
+ to compare against.
+
+ The new tesselator generates many more fans and strips, reducing the
+ number of vertices that need to be sent to the hardware.
+
+ Key to the statistics:
+
+ vert number of input vertices on all contours
+ cntr number of input contours
+ tri number of triangles in all output primitives
+ strip number of triangle strips
+ fan number of triangle fans
+ ind number of independent triangles
+ ms number of milliseconds for tesselation
+ (on a 150MHz R4400 Indy)
+
+ Convex polygon examples:
+
+New: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.0459 ms
+Old: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.149 ms
+New: 4 vert, 1 cntr, 2 tri, 0 strip, 1 fan, 0 ind, 0.0459 ms
+Old: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.161 ms
+New: 36 vert, 1 cntr, 34 tri, 0 strip, 1 fan, 0 ind, 0.153 ms
+Old: 36 vert, 1 cntr, 34 tri, 0 strip, 0 fan, 34 ind, 0.621 ms
+
+ Concave single-contour polygons:
+
+New: 5 vert, 1 cntr, 3 tri, 0 strip, 1 fan, 0 ind, 0.052 ms
+Old: 5 vert, 1 cntr, 3 tri, 0 strip, 0 fan, 3 ind, 0.252 ms
+New: 19 vert, 1 cntr, 17 tri, 2 strip, 2 fan, 1 ind, 0.911 ms
+Old: 19 vert, 1 cntr, 17 tri, 0 strip, 0 fan, 17 ind, 0.529 ms
+New: 151 vert, 1 cntr, 149 tri, 13 strip, 18 fan, 3 ind, 6.82 ms
+Old: 151 vert, 1 cntr, 149 tri, 0 strip, 3 fan, 143 ind, 2.7 ms
+New: 574 vert, 1 cntr, 572 tri, 59 strip, 54 fan, 11 ind, 26.6 ms
+Old: 574 vert, 1 cntr, 572 tri, 0 strip, 31 fan, 499 ind, 12.4 ms
+
+ Multiple contours, but no intersections:
+
+New: 7 vert, 2 cntr, 7 tri, 1 strip, 0 fan, 0 ind, 0.527 ms
+Old: 7 vert, 2 cntr, 7 tri, 0 strip, 0 fan, 7 ind, 0.274 ms
+New: 81 vert, 6 cntr, 89 tri, 9 strip, 7 fan, 6 ind, 3.88 ms
+Old: 81 vert, 6 cntr, 89 tri, 0 strip, 13 fan, 61 ind, 2.2 ms
+New: 391 vert, 19 cntr, 413 tri, 37 strip, 32 fan, 26 ind, 20.2 ms
+Old: 391 vert, 19 cntr, 413 tri, 0 strip, 25 fan, 363 ind, 8.68 ms
+
+ Self-intersecting and degenerate examples:
+
+Bowtie: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.483 ms
+Star: 5 vert, 1 cntr, 5 tri, 0 strip, 0 fan, 5 ind, 0.91 ms
+Random: 24 vert, 7 cntr, 46 tri, 2 strip, 12 fan, 7 ind, 5.32 ms
+Font: 333 vert, 2 cntr, 331 tri, 32 strip, 16 fan, 3 ind, 14.1 ms
+: 167 vert, 35 cntr, 254 tri, 8 strip, 56 fan, 52 ind, 46.3 ms
+: 78 vert, 1 cntr, 2675 tri, 148 strip, 207 fan, 180 ind, 243 ms
+: 12480 vert, 2 cntr, 12478 tri, 736 strip,1275 fan, 5 ind, 1010 ms
diff --git a/mesalib/src/glu/sgi/libtess/alg-outline b/mesalib/src/glu/sgi/libtess/alg-outline
new file mode 100644
index 000000000..33fd69728
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/alg-outline
@@ -0,0 +1,228 @@
+/*
+*/
+
+This is only a very brief overview. There is quite a bit of
+additional documentation in the source code itself.
+
+
+Goals of robust tesselation
+---------------------------
+
+The tesselation algorithm is fundamentally a 2D algorithm. We
+initially project all data into a plane; our goal is to robustly
+tesselate the projected data. The same topological tesselation is
+then applied to the input data.
+
+Topologically, the output should always be a tesselation. If the
+input is even slightly non-planar, then some triangles will
+necessarily be back-facing when viewed from some angles, but the goal
+is to minimize this effect.
+
+The algorithm needs some capability of cleaning up the input data as
+well as the numerical errors in its own calculations. One way to do
+this is to specify a tolerance as defined above, and clean up the
+input and output during the line sweep process. At the very least,
+the algorithm must handle coincident vertices, vertices incident to an
+edge, and coincident edges.
+
+
+Phases of the algorithm
+-----------------------
+
+1. Find the polygon normal N.
+2. Project the vertex data onto a plane. It does not need to be
+ perpendicular to the normal, eg. we can project onto the plane
+ perpendicular to the coordinate axis whose dot product with N
+ is largest.
+3. Using a line-sweep algorithm, partition the plane into x-monotone
+ regions. Any vertical line intersects an x-monotone region in
+ at most one interval.
+4. Triangulate the x-monotone regions.
+5. Group the triangles into strips and fans.
+
+
+Finding the normal vector
+-------------------------
+
+A common way to find a polygon normal is to compute the signed area
+when the polygon is projected along the three coordinate axes. We
+can't do this, since contours can have zero area without being
+degenerate (eg. a bowtie).
+
+We fit a plane to the vertex data, ignoring how they are connected
+into contours. Ideally this would be a least-squares fit; however for
+our purpose the accuracy of the normal is not important. Instead we
+find three vertices which are widely separated, and compute the normal
+to the triangle they form. The vertices are chosen so that the
+triangle has an area at least 1/sqrt(3) times the largest area of any
+triangle formed using the input vertices.
+
+The contours do affect the orientation of the normal; after computing
+the normal, we check that the sum of the signed contour areas is
+non-negative, and reverse the normal if necessary.
+
+
+Projecting the vertices
+-----------------------
+
+We project the vertices onto a plane perpendicular to one of the three
+coordinate axes. This helps numerical accuracy by removing a
+transformation step between the original input data and the data
+processed by the algorithm. The projection also compresses the input
+data; the 2D distance between vertices after projection may be smaller
+than the original 2D distance. However by choosing the coordinate
+axis whose dot product with the normal is greatest, the compression
+factor is at most 1/sqrt(3).
+
+Even though the *accuracy* of the normal is not that important (since
+we are projecting perpendicular to a coordinate axis anyway), the
+*robustness* of the computation is important. For example, if there
+are many vertices which lie almost along a line, and one vertex V
+which is well-separated from the line, then our normal computation
+should involve V otherwise the results will be garbage.
+
+The advantage of projecting perpendicular to the polygon normal is
+that computed intersection points will be as close as possible to
+their ideal locations. To get this behavior, define TRUE_PROJECT.
+
+
+The Line Sweep
+--------------
+
+There are three data structures: the mesh, the event queue, and the
+edge dictionary.
+
+The mesh is a "quad-edge" data structure which records the topology of
+the current decomposition; for details see the include file "mesh.h".
+
+The event queue simply holds all vertices (both original and computed
+ones), organized so that we can quickly extract the vertex with the
+minimum x-coord (and among those, the one with the minimum y-coord).
+
+The edge dictionary describes the current intersection of the sweep
+line with the regions of the polygon. This is just an ordering of the
+edges which intersect the sweep line, sorted by their current order of
+intersection. For each pair of edges, we store some information about
+the monotone region between them -- these are call "active regions"
+(since they are crossed by the current sweep line).
+
+The basic algorithm is to sweep from left to right, processing each
+vertex. The processed portion of the mesh (left of the sweep line) is
+a planar decomposition. As we cross each vertex, we update the mesh
+and the edge dictionary, then we check any newly adjacent pairs of
+edges to see if they intersect.
+
+A vertex can have any number of edges. Vertices with many edges can
+be created as vertices are merged and intersection points are
+computed. For unprocessed vertices (right of the sweep line), these
+edges are in no particular order around the vertex; for processed
+vertices, the topological ordering should match the geometric ordering.
+
+The vertex processing happens in two phases: first we process are the
+left-going edges (all these edges are currently in the edge
+dictionary). This involves:
+
+ - deleting the left-going edges from the dictionary;
+ - relinking the mesh if necessary, so that the order of these edges around
+ the event vertex matches the order in the dictionary;
+ - marking any terminated regions (regions which lie between two left-going
+ edges) as either "inside" or "outside" according to their winding number.
+
+When there are no left-going edges, and the event vertex is in an
+"interior" region, we need to add an edge (to split the region into
+monotone pieces). To do this we simply join the event vertex to the
+rightmost left endpoint of the upper or lower edge of the containing
+region.
+
+Then we process the right-going edges. This involves:
+
+ - inserting the edges in the edge dictionary;
+ - computing the winding number of any newly created active regions.
+ We can compute this incrementally using the winding of each edge
+ that we cross as we walk through the dictionary.
+ - relinking the mesh if necessary, so that the order of these edges around
+ the event vertex matches the order in the dictionary;
+ - checking any newly adjacent edges for intersection and/or merging.
+
+If there are no right-going edges, again we need to add one to split
+the containing region into monotone pieces. In our case it is most
+convenient to add an edge to the leftmost right endpoint of either
+containing edge; however we may need to change this later (see the
+code for details).
+
+
+Invariants
+----------
+
+These are the most important invariants maintained during the sweep.
+We define a function VertLeq(v1,v2) which defines the order in which
+vertices cross the sweep line, and a function EdgeLeq(e1,e2; loc)
+which says whether e1 is below e2 at the sweep event location "loc".
+This function is defined only at sweep event locations which lie
+between the rightmost left endpoint of {e1,e2}, and the leftmost right
+endpoint of {e1,e2}.
+
+Invariants for the Edge Dictionary.
+
+ - Each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2)
+ at any valid location of the sweep event.
+ - If EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2
+ share a common endpoint.
+ - For each e in the dictionary, e->Dst has been processed but not e->Org.
+ - Each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org)
+ where "event" is the current sweep line event.
+ - No edge e has zero length.
+ - No two edges have identical left and right endpoints.
+
+Invariants for the Mesh (the processed portion).
+
+ - The portion of the mesh left of the sweep line is a planar graph,
+ ie. there is *some* way to embed it in the plane.
+ - No processed edge has zero length.
+ - No two processed vertices have identical coordinates.
+ - Each "inside" region is monotone, ie. can be broken into two chains
+ of monotonically increasing vertices according to VertLeq(v1,v2)
+ - a non-invariant: these chains may intersect (slightly) due to
+ numerical errors, but this does not affect the algorithm's operation.
+
+Invariants for the Sweep.
+
+ - If a vertex has any left-going edges, then these must be in the edge
+ dictionary at the time the vertex is processed.
+ - If an edge is marked "fixUpperEdge" (it is a temporary edge introduced
+ by ConnectRightVertex), then it is the only right-going edge from
+ its associated vertex. (This says that these edges exist only
+ when it is necessary.)
+
+
+Robustness
+----------
+
+The key to the robustness of the algorithm is maintaining the
+invariants above, especially the correct ordering of the edge
+dictionary. We achieve this by:
+
+ 1. Writing the numerical computations for maximum precision rather
+ than maximum speed.
+
+ 2. Making no assumptions at all about the results of the edge
+ intersection calculations -- for sufficiently degenerate inputs,
+ the computed location is not much better than a random number.
+
+ 3. When numerical errors violate the invariants, restore them
+ by making *topological* changes when necessary (ie. relinking
+ the mesh structure).
+
+
+Triangulation and Grouping
+--------------------------
+
+We finish the line sweep before doing any triangulation. This is
+because even after a monotone region is complete, there can be further
+changes to its vertex data because of further vertex merging.
+
+After triangulating all monotone regions, we want to group the
+triangles into fans and strips. We do this using a greedy approach.
+The triangulation itself is not optimized to reduce the number of
+primitives; we just try to get a reasonable decomposition of the
+computed triangulation.
diff --git a/mesalib/src/glu/sgi/libtess/dict-list.h b/mesalib/src/glu/sgi/libtess/dict-list.h
new file mode 100644
index 000000000..11331a76e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/dict-list.h
@@ -0,0 +1,100 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __dict_list_h_
+#define __dict_list_h_
+
+/* Use #define's so that another heap implementation can use this one */
+
+#define DictKey DictListKey
+#define Dict DictList
+#define DictNode DictListNode
+
+#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq)
+#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict)
+
+#define dictSearch(dict,key) __gl_dictListSearch(dict,key)
+#define dictInsert(dict,key) __gl_dictListInsert(dict,key)
+#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key)
+#define dictDelete(dict,node) __gl_dictListDelete(dict,node)
+
+#define dictKey(n) __gl_dictListKey(n)
+#define dictSucc(n) __gl_dictListSucc(n)
+#define dictPred(n) __gl_dictListPred(n)
+#define dictMin(d) __gl_dictListMin(d)
+#define dictMax(d) __gl_dictListMax(d)
+
+
+
+typedef void *DictKey;
+typedef struct Dict Dict;
+typedef struct DictNode DictNode;
+
+Dict *dictNewDict(
+ void *frame,
+ int (*leq)(void *frame, DictKey key1, DictKey key2) );
+
+void dictDeleteDict( Dict *dict );
+
+/* Search returns the node with the smallest key greater than or equal
+ * to the given key. If there is no such key, returns a node whose
+ * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc.
+ */
+DictNode *dictSearch( Dict *dict, DictKey key );
+DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key );
+void dictDelete( Dict *dict, DictNode *node );
+
+#define __gl_dictListKey(n) ((n)->key)
+#define __gl_dictListSucc(n) ((n)->next)
+#define __gl_dictListPred(n) ((n)->prev)
+#define __gl_dictListMin(d) ((d)->head.next)
+#define __gl_dictListMax(d) ((d)->head.prev)
+#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k)))
+
+
+/*** Private data structures ***/
+
+struct DictNode {
+ DictKey key;
+ DictNode *next;
+ DictNode *prev;
+};
+
+struct Dict {
+ DictNode head;
+ void *frame;
+ int (*leq)(void *frame, DictKey key1, DictKey key2);
+};
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/dict.c b/mesalib/src/glu/sgi/libtess/dict.c
new file mode 100644
index 000000000..49d4f759e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/dict.c
@@ -0,0 +1,111 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include <stddef.h>
+#include "dict-list.h"
+#include "memalloc.h"
+
+/* really __gl_dictListNewDict */
+Dict *dictNewDict( void *frame,
+ int (*leq)(void *frame, DictKey key1, DictKey key2) )
+{
+ Dict *dict = (Dict *) memAlloc( sizeof( Dict ));
+ DictNode *head;
+
+ if (dict == NULL) return NULL;
+
+ head = &dict->head;
+
+ head->key = NULL;
+ head->next = head;
+ head->prev = head;
+
+ dict->frame = frame;
+ dict->leq = leq;
+
+ return dict;
+}
+
+/* really __gl_dictListDeleteDict */
+void dictDeleteDict( Dict *dict )
+{
+ DictNode *node, *next;
+
+ for( node = dict->head.next; node != &dict->head; node = next ) {
+ next = node->next;
+ memFree( node );
+ }
+ memFree( dict );
+}
+
+/* really __gl_dictListInsertBefore */
+DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key )
+{
+ DictNode *newNode;
+
+ do {
+ node = node->prev;
+ } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key));
+
+ newNode = (DictNode *) memAlloc( sizeof( DictNode ));
+ if (newNode == NULL) return NULL;
+
+ newNode->key = key;
+ newNode->next = node->next;
+ node->next->prev = newNode;
+ newNode->prev = node;
+ node->next = newNode;
+
+ return newNode;
+}
+
+/* really __gl_dictListDelete */
+void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/
+{
+ node->next->prev = node->prev;
+ node->prev->next = node->next;
+ memFree( node );
+}
+
+/* really __gl_dictListSearch */
+DictNode *dictSearch( Dict *dict, DictKey key )
+{
+ DictNode *node = &dict->head;
+
+ do {
+ node = node->next;
+ } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key));
+
+ return node;
+}
diff --git a/mesalib/src/glu/sgi/libtess/dict.h b/mesalib/src/glu/sgi/libtess/dict.h
new file mode 100644
index 000000000..11331a76e
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/dict.h
@@ -0,0 +1,100 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __dict_list_h_
+#define __dict_list_h_
+
+/* Use #define's so that another heap implementation can use this one */
+
+#define DictKey DictListKey
+#define Dict DictList
+#define DictNode DictListNode
+
+#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq)
+#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict)
+
+#define dictSearch(dict,key) __gl_dictListSearch(dict,key)
+#define dictInsert(dict,key) __gl_dictListInsert(dict,key)
+#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key)
+#define dictDelete(dict,node) __gl_dictListDelete(dict,node)
+
+#define dictKey(n) __gl_dictListKey(n)
+#define dictSucc(n) __gl_dictListSucc(n)
+#define dictPred(n) __gl_dictListPred(n)
+#define dictMin(d) __gl_dictListMin(d)
+#define dictMax(d) __gl_dictListMax(d)
+
+
+
+typedef void *DictKey;
+typedef struct Dict Dict;
+typedef struct DictNode DictNode;
+
+Dict *dictNewDict(
+ void *frame,
+ int (*leq)(void *frame, DictKey key1, DictKey key2) );
+
+void dictDeleteDict( Dict *dict );
+
+/* Search returns the node with the smallest key greater than or equal
+ * to the given key. If there is no such key, returns a node whose
+ * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc.
+ */
+DictNode *dictSearch( Dict *dict, DictKey key );
+DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key );
+void dictDelete( Dict *dict, DictNode *node );
+
+#define __gl_dictListKey(n) ((n)->key)
+#define __gl_dictListSucc(n) ((n)->next)
+#define __gl_dictListPred(n) ((n)->prev)
+#define __gl_dictListMin(d) ((d)->head.next)
+#define __gl_dictListMax(d) ((d)->head.prev)
+#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k)))
+
+
+/*** Private data structures ***/
+
+struct DictNode {
+ DictKey key;
+ DictNode *next;
+ DictNode *prev;
+};
+
+struct Dict {
+ DictNode head;
+ void *frame;
+ int (*leq)(void *frame, DictKey key1, DictKey key2);
+};
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/geom.c b/mesalib/src/glu/sgi/libtess/geom.c
new file mode 100644
index 000000000..7d3b8d8a6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/geom.c
@@ -0,0 +1,264 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <assert.h>
+#include "mesh.h"
+#include "geom.h"
+
+int __gl_vertLeq( GLUvertex *u, GLUvertex *v )
+{
+ /* Returns TRUE if u is lexicographically <= v. */
+
+ return VertLeq( u, v );
+}
+
+GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
+{
+ /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
+ * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
+ * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
+ * If uw is vertical (and thus passes thru v), the result is zero.
+ *
+ * The calculation is extremely accurate and stable, even when v
+ * is very close to u or w. In particular if we set v->t = 0 and
+ * let r be the negated result (this evaluates (uw)(v->s)), then
+ * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
+ */
+ GLdouble gapL, gapR;
+
+ assert( VertLeq( u, v ) && VertLeq( v, w ));
+
+ gapL = v->s - u->s;
+ gapR = w->s - v->s;
+
+ if( gapL + gapR > 0 ) {
+ if( gapL < gapR ) {
+ return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR));
+ } else {
+ return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR));
+ }
+ }
+ /* vertical line */
+ return 0;
+}
+
+GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
+{
+ /* Returns a number whose sign matches EdgeEval(u,v,w) but which
+ * is cheaper to evaluate. Returns > 0, == 0 , or < 0
+ * as v is above, on, or below the edge uw.
+ */
+ GLdouble gapL, gapR;
+
+ assert( VertLeq( u, v ) && VertLeq( v, w ));
+
+ gapL = v->s - u->s;
+ gapR = w->s - v->s;
+
+ if( gapL + gapR > 0 ) {
+ return (v->t - w->t) * gapL + (v->t - u->t) * gapR;
+ }
+ /* vertical line */
+ return 0;
+}
+
+
+/***********************************************************************
+ * Define versions of EdgeSign, EdgeEval with s and t transposed.
+ */
+
+GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
+{
+ /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
+ * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
+ * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v.
+ * If uw is vertical (and thus passes thru v), the result is zero.
+ *
+ * The calculation is extremely accurate and stable, even when v
+ * is very close to u or w. In particular if we set v->s = 0 and
+ * let r be the negated result (this evaluates (uw)(v->t)), then
+ * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s).
+ */
+ GLdouble gapL, gapR;
+
+ assert( TransLeq( u, v ) && TransLeq( v, w ));
+
+ gapL = v->t - u->t;
+ gapR = w->t - v->t;
+
+ if( gapL + gapR > 0 ) {
+ if( gapL < gapR ) {
+ return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR));
+ } else {
+ return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR));
+ }
+ }
+ /* vertical line */
+ return 0;
+}
+
+GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
+{
+ /* Returns a number whose sign matches TransEval(u,v,w) but which
+ * is cheaper to evaluate. Returns > 0, == 0 , or < 0
+ * as v is above, on, or below the edge uw.
+ */
+ GLdouble gapL, gapR;
+
+ assert( TransLeq( u, v ) && TransLeq( v, w ));
+
+ gapL = v->t - u->t;
+ gapR = w->t - v->t;
+
+ if( gapL + gapR > 0 ) {
+ return (v->s - w->s) * gapL + (v->s - u->s) * gapR;
+ }
+ /* vertical line */
+ return 0;
+}
+
+
+int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w )
+{
+ /* For almost-degenerate situations, the results are not reliable.
+ * Unless the floating-point arithmetic can be performed without
+ * rounding errors, *any* implementation will give incorrect results
+ * on some degenerate inputs, so the client must have some way to
+ * handle this situation.
+ */
+ return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0;
+}
+
+/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b),
+ * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces
+ * this in the rare case that one argument is slightly negative.
+ * The implementation is extremely stable numerically.
+ * In particular it guarantees that the result r satisfies
+ * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
+ * even when a and b differ greatly in magnitude.
+ */
+#define RealInterpolate(a,x,b,y) \
+ (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \
+ ((a <= b) ? ((b == 0) ? ((x+y) / 2) \
+ : (x + (y-x) * (a/(a+b)))) \
+ : (y + (x-y) * (b/(a+b)))))
+
+#ifndef FOR_TRITE_TEST_PROGRAM
+#define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y)
+#else
+
+/* Claim: the ONLY property the sweep algorithm relies on is that
+ * MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that.
+ */
+#include <stdlib.h>
+extern int RandomInterpolate;
+
+GLdouble Interpolate( GLdouble a, GLdouble x, GLdouble b, GLdouble y)
+{
+printf("*********************%d\n",RandomInterpolate);
+ if( RandomInterpolate ) {
+ a = 1.2 * drand48() - 0.1;
+ a = (a < 0) ? 0 : ((a > 1) ? 1 : a);
+ b = 1.0 - a;
+ }
+ return RealInterpolate(a,x,b,y);
+}
+
+#endif
+
+#define Swap(a,b) if (1) { GLUvertex *t = a; a = b; b = t; } else
+
+void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
+ GLUvertex *o2, GLUvertex *d2,
+ GLUvertex *v )
+/* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
+ * The computed point is guaranteed to lie in the intersection of the
+ * bounding rectangles defined by each edge.
+ */
+{
+ GLdouble z1, z2;
+
+ /* This is certainly not the most efficient way to find the intersection
+ * of two line segments, but it is very numerically stable.
+ *
+ * Strategy: find the two middle vertices in the VertLeq ordering,
+ * and interpolate the intersection s-value from these. Then repeat
+ * using the TransLeq ordering to find the intersection t-value.
+ */
+
+ if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); }
+ if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); }
+ if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
+
+ if( ! VertLeq( o2, d1 )) {
+ /* Technically, no intersection -- do our best */
+ v->s = (o2->s + d1->s) / 2;
+ } else if( VertLeq( d1, d2 )) {
+ /* Interpolate between o2 and d1 */
+ z1 = EdgeEval( o1, o2, d1 );
+ z2 = EdgeEval( o2, d1, d2 );
+ if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
+ v->s = Interpolate( z1, o2->s, z2, d1->s );
+ } else {
+ /* Interpolate between o2 and d2 */
+ z1 = EdgeSign( o1, o2, d1 );
+ z2 = -EdgeSign( o1, d2, d1 );
+ if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
+ v->s = Interpolate( z1, o2->s, z2, d2->s );
+ }
+
+ /* Now repeat the process for t */
+
+ if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); }
+ if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); }
+ if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
+
+ if( ! TransLeq( o2, d1 )) {
+ /* Technically, no intersection -- do our best */
+ v->t = (o2->t + d1->t) / 2;
+ } else if( TransLeq( d1, d2 )) {
+ /* Interpolate between o2 and d1 */
+ z1 = TransEval( o1, o2, d1 );
+ z2 = TransEval( o2, d1, d2 );
+ if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
+ v->t = Interpolate( z1, o2->t, z2, d1->t );
+ } else {
+ /* Interpolate between o2 and d2 */
+ z1 = TransSign( o1, o2, d1 );
+ z2 = -TransSign( o1, d2, d1 );
+ if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
+ v->t = Interpolate( z1, o2->t, z2, d2->t );
+ }
+}
diff --git a/mesalib/src/glu/sgi/libtess/geom.h b/mesalib/src/glu/sgi/libtess/geom.h
new file mode 100644
index 000000000..5cb76c7d1
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/geom.h
@@ -0,0 +1,84 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __geom_h_
+#define __geom_h_
+
+#include "mesh.h"
+
+#ifdef NO_BRANCH_CONDITIONS
+/* MIPS architecture has special instructions to evaluate boolean
+ * conditions -- more efficient than branching, IF you can get the
+ * compiler to generate the right instructions (SGI compiler doesn't)
+ */
+#define VertEq(u,v) (((u)->s == (v)->s) & ((u)->t == (v)->t))
+#define VertLeq(u,v) (((u)->s < (v)->s) | \
+ ((u)->s == (v)->s & (u)->t <= (v)->t))
+#else
+#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t)
+#define VertLeq(u,v) (((u)->s < (v)->s) || \
+ ((u)->s == (v)->s && (u)->t <= (v)->t))
+#endif
+
+#define EdgeEval(u,v,w) __gl_edgeEval(u,v,w)
+#define EdgeSign(u,v,w) __gl_edgeSign(u,v,w)
+
+/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */
+
+#define TransLeq(u,v) (((u)->t < (v)->t) || \
+ ((u)->t == (v)->t && (u)->s <= (v)->s))
+#define TransEval(u,v,w) __gl_transEval(u,v,w)
+#define TransSign(u,v,w) __gl_transSign(u,v,w)
+
+
+#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org )
+#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst )
+
+#undef ABS
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t))
+
+#define VertCCW(u,v,w) __gl_vertCCW(u,v,w)
+
+int __gl_vertLeq( GLUvertex *u, GLUvertex *v );
+GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w );
+GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w );
+GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w );
+GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w );
+int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w );
+void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
+ GLUvertex *o2, GLUvertex *d2,
+ GLUvertex *v );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/memalloc.c b/mesalib/src/glu/sgi/libtess/memalloc.c
new file mode 100644
index 000000000..81879ef78
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/memalloc.c
@@ -0,0 +1,55 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "memalloc.h"
+#include "string.h"
+
+int __gl_memInit( size_t maxFast )
+{
+#ifndef NO_MALLOPT
+/* mallopt( M_MXFAST, maxFast );*/
+#ifdef MEMORY_DEBUG
+ mallopt( M_DEBUG, 1 );
+#endif
+#endif
+ return 1;
+}
+
+#ifdef MEMORY_DEBUG
+void *__gl_memAlloc( size_t n )
+{
+ return memset( malloc( n ), 0xa5, n );
+}
+#endif
+
diff --git a/mesalib/src/glu/sgi/libtess/memalloc.h b/mesalib/src/glu/sgi/libtess/memalloc.h
new file mode 100644
index 000000000..c2f969b8b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/memalloc.h
@@ -0,0 +1,54 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __memalloc_simple_h_
+#define __memalloc_simple_h_
+
+#include <stdlib.h>
+
+#define memRealloc realloc
+#define memFree free
+
+#define memInit __gl_memInit
+/*extern void __gl_memInit( size_t );*/
+extern int __gl_memInit( size_t );
+
+#ifndef MEMORY_DEBUG
+#define memAlloc malloc
+#else
+#define memAlloc __gl_memAlloc
+extern void * __gl_memAlloc( size_t );
+#endif
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/mesh.c b/mesalib/src/glu/sgi/libtess/mesh.c
new file mode 100644
index 000000000..ae861f864
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/mesh.c
@@ -0,0 +1,789 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <stddef.h>
+#include <assert.h>
+#include "mesh.h"
+#include "memalloc.h"
+
+#define TRUE 1
+#define FALSE 0
+
+static GLUvertex *allocVertex()
+{
+ return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
+}
+
+static GLUface *allocFace()
+{
+ return (GLUface *)memAlloc( sizeof( GLUface ));
+}
+
+/************************ Utility Routines ************************/
+
+/* Allocate and free half-edges in pairs for efficiency.
+ * The *only* place that should use this fact is allocation/free.
+ */
+typedef struct { GLUhalfEdge e, eSym; } EdgePair;
+
+/* MakeEdge creates a new pair of half-edges which form their own loop.
+ * No vertex or face structures are allocated, but these must be assigned
+ * before the current edge operation is completed.
+ */
+static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext )
+{
+ GLUhalfEdge *e;
+ GLUhalfEdge *eSym;
+ GLUhalfEdge *ePrev;
+ EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
+ if (pair == NULL) return NULL;
+
+ e = &pair->e;
+ eSym = &pair->eSym;
+
+ /* Make sure eNext points to the first edge of the edge pair */
+ if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
+
+ /* Insert in circular doubly-linked list before eNext.
+ * Note that the prev pointer is stored in Sym->next.
+ */
+ ePrev = eNext->Sym->next;
+ eSym->next = ePrev;
+ ePrev->Sym->next = e;
+ e->next = eNext;
+ eNext->Sym->next = eSym;
+
+ e->Sym = eSym;
+ e->Onext = e;
+ e->Lnext = eSym;
+ e->Org = NULL;
+ e->Lface = NULL;
+ e->winding = 0;
+ e->activeRegion = NULL;
+
+ eSym->Sym = e;
+ eSym->Onext = eSym;
+ eSym->Lnext = e;
+ eSym->Org = NULL;
+ eSym->Lface = NULL;
+ eSym->winding = 0;
+ eSym->activeRegion = NULL;
+
+ return e;
+}
+
+/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
+ * CS348a notes (see mesh.h). Basically it modifies the mesh so that
+ * a->Onext and b->Onext are exchanged. This can have various effects
+ * depending on whether a and b belong to different face or vertex rings.
+ * For more explanation see __gl_meshSplice() below.
+ */
+static void Splice( GLUhalfEdge *a, GLUhalfEdge *b )
+{
+ GLUhalfEdge *aOnext = a->Onext;
+ GLUhalfEdge *bOnext = b->Onext;
+
+ aOnext->Sym->Lnext = b;
+ bOnext->Sym->Lnext = a;
+ a->Onext = bOnext;
+ b->Onext = aOnext;
+}
+
+/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
+ * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
+ * a place to insert the new vertex in the global vertex list. We insert
+ * the new vertex *before* vNext so that algorithms which walk the vertex
+ * list will not see the newly created vertices.
+ */
+static void MakeVertex( GLUvertex *newVertex,
+ GLUhalfEdge *eOrig, GLUvertex *vNext )
+{
+ GLUhalfEdge *e;
+ GLUvertex *vPrev;
+ GLUvertex *vNew = newVertex;
+
+ assert(vNew != NULL);
+
+ /* insert in circular doubly-linked list before vNext */
+ vPrev = vNext->prev;
+ vNew->prev = vPrev;
+ vPrev->next = vNew;
+ vNew->next = vNext;
+ vNext->prev = vNew;
+
+ vNew->anEdge = eOrig;
+ vNew->data = NULL;
+ /* leave coords, s, t undefined */
+
+ /* fix other edges on this vertex loop */
+ e = eOrig;
+ do {
+ e->Org = vNew;
+ e = e->Onext;
+ } while( e != eOrig );
+}
+
+/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
+ * face of all edges in the face loop to which eOrig belongs. "fNext" gives
+ * a place to insert the new face in the global face list. We insert
+ * the new face *before* fNext so that algorithms which walk the face
+ * list will not see the newly created faces.
+ */
+static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
+{
+ GLUhalfEdge *e;
+ GLUface *fPrev;
+ GLUface *fNew = newFace;
+
+ assert(fNew != NULL);
+
+ /* insert in circular doubly-linked list before fNext */
+ fPrev = fNext->prev;
+ fNew->prev = fPrev;
+ fPrev->next = fNew;
+ fNew->next = fNext;
+ fNext->prev = fNew;
+
+ fNew->anEdge = eOrig;
+ fNew->data = NULL;
+ fNew->trail = NULL;
+ fNew->marked = FALSE;
+
+ /* The new face is marked "inside" if the old one was. This is a
+ * convenience for the common case where a face has been split in two.
+ */
+ fNew->inside = fNext->inside;
+
+ /* fix other edges on this face loop */
+ e = eOrig;
+ do {
+ e->Lface = fNew;
+ e = e->Lnext;
+ } while( e != eOrig );
+}
+
+/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
+ * and removes from the global edge list.
+ */
+static void KillEdge( GLUhalfEdge *eDel )
+{
+ GLUhalfEdge *ePrev, *eNext;
+
+ /* Half-edges are allocated in pairs, see EdgePair above */
+ if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
+
+ /* delete from circular doubly-linked list */
+ eNext = eDel->next;
+ ePrev = eDel->Sym->next;
+ eNext->Sym->next = ePrev;
+ ePrev->Sym->next = eNext;
+
+ memFree( eDel );
+}
+
+
+/* KillVertex( vDel ) destroys a vertex and removes it from the global
+ * vertex list. It updates the vertex loop to point to a given new vertex.
+ */
+static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
+{
+ GLUhalfEdge *e, *eStart = vDel->anEdge;
+ GLUvertex *vPrev, *vNext;
+
+ /* change the origin of all affected edges */
+ e = eStart;
+ do {
+ e->Org = newOrg;
+ e = e->Onext;
+ } while( e != eStart );
+
+ /* delete from circular doubly-linked list */
+ vPrev = vDel->prev;
+ vNext = vDel->next;
+ vNext->prev = vPrev;
+ vPrev->next = vNext;
+
+ memFree( vDel );
+}
+
+/* KillFace( fDel ) destroys a face and removes it from the global face
+ * list. It updates the face loop to point to a given new face.
+ */
+static void KillFace( GLUface *fDel, GLUface *newLface )
+{
+ GLUhalfEdge *e, *eStart = fDel->anEdge;
+ GLUface *fPrev, *fNext;
+
+ /* change the left face of all affected edges */
+ e = eStart;
+ do {
+ e->Lface = newLface;
+ e = e->Lnext;
+ } while( e != eStart );
+
+ /* delete from circular doubly-linked list */
+ fPrev = fDel->prev;
+ fNext = fDel->next;
+ fNext->prev = fPrev;
+ fPrev->next = fNext;
+
+ memFree( fDel );
+}
+
+
+/****************** Basic Edge Operations **********************/
+
+/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
+ * The loop consists of the two new half-edges.
+ */
+GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
+{
+ GLUvertex *newVertex1= allocVertex();
+ GLUvertex *newVertex2= allocVertex();
+ GLUface *newFace= allocFace();
+ GLUhalfEdge *e;
+
+ /* if any one is null then all get freed */
+ if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
+ if (newVertex1 != NULL) memFree(newVertex1);
+ if (newVertex2 != NULL) memFree(newVertex2);
+ if (newFace != NULL) memFree(newFace);
+ return NULL;
+ }
+
+ e = MakeEdge( &mesh->eHead );
+ if (e == NULL) return NULL;
+
+ MakeVertex( newVertex1, e, &mesh->vHead );
+ MakeVertex( newVertex2, e->Sym, &mesh->vHead );
+ MakeFace( newFace, e, &mesh->fHead );
+ return e;
+}
+
+
+/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
+ * mesh connectivity and topology. It changes the mesh so that
+ * eOrg->Onext <- OLD( eDst->Onext )
+ * eDst->Onext <- OLD( eOrg->Onext )
+ * where OLD(...) means the value before the meshSplice operation.
+ *
+ * This can have two effects on the vertex structure:
+ * - if eOrg->Org != eDst->Org, the two vertices are merged together
+ * - if eOrg->Org == eDst->Org, the origin is split into two vertices
+ * In both cases, eDst->Org is changed and eOrg->Org is untouched.
+ *
+ * Similarly (and independently) for the face structure,
+ * - if eOrg->Lface == eDst->Lface, one loop is split into two
+ * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
+ * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
+ *
+ * Some special cases:
+ * If eDst == eOrg, the operation has no effect.
+ * If eDst == eOrg->Lnext, the new face will have a single edge.
+ * If eDst == eOrg->Lprev, the old face will have a single edge.
+ * If eDst == eOrg->Onext, the new vertex will have a single edge.
+ * If eDst == eOrg->Oprev, the old vertex will have a single edge.
+ */
+int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
+{
+ int joiningLoops = FALSE;
+ int joiningVertices = FALSE;
+
+ if( eOrg == eDst ) return 1;
+
+ if( eDst->Org != eOrg->Org ) {
+ /* We are merging two disjoint vertices -- destroy eDst->Org */
+ joiningVertices = TRUE;
+ KillVertex( eDst->Org, eOrg->Org );
+ }
+ if( eDst->Lface != eOrg->Lface ) {
+ /* We are connecting two disjoint loops -- destroy eDst->Lface */
+ joiningLoops = TRUE;
+ KillFace( eDst->Lface, eOrg->Lface );
+ }
+
+ /* Change the edge structure */
+ Splice( eDst, eOrg );
+
+ if( ! joiningVertices ) {
+ GLUvertex *newVertex= allocVertex();
+ if (newVertex == NULL) return 0;
+
+ /* We split one vertex into two -- the new vertex is eDst->Org.
+ * Make sure the old vertex points to a valid half-edge.
+ */
+ MakeVertex( newVertex, eDst, eOrg->Org );
+ eOrg->Org->anEdge = eOrg;
+ }
+ if( ! joiningLoops ) {
+ GLUface *newFace= allocFace();
+ if (newFace == NULL) return 0;
+
+ /* We split one loop into two -- the new loop is eDst->Lface.
+ * Make sure the old face points to a valid half-edge.
+ */
+ MakeFace( newFace, eDst, eOrg->Lface );
+ eOrg->Lface->anEdge = eOrg;
+ }
+
+ return 1;
+}
+
+
+/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
+ * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
+ * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
+ * the newly created loop will contain eDel->Dst. If the deletion of eDel
+ * would create isolated vertices, those are deleted as well.
+ *
+ * This function could be implemented as two calls to __gl_meshSplice
+ * plus a few calls to memFree, but this would allocate and delete
+ * unnecessary vertices and faces.
+ */
+int __gl_meshDelete( GLUhalfEdge *eDel )
+{
+ GLUhalfEdge *eDelSym = eDel->Sym;
+ int joiningLoops = FALSE;
+
+ /* First step: disconnect the origin vertex eDel->Org. We make all
+ * changes to get a consistent mesh in this "intermediate" state.
+ */
+ if( eDel->Lface != eDel->Rface ) {
+ /* We are joining two loops into one -- remove the left face */
+ joiningLoops = TRUE;
+ KillFace( eDel->Lface, eDel->Rface );
+ }
+
+ if( eDel->Onext == eDel ) {
+ KillVertex( eDel->Org, NULL );
+ } else {
+ /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
+ eDel->Rface->anEdge = eDel->Oprev;
+ eDel->Org->anEdge = eDel->Onext;
+
+ Splice( eDel, eDel->Oprev );
+ if( ! joiningLoops ) {
+ GLUface *newFace= allocFace();
+ if (newFace == NULL) return 0;
+
+ /* We are splitting one loop into two -- create a new loop for eDel. */
+ MakeFace( newFace, eDel, eDel->Lface );
+ }
+ }
+
+ /* Claim: the mesh is now in a consistent state, except that eDel->Org
+ * may have been deleted. Now we disconnect eDel->Dst.
+ */
+ if( eDelSym->Onext == eDelSym ) {
+ KillVertex( eDelSym->Org, NULL );
+ KillFace( eDelSym->Lface, NULL );
+ } else {
+ /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
+ eDel->Lface->anEdge = eDelSym->Oprev;
+ eDelSym->Org->anEdge = eDelSym->Onext;
+ Splice( eDelSym, eDelSym->Oprev );
+ }
+
+ /* Any isolated vertices or faces have already been freed. */
+ KillEdge( eDel );
+
+ return 1;
+}
+
+
+/******************** Other Edge Operations **********************/
+
+/* All these routines can be implemented with the basic edge
+ * operations above. They are provided for convenience and efficiency.
+ */
+
+
+/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
+ * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
+ * eOrg and eNew will have the same left face.
+ */
+GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
+{
+ GLUhalfEdge *eNewSym;
+ GLUhalfEdge *eNew = MakeEdge( eOrg );
+ if (eNew == NULL) return NULL;
+
+ eNewSym = eNew->Sym;
+
+ /* Connect the new edge appropriately */
+ Splice( eNew, eOrg->Lnext );
+
+ /* Set the vertex and face information */
+ eNew->Org = eOrg->Dst;
+ {
+ GLUvertex *newVertex= allocVertex();
+ if (newVertex == NULL) return NULL;
+
+ MakeVertex( newVertex, eNewSym, eNew->Org );
+ }
+ eNew->Lface = eNewSym->Lface = eOrg->Lface;
+
+ return eNew;
+}
+
+
+/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
+ * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
+ * eOrg and eNew will have the same left face.
+ */
+GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
+{
+ GLUhalfEdge *eNew;
+ GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
+ if (tempHalfEdge == NULL) return NULL;
+
+ eNew = tempHalfEdge->Sym;
+
+ /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
+ Splice( eOrg->Sym, eOrg->Sym->Oprev );
+ Splice( eOrg->Sym, eNew );
+
+ /* Set the vertex and face information */
+ eOrg->Dst = eNew->Org;
+ eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */
+ eNew->Rface = eOrg->Rface;
+ eNew->winding = eOrg->winding; /* copy old winding information */
+ eNew->Sym->winding = eOrg->Sym->winding;
+
+ return eNew;
+}
+
+
+/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
+ * to eDst->Org, and returns the corresponding half-edge eNew.
+ * If eOrg->Lface == eDst->Lface, this splits one loop into two,
+ * and the newly created loop is eNew->Lface. Otherwise, two disjoint
+ * loops are merged into one, and the loop eDst->Lface is destroyed.
+ *
+ * If (eOrg == eDst), the new face will have only two edges.
+ * If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
+ * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
+ */
+GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
+{
+ GLUhalfEdge *eNewSym;
+ int joiningLoops = FALSE;
+ GLUhalfEdge *eNew = MakeEdge( eOrg );
+ if (eNew == NULL) return NULL;
+
+ eNewSym = eNew->Sym;
+
+ if( eDst->Lface != eOrg->Lface ) {
+ /* We are connecting two disjoint loops -- destroy eDst->Lface */
+ joiningLoops = TRUE;
+ KillFace( eDst->Lface, eOrg->Lface );
+ }
+
+ /* Connect the new edge appropriately */
+ Splice( eNew, eOrg->Lnext );
+ Splice( eNewSym, eDst );
+
+ /* Set the vertex and face information */
+ eNew->Org = eOrg->Dst;
+ eNewSym->Org = eDst->Org;
+ eNew->Lface = eNewSym->Lface = eOrg->Lface;
+
+ /* Make sure the old face points to a valid half-edge */
+ eOrg->Lface->anEdge = eNewSym;
+
+ if( ! joiningLoops ) {
+ GLUface *newFace= allocFace();
+ if (newFace == NULL) return NULL;
+
+ /* We split one loop into two -- the new loop is eNew->Lface */
+ MakeFace( newFace, eNew, eOrg->Lface );
+ }
+ return eNew;
+}
+
+
+/******************** Other Operations **********************/
+
+/* __gl_meshZapFace( fZap ) destroys a face and removes it from the
+ * global face list. All edges of fZap will have a NULL pointer as their
+ * left face. Any edges which also have a NULL pointer as their right face
+ * are deleted entirely (along with any isolated vertices this produces).
+ * An entire mesh can be deleted by zapping its faces, one at a time,
+ * in any order. Zapped faces cannot be used in further mesh operations!
+ */
+void __gl_meshZapFace( GLUface *fZap )
+{
+ GLUhalfEdge *eStart = fZap->anEdge;
+ GLUhalfEdge *e, *eNext, *eSym;
+ GLUface *fPrev, *fNext;
+
+ /* walk around face, deleting edges whose right face is also NULL */
+ eNext = eStart->Lnext;
+ do {
+ e = eNext;
+ eNext = e->Lnext;
+
+ e->Lface = NULL;
+ if( e->Rface == NULL ) {
+ /* delete the edge -- see __gl_MeshDelete above */
+
+ if( e->Onext == e ) {
+ KillVertex( e->Org, NULL );
+ } else {
+ /* Make sure that e->Org points to a valid half-edge */
+ e->Org->anEdge = e->Onext;
+ Splice( e, e->Oprev );
+ }
+ eSym = e->Sym;
+ if( eSym->Onext == eSym ) {
+ KillVertex( eSym->Org, NULL );
+ } else {
+ /* Make sure that eSym->Org points to a valid half-edge */
+ eSym->Org->anEdge = eSym->Onext;
+ Splice( eSym, eSym->Oprev );
+ }
+ KillEdge( e );
+ }
+ } while( e != eStart );
+
+ /* delete from circular doubly-linked list */
+ fPrev = fZap->prev;
+ fNext = fZap->next;
+ fNext->prev = fPrev;
+ fPrev->next = fNext;
+
+ memFree( fZap );
+}
+
+
+/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
+ * and no loops (what we usually call a "face").
+ */
+GLUmesh *__gl_meshNewMesh( void )
+{
+ GLUvertex *v;
+ GLUface *f;
+ GLUhalfEdge *e;
+ GLUhalfEdge *eSym;
+ GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
+ if (mesh == NULL) {
+ return NULL;
+ }
+
+ v = &mesh->vHead;
+ f = &mesh->fHead;
+ e = &mesh->eHead;
+ eSym = &mesh->eHeadSym;
+
+ v->next = v->prev = v;
+ v->anEdge = NULL;
+ v->data = NULL;
+
+ f->next = f->prev = f;
+ f->anEdge = NULL;
+ f->data = NULL;
+ f->trail = NULL;
+ f->marked = FALSE;
+ f->inside = FALSE;
+
+ e->next = e;
+ e->Sym = eSym;
+ e->Onext = NULL;
+ e->Lnext = NULL;
+ e->Org = NULL;
+ e->Lface = NULL;
+ e->winding = 0;
+ e->activeRegion = NULL;
+
+ eSym->next = eSym;
+ eSym->Sym = e;
+ eSym->Onext = NULL;
+ eSym->Lnext = NULL;
+ eSym->Org = NULL;
+ eSym->Lface = NULL;
+ eSym->winding = 0;
+ eSym->activeRegion = NULL;
+
+ return mesh;
+}
+
+
+/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
+ * both meshes, and returns the new mesh (the old meshes are destroyed).
+ */
+GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
+{
+ GLUface *f1 = &mesh1->fHead;
+ GLUvertex *v1 = &mesh1->vHead;
+ GLUhalfEdge *e1 = &mesh1->eHead;
+ GLUface *f2 = &mesh2->fHead;
+ GLUvertex *v2 = &mesh2->vHead;
+ GLUhalfEdge *e2 = &mesh2->eHead;
+
+ /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
+ if( f2->next != f2 ) {
+ f1->prev->next = f2->next;
+ f2->next->prev = f1->prev;
+ f2->prev->next = f1;
+ f1->prev = f2->prev;
+ }
+
+ if( v2->next != v2 ) {
+ v1->prev->next = v2->next;
+ v2->next->prev = v1->prev;
+ v2->prev->next = v1;
+ v1->prev = v2->prev;
+ }
+
+ if( e2->next != e2 ) {
+ e1->Sym->next->Sym->next = e2->next;
+ e2->next->Sym->next = e1->Sym->next;
+ e2->Sym->next->Sym->next = e1;
+ e1->Sym->next = e2->Sym->next;
+ }
+
+ memFree( mesh2 );
+ return mesh1;
+}
+
+
+#ifdef DELETE_BY_ZAPPING
+
+/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
+ */
+void __gl_meshDeleteMesh( GLUmesh *mesh )
+{
+ GLUface *fHead = &mesh->fHead;
+
+ while( fHead->next != fHead ) {
+ __gl_meshZapFace( fHead->next );
+ }
+ assert( mesh->vHead.next == &mesh->vHead );
+
+ memFree( mesh );
+}
+
+#else
+
+/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
+ */
+void __gl_meshDeleteMesh( GLUmesh *mesh )
+{
+ GLUface *f, *fNext;
+ GLUvertex *v, *vNext;
+ GLUhalfEdge *e, *eNext;
+
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
+ fNext = f->next;
+ memFree( f );
+ }
+
+ for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
+ vNext = v->next;
+ memFree( v );
+ }
+
+ for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
+ /* One call frees both e and e->Sym (see EdgePair above) */
+ eNext = e->next;
+ memFree( e );
+ }
+
+ memFree( mesh );
+}
+
+#endif
+
+#ifndef NDEBUG
+
+/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
+ */
+void __gl_meshCheckMesh( GLUmesh *mesh )
+{
+ GLUface *fHead = &mesh->fHead;
+ GLUvertex *vHead = &mesh->vHead;
+ GLUhalfEdge *eHead = &mesh->eHead;
+ GLUface *f, *fPrev;
+ GLUvertex *v, *vPrev;
+ GLUhalfEdge *e, *ePrev;
+
+ fPrev = fHead;
+ for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
+ assert( f->prev == fPrev );
+ e = f->anEdge;
+ do {
+ assert( e->Sym != e );
+ assert( e->Sym->Sym == e );
+ assert( e->Lnext->Onext->Sym == e );
+ assert( e->Onext->Sym->Lnext == e );
+ assert( e->Lface == f );
+ e = e->Lnext;
+ } while( e != f->anEdge );
+ }
+ assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
+
+ vPrev = vHead;
+ for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
+ assert( v->prev == vPrev );
+ e = v->anEdge;
+ do {
+ assert( e->Sym != e );
+ assert( e->Sym->Sym == e );
+ assert( e->Lnext->Onext->Sym == e );
+ assert( e->Onext->Sym->Lnext == e );
+ assert( e->Org == v );
+ e = e->Onext;
+ } while( e != v->anEdge );
+ }
+ assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
+
+ ePrev = eHead;
+ for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
+ assert( e->Sym->next == ePrev->Sym );
+ assert( e->Sym != e );
+ assert( e->Sym->Sym == e );
+ assert( e->Org != NULL );
+ assert( e->Dst != NULL );
+ assert( e->Lnext->Onext->Sym == e );
+ assert( e->Onext->Sym->Lnext == e );
+ }
+ assert( e->Sym->next == ePrev->Sym
+ && e->Sym == &mesh->eHeadSym
+ && e->Sym->Sym == e
+ && e->Org == NULL && e->Dst == NULL
+ && e->Lface == NULL && e->Rface == NULL );
+}
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/mesh.h b/mesalib/src/glu/sgi/libtess/mesh.h
new file mode 100644
index 000000000..690c5f2f6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/mesh.h
@@ -0,0 +1,266 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __mesh_h_
+#define __mesh_h_
+
+#include <GL/glu.h>
+
+typedef struct GLUmesh GLUmesh;
+
+typedef struct GLUvertex GLUvertex;
+typedef struct GLUface GLUface;
+typedef struct GLUhalfEdge GLUhalfEdge;
+
+typedef struct ActiveRegion ActiveRegion; /* Internal data */
+
+/* The mesh structure is similar in spirit, notation, and operations
+ * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
+ * for the manipulation of general subdivisions and the computation of
+ * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
+ * For a simplified description, see the course notes for CS348a,
+ * "Mathematical Foundations of Computer Graphics", available at the
+ * Stanford bookstore (and taught during the fall quarter).
+ * The implementation also borrows a tiny subset of the graph-based approach
+ * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
+ * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
+ *
+ * The fundamental data structure is the "half-edge". Two half-edges
+ * go together to make an edge, but they point in opposite directions.
+ * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
+ * its origin vertex (Org), the face on its left side (Lface), and the
+ * adjacent half-edges in the CCW direction around the origin vertex
+ * (Onext) and around the left face (Lnext). There is also a "next"
+ * pointer for the global edge list (see below).
+ *
+ * The notation used for mesh navigation:
+ * Sym = the mate of a half-edge (same edge, but opposite direction)
+ * Onext = edge CCW around origin vertex (keep same origin)
+ * Dnext = edge CCW around destination vertex (keep same dest)
+ * Lnext = edge CCW around left face (dest becomes new origin)
+ * Rnext = edge CCW around right face (origin becomes new dest)
+ *
+ * "prev" means to substitute CW for CCW in the definitions above.
+ *
+ * The mesh keeps global lists of all vertices, faces, and edges,
+ * stored as doubly-linked circular lists with a dummy header node.
+ * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
+ *
+ * The circular edge list is special; since half-edges always occur
+ * in pairs (e and e->Sym), each half-edge stores a pointer in only
+ * one direction. Starting at eHead and following the e->next pointers
+ * will visit each *edge* once (ie. e or e->Sym, but not both).
+ * e->Sym stores a pointer in the opposite direction, thus it is
+ * always true that e->Sym->next->Sym->next == e.
+ *
+ * Each vertex has a pointer to next and previous vertices in the
+ * circular list, and a pointer to a half-edge with this vertex as
+ * the origin (NULL if this is the dummy header). There is also a
+ * field "data" for client data.
+ *
+ * Each face has a pointer to the next and previous faces in the
+ * circular list, and a pointer to a half-edge with this face as
+ * the left face (NULL if this is the dummy header). There is also
+ * a field "data" for client data.
+ *
+ * Note that what we call a "face" is really a loop; faces may consist
+ * of more than one loop (ie. not simply connected), but there is no
+ * record of this in the data structure. The mesh may consist of
+ * several disconnected regions, so it may not be possible to visit
+ * the entire mesh by starting at a half-edge and traversing the edge
+ * structure.
+ *
+ * The mesh does NOT support isolated vertices; a vertex is deleted along
+ * with its last edge. Similarly when two faces are merged, one of the
+ * faces is deleted (see __gl_meshDelete below). For mesh operations,
+ * all face (loop) and vertex pointers must not be NULL. However, once
+ * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
+ * faces of the mesh, one at a time. All external faces can be "zapped"
+ * before the mesh is returned to the client; then a NULL face indicates
+ * a region which is not part of the output polygon.
+ */
+
+struct GLUvertex {
+ GLUvertex *next; /* next vertex (never NULL) */
+ GLUvertex *prev; /* previous vertex (never NULL) */
+ GLUhalfEdge *anEdge; /* a half-edge with this origin */
+ void *data; /* client's data */
+
+ /* Internal data (keep hidden) */
+ GLdouble coords[3]; /* vertex location in 3D */
+ GLdouble s, t; /* projection onto the sweep plane */
+ long pqHandle; /* to allow deletion from priority queue */
+};
+
+struct GLUface {
+ GLUface *next; /* next face (never NULL) */
+ GLUface *prev; /* previous face (never NULL) */
+ GLUhalfEdge *anEdge; /* a half edge with this left face */
+ void *data; /* room for client's data */
+
+ /* Internal data (keep hidden) */
+ GLUface *trail; /* "stack" for conversion to strips */
+ GLboolean marked; /* flag for conversion to strips */
+ GLboolean inside; /* this face is in the polygon interior */
+};
+
+struct GLUhalfEdge {
+ GLUhalfEdge *next; /* doubly-linked list (prev==Sym->next) */
+ GLUhalfEdge *Sym; /* same edge, opposite direction */
+ GLUhalfEdge *Onext; /* next edge CCW around origin */
+ GLUhalfEdge *Lnext; /* next edge CCW around left face */
+ GLUvertex *Org; /* origin vertex (Overtex too long) */
+ GLUface *Lface; /* left face */
+
+ /* Internal data (keep hidden) */
+ ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */
+ int winding; /* change in winding number when crossing
+ from the right face to the left face */
+};
+
+#define Rface Sym->Lface
+#define Dst Sym->Org
+
+#define Oprev Sym->Lnext
+#define Lprev Onext->Sym
+#define Dprev Lnext->Sym
+#define Rprev Sym->Onext
+#define Dnext Rprev->Sym /* 3 pointers */
+#define Rnext Oprev->Sym /* 3 pointers */
+
+
+struct GLUmesh {
+ GLUvertex vHead; /* dummy header for vertex list */
+ GLUface fHead; /* dummy header for face list */
+ GLUhalfEdge eHead; /* dummy header for edge list */
+ GLUhalfEdge eHeadSym; /* and its symmetric counterpart */
+};
+
+/* The mesh operations below have three motivations: completeness,
+ * convenience, and efficiency. The basic mesh operations are MakeEdge,
+ * Splice, and Delete. All the other edge operations can be implemented
+ * in terms of these. The other operations are provided for convenience
+ * and/or efficiency.
+ *
+ * When a face is split or a vertex is added, they are inserted into the
+ * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
+ * This makes it easier to process all vertices or faces in the global lists
+ * without worrying about processing the same data twice. As a convenience,
+ * when a face is split, the "inside" flag is copied from the old face.
+ * Other internal data (v->data, v->activeRegion, f->data, f->marked,
+ * f->trail, e->winding) is set to zero.
+ *
+ * ********************** Basic Edge Operations **************************
+ *
+ * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
+ * The loop (face) consists of the two new half-edges.
+ *
+ * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
+ * mesh connectivity and topology. It changes the mesh so that
+ * eOrg->Onext <- OLD( eDst->Onext )
+ * eDst->Onext <- OLD( eOrg->Onext )
+ * where OLD(...) means the value before the meshSplice operation.
+ *
+ * This can have two effects on the vertex structure:
+ * - if eOrg->Org != eDst->Org, the two vertices are merged together
+ * - if eOrg->Org == eDst->Org, the origin is split into two vertices
+ * In both cases, eDst->Org is changed and eOrg->Org is untouched.
+ *
+ * Similarly (and independently) for the face structure,
+ * - if eOrg->Lface == eDst->Lface, one loop is split into two
+ * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
+ * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
+ *
+ * __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
+ * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
+ * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
+ * the newly created loop will contain eDel->Dst. If the deletion of eDel
+ * would create isolated vertices, those are deleted as well.
+ *
+ * ********************** Other Edge Operations **************************
+ *
+ * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
+ * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
+ * eOrg and eNew will have the same left face.
+ *
+ * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
+ * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
+ * eOrg and eNew will have the same left face.
+ *
+ * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
+ * to eDst->Org, and returns the corresponding half-edge eNew.
+ * If eOrg->Lface == eDst->Lface, this splits one loop into two,
+ * and the newly created loop is eNew->Lface. Otherwise, two disjoint
+ * loops are merged into one, and the loop eDst->Lface is destroyed.
+ *
+ * ************************ Other Operations *****************************
+ *
+ * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
+ * and no loops (what we usually call a "face").
+ *
+ * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
+ * both meshes, and returns the new mesh (the old meshes are destroyed).
+ *
+ * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
+ *
+ * __gl_meshZapFace( fZap ) destroys a face and removes it from the
+ * global face list. All edges of fZap will have a NULL pointer as their
+ * left face. Any edges which also have a NULL pointer as their right face
+ * are deleted entirely (along with any isolated vertices this produces).
+ * An entire mesh can be deleted by zapping its faces, one at a time,
+ * in any order. Zapped faces cannot be used in further mesh operations!
+ *
+ * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
+ */
+
+GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh );
+int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
+int __gl_meshDelete( GLUhalfEdge *eDel );
+
+GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg );
+GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg );
+GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
+
+GLUmesh *__gl_meshNewMesh( void );
+GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 );
+void __gl_meshDeleteMesh( GLUmesh *mesh );
+void __gl_meshZapFace( GLUface *fZap );
+
+#ifdef NDEBUG
+#define __gl_meshCheckMesh( mesh )
+#else
+void __gl_meshCheckMesh( GLUmesh *mesh );
+#endif
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/normal.c b/mesalib/src/glu/sgi/libtess/normal.c
new file mode 100644
index 000000000..0a2494be3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/normal.c
@@ -0,0 +1,253 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include "mesh.h"
+#include "tess.h"
+#include "normal.h"
+#include <math.h>
+#include <assert.h>
+
+#define TRUE 1
+#define FALSE 0
+
+#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2])
+
+#if 0
+static void Normalize( GLdouble v[3] )
+{
+ GLdouble len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+
+ assert( len > 0 );
+ len = sqrt( len );
+ v[0] /= len;
+ v[1] /= len;
+ v[2] /= len;
+}
+#endif
+
+#undef ABS
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+static int LongAxis( GLdouble v[3] )
+{
+ int i = 0;
+
+ if( ABS(v[1]) > ABS(v[0]) ) { i = 1; }
+ if( ABS(v[2]) > ABS(v[i]) ) { i = 2; }
+ return i;
+}
+
+static void ComputeNormal( GLUtesselator *tess, GLdouble norm[3] )
+{
+ GLUvertex *v, *v1, *v2;
+ GLdouble c, tLen2, maxLen2;
+ GLdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3];
+ GLUvertex *maxVert[3], *minVert[3];
+ GLUvertex *vHead = &tess->mesh->vHead;
+ int i;
+
+ maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD;
+ minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD;
+
+ for( v = vHead->next; v != vHead; v = v->next ) {
+ for( i = 0; i < 3; ++i ) {
+ c = v->coords[i];
+ if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; }
+ if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; }
+ }
+ }
+
+ /* Find two vertices separated by at least 1/sqrt(3) of the maximum
+ * distance between any two vertices
+ */
+ i = 0;
+ if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; }
+ if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; }
+ if( minVal[i] >= maxVal[i] ) {
+ /* All vertices are the same -- normal doesn't matter */
+ norm[0] = 0; norm[1] = 0; norm[2] = 1;
+ return;
+ }
+
+ /* Look for a third vertex which forms the triangle with maximum area
+ * (Length of normal == twice the triangle area)
+ */
+ maxLen2 = 0;
+ v1 = minVert[i];
+ v2 = maxVert[i];
+ d1[0] = v1->coords[0] - v2->coords[0];
+ d1[1] = v1->coords[1] - v2->coords[1];
+ d1[2] = v1->coords[2] - v2->coords[2];
+ for( v = vHead->next; v != vHead; v = v->next ) {
+ d2[0] = v->coords[0] - v2->coords[0];
+ d2[1] = v->coords[1] - v2->coords[1];
+ d2[2] = v->coords[2] - v2->coords[2];
+ tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1];
+ tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2];
+ tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0];
+ tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2];
+ if( tLen2 > maxLen2 ) {
+ maxLen2 = tLen2;
+ norm[0] = tNorm[0];
+ norm[1] = tNorm[1];
+ norm[2] = tNorm[2];
+ }
+ }
+
+ if( maxLen2 <= 0 ) {
+ /* All points lie on a single line -- any decent normal will do */
+ norm[0] = norm[1] = norm[2] = 0;
+ norm[LongAxis(d1)] = 1;
+ }
+}
+
+
+static void CheckOrientation( GLUtesselator *tess )
+{
+ GLdouble area;
+ GLUface *f, *fHead = &tess->mesh->fHead;
+ GLUvertex *v, *vHead = &tess->mesh->vHead;
+ GLUhalfEdge *e;
+
+ /* When we compute the normal automatically, we choose the orientation
+ * so that the the sum of the signed areas of all contours is non-negative.
+ */
+ area = 0;
+ for( f = fHead->next; f != fHead; f = f->next ) {
+ e = f->anEdge;
+ if( e->winding <= 0 ) continue;
+ do {
+ area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t);
+ e = e->Lnext;
+ } while( e != f->anEdge );
+ }
+ if( area < 0 ) {
+ /* Reverse the orientation by flipping all the t-coordinates */
+ for( v = vHead->next; v != vHead; v = v->next ) {
+ v->t = - v->t;
+ }
+ tess->tUnit[0] = - tess->tUnit[0];
+ tess->tUnit[1] = - tess->tUnit[1];
+ tess->tUnit[2] = - tess->tUnit[2];
+ }
+}
+
+#ifdef FOR_TRITE_TEST_PROGRAM
+#include <stdlib.h>
+extern int RandomSweep;
+#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0)
+#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0)
+#else
+#if defined(SLANTED_SWEEP)
+/* The "feature merging" is not intended to be complete. There are
+ * special cases where edges are nearly parallel to the sweep line
+ * which are not implemented. The algorithm should still behave
+ * robustly (ie. produce a reasonable tesselation) in the presence
+ * of such edges, however it may miss features which could have been
+ * merged. We could minimize this effect by choosing the sweep line
+ * direction to be something unusual (ie. not parallel to one of the
+ * coordinate axes).
+ */
+#define S_UNIT_X 0.50941539564955385 /* Pre-normalized */
+#define S_UNIT_Y 0.86052074622010633
+#else
+#define S_UNIT_X 1.0
+#define S_UNIT_Y 0.0
+#endif
+#endif
+
+/* Determine the polygon normal and project vertices onto the plane
+ * of the polygon.
+ */
+void __gl_projectPolygon( GLUtesselator *tess )
+{
+ GLUvertex *v, *vHead = &tess->mesh->vHead;
+ GLdouble norm[3];
+ GLdouble *sUnit, *tUnit;
+ int i, computedNormal = FALSE;
+
+ norm[0] = tess->normal[0];
+ norm[1] = tess->normal[1];
+ norm[2] = tess->normal[2];
+ if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
+ ComputeNormal( tess, norm );
+ computedNormal = TRUE;
+ }
+ sUnit = tess->sUnit;
+ tUnit = tess->tUnit;
+ i = LongAxis( norm );
+
+#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT)
+ /* Choose the initial sUnit vector to be approximately perpendicular
+ * to the normal.
+ */
+ Normalize( norm );
+
+ sUnit[i] = 0;
+ sUnit[(i+1)%3] = S_UNIT_X;
+ sUnit[(i+2)%3] = S_UNIT_Y;
+
+ /* Now make it exactly perpendicular */
+ w = Dot( sUnit, norm );
+ sUnit[0] -= w * norm[0];
+ sUnit[1] -= w * norm[1];
+ sUnit[2] -= w * norm[2];
+ Normalize( sUnit );
+
+ /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */
+ tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1];
+ tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2];
+ tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0];
+ Normalize( tUnit );
+#else
+ /* Project perpendicular to a coordinate axis -- better numerically */
+ sUnit[i] = 0;
+ sUnit[(i+1)%3] = S_UNIT_X;
+ sUnit[(i+2)%3] = S_UNIT_Y;
+
+ tUnit[i] = 0;
+ tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y;
+ tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X;
+#endif
+
+ /* Project the vertices onto the sweep plane */
+ for( v = vHead->next; v != vHead; v = v->next ) {
+ v->s = Dot( v->coords, sUnit );
+ v->t = Dot( v->coords, tUnit );
+ }
+ if( computedNormal ) {
+ CheckOrientation( tess );
+ }
+}
diff --git a/mesalib/src/glu/sgi/libtess/normal.h b/mesalib/src/glu/sgi/libtess/normal.h
new file mode 100644
index 000000000..c376ca445
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/normal.h
@@ -0,0 +1,45 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __normal_h_
+#define __normal_h_
+
+#include "tess.h"
+
+/* __gl_projectPolygon( tess ) determines the polygon normal
+ * and project vertices onto the plane of the polygon.
+ */
+void __gl_projectPolygon( GLUtesselator *tess );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/priorityq-heap.c b/mesalib/src/glu/sgi/libtess/priorityq-heap.c
new file mode 100644
index 000000000..e3a6c6068
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/priorityq-heap.c
@@ -0,0 +1,252 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include <stddef.h>
+#include <assert.h>
+#include "priorityq-heap.h"
+#include "memalloc.h"
+
+#define INIT_SIZE 32
+
+#define TRUE 1
+#define FALSE 0
+
+#ifdef FOR_TRITE_TEST_PROGRAM
+#define LEQ(x,y) (*pq->leq)(x,y)
+#else
+/* Violates modularity, but a little faster */
+#include "geom.h"
+#define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y)
+#endif
+
+/* really __gl_pqHeapNewPriorityQ */
+PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
+{
+ PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
+ if (pq == NULL) return NULL;
+
+ pq->size = 0;
+ pq->max = INIT_SIZE;
+ pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) );
+ if (pq->nodes == NULL) {
+ memFree(pq);
+ return NULL;
+ }
+
+ pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) );
+ if (pq->handles == NULL) {
+ memFree(pq->nodes);
+ memFree(pq);
+ return NULL;
+ }
+
+ pq->initialized = FALSE;
+ pq->freeList = 0;
+ pq->leq = leq;
+
+ pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */
+ pq->handles[1].key = NULL;
+ return pq;
+}
+
+/* really __gl_pqHeapDeletePriorityQ */
+void pqDeletePriorityQ( PriorityQ *pq )
+{
+ memFree( pq->handles );
+ memFree( pq->nodes );
+ memFree( pq );
+}
+
+
+static void FloatDown( PriorityQ *pq, long curr )
+{
+ PQnode *n = pq->nodes;
+ PQhandleElem *h = pq->handles;
+ PQhandle hCurr, hChild;
+ long child;
+
+ hCurr = n[curr].handle;
+ for( ;; ) {
+ child = curr << 1;
+ if( child < pq->size && LEQ( h[n[child+1].handle].key,
+ h[n[child].handle].key )) {
+ ++child;
+ }
+
+ assert(child <= pq->max);
+
+ hChild = n[child].handle;
+ if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) {
+ n[curr].handle = hCurr;
+ h[hCurr].node = curr;
+ break;
+ }
+ n[curr].handle = hChild;
+ h[hChild].node = curr;
+ curr = child;
+ }
+}
+
+
+static void FloatUp( PriorityQ *pq, long curr )
+{
+ PQnode *n = pq->nodes;
+ PQhandleElem *h = pq->handles;
+ PQhandle hCurr, hParent;
+ long parent;
+
+ hCurr = n[curr].handle;
+ for( ;; ) {
+ parent = curr >> 1;
+ hParent = n[parent].handle;
+ if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) {
+ n[curr].handle = hCurr;
+ h[hCurr].node = curr;
+ break;
+ }
+ n[curr].handle = hParent;
+ h[hParent].node = curr;
+ curr = parent;
+ }
+}
+
+/* really __gl_pqHeapInit */
+void pqInit( PriorityQ *pq )
+{
+ long i;
+
+ /* This method of building a heap is O(n), rather than O(n lg n). */
+
+ for( i = pq->size; i >= 1; --i ) {
+ FloatDown( pq, i );
+ }
+ pq->initialized = TRUE;
+}
+
+/* really __gl_pqHeapInsert */
+/* returns LONG_MAX iff out of memory */
+PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
+{
+ long curr;
+ PQhandle free;
+
+ curr = ++ pq->size;
+ if( (curr*2) > pq->max ) {
+ PQnode *saveNodes= pq->nodes;
+ PQhandleElem *saveHandles= pq->handles;
+
+ /* If the heap overflows, double its size. */
+ pq->max <<= 1;
+ pq->nodes = (PQnode *)memRealloc( pq->nodes,
+ (size_t)
+ ((pq->max + 1) * sizeof( pq->nodes[0] )));
+ if (pq->nodes == NULL) {
+ pq->nodes = saveNodes; /* restore ptr to free upon return */
+ return LONG_MAX;
+ }
+ pq->handles = (PQhandleElem *)memRealloc( pq->handles,
+ (size_t)
+ ((pq->max + 1) *
+ sizeof( pq->handles[0] )));
+ if (pq->handles == NULL) {
+ pq->handles = saveHandles; /* restore ptr to free upon return */
+ return LONG_MAX;
+ }
+ }
+
+ if( pq->freeList == 0 ) {
+ free = curr;
+ } else {
+ free = pq->freeList;
+ pq->freeList = pq->handles[free].node;
+ }
+
+ pq->nodes[curr].handle = free;
+ pq->handles[free].node = curr;
+ pq->handles[free].key = keyNew;
+
+ if( pq->initialized ) {
+ FloatUp( pq, curr );
+ }
+ assert(free != LONG_MAX);
+ return free;
+}
+
+/* really __gl_pqHeapExtractMin */
+PQkey pqExtractMin( PriorityQ *pq )
+{
+ PQnode *n = pq->nodes;
+ PQhandleElem *h = pq->handles;
+ PQhandle hMin = n[1].handle;
+ PQkey min = h[hMin].key;
+
+ if( pq->size > 0 ) {
+ n[1].handle = n[pq->size].handle;
+ h[n[1].handle].node = 1;
+
+ h[hMin].key = NULL;
+ h[hMin].node = pq->freeList;
+ pq->freeList = hMin;
+
+ if( -- pq->size > 0 ) {
+ FloatDown( pq, 1 );
+ }
+ }
+ return min;
+}
+
+/* really __gl_pqHeapDelete */
+void pqDelete( PriorityQ *pq, PQhandle hCurr )
+{
+ PQnode *n = pq->nodes;
+ PQhandleElem *h = pq->handles;
+ long curr;
+
+ assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL );
+
+ curr = h[hCurr].node;
+ n[curr].handle = n[pq->size].handle;
+ h[n[curr].handle].node = curr;
+
+ if( curr <= -- pq->size ) {
+ if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) {
+ FloatDown( pq, curr );
+ } else {
+ FloatUp( pq, curr );
+ }
+ }
+ h[hCurr].key = NULL;
+ h[hCurr].node = pq->freeList;
+ pq->freeList = hCurr;
+}
diff --git a/mesalib/src/glu/sgi/libtess/priorityq-heap.h b/mesalib/src/glu/sgi/libtess/priorityq-heap.h
new file mode 100644
index 000000000..dc9aaef87
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/priorityq-heap.h
@@ -0,0 +1,107 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __priorityq_heap_h_
+#define __priorityq_heap_h_
+
+/* Use #define's so that another heap implementation can use this one */
+
+#define PQkey PQHeapKey
+#define PQhandle PQHeapHandle
+#define PriorityQ PriorityQHeap
+
+#define pqNewPriorityQ(leq) __gl_pqHeapNewPriorityQ(leq)
+#define pqDeletePriorityQ(pq) __gl_pqHeapDeletePriorityQ(pq)
+
+/* The basic operations are insertion of a new key (pqInsert),
+ * and examination/extraction of a key whose value is minimum
+ * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
+ * for this purpose pqInsert returns a "handle" which is supplied
+ * as the argument.
+ *
+ * An initial heap may be created efficiently by calling pqInsert
+ * repeatedly, then calling pqInit. In any case pqInit must be called
+ * before any operations other than pqInsert are used.
+ *
+ * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
+ * This may also be tested with pqIsEmpty.
+ */
+#define pqInit(pq) __gl_pqHeapInit(pq)
+#define pqInsert(pq,key) __gl_pqHeapInsert(pq,key)
+#define pqMinimum(pq) __gl_pqHeapMinimum(pq)
+#define pqExtractMin(pq) __gl_pqHeapExtractMin(pq)
+#define pqDelete(pq,handle) __gl_pqHeapDelete(pq,handle)
+#define pqIsEmpty(pq) __gl_pqHeapIsEmpty(pq)
+
+
+/* Since we support deletion the data structure is a little more
+ * complicated than an ordinary heap. "nodes" is the heap itself;
+ * active nodes are stored in the range 1..pq->size. When the
+ * heap exceeds its allocated size (pq->max), its size doubles.
+ * The children of node i are nodes 2i and 2i+1.
+ *
+ * Each node stores an index into an array "handles". Each handle
+ * stores a key, plus a pointer back to the node which currently
+ * represents that key (ie. nodes[handles[i].node].handle == i).
+ */
+
+typedef void *PQkey;
+typedef long PQhandle;
+typedef struct PriorityQ PriorityQ;
+
+typedef struct { PQhandle handle; } PQnode;
+typedef struct { PQkey key; PQhandle node; } PQhandleElem;
+
+struct PriorityQ {
+ PQnode *nodes;
+ PQhandleElem *handles;
+ long size, max;
+ PQhandle freeList;
+ int initialized;
+ int (*leq)(PQkey key1, PQkey key2);
+};
+
+PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
+void pqDeletePriorityQ( PriorityQ *pq );
+
+void pqInit( PriorityQ *pq );
+PQhandle pqInsert( PriorityQ *pq, PQkey key );
+PQkey pqExtractMin( PriorityQ *pq );
+void pqDelete( PriorityQ *pq, PQhandle handle );
+
+
+#define __gl_pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key)
+#define __gl_pqHeapIsEmpty(pq) ((pq)->size == 0)
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/priorityq-sort.h b/mesalib/src/glu/sgi/libtess/priorityq-sort.h
new file mode 100644
index 000000000..746cf5fa6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/priorityq-sort.h
@@ -0,0 +1,117 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __priorityq_sort_h_
+#define __priorityq_sort_h_
+
+#include "priorityq-heap.h"
+
+#undef PQkey
+#undef PQhandle
+#undef PriorityQ
+#undef pqNewPriorityQ
+#undef pqDeletePriorityQ
+#undef pqInit
+#undef pqInsert
+#undef pqMinimum
+#undef pqExtractMin
+#undef pqDelete
+#undef pqIsEmpty
+
+/* Use #define's so that another heap implementation can use this one */
+
+#define PQkey PQSortKey
+#define PQhandle PQSortHandle
+#define PriorityQ PriorityQSort
+
+#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq)
+#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq)
+
+/* The basic operations are insertion of a new key (pqInsert),
+ * and examination/extraction of a key whose value is minimum
+ * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
+ * for this purpose pqInsert returns a "handle" which is supplied
+ * as the argument.
+ *
+ * An initial heap may be created efficiently by calling pqInsert
+ * repeatedly, then calling pqInit. In any case pqInit must be called
+ * before any operations other than pqInsert are used.
+ *
+ * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
+ * This may also be tested with pqIsEmpty.
+ */
+#define pqInit(pq) __gl_pqSortInit(pq)
+#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
+#define pqMinimum(pq) __gl_pqSortMinimum(pq)
+#define pqExtractMin(pq) __gl_pqSortExtractMin(pq)
+#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle)
+#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq)
+
+
+/* Since we support deletion the data structure is a little more
+ * complicated than an ordinary heap. "nodes" is the heap itself;
+ * active nodes are stored in the range 1..pq->size. When the
+ * heap exceeds its allocated size (pq->max), its size doubles.
+ * The children of node i are nodes 2i and 2i+1.
+ *
+ * Each node stores an index into an array "handles". Each handle
+ * stores a key, plus a pointer back to the node which currently
+ * represents that key (ie. nodes[handles[i].node].handle == i).
+ */
+
+typedef PQHeapKey PQkey;
+typedef PQHeapHandle PQhandle;
+typedef struct PriorityQ PriorityQ;
+
+struct PriorityQ {
+ PriorityQHeap *heap;
+ PQkey *keys;
+ PQkey **order;
+ PQhandle size, max;
+ int initialized;
+ int (*leq)(PQkey key1, PQkey key2);
+};
+
+PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
+void pqDeletePriorityQ( PriorityQ *pq );
+
+int pqInit( PriorityQ *pq );
+PQhandle pqInsert( PriorityQ *pq, PQkey key );
+PQkey pqExtractMin( PriorityQ *pq );
+void pqDelete( PriorityQ *pq, PQhandle handle );
+
+PQkey pqMinimum( PriorityQ *pq );
+int pqIsEmpty( PriorityQ *pq );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/priorityq.c b/mesalib/src/glu/sgi/libtess/priorityq.c
new file mode 100644
index 000000000..11f0263ac
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/priorityq.c
@@ -0,0 +1,260 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <stddef.h>
+#include <assert.h>
+#include <limits.h> /* LONG_MAX */
+#include "memalloc.h"
+
+/* Include all the code for the regular heap-based queue here. */
+
+#include "priorityq-heap.c"
+
+/* Now redefine all the function names to map to their "Sort" versions. */
+
+#include "priorityq-sort.h"
+
+/* really __gl_pqSortNewPriorityQ */
+PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
+{
+ PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
+ if (pq == NULL) return NULL;
+
+ pq->heap = __gl_pqHeapNewPriorityQ( leq );
+ if (pq->heap == NULL) {
+ memFree(pq);
+ return NULL;
+ }
+
+ pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) );
+ if (pq->keys == NULL) {
+ __gl_pqHeapDeletePriorityQ(pq->heap);
+ memFree(pq);
+ return NULL;
+ }
+
+ pq->size = 0;
+ pq->max = INIT_SIZE;
+ pq->initialized = FALSE;
+ pq->leq = leq;
+ return pq;
+}
+
+/* really __gl_pqSortDeletePriorityQ */
+void pqDeletePriorityQ( PriorityQ *pq )
+{
+ assert(pq != NULL);
+ if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap );
+ if (pq->order != NULL) memFree( pq->order );
+ if (pq->keys != NULL) memFree( pq->keys );
+ memFree( pq );
+}
+
+
+#define LT(x,y) (! LEQ(y,x))
+#define GT(x,y) (! LEQ(x,y))
+#define Swap(a,b) if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else
+
+/* really __gl_pqSortInit */
+int pqInit( PriorityQ *pq )
+{
+ PQkey **p, **r, **i, **j, *piv;
+ struct { PQkey **p, **r; } Stack[50], *top = Stack;
+ unsigned long seed = 2016473283;
+
+ /* Create an array of indirect pointers to the keys, so that we
+ * the handles we have returned are still valid.
+ */
+/*
+ pq->order = (PQHeapKey **)memAlloc( (size_t)
+ (pq->size * sizeof(pq->order[0])) );
+*/
+ pq->order = (PQHeapKey **)memAlloc( (size_t)
+ ((pq->size+1) * sizeof(pq->order[0])) );
+/* the previous line is a patch to compensate for the fact that IBM */
+/* machines return a null on a malloc of zero bytes (unlike SGI), */
+/* so we have to put in this defense to guard against a memory */
+/* fault four lines down. from fossum@austin.ibm.com. */
+ if (pq->order == NULL) return 0;
+
+ p = pq->order;
+ r = p + pq->size - 1;
+ for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) {
+ *i = piv;
+ }
+
+ /* Sort the indirect pointers in descending order,
+ * using randomized Quicksort
+ */
+ top->p = p; top->r = r; ++top;
+ while( --top >= Stack ) {
+ p = top->p;
+ r = top->r;
+ while( r > p + 10 ) {
+ seed = seed * 1539415821 + 1;
+ i = p + seed % (r - p + 1);
+ piv = *i;
+ *i = *p;
+ *p = piv;
+ i = p - 1;
+ j = r + 1;
+ do {
+ do { ++i; } while( GT( **i, *piv ));
+ do { --j; } while( LT( **j, *piv ));
+ Swap( i, j );
+ } while( i < j );
+ Swap( i, j ); /* Undo last swap */
+ if( i - p < r - j ) {
+ top->p = j+1; top->r = r; ++top;
+ r = i-1;
+ } else {
+ top->p = p; top->r = i-1; ++top;
+ p = j+1;
+ }
+ }
+ /* Insertion sort small lists */
+ for( i = p+1; i <= r; ++i ) {
+ piv = *i;
+ for( j = i; j > p && LT( **(j-1), *piv ); --j ) {
+ *j = *(j-1);
+ }
+ *j = piv;
+ }
+ }
+ pq->max = pq->size;
+ pq->initialized = TRUE;
+ __gl_pqHeapInit( pq->heap ); /* always succeeds */
+
+#ifndef NDEBUG
+ p = pq->order;
+ r = p + pq->size - 1;
+ for( i = p; i < r; ++i ) {
+ assert( LEQ( **(i+1), **i ));
+ }
+#endif
+
+ return 1;
+}
+
+/* really __gl_pqSortInsert */
+/* returns LONG_MAX iff out of memory */
+PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
+{
+ long curr;
+
+ if( pq->initialized ) {
+ return __gl_pqHeapInsert( pq->heap, keyNew );
+ }
+ curr = pq->size;
+ if( ++ pq->size >= pq->max ) {
+ PQkey *saveKey= pq->keys;
+
+ /* If the heap overflows, double its size. */
+ pq->max <<= 1;
+ pq->keys = (PQHeapKey *)memRealloc( pq->keys,
+ (size_t)
+ (pq->max * sizeof( pq->keys[0] )));
+ if (pq->keys == NULL) {
+ pq->keys = saveKey; /* restore ptr to free upon return */
+ return LONG_MAX;
+ }
+ }
+ assert(curr != LONG_MAX);
+ pq->keys[curr] = keyNew;
+
+ /* Negative handles index the sorted array. */
+ return -(curr+1);
+}
+
+/* really __gl_pqSortExtractMin */
+PQkey pqExtractMin( PriorityQ *pq )
+{
+ PQkey sortMin, heapMin;
+
+ if( pq->size == 0 ) {
+ return __gl_pqHeapExtractMin( pq->heap );
+ }
+ sortMin = *(pq->order[pq->size-1]);
+ if( ! __gl_pqHeapIsEmpty( pq->heap )) {
+ heapMin = __gl_pqHeapMinimum( pq->heap );
+ if( LEQ( heapMin, sortMin )) {
+ return __gl_pqHeapExtractMin( pq->heap );
+ }
+ }
+ do {
+ -- pq->size;
+ } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL );
+ return sortMin;
+}
+
+/* really __gl_pqSortMinimum */
+PQkey pqMinimum( PriorityQ *pq )
+{
+ PQkey sortMin, heapMin;
+
+ if( pq->size == 0 ) {
+ return __gl_pqHeapMinimum( pq->heap );
+ }
+ sortMin = *(pq->order[pq->size-1]);
+ if( ! __gl_pqHeapIsEmpty( pq->heap )) {
+ heapMin = __gl_pqHeapMinimum( pq->heap );
+ if( LEQ( heapMin, sortMin )) {
+ return heapMin;
+ }
+ }
+ return sortMin;
+}
+
+/* really __gl_pqSortIsEmpty */
+int pqIsEmpty( PriorityQ *pq )
+{
+ return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap );
+}
+
+/* really __gl_pqSortDelete */
+void pqDelete( PriorityQ *pq, PQhandle curr )
+{
+ if( curr >= 0 ) {
+ __gl_pqHeapDelete( pq->heap, curr );
+ return;
+ }
+ curr = -(curr+1);
+ assert( curr < pq->max && pq->keys[curr] != NULL );
+
+ pq->keys[curr] = NULL;
+ while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) {
+ -- pq->size;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libtess/priorityq.h b/mesalib/src/glu/sgi/libtess/priorityq.h
new file mode 100644
index 000000000..746cf5fa6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/priorityq.h
@@ -0,0 +1,117 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __priorityq_sort_h_
+#define __priorityq_sort_h_
+
+#include "priorityq-heap.h"
+
+#undef PQkey
+#undef PQhandle
+#undef PriorityQ
+#undef pqNewPriorityQ
+#undef pqDeletePriorityQ
+#undef pqInit
+#undef pqInsert
+#undef pqMinimum
+#undef pqExtractMin
+#undef pqDelete
+#undef pqIsEmpty
+
+/* Use #define's so that another heap implementation can use this one */
+
+#define PQkey PQSortKey
+#define PQhandle PQSortHandle
+#define PriorityQ PriorityQSort
+
+#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq)
+#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq)
+
+/* The basic operations are insertion of a new key (pqInsert),
+ * and examination/extraction of a key whose value is minimum
+ * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
+ * for this purpose pqInsert returns a "handle" which is supplied
+ * as the argument.
+ *
+ * An initial heap may be created efficiently by calling pqInsert
+ * repeatedly, then calling pqInit. In any case pqInit must be called
+ * before any operations other than pqInsert are used.
+ *
+ * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
+ * This may also be tested with pqIsEmpty.
+ */
+#define pqInit(pq) __gl_pqSortInit(pq)
+#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
+#define pqMinimum(pq) __gl_pqSortMinimum(pq)
+#define pqExtractMin(pq) __gl_pqSortExtractMin(pq)
+#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle)
+#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq)
+
+
+/* Since we support deletion the data structure is a little more
+ * complicated than an ordinary heap. "nodes" is the heap itself;
+ * active nodes are stored in the range 1..pq->size. When the
+ * heap exceeds its allocated size (pq->max), its size doubles.
+ * The children of node i are nodes 2i and 2i+1.
+ *
+ * Each node stores an index into an array "handles". Each handle
+ * stores a key, plus a pointer back to the node which currently
+ * represents that key (ie. nodes[handles[i].node].handle == i).
+ */
+
+typedef PQHeapKey PQkey;
+typedef PQHeapHandle PQhandle;
+typedef struct PriorityQ PriorityQ;
+
+struct PriorityQ {
+ PriorityQHeap *heap;
+ PQkey *keys;
+ PQkey **order;
+ PQhandle size, max;
+ int initialized;
+ int (*leq)(PQkey key1, PQkey key2);
+};
+
+PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
+void pqDeletePriorityQ( PriorityQ *pq );
+
+int pqInit( PriorityQ *pq );
+PQhandle pqInsert( PriorityQ *pq, PQkey key );
+PQkey pqExtractMin( PriorityQ *pq );
+void pqDelete( PriorityQ *pq, PQhandle handle );
+
+PQkey pqMinimum( PriorityQ *pq );
+int pqIsEmpty( PriorityQ *pq );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/render.c b/mesalib/src/glu/sgi/libtess/render.c
new file mode 100644
index 000000000..4f376f7f4
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/render.c
@@ -0,0 +1,498 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <assert.h>
+#include <stddef.h>
+#include "mesh.h"
+#include "tess.h"
+#include "render.h"
+
+#define TRUE 1
+#define FALSE 0
+
+/* This structure remembers the information we need about a primitive
+ * to be able to render it later, once we have determined which
+ * primitive is able to use the most triangles.
+ */
+struct FaceCount {
+ long size; /* number of triangles used */
+ GLUhalfEdge *eStart; /* edge where this primitive starts */
+ void (*render)(GLUtesselator *, GLUhalfEdge *, long);
+ /* routine to render this primitive */
+};
+
+static struct FaceCount MaximumFan( GLUhalfEdge *eOrig );
+static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig );
+
+static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
+static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
+static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
+ long size );
+
+static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
+static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
+
+
+
+/************************ Strips and Fans decomposition ******************/
+
+/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
+ * fans, strips, and separate triangles. A substantial effort is made
+ * to use as few rendering primitives as possible (ie. to make the fans
+ * and strips as large as possible).
+ *
+ * The rendering output is provided as callbacks (see the api).
+ */
+void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
+{
+ GLUface *f;
+
+ /* Make a list of separate triangles so we can render them all at once */
+ tess->lonelyTriList = NULL;
+
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
+ f->marked = FALSE;
+ }
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
+
+ /* We examine all faces in an arbitrary order. Whenever we find
+ * an unprocessed face F, we output a group of faces including F
+ * whose size is maximum.
+ */
+ if( f->inside && ! f->marked ) {
+ RenderMaximumFaceGroup( tess, f );
+ assert( f->marked );
+ }
+ }
+ if( tess->lonelyTriList != NULL ) {
+ RenderLonelyTriangles( tess, tess->lonelyTriList );
+ tess->lonelyTriList = NULL;
+ }
+}
+
+
+static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
+{
+ /* We want to find the largest triangle fan or strip of unmarked faces
+ * which includes the given face fOrig. There are 3 possible fans
+ * passing through fOrig (one centered at each vertex), and 3 possible
+ * strips (one for each CCW permutation of the vertices). Our strategy
+ * is to try all of these, and take the primitive which uses the most
+ * triangles (a greedy approach).
+ */
+ GLUhalfEdge *e = fOrig->anEdge;
+ struct FaceCount max, newFace;
+
+ max.size = 1;
+ max.eStart = e;
+ max.render = &RenderTriangle;
+
+ if( ! tess->flagBoundary ) {
+ newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
+ newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
+ newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
+
+ newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
+ newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
+ newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
+ }
+ (*(max.render))( tess, max.eStart, max.size );
+}
+
+
+/* Macros which keep track of faces we have marked temporarily, and allow
+ * us to backtrack when necessary. With triangle fans, this is not
+ * really necessary, since the only awkward case is a loop of triangles
+ * around a single origin vertex. However with strips the situation is
+ * more complicated, and we need a general tracking method like the
+ * one here.
+ */
+#define Marked(f) (! (f)->inside || (f)->marked)
+
+#define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
+
+#define FreeTrail(t) if( 1 ) { \
+ while( (t) != NULL ) { \
+ (t)->marked = FALSE; t = (t)->trail; \
+ } \
+ } else /* absorb trailing semicolon */
+
+
+
+static struct FaceCount MaximumFan( GLUhalfEdge *eOrig )
+{
+ /* eOrig->Lface is the face we want to render. We want to find the size
+ * of a maximal fan around eOrig->Org. To do this we just walk around
+ * the origin vertex as far as possible in both directions.
+ */
+ struct FaceCount newFace = { 0, NULL, &RenderFan };
+ GLUface *trail = NULL;
+ GLUhalfEdge *e;
+
+ for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
+ AddToTrail( e->Lface, trail );
+ ++newFace.size;
+ }
+ for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
+ AddToTrail( e->Rface, trail );
+ ++newFace.size;
+ }
+ newFace.eStart = e;
+ /*LINTED*/
+ FreeTrail( trail );
+ return newFace;
+}
+
+
+#define IsEven(n) (((n) & 1) == 0)
+
+static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig )
+{
+ /* Here we are looking for a maximal strip that contains the vertices
+ * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
+ * reverse, such that all triangles are oriented CCW).
+ *
+ * Again we walk forward and backward as far as possible. However for
+ * strips there is a twist: to get CCW orientations, there must be
+ * an *even* number of triangles in the strip on one side of eOrig.
+ * We walk the strip starting on a side with an even number of triangles;
+ * if both side have an odd number, we are forced to shorten one side.
+ */
+ struct FaceCount newFace = { 0, NULL, &RenderStrip };
+ long headSize = 0, tailSize = 0;
+ GLUface *trail = NULL;
+ GLUhalfEdge *e, *eTail, *eHead;
+
+ for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
+ AddToTrail( e->Lface, trail );
+ ++tailSize;
+ e = e->Dprev;
+ if( Marked( e->Lface )) break;
+ AddToTrail( e->Lface, trail );
+ }
+ eTail = e;
+
+ for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
+ AddToTrail( e->Rface, trail );
+ ++headSize;
+ e = e->Oprev;
+ if( Marked( e->Rface )) break;
+ AddToTrail( e->Rface, trail );
+ }
+ eHead = e;
+
+ newFace.size = tailSize + headSize;
+ if( IsEven( tailSize )) {
+ newFace.eStart = eTail->Sym;
+ } else if( IsEven( headSize )) {
+ newFace.eStart = eHead;
+ } else {
+ /* Both sides have odd length, we must shorten one of them. In fact,
+ * we must start from eHead to guarantee inclusion of eOrig->Lface.
+ */
+ --newFace.size;
+ newFace.eStart = eHead->Onext;
+ }
+ /*LINTED*/
+ FreeTrail( trail );
+ return newFace;
+}
+
+
+static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size )
+{
+ /* Just add the triangle to a triangle list, so we can render all
+ * the separate triangles at once.
+ */
+ assert( size == 1 );
+ AddToTrail( e->Lface, tess->lonelyTriList );
+}
+
+
+static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
+{
+ /* Now we render all the separate triangles which could not be
+ * grouped into a triangle fan or strip.
+ */
+ GLUhalfEdge *e;
+ int newState;
+ int edgeState = -1; /* force edge state output for first vertex */
+
+ CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES );
+
+ for( ; f != NULL; f = f->trail ) {
+ /* Loop once for each edge (there will always be 3 edges) */
+
+ e = f->anEdge;
+ do {
+ if( tess->flagBoundary ) {
+ /* Set the "edge state" to TRUE just before we output the
+ * first vertex of each edge on the polygon boundary.
+ */
+ newState = ! e->Rface->inside;
+ if( edgeState != newState ) {
+ edgeState = newState;
+ CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
+ }
+ }
+ CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
+
+ e = e->Lnext;
+ } while( e != f->anEdge );
+ }
+ CALL_END_OR_END_DATA();
+}
+
+
+static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size )
+{
+ /* Render as many CCW triangles as possible in a fan starting from
+ * edge "e". The fan *should* contain exactly "size" triangles
+ * (otherwise we've goofed up somewhere).
+ */
+ CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );
+ CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
+ CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
+
+ while( ! Marked( e->Lface )) {
+ e->Lface->marked = TRUE;
+ --size;
+ e = e->Onext;
+ CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
+ }
+
+ assert( size == 0 );
+ CALL_END_OR_END_DATA();
+}
+
+
+static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size )
+{
+ /* Render as many CCW triangles as possible in a strip starting from
+ * edge "e". The strip *should* contain exactly "size" triangles
+ * (otherwise we've goofed up somewhere).
+ */
+ CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP );
+ CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
+ CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
+
+ while( ! Marked( e->Lface )) {
+ e->Lface->marked = TRUE;
+ --size;
+ e = e->Dprev;
+ CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
+ if( Marked( e->Lface )) break;
+
+ e->Lface->marked = TRUE;
+ --size;
+ e = e->Onext;
+ CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
+ }
+
+ assert( size == 0 );
+ CALL_END_OR_END_DATA();
+}
+
+
+/************************ Boundary contour decomposition ******************/
+
+/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
+ * contour for each face marked "inside". The rendering output is
+ * provided as callbacks (see the api).
+ */
+void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
+{
+ GLUface *f;
+ GLUhalfEdge *e;
+
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
+ if( f->inside ) {
+ CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP );
+ e = f->anEdge;
+ do {
+ CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
+ e = e->Lnext;
+ } while( e != f->anEdge );
+ CALL_END_OR_END_DATA();
+ }
+ }
+}
+
+
+/************************ Quick-and-dirty decomposition ******************/
+
+#define SIGN_INCONSISTENT 2
+
+static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check )
+/*
+ * If check==FALSE, we compute the polygon normal and place it in norm[].
+ * If check==TRUE, we check that each triangle in the fan from v0 has a
+ * consistent orientation with respect to norm[]. If triangles are
+ * consistently oriented CCW, return 1; if CW, return -1; if all triangles
+ * are degenerate return 0; otherwise (no consistent orientation) return
+ * SIGN_INCONSISTENT.
+ */
+{
+ CachedVertex *v0 = tess->cache;
+ CachedVertex *vn = v0 + tess->cacheCount;
+ CachedVertex *vc;
+ GLdouble dot, xc, yc, zc, xp, yp, zp, n[3];
+ int sign = 0;
+
+ /* Find the polygon normal. It is important to get a reasonable
+ * normal even when the polygon is self-intersecting (eg. a bowtie).
+ * Otherwise, the computed normal could be very tiny, but perpendicular
+ * to the true plane of the polygon due to numerical noise. Then all
+ * the triangles would appear to be degenerate and we would incorrectly
+ * decompose the polygon as a fan (or simply not render it at all).
+ *
+ * We use a sum-of-triangles normal algorithm rather than the more
+ * efficient sum-of-trapezoids method (used in CheckOrientation()
+ * in normal.c). This lets us explicitly reverse the signed area
+ * of some triangles to get a reasonable normal in the self-intersecting
+ * case.
+ */
+ if( ! check ) {
+ norm[0] = norm[1] = norm[2] = 0.0;
+ }
+
+ vc = v0 + 1;
+ xc = vc->coords[0] - v0->coords[0];
+ yc = vc->coords[1] - v0->coords[1];
+ zc = vc->coords[2] - v0->coords[2];
+ while( ++vc < vn ) {
+ xp = xc; yp = yc; zp = zc;
+ xc = vc->coords[0] - v0->coords[0];
+ yc = vc->coords[1] - v0->coords[1];
+ zc = vc->coords[2] - v0->coords[2];
+
+ /* Compute (vp - v0) cross (vc - v0) */
+ n[0] = yp*zc - zp*yc;
+ n[1] = zp*xc - xp*zc;
+ n[2] = xp*yc - yp*xc;
+
+ dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
+ if( ! check ) {
+ /* Reverse the contribution of back-facing triangles to get
+ * a reasonable normal for self-intersecting polygons (see above)
+ */
+ if( dot >= 0 ) {
+ norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
+ } else {
+ norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
+ }
+ } else if( dot != 0 ) {
+ /* Check the new orientation for consistency with previous triangles */
+ if( dot > 0 ) {
+ if( sign < 0 ) return SIGN_INCONSISTENT;
+ sign = 1;
+ } else {
+ if( sign > 0 ) return SIGN_INCONSISTENT;
+ sign = -1;
+ }
+ }
+ }
+ return sign;
+}
+
+/* __gl_renderCache( tess ) takes a single contour and tries to render it
+ * as a triangle fan. This handles convex polygons, as well as some
+ * non-convex polygons if we get lucky.
+ *
+ * Returns TRUE if the polygon was successfully rendered. The rendering
+ * output is provided as callbacks (see the api).
+ */
+GLboolean __gl_renderCache( GLUtesselator *tess )
+{
+ CachedVertex *v0 = tess->cache;
+ CachedVertex *vn = v0 + tess->cacheCount;
+ CachedVertex *vc;
+ GLdouble norm[3];
+ int sign;
+
+ if( tess->cacheCount < 3 ) {
+ /* Degenerate contour -- no output */
+ return TRUE;
+ }
+
+ norm[0] = tess->normal[0];
+ norm[1] = tess->normal[1];
+ norm[2] = tess->normal[2];
+ if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
+ ComputeNormal( tess, norm, FALSE );
+ }
+
+ sign = ComputeNormal( tess, norm, TRUE );
+ if( sign == SIGN_INCONSISTENT ) {
+ /* Fan triangles did not have a consistent orientation */
+ return FALSE;
+ }
+ if( sign == 0 ) {
+ /* All triangles were degenerate */
+ return TRUE;
+ }
+
+ /* Make sure we do the right thing for each winding rule */
+ switch( tess->windingRule ) {
+ case GLU_TESS_WINDING_ODD:
+ case GLU_TESS_WINDING_NONZERO:
+ break;
+ case GLU_TESS_WINDING_POSITIVE:
+ if( sign < 0 ) return TRUE;
+ break;
+ case GLU_TESS_WINDING_NEGATIVE:
+ if( sign > 0 ) return TRUE;
+ break;
+ case GLU_TESS_WINDING_ABS_GEQ_TWO:
+ return TRUE;
+ }
+
+ CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP
+ : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN
+ : GL_TRIANGLES );
+
+ CALL_VERTEX_OR_VERTEX_DATA( v0->data );
+ if( sign > 0 ) {
+ for( vc = v0+1; vc < vn; ++vc ) {
+ CALL_VERTEX_OR_VERTEX_DATA( vc->data );
+ }
+ } else {
+ for( vc = vn-1; vc > v0; --vc ) {
+ CALL_VERTEX_OR_VERTEX_DATA( vc->data );
+ }
+ }
+ CALL_END_OR_END_DATA();
+ return TRUE;
+}
diff --git a/mesalib/src/glu/sgi/libtess/render.h b/mesalib/src/glu/sgi/libtess/render.h
new file mode 100644
index 000000000..a298c9a94
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/render.h
@@ -0,0 +1,52 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __render_h_
+#define __render_h_
+
+#include "mesh.h"
+
+/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
+ * fans, strips, and separate triangles. A substantial effort is made
+ * to use as few rendering primitives as possible (ie. to make the fans
+ * and strips as large as possible).
+ *
+ * The rendering output is provided as callbacks (see the api).
+ */
+void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh );
+void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh );
+
+GLboolean __gl_renderCache( GLUtesselator *tess );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/sweep.c b/mesalib/src/glu/sgi/libtess/sweep.c
new file mode 100644
index 000000000..744be6b47
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/sweep.c
@@ -0,0 +1,1357 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <assert.h>
+#include <stddef.h>
+#include <setjmp.h> /* longjmp */
+#include <limits.h> /* LONG_MAX */
+
+#include "mesh.h"
+#include "geom.h"
+#include "tess.h"
+#include "dict.h"
+#include "priorityq.h"
+#include "memalloc.h"
+#include "sweep.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#ifdef FOR_TRITE_TEST_PROGRAM
+extern void DebugEvent( GLUtesselator *tess );
+#else
+#define DebugEvent( tess )
+#endif
+
+/*
+ * Invariants for the Edge Dictionary.
+ * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2)
+ * at any valid location of the sweep event
+ * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2
+ * share a common endpoint
+ * - for each e, e->Dst has been processed, but not e->Org
+ * - each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org)
+ * where "event" is the current sweep line event.
+ * - no edge e has zero length
+ *
+ * Invariants for the Mesh (the processed portion).
+ * - the portion of the mesh left of the sweep line is a planar graph,
+ * ie. there is *some* way to embed it in the plane
+ * - no processed edge has zero length
+ * - no two processed vertices have identical coordinates
+ * - each "inside" region is monotone, ie. can be broken into two chains
+ * of monotonically increasing vertices according to VertLeq(v1,v2)
+ * - a non-invariant: these chains may intersect (very slightly)
+ *
+ * Invariants for the Sweep.
+ * - if none of the edges incident to the event vertex have an activeRegion
+ * (ie. none of these edges are in the edge dictionary), then the vertex
+ * has only right-going edges.
+ * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced
+ * by ConnectRightVertex), then it is the only right-going edge from
+ * its associated vertex. (This says that these edges exist only
+ * when it is necessary.)
+ */
+
+#undef MAX
+#undef MIN
+#define MAX(x,y) ((x) >= (y) ? (x) : (y))
+#define MIN(x,y) ((x) <= (y) ? (x) : (y))
+
+/* When we merge two edges into one, we need to compute the combined
+ * winding of the new edge.
+ */
+#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \
+ eDst->Sym->winding += eSrc->Sym->winding)
+
+static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent );
+static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp );
+static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp );
+
+static int EdgeLeq( GLUtesselator *tess, ActiveRegion *reg1,
+ ActiveRegion *reg2 )
+/*
+ * Both edges must be directed from right to left (this is the canonical
+ * direction for the upper edge of each region).
+ *
+ * The strategy is to evaluate a "t" value for each edge at the
+ * current sweep line position, given by tess->event. The calculations
+ * are designed to be very stable, but of course they are not perfect.
+ *
+ * Special case: if both edge destinations are at the sweep event,
+ * we sort the edges by slope (they would otherwise compare equally).
+ */
+{
+ GLUvertex *event = tess->event;
+ GLUhalfEdge *e1, *e2;
+ GLdouble t1, t2;
+
+ e1 = reg1->eUp;
+ e2 = reg2->eUp;
+
+ if( e1->Dst == event ) {
+ if( e2->Dst == event ) {
+ /* Two edges right of the sweep line which meet at the sweep event.
+ * Sort them by slope.
+ */
+ if( VertLeq( e1->Org, e2->Org )) {
+ return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0;
+ }
+ return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0;
+ }
+ return EdgeSign( e2->Dst, event, e2->Org ) <= 0;
+ }
+ if( e2->Dst == event ) {
+ return EdgeSign( e1->Dst, event, e1->Org ) >= 0;
+ }
+
+ /* General case - compute signed distance *from* e1, e2 to event */
+ t1 = EdgeEval( e1->Dst, event, e1->Org );
+ t2 = EdgeEval( e2->Dst, event, e2->Org );
+ return (t1 >= t2);
+}
+
+
+static void DeleteRegion( GLUtesselator *tess, ActiveRegion *reg )
+{
+ if( reg->fixUpperEdge ) {
+ /* It was created with zero winding number, so it better be
+ * deleted with zero winding number (ie. it better not get merged
+ * with a real edge).
+ */
+ assert( reg->eUp->winding == 0 );
+ }
+ reg->eUp->activeRegion = NULL;
+ dictDelete( tess->dict, reg->nodeUp ); /* __gl_dictListDelete */
+ memFree( reg );
+}
+
+
+static int FixUpperEdge( ActiveRegion *reg, GLUhalfEdge *newEdge )
+/*
+ * Replace an upper edge which needs fixing (see ConnectRightVertex).
+ */
+{
+ assert( reg->fixUpperEdge );
+ if ( !__gl_meshDelete( reg->eUp ) ) return 0;
+ reg->fixUpperEdge = FALSE;
+ reg->eUp = newEdge;
+ newEdge->activeRegion = reg;
+
+ return 1;
+}
+
+static ActiveRegion *TopLeftRegion( ActiveRegion *reg )
+{
+ GLUvertex *org = reg->eUp->Org;
+ GLUhalfEdge *e;
+
+ /* Find the region above the uppermost edge with the same origin */
+ do {
+ reg = RegionAbove( reg );
+ } while( reg->eUp->Org == org );
+
+ /* If the edge above was a temporary edge introduced by ConnectRightVertex,
+ * now is the time to fix it.
+ */
+ if( reg->fixUpperEdge ) {
+ e = __gl_meshConnect( RegionBelow(reg)->eUp->Sym, reg->eUp->Lnext );
+ if (e == NULL) return NULL;
+ if ( !FixUpperEdge( reg, e ) ) return NULL;
+ reg = RegionAbove( reg );
+ }
+ return reg;
+}
+
+static ActiveRegion *TopRightRegion( ActiveRegion *reg )
+{
+ GLUvertex *dst = reg->eUp->Dst;
+
+ /* Find the region above the uppermost edge with the same destination */
+ do {
+ reg = RegionAbove( reg );
+ } while( reg->eUp->Dst == dst );
+ return reg;
+}
+
+static ActiveRegion *AddRegionBelow( GLUtesselator *tess,
+ ActiveRegion *regAbove,
+ GLUhalfEdge *eNewUp )
+/*
+ * Add a new active region to the sweep line, *somewhere* below "regAbove"
+ * (according to where the new edge belongs in the sweep-line dictionary).
+ * The upper edge of the new region will be "eNewUp".
+ * Winding number and "inside" flag are not updated.
+ */
+{
+ ActiveRegion *regNew = (ActiveRegion *)memAlloc( sizeof( ActiveRegion ));
+ if (regNew == NULL) longjmp(tess->env,1);
+
+ regNew->eUp = eNewUp;
+ /* __gl_dictListInsertBefore */
+ regNew->nodeUp = dictInsertBefore( tess->dict, regAbove->nodeUp, regNew );
+ if (regNew->nodeUp == NULL) longjmp(tess->env,1);
+ regNew->fixUpperEdge = FALSE;
+ regNew->sentinel = FALSE;
+ regNew->dirty = FALSE;
+
+ eNewUp->activeRegion = regNew;
+ return regNew;
+}
+
+static GLboolean IsWindingInside( GLUtesselator *tess, int n )
+{
+ switch( tess->windingRule ) {
+ case GLU_TESS_WINDING_ODD:
+ return (n & 1);
+ case GLU_TESS_WINDING_NONZERO:
+ return (n != 0);
+ case GLU_TESS_WINDING_POSITIVE:
+ return (n > 0);
+ case GLU_TESS_WINDING_NEGATIVE:
+ return (n < 0);
+ case GLU_TESS_WINDING_ABS_GEQ_TWO:
+ return (n >= 2) || (n <= -2);
+ }
+ /*LINTED*/
+ assert( FALSE );
+ /*NOTREACHED*/
+ return GL_FALSE; /* avoid compiler complaints */
+}
+
+
+static void ComputeWinding( GLUtesselator *tess, ActiveRegion *reg )
+{
+ reg->windingNumber = RegionAbove(reg)->windingNumber + reg->eUp->winding;
+ reg->inside = IsWindingInside( tess, reg->windingNumber );
+}
+
+
+static void FinishRegion( GLUtesselator *tess, ActiveRegion *reg )
+/*
+ * Delete a region from the sweep line. This happens when the upper
+ * and lower chains of a region meet (at a vertex on the sweep line).
+ * The "inside" flag is copied to the appropriate mesh face (we could
+ * not do this before -- since the structure of the mesh is always
+ * changing, this face may not have even existed until now).
+ */
+{
+ GLUhalfEdge *e = reg->eUp;
+ GLUface *f = e->Lface;
+
+ f->inside = reg->inside;
+ f->anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */
+ DeleteRegion( tess, reg );
+}
+
+
+static GLUhalfEdge *FinishLeftRegions( GLUtesselator *tess,
+ ActiveRegion *regFirst, ActiveRegion *regLast )
+/*
+ * We are given a vertex with one or more left-going edges. All affected
+ * edges should be in the edge dictionary. Starting at regFirst->eUp,
+ * we walk down deleting all regions where both edges have the same
+ * origin vOrg. At the same time we copy the "inside" flag from the
+ * active region to the face, since at this point each face will belong
+ * to at most one region (this was not necessarily true until this point
+ * in the sweep). The walk stops at the region above regLast; if regLast
+ * is NULL we walk as far as possible. At the same time we relink the
+ * mesh if necessary, so that the ordering of edges around vOrg is the
+ * same as in the dictionary.
+ */
+{
+ ActiveRegion *reg, *regPrev;
+ GLUhalfEdge *e, *ePrev;
+
+ regPrev = regFirst;
+ ePrev = regFirst->eUp;
+ while( regPrev != regLast ) {
+ regPrev->fixUpperEdge = FALSE; /* placement was OK */
+ reg = RegionBelow( regPrev );
+ e = reg->eUp;
+ if( e->Org != ePrev->Org ) {
+ if( ! reg->fixUpperEdge ) {
+ /* Remove the last left-going edge. Even though there are no further
+ * edges in the dictionary with this origin, there may be further
+ * such edges in the mesh (if we are adding left edges to a vertex
+ * that has already been processed). Thus it is important to call
+ * FinishRegion rather than just DeleteRegion.
+ */
+ FinishRegion( tess, regPrev );
+ break;
+ }
+ /* If the edge below was a temporary edge introduced by
+ * ConnectRightVertex, now is the time to fix it.
+ */
+ e = __gl_meshConnect( ePrev->Lprev, e->Sym );
+ if (e == NULL) longjmp(tess->env,1);
+ if ( !FixUpperEdge( reg, e ) ) longjmp(tess->env,1);
+ }
+
+ /* Relink edges so that ePrev->Onext == e */
+ if( ePrev->Onext != e ) {
+ if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( ePrev, e ) ) longjmp(tess->env,1);
+ }
+ FinishRegion( tess, regPrev ); /* may change reg->eUp */
+ ePrev = reg->eUp;
+ regPrev = reg;
+ }
+ return ePrev;
+}
+
+
+static void AddRightEdges( GLUtesselator *tess, ActiveRegion *regUp,
+ GLUhalfEdge *eFirst, GLUhalfEdge *eLast, GLUhalfEdge *eTopLeft,
+ GLboolean cleanUp )
+/*
+ * Purpose: insert right-going edges into the edge dictionary, and update
+ * winding numbers and mesh connectivity appropriately. All right-going
+ * edges share a common origin vOrg. Edges are inserted CCW starting at
+ * eFirst; the last edge inserted is eLast->Oprev. If vOrg has any
+ * left-going edges already processed, then eTopLeft must be the edge
+ * such that an imaginary upward vertical segment from vOrg would be
+ * contained between eTopLeft->Oprev and eTopLeft; otherwise eTopLeft
+ * should be NULL.
+ */
+{
+ ActiveRegion *reg, *regPrev;
+ GLUhalfEdge *e, *ePrev;
+ int firstTime = TRUE;
+
+ /* Insert the new right-going edges in the dictionary */
+ e = eFirst;
+ do {
+ assert( VertLeq( e->Org, e->Dst ));
+ AddRegionBelow( tess, regUp, e->Sym );
+ e = e->Onext;
+ } while ( e != eLast );
+
+ /* Walk *all* right-going edges from e->Org, in the dictionary order,
+ * updating the winding numbers of each region, and re-linking the mesh
+ * edges to match the dictionary ordering (if necessary).
+ */
+ if( eTopLeft == NULL ) {
+ eTopLeft = RegionBelow( regUp )->eUp->Rprev;
+ }
+ regPrev = regUp;
+ ePrev = eTopLeft;
+ for( ;; ) {
+ reg = RegionBelow( regPrev );
+ e = reg->eUp->Sym;
+ if( e->Org != ePrev->Org ) break;
+
+ if( e->Onext != ePrev ) {
+ /* Unlink e from its current position, and relink below ePrev */
+ if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( ePrev->Oprev, e ) ) longjmp(tess->env,1);
+ }
+ /* Compute the winding number and "inside" flag for the new regions */
+ reg->windingNumber = regPrev->windingNumber - e->winding;
+ reg->inside = IsWindingInside( tess, reg->windingNumber );
+
+ /* Check for two outgoing edges with same slope -- process these
+ * before any intersection tests (see example in __gl_computeInterior).
+ */
+ regPrev->dirty = TRUE;
+ if( ! firstTime && CheckForRightSplice( tess, regPrev )) {
+ AddWinding( e, ePrev );
+ DeleteRegion( tess, regPrev );
+ if ( !__gl_meshDelete( ePrev ) ) longjmp(tess->env,1);
+ }
+ firstTime = FALSE;
+ regPrev = reg;
+ ePrev = e;
+ }
+ regPrev->dirty = TRUE;
+ assert( regPrev->windingNumber - e->winding == reg->windingNumber );
+
+ if( cleanUp ) {
+ /* Check for intersections between newly adjacent edges. */
+ WalkDirtyRegions( tess, regPrev );
+ }
+}
+
+
+static void CallCombine( GLUtesselator *tess, GLUvertex *isect,
+ void *data[4], GLfloat weights[4], int needed )
+{
+ GLdouble coords[3];
+
+ /* Copy coord data in case the callback changes it. */
+ coords[0] = isect->coords[0];
+ coords[1] = isect->coords[1];
+ coords[2] = isect->coords[2];
+
+ isect->data = NULL;
+ CALL_COMBINE_OR_COMBINE_DATA( coords, data, weights, &isect->data );
+ if( isect->data == NULL ) {
+ if( ! needed ) {
+ isect->data = data[0];
+ } else if( ! tess->fatalError ) {
+ /* The only way fatal error is when two edges are found to intersect,
+ * but the user has not provided the callback necessary to handle
+ * generated intersection points.
+ */
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_NEED_COMBINE_CALLBACK );
+ tess->fatalError = TRUE;
+ }
+ }
+}
+
+static void SpliceMergeVertices( GLUtesselator *tess, GLUhalfEdge *e1,
+ GLUhalfEdge *e2 )
+/*
+ * Two vertices with idential coordinates are combined into one.
+ * e1->Org is kept, while e2->Org is discarded.
+ */
+{
+ void *data[4] = { NULL, NULL, NULL, NULL };
+ GLfloat weights[4] = { 0.5, 0.5, 0.0, 0.0 };
+
+ data[0] = e1->Org->data;
+ data[1] = e2->Org->data;
+ CallCombine( tess, e1->Org, data, weights, FALSE );
+ if ( !__gl_meshSplice( e1, e2 ) ) longjmp(tess->env,1);
+}
+
+static void VertexWeights( GLUvertex *isect, GLUvertex *org, GLUvertex *dst,
+ GLfloat *weights )
+/*
+ * Find some weights which describe how the intersection vertex is
+ * a linear combination of "org" and "dest". Each of the two edges
+ * which generated "isect" is allocated 50% of the weight; each edge
+ * splits the weight between its org and dst according to the
+ * relative distance to "isect".
+ */
+{
+ GLdouble t1 = VertL1dist( org, isect );
+ GLdouble t2 = VertL1dist( dst, isect );
+
+ weights[0] = 0.5 * t2 / (t1 + t2);
+ weights[1] = 0.5 * t1 / (t1 + t2);
+ isect->coords[0] += weights[0]*org->coords[0] + weights[1]*dst->coords[0];
+ isect->coords[1] += weights[0]*org->coords[1] + weights[1]*dst->coords[1];
+ isect->coords[2] += weights[0]*org->coords[2] + weights[1]*dst->coords[2];
+}
+
+
+static void GetIntersectData( GLUtesselator *tess, GLUvertex *isect,
+ GLUvertex *orgUp, GLUvertex *dstUp,
+ GLUvertex *orgLo, GLUvertex *dstLo )
+/*
+ * We've computed a new intersection point, now we need a "data" pointer
+ * from the user so that we can refer to this new vertex in the
+ * rendering callbacks.
+ */
+{
+ void *data[4];
+ GLfloat weights[4];
+
+ data[0] = orgUp->data;
+ data[1] = dstUp->data;
+ data[2] = orgLo->data;
+ data[3] = dstLo->data;
+
+ isect->coords[0] = isect->coords[1] = isect->coords[2] = 0;
+ VertexWeights( isect, orgUp, dstUp, &weights[0] );
+ VertexWeights( isect, orgLo, dstLo, &weights[2] );
+
+ CallCombine( tess, isect, data, weights, TRUE );
+}
+
+static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp )
+/*
+ * Check the upper and lower edge of "regUp", to make sure that the
+ * eUp->Org is above eLo, or eLo->Org is below eUp (depending on which
+ * origin is leftmost).
+ *
+ * The main purpose is to splice right-going edges with the same
+ * dest vertex and nearly identical slopes (ie. we can't distinguish
+ * the slopes numerically). However the splicing can also help us
+ * to recover from numerical errors. For example, suppose at one
+ * point we checked eUp and eLo, and decided that eUp->Org is barely
+ * above eLo. Then later, we split eLo into two edges (eg. from
+ * a splice operation like this one). This can change the result of
+ * our test so that now eUp->Org is incident to eLo, or barely below it.
+ * We must correct this condition to maintain the dictionary invariants.
+ *
+ * One possibility is to check these edges for intersection again
+ * (ie. CheckForIntersect). This is what we do if possible. However
+ * CheckForIntersect requires that tess->event lies between eUp and eLo,
+ * so that it has something to fall back on when the intersection
+ * calculation gives us an unusable answer. So, for those cases where
+ * we can't check for intersection, this routine fixes the problem
+ * by just splicing the offending vertex into the other edge.
+ * This is a guaranteed solution, no matter how degenerate things get.
+ * Basically this is a combinatorial solution to a numerical problem.
+ */
+{
+ ActiveRegion *regLo = RegionBelow(regUp);
+ GLUhalfEdge *eUp = regUp->eUp;
+ GLUhalfEdge *eLo = regLo->eUp;
+
+ if( VertLeq( eUp->Org, eLo->Org )) {
+ if( EdgeSign( eLo->Dst, eUp->Org, eLo->Org ) > 0 ) return FALSE;
+
+ /* eUp->Org appears to be below eLo */
+ if( ! VertEq( eUp->Org, eLo->Org )) {
+ /* Splice eUp->Org into eLo */
+ if ( __gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eUp, eLo->Oprev ) ) longjmp(tess->env,1);
+ regUp->dirty = regLo->dirty = TRUE;
+
+ } else if( eUp->Org != eLo->Org ) {
+ /* merge the two vertices, discarding eUp->Org */
+ pqDelete( tess->pq, eUp->Org->pqHandle ); /* __gl_pqSortDelete */
+ SpliceMergeVertices( tess, eLo->Oprev, eUp );
+ }
+ } else {
+ if( EdgeSign( eUp->Dst, eLo->Org, eUp->Org ) < 0 ) return FALSE;
+
+ /* eLo->Org appears to be above eUp, so splice eLo->Org into eUp */
+ RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
+ if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1);
+ }
+ return TRUE;
+}
+
+static int CheckForLeftSplice( GLUtesselator *tess, ActiveRegion *regUp )
+/*
+ * Check the upper and lower edge of "regUp", to make sure that the
+ * eUp->Dst is above eLo, or eLo->Dst is below eUp (depending on which
+ * destination is rightmost).
+ *
+ * Theoretically, this should always be true. However, splitting an edge
+ * into two pieces can change the results of previous tests. For example,
+ * suppose at one point we checked eUp and eLo, and decided that eUp->Dst
+ * is barely above eLo. Then later, we split eLo into two edges (eg. from
+ * a splice operation like this one). This can change the result of
+ * the test so that now eUp->Dst is incident to eLo, or barely below it.
+ * We must correct this condition to maintain the dictionary invariants
+ * (otherwise new edges might get inserted in the wrong place in the
+ * dictionary, and bad stuff will happen).
+ *
+ * We fix the problem by just splicing the offending vertex into the
+ * other edge.
+ */
+{
+ ActiveRegion *regLo = RegionBelow(regUp);
+ GLUhalfEdge *eUp = regUp->eUp;
+ GLUhalfEdge *eLo = regLo->eUp;
+ GLUhalfEdge *e;
+
+ assert( ! VertEq( eUp->Dst, eLo->Dst ));
+
+ if( VertLeq( eUp->Dst, eLo->Dst )) {
+ if( EdgeSign( eUp->Dst, eLo->Dst, eUp->Org ) < 0 ) return FALSE;
+
+ /* eLo->Dst is above eUp, so splice eLo->Dst into eUp */
+ RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
+ e = __gl_meshSplitEdge( eUp );
+ if (e == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eLo->Sym, e ) ) longjmp(tess->env,1);
+ e->Lface->inside = regUp->inside;
+ } else {
+ if( EdgeSign( eLo->Dst, eUp->Dst, eLo->Org ) > 0 ) return FALSE;
+
+ /* eUp->Dst is below eLo, so splice eUp->Dst into eLo */
+ regUp->dirty = regLo->dirty = TRUE;
+ e = __gl_meshSplitEdge( eLo );
+ if (e == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eUp->Lnext, eLo->Sym ) ) longjmp(tess->env,1);
+ e->Rface->inside = regUp->inside;
+ }
+ return TRUE;
+}
+
+
+static int CheckForIntersect( GLUtesselator *tess, ActiveRegion *regUp )
+/*
+ * Check the upper and lower edges of the given region to see if
+ * they intersect. If so, create the intersection and add it
+ * to the data structures.
+ *
+ * Returns TRUE if adding the new intersection resulted in a recursive
+ * call to AddRightEdges(); in this case all "dirty" regions have been
+ * checked for intersections, and possibly regUp has been deleted.
+ */
+{
+ ActiveRegion *regLo = RegionBelow(regUp);
+ GLUhalfEdge *eUp = regUp->eUp;
+ GLUhalfEdge *eLo = regLo->eUp;
+ GLUvertex *orgUp = eUp->Org;
+ GLUvertex *orgLo = eLo->Org;
+ GLUvertex *dstUp = eUp->Dst;
+ GLUvertex *dstLo = eLo->Dst;
+ GLdouble tMinUp, tMaxLo;
+ GLUvertex isect, *orgMin;
+ GLUhalfEdge *e;
+
+ assert( ! VertEq( dstLo, dstUp ));
+ assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 );
+ assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 );
+ assert( orgUp != tess->event && orgLo != tess->event );
+ assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge );
+
+ if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */
+
+ tMinUp = MIN( orgUp->t, dstUp->t );
+ tMaxLo = MAX( orgLo->t, dstLo->t );
+ if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */
+
+ if( VertLeq( orgUp, orgLo )) {
+ if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE;
+ } else {
+ if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE;
+ }
+
+ /* At this point the edges intersect, at least marginally */
+ DebugEvent( tess );
+
+ __gl_edgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect );
+ /* The following properties are guaranteed: */
+ assert( MIN( orgUp->t, dstUp->t ) <= isect.t );
+ assert( isect.t <= MAX( orgLo->t, dstLo->t ));
+ assert( MIN( dstLo->s, dstUp->s ) <= isect.s );
+ assert( isect.s <= MAX( orgLo->s, orgUp->s ));
+
+ if( VertLeq( &isect, tess->event )) {
+ /* The intersection point lies slightly to the left of the sweep line,
+ * so move it until it''s slightly to the right of the sweep line.
+ * (If we had perfect numerical precision, this would never happen
+ * in the first place). The easiest and safest thing to do is
+ * replace the intersection by tess->event.
+ */
+ isect.s = tess->event->s;
+ isect.t = tess->event->t;
+ }
+ /* Similarly, if the computed intersection lies to the right of the
+ * rightmost origin (which should rarely happen), it can cause
+ * unbelievable inefficiency on sufficiently degenerate inputs.
+ * (If you have the test program, try running test54.d with the
+ * "X zoom" option turned on).
+ */
+ orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo;
+ if( VertLeq( orgMin, &isect )) {
+ isect.s = orgMin->s;
+ isect.t = orgMin->t;
+ }
+
+ if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) {
+ /* Easy case -- intersection at one of the right endpoints */
+ (void) CheckForRightSplice( tess, regUp );
+ return FALSE;
+ }
+
+ if( (! VertEq( dstUp, tess->event )
+ && EdgeSign( dstUp, tess->event, &isect ) >= 0)
+ || (! VertEq( dstLo, tess->event )
+ && EdgeSign( dstLo, tess->event, &isect ) <= 0 ))
+ {
+ /* Very unusual -- the new upper or lower edge would pass on the
+ * wrong side of the sweep event, or through it. This can happen
+ * due to very small numerical errors in the intersection calculation.
+ */
+ if( dstLo == tess->event ) {
+ /* Splice dstLo into eUp, and process the new region(s) */
+ if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eLo->Sym, eUp ) ) longjmp(tess->env,1);
+ regUp = TopLeftRegion( regUp );
+ if (regUp == NULL) longjmp(tess->env,1);
+ eUp = RegionBelow(regUp)->eUp;
+ FinishLeftRegions( tess, RegionBelow(regUp), regLo );
+ AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE );
+ return TRUE;
+ }
+ if( dstUp == tess->event ) {
+ /* Splice dstUp into eLo, and process the new region(s) */
+ if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1);
+ regLo = regUp;
+ regUp = TopRightRegion( regUp );
+ e = RegionBelow(regUp)->eUp->Rprev;
+ regLo->eUp = eLo->Oprev;
+ eLo = FinishLeftRegions( tess, regLo, NULL );
+ AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE );
+ return TRUE;
+ }
+ /* Special case: called from ConnectRightVertex. If either
+ * edge passes on the wrong side of tess->event, split it
+ * (and wait for ConnectRightVertex to splice it appropriately).
+ */
+ if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) {
+ RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
+ if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
+ eUp->Org->s = tess->event->s;
+ eUp->Org->t = tess->event->t;
+ }
+ if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) {
+ regUp->dirty = regLo->dirty = TRUE;
+ if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
+ eLo->Org->s = tess->event->s;
+ eLo->Org->t = tess->event->t;
+ }
+ /* leave the rest for ConnectRightVertex */
+ return FALSE;
+ }
+
+ /* General case -- split both edges, splice into new vertex.
+ * When we do the splice operation, the order of the arguments is
+ * arbitrary as far as correctness goes. However, when the operation
+ * creates a new face, the work done is proportional to the size of
+ * the new face. We expect the faces in the processed part of
+ * the mesh (ie. eUp->Lface) to be smaller than the faces in the
+ * unprocessed original contours (which will be eLo->Oprev->Lface).
+ */
+ if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
+ if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
+ if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1);
+ eUp->Org->s = isect.s;
+ eUp->Org->t = isect.t;
+ eUp->Org->pqHandle = pqInsert( tess->pq, eUp->Org ); /* __gl_pqSortInsert */
+ if (eUp->Org->pqHandle == LONG_MAX) {
+ pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */
+ tess->pq = NULL;
+ longjmp(tess->env,1);
+ }
+ GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo );
+ RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE;
+ return FALSE;
+}
+
+static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp )
+/*
+ * When the upper or lower edge of any region changes, the region is
+ * marked "dirty". This routine walks through all the dirty regions
+ * and makes sure that the dictionary invariants are satisfied
+ * (see the comments at the beginning of this file). Of course
+ * new dirty regions can be created as we make changes to restore
+ * the invariants.
+ */
+{
+ ActiveRegion *regLo = RegionBelow(regUp);
+ GLUhalfEdge *eUp, *eLo;
+
+ for( ;; ) {
+ /* Find the lowest dirty region (we walk from the bottom up). */
+ while( regLo->dirty ) {
+ regUp = regLo;
+ regLo = RegionBelow(regLo);
+ }
+ if( ! regUp->dirty ) {
+ regLo = regUp;
+ regUp = RegionAbove( regUp );
+ if( regUp == NULL || ! regUp->dirty ) {
+ /* We've walked all the dirty regions */
+ return;
+ }
+ }
+ regUp->dirty = FALSE;
+ eUp = regUp->eUp;
+ eLo = regLo->eUp;
+
+ if( eUp->Dst != eLo->Dst ) {
+ /* Check that the edge ordering is obeyed at the Dst vertices. */
+ if( CheckForLeftSplice( tess, regUp )) {
+
+ /* If the upper or lower edge was marked fixUpperEdge, then
+ * we no longer need it (since these edges are needed only for
+ * vertices which otherwise have no right-going edges).
+ */
+ if( regLo->fixUpperEdge ) {
+ DeleteRegion( tess, regLo );
+ if ( !__gl_meshDelete( eLo ) ) longjmp(tess->env,1);
+ regLo = RegionBelow( regUp );
+ eLo = regLo->eUp;
+ } else if( regUp->fixUpperEdge ) {
+ DeleteRegion( tess, regUp );
+ if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);
+ regUp = RegionAbove( regLo );
+ eUp = regUp->eUp;
+ }
+ }
+ }
+ if( eUp->Org != eLo->Org ) {
+ if( eUp->Dst != eLo->Dst
+ && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge
+ && (eUp->Dst == tess->event || eLo->Dst == tess->event) )
+ {
+ /* When all else fails in CheckForIntersect(), it uses tess->event
+ * as the intersection location. To make this possible, it requires
+ * that tess->event lie between the upper and lower edges, and also
+ * that neither of these is marked fixUpperEdge (since in the worst
+ * case it might splice one of these edges into tess->event, and
+ * violate the invariant that fixable edges are the only right-going
+ * edge from their associated vertex).
+ */
+ if( CheckForIntersect( tess, regUp )) {
+ /* WalkDirtyRegions() was called recursively; we're done */
+ return;
+ }
+ } else {
+ /* Even though we can't use CheckForIntersect(), the Org vertices
+ * may violate the dictionary edge ordering. Check and correct this.
+ */
+ (void) CheckForRightSplice( tess, regUp );
+ }
+ }
+ if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) {
+ /* A degenerate loop consisting of only two edges -- delete it. */
+ AddWinding( eLo, eUp );
+ DeleteRegion( tess, regUp );
+ if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);
+ regUp = RegionAbove( regLo );
+ }
+ }
+}
+
+
+static void ConnectRightVertex( GLUtesselator *tess, ActiveRegion *regUp,
+ GLUhalfEdge *eBottomLeft )
+/*
+ * Purpose: connect a "right" vertex vEvent (one where all edges go left)
+ * to the unprocessed portion of the mesh. Since there are no right-going
+ * edges, two regions (one above vEvent and one below) are being merged
+ * into one. "regUp" is the upper of these two regions.
+ *
+ * There are two reasons for doing this (adding a right-going edge):
+ * - if the two regions being merged are "inside", we must add an edge
+ * to keep them separated (the combined region would not be monotone).
+ * - in any case, we must leave some record of vEvent in the dictionary,
+ * so that we can merge vEvent with features that we have not seen yet.
+ * For example, maybe there is a vertical edge which passes just to
+ * the right of vEvent; we would like to splice vEvent into this edge.
+ *
+ * However, we don't want to connect vEvent to just any vertex. We don''t
+ * want the new edge to cross any other edges; otherwise we will create
+ * intersection vertices even when the input data had no self-intersections.
+ * (This is a bad thing; if the user's input data has no intersections,
+ * we don't want to generate any false intersections ourselves.)
+ *
+ * Our eventual goal is to connect vEvent to the leftmost unprocessed
+ * vertex of the combined region (the union of regUp and regLo).
+ * But because of unseen vertices with all right-going edges, and also
+ * new vertices which may be created by edge intersections, we don''t
+ * know where that leftmost unprocessed vertex is. In the meantime, we
+ * connect vEvent to the closest vertex of either chain, and mark the region
+ * as "fixUpperEdge". This flag says to delete and reconnect this edge
+ * to the next processed vertex on the boundary of the combined region.
+ * Quite possibly the vertex we connected to will turn out to be the
+ * closest one, in which case we won''t need to make any changes.
+ */
+{
+ GLUhalfEdge *eNew;
+ GLUhalfEdge *eTopLeft = eBottomLeft->Onext;
+ ActiveRegion *regLo = RegionBelow(regUp);
+ GLUhalfEdge *eUp = regUp->eUp;
+ GLUhalfEdge *eLo = regLo->eUp;
+ int degenerate = FALSE;
+
+ if( eUp->Dst != eLo->Dst ) {
+ (void) CheckForIntersect( tess, regUp );
+ }
+
+ /* Possible new degeneracies: upper or lower edge of regUp may pass
+ * through vEvent, or may coincide with new intersection vertex
+ */
+ if( VertEq( eUp->Org, tess->event )) {
+ if ( !__gl_meshSplice( eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1);
+ regUp = TopLeftRegion( regUp );
+ if (regUp == NULL) longjmp(tess->env,1);
+ eTopLeft = RegionBelow( regUp )->eUp;
+ FinishLeftRegions( tess, RegionBelow(regUp), regLo );
+ degenerate = TRUE;
+ }
+ if( VertEq( eLo->Org, tess->event )) {
+ if ( !__gl_meshSplice( eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1);
+ eBottomLeft = FinishLeftRegions( tess, regLo, NULL );
+ degenerate = TRUE;
+ }
+ if( degenerate ) {
+ AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );
+ return;
+ }
+
+ /* Non-degenerate situation -- need to add a temporary, fixable edge.
+ * Connect to the closer of eLo->Org, eUp->Org.
+ */
+ if( VertLeq( eLo->Org, eUp->Org )) {
+ eNew = eLo->Oprev;
+ } else {
+ eNew = eUp;
+ }
+ eNew = __gl_meshConnect( eBottomLeft->Lprev, eNew );
+ if (eNew == NULL) longjmp(tess->env,1);
+
+ /* Prevent cleanup, otherwise eNew might disappear before we've even
+ * had a chance to mark it as a temporary edge.
+ */
+ AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE );
+ eNew->Sym->activeRegion->fixUpperEdge = TRUE;
+ WalkDirtyRegions( tess, regUp );
+}
+
+/* Because vertices at exactly the same location are merged together
+ * before we process the sweep event, some degenerate cases can't occur.
+ * However if someone eventually makes the modifications required to
+ * merge features which are close together, the cases below marked
+ * TOLERANCE_NONZERO will be useful. They were debugged before the
+ * code to merge identical vertices in the main loop was added.
+ */
+#define TOLERANCE_NONZERO FALSE
+
+static void ConnectLeftDegenerate( GLUtesselator *tess,
+ ActiveRegion *regUp, GLUvertex *vEvent )
+/*
+ * The event vertex lies exacty on an already-processed edge or vertex.
+ * Adding the new vertex involves splicing it into the already-processed
+ * part of the mesh.
+ */
+{
+ GLUhalfEdge *e, *eTopLeft, *eTopRight, *eLast;
+ ActiveRegion *reg;
+
+ e = regUp->eUp;
+ if( VertEq( e->Org, vEvent )) {
+ /* e->Org is an unprocessed vertex - just combine them, and wait
+ * for e->Org to be pulled from the queue
+ */
+ assert( TOLERANCE_NONZERO );
+ SpliceMergeVertices( tess, e, vEvent->anEdge );
+ return;
+ }
+
+ if( ! VertEq( e->Dst, vEvent )) {
+ /* General case -- splice vEvent into edge e which passes through it */
+ if (__gl_meshSplitEdge( e->Sym ) == NULL) longjmp(tess->env,1);
+ if( regUp->fixUpperEdge ) {
+ /* This edge was fixable -- delete unused portion of original edge */
+ if ( !__gl_meshDelete( e->Onext ) ) longjmp(tess->env,1);
+ regUp->fixUpperEdge = FALSE;
+ }
+ if ( !__gl_meshSplice( vEvent->anEdge, e ) ) longjmp(tess->env,1);
+ SweepEvent( tess, vEvent ); /* recurse */
+ return;
+ }
+
+ /* vEvent coincides with e->Dst, which has already been processed.
+ * Splice in the additional right-going edges.
+ */
+ assert( TOLERANCE_NONZERO );
+ regUp = TopRightRegion( regUp );
+ reg = RegionBelow( regUp );
+ eTopRight = reg->eUp->Sym;
+ eTopLeft = eLast = eTopRight->Onext;
+ if( reg->fixUpperEdge ) {
+ /* Here e->Dst has only a single fixable edge going right.
+ * We can delete it since now we have some real right-going edges.
+ */
+ assert( eTopLeft != eTopRight ); /* there are some left edges too */
+ DeleteRegion( tess, reg );
+ if ( !__gl_meshDelete( eTopRight ) ) longjmp(tess->env,1);
+ eTopRight = eTopLeft->Oprev;
+ }
+ if ( !__gl_meshSplice( vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1);
+ if( ! EdgeGoesLeft( eTopLeft )) {
+ /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */
+ eTopLeft = NULL;
+ }
+ AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE );
+}
+
+
+static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent )
+/*
+ * Purpose: connect a "left" vertex (one where both edges go right)
+ * to the processed portion of the mesh. Let R be the active region
+ * containing vEvent, and let U and L be the upper and lower edge
+ * chains of R. There are two possibilities:
+ *
+ * - the normal case: split R into two regions, by connecting vEvent to
+ * the rightmost vertex of U or L lying to the left of the sweep line
+ *
+ * - the degenerate case: if vEvent is close enough to U or L, we
+ * merge vEvent into that edge chain. The subcases are:
+ * - merging with the rightmost vertex of U or L
+ * - merging with the active edge of U or L
+ * - merging with an already-processed portion of U or L
+ */
+{
+ ActiveRegion *regUp, *regLo, *reg;
+ GLUhalfEdge *eUp, *eLo, *eNew;
+ ActiveRegion tmp;
+
+ /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */
+
+ /* Get a pointer to the active region containing vEvent */
+ tmp.eUp = vEvent->anEdge->Sym;
+ /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */
+ regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));
+ regLo = RegionBelow( regUp );
+ eUp = regUp->eUp;
+ eLo = regLo->eUp;
+
+ /* Try merging with U or L first */
+ if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {
+ ConnectLeftDegenerate( tess, regUp, vEvent );
+ return;
+ }
+
+ /* Connect vEvent to rightmost processed vertex of either chain.
+ * e->Dst is the vertex that we will connect to vEvent.
+ */
+ reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;
+
+ if( regUp->inside || reg->fixUpperEdge) {
+ if( reg == regUp ) {
+ eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext );
+ if (eNew == NULL) longjmp(tess->env,1);
+ } else {
+ GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge);
+ if (tempHalfEdge == NULL) longjmp(tess->env,1);
+
+ eNew = tempHalfEdge->Sym;
+ }
+ if( reg->fixUpperEdge ) {
+ if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1);
+ } else {
+ ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));
+ }
+ SweepEvent( tess, vEvent );
+ } else {
+ /* The new vertex is in a region which does not belong to the polygon.
+ * We don''t need to connect this vertex to the rest of the mesh.
+ */
+ AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );
+ }
+}
+
+
+static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent )
+/*
+ * Does everything necessary when the sweep line crosses a vertex.
+ * Updates the mesh and the edge dictionary.
+ */
+{
+ ActiveRegion *regUp, *reg;
+ GLUhalfEdge *e, *eTopLeft, *eBottomLeft;
+
+ tess->event = vEvent; /* for access in EdgeLeq() */
+ DebugEvent( tess );
+
+ /* Check if this vertex is the right endpoint of an edge that is
+ * already in the dictionary. In this case we don't need to waste
+ * time searching for the location to insert new edges.
+ */
+ e = vEvent->anEdge;
+ while( e->activeRegion == NULL ) {
+ e = e->Onext;
+ if( e == vEvent->anEdge ) {
+ /* All edges go right -- not incident to any processed edges */
+ ConnectLeftVertex( tess, vEvent );
+ return;
+ }
+ }
+
+ /* Processing consists of two phases: first we "finish" all the
+ * active regions where both the upper and lower edges terminate
+ * at vEvent (ie. vEvent is closing off these regions).
+ * We mark these faces "inside" or "outside" the polygon according
+ * to their winding number, and delete the edges from the dictionary.
+ * This takes care of all the left-going edges from vEvent.
+ */
+ regUp = TopLeftRegion( e->activeRegion );
+ if (regUp == NULL) longjmp(tess->env,1);
+ reg = RegionBelow( regUp );
+ eTopLeft = reg->eUp;
+ eBottomLeft = FinishLeftRegions( tess, reg, NULL );
+
+ /* Next we process all the right-going edges from vEvent. This
+ * involves adding the edges to the dictionary, and creating the
+ * associated "active regions" which record information about the
+ * regions between adjacent dictionary edges.
+ */
+ if( eBottomLeft->Onext == eTopLeft ) {
+ /* No right-going edges -- add a temporary "fixable" edge */
+ ConnectRightVertex( tess, regUp, eBottomLeft );
+ } else {
+ AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );
+ }
+}
+
+
+/* Make the sentinel coordinates big enough that they will never be
+ * merged with real input features. (Even with the largest possible
+ * input contour and the maximum tolerance of 1.0, no merging will be
+ * done with coordinates larger than 3 * GLU_TESS_MAX_COORD).
+ */
+#define SENTINEL_COORD (4 * GLU_TESS_MAX_COORD)
+
+static void AddSentinel( GLUtesselator *tess, GLdouble t )
+/*
+ * We add two sentinel edges above and below all other edges,
+ * to avoid special cases at the top and bottom.
+ */
+{
+ GLUhalfEdge *e;
+ ActiveRegion *reg = (ActiveRegion *)memAlloc( sizeof( ActiveRegion ));
+ if (reg == NULL) longjmp(tess->env,1);
+
+ e = __gl_meshMakeEdge( tess->mesh );
+ if (e == NULL) longjmp(tess->env,1);
+
+ e->Org->s = SENTINEL_COORD;
+ e->Org->t = t;
+ e->Dst->s = -SENTINEL_COORD;
+ e->Dst->t = t;
+ tess->event = e->Dst; /* initialize it */
+
+ reg->eUp = e;
+ reg->windingNumber = 0;
+ reg->inside = FALSE;
+ reg->fixUpperEdge = FALSE;
+ reg->sentinel = TRUE;
+ reg->dirty = FALSE;
+ reg->nodeUp = dictInsert( tess->dict, reg ); /* __gl_dictListInsertBefore */
+ if (reg->nodeUp == NULL) longjmp(tess->env,1);
+}
+
+
+static void InitEdgeDict( GLUtesselator *tess )
+/*
+ * We maintain an ordering of edge intersections with the sweep line.
+ * This order is maintained in a dynamic dictionary.
+ */
+{
+ /* __gl_dictListNewDict */
+ tess->dict = dictNewDict( tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq );
+ if (tess->dict == NULL) longjmp(tess->env,1);
+
+ AddSentinel( tess, -SENTINEL_COORD );
+ AddSentinel( tess, SENTINEL_COORD );
+}
+
+
+static void DoneEdgeDict( GLUtesselator *tess )
+{
+ ActiveRegion *reg;
+#ifndef NDEBUG
+ int fixedEdges = 0;
+#endif
+
+ /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
+ while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {
+ /*
+ * At the end of all processing, the dictionary should contain
+ * only the two sentinel edges, plus at most one "fixable" edge
+ * created by ConnectRightVertex().
+ */
+ if( ! reg->sentinel ) {
+ assert( reg->fixUpperEdge );
+ assert( ++fixedEdges == 1 );
+ }
+ assert( reg->windingNumber == 0 );
+ DeleteRegion( tess, reg );
+/* __gl_meshDelete( reg->eUp );*/
+ }
+ dictDeleteDict( tess->dict ); /* __gl_dictListDeleteDict */
+}
+
+
+static void RemoveDegenerateEdges( GLUtesselator *tess )
+/*
+ * Remove zero-length edges, and contours with fewer than 3 vertices.
+ */
+{
+ GLUhalfEdge *e, *eNext, *eLnext;
+ GLUhalfEdge *eHead = &tess->mesh->eHead;
+
+ /*LINTED*/
+ for( e = eHead->next; e != eHead; e = eNext ) {
+ eNext = e->next;
+ eLnext = e->Lnext;
+
+ if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) {
+ /* Zero-length edge, contour has at least 3 edges */
+
+ SpliceMergeVertices( tess, eLnext, e ); /* deletes e->Org */
+ if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1); /* e is a self-loop */
+ e = eLnext;
+ eLnext = e->Lnext;
+ }
+ if( eLnext->Lnext == e ) {
+ /* Degenerate contour (one or two edges) */
+
+ if( eLnext != e ) {
+ if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; }
+ if ( !__gl_meshDelete( eLnext ) ) longjmp(tess->env,1);
+ }
+ if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; }
+ if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1);
+ }
+ }
+}
+
+static int InitPriorityQ( GLUtesselator *tess )
+/*
+ * Insert all vertices into the priority queue which determines the
+ * order in which vertices cross the sweep line.
+ */
+{
+ PriorityQ *pq;
+ GLUvertex *v, *vHead;
+
+ /* __gl_pqSortNewPriorityQ */
+ pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq );
+ if (pq == NULL) return 0;
+
+ vHead = &tess->mesh->vHead;
+ for( v = vHead->next; v != vHead; v = v->next ) {
+ v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */
+ if (v->pqHandle == LONG_MAX) break;
+ }
+ if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */
+ pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */
+ tess->pq = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static void DonePriorityQ( GLUtesselator *tess )
+{
+ pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */
+}
+
+
+static int RemoveDegenerateFaces( GLUmesh *mesh )
+/*
+ * Delete any degenerate faces with only two edges. WalkDirtyRegions()
+ * will catch almost all of these, but it won't catch degenerate faces
+ * produced by splice operations on already-processed edges.
+ * The two places this can happen are in FinishLeftRegions(), when
+ * we splice in a "temporary" edge produced by ConnectRightVertex(),
+ * and in CheckForLeftSplice(), where we splice already-processed
+ * edges to ensure that our dictionary invariants are not violated
+ * by numerical errors.
+ *
+ * In both these cases it is *very* dangerous to delete the offending
+ * edge at the time, since one of the routines further up the stack
+ * will sometimes be keeping a pointer to that edge.
+ */
+{
+ GLUface *f, *fNext;
+ GLUhalfEdge *e;
+
+ /*LINTED*/
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
+ fNext = f->next;
+ e = f->anEdge;
+ assert( e->Lnext != e );
+
+ if( e->Lnext->Lnext == e ) {
+ /* A face with only two edges */
+ AddWinding( e->Onext, e );
+ if ( !__gl_meshDelete( e ) ) return 0;
+ }
+ }
+ return 1;
+}
+
+int __gl_computeInterior( GLUtesselator *tess )
+/*
+ * __gl_computeInterior( tess ) computes the planar arrangement specified
+ * by the given contours, and further subdivides this arrangement
+ * into regions. Each region is marked "inside" if it belongs
+ * to the polygon, according to the rule given by tess->windingRule.
+ * Each interior region is guaranteed be monotone.
+ */
+{
+ GLUvertex *v, *vNext;
+
+ tess->fatalError = FALSE;
+
+ /* Each vertex defines an event for our sweep line. Start by inserting
+ * all the vertices in a priority queue. Events are processed in
+ * lexicographic order, ie.
+ *
+ * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y)
+ */
+ RemoveDegenerateEdges( tess );
+ if ( !InitPriorityQ( tess ) ) return 0; /* if error */
+ InitEdgeDict( tess );
+
+ /* __gl_pqSortExtractMin */
+ while( (v = (GLUvertex *)pqExtractMin( tess->pq )) != NULL ) {
+ for( ;; ) {
+ vNext = (GLUvertex *)pqMinimum( tess->pq ); /* __gl_pqSortMinimum */
+ if( vNext == NULL || ! VertEq( vNext, v )) break;
+
+ /* Merge together all vertices at exactly the same location.
+ * This is more efficient than processing them one at a time,
+ * simplifies the code (see ConnectLeftDegenerate), and is also
+ * important for correct handling of certain degenerate cases.
+ * For example, suppose there are two identical edges A and B
+ * that belong to different contours (so without this code they would
+ * be processed by separate sweep events). Suppose another edge C
+ * crosses A and B from above. When A is processed, we split it
+ * at its intersection point with C. However this also splits C,
+ * so when we insert B we may compute a slightly different
+ * intersection point. This might leave two edges with a small
+ * gap between them. This kind of error is especially obvious
+ * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY).
+ */
+ vNext = (GLUvertex *)pqExtractMin( tess->pq ); /* __gl_pqSortExtractMin*/
+ SpliceMergeVertices( tess, v->anEdge, vNext->anEdge );
+ }
+ SweepEvent( tess, v );
+ }
+
+ /* Set tess->event for debugging purposes */
+ /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
+ tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org;
+ DebugEvent( tess );
+ DoneEdgeDict( tess );
+ DonePriorityQ( tess );
+
+ if ( !RemoveDegenerateFaces( tess->mesh ) ) return 0;
+ __gl_meshCheckMesh( tess->mesh );
+
+ return 1;
+}
diff --git a/mesalib/src/glu/sgi/libtess/sweep.h b/mesalib/src/glu/sgi/libtess/sweep.h
new file mode 100644
index 000000000..feb68b0ff
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/sweep.h
@@ -0,0 +1,77 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __sweep_h_
+#define __sweep_h_
+
+#include "mesh.h"
+
+/* __gl_computeInterior( tess ) computes the planar arrangement specified
+ * by the given contours, and further subdivides this arrangement
+ * into regions. Each region is marked "inside" if it belongs
+ * to the polygon, according to the rule given by tess->windingRule.
+ * Each interior region is guaranteed be monotone.
+ */
+int __gl_computeInterior( GLUtesselator *tess );
+
+
+/* The following is here *only* for access by debugging routines */
+
+#include "dict.h"
+
+/* For each pair of adjacent edges crossing the sweep line, there is
+ * an ActiveRegion to represent the region between them. The active
+ * regions are kept in sorted order in a dynamic dictionary. As the
+ * sweep line crosses each vertex, we update the affected regions.
+ */
+
+struct ActiveRegion {
+ GLUhalfEdge *eUp; /* upper edge, directed right to left */
+ DictNode *nodeUp; /* dictionary node corresponding to eUp */
+ int windingNumber; /* used to determine which regions are
+ * inside the polygon */
+ GLboolean inside; /* is this region inside the polygon? */
+ GLboolean sentinel; /* marks fake edges at t = +/-infinity */
+ GLboolean dirty; /* marks regions where the upper or lower
+ * edge has changed, but we haven't checked
+ * whether they intersect yet */
+ GLboolean fixUpperEdge; /* marks temporary edges introduced when
+ * we process a "right vertex" (one without
+ * any edges leaving to the right) */
+};
+
+#define RegionBelow(r) ((ActiveRegion *) dictKey(dictPred((r)->nodeUp)))
+#define RegionAbove(r) ((ActiveRegion *) dictKey(dictSucc((r)->nodeUp)))
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/tess.c b/mesalib/src/glu/sgi/libtess/tess.c
new file mode 100644
index 000000000..029a02c3a
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/tess.c
@@ -0,0 +1,628 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <stddef.h>
+#include <assert.h>
+#include <setjmp.h>
+#include "memalloc.h"
+#include "tess.h"
+#include "mesh.h"
+#include "normal.h"
+#include "sweep.h"
+#include "tessmono.h"
+#include "render.h"
+
+#define GLU_TESS_DEFAULT_TOLERANCE 0.0
+#define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */
+
+#define TRUE 1
+#define FALSE 0
+
+/*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4],
+ GLfloat weight[4], void **dataOut ) {}
+/*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {}
+
+
+/*ARGSUSED*/ void GLAPIENTRY __gl_noBeginData( GLenum type,
+ void *polygonData ) {}
+/*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge,
+ void *polygonData ) {}
+/*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data,
+ void *polygonData ) {}
+/*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {}
+/*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum,
+ void *polygonData ) {}
+/*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3],
+ void *data[4],
+ GLfloat weight[4],
+ void **outData,
+ void *polygonData ) {}
+
+/* Half-edges are allocated in pairs (see mesh.c) */
+typedef struct { GLUhalfEdge e, eSym; } EdgePair;
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \
+ MAX(sizeof(GLUvertex),sizeof(GLUface))))
+
+
+GLUtesselator * GLAPIENTRY
+gluNewTess( void )
+{
+ GLUtesselator *tess;
+
+ /* Only initialize fields which can be changed by the api. Other fields
+ * are initialized where they are used.
+ */
+
+ if (memInit( MAX_FAST_ALLOC ) == 0) {
+ return 0; /* out of memory */
+ }
+ tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator ));
+ if (tess == NULL) {
+ return 0; /* out of memory */
+ }
+
+ tess->state = T_DORMANT;
+
+ tess->normal[0] = 0;
+ tess->normal[1] = 0;
+ tess->normal[2] = 0;
+
+ tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE;
+ tess->windingRule = GLU_TESS_WINDING_ODD;
+ tess->flagBoundary = FALSE;
+ tess->boundaryOnly = FALSE;
+
+ tess->callBegin = &noBegin;
+ tess->callEdgeFlag = &noEdgeFlag;
+ tess->callVertex = &noVertex;
+ tess->callEnd = &noEnd;
+
+ tess->callError = &noError;
+ tess->callCombine = &noCombine;
+ tess->callMesh = &noMesh;
+
+ tess->callBeginData= &__gl_noBeginData;
+ tess->callEdgeFlagData= &__gl_noEdgeFlagData;
+ tess->callVertexData= &__gl_noVertexData;
+ tess->callEndData= &__gl_noEndData;
+ tess->callErrorData= &__gl_noErrorData;
+ tess->callCombineData= &__gl_noCombineData;
+
+ tess->polygonData= NULL;
+
+ return tess;
+}
+
+static void MakeDormant( GLUtesselator *tess )
+{
+ /* Return the tessellator to its original dormant state. */
+
+ if( tess->mesh != NULL ) {
+ __gl_meshDeleteMesh( tess->mesh );
+ }
+ tess->state = T_DORMANT;
+ tess->lastEdge = NULL;
+ tess->mesh = NULL;
+}
+
+#define RequireState( tess, s ) if( tess->state != s ) GotoState(tess,s)
+
+static void GotoState( GLUtesselator *tess, enum TessState newState )
+{
+ while( tess->state != newState ) {
+ /* We change the current state one level at a time, to get to
+ * the desired state.
+ */
+ if( tess->state < newState ) {
+ switch( tess->state ) {
+ case T_DORMANT:
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON );
+ gluTessBeginPolygon( tess, NULL );
+ break;
+ case T_IN_POLYGON:
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR );
+ gluTessBeginContour( tess );
+ break;
+ default:
+ ;
+ }
+ } else {
+ switch( tess->state ) {
+ case T_IN_CONTOUR:
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR );
+ gluTessEndContour( tess );
+ break;
+ case T_IN_POLYGON:
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON );
+ /* gluTessEndPolygon( tess ) is too much work! */
+ MakeDormant( tess );
+ break;
+ default:
+ ;
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+gluDeleteTess( GLUtesselator *tess )
+{
+ RequireState( tess, T_DORMANT );
+ memFree( tess );
+}
+
+
+void GLAPIENTRY
+gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value )
+{
+ GLenum windingRule;
+
+ switch( which ) {
+ case GLU_TESS_TOLERANCE:
+ if( value < 0.0 || value > 1.0 ) break;
+ tess->relTolerance = value;
+ return;
+
+ case GLU_TESS_WINDING_RULE:
+ windingRule = (GLenum) value;
+ if( windingRule != value ) break; /* not an integer */
+
+ switch( windingRule ) {
+ case GLU_TESS_WINDING_ODD:
+ case GLU_TESS_WINDING_NONZERO:
+ case GLU_TESS_WINDING_POSITIVE:
+ case GLU_TESS_WINDING_NEGATIVE:
+ case GLU_TESS_WINDING_ABS_GEQ_TWO:
+ tess->windingRule = windingRule;
+ return;
+ default:
+ break;
+ }
+
+ case GLU_TESS_BOUNDARY_ONLY:
+ tess->boundaryOnly = (value != 0);
+ return;
+
+ default:
+ CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
+ return;
+ }
+ CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE );
+}
+
+/* Returns tessellator property */
+void GLAPIENTRY
+gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value )
+{
+ switch (which) {
+ case GLU_TESS_TOLERANCE:
+ /* tolerance should be in range [0..1] */
+ assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0);
+ *value= tess->relTolerance;
+ break;
+ case GLU_TESS_WINDING_RULE:
+ assert(tess->windingRule == GLU_TESS_WINDING_ODD ||
+ tess->windingRule == GLU_TESS_WINDING_NONZERO ||
+ tess->windingRule == GLU_TESS_WINDING_POSITIVE ||
+ tess->windingRule == GLU_TESS_WINDING_NEGATIVE ||
+ tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO);
+ *value= tess->windingRule;
+ break;
+ case GLU_TESS_BOUNDARY_ONLY:
+ assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE);
+ *value= tess->boundaryOnly;
+ break;
+ default:
+ *value= 0.0;
+ CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
+ break;
+ }
+} /* gluGetTessProperty() */
+
+void GLAPIENTRY
+gluTessNormal( GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z )
+{
+ tess->normal[0] = x;
+ tess->normal[1] = y;
+ tess->normal[2] = z;
+}
+
+void GLAPIENTRY
+gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn)
+{
+ switch( which ) {
+ case GLU_TESS_BEGIN:
+ tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn;
+ return;
+ case GLU_TESS_BEGIN_DATA:
+ tess->callBeginData = (fn == NULL) ?
+ &__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
+ return;
+ case GLU_TESS_EDGE_FLAG:
+ tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag :
+ (void (GLAPIENTRY *)(GLboolean)) fn;
+ /* If the client wants boundary edges to be flagged,
+ * we render everything as separate triangles (no strips or fans).
+ */
+ tess->flagBoundary = (fn != NULL);
+ return;
+ case GLU_TESS_EDGE_FLAG_DATA:
+ tess->callEdgeFlagData= (fn == NULL) ?
+ &__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn;
+ /* If the client wants boundary edges to be flagged,
+ * we render everything as separate triangles (no strips or fans).
+ */
+ tess->flagBoundary = (fn != NULL);
+ return;
+ case GLU_TESS_VERTEX:
+ tess->callVertex = (fn == NULL) ? &noVertex :
+ (void (GLAPIENTRY *)(void *)) fn;
+ return;
+ case GLU_TESS_VERTEX_DATA:
+ tess->callVertexData = (fn == NULL) ?
+ &__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn;
+ return;
+ case GLU_TESS_END:
+ tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn;
+ return;
+ case GLU_TESS_END_DATA:
+ tess->callEndData = (fn == NULL) ? &__gl_noEndData :
+ (void (GLAPIENTRY *)(void *)) fn;
+ return;
+ case GLU_TESS_ERROR:
+ tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn;
+ return;
+ case GLU_TESS_ERROR_DATA:
+ tess->callErrorData = (fn == NULL) ?
+ &__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
+ return;
+ case GLU_TESS_COMBINE:
+ tess->callCombine = (fn == NULL) ? &noCombine :
+ (void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn;
+ return;
+ case GLU_TESS_COMBINE_DATA:
+ tess->callCombineData = (fn == NULL) ? &__gl_noCombineData :
+ (void (GLAPIENTRY *)(GLdouble [3],
+ void *[4],
+ GLfloat [4],
+ void **,
+ void *)) fn;
+ return;
+ case GLU_TESS_MESH:
+ tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn;
+ return;
+ default:
+ CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
+ return;
+ }
+}
+
+static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
+{
+ GLUhalfEdge *e;
+
+ e = tess->lastEdge;
+ if( e == NULL ) {
+ /* Make a self-loop (one vertex, one edge). */
+
+ e = __gl_meshMakeEdge( tess->mesh );
+ if (e == NULL) return 0;
+ if ( !__gl_meshSplice( e, e->Sym ) ) return 0;
+ } else {
+ /* Create a new vertex and edge which immediately follow e
+ * in the ordering around the left face.
+ */
+ if (__gl_meshSplitEdge( e ) == NULL) return 0;
+ e = e->Lnext;
+ }
+
+ /* The new vertex is now e->Org. */
+ e->Org->data = data;
+ e->Org->coords[0] = coords[0];
+ e->Org->coords[1] = coords[1];
+ e->Org->coords[2] = coords[2];
+
+ /* The winding of an edge says how the winding number changes as we
+ * cross from the edge''s right face to its left face. We add the
+ * vertices in such an order that a CCW contour will add +1 to
+ * the winding number of the region inside the contour.
+ */
+ e->winding = 1;
+ e->Sym->winding = -1;
+
+ tess->lastEdge = e;
+
+ return 1;
+}
+
+
+static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
+{
+ CachedVertex *v = &tess->cache[tess->cacheCount];
+
+ v->data = data;
+ v->coords[0] = coords[0];
+ v->coords[1] = coords[1];
+ v->coords[2] = coords[2];
+ ++tess->cacheCount;
+}
+
+
+static int EmptyCache( GLUtesselator *tess )
+{
+ CachedVertex *v = tess->cache;
+ CachedVertex *vLast;
+
+ tess->mesh = __gl_meshNewMesh();
+ if (tess->mesh == NULL) return 0;
+
+ for( vLast = v + tess->cacheCount; v < vLast; ++v ) {
+ if ( !AddVertex( tess, v->coords, v->data ) ) return 0;
+ }
+ tess->cacheCount = 0;
+ tess->emptyCache = FALSE;
+
+ return 1;
+}
+
+
+void GLAPIENTRY
+gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
+{
+ int i, tooLarge = FALSE;
+ GLdouble x, clamped[3];
+
+ RequireState( tess, T_IN_CONTOUR );
+
+ if( tess->emptyCache ) {
+ if ( !EmptyCache( tess ) ) {
+ CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
+ return;
+ }
+ tess->lastEdge = NULL;
+ }
+ for( i = 0; i < 3; ++i ) {
+ x = coords[i];
+ if( x < - GLU_TESS_MAX_COORD ) {
+ x = - GLU_TESS_MAX_COORD;
+ tooLarge = TRUE;
+ }
+ if( x > GLU_TESS_MAX_COORD ) {
+ x = GLU_TESS_MAX_COORD;
+ tooLarge = TRUE;
+ }
+ clamped[i] = x;
+ }
+ if( tooLarge ) {
+ CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE );
+ }
+
+ if( tess->mesh == NULL ) {
+ if( tess->cacheCount < TESS_MAX_CACHE ) {
+ CacheVertex( tess, clamped, data );
+ return;
+ }
+ if ( !EmptyCache( tess ) ) {
+ CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
+ return;
+ }
+ }
+ if ( !AddVertex( tess, clamped, data ) ) {
+ CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
+ }
+}
+
+
+void GLAPIENTRY
+gluTessBeginPolygon( GLUtesselator *tess, void *data )
+{
+ RequireState( tess, T_DORMANT );
+
+ tess->state = T_IN_POLYGON;
+ tess->cacheCount = 0;
+ tess->emptyCache = FALSE;
+ tess->mesh = NULL;
+
+ tess->polygonData= data;
+}
+
+
+void GLAPIENTRY
+gluTessBeginContour( GLUtesselator *tess )
+{
+ RequireState( tess, T_IN_POLYGON );
+
+ tess->state = T_IN_CONTOUR;
+ tess->lastEdge = NULL;
+ if( tess->cacheCount > 0 ) {
+ /* Just set a flag so we don't get confused by empty contours
+ * -- these can be generated accidentally with the obsolete
+ * NextContour() interface.
+ */
+ tess->emptyCache = TRUE;
+ }
+}
+
+
+void GLAPIENTRY
+gluTessEndContour( GLUtesselator *tess )
+{
+ RequireState( tess, T_IN_CONTOUR );
+ tess->state = T_IN_POLYGON;
+}
+
+void GLAPIENTRY
+gluTessEndPolygon( GLUtesselator *tess )
+{
+ GLUmesh *mesh;
+
+ if (setjmp(tess->env) != 0) {
+ /* come back here if out of memory */
+ CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
+ return;
+ }
+
+ RequireState( tess, T_IN_POLYGON );
+ tess->state = T_DORMANT;
+
+ if( tess->mesh == NULL ) {
+ if( ! tess->flagBoundary && tess->callMesh == &noMesh ) {
+
+ /* Try some special code to make the easy cases go quickly
+ * (eg. convex polygons). This code does NOT handle multiple contours,
+ * intersections, edge flags, and of course it does not generate
+ * an explicit mesh either.
+ */
+ if( __gl_renderCache( tess )) {
+ tess->polygonData= NULL;
+ return;
+ }
+ }
+ if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/
+ }
+
+ /* Determine the polygon normal and project vertices onto the plane
+ * of the polygon.
+ */
+ __gl_projectPolygon( tess );
+
+ /* __gl_computeInterior( tess ) computes the planar arrangement specified
+ * by the given contours, and further subdivides this arrangement
+ * into regions. Each region is marked "inside" if it belongs
+ * to the polygon, according to the rule given by tess->windingRule.
+ * Each interior region is guaranteed be monotone.
+ */
+ if ( !__gl_computeInterior( tess ) ) {
+ longjmp(tess->env,1); /* could've used a label */
+ }
+
+ mesh = tess->mesh;
+ if( ! tess->fatalError ) {
+ int rc = 1;
+
+ /* If the user wants only the boundary contours, we throw away all edges
+ * except those which separate the interior from the exterior.
+ * Otherwise we tessellate all the regions marked "inside".
+ */
+ if( tess->boundaryOnly ) {
+ rc = __gl_meshSetWindingNumber( mesh, 1, TRUE );
+ } else {
+ rc = __gl_meshTessellateInterior( mesh );
+ }
+ if (rc == 0) longjmp(tess->env,1); /* could've used a label */
+
+ __gl_meshCheckMesh( mesh );
+
+ if( tess->callBegin != &noBegin || tess->callEnd != &noEnd
+ || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag
+ || tess->callBeginData != &__gl_noBeginData
+ || tess->callEndData != &__gl_noEndData
+ || tess->callVertexData != &__gl_noVertexData
+ || tess->callEdgeFlagData != &__gl_noEdgeFlagData )
+ {
+ if( tess->boundaryOnly ) {
+ __gl_renderBoundary( tess, mesh ); /* output boundary contours */
+ } else {
+ __gl_renderMesh( tess, mesh ); /* output strips and fans */
+ }
+ }
+ if( tess->callMesh != &noMesh ) {
+
+ /* Throw away the exterior faces, so that all faces are interior.
+ * This way the user doesn't have to check the "inside" flag,
+ * and we don't need to even reveal its existence. It also leaves
+ * the freedom for an implementation to not generate the exterior
+ * faces in the first place.
+ */
+ __gl_meshDiscardExterior( mesh );
+ (*tess->callMesh)( mesh ); /* user wants the mesh itself */
+ tess->mesh = NULL;
+ tess->polygonData= NULL;
+ return;
+ }
+ }
+ __gl_meshDeleteMesh( mesh );
+ tess->polygonData= NULL;
+ tess->mesh = NULL;
+}
+
+
+/*XXXblythe unused function*/
+#if 0
+void GLAPIENTRY
+gluDeleteMesh( GLUmesh *mesh )
+{
+ __gl_meshDeleteMesh( mesh );
+}
+#endif
+
+
+
+/*******************************************************/
+
+/* Obsolete calls -- for backward compatibility */
+
+void GLAPIENTRY
+gluBeginPolygon( GLUtesselator *tess )
+{
+ gluTessBeginPolygon( tess, NULL );
+ gluTessBeginContour( tess );
+}
+
+
+/*ARGSUSED*/
+void GLAPIENTRY
+gluNextContour( GLUtesselator *tess, GLenum type )
+{
+ gluTessEndContour( tess );
+ gluTessBeginContour( tess );
+}
+
+
+void GLAPIENTRY
+gluEndPolygon( GLUtesselator *tess )
+{
+ gluTessEndContour( tess );
+ gluTessEndPolygon( tess );
+}
diff --git a/mesalib/src/glu/sgi/libtess/tess.h b/mesalib/src/glu/sgi/libtess/tess.h
new file mode 100644
index 000000000..162496088
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/tess.h
@@ -0,0 +1,165 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __tess_h_
+#define __tess_h_
+
+#include <GL/glu.h>
+#include <setjmp.h>
+#include "mesh.h"
+#include "dict.h"
+#include "priorityq.h"
+
+/* The begin/end calls must be properly nested. We keep track of
+ * the current state to enforce the ordering.
+ */
+enum TessState { T_DORMANT, T_IN_POLYGON, T_IN_CONTOUR };
+
+/* We cache vertex data for single-contour polygons so that we can
+ * try a quick-and-dirty decomposition first.
+ */
+#define TESS_MAX_CACHE 100
+
+typedef struct CachedVertex {
+ GLdouble coords[3];
+ void *data;
+} CachedVertex;
+
+struct GLUtesselator {
+
+ /*** state needed for collecting the input data ***/
+
+ enum TessState state; /* what begin/end calls have we seen? */
+
+ GLUhalfEdge *lastEdge; /* lastEdge->Org is the most recent vertex */
+ GLUmesh *mesh; /* stores the input contours, and eventually
+ the tessellation itself */
+
+ void (GLAPIENTRY *callError)( GLenum errnum );
+
+ /*** state needed for projecting onto the sweep plane ***/
+
+ GLdouble normal[3]; /* user-specified normal (if provided) */
+ GLdouble sUnit[3]; /* unit vector in s-direction (debugging) */
+ GLdouble tUnit[3]; /* unit vector in t-direction (debugging) */
+
+ /*** state needed for the line sweep ***/
+
+ GLdouble relTolerance; /* tolerance for merging features */
+ GLenum windingRule; /* rule for determining polygon interior */
+ GLboolean fatalError; /* fatal error: needed combine callback */
+
+ Dict *dict; /* edge dictionary for sweep line */
+ PriorityQ *pq; /* priority queue of vertex events */
+ GLUvertex *event; /* current sweep event being processed */
+
+ void (GLAPIENTRY *callCombine)( GLdouble coords[3], void *data[4],
+ GLfloat weight[4], void **outData );
+
+ /*** state needed for rendering callbacks (see render.c) ***/
+
+ GLboolean flagBoundary; /* mark boundary edges (use EdgeFlag) */
+ GLboolean boundaryOnly; /* Extract contours, not triangles */
+ GLUface *lonelyTriList;
+ /* list of triangles which could not be rendered as strips or fans */
+
+ void (GLAPIENTRY *callBegin)( GLenum type );
+ void (GLAPIENTRY *callEdgeFlag)( GLboolean boundaryEdge );
+ void (GLAPIENTRY *callVertex)( void *data );
+ void (GLAPIENTRY *callEnd)( void );
+ void (GLAPIENTRY *callMesh)( GLUmesh *mesh );
+
+
+ /*** state needed to cache single-contour polygons for renderCache() */
+
+ GLboolean emptyCache; /* empty cache on next vertex() call */
+ int cacheCount; /* number of cached vertices */
+ CachedVertex cache[TESS_MAX_CACHE]; /* the vertex data */
+
+ /*** rendering callbacks that also pass polygon data ***/
+ void (GLAPIENTRY *callBeginData)( GLenum type, void *polygonData );
+ void (GLAPIENTRY *callEdgeFlagData)( GLboolean boundaryEdge,
+ void *polygonData );
+ void (GLAPIENTRY *callVertexData)( void *data, void *polygonData );
+ void (GLAPIENTRY *callEndData)( void *polygonData );
+ void (GLAPIENTRY *callErrorData)( GLenum errnum, void *polygonData );
+ void (GLAPIENTRY *callCombineData)( GLdouble coords[3], void *data[4],
+ GLfloat weight[4], void **outData,
+ void *polygonData );
+
+ jmp_buf env; /* place to jump to when memAllocs fail */
+
+ void *polygonData; /* client data for current polygon */
+};
+
+void GLAPIENTRY __gl_noBeginData( GLenum type, void *polygonData );
+void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, void *polygonData );
+void GLAPIENTRY __gl_noVertexData( void *data, void *polygonData );
+void GLAPIENTRY __gl_noEndData( void *polygonData );
+void GLAPIENTRY __gl_noErrorData( GLenum errnum, void *polygonData );
+void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], void *data[4],
+ GLfloat weight[4], void **outData,
+ void *polygonData );
+
+#define CALL_BEGIN_OR_BEGIN_DATA(a) \
+ if (tess->callBeginData != &__gl_noBeginData) \
+ (*tess->callBeginData)((a),tess->polygonData); \
+ else (*tess->callBegin)((a));
+
+#define CALL_VERTEX_OR_VERTEX_DATA(a) \
+ if (tess->callVertexData != &__gl_noVertexData) \
+ (*tess->callVertexData)((a),tess->polygonData); \
+ else (*tess->callVertex)((a));
+
+#define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a) \
+ if (tess->callEdgeFlagData != &__gl_noEdgeFlagData) \
+ (*tess->callEdgeFlagData)((a),tess->polygonData); \
+ else (*tess->callEdgeFlag)((a));
+
+#define CALL_END_OR_END_DATA() \
+ if (tess->callEndData != &__gl_noEndData) \
+ (*tess->callEndData)(tess->polygonData); \
+ else (*tess->callEnd)();
+
+#define CALL_COMBINE_OR_COMBINE_DATA(a,b,c,d) \
+ if (tess->callCombineData != &__gl_noCombineData) \
+ (*tess->callCombineData)((a),(b),(c),(d),tess->polygonData); \
+ else (*tess->callCombine)((a),(b),(c),(d));
+
+#define CALL_ERROR_OR_ERROR_DATA(a) \
+ if (tess->callErrorData != &__gl_noErrorData) \
+ (*tess->callErrorData)((a),tess->polygonData); \
+ else (*tess->callError)((a));
+
+#endif
diff --git a/mesalib/src/glu/sgi/libtess/tessmono.c b/mesalib/src/glu/sgi/libtess/tessmono.c
new file mode 100644
index 000000000..4d0844005
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/tessmono.c
@@ -0,0 +1,201 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#include "gluos.h"
+#include <stdlib.h>
+#include "geom.h"
+#include "mesh.h"
+#include "tessmono.h"
+#include <assert.h>
+
+#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \
+ eDst->Sym->winding += eSrc->Sym->winding)
+
+/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
+ * (what else would it do??) The region must consist of a single
+ * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
+ * case means that any vertical line intersects the interior of the
+ * region in a single interval.
+ *
+ * Tessellation consists of adding interior edges (actually pairs of
+ * half-edges), to split the region into non-overlapping triangles.
+ *
+ * The basic idea is explained in Preparata and Shamos (which I don''t
+ * have handy right now), although their implementation is more
+ * complicated than this one. The are two edge chains, an upper chain
+ * and a lower chain. We process all vertices from both chains in order,
+ * from right to left.
+ *
+ * The algorithm ensures that the following invariant holds after each
+ * vertex is processed: the untessellated region consists of two
+ * chains, where one chain (say the upper) is a single edge, and
+ * the other chain is concave. The left vertex of the single edge
+ * is always to the left of all vertices in the concave chain.
+ *
+ * Each step consists of adding the rightmost unprocessed vertex to one
+ * of the two chains, and forming a fan of triangles from the rightmost
+ * of two chain endpoints. Determining whether we can add each triangle
+ * to the fan is a simple orientation test. By making the fan as large
+ * as possible, we restore the invariant (check it yourself).
+ */
+int __gl_meshTessellateMonoRegion( GLUface *face )
+{
+ GLUhalfEdge *up, *lo;
+
+ /* All edges are oriented CCW around the boundary of the region.
+ * First, find the half-edge whose origin vertex is rightmost.
+ * Since the sweep goes from left to right, face->anEdge should
+ * be close to the edge we want.
+ */
+ up = face->anEdge;
+ assert( up->Lnext != up && up->Lnext->Lnext != up );
+
+ for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev )
+ ;
+ for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext )
+ ;
+ lo = up->Lprev;
+
+ while( up->Lnext != lo ) {
+ if( VertLeq( up->Dst, lo->Org )) {
+ /* up->Dst is on the left. It is safe to form triangles from lo->Org.
+ * The EdgeGoesLeft test guarantees progress even when some triangles
+ * are CW, given that the upper and lower chains are truly monotone.
+ */
+ while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext )
+ || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) {
+ GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
+ if (tempHalfEdge == NULL) return 0;
+ lo = tempHalfEdge->Sym;
+ }
+ lo = lo->Lprev;
+ } else {
+ /* lo->Org is on the left. We can make CCW triangles from up->Dst. */
+ while( lo->Lnext != up && (EdgeGoesRight( up->Lprev )
+ || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) {
+ GLUhalfEdge *tempHalfEdge= __gl_meshConnect( up, up->Lprev );
+ if (tempHalfEdge == NULL) return 0;
+ up = tempHalfEdge->Sym;
+ }
+ up = up->Lnext;
+ }
+ }
+
+ /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region
+ * can be tessellated in a fan from this leftmost vertex.
+ */
+ assert( lo->Lnext != up );
+ while( lo->Lnext->Lnext != up ) {
+ GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
+ if (tempHalfEdge == NULL) return 0;
+ lo = tempHalfEdge->Sym;
+ }
+
+ return 1;
+}
+
+
+/* __gl_meshTessellateInterior( mesh ) tessellates each region of
+ * the mesh which is marked "inside" the polygon. Each such region
+ * must be monotone.
+ */
+int __gl_meshTessellateInterior( GLUmesh *mesh )
+{
+ GLUface *f, *next;
+
+ /*LINTED*/
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
+ /* Make sure we don''t try to tessellate the new triangles. */
+ next = f->next;
+ if( f->inside ) {
+ if ( !__gl_meshTessellateMonoRegion( f ) ) return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
+ * which are not marked "inside" the polygon. Since further mesh operations
+ * on NULL faces are not allowed, the main purpose is to clean up the
+ * mesh so that exterior loops are not represented in the data structure.
+ */
+void __gl_meshDiscardExterior( GLUmesh *mesh )
+{
+ GLUface *f, *next;
+
+ /*LINTED*/
+ for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
+ /* Since f will be destroyed, save its next pointer. */
+ next = f->next;
+ if( ! f->inside ) {
+ __gl_meshZapFace( f );
+ }
+ }
+}
+
+#define MARKED_FOR_DELETION 0x7fffffff
+
+/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
+ * winding numbers on all edges so that regions marked "inside" the
+ * polygon have a winding number of "value", and regions outside
+ * have a winding number of 0.
+ *
+ * If keepOnlyBoundary is TRUE, it also deletes all edges which do not
+ * separate an interior region from an exterior one.
+ */
+int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
+ GLboolean keepOnlyBoundary )
+{
+ GLUhalfEdge *e, *eNext;
+
+ for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
+ eNext = e->next;
+ if( e->Rface->inside != e->Lface->inside ) {
+
+ /* This is a boundary edge (one side is interior, one is exterior). */
+ e->winding = (e->Lface->inside) ? value : -value;
+ } else {
+
+ /* Both regions are interior, or both are exterior. */
+ if( ! keepOnlyBoundary ) {
+ e->winding = 0;
+ } else {
+ if ( !__gl_meshDelete( e ) ) return 0;
+ }
+ }
+ }
+ return 1;
+}
diff --git a/mesalib/src/glu/sgi/libtess/tessmono.h b/mesalib/src/glu/sgi/libtess/tessmono.h
new file mode 100644
index 000000000..8ee1b2fe3
--- /dev/null
+++ b/mesalib/src/glu/sgi/libtess/tessmono.h
@@ -0,0 +1,71 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+/*
+** Author: Eric Veach, July 1994.
+**
+*/
+
+#ifndef __tessmono_h_
+#define __tessmono_h_
+
+/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
+ * (what else would it do??) The region must consist of a single
+ * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
+ * case means that any vertical line intersects the interior of the
+ * region in a single interval.
+ *
+ * Tessellation consists of adding interior edges (actually pairs of
+ * half-edges), to split the region into non-overlapping triangles.
+ *
+ * __gl_meshTessellateInterior( mesh ) tessellates each region of
+ * the mesh which is marked "inside" the polygon. Each such region
+ * must be monotone.
+ *
+ * __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
+ * which are not marked "inside" the polygon. Since further mesh operations
+ * on NULL faces are not allowed, the main purpose is to clean up the
+ * mesh so that exterior loops are not represented in the data structure.
+ *
+ * __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
+ * winding numbers on all edges so that regions marked "inside" the
+ * polygon have a winding number of "value", and regions outside
+ * have a winding number of 0.
+ *
+ * If keepOnlyBoundary is TRUE, it also deletes all edges which do not
+ * separate an interior region from an exterior one.
+ */
+
+int __gl_meshTessellateMonoRegion( GLUface *face );
+int __gl_meshTessellateInterior( GLUmesh *mesh );
+void __gl_meshDiscardExterior( GLUmesh *mesh );
+int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
+ GLboolean keepOnlyBoundary );
+
+#endif
diff --git a/mesalib/src/glu/sgi/libutil/error.c b/mesalib/src/glu/sgi/libutil/error.c
new file mode 100644
index 000000000..e734818ed
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/error.c
@@ -0,0 +1,83 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "gluos.h"
+#include "gluint.h"
+#include <GL/glu.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+struct token_string
+{
+ GLuint Token;
+ const char *String;
+};
+
+static const struct token_string Errors[] = {
+ { GL_NO_ERROR, "no error" },
+ { GL_INVALID_ENUM, "invalid enumerant" },
+ { GL_INVALID_VALUE, "invalid value" },
+ { GL_INVALID_OPERATION, "invalid operation" },
+ { GL_STACK_OVERFLOW, "stack overflow" },
+ { GL_STACK_UNDERFLOW, "stack underflow" },
+ { GL_OUT_OF_MEMORY, "out of memory" },
+ { GL_TABLE_TOO_LARGE, "table too large" },
+#ifdef GL_EXT_framebuffer_object
+ { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
+#endif
+ /* GLU */
+ { GLU_INVALID_ENUM, "invalid enumerant" },
+ { GLU_INVALID_VALUE, "invalid value" },
+ { GLU_OUT_OF_MEMORY, "out of memory" },
+ { GLU_INCOMPATIBLE_GL_VERSION, "incompatible gl version" },
+ { GLU_INVALID_OPERATION, "invalid operation" },
+ { ~0, NULL } /* end of list indicator */
+};
+
+
+
+const GLubyte* GLAPIENTRY
+gluErrorString(GLenum errorCode)
+{
+ int i;
+ for (i = 0; Errors[i].String; i++) {
+ if (Errors[i].Token == errorCode)
+ return (const GLubyte *) Errors[i].String;
+ }
+ if ((errorCode >= GLU_NURBS_ERROR1) && (errorCode <= GLU_NURBS_ERROR37)) {
+ return (const GLubyte *) __gluNURBSErrorString(errorCode - (GLU_NURBS_ERROR1 - 1));
+ }
+ if ((errorCode >= GLU_TESS_ERROR1) && (errorCode <= GLU_TESS_ERROR6)) {
+ return (const GLubyte *) __gluTessErrorString(errorCode - (GLU_TESS_ERROR1 - 1));
+ }
+ return (const GLubyte *) 0;
+}
+
diff --git a/mesalib/src/glu/sgi/libutil/glue.c b/mesalib/src/glu/sgi/libutil/glue.c
new file mode 100644
index 000000000..cd65d65ad
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/glue.c
@@ -0,0 +1,93 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include <stdlib.h>
+#include "gluint.h"
+
+static unsigned char *__gluNurbsErrors[] = {
+ (unsigned char*) " ",
+ (unsigned char*) "spline order un-supported",
+ (unsigned char*) "too few knots",
+ (unsigned char*) "valid knot range is empty",
+ (unsigned char*) "decreasing knot sequence knot",
+ (unsigned char*) "knot multiplicity greater than order of spline",
+ (unsigned char*) "gluEndCurve() must follow gluBeginCurve()",
+ (unsigned char*) "gluBeginCurve() must precede gluEndCurve()",
+ (unsigned char*) "missing or extra geometric data",
+ (unsigned char*) "can't draw piecewise linear trimming curves",
+ (unsigned char*) "missing or extra domain data",
+ (unsigned char*) "missing or extra domain data",
+ (unsigned char*) "gluEndTrim() must precede gluEndSurface()",
+ (unsigned char*) "gluBeginSurface() must precede gluEndSurface()",
+ (unsigned char*) "curve of improper type passed as trim curve",
+ (unsigned char*) "gluBeginSurface() must precede gluBeginTrim()",
+ (unsigned char*) "gluEndTrim() must follow gluBeginTrim()",
+ (unsigned char*) "gluBeginTrim() must precede gluEndTrim()",
+ (unsigned char*) "invalid or missing trim curve",
+ (unsigned char*) "gluBeginTrim() must precede gluPwlCurve()",
+ (unsigned char*) "piecewise linear trimming curve referenced twice",
+ (unsigned char*) "piecewise linear trimming curve and nurbs curve mixed",
+ (unsigned char*) "improper usage of trim data type",
+ (unsigned char*) "nurbs curve referenced twice",
+ (unsigned char*) "nurbs curve and piecewise linear trimming curve mixed",
+ (unsigned char*) "nurbs surface referenced twice",
+ (unsigned char*) "invalid property",
+ (unsigned char*) "gluEndSurface() must follow gluBeginSurface()",
+ (unsigned char*) "intersecting or misoriented trim curves",
+ (unsigned char*) "intersecting trim curves",
+ (unsigned char*) "UNUSED",
+ (unsigned char*) "unconnected trim curves",
+ (unsigned char*) "unknown knot error",
+ (unsigned char*) "negative vertex count encountered",
+ (unsigned char*) "negative byte-stride encounteed",
+ (unsigned char*) "unknown type descriptor",
+ (unsigned char*) "null control point reference",
+ (unsigned char*) "duplicate point on piecewise linear trimming curve",
+};
+
+const unsigned char *__gluNURBSErrorString( int errnum )
+{
+ return __gluNurbsErrors[errnum];
+}
+
+static unsigned char *__gluTessErrors[] = {
+ (unsigned char*) " ",
+ (unsigned char*) "gluTessBeginPolygon() must precede a gluTessEndPolygon()",
+ (unsigned char*) "gluTessBeginContour() must precede a gluTessEndContour()",
+ (unsigned char*) "gluTessEndPolygon() must follow a gluTessBeginPolygon()",
+ (unsigned char*) "gluTessEndContour() must follow a gluTessBeginContour()",
+ (unsigned char*) "a coordinate is too large",
+ (unsigned char*) "need combine callback",
+};
+
+const unsigned char *__gluTessErrorString( int errnum )
+{
+ return __gluTessErrors[errnum];
+} /* __glTessErrorString() */
diff --git a/mesalib/src/glu/sgi/libutil/gluint.h b/mesalib/src/glu/sgi/libutil/gluint.h
new file mode 100644
index 000000000..fd513caa6
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/gluint.h
@@ -0,0 +1,48 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifndef __gluint_h__
+#define __gluint_h__
+
+extern const unsigned char *__gluNURBSErrorString( int errnum );
+
+extern const unsigned char *__gluTessErrorString( int errnum );
+
+#ifdef _EXTENSIONS_
+#define COS cosf
+#define SIN sinf
+#define SQRT sqrtf
+#else
+#define COS cos
+#define SIN sin
+#define SQRT sqrt
+#endif
+
+#endif /* __gluint_h__ */
diff --git a/mesalib/src/glu/sgi/libutil/mipmap.c b/mesalib/src/glu/sgi/libutil/mipmap.c
new file mode 100644
index 000000000..af647af73
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/mipmap.c
@@ -0,0 +1,8931 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "gluos.h"
+#include <assert.h>
+#include <GL/glu.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h> /* UINT_MAX */
+#include <math.h>
+#include "gluint.h"
+
+typedef union {
+ unsigned char ub[4];
+ unsigned short us[2];
+ unsigned int ui;
+ char b[4];
+ short s[2];
+ int i;
+ float f;
+} Type_Widget;
+
+/* Pixel storage modes */
+typedef struct {
+ GLint pack_alignment;
+ GLint pack_row_length;
+ GLint pack_skip_rows;
+ GLint pack_skip_pixels;
+ GLint pack_lsb_first;
+ GLint pack_swap_bytes;
+ GLint pack_skip_images;
+ GLint pack_image_height;
+
+ GLint unpack_alignment;
+ GLint unpack_row_length;
+ GLint unpack_skip_rows;
+ GLint unpack_skip_pixels;
+ GLint unpack_lsb_first;
+ GLint unpack_swap_bytes;
+ GLint unpack_skip_images;
+ GLint unpack_image_height;
+} PixelStorageModes;
+
+static int gluBuild1DMipmapLevelsCore(GLenum, GLint,
+ GLsizei,
+ GLsizei,
+ GLenum, GLenum, GLint, GLint, GLint,
+ const void *);
+static int gluBuild2DMipmapLevelsCore(GLenum, GLint,
+ GLsizei, GLsizei,
+ GLsizei, GLsizei,
+ GLenum, GLenum, GLint, GLint, GLint,
+ const void *);
+static int gluBuild3DMipmapLevelsCore(GLenum, GLint,
+ GLsizei, GLsizei, GLsizei,
+ GLsizei, GLsizei, GLsizei,
+ GLenum, GLenum, GLint, GLint, GLint,
+ const void *);
+
+/*
+ * internal function declarations
+ */
+static GLfloat bytes_per_element(GLenum type);
+static GLint elements_per_group(GLenum format, GLenum type);
+static GLint is_index(GLenum format);
+static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
+static void fill_image(const PixelStorageModes *,
+ GLint width, GLint height, GLenum format,
+ GLenum type, GLboolean index_format,
+ const void *userdata, GLushort *newimage);
+static void empty_image(const PixelStorageModes *,
+ GLint width, GLint height, GLenum format,
+ GLenum type, GLboolean index_format,
+ const GLushort *oldimage, void *userdata);
+static void scale_internal(GLint components, GLint widthin, GLint heightin,
+ const GLushort *datain,
+ GLint widthout, GLint heightout,
+ GLushort *dataout);
+
+static void scale_internal_ubyte(GLint components, GLint widthin,
+ GLint heightin, const GLubyte *datain,
+ GLint widthout, GLint heightout,
+ GLubyte *dataout, GLint element_size,
+ GLint ysize, GLint group_size);
+static void scale_internal_byte(GLint components, GLint widthin,
+ GLint heightin, const GLbyte *datain,
+ GLint widthout, GLint heightout,
+ GLbyte *dataout, GLint element_size,
+ GLint ysize, GLint group_size);
+static void scale_internal_ushort(GLint components, GLint widthin,
+ GLint heightin, const GLushort *datain,
+ GLint widthout, GLint heightout,
+ GLushort *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes);
+static void scale_internal_short(GLint components, GLint widthin,
+ GLint heightin, const GLshort *datain,
+ GLint widthout, GLint heightout,
+ GLshort *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes);
+static void scale_internal_uint(GLint components, GLint widthin,
+ GLint heightin, const GLuint *datain,
+ GLint widthout, GLint heightout,
+ GLuint *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes);
+static void scale_internal_int(GLint components, GLint widthin,
+ GLint heightin, const GLint *datain,
+ GLint widthout, GLint heightout,
+ GLint *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes);
+static void scale_internal_float(GLint components, GLint widthin,
+ GLint heightin, const GLfloat *datain,
+ GLint widthout, GLint heightout,
+ GLfloat *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes);
+
+static int checkMipmapArgs(GLenum, GLenum, GLenum);
+static GLboolean legalFormat(GLenum);
+static GLboolean legalType(GLenum);
+static GLboolean isTypePackedPixel(GLenum);
+static GLboolean isLegalFormatForPackedPixelType(GLenum, GLenum);
+static GLboolean isLegalLevels(GLint, GLint, GLint, GLint);
+static void closestFit(GLenum, GLint, GLint, GLint, GLenum, GLenum,
+ GLint *, GLint *);
+
+/* all extract/shove routines must return double to handle unsigned ints */
+static GLdouble extractUbyte(int, const void *);
+static void shoveUbyte(GLdouble, int, void *);
+static GLdouble extractSbyte(int, const void *);
+static void shoveSbyte(GLdouble, int, void *);
+static GLdouble extractUshort(int, const void *);
+static void shoveUshort(GLdouble, int, void *);
+static GLdouble extractSshort(int, const void *);
+static void shoveSshort(GLdouble, int, void *);
+static GLdouble extractUint(int, const void *);
+static void shoveUint(GLdouble, int, void *);
+static GLdouble extractSint(int, const void *);
+static void shoveSint(GLdouble, int, void *);
+static GLdouble extractFloat(int, const void *);
+static void shoveFloat(GLdouble, int, void *);
+static void halveImageSlice(int, GLdouble (*)(int, const void *),
+ void (*)(GLdouble, int, void *),
+ GLint, GLint, GLint,
+ const void *, void *,
+ GLint, GLint, GLint, GLint, GLint);
+static void halveImage3D(int, GLdouble (*)(int, const void *),
+ void (*)(GLdouble, int, void *),
+ GLint, GLint, GLint,
+ const void *, void *,
+ GLint, GLint, GLint, GLint, GLint);
+
+/* packedpixel type scale routines */
+static void extract332(int,const void *, GLfloat []);
+static void shove332(const GLfloat [],int ,void *);
+static void extract233rev(int,const void *, GLfloat []);
+static void shove233rev(const GLfloat [],int ,void *);
+static void extract565(int,const void *, GLfloat []);
+static void shove565(const GLfloat [],int ,void *);
+static void extract565rev(int,const void *, GLfloat []);
+static void shove565rev(const GLfloat [],int ,void *);
+static void extract4444(int,const void *, GLfloat []);
+static void shove4444(const GLfloat [],int ,void *);
+static void extract4444rev(int,const void *, GLfloat []);
+static void shove4444rev(const GLfloat [],int ,void *);
+static void extract5551(int,const void *, GLfloat []);
+static void shove5551(const GLfloat [],int ,void *);
+static void extract1555rev(int,const void *, GLfloat []);
+static void shove1555rev(const GLfloat [],int ,void *);
+static void extract8888(int,const void *, GLfloat []);
+static void shove8888(const GLfloat [],int ,void *);
+static void extract8888rev(int,const void *, GLfloat []);
+static void shove8888rev(const GLfloat [],int ,void *);
+static void extract1010102(int,const void *, GLfloat []);
+static void shove1010102(const GLfloat [],int ,void *);
+static void extract2101010rev(int,const void *, GLfloat []);
+static void shove2101010rev(const GLfloat [],int ,void *);
+static void scaleInternalPackedPixel(int,
+ void (*)(int, const void *,GLfloat []),
+ void (*)(const GLfloat [],int, void *),
+ GLint,GLint, const void *,
+ GLint,GLint,void *,GLint,GLint,GLint);
+static void halveImagePackedPixel(int,
+ void (*)(int, const void *,GLfloat []),
+ void (*)(const GLfloat [],int, void *),
+ GLint, GLint, const void *,
+ void *, GLint, GLint, GLint);
+static void halve1DimagePackedPixel(int,
+ void (*)(int, const void *,GLfloat []),
+ void (*)(const GLfloat [],int, void *),
+ GLint, GLint, const void *,
+ void *, GLint, GLint, GLint);
+
+static void halve1Dimage_ubyte(GLint, GLuint, GLuint,const GLubyte *,
+ GLubyte *, GLint, GLint, GLint);
+static void halve1Dimage_byte(GLint, GLuint, GLuint,const GLbyte *, GLbyte *,
+ GLint, GLint, GLint);
+static void halve1Dimage_ushort(GLint, GLuint, GLuint, const GLushort *,
+ GLushort *, GLint, GLint, GLint, GLint);
+static void halve1Dimage_short(GLint, GLuint, GLuint,const GLshort *, GLshort *,
+ GLint, GLint, GLint, GLint);
+static void halve1Dimage_uint(GLint, GLuint, GLuint, const GLuint *, GLuint *,
+ GLint, GLint, GLint, GLint);
+static void halve1Dimage_int(GLint, GLuint, GLuint, const GLint *, GLint *,
+ GLint, GLint, GLint, GLint);
+static void halve1Dimage_float(GLint, GLuint, GLuint, const GLfloat *, GLfloat *,
+ GLint, GLint, GLint, GLint);
+
+static GLint imageSize3D(GLint, GLint, GLint, GLenum,GLenum);
+static void fillImage3D(const PixelStorageModes *, GLint, GLint, GLint,GLenum,
+ GLenum, GLboolean, const void *, GLushort *);
+static void emptyImage3D(const PixelStorageModes *,
+ GLint, GLint, GLint, GLenum,
+ GLenum, GLboolean,
+ const GLushort *, void *);
+static void scaleInternal3D(GLint, GLint, GLint, GLint, const GLushort *,
+ GLint, GLint, GLint, GLushort *);
+
+static void retrieveStoreModes(PixelStorageModes *psm)
+{
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
+ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
+ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
+ glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
+
+ glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
+ glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
+ glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
+ glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
+ glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
+ glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
+}
+
+static void retrieveStoreModes3D(PixelStorageModes *psm)
+{
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
+ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
+ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
+ glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
+ glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &psm->unpack_skip_images);
+ glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &psm->unpack_image_height);
+
+ glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
+ glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
+ glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
+ glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
+ glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
+ glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
+ glGetIntegerv(GL_PACK_SKIP_IMAGES, &psm->pack_skip_images);
+ glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &psm->pack_image_height);
+}
+
+static int computeLog(GLuint value)
+{
+ int i;
+
+ i = 0;
+
+ /* Error! */
+ if (value == 0) return -1;
+
+ for (;;) {
+ if (value & 1) {
+ /* Error ! */
+ if (value != 1) return -1;
+ return i;
+ }
+ value = value >> 1;
+ i++;
+ }
+}
+
+/*
+** Compute the nearest power of 2 number. This algorithm is a little
+** strange, but it works quite well.
+*/
+static int nearestPower(GLuint value)
+{
+ int i;
+
+ i = 1;
+
+ /* Error! */
+ if (value == 0) return -1;
+
+ for (;;) {
+ if (value == 1) {
+ return i;
+ } else if (value == 3) {
+ return i*4;
+ }
+ value = value >> 1;
+ i *= 2;
+ }
+}
+
+#define __GLU_SWAP_2_BYTES(s)\
+(GLushort)(((GLushort)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
+
+#define __GLU_SWAP_4_BYTES(s)\
+(GLuint)(((GLuint)((const GLubyte*)(s))[3])<<24 | \
+ ((GLuint)((const GLubyte*)(s))[2])<<16 | \
+ ((GLuint)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
+
+static void halveImage(GLint components, GLuint width, GLuint height,
+ const GLushort *datain, GLushort *dataout)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int delta;
+ GLushort *s;
+ const GLushort *t;
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ delta = width * components;
+ s = dataout;
+ t = datain;
+
+ /* Piece o' cake! */
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (t[0] + t[components] + t[delta] +
+ t[delta+components] + 2) / 4;
+ s++; t++;
+ }
+ t += components;
+ }
+ t += delta;
+ }
+}
+
+static void halveImage_ubyte(GLint components, GLuint width, GLuint height,
+ const GLubyte *datain, GLubyte *dataout,
+ GLint element_size, GLint ysize, GLint group_size)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLubyte *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_ubyte(components,width,height,datain,dataout,
+ element_size,ysize,group_size);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (*(const GLubyte*)t +
+ *(const GLubyte*)(t+group_size) +
+ *(const GLubyte*)(t+ysize) +
+ *(const GLubyte*)(t+ysize+group_size) + 2) / 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+/* */
+static void halve1Dimage_ubyte(GLint components, GLuint width, GLuint height,
+ const GLubyte *dataIn, GLubyte *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLubyte *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+ *dest= (*(const GLubyte*)src +
+ *(const GLubyte*)(src+group_size)) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+ *dest= (*(const GLubyte*)src + *(const GLubyte*)(src+ysize)) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+} /* halve1Dimage_ubyte() */
+
+static void halveImage_byte(GLint components, GLuint width, GLuint height,
+ const GLbyte *datain, GLbyte *dataout,
+ GLint element_size,
+ GLint ysize, GLint group_size)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLbyte *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_byte(components,width,height,datain,dataout,
+ element_size,ysize,group_size);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (*(const GLbyte*)t +
+ *(const GLbyte*)(t+group_size) +
+ *(const GLbyte*)(t+ysize) +
+ *(const GLbyte*)(t+ysize+group_size) + 2) / 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+static void halve1Dimage_byte(GLint components, GLuint width, GLuint height,
+ const GLbyte *dataIn, GLbyte *dataOut,
+ GLint element_size,GLint ysize, GLint group_size)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLbyte *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+ *dest= (*(const GLbyte*)src + *(const GLbyte*)(src+group_size)) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+ *dest= (*(const GLbyte*)src + *(const GLbyte*)(src+ysize)) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ }
+
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+} /* halve1Dimage_byte() */
+
+static void halveImage_ushort(GLint components, GLuint width, GLuint height,
+ const GLushort *datain, GLushort *dataout,
+ GLint element_size, GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLushort *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_ushort(components,width,height,datain,dataout,
+ element_size,ysize,group_size, myswap_bytes);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ if (!myswap_bytes)
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (*(const GLushort*)t +
+ *(const GLushort*)(t+group_size) +
+ *(const GLushort*)(t+ysize) +
+ *(const GLushort*)(t+ysize+group_size) + 2) / 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+ else
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (__GLU_SWAP_2_BYTES(t) +
+ __GLU_SWAP_2_BYTES(t+group_size) +
+ __GLU_SWAP_2_BYTES(t+ysize) +
+ __GLU_SWAP_2_BYTES(t+ysize+group_size)+ 2)/4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+static void halve1Dimage_ushort(GLint components, GLuint width, GLuint height,
+ const GLushort *dataIn, GLushort *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size, GLint myswap_bytes)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLushort *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLushort ushort[BOX2];
+ if (myswap_bytes) {
+ ushort[0]= __GLU_SWAP_2_BYTES(src);
+ ushort[1]= __GLU_SWAP_2_BYTES(src+group_size);
+ }
+ else {
+ ushort[0]= *(const GLushort*)src;
+ ushort[1]= *(const GLushort*)(src+group_size);
+ }
+
+ *dest= (ushort[0] + ushort[1]) / 2;
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLushort ushort[BOX2];
+ if (myswap_bytes) {
+ ushort[0]= __GLU_SWAP_2_BYTES(src);
+ ushort[1]= __GLU_SWAP_2_BYTES(src+ysize);
+ }
+ else {
+ ushort[0]= *(const GLushort*)src;
+ ushort[1]= *(const GLushort*)(src+ysize);
+ }
+ *dest= (ushort[0] + ushort[1]) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ }
+
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+
+} /* halve1Dimage_ushort() */
+
+
+static void halveImage_short(GLint components, GLuint width, GLuint height,
+ const GLshort *datain, GLshort *dataout,
+ GLint element_size, GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLshort *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_short(components,width,height,datain,dataout,
+ element_size,ysize,group_size, myswap_bytes);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ if (!myswap_bytes)
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (*(const GLshort*)t +
+ *(const GLshort*)(t+group_size) +
+ *(const GLshort*)(t+ysize) +
+ *(const GLshort*)(t+ysize+group_size) + 2) / 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+ else
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ GLushort b;
+ GLint buf;
+ b = __GLU_SWAP_2_BYTES(t);
+ buf = *(const GLshort*)&b;
+ b = __GLU_SWAP_2_BYTES(t+group_size);
+ buf += *(const GLshort*)&b;
+ b = __GLU_SWAP_2_BYTES(t+ysize);
+ buf += *(const GLshort*)&b;
+ b = __GLU_SWAP_2_BYTES(t+ysize+group_size);
+ buf += *(const GLshort*)&b;
+ s[0] = (GLshort)((buf+2)/4);
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+static void halve1Dimage_short(GLint components, GLuint width, GLuint height,
+ const GLshort *dataIn, GLshort *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size, GLint myswap_bytes)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLshort *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLshort sshort[BOX2];
+ if (myswap_bytes) {
+ sshort[0]= __GLU_SWAP_2_BYTES(src);
+ sshort[1]= __GLU_SWAP_2_BYTES(src+group_size);
+ }
+ else {
+ sshort[0]= *(const GLshort*)src;
+ sshort[1]= *(const GLshort*)(src+group_size);
+ }
+
+ *dest= (sshort[0] + sshort[1]) / 2;
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLshort sshort[BOX2];
+ if (myswap_bytes) {
+ sshort[0]= __GLU_SWAP_2_BYTES(src);
+ sshort[1]= __GLU_SWAP_2_BYTES(src+ysize);
+ }
+ else {
+ sshort[0]= *(const GLshort*)src;
+ sshort[1]= *(const GLshort*)(src+ysize);
+ }
+ *dest= (sshort[0] + sshort[1]) / 2;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ }
+
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+
+} /* halve1Dimage_short() */
+
+
+static void halveImage_uint(GLint components, GLuint width, GLuint height,
+ const GLuint *datain, GLuint *dataout,
+ GLint element_size, GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLuint *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_uint(components,width,height,datain,dataout,
+ element_size,ysize,group_size, myswap_bytes);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ if (!myswap_bytes)
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ /* need to cast to double to hold large unsigned ints */
+ s[0] = ((double)*(const GLuint*)t +
+ (double)*(const GLuint*)(t+group_size) +
+ (double)*(const GLuint*)(t+ysize) +
+ (double)*(const GLuint*)(t+ysize+group_size))/4 + 0.5;
+ s++; t += element_size;
+
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+ else
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ /* need to cast to double to hold large unsigned ints */
+ GLdouble buf;
+ buf = (GLdouble)__GLU_SWAP_4_BYTES(t) +
+ (GLdouble)__GLU_SWAP_4_BYTES(t+group_size) +
+ (GLdouble)__GLU_SWAP_4_BYTES(t+ysize) +
+ (GLdouble)__GLU_SWAP_4_BYTES(t+ysize+group_size);
+ s[0] = (GLuint)(buf/4 + 0.5);
+
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+/* */
+static void halve1Dimage_uint(GLint components, GLuint width, GLuint height,
+ const GLuint *dataIn, GLuint *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size, GLint myswap_bytes)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLuint *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLuint uint[BOX2];
+ if (myswap_bytes) {
+ uint[0]= __GLU_SWAP_4_BYTES(src);
+ uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
+ }
+ else {
+ uint[0]= *(const GLuint*)src;
+ uint[1]= *(const GLuint*)(src+group_size);
+ }
+ *dest= ((double)uint[0]+(double)uint[1])/2.0;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLuint uint[BOX2];
+ if (myswap_bytes) {
+ uint[0]= __GLU_SWAP_4_BYTES(src);
+ uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
+ }
+ else {
+ uint[0]= *(const GLuint*)src;
+ uint[1]= *(const GLuint*)(src+ysize);
+ }
+ *dest= ((double)uint[0]+(double)uint[1])/2.0;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ }
+
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+
+} /* halve1Dimage_uint() */
+
+static void halveImage_int(GLint components, GLuint width, GLuint height,
+ const GLint *datain, GLint *dataout, GLint element_size,
+ GLint ysize, GLint group_size, GLint myswap_bytes)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLint *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_int(components,width,height,datain,dataout,
+ element_size,ysize,group_size, myswap_bytes);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ if (!myswap_bytes)
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = ((float)*(const GLint*)t +
+ (float)*(const GLint*)(t+group_size) +
+ (float)*(const GLint*)(t+ysize) +
+ (float)*(const GLint*)(t+ysize+group_size))/4 + 0.5;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+ else
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ GLuint b;
+ GLfloat buf;
+ b = __GLU_SWAP_4_BYTES(t);
+ buf = *(GLint*)&b;
+ b = __GLU_SWAP_4_BYTES(t+group_size);
+ buf += *(GLint*)&b;
+ b = __GLU_SWAP_4_BYTES(t+ysize);
+ buf += *(GLint*)&b;
+ b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
+ buf += *(GLint*)&b;
+ s[0] = (GLint)(buf/4 + 0.5);
+
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+/* */
+static void halve1Dimage_int(GLint components, GLuint width, GLuint height,
+ const GLint *dataIn, GLint *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size, GLint myswap_bytes)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLint *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLuint uint[BOX2];
+ if (myswap_bytes) {
+ uint[0]= __GLU_SWAP_4_BYTES(src);
+ uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
+ }
+ else {
+ uint[0]= *(const GLuint*)src;
+ uint[1]= *(const GLuint*)(src+group_size);
+ }
+ *dest= ((float)uint[0]+(float)uint[1])/2.0;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLuint uint[BOX2];
+ if (myswap_bytes) {
+ uint[0]= __GLU_SWAP_4_BYTES(src);
+ uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
+ }
+ else {
+ uint[0]= *(const GLuint*)src;
+ uint[1]= *(const GLuint*)(src+ysize);
+ }
+ *dest= ((float)uint[0]+(float)uint[1])/2.0;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize;
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ }
+
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+
+} /* halve1Dimage_int() */
+
+
+static void halveImage_float(GLint components, GLuint width, GLuint height,
+ const GLfloat *datain, GLfloat *dataout,
+ GLint element_size, GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ int i, j, k;
+ int newwidth, newheight;
+ int padBytes;
+ GLfloat *s;
+ const char *t;
+
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
+ halve1Dimage_float(components,width,height,datain,dataout,
+ element_size,ysize,group_size, myswap_bytes);
+ return;
+ }
+
+ newwidth = width / 2;
+ newheight = height / 2;
+ padBytes = ysize - (width*group_size);
+ s = dataout;
+ t = (const char *)datain;
+
+ /* Piece o' cake! */
+ if (!myswap_bytes)
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ s[0] = (*(const GLfloat*)t +
+ *(const GLfloat*)(t+group_size) +
+ *(const GLfloat*)(t+ysize) +
+ *(const GLfloat*)(t+ysize+group_size)) / 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+ else
+ for (i = 0; i < newheight; i++) {
+ for (j = 0; j < newwidth; j++) {
+ for (k = 0; k < components; k++) {
+ union { GLuint b; GLfloat f; } swapbuf;
+ swapbuf.b = __GLU_SWAP_4_BYTES(t);
+ s[0] = swapbuf.f;
+ swapbuf.b = __GLU_SWAP_4_BYTES(t+group_size);
+ s[0] += swapbuf.f;
+ swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize);
+ s[0] += swapbuf.f;
+ swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
+ s[0] += swapbuf.f;
+ s[0] /= 4;
+ s++; t += element_size;
+ }
+ t += group_size;
+ }
+ t += padBytes;
+ t += ysize;
+ }
+}
+
+/* */
+static void halve1Dimage_float(GLint components, GLuint width, GLuint height,
+ const GLfloat *dataIn, GLfloat *dataOut,
+ GLint element_size, GLint ysize,
+ GLint group_size, GLint myswap_bytes)
+{
+ GLint halfWidth= width / 2;
+ GLint halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ GLfloat *dest= dataOut;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ for (jj= 0; jj< halfWidth; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLfloat sfloat[BOX2];
+ if (myswap_bytes) {
+ sfloat[0]= __GLU_SWAP_4_BYTES(src);
+ sfloat[1]= __GLU_SWAP_4_BYTES(src+group_size);
+ }
+ else {
+ sfloat[0]= *(const GLfloat*)src;
+ sfloat[1]= *(const GLfloat*)(src+group_size);
+ }
+
+ *dest= (sfloat[0] + sfloat[1]) / 2.0;
+ src+= element_size;
+ dest++;
+ }
+ src+= group_size; /* skip to next 2 */
+ }
+ {
+ int padBytes= ysize - (width*group_size);
+ src+= padBytes; /* for assertion only */
+ }
+ }
+ else if (width == 1) { /* 1 column */
+ int padBytes= ysize - (width * group_size);
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+ int kk;
+ for (kk= 0; kk< components; kk++) {
+#define BOX2 2
+ GLfloat sfloat[BOX2];
+ if (myswap_bytes) {
+ sfloat[0]= __GLU_SWAP_4_BYTES(src);
+ sfloat[1]= __GLU_SWAP_4_BYTES(src+ysize);
+ }
+ else {
+ sfloat[0]= *(const GLfloat*)src;
+ sfloat[1]= *(const GLfloat*)(src+ysize);
+ }
+ *dest= (sfloat[0] + sfloat[1]) / 2.0;
+
+ src+= element_size;
+ dest++;
+ }
+ src+= padBytes; /* add pad bytes, if any, to get to end to row */
+ src+= ysize; /* skip to odd row */
+ }
+ }
+
+ assert(src == &((const char *)dataIn)[ysize*height]);
+ assert((char *)dest == &((char *)dataOut)
+ [components * element_size * halfWidth * halfHeight]);
+} /* halve1Dimage_float() */
+
+static void scale_internal(GLint components, GLint widthin, GLint heightin,
+ const GLushort *datain,
+ GLint widthout, GLint heightout,
+ GLushort *dataout)
+{
+ float x, lowx, highx, convx, halfconvx;
+ float y, lowy, highy, convy, halfconvy;
+ float xpercent,ypercent;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,yint,xint,xindex,yindex;
+ int temp;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage(components, widthin, heightin, datain, dataout);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ halfconvx = convx/2;
+ halfconvy = convy/2;
+ for (i = 0; i < heightout; i++) {
+ y = convy * (i+0.5);
+ if (heightin > heightout) {
+ highy = y + halfconvy;
+ lowy = y - halfconvy;
+ } else {
+ highy = y + 0.5;
+ lowy = y - 0.5;
+ }
+ for (j = 0; j < widthout; j++) {
+ x = convx * (j+0.5);
+ if (widthin > widthout) {
+ highx = x + halfconvx;
+ lowx = x - halfconvx;
+ } else {
+ highx = x + 0.5;
+ lowx = x - 0.5;
+ }
+
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+ area = 0.0;
+
+ y = lowy;
+ yint = floor(y);
+ while (y < highy) {
+ yindex = (yint + heightin) % heightin;
+ if (highy < yint+1) {
+ ypercent = highy - y;
+ } else {
+ ypercent = yint+1 - y;
+ }
+
+ x = lowx;
+ xint = floor(x);
+
+ while (x < highx) {
+ xindex = (xint + widthin) % widthin;
+ if (highx < xint+1) {
+ xpercent = highx - x;
+ } else {
+ xpercent = xint+1 - x;
+ }
+
+ percent = xpercent * ypercent;
+ area += percent;
+ temp = (xindex + (yindex * widthin)) * components;
+ for (k = 0; k < components; k++) {
+ totals[k] += datain[temp + k] * percent;
+ }
+
+ xint++;
+ x = xint;
+ }
+ yint++;
+ y = yint;
+ }
+
+ temp = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ /* totals[] should be rounded in the case of enlarging an RGB
+ * ramp when the type is 332 or 4444
+ */
+ dataout[temp + k] = (totals[k]+0.5)/area;
+ }
+ }
+ }
+}
+
+static void scale_internal_ubyte(GLint components, GLint widthin,
+ GLint heightin, const GLubyte *datain,
+ GLint widthout, GLint heightout,
+ GLubyte *dataout, GLint element_size,
+ GLint ysize, GLint group_size)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_ubyte(components, widthin, heightin,
+ (const GLubyte *)datain, (GLubyte *)dataout,
+ element_size, ysize, group_size);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ totals[k] += (GLubyte)(*(left))*(1-lowx_float)
+ +(GLubyte)(*(right))*highx_float;
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * x_percent;
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index)) * percent;
+ }
+ }
+
+
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLubyte)(*(temp_index));
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+static void scale_internal_byte(GLint components, GLint widthin,
+ GLint heightin, const GLbyte *datain,
+ GLint widthout, GLint heightout,
+ GLbyte *dataout, GLint element_size,
+ GLint ysize, GLint group_size)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_byte(components, widthin, heightin,
+ (const GLbyte *)datain, (GLbyte *)dataout,
+ element_size, ysize, group_size);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ totals[k] += (GLbyte)(*(left))*(1-lowx_float)
+ +(GLbyte)(*(right))*highx_float;
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * x_percent;
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * y_percent;
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index)) * percent;
+ }
+ }
+
+
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ totals[k] += (GLbyte)(*(temp_index));
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+static void scale_internal_ushort(GLint components, GLint widthin,
+ GLint heightin, const GLushort *datain,
+ GLint widthout, GLint heightout,
+ GLushort *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_ushort(components, widthin, heightin,
+ (const GLushort *)datain, (GLushort *)dataout,
+ element_size, ysize, group_size, myswap_bytes);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
+ __GLU_SWAP_2_BYTES(right) * highx_float;
+ } else {
+ totals[k] += *(const GLushort*)left * (1-lowx_float)
+ + *(const GLushort*)right * highx_float;
+ }
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * x_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * x_percent;
+ }
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index);
+ } else {
+ totals[k] += *(const GLushort*)temp_index;
+ }
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+static void scale_internal_short(GLint components, GLint widthin,
+ GLint heightin, const GLshort *datain,
+ GLint widthout, GLint heightout,
+ GLshort *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ GLushort swapbuf; /* unsigned buffer */
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_short(components, widthin, heightin,
+ (const GLshort *)datain, (GLshort *)dataout,
+ element_size, ysize, group_size, myswap_bytes);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(left);
+ totals[k] += *(const GLshort*)&swapbuf * (1-lowx_float);
+ swapbuf = __GLU_SWAP_2_BYTES(right);
+ totals[k] += *(const GLshort*)&swapbuf * highx_float;
+ } else {
+ totals[k] += *(const GLshort*)left * (1-lowx_float)
+ + *(const GLshort*)right * highx_float;
+ }
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * x_percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * x_percent;
+ }
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLshort*)temp_index * percent;
+ }
+ }
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_2_BYTES(temp_index);
+ totals[k] += *(const GLshort*)&swapbuf;
+ } else {
+ totals[k] += *(const GLshort*)temp_index;
+ }
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+static void scale_internal_uint(GLint components, GLint widthin,
+ GLint heightin, const GLuint *datain,
+ GLint widthout, GLint heightout,
+ GLuint *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_uint(components, widthin, heightin,
+ (const GLuint *)datain, (GLuint *)dataout,
+ element_size, ysize, group_size, myswap_bytes);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_4_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_4_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_4_BYTES(left) * (1-lowx_float)
+ + __GLU_SWAP_4_BYTES(right) * highx_float;
+ } else {
+ totals[k] += *(const GLuint*)left * (1-lowx_float)
+ + *(const GLuint*)right * highx_float;
+ }
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_4_BYTES(temp_index) * x_percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * x_percent;
+ }
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_4_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLuint*)temp_index * percent;
+ }
+ }
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_4_BYTES(temp_index);
+ } else {
+ totals[k] += *(const GLuint*)temp_index;
+ }
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ /* clamp at UINT_MAX */
+ float value= totals[k]/area;
+ if (value >= (float) UINT_MAX) { /* need '=' */
+ dataout[outindex + k] = UINT_MAX;
+ }
+ else dataout[outindex + k] = value;
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+
+
+static void scale_internal_int(GLint components, GLint widthin,
+ GLint heightin, const GLint *datain,
+ GLint widthout, GLint heightout,
+ GLint *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ GLuint swapbuf; /* unsigned buffer */
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_int(components, widthin, heightin,
+ (const GLint *)datain, (GLint *)dataout,
+ element_size, ysize, group_size, myswap_bytes);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(left);
+ totals[k] += *(const GLint*)&swapbuf * (1-lowx_float);
+ swapbuf = __GLU_SWAP_4_BYTES(right);
+ totals[k] += *(const GLint*)&swapbuf * highx_float;
+ } else {
+ totals[k] += *(const GLint*)left * (1-lowx_float)
+ + *(const GLint*)right * highx_float;
+ }
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * x_percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * x_percent;
+ }
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * y_percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf * percent;
+ } else {
+ totals[k] += *(const GLint*)temp_index * percent;
+ }
+ }
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += *(const GLint*)&swapbuf;
+ } else {
+ totals[k] += *(const GLint*)temp_index;
+ }
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+
+
+static void scale_internal_float(GLint components, GLint widthin,
+ GLint heightin, const GLfloat *datain,
+ GLint widthout, GLint heightout,
+ GLfloat *dataout, GLint element_size,
+ GLint ysize, GLint group_size,
+ GLint myswap_bytes)
+{
+ float convx;
+ float convy;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ const char *temp_index;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ union { GLuint b; GLfloat f; } swapbuf;
+
+ if (widthin == widthout*2 && heightin == heightout*2) {
+ halveImage_float(components, widthin, heightin,
+ (const GLfloat *)datain, (GLfloat *)dataout,
+ element_size, ysize, group_size, myswap_bytes);
+ return;
+ }
+ convy = (float) heightin/heightout;
+ convx = (float) widthin/widthout;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightout; i++) {
+ /* Clamp here to be sure we don't read beyond input buffer. */
+ if (highy_int >= heightin)
+ highy_int = heightin - 1;
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthout; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*group_size;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ percent = y_percent * (1-lowx_float);
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * y_percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ right = temp;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the last row */
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)datain + xindex + highy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * y_percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += ysize;
+ right += ysize;
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(left);
+ totals[k] += swapbuf.f * (1-lowx_float);
+ swapbuf.b = __GLU_SWAP_4_BYTES(right);
+ totals[k] += swapbuf.f * highx_float;
+ } else {
+ totals[k] += *(const GLfloat*)left * (1-lowx_float)
+ + *(const GLfloat*)right * highx_float;
+ }
+ }
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * x_percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * x_percent;
+ }
+ }
+ }
+ percent = x_percent * highy_float;
+ temp += ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+
+ temp = (const char *)datain + xindex + lowy_int*ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += group_size;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * y_percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * y_percent;
+ }
+ }
+ }
+ temp += group_size;
+ percent = y_percent * highx_float;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)datain + xindex + lowy_int * ysize;
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f * percent;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index * percent;
+ }
+ }
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)datain + xindex + group_size +
+ (lowy_int+1)*ysize;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
+ totals[k] += swapbuf.f;
+ } else {
+ totals[k] += *(const GLfloat*)temp_index;
+ }
+ }
+ temp += group_size;
+ }
+ temp0 += ysize;
+ }
+
+ outindex = (j + (i * widthout)) * components;
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+}
+
+static int checkMipmapArgs(GLenum internalFormat, GLenum format, GLenum type)
+{
+ if (!legalFormat(format) || !legalType(type)) {
+ return GLU_INVALID_ENUM;
+ }
+ if (format == GL_STENCIL_INDEX) {
+ return GLU_INVALID_ENUM;
+ }
+
+ if (!isLegalFormatForPackedPixelType(format, type)) {
+ return GLU_INVALID_OPERATION;
+ }
+
+ return 0;
+} /* checkMipmapArgs() */
+
+static GLboolean legalFormat(GLenum format)
+{
+ 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_RGB:
+ case GL_RGBA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_BGR:
+ case GL_BGRA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean legalType(GLenum type)
+{
+ 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:
+ 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:
+ 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;
+ }
+}
+
+/* */
+static GLboolean isTypePackedPixel(GLenum type)
+{
+ assert(legalType(type));
+
+ if (type == GL_UNSIGNED_BYTE_3_3_2 ||
+ type == GL_UNSIGNED_BYTE_2_3_3_REV ||
+ type == GL_UNSIGNED_SHORT_5_6_5 ||
+ type == GL_UNSIGNED_SHORT_5_6_5_REV ||
+ type == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ type == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ type == GL_UNSIGNED_INT_8_8_8_8 ||
+ type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ type == GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL_UNSIGNED_INT_2_10_10_10_REV) {
+ return 1;
+ }
+ else return 0;
+} /* isTypePackedPixel() */
+
+/* Determines if the packed pixel type is compatible with the format */
+static GLboolean isLegalFormatForPackedPixelType(GLenum format, GLenum type)
+{
+ /* if not a packed pixel type then return true */
+ if (!isTypePackedPixel(type)) {
+ return GL_TRUE;
+ }
+
+ /* 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB */
+ if ((type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_BYTE_2_3_3_REV||
+ type == GL_UNSIGNED_SHORT_5_6_5|| type == GL_UNSIGNED_SHORT_5_6_5_REV)
+ && format != GL_RGB)
+ return GL_FALSE;
+
+ /* 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
+ * 10_10_10_2/2_10_10_10_REV are only compatible with RGBA, BGRA & ABGR_EXT.
+ */
+ if ((type == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ type == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ type == GL_UNSIGNED_INT_8_8_8_8 ||
+ type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ type == GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
+ (format != GL_RGBA &&
+ format != GL_BGRA)) {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+} /* isLegalFormatForPackedPixelType() */
+
+static GLboolean isLegalLevels(GLint userLevel,GLint baseLevel,GLint maxLevel,
+ GLint totalLevels)
+{
+ if (baseLevel < 0 || baseLevel < userLevel || maxLevel < baseLevel ||
+ totalLevels < maxLevel)
+ return GL_FALSE;
+ else return GL_TRUE;
+} /* isLegalLevels() */
+
+/* Given user requested texture size, determine if it fits. If it
+ * doesn't then halve both sides and make the determination again
+ * until it does fit (for IR only).
+ * Note that proxy textures are not implemented in RE* even though
+ * they advertise the texture extension.
+ * Note that proxy textures are implemented but not according to spec in
+ * IMPACT*.
+ */
+static void closestFit(GLenum target, GLint width, GLint height,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint *newWidth, GLint *newHeight)
+{
+ /* Use proxy textures if OpenGL version is >= 1.1 */
+ if ( (strtod((const char *)glGetString(GL_VERSION),NULL) >= 1.1)
+ ) {
+ GLint widthPowerOf2= nearestPower(width);
+ GLint heightPowerOf2= nearestPower(height);
+ GLint proxyWidth;
+
+ do {
+ /* compute level 1 width & height, clamping each at 1 */
+ GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
+ widthPowerOf2 >> 1 :
+ widthPowerOf2;
+ GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
+ heightPowerOf2 >> 1 :
+ heightPowerOf2;
+ GLenum proxyTarget;
+ assert(widthAtLevelOne > 0); assert(heightAtLevelOne > 0);
+
+ /* does width x height at level 1 & all their mipmaps fit? */
+ if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
+ proxyTarget = GL_PROXY_TEXTURE_2D;
+ glTexImage2D(proxyTarget, 1, /* must be non-zero */
+ internalFormat,
+ widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
+ } else
+#if defined(GL_ARB_texture_cube_map)
+ if ((target == GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB) ||
+ (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB) ||
+ (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB) ||
+ (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB) ||
+ (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB) ||
+ (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
+ proxyTarget = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
+ glTexImage2D(proxyTarget, 1, /* must be non-zero */
+ internalFormat,
+ widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
+ } else
+#endif /* GL_ARB_texture_cube_map */
+ {
+ assert(target == GL_TEXTURE_1D || target == GL_PROXY_TEXTURE_1D);
+ proxyTarget = GL_PROXY_TEXTURE_1D;
+ glTexImage1D(proxyTarget, 1, /* must be non-zero */
+ internalFormat,widthAtLevelOne,0,format,type,NULL);
+ }
+ glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
+ /* does it fit??? */
+ if (proxyWidth == 0) { /* nope, so try again with these sizes */
+ if (widthPowerOf2 == 1 && heightPowerOf2 == 1) {
+ /* An 1x1 texture couldn't fit for some reason, so
+ * break out. This should never happen. But things
+ * happen. The disadvantage with this if-statement is
+ * that we will never be aware of when this happens
+ * since it will silently branch out.
+ */
+ goto noProxyTextures;
+ }
+ widthPowerOf2= widthAtLevelOne;
+ heightPowerOf2= heightAtLevelOne;
+ }
+ /* else it does fit */
+ } while (proxyWidth == 0);
+ /* loop must terminate! */
+
+ /* return the width & height at level 0 that fits */
+ *newWidth= widthPowerOf2;
+ *newHeight= heightPowerOf2;
+/*printf("Proxy Textures\n");*/
+ } /* if gluCheckExtension() */
+ else { /* no texture extension, so do this instead */
+ GLint maxsize;
+
+noProxyTextures:
+
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
+ /* clamp user's texture sizes to maximum sizes, if necessary */
+ *newWidth = nearestPower(width);
+ if (*newWidth > maxsize) *newWidth = maxsize;
+ *newHeight = nearestPower(height);
+ if (*newHeight > maxsize) *newHeight = maxsize;
+/*printf("NO proxy textures\n");*/
+ }
+} /* closestFit() */
+
+GLint GLAPIENTRY
+gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin,
+ GLenum typein, const void *datain,
+ GLsizei widthout, GLsizei heightout, GLenum typeout,
+ void *dataout)
+{
+ int components;
+ GLushort *beforeImage;
+ GLushort *afterImage;
+ PixelStorageModes psm;
+
+ if (widthin == 0 || heightin == 0 || widthout == 0 || heightout == 0) {
+ return 0;
+ }
+ if (widthin < 0 || heightin < 0 || widthout < 0 || heightout < 0) {
+ return GLU_INVALID_VALUE;
+ }
+ if (!legalFormat(format) || !legalType(typein) || !legalType(typeout)) {
+ return GLU_INVALID_ENUM;
+ }
+ if (!isLegalFormatForPackedPixelType(format, typein)) {
+ return GLU_INVALID_OPERATION;
+ }
+ if (!isLegalFormatForPackedPixelType(format, typeout)) {
+ return GLU_INVALID_OPERATION;
+ }
+ beforeImage =
+ malloc(image_size(widthin, heightin, format, GL_UNSIGNED_SHORT));
+ afterImage =
+ malloc(image_size(widthout, heightout, format, GL_UNSIGNED_SHORT));
+ if (beforeImage == NULL || afterImage == NULL) {
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ retrieveStoreModes(&psm);
+ fill_image(&psm,widthin, heightin, format, typein, is_index(format),
+ datain, beforeImage);
+ components = elements_per_group(format, 0);
+ scale_internal(components, widthin, heightin, beforeImage,
+ widthout, heightout, afterImage);
+ empty_image(&psm,widthout, heightout, format, typeout,
+ is_index(format), afterImage, dataout);
+ free((GLbyte *) beforeImage);
+ free((GLbyte *) afterImage);
+
+ return 0;
+}
+
+int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat,
+ GLsizei width,
+ GLsizei widthPowerOf2,
+ GLenum format, GLenum type,
+ GLint userLevel, GLint baseLevel,GLint maxLevel,
+ const void *data)
+{
+ GLint newwidth;
+ GLint level, levels;
+ GLushort *newImage;
+ GLint newImage_width;
+ GLushort *otherImage;
+ GLushort *imageTemp;
+ GLint memreq;
+ GLint cmpts;
+ PixelStorageModes psm;
+
+ assert(checkMipmapArgs(internalFormat,format,type) == 0);
+ assert(width >= 1);
+
+ otherImage = NULL;
+
+ newwidth= widthPowerOf2;
+ levels = computeLog(newwidth);
+
+ levels+= userLevel;
+
+ retrieveStoreModes(&psm);
+ newImage = (GLushort *)
+ malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
+ newImage_width = width;
+ if (newImage == NULL) {
+ return GLU_OUT_OF_MEMORY;
+ }
+ fill_image(&psm,width, 1, format, type, is_index(format),
+ data, newImage);
+ cmpts = elements_per_group(format,type);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ /*
+ ** If swap_bytes was set, swapping occurred in fill_image.
+ */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+
+ for (level = userLevel; level <= levels; level++) {
+ if (newImage_width == newwidth) {
+ /* Use newImage for this level */
+ if (baseLevel <= level && level <= maxLevel) {
+ glTexImage1D(target, level, internalFormat, newImage_width,
+ 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
+ }
+ } else {
+ if (otherImage == NULL) {
+ memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
+ otherImage = (GLushort *) malloc(memreq);
+ if (otherImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ }
+ scale_internal(cmpts, newImage_width, 1, newImage,
+ newwidth, 1, otherImage);
+ /* Swap newImage and otherImage */
+ imageTemp = otherImage;
+ otherImage = newImage;
+ newImage = imageTemp;
+
+ newImage_width = newwidth;
+ if (baseLevel <= level && level <= maxLevel) {
+ glTexImage1D(target, level, internalFormat, newImage_width,
+ 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
+ }
+ }
+ if (newwidth > 1) newwidth /= 2;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+
+ free((GLbyte *) newImage);
+ if (otherImage) {
+ free((GLbyte *) otherImage);
+ }
+ return 0;
+}
+
+GLint GLAPIENTRY
+gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
+ GLsizei width,
+ GLenum format, GLenum type,
+ GLint userLevel, GLint baseLevel, GLint maxLevel,
+ const void *data)
+{
+ int levels;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ levels = computeLog(width);
+
+ levels+= userLevel;
+ if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
+ return GLU_INVALID_VALUE;
+
+ return gluBuild1DMipmapLevelsCore(target, internalFormat,
+ width,
+ width,format, type,
+ userLevel, baseLevel, maxLevel,
+ data);
+} /* gluBuild1DMipmapLevels() */
+
+GLint GLAPIENTRY
+gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
+ GLenum format, GLenum type,
+ const void *data)
+{
+ GLint widthPowerOf2;
+ int levels;
+ GLint dummy;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ closestFit(target,width,1,internalFormat,format,type,&widthPowerOf2,&dummy);
+ levels = computeLog(widthPowerOf2);
+
+ return gluBuild1DMipmapLevelsCore(target,internalFormat,
+ width,
+ widthPowerOf2,
+ format,type,0,0,levels,data);
+}
+
+static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat,
+ GLint width, GLint height, GLenum format,
+ GLenum type, const void *data)
+{
+ GLint newwidth, newheight;
+ GLint level, levels;
+ GLushort *newImage;
+ GLint newImage_width;
+ GLint newImage_height;
+ GLushort *otherImage;
+ GLushort *imageTemp;
+ GLint memreq;
+ GLint cmpts;
+ PixelStorageModes psm;
+
+ retrieveStoreModes(&psm);
+
+#if 0
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
+ newwidth = nearestPower(width);
+ if (newwidth > maxsize) newwidth = maxsize;
+ newheight = nearestPower(height);
+ if (newheight > maxsize) newheight = maxsize;
+#else
+ closestFit(target,width,height,internalFormat,format,type,
+ &newwidth,&newheight);
+#endif
+ levels = computeLog(newwidth);
+ level = computeLog(newheight);
+ if (level > levels) levels=level;
+
+ otherImage = NULL;
+ newImage = (GLushort *)
+ malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
+ newImage_width = width;
+ newImage_height = height;
+ if (newImage == NULL) {
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ fill_image(&psm,width, height, format, type, is_index(format),
+ data, newImage);
+
+ cmpts = elements_per_group(format,type);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ /*
+ ** If swap_bytes was set, swapping occurred in fill_image.
+ */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+
+ for (level = 0; level <= levels; level++) {
+ if (newImage_width == newwidth && newImage_height == newheight) { /* Use newImage for this level */
+ glTexImage2D(target, level, internalFormat, newImage_width,
+ newImage_height, 0, format, GL_UNSIGNED_SHORT,
+ (void *) newImage);
+ } else {
+ if (otherImage == NULL) {
+ memreq =
+ image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
+ otherImage = (GLushort *) malloc(memreq);
+ if (otherImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ }
+ scale_internal(cmpts, newImage_width, newImage_height, newImage,
+ newwidth, newheight, otherImage);
+ /* Swap newImage and otherImage */
+ imageTemp = otherImage;
+ otherImage = newImage;
+ newImage = imageTemp;
+
+ newImage_width = newwidth;
+ newImage_height = newheight;
+ glTexImage2D(target, level, internalFormat, newImage_width,
+ newImage_height, 0, format, GL_UNSIGNED_SHORT,
+ (void *) newImage);
+ }
+ if (newwidth > 1) newwidth /= 2;
+ if (newheight > 1) newheight /= 2;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+
+ free((GLbyte *) newImage);
+ if (otherImage) {
+ free((GLbyte *) otherImage);
+ }
+ return 0;
+}
+
+/* To make swapping images less error prone */
+#define __GLU_INIT_SWAP_IMAGE void *tmpImage
+#define __GLU_SWAP_IMAGE(a,b) tmpImage = a; a = b; b = tmpImage;
+
+static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei widthPowerOf2,
+ GLsizei heightPowerOf2,
+ GLenum format, GLenum type,
+ GLint userLevel,
+ GLint baseLevel,GLint maxLevel,
+ const void *data)
+{
+ GLint newwidth, newheight;
+ GLint level, levels;
+ const void *usersImage; /* passed from user. Don't touch! */
+ void *srcImage, *dstImage; /* scratch area to build mipmapped images */
+ __GLU_INIT_SWAP_IMAGE;
+ GLint memreq;
+ GLint cmpts;
+
+ GLint myswap_bytes, groups_per_line, element_size, group_size;
+ GLint rowsize, padding;
+ PixelStorageModes psm;
+
+ assert(checkMipmapArgs(internalFormat,format,type) == 0);
+ assert(width >= 1 && height >= 1);
+
+ if(type == GL_BITMAP) {
+ return bitmapBuild2DMipmaps(target, internalFormat, width, height,
+ format, type, data);
+ }
+
+ srcImage = dstImage = NULL;
+
+ newwidth= widthPowerOf2;
+ newheight= heightPowerOf2;
+ levels = computeLog(newwidth);
+ level = computeLog(newheight);
+ if (level > levels) levels=level;
+
+ levels+= userLevel;
+
+ retrieveStoreModes(&psm);
+ myswap_bytes = psm.unpack_swap_bytes;
+ cmpts = elements_per_group(format,type);
+ if (psm.unpack_row_length > 0) {
+ groups_per_line = psm.unpack_row_length;
+ } else {
+ groups_per_line = width;
+ }
+
+ element_size = bytes_per_element(type);
+ group_size = element_size * cmpts;
+ if (element_size == 1) myswap_bytes = 0;
+
+ rowsize = groups_per_line * group_size;
+ padding = (rowsize % psm.unpack_alignment);
+ if (padding) {
+ rowsize += psm.unpack_alignment - padding;
+ }
+ usersImage = (const GLubyte *) data + psm.unpack_skip_rows * rowsize +
+ psm.unpack_skip_pixels * group_size;
+
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+ level = userLevel;
+
+ /* already power-of-two square */
+ if (width == newwidth && height == newheight) {
+ /* Use usersImage for level userLevel */
+ if (baseLevel <= level && level <= maxLevel) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glTexImage2D(target, level, internalFormat, width,
+ height, 0, format, type,
+ usersImage);
+ }
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ if(levels == 0) { /* we're done. clean up and return */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return 0;
+ }
+ {
+ int nextWidth= newwidth/2;
+ int nextHeight= newheight/2;
+
+ /* clamp to 1 */
+ if (nextWidth < 1) nextWidth= 1;
+ if (nextHeight < 1) nextHeight= 1;
+ memreq = image_size(nextWidth, nextHeight, format, type);
+ }
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memreq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ default:
+ return GLU_INVALID_ENUM;
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ else
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ halveImage_ubyte(cmpts, width, height,
+ (const GLubyte *)usersImage, (GLubyte *)dstImage,
+ element_size, rowsize, group_size);
+ break;
+ case GL_BYTE:
+ halveImage_byte(cmpts, width, height,
+ (const GLbyte *)usersImage, (GLbyte *)dstImage,
+ element_size, rowsize, group_size);
+ break;
+ case GL_UNSIGNED_SHORT:
+ halveImage_ushort(cmpts, width, height,
+ (const GLushort *)usersImage, (GLushort *)dstImage,
+ element_size, rowsize, group_size, myswap_bytes);
+ break;
+ case GL_SHORT:
+ halveImage_short(cmpts, width, height,
+ (const GLshort *)usersImage, (GLshort *)dstImage,
+ element_size, rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT:
+ halveImage_uint(cmpts, width, height,
+ (const GLuint *)usersImage, (GLuint *)dstImage,
+ element_size, rowsize, group_size, myswap_bytes);
+ break;
+ case GL_INT:
+ halveImage_int(cmpts, width, height,
+ (const GLint *)usersImage, (GLint *)dstImage,
+ element_size, rowsize, group_size, myswap_bytes);
+ break;
+ case GL_FLOAT:
+ halveImage_float(cmpts, width, height,
+ (const GLfloat *)usersImage, (GLfloat *)dstImage,
+ element_size, rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ assert(format == GL_RGB);
+ halveImagePackedPixel(3,extract332,shove332,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ assert(format == GL_RGB);
+ halveImagePackedPixel(3,extract233rev,shove233rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ halveImagePackedPixel(3,extract565,shove565,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ halveImagePackedPixel(3,extract565rev,shove565rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ halveImagePackedPixel(4,extract4444,shove4444,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ halveImagePackedPixel(4,extract4444rev,shove4444rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ halveImagePackedPixel(4,extract5551,shove5551,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ halveImagePackedPixel(4,extract1555rev,shove1555rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ halveImagePackedPixel(4,extract8888,shove8888,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ halveImagePackedPixel(4,extract8888rev,shove8888rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ halveImagePackedPixel(4,extract1010102,shove1010102,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
+ width,height,usersImage,dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ newwidth = width/2;
+ newheight = height/2;
+ /* clamp to 1 */
+ if (newwidth < 1) newwidth= 1;
+ if (newheight < 1) newheight= 1;
+
+ myswap_bytes = 0;
+ rowsize = newwidth * group_size;
+ memreq = image_size(newwidth, newheight, format, type);
+ /* Swap srcImage and dstImage */
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memreq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ default:
+ return GLU_INVALID_ENUM;
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ /* level userLevel+1 is in srcImage; level userLevel already saved */
+ level = userLevel+1;
+ } else { /* user's image is *not* nice power-of-2 sized square */
+ memreq = image_size(newwidth, newheight, format, type);
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memreq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ default:
+ return GLU_INVALID_ENUM;
+ }
+
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ scale_internal_ubyte(cmpts, width, height,
+ (const GLubyte *)usersImage, newwidth, newheight,
+ (GLubyte *)dstImage, element_size,
+ rowsize, group_size);
+ break;
+ case GL_BYTE:
+ scale_internal_byte(cmpts, width, height,
+ (const GLbyte *)usersImage, newwidth, newheight,
+ (GLbyte *)dstImage, element_size,
+ rowsize, group_size);
+ break;
+ case GL_UNSIGNED_SHORT:
+ scale_internal_ushort(cmpts, width, height,
+ (const GLushort *)usersImage, newwidth, newheight,
+ (GLushort *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_SHORT:
+ scale_internal_short(cmpts, width, height,
+ (const GLshort *)usersImage, newwidth, newheight,
+ (GLshort *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT:
+ scale_internal_uint(cmpts, width, height,
+ (const GLuint *)usersImage, newwidth, newheight,
+ (GLuint *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_INT:
+ scale_internal_int(cmpts, width, height,
+ (const GLint *)usersImage, newwidth, newheight,
+ (GLint *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_FLOAT:
+ scale_internal_float(cmpts, width, height,
+ (const GLfloat *)usersImage, newwidth, newheight,
+ (GLfloat *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ scaleInternalPackedPixel(3,extract332,shove332,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ scaleInternalPackedPixel(3,extract233rev,shove233rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ scaleInternalPackedPixel(3,extract565,shove565,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ scaleInternalPackedPixel(3,extract565rev,shove565rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ scaleInternalPackedPixel(4,extract4444,shove4444,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ scaleInternalPackedPixel(4,extract4444rev,shove4444rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ scaleInternalPackedPixel(4,extract5551,shove5551,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ scaleInternalPackedPixel(4,extract1555rev,shove1555rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ scaleInternalPackedPixel(4,extract8888,shove8888,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ scaleInternalPackedPixel(4,extract8888rev,shove8888rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ scaleInternalPackedPixel(4,extract1010102,shove1010102,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ scaleInternalPackedPixel(4,extract2101010rev,shove2101010rev,
+ width, height,usersImage,
+ newwidth,newheight,(void *)dstImage,
+ element_size,rowsize,myswap_bytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ myswap_bytes = 0;
+ rowsize = newwidth * group_size;
+ /* Swap dstImage and srcImage */
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+
+ if(levels != 0) { /* use as little memory as possible */
+ {
+ int nextWidth= newwidth/2;
+ int nextHeight= newheight/2;
+ if (nextWidth < 1) nextWidth= 1;
+ if (nextHeight < 1) nextHeight= 1;
+
+ memreq = image_size(nextWidth, nextHeight, format, type);
+ }
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memreq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memreq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memreq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memreq);
+ break;
+ default:
+ return GLU_INVALID_ENUM;
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ }
+ /* level userLevel is in srcImage; nothing saved yet */
+ level = userLevel;
+ }
+
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ if (baseLevel <= level && level <= maxLevel) {
+ glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
+ format, type, (void *)srcImage);
+ }
+
+ level++; /* update current level for the loop */
+ for (; level <= levels; level++) {
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ halveImage_ubyte(cmpts, newwidth, newheight,
+ (GLubyte *)srcImage, (GLubyte *)dstImage, element_size,
+ rowsize, group_size);
+ break;
+ case GL_BYTE:
+ halveImage_byte(cmpts, newwidth, newheight,
+ (GLbyte *)srcImage, (GLbyte *)dstImage, element_size,
+ rowsize, group_size);
+ break;
+ case GL_UNSIGNED_SHORT:
+ halveImage_ushort(cmpts, newwidth, newheight,
+ (GLushort *)srcImage, (GLushort *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_SHORT:
+ halveImage_short(cmpts, newwidth, newheight,
+ (GLshort *)srcImage, (GLshort *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT:
+ halveImage_uint(cmpts, newwidth, newheight,
+ (GLuint *)srcImage, (GLuint *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_INT:
+ halveImage_int(cmpts, newwidth, newheight,
+ (GLint *)srcImage, (GLint *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_FLOAT:
+ halveImage_float(cmpts, newwidth, newheight,
+ (GLfloat *)srcImage, (GLfloat *)dstImage, element_size,
+ rowsize, group_size, myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ halveImagePackedPixel(3,extract332,shove332,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ halveImagePackedPixel(3,extract233rev,shove233rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ halveImagePackedPixel(3,extract565,shove565,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ halveImagePackedPixel(3,extract565rev,shove565rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ halveImagePackedPixel(4,extract4444,shove4444,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ halveImagePackedPixel(4,extract4444rev,shove4444rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ halveImagePackedPixel(4,extract5551,shove5551,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ halveImagePackedPixel(4,extract1555rev,shove1555rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ halveImagePackedPixel(4,extract8888,shove8888,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ halveImagePackedPixel(4,extract8888rev,shove8888rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ halveImagePackedPixel(4,extract1010102,shove1010102,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
+ newwidth,newheight,
+ srcImage,dstImage,element_size,rowsize,
+ myswap_bytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+
+ if (newwidth > 1) { newwidth /= 2; rowsize /= 2;}
+ if (newheight > 1) newheight /= 2;
+ {
+ /* compute amount to pad per row, if any */
+ int rowPad= rowsize % psm.unpack_alignment;
+
+ /* should row be padded? */
+ if (rowPad == 0) { /* nope, row should not be padded */
+ /* call tex image with srcImage untouched since it's not padded */
+ if (baseLevel <= level && level <= maxLevel) {
+ glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
+ format, type, (void *) srcImage);
+ }
+ }
+ else { /* yes, row should be padded */
+ /* compute length of new row in bytes, including padding */
+ int newRowLength= rowsize + psm.unpack_alignment - rowPad;
+ int ii; unsigned char *dstTrav, *srcTrav; /* indices for copying */
+
+ /* allocate new image for mipmap of size newRowLength x newheight */
+ void *newMipmapImage= malloc((size_t) (newRowLength*newheight));
+ if (newMipmapImage == NULL) {
+ /* out of memory so return */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ /* copy image from srcImage into newMipmapImage by rows */
+ for (ii= 0,
+ dstTrav= (unsigned char *) newMipmapImage,
+ srcTrav= (unsigned char *) srcImage;
+ ii< newheight;
+ ii++,
+ dstTrav+= newRowLength, /* make sure the correct distance... */
+ srcTrav+= rowsize) { /* ...is skipped */
+ memcpy(dstTrav,srcTrav,rowsize);
+ /* note that the pad bytes are not visited and will contain
+ * garbage, which is ok.
+ */
+ }
+
+ /* ...and use this new image for mipmapping instead */
+ if (baseLevel <= level && level <= maxLevel) {
+ glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
+ format, type, newMipmapImage);
+ }
+ free(newMipmapImage); /* don't forget to free it! */
+ } /* else */
+ }
+ } /* for level */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+
+ free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
+ if (dstImage) { /* if it's non-rectangular and only 1 level */
+ free(dstImage);
+ }
+ return 0;
+} /* gluBuild2DMipmapLevelsCore() */
+
+GLint GLAPIENTRY
+gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint userLevel, GLint baseLevel, GLint maxLevel,
+ const void *data)
+{
+ int level, levels;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1 || height < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ levels = computeLog(width);
+ level = computeLog(height);
+ if (level > levels) levels=level;
+
+ levels+= userLevel;
+ if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
+ return GLU_INVALID_VALUE;
+
+ return gluBuild2DMipmapLevelsCore(target, internalFormat,
+ width, height,
+ width, height,
+ format, type,
+ userLevel, baseLevel, maxLevel,
+ data);
+} /* gluBuild2DMipmapLevels() */
+
+GLint GLAPIENTRY
+gluBuild2DMipmaps(GLenum target, GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const void *data)
+{
+ GLint widthPowerOf2, heightPowerOf2;
+ int level, levels;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1 || height < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ closestFit(target,width,height,internalFormat,format,type,
+ &widthPowerOf2,&heightPowerOf2);
+
+ levels = computeLog(widthPowerOf2);
+ level = computeLog(heightPowerOf2);
+ if (level > levels) levels=level;
+
+ return gluBuild2DMipmapLevelsCore(target,internalFormat,
+ width, height,
+ widthPowerOf2,heightPowerOf2,
+ format,type,
+ 0,0,levels,data);
+} /* gluBuild2DMipmaps() */
+
+#if 0
+/*
+** This routine is for the limited case in which
+** type == GL_UNSIGNED_BYTE && format != index &&
+** unpack_alignment = 1 && unpack_swap_bytes == false
+**
+** so all of the work data can be kept as ubytes instead of shorts.
+*/
+static int fastBuild2DMipmaps(const PixelStorageModes *psm,
+ GLenum target, GLint components, GLint width,
+ GLint height, GLenum format,
+ GLenum type, void *data)
+{
+ GLint newwidth, newheight;
+ GLint level, levels;
+ GLubyte *newImage;
+ GLint newImage_width;
+ GLint newImage_height;
+ GLubyte *otherImage;
+ GLubyte *imageTemp;
+ GLint memreq;
+ GLint cmpts;
+
+
+#if 0
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
+ newwidth = nearestPower(width);
+ if (newwidth > maxsize) newwidth = maxsize;
+ newheight = nearestPower(height);
+ if (newheight > maxsize) newheight = maxsize;
+#else
+ closestFit(target,width,height,components,format,type,
+ &newwidth,&newheight);
+#endif
+ levels = computeLog(newwidth);
+ level = computeLog(newheight);
+ if (level > levels) levels=level;
+
+ cmpts = elements_per_group(format,type);
+
+ otherImage = NULL;
+ /**
+ ** No need to copy the user data if its in the packed correctly.
+ ** Make sure that later routines don't change that data.
+ */
+ if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
+ newImage = (GLubyte *)data;
+ newImage_width = width;
+ newImage_height = height;
+ } else {
+ GLint rowsize;
+ GLint groups_per_line;
+ GLint elements_per_line;
+ const GLubyte *start;
+ const GLubyte *iter;
+ GLubyte *iter2;
+ GLint i, j;
+
+ newImage = (GLubyte *)
+ malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
+ newImage_width = width;
+ newImage_height = height;
+ if (newImage == NULL) {
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ /*
+ ** Abbreviated version of fill_image for this restricted case.
+ */
+ if (psm->unpack_row_length > 0) {
+ groups_per_line = psm->unpack_row_length;
+ } else {
+ groups_per_line = width;
+ }
+ rowsize = groups_per_line * cmpts;
+ elements_per_line = width * cmpts;
+ start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
+ psm->unpack_skip_pixels * cmpts;
+ iter2 = newImage;
+
+ for (i = 0; i < height; i++) {
+ iter = start;
+ for (j = 0; j < elements_per_line; j++) {
+ *iter2 = *iter;
+ iter++;
+ iter2++;
+ }
+ start += rowsize;
+ }
+ }
+
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+
+ for (level = 0; level <= levels; level++) {
+ if (newImage_width == newwidth && newImage_height == newheight) {
+ /* Use newImage for this level */
+ glTexImage2D(target, level, components, newImage_width,
+ newImage_height, 0, format, GL_UNSIGNED_BYTE,
+ (void *) newImage);
+ } else {
+ if (otherImage == NULL) {
+ memreq =
+ image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
+ otherImage = (GLubyte *) malloc(memreq);
+ if (otherImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
+ return GLU_OUT_OF_MEMORY;
+ }
+ }
+/*
+ scale_internal_ubyte(cmpts, newImage_width, newImage_height,
+ newImage, newwidth, newheight, otherImage);
+*/
+ /* Swap newImage and otherImage */
+ imageTemp = otherImage;
+ otherImage = newImage;
+ newImage = imageTemp;
+
+ newImage_width = newwidth;
+ newImage_height = newheight;
+ glTexImage2D(target, level, components, newImage_width,
+ newImage_height, 0, format, GL_UNSIGNED_BYTE,
+ (void *) newImage);
+ }
+ if (newwidth > 1) newwidth /= 2;
+ if (newheight > 1) newheight /= 2;
+ }
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
+
+ if (newImage != (const GLubyte *)data) {
+ free((GLbyte *) newImage);
+ }
+ if (otherImage && otherImage != (const GLubyte *)data) {
+ free((GLbyte *) otherImage);
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Utility Routines
+ */
+static GLint elements_per_group(GLenum format, GLenum type)
+{
+ /*
+ * Return the number of elements per group of a specified format
+ */
+
+ /* If the type is packedpixels then answer is 1 (ignore format) */
+ if (type == GL_UNSIGNED_BYTE_3_3_2 ||
+ type == GL_UNSIGNED_BYTE_2_3_3_REV ||
+ type == GL_UNSIGNED_SHORT_5_6_5 ||
+ type == GL_UNSIGNED_SHORT_5_6_5_REV ||
+ type == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ type == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ type == GL_UNSIGNED_INT_8_8_8_8 ||
+ type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ type == GL_UNSIGNED_INT_10_10_10_2 ||
+ type == GL_UNSIGNED_INT_2_10_10_10_REV) {
+ return 1;
+ }
+
+ /* Types are not packed pixels, so get elements per group */
+ switch(format) {
+ case GL_RGB:
+ case GL_BGR:
+ return 3;
+ case GL_LUMINANCE_ALPHA:
+ return 2;
+ case GL_RGBA:
+ case GL_BGRA:
+ return 4;
+ default:
+ return 1;
+ }
+}
+
+static GLfloat bytes_per_element(GLenum type)
+{
+ /*
+ * Return the number of bytes per element, based on the element type
+ */
+ switch(type) {
+ case GL_BITMAP:
+ return 1.0 / 8.0;
+ case GL_UNSIGNED_SHORT:
+ return(sizeof(GLushort));
+ case GL_SHORT:
+ return(sizeof(GLshort));
+ case GL_UNSIGNED_BYTE:
+ return(sizeof(GLubyte));
+ case GL_BYTE:
+ return(sizeof(GLbyte));
+ case GL_INT:
+ return(sizeof(GLint));
+ case GL_UNSIGNED_INT:
+ return(sizeof(GLuint));
+ case GL_FLOAT:
+ return(sizeof(GLfloat));
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ return(sizeof(GLubyte));
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ return(sizeof(GLushort));
+ 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(sizeof(GLuint));
+ default:
+ return 4;
+ }
+}
+
+static GLint is_index(GLenum format)
+{
+ return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
+}
+
+/*
+** Compute memory required for internal packed array of data of given type
+** and format.
+*/
+static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
+{
+ int bytes_per_row;
+ int components;
+
+assert(width > 0);
+assert(height > 0);
+ components = elements_per_group(format,type);
+ if (type == GL_BITMAP) {
+ bytes_per_row = (width + 7) / 8;
+ } else {
+ bytes_per_row = bytes_per_element(type) * width;
+ }
+ return bytes_per_row * height * components;
+}
+
+/*
+** Extract array from user's data applying all pixel store modes.
+** The internal format used is an array of unsigned shorts.
+*/
+static void fill_image(const PixelStorageModes *psm,
+ GLint width, GLint height, GLenum format,
+ GLenum type, GLboolean index_format,
+ const void *userdata, GLushort *newimage)
+{
+ GLint components;
+ GLint element_size;
+ GLint rowsize;
+ GLint padding;
+ GLint groups_per_line;
+ GLint group_size;
+ GLint elements_per_line;
+ const GLubyte *start;
+ const GLubyte *iter;
+ GLushort *iter2;
+ GLint i, j, k;
+ GLint myswap_bytes;
+
+ myswap_bytes = psm->unpack_swap_bytes;
+ components = elements_per_group(format,type);
+ if (psm->unpack_row_length > 0) {
+ groups_per_line = psm->unpack_row_length;
+ } else {
+ groups_per_line = width;
+ }
+
+ /* All formats except GL_BITMAP fall out trivially */
+ if (type == GL_BITMAP) {
+ GLint bit_offset;
+ GLint current_bit;
+
+ rowsize = (groups_per_line * components + 7) / 8;
+ padding = (rowsize % psm->unpack_alignment);
+ if (padding) {
+ rowsize += psm->unpack_alignment - padding;
+ }
+ start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
+ (psm->unpack_skip_pixels * components / 8);
+ elements_per_line = width * components;
+ iter2 = newimage;
+ for (i = 0; i < height; i++) {
+ iter = start;
+ bit_offset = (psm->unpack_skip_pixels * components) % 8;
+ for (j = 0; j < elements_per_line; j++) {
+ /* Retrieve bit */
+ if (psm->unpack_lsb_first) {
+ current_bit = iter[0] & (1 << bit_offset);
+ } else {
+ current_bit = iter[0] & (1 << (7 - bit_offset));
+ }
+ if (current_bit) {
+ if (index_format) {
+ *iter2 = 1;
+ } else {
+ *iter2 = 65535;
+ }
+ } else {
+ *iter2 = 0;
+ }
+ bit_offset++;
+ if (bit_offset == 8) {
+ bit_offset = 0;
+ iter++;
+ }
+ iter2++;
+ }
+ start += rowsize;
+ }
+ } else {
+ element_size = bytes_per_element(type);
+ group_size = element_size * components;
+ if (element_size == 1) myswap_bytes = 0;
+
+ rowsize = groups_per_line * group_size;
+ padding = (rowsize % psm->unpack_alignment);
+ if (padding) {
+ rowsize += psm->unpack_alignment - padding;
+ }
+ start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
+ psm->unpack_skip_pixels * group_size;
+ elements_per_line = width * components;
+
+ iter2 = newimage;
+ for (i = 0; i < height; i++) {
+ iter = start;
+ for (j = 0; j < elements_per_line; j++) {
+ Type_Widget widget;
+ float extractComponents[4];
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE_3_3_2:
+ extract332(0,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ extract233rev(0,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (index_format) {
+ *iter2++ = *iter;
+ } else {
+ *iter2++ = (*iter) * 257;
+ }
+ break;
+ case GL_BYTE:
+ if (index_format) {
+ *iter2++ = *((const GLbyte *) iter);
+ } else {
+ /* rough approx */
+ *iter2++ = (*((const GLbyte *) iter)) * 516;
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ extract565(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ extract565rev(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ extract4444(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ extract4444rev(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ extract5551(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ extract1555rev(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ if (myswap_bytes) {
+ widget.ub[0] = iter[1];
+ widget.ub[1] = iter[0];
+ } else {
+ widget.ub[0] = iter[0];
+ widget.ub[1] = iter[1];
+ }
+ if (type == GL_SHORT) {
+ if (index_format) {
+ *iter2++ = widget.s[0];
+ } else {
+ /* rough approx */
+ *iter2++ = widget.s[0]*2;
+ }
+ } else {
+ *iter2++ = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ extract8888(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ extract8888rev(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ extract1010102(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ extract2101010rev(myswap_bytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ if (myswap_bytes) {
+ widget.ub[0] = iter[3];
+ widget.ub[1] = iter[2];
+ widget.ub[2] = iter[1];
+ widget.ub[3] = iter[0];
+ } else {
+ widget.ub[0] = iter[0];
+ widget.ub[1] = iter[1];
+ widget.ub[2] = iter[2];
+ widget.ub[3] = iter[3];
+ }
+ if (type == GL_FLOAT) {
+ if (index_format) {
+ *iter2++ = widget.f;
+ } else {
+ *iter2++ = 65535 * widget.f;
+ }
+ } else if (type == GL_UNSIGNED_INT) {
+ if (index_format) {
+ *iter2++ = widget.ui;
+ } else {
+ *iter2++ = widget.ui >> 16;
+ }
+ } else {
+ if (index_format) {
+ *iter2++ = widget.i;
+ } else {
+ *iter2++ = widget.i >> 15;
+ }
+ }
+ break;
+ }
+ iter += element_size;
+ } /* for j */
+ start += rowsize;
+#if 1
+ /* want 'iter' pointing at start, not within, row for assertion
+ * purposes
+ */
+ iter= start;
+#endif
+ } /* for i */
+
+ /* iterators should be one byte past end */
+ if (!isTypePackedPixel(type)) {
+ assert(iter2 == &newimage[width*height*components]);
+ }
+ else {
+ assert(iter2 == &newimage[width*height*
+ elements_per_group(format,0)]);
+ }
+ assert( iter == &((const GLubyte *)userdata)[rowsize*height +
+ psm->unpack_skip_rows * rowsize +
+ psm->unpack_skip_pixels * group_size] );
+
+ } /* else */
+} /* fill_image() */
+
+/*
+** Insert array into user's data applying all pixel store modes.
+** The internal format is an array of unsigned shorts.
+** empty_image() because it is the opposite of fill_image().
+*/
+static void empty_image(const PixelStorageModes *psm,
+ GLint width, GLint height, GLenum format,
+ GLenum type, GLboolean index_format,
+ const GLushort *oldimage, void *userdata)
+{
+ GLint components;
+ GLint element_size;
+ GLint rowsize;
+ GLint padding;
+ GLint groups_per_line;
+ GLint group_size;
+ GLint elements_per_line;
+ GLubyte *start;
+ GLubyte *iter;
+ const GLushort *iter2;
+ GLint i, j, k;
+ GLint myswap_bytes;
+
+ myswap_bytes = psm->pack_swap_bytes;
+ components = elements_per_group(format,type);
+ if (psm->pack_row_length > 0) {
+ groups_per_line = psm->pack_row_length;
+ } else {
+ groups_per_line = width;
+ }
+
+ /* All formats except GL_BITMAP fall out trivially */
+ if (type == GL_BITMAP) {
+ GLint bit_offset;
+ GLint current_bit;
+
+ rowsize = (groups_per_line * components + 7) / 8;
+ padding = (rowsize % psm->pack_alignment);
+ if (padding) {
+ rowsize += psm->pack_alignment - padding;
+ }
+ start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
+ (psm->pack_skip_pixels * components / 8);
+ elements_per_line = width * components;
+ iter2 = oldimage;
+ for (i = 0; i < height; i++) {
+ iter = start;
+ bit_offset = (psm->pack_skip_pixels * components) % 8;
+ for (j = 0; j < elements_per_line; j++) {
+ if (index_format) {
+ current_bit = iter2[0] & 1;
+ } else {
+ if (iter2[0] > 32767) {
+ current_bit = 1;
+ } else {
+ current_bit = 0;
+ }
+ }
+
+ if (current_bit) {
+ if (psm->pack_lsb_first) {
+ *iter |= (1 << bit_offset);
+ } else {
+ *iter |= (1 << (7 - bit_offset));
+ }
+ } else {
+ if (psm->pack_lsb_first) {
+ *iter &= ~(1 << bit_offset);
+ } else {
+ *iter &= ~(1 << (7 - bit_offset));
+ }
+ }
+
+ bit_offset++;
+ if (bit_offset == 8) {
+ bit_offset = 0;
+ iter++;
+ }
+ iter2++;
+ }
+ start += rowsize;
+ }
+ } else {
+ float shoveComponents[4];
+
+ element_size = bytes_per_element(type);
+ group_size = element_size * components;
+ if (element_size == 1) myswap_bytes = 0;
+
+ rowsize = groups_per_line * group_size;
+ padding = (rowsize % psm->pack_alignment);
+ if (padding) {
+ rowsize += psm->pack_alignment - padding;
+ }
+ start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
+ psm->pack_skip_pixels * group_size;
+ elements_per_line = width * components;
+
+ iter2 = oldimage;
+ for (i = 0; i < height; i++) {
+ iter = start;
+ for (j = 0; j < elements_per_line; j++) {
+ Type_Widget widget;
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE_3_3_2:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove332(shoveComponents,0,(void *)iter);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove233rev(shoveComponents,0,(void *)iter);
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (index_format) {
+ *iter = *iter2++;
+ } else {
+ *iter = *iter2++ >> 8;
+ }
+ break;
+ case GL_BYTE:
+ if (index_format) {
+ *((GLbyte *) iter) = *iter2++;
+ } else {
+ *((GLbyte *) iter) = *iter2++ >> 9;
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove565(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ }
+ else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove565rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ }
+ else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove4444(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove5551(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ if (type == GL_SHORT) {
+ if (index_format) {
+ widget.s[0] = *iter2++;
+ } else {
+ widget.s[0] = *iter2++ >> 1;
+ }
+ } else {
+ widget.us[0] = *iter2++;
+ }
+ if (myswap_bytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ iter[0] = widget.ub[0];
+ iter[1] = widget.ub[1];
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove8888(shoveComponents,0,(void *)&widget.ui);
+ if (myswap_bytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove8888rev(shoveComponents,0,(void *)&widget.ui);
+ if (myswap_bytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove1010102(shoveComponents,0,(void *)&widget.ui);
+ if (myswap_bytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove2101010rev(shoveComponents,0,(void *)&widget.ui);
+ if (myswap_bytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ if (type == GL_FLOAT) {
+ if (index_format) {
+ widget.f = *iter2++;
+ } else {
+ widget.f = *iter2++ / (float) 65535.0;
+ }
+ } else if (type == GL_UNSIGNED_INT) {
+ if (index_format) {
+ widget.ui = *iter2++;
+ } else {
+ widget.ui = (unsigned int) *iter2++ * 65537;
+ }
+ } else {
+ if (index_format) {
+ widget.i = *iter2++;
+ } else {
+ widget.i = ((unsigned int) *iter2++ * 65537)/2;
+ }
+ }
+ if (myswap_bytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ iter[0] = widget.ub[0];
+ iter[1] = widget.ub[1];
+ iter[2] = widget.ub[2];
+ iter[3] = widget.ub[3];
+ }
+ break;
+ }
+ iter += element_size;
+ } /* for j */
+ start += rowsize;
+#if 1
+ /* want 'iter' pointing at start, not within, row for assertion
+ * purposes
+ */
+ iter= start;
+#endif
+ } /* for i */
+
+ /* iterators should be one byte past end */
+ if (!isTypePackedPixel(type)) {
+ assert(iter2 == &oldimage[width*height*components]);
+ }
+ else {
+ assert(iter2 == &oldimage[width*height*
+ elements_per_group(format,0)]);
+ }
+ assert( iter == &((GLubyte *)userdata)[rowsize*height +
+ psm->pack_skip_rows * rowsize +
+ psm->pack_skip_pixels * group_size] );
+
+ } /* else */
+} /* empty_image() */
+
+/*--------------------------------------------------------------------------
+ * Decimation of packed pixel types
+ *--------------------------------------------------------------------------
+ */
+static void extract332(int isSwap,
+ const void *packedPixel, GLfloat extractComponents[])
+{
+ GLubyte ubyte= *(const GLubyte *)packedPixel;
+
+ isSwap= isSwap; /* turn off warnings */
+
+ /* 11100000 == 0xe0 */
+ /* 00011100 == 0x1c */
+ /* 00000011 == 0x03 */
+
+ extractComponents[0]= (float)((ubyte & 0xe0) >> 5) / 7.0;
+ extractComponents[1]= (float)((ubyte & 0x1c) >> 2) / 7.0; /* 7 = 2^3-1 */
+ extractComponents[2]= (float)((ubyte & 0x03) ) / 3.0; /* 3 = 2^2-1 */
+} /* extract332() */
+
+static void shove332(const GLfloat shoveComponents[],
+ int index, void *packedPixel)
+{
+ /* 11100000 == 0xe0 */
+ /* 00011100 == 0x1c */
+ /* 00000011 == 0x03 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLubyte *)packedPixel)[index] =
+ ((GLubyte)((shoveComponents[0] * 7)+0.5) << 5) & 0xe0;
+ ((GLubyte *)packedPixel)[index] |=
+ ((GLubyte)((shoveComponents[1] * 7)+0.5) << 2) & 0x1c;
+ ((GLubyte *)packedPixel)[index] |=
+ ((GLubyte)((shoveComponents[2] * 3)+0.5) ) & 0x03;
+} /* shove332() */
+
+static void extract233rev(int isSwap,
+ const void *packedPixel, GLfloat extractComponents[])
+{
+ GLubyte ubyte= *(const GLubyte *)packedPixel;
+
+ isSwap= isSwap; /* turn off warnings */
+
+ /* 0000,0111 == 0x07 */
+ /* 0011,1000 == 0x38 */
+ /* 1100,0000 == 0xC0 */
+
+ extractComponents[0]= (float)((ubyte & 0x07) ) / 7.0;
+ extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
+ extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
+} /* extract233rev() */
+
+static void shove233rev(const GLfloat shoveComponents[],
+ int index, void *packedPixel)
+{
+ /* 0000,0111 == 0x07 */
+ /* 0011,1000 == 0x38 */
+ /* 1100,0000 == 0xC0 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLubyte *)packedPixel)[index] =
+ ((GLubyte)((shoveComponents[0] * 7.0)+0.5) ) & 0x07;
+ ((GLubyte *)packedPixel)[index]|=
+ ((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
+ ((GLubyte *)packedPixel)[index]|=
+ ((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
+} /* shove233rev() */
+
+static void extract565(int isSwap,
+ const void *packedPixel, GLfloat extractComponents[])
+{
+ GLushort ushort= *(const GLushort *)packedPixel;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 11111000,00000000 == 0xf800 */
+ /* 00000111,11100000 == 0x07e0 */
+ /* 00000000,00011111 == 0x001f */
+
+ extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
+ extractComponents[1]=(float)((ushort & 0x07e0) >> 5) / 63.0;/* 63 = 2^6-1*/
+ extractComponents[2]=(float)((ushort & 0x001f) ) / 31.0;
+} /* extract565() */
+
+static void shove565(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 11111000,00000000 == 0xf800 */
+ /* 00000111,11100000 == 0x07e0 */
+ /* 00000000,00011111 == 0x001f */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 63)+0.5) << 5) & 0x07e0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 31)+0.5) ) & 0x001f;
+} /* shove565() */
+
+static void extract565rev(int isSwap,
+ const void *packedPixel, GLfloat extractComponents[])
+{
+ GLushort ushort= *(const GLushort *)packedPixel;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 00000000,00011111 == 0x001f */
+ /* 00000111,11100000 == 0x07e0 */
+ /* 11111000,00000000 == 0xf800 */
+
+ extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
+ extractComponents[1]= (float)((ushort & 0x07E0) >> 5) / 63.0;
+ extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
+} /* extract565rev() */
+
+static void shove565rev(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 00000000,00011111 == 0x001f */
+ /* 00000111,11100000 == 0x07e0 */
+ /* 11111000,00000000 == 0xf800 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 31.0)+0.5) ) & 0x001F;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 63.0)+0.5) << 5) & 0x07E0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
+} /* shove565rev() */
+
+static void extract4444(int isSwap,const void *packedPixel,
+ GLfloat extractComponents[])
+{
+ GLushort ushort;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 11110000,00000000 == 0xf000 */
+ /* 00001111,00000000 == 0x0f00 */
+ /* 00000000,11110000 == 0x00f0 */
+ /* 00000000,00001111 == 0x000f */
+
+ extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
+ extractComponents[1]= (float)((ushort & 0x0f00) >> 8) / 15.0;
+ extractComponents[2]= (float)((ushort & 0x00f0) >> 4) / 15.0;
+ extractComponents[3]= (float)((ushort & 0x000f) ) / 15.0;
+} /* extract4444() */
+
+static void shove4444(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 15)+0.5) << 8) & 0x0f00;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 15)+0.5) << 4) & 0x00f0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[3] * 15)+0.5) ) & 0x000f;
+} /* shove4444() */
+
+static void extract4444rev(int isSwap,const void *packedPixel,
+ GLfloat extractComponents[])
+{
+ GLushort ushort;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 00000000,00001111 == 0x000f */
+ /* 00000000,11110000 == 0x00f0 */
+ /* 00001111,00000000 == 0x0f00 */
+ /* 11110000,00000000 == 0xf000 */
+
+ /* 15 = 2^4-1 */
+ extractComponents[0]= (float)((ushort & 0x000F) ) / 15.0;
+ extractComponents[1]= (float)((ushort & 0x00F0) >> 4) / 15.0;
+ extractComponents[2]= (float)((ushort & 0x0F00) >> 8) / 15.0;
+ extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
+} /* extract4444rev() */
+
+static void shove4444rev(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 00000000,00001111 == 0x000f */
+ /* 00000000,11110000 == 0x00f0 */
+ /* 00001111,00000000 == 0x0f00 */
+ /* 11110000,00000000 == 0xf000 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 15)+0.5) ) & 0x000F;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 15)+0.5) << 4) & 0x00F0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 15)+0.5) << 8) & 0x0F00;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
+} /* shove4444rev() */
+
+static void extract5551(int isSwap,const void *packedPixel,
+ GLfloat extractComponents[])
+{
+ GLushort ushort;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 11111000,00000000 == 0xf800 */
+ /* 00000111,11000000 == 0x07c0 */
+ /* 00000000,00111110 == 0x003e */
+ /* 00000000,00000001 == 0x0001 */
+
+ extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
+ extractComponents[1]=(float)((ushort & 0x07c0) >> 6) / 31.0;
+ extractComponents[2]=(float)((ushort & 0x003e) >> 1) / 31.0;
+ extractComponents[3]=(float)((ushort & 0x0001) );
+} /* extract5551() */
+
+static void shove5551(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 11111000,00000000 == 0xf800 */
+ /* 00000111,11000000 == 0x07c0 */
+ /* 00000000,00111110 == 0x003e */
+ /* 00000000,00000001 == 0x0001 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 31)+0.5) << 6) & 0x07c0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 31)+0.5) << 1) & 0x003e;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[3])+0.5) ) & 0x0001;
+} /* shove5551() */
+
+static void extract1555rev(int isSwap,const void *packedPixel,
+ GLfloat extractComponents[])
+{
+ GLushort ushort;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(packedPixel);
+ }
+ else {
+ ushort= *(const GLushort *)packedPixel;
+ }
+
+ /* 00000000,00011111 == 0x001F */
+ /* 00000011,11100000 == 0x03E0 */
+ /* 01111100,00000000 == 0x7C00 */
+ /* 10000000,00000000 == 0x8000 */
+
+ /* 31 = 2^5-1 */
+ extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
+ extractComponents[1]= (float)((ushort & 0x03E0) >> 5) / 31.0;
+ extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
+ extractComponents[3]= (float)((ushort & 0x8000) >> 15);
+} /* extract1555rev() */
+
+static void shove1555rev(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 00000000,00011111 == 0x001F */
+ /* 00000011,11100000 == 0x03E0 */
+ /* 01111100,00000000 == 0x7C00 */
+ /* 10000000,00000000 == 0x8000 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLushort *)packedPixel)[index] =
+ ((GLushort)((shoveComponents[0] * 31)+0.5) ) & 0x001F;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[1] * 31)+0.5) << 5) & 0x03E0;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
+ ((GLushort *)packedPixel)[index]|=
+ ((GLushort)((shoveComponents[3])+0.5) << 15) & 0x8000;
+} /* shove1555rev() */
+
+static void extract8888(int isSwap,
+ const void *packedPixel, GLfloat extractComponents[])
+{
+ GLuint uint;
+
+ if (isSwap) {
+ uint= __GLU_SWAP_4_BYTES(packedPixel);
+ }
+ else {
+ uint= *(const GLuint *)packedPixel;
+ }
+
+ /* 11111111,00000000,00000000,00000000 == 0xff000000 */
+ /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
+ /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
+ /* 00000000,00000000,00000000,11111111 == 0x000000ff */
+
+ /* 255 = 2^8-1 */
+ extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
+ extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
+ extractComponents[2]= (float)((uint & 0x0000ff00) >> 8) / 255.0;
+ extractComponents[3]= (float)((uint & 0x000000ff) ) / 255.0;
+} /* extract8888() */
+
+static void shove8888(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 11111111,00000000,00000000,00000000 == 0xff000000 */
+ /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
+ /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
+ /* 00000000,00000000,00000000,11111111 == 0x000000ff */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLuint *)packedPixel)[index] =
+ ((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[2] * 255)+0.5) << 8) & 0x0000ff00;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[3] * 255)+0.5) ) & 0x000000ff;
+} /* shove8888() */
+
+static void extract8888rev(int isSwap,
+ const void *packedPixel,GLfloat extractComponents[])
+{
+ GLuint uint;
+
+ if (isSwap) {
+ uint= __GLU_SWAP_4_BYTES(packedPixel);
+ }
+ else {
+ uint= *(const GLuint *)packedPixel;
+ }
+
+ /* 00000000,00000000,00000000,11111111 == 0x000000ff */
+ /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
+ /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
+ /* 11111111,00000000,00000000,00000000 == 0xff000000 */
+
+ /* 255 = 2^8-1 */
+ extractComponents[0]= (float)((uint & 0x000000FF) ) / 255.0;
+ extractComponents[1]= (float)((uint & 0x0000FF00) >> 8) / 255.0;
+ extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
+ extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
+} /* extract8888rev() */
+
+static void shove8888rev(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 00000000,00000000,00000000,11111111 == 0x000000ff */
+ /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
+ /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
+ /* 11111111,00000000,00000000,00000000 == 0xff000000 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLuint *)packedPixel)[index] =
+ ((GLuint)((shoveComponents[0] * 255)+0.5) ) & 0x000000FF;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[1] * 255)+0.5) << 8) & 0x0000FF00;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
+} /* shove8888rev() */
+
+static void extract1010102(int isSwap,
+ const void *packedPixel,GLfloat extractComponents[])
+{
+ GLuint uint;
+
+ if (isSwap) {
+ uint= __GLU_SWAP_4_BYTES(packedPixel);
+ }
+ else {
+ uint= *(const GLuint *)packedPixel;
+ }
+
+ /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
+ /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
+ /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
+ /* 00000000,00000000,00000000,00000011 == 0x00000003 */
+
+ /* 1023 = 2^10-1 */
+ extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
+ extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
+ extractComponents[2]= (float)((uint & 0x00000ffc) >> 2) / 1023.0;
+ extractComponents[3]= (float)((uint & 0x00000003) ) / 3.0;
+} /* extract1010102() */
+
+static void shove1010102(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
+ /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
+ /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
+ /* 00000000,00000000,00000000,00000011 == 0x00000003 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLuint *)packedPixel)[index] =
+ ((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[2] * 1023)+0.5) << 2) & 0x00000ffc;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[3] * 3)+0.5) ) & 0x00000003;
+} /* shove1010102() */
+
+static void extract2101010rev(int isSwap,
+ const void *packedPixel,
+ GLfloat extractComponents[])
+{
+ GLuint uint;
+
+ if (isSwap) {
+ uint= __GLU_SWAP_4_BYTES(packedPixel);
+ }
+ else {
+ uint= *(const GLuint *)packedPixel;
+ }
+
+ /* 00000000,00000000,00000011,11111111 == 0x000003FF */
+ /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
+ /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
+ /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
+
+ /* 1023 = 2^10-1 */
+ extractComponents[0]= (float)((uint & 0x000003FF) ) / 1023.0;
+ extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
+ extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
+ extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
+ /* 3 = 2^2-1 */
+} /* extract2101010rev() */
+
+static void shove2101010rev(const GLfloat shoveComponents[],
+ int index,void *packedPixel)
+{
+ /* 00000000,00000000,00000011,11111111 == 0x000003FF */
+ /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
+ /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
+ /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
+
+ assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
+ assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
+ assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
+ assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
+
+ /* due to limited precision, need to round before shoving */
+ ((GLuint *)packedPixel)[index] =
+ ((GLuint)((shoveComponents[0] * 1023)+0.5) ) & 0x000003FF;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
+ ((GLuint *)packedPixel)[index]|=
+ ((GLuint)((shoveComponents[3] * 3)+0.5) << 30) & 0xC0000000;
+} /* shove2101010rev() */
+
+static void scaleInternalPackedPixel(int components,
+ void (*extractPackedPixel)
+ (int, const void *,GLfloat []),
+ void (*shovePackedPixel)
+ (const GLfloat [], int, void *),
+ GLint widthIn,GLint heightIn,
+ const void *dataIn,
+ GLint widthOut,GLint heightOut,
+ void *dataOut,
+ GLint pixelSizeInBytes,
+ GLint rowSizeInBytes,GLint isSwap)
+{
+ float convx;
+ float convy;
+ float percent;
+
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
+
+ float area;
+ int i,j,k,xindex;
+
+ const char *temp, *temp0;
+ int outindex;
+
+ int lowx_int, highx_int, lowy_int, highy_int;
+ float x_percent, y_percent;
+ float lowx_float, highx_float, lowy_float, highy_float;
+ float convy_float, convx_float;
+ int convy_int, convx_int;
+ int l, m;
+ const char *left, *right;
+
+ if (widthIn == widthOut*2 && heightIn == heightOut*2) {
+ halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
+ widthIn, heightIn, dataIn, dataOut,
+ pixelSizeInBytes,rowSizeInBytes,isSwap);
+ return;
+ }
+ convy = (float) heightIn/heightOut;
+ convx = (float) widthIn/widthOut;
+ convy_int = floor(convy);
+ convy_float = convy - convy_int;
+ convx_int = floor(convx);
+ convx_float = convx - convx_int;
+
+ area = convx * convy;
+
+ lowy_int = 0;
+ lowy_float = 0;
+ highy_int = convy_int;
+ highy_float = convy_float;
+
+ for (i = 0; i < heightOut; i++) {
+ lowx_int = 0;
+ lowx_float = 0;
+ highx_int = convx_int;
+ highx_float = convx_float;
+
+ for (j = 0; j < widthOut; j++) {
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy)
+ ** to (highx, highy) on input data into this pixel on output
+ ** data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+
+ /* calculate the value for pixels in the 1st row */
+ xindex = lowx_int*pixelSizeInBytes;
+ if((highy_int>lowy_int) && (highx_int>lowx_int)) {
+
+ y_percent = 1-lowy_float;
+ temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
+ percent = y_percent * (1-lowx_float);
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ left = temp;
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += pixelSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * y_percent;
+ }
+#endif
+ }
+ temp += pixelSizeInBytes;
+ right = temp;
+ percent = y_percent * highx_float;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+
+ /* calculate the value for pixels in the last row */
+
+ y_percent = highy_float;
+ percent = y_percent * (1-lowx_float);
+ temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ for(l = lowx_int+1; l < highx_int; l++) {
+ temp += pixelSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * y_percent;
+ }
+#endif
+
+ }
+ temp += pixelSizeInBytes;
+ percent = y_percent * highx_float;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+
+ /* calculate the value for pixels in the 1st and last column */
+ for(m = lowy_int+1; m < highy_int; m++) {
+ left += rowSizeInBytes;
+ right += rowSizeInBytes;
+#if 0
+ for (k = 0; k < components;
+ k++, left += element_size, right += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
+ __GLU_SWAP_2_BYTES(right) * highx_float;
+ } else {
+ totals[k] += *(const GLushort*)left * (1-lowx_float)
+ + *(const GLushort*)right * highx_float;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,left,extractTotals);
+ (*extractPackedPixel)(isSwap,right,extractMoreTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= (extractTotals[k]*(1-lowx_float) +
+ extractMoreTotals[k]*highx_float);
+ }
+#endif
+ }
+ } else if (highy_int > lowy_int) {
+ x_percent = highx_float - lowx_float;
+ percent = (1-lowy_float)*x_percent;
+ temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ for(m = lowy_int+1; m < highy_int; m++) {
+ temp += rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * x_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * x_percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * x_percent;
+ }
+#endif
+ }
+ percent = x_percent * highy_float;
+ temp += rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ } else if (highx_int > lowx_int) {
+ y_percent = highy_float - lowy_float;
+ percent = (1-lowx_float)*y_percent;
+ temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ for (l = lowx_int+1; l < highx_int; l++) {
+ temp += pixelSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] +=
+ __GLU_SWAP_2_BYTES(temp_index) * y_percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * y_percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * y_percent;
+ }
+#endif
+ }
+ temp += pixelSizeInBytes;
+ percent = y_percent * highx_float;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ } else {
+ percent = (highy_float-lowy_float)*(highx_float-lowx_float);
+ temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
+ } else {
+ totals[k] += *(const GLushort*)temp_index * percent;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k] * percent;
+ }
+#endif
+ }
+
+ /* this is for the pixels in the body */
+ temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
+ for (m = lowy_int+1; m < highy_int; m++) {
+ temp = temp0;
+ for(l = lowx_int+1; l < highx_int; l++) {
+#if 0
+ for (k = 0, temp_index = temp; k < components;
+ k++, temp_index += element_size) {
+ if (myswap_bytes) {
+ totals[k] += __GLU_SWAP_2_BYTES(temp_index);
+ } else {
+ totals[k] += *(const GLushort*)temp_index;
+ }
+ }
+#else
+ (*extractPackedPixel)(isSwap,temp,extractTotals);
+ for (k = 0; k < components; k++) {
+ totals[k]+= extractTotals[k];
+ }
+#endif
+ temp += pixelSizeInBytes;
+ }
+ temp0 += rowSizeInBytes;
+ }
+
+ outindex = (j + (i * widthOut)); /* * (components == 1) */
+#if 0
+ for (k = 0; k < components; k++) {
+ dataout[outindex + k] = totals[k]/area;
+ /*printf("totals[%d] = %f\n", k, totals[k]);*/
+ }
+#else
+ for (k = 0; k < components; k++) {
+ shoveTotals[k]= totals[k]/area;
+ }
+ (*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
+#endif
+ lowx_int = highx_int;
+ lowx_float = highx_float;
+ highx_int += convx_int;
+ highx_float += convx_float;
+ if(highx_float > 1) {
+ highx_float -= 1.0;
+ highx_int++;
+ }
+ }
+ lowy_int = highy_int;
+ lowy_float = highy_float;
+ highy_int += convy_int;
+ highy_float += convy_float;
+ if(highy_float > 1) {
+ highy_float -= 1.0;
+ highy_int++;
+ }
+ }
+
+ assert(outindex == (widthOut*heightOut - 1));
+} /* scaleInternalPackedPixel() */
+
+/* rowSizeInBytes is at least the width (in bytes) due to padding on
+ * inputs; not always equal. Output NEVER has row padding.
+ */
+static void halveImagePackedPixel(int components,
+ void (*extractPackedPixel)
+ (int, const void *,GLfloat []),
+ void (*shovePackedPixel)
+ (const GLfloat [],int, void *),
+ GLint width, GLint height,
+ const void *dataIn, void *dataOut,
+ GLint pixelSizeInBytes,
+ GLint rowSizeInBytes, GLint isSwap)
+{
+ /* handle case where there is only 1 column/row */
+ if (width == 1 || height == 1) {
+ assert(!(width == 1 && height == 1)); /* can't be 1x1 */
+ halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
+ width,height,dataIn,dataOut,pixelSizeInBytes,
+ rowSizeInBytes,isSwap);
+ return;
+ }
+
+ {
+ int ii, jj;
+
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
+ int outIndex= 0;
+
+ for (ii= 0; ii< halfHeight; ii++) {
+ for (jj= 0; jj< halfWidth; jj++) {
+#define BOX4 4
+ float totals[4]; /* 4 is maximum components */
+ float extractTotals[BOX4][4]; /* 4 is maximum components */
+ int cc;
+
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
+ &extractTotals[1][0]);
+ (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
+ &extractTotals[2][0]);
+ (*extractPackedPixel)(isSwap,
+ (src+rowSizeInBytes+pixelSizeInBytes),
+ &extractTotals[3][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 4 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED];
+ * totals[RED]/= 4.0;
+ */
+ for (kk = 0; kk < BOX4; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX4;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+ /* skip over to next square of 4 */
+ src+= pixelSizeInBytes + pixelSizeInBytes;
+ }
+ /* skip past pad bytes, if any, to get to next row */
+ src+= padBytes;
+
+ /* src is at beginning of a row here, but it's the second row of
+ * the square block of 4 pixels that we just worked on so we
+ * need to go one more row.
+ * i.e.,
+ * OO...
+ * here -->OO...
+ * but want -->OO...
+ * OO...
+ * ...
+ */
+ src+= rowSizeInBytes;
+ }
+
+ /* both pointers must reach one byte after the end */
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
+ assert(outIndex == halfWidth * halfHeight);
+ }
+} /* halveImagePackedPixel() */
+
+static void halve1DimagePackedPixel(int components,
+ void (*extractPackedPixel)
+ (int, const void *,GLfloat []),
+ void (*shovePackedPixel)
+ (const GLfloat [],int, void *),
+ GLint width, GLint height,
+ const void *dataIn, void *dataOut,
+ GLint pixelSizeInBytes,
+ GLint rowSizeInBytes, GLint isSwap)
+{
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ const char *src= (const char *) dataIn;
+ int jj;
+
+ assert(width == 1 || height == 1); /* must be 1D */
+ assert(width != height); /* can't be square */
+
+ if (height == 1) { /* 1 row */
+ int outIndex= 0;
+
+ assert(width != 1); /* widthxheight can't be 1x1 */
+ halfHeight= 1;
+
+ /* one horizontal row with possible pad bytes */
+
+ for (jj= 0; jj< halfWidth; jj++) {
+#define BOX2 2
+ float totals[4]; /* 4 is maximum components */
+ float extractTotals[BOX2][4]; /* 4 is maximum components */
+ int cc;
+
+ /* average two at a time, instead of four */
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
+ &extractTotals[1][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 2 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
+ * totals[RED]/= 2.0;
+ */
+ for (kk = 0; kk < BOX2; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX2;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+ /* skip over to next group of 2 */
+ src+= pixelSizeInBytes + pixelSizeInBytes;
+ }
+
+ {
+ int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
+ src+= padBytes; /* for assertion only */
+ }
+ assert(src == &((const char *)dataIn)[rowSizeInBytes]);
+ assert(outIndex == halfWidth * halfHeight);
+ }
+ else if (width == 1) { /* 1 column */
+ int outIndex= 0;
+
+ assert(height != 1); /* widthxheight can't be 1x1 */
+ halfWidth= 1;
+ /* one vertical column with possible pad bytes per row */
+ /* average two at a time */
+
+ for (jj= 0; jj< halfHeight; jj++) {
+#define BOX2 2
+ float totals[4]; /* 4 is maximum components */
+ float extractTotals[BOX2][4]; /* 4 is maximum components */
+ int cc;
+
+ /* average two at a time, instead of four */
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
+ &extractTotals[1][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 2 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
+ * totals[RED]/= 2.0;
+ */
+ for (kk = 0; kk < BOX2; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX2;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+ src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
+ }
+
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
+ assert(outIndex == halfWidth * halfHeight);
+ }
+} /* halve1DimagePackedPixel() */
+
+/*===========================================================================*/
+
+#ifdef RESOLVE_3D_TEXTURE_SUPPORT
+/*
+ * This section ensures that GLU 1.3 will load and run on
+ * a GL 1.1 implementation. It dynamically resolves the
+ * call to glTexImage3D() which might not be available.
+ * Or is it might be supported as an extension.
+ * Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
+ */
+
+typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+static TexImage3Dproc pTexImage3D = 0;
+
+#if !defined(_WIN32) && !defined(__WIN32__)
+# include <dlfcn.h>
+# include <sys/types.h>
+#else
+ WINGDIAPI PROC WINAPI wglGetProcAddress(LPCSTR);
+#endif
+
+static void gluTexImage3D( GLenum target, GLint level,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ if (!pTexImage3D) {
+#if defined(_WIN32) || defined(__WIN32__)
+ pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
+ if (!pTexImage3D)
+ pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
+#else
+ void *libHandle = dlopen("libgl.so", RTLD_LAZY);
+ pTexImage3D = TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
+ if (!pTexImage3D)
+ pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
+ dlclose(libHandle);
+#endif
+ }
+
+ /* Now call glTexImage3D */
+ if (pTexImage3D)
+ pTexImage3D(target, level, internalFormat, width, height,
+ depth, border, format, type, pixels);
+}
+
+#else
+
+/* Only bind to a GL 1.2 implementation: */
+#define gluTexImage3D glTexImage3D
+
+#endif
+
+static GLint imageSize3D(GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type)
+{
+ int components= elements_per_group(format,type);
+ int bytes_per_row= bytes_per_element(type) * width;
+
+assert(width > 0 && height > 0 && depth > 0);
+assert(type != GL_BITMAP);
+
+ return bytes_per_row * height * depth * components;
+} /* imageSize3D() */
+
+static void fillImage3D(const PixelStorageModes *psm,
+ GLint width, GLint height, GLint depth, GLenum format,
+ GLenum type, GLboolean indexFormat,
+ const void *userImage, GLushort *newImage)
+{
+ int myswapBytes;
+ int components;
+ int groupsPerLine;
+ int elementSize;
+ int groupSize;
+ int rowSize;
+ int padding;
+ int elementsPerLine;
+ int rowsPerImage;
+ int imageSize;
+ const GLubyte *start, *rowStart, *iter;
+ GLushort *iter2;
+ int ww, hh, dd, k;
+
+ myswapBytes= psm->unpack_swap_bytes;
+ components= elements_per_group(format,type);
+ if (psm->unpack_row_length > 0) {
+ groupsPerLine= psm->unpack_row_length;
+ }
+ else {
+ groupsPerLine= width;
+ }
+ elementSize= bytes_per_element(type);
+ groupSize= elementSize * components;
+ if (elementSize == 1) myswapBytes= 0;
+
+ /* 3dstuff begin */
+ if (psm->unpack_image_height > 0) {
+ rowsPerImage= psm->unpack_image_height;
+ }
+ else {
+ rowsPerImage= height;
+ }
+ /* 3dstuff end */
+
+ rowSize= groupsPerLine * groupSize;
+ padding= rowSize % psm->unpack_alignment;
+ if (padding) {
+ rowSize+= psm->unpack_alignment - padding;
+ }
+
+ imageSize= rowsPerImage * rowSize; /* 3dstuff */
+
+ start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
+ psm->unpack_skip_pixels * groupSize +
+ /*3dstuff*/
+ psm->unpack_skip_images * imageSize;
+ elementsPerLine = width * components;
+
+ iter2= newImage;
+ for (dd= 0; dd < depth; dd++) {
+ rowStart= start;
+
+ for (hh= 0; hh < height; hh++) {
+ iter= rowStart;
+
+ for (ww= 0; ww < elementsPerLine; ww++) {
+ Type_Widget widget;
+ float extractComponents[4];
+
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ if (indexFormat) {
+ *iter2++ = *iter;
+ } else {
+ *iter2++ = (*iter) * 257;
+ }
+ break;
+ case GL_BYTE:
+ if (indexFormat) {
+ *iter2++ = *((const GLbyte *) iter);
+ } else {
+ /* rough approx */
+ *iter2++ = (*((const GLbyte *) iter)) * 516;
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ extract332(0,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ extract233rev(0,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ extract565(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ extract565rev(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 3; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ extract4444(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ extract4444rev(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ extract5551(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ extract1555rev(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ if (myswapBytes) {
+ widget.ub[0] = iter[1];
+ widget.ub[1] = iter[0];
+ } else {
+ widget.ub[0] = iter[0];
+ widget.ub[1] = iter[1];
+ }
+ if (type == GL_SHORT) {
+ if (indexFormat) {
+ *iter2++ = widget.s[0];
+ } else {
+ /* rough approx */
+ *iter2++ = widget.s[0]*2;
+ }
+ } else {
+ *iter2++ = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ extract8888(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ extract8888rev(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ extract1010102(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ extract2101010rev(myswapBytes,iter,extractComponents);
+ for (k = 0; k < 4; k++) {
+ *iter2++ = (GLushort)(extractComponents[k]*65535);
+ }
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ if (myswapBytes) {
+ widget.ub[0] = iter[3];
+ widget.ub[1] = iter[2];
+ widget.ub[2] = iter[1];
+ widget.ub[3] = iter[0];
+ } else {
+ widget.ub[0] = iter[0];
+ widget.ub[1] = iter[1];
+ widget.ub[2] = iter[2];
+ widget.ub[3] = iter[3];
+ }
+ if (type == GL_FLOAT) {
+ if (indexFormat) {
+ *iter2++ = widget.f;
+ } else {
+ *iter2++ = 65535 * widget.f;
+ }
+ } else if (type == GL_UNSIGNED_INT) {
+ if (indexFormat) {
+ *iter2++ = widget.ui;
+ } else {
+ *iter2++ = widget.ui >> 16;
+ }
+ } else {
+ if (indexFormat) {
+ *iter2++ = widget.i;
+ } else {
+ *iter2++ = widget.i >> 15;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ iter+= elementSize;
+ } /* for ww */
+ rowStart+= rowSize;
+
+ iter= rowStart; /* for assertion purposes */
+ } /* for hh */
+
+ start+= imageSize;
+ } /* for dd */
+
+ /* iterators should be one byte past end */
+ if (!isTypePackedPixel(type)) {
+ assert(iter2 == &newImage[width*height*depth*components]);
+ }
+ else {
+ assert(iter2 == &newImage[width*height*depth*
+ elements_per_group(format,0)]);
+ }
+ assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
+ psm->unpack_skip_rows * rowSize +
+ psm->unpack_skip_pixels * groupSize +
+ /*3dstuff*/
+ psm->unpack_skip_images * imageSize] );
+} /* fillImage3D () */
+
+static void scaleInternal3D(GLint components,
+ GLint widthIn, GLint heightIn, GLint depthIn,
+ const GLushort *dataIn,
+ GLint widthOut, GLint heightOut, GLint depthOut,
+ GLushort *dataOut)
+{
+ float x, lowx, highx, convx, halfconvx;
+ float y, lowy, highy, convy, halfconvy;
+ float z, lowz, highz, convz, halfconvz;
+ float xpercent,ypercent,zpercent;
+ float percent;
+ /* Max components in a format is 4, so... */
+ float totals[4];
+ float volume;
+ int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
+ int temp;
+
+ convz = (float) depthIn/depthOut;
+ convy = (float) heightIn/heightOut;
+ convx = (float) widthIn/widthOut;
+ halfconvx = convx/2;
+ halfconvy = convy/2;
+ halfconvz = convz/2;
+ for (d = 0; d < depthOut; d++) {
+ z = convz * (d+0.5);
+ if (depthIn > depthOut) {
+ highz = z + halfconvz;
+ lowz = z - halfconvz;
+ } else {
+ highz = z + 0.5;
+ lowz = z - 0.5;
+ }
+ for (i = 0; i < heightOut; i++) {
+ y = convy * (i+0.5);
+ if (heightIn > heightOut) {
+ highy = y + halfconvy;
+ lowy = y - halfconvy;
+ } else {
+ highy = y + 0.5;
+ lowy = y - 0.5;
+ }
+ for (j = 0; j < widthOut; j++) {
+ x = convx * (j+0.5);
+ if (widthIn > widthOut) {
+ highx = x + halfconvx;
+ lowx = x - halfconvx;
+ } else {
+ highx = x + 0.5;
+ lowx = x - 0.5;
+ }
+
+ /*
+ ** Ok, now apply box filter to box that goes from (lowx, lowy,
+ ** lowz) to (highx, highy, highz) on input data into this pixel
+ ** on output data.
+ */
+ totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
+ volume = 0.0;
+
+ z = lowz;
+ zint = floor(z);
+ while (z < highz) {
+ zindex = (zint + depthIn) % depthIn;
+ if (highz < zint+1) {
+ zpercent = highz - z;
+ } else {
+ zpercent = zint+1 - z;
+ }
+
+ y = lowy;
+ yint = floor(y);
+ while (y < highy) {
+ yindex = (yint + heightIn) % heightIn;
+ if (highy < yint+1) {
+ ypercent = highy - y;
+ } else {
+ ypercent = yint+1 - y;
+ }
+
+ x = lowx;
+ xint = floor(x);
+
+ while (x < highx) {
+ xindex = (xint + widthIn) % widthIn;
+ if (highx < xint+1) {
+ xpercent = highx - x;
+ } else {
+ xpercent = xint+1 - x;
+ }
+
+ percent = xpercent * ypercent * zpercent;
+ volume += percent;
+
+ temp = (xindex + (yindex*widthIn) +
+ (zindex*widthIn*heightIn)) * components;
+ for (k = 0; k < components; k++) {
+ assert(0 <= (temp+k) &&
+ (temp+k) <
+ (widthIn*heightIn*depthIn*components));
+ totals[k] += dataIn[temp + k] * percent;
+ }
+
+ xint++;
+ x = xint;
+ } /* while x */
+
+ yint++;
+ y = yint;
+ } /* while y */
+
+ zint++;
+ z = zint;
+ } /* while z */
+
+ temp = (j + (i * widthOut) +
+ (d*widthOut*heightOut)) * components;
+ for (k = 0; k < components; k++) {
+ /* totals[] should be rounded in the case of enlarging an
+ * RGB ramp when the type is 332 or 4444
+ */
+ assert(0 <= (temp+k) &&
+ (temp+k) < (widthOut*heightOut*depthOut*components));
+ dataOut[temp + k] = (totals[k]+0.5)/volume;
+ }
+ } /* for j */
+ } /* for i */
+ } /* for d */
+} /* scaleInternal3D() */
+
+static void emptyImage3D(const PixelStorageModes *psm,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, GLboolean indexFormat,
+ const GLushort *oldImage, void *userImage)
+{
+ int myswapBytes;
+ int components;
+ int groupsPerLine;
+ int elementSize;
+ int groupSize;
+ int rowSize;
+ int padding;
+ GLubyte *start, *rowStart, *iter;
+ int elementsPerLine;
+ const GLushort *iter2;
+ int ii, jj, dd, k;
+ int rowsPerImage;
+ int imageSize;
+
+ myswapBytes= psm->pack_swap_bytes;
+ components = elements_per_group(format,type);
+ if (psm->pack_row_length > 0) {
+ groupsPerLine = psm->pack_row_length;
+ }
+ else {
+ groupsPerLine = width;
+ }
+
+ elementSize= bytes_per_element(type);
+ groupSize= elementSize * components;
+ if (elementSize == 1) myswapBytes= 0;
+
+ /* 3dstuff begin */
+ if (psm->pack_image_height > 0) {
+ rowsPerImage= psm->pack_image_height;
+ }
+ else {
+ rowsPerImage= height;
+ }
+
+ /* 3dstuff end */
+
+ rowSize = groupsPerLine * groupSize;
+ padding = rowSize % psm->pack_alignment;
+ if (padding) {
+ rowSize+= psm->pack_alignment - padding;
+ }
+
+ imageSize= rowsPerImage * rowSize; /* 3dstuff */
+
+ start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
+ psm->pack_skip_pixels * groupSize +
+ /*3dstuff*/
+ psm->pack_skip_images * imageSize;
+ elementsPerLine= width * components;
+
+ iter2 = oldImage;
+ for (dd= 0; dd < depth; dd++) {
+ rowStart= start;
+
+ for (ii= 0; ii< height; ii++) {
+ iter = rowStart;
+
+ for (jj = 0; jj < elementsPerLine; jj++) {
+ Type_Widget widget;
+ float shoveComponents[4];
+
+ switch(type){
+ case GL_UNSIGNED_BYTE:
+ if (indexFormat) {
+ *iter = *iter2++;
+ } else {
+ *iter = *iter2++ >> 8;
+ }
+ break;
+ case GL_BYTE:
+ if (indexFormat) {
+ *((GLbyte *) iter) = *iter2++;
+ } else {
+ *((GLbyte *) iter) = *iter2++ >> 9;
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove332(shoveComponents,0,(void *)iter);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove233rev(shoveComponents,0,(void *)iter);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove565(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ }
+ else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ for (k = 0; k < 3; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove565rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ }
+ else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove4444(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove5551(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ *(GLushort *)iter = widget.us[0];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ if (type == GL_SHORT) {
+ if (indexFormat) {
+ widget.s[0] = *iter2++;
+ } else {
+ widget.s[0] = *iter2++ >> 1;
+ }
+ } else {
+ widget.us[0] = *iter2++;
+ }
+ if (myswapBytes) {
+ iter[0] = widget.ub[1];
+ iter[1] = widget.ub[0];
+ } else {
+ iter[0] = widget.ub[0];
+ iter[1] = widget.ub[1];
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove8888(shoveComponents,0,(void *)&widget.ui);
+ if (myswapBytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove8888rev(shoveComponents,0,(void *)&widget.ui);
+ if (myswapBytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove1010102(shoveComponents,0,(void *)&widget.ui);
+ if (myswapBytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ for (k = 0; k < 4; k++) {
+ shoveComponents[k]= *iter2++ / 65535.0;
+ }
+ shove2101010rev(shoveComponents,0,(void *)&widget.ui);
+ if (myswapBytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ *(GLuint *)iter= widget.ui;
+ }
+ break;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ if (type == GL_FLOAT) {
+ if (indexFormat) {
+ widget.f = *iter2++;
+ } else {
+ widget.f = *iter2++ / (float) 65535.0;
+ }
+ } else if (type == GL_UNSIGNED_INT) {
+ if (indexFormat) {
+ widget.ui = *iter2++;
+ } else {
+ widget.ui = (unsigned int) *iter2++ * 65537;
+ }
+ } else {
+ if (indexFormat) {
+ widget.i = *iter2++;
+ } else {
+ widget.i = ((unsigned int) *iter2++ * 65537)/2;
+ }
+ }
+ if (myswapBytes) {
+ iter[3] = widget.ub[0];
+ iter[2] = widget.ub[1];
+ iter[1] = widget.ub[2];
+ iter[0] = widget.ub[3];
+ } else {
+ iter[0] = widget.ub[0];
+ iter[1] = widget.ub[1];
+ iter[2] = widget.ub[2];
+ iter[3] = widget.ub[3];
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ iter+= elementSize;
+ } /* for jj */
+
+ rowStart+= rowSize;
+ } /* for ii */
+
+ start+= imageSize;
+ } /* for dd */
+
+ /* iterators should be one byte past end */
+ if (!isTypePackedPixel(type)) {
+ assert(iter2 == &oldImage[width*height*depth*components]);
+ }
+ else {
+ assert(iter2 == &oldImage[width*height*depth*
+ elements_per_group(format,0)]);
+ }
+ assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
+ psm->unpack_skip_rows * rowSize +
+ psm->unpack_skip_pixels * groupSize +
+ /*3dstuff*/
+ psm->unpack_skip_images * imageSize] );
+} /* emptyImage3D() */
+
+static
+int gluScaleImage3D(GLenum format,
+ GLint widthIn, GLint heightIn, GLint depthIn,
+ GLenum typeIn, const void *dataIn,
+ GLint widthOut, GLint heightOut, GLint depthOut,
+ GLenum typeOut, void *dataOut)
+{
+ int components;
+ GLushort *beforeImage, *afterImage;
+ PixelStorageModes psm;
+
+ if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
+ widthOut == 0 || heightOut == 0 || depthOut == 0) {
+ return 0;
+ }
+
+ if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
+ widthOut < 0 || heightOut < 0 || depthOut < 0) {
+ return GLU_INVALID_VALUE;
+ }
+
+ if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
+ typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
+ return GLU_INVALID_ENUM;
+ }
+ if (!isLegalFormatForPackedPixelType(format, typeIn)) {
+ return GLU_INVALID_OPERATION;
+ }
+ if (!isLegalFormatForPackedPixelType(format, typeOut)) {
+ return GLU_INVALID_OPERATION;
+ }
+
+ beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
+ GL_UNSIGNED_SHORT));
+ afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
+ GL_UNSIGNED_SHORT));
+ if (beforeImage == NULL || afterImage == NULL) {
+ return GLU_OUT_OF_MEMORY;
+ }
+ retrieveStoreModes3D(&psm);
+
+ fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
+ dataIn, beforeImage);
+ components = elements_per_group(format,0);
+ scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
+ widthOut,heightOut,depthOut,afterImage);
+ emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
+ is_index(format),afterImage, dataOut);
+ free((void *) beforeImage);
+ free((void *) afterImage);
+
+ return 0;
+} /* gluScaleImage3D() */
+
+
+static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint *newWidth, GLint *newHeight, GLint *newDepth)
+{
+ GLint widthPowerOf2= nearestPower(width);
+ GLint heightPowerOf2= nearestPower(height);
+ GLint depthPowerOf2= nearestPower(depth);
+ GLint proxyWidth;
+
+ do {
+ /* compute level 1 width & height & depth, clamping each at 1 */
+ GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
+ widthPowerOf2 >> 1 :
+ widthPowerOf2;
+ GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
+ heightPowerOf2 >> 1 :
+ heightPowerOf2;
+ GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
+ depthPowerOf2 >> 1 :
+ depthPowerOf2;
+ GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
+ assert(widthAtLevelOne > 0);
+ assert(heightAtLevelOne > 0);
+ assert(depthAtLevelOne > 0);
+
+ /* does width x height x depth at level 1 & all their mipmaps fit? */
+ assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
+ gluTexImage3D(proxyTarget, 1, /* must be non-zero */
+ internalFormat,
+ widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
+ 0,format,type,NULL);
+ glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
+ /* does it fit??? */
+ if (proxyWidth == 0) { /* nope, so try again with these sizes */
+ if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
+ depthPowerOf2 == 1) {
+ *newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
+ return;
+ }
+ widthPowerOf2= widthAtLevelOne;
+ heightPowerOf2= heightAtLevelOne;
+ depthPowerOf2= depthAtLevelOne;
+ }
+ /* else it does fit */
+ } while (proxyWidth == 0);
+ /* loop must terminate! */
+
+ /* return the width & height at level 0 that fits */
+ *newWidth= widthPowerOf2;
+ *newHeight= heightPowerOf2;
+ *newDepth= depthPowerOf2;
+/*printf("Proxy Textures\n");*/
+} /* closestFit3D() */
+
+static void halveImagePackedPixelSlice(int components,
+ void (*extractPackedPixel)
+ (int, const void *,GLfloat []),
+ void (*shovePackedPixel)
+ (const GLfloat [],int, void *),
+ GLint width, GLint height, GLint depth,
+ const void *dataIn, void *dataOut,
+ GLint pixelSizeInBytes,
+ GLint rowSizeInBytes,
+ GLint imageSizeInBytes,
+ GLint isSwap)
+{
+ int ii, jj;
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ int halfDepth= depth / 2;
+ const char *src= (const char *)dataIn;
+ int outIndex= 0;
+
+ assert((width == 1 || height == 1) && depth >= 2);
+
+ if (width == height) { /* a 1-pixel column viewed from top */
+ assert(width == 1 && height == 1);
+ assert(depth >= 2);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ float totals[4];
+ float extractTotals[BOX2][4];
+ int cc;
+
+ (*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
+ &extractTotals[1][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* average 2 pixels since only a column */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
+ * totals[RED]/= 2.0;
+ */
+ for (kk = 0; kk < BOX2; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX2;
+ } /* for cc */
+
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+ outIndex++;
+ /* skip over to next group of 2 */
+ src+= imageSizeInBytes + imageSizeInBytes;
+ } /* for ii */
+ }
+ else if (height == 1) { /* horizontal slice viewed from top */
+ assert(width != 1);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ for (jj= 0; jj< halfWidth; jj++) {
+ float totals[4];
+ float extractTotals[BOX4][4];
+ int cc;
+
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
+ &extractTotals[1][0]);
+ (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
+ &extractTotals[2][0]);
+ (*extractPackedPixel)(isSwap,
+ (src+imageSizeInBytes+pixelSizeInBytes),
+ &extractTotals[3][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 4 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED];
+ * totals[RED]/= 4.0;
+ */
+ for (kk = 0; kk < BOX4; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX4;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+ /* skip over to next horizontal square of 4 */
+ src+= imageSizeInBytes + imageSizeInBytes;
+ }
+ }
+
+ /* assert() */
+ }
+ else if (width == 1) { /* vertical slice viewed from top */
+ assert(height != 1);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ for (jj= 0; jj< halfHeight; jj++) {
+ float totals[4];
+ float extractTotals[BOX4][4];
+ int cc;
+
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
+ &extractTotals[1][0]);
+ (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
+ &extractTotals[2][0]);
+ (*extractPackedPixel)(isSwap,
+ (src+imageSizeInBytes+rowSizeInBytes),
+ &extractTotals[3][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 4 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED];
+ * totals[RED]/= 4.0;
+ */
+ for (kk = 0; kk < BOX4; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX4;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+
+ /* skip over to next vertical square of 4 */
+ src+= imageSizeInBytes + imageSizeInBytes;
+ }
+ }
+ /* assert() */
+ }
+
+} /* halveImagePackedPixelSlice() */
+
+static void halveImagePackedPixel3D(int components,
+ void (*extractPackedPixel)
+ (int, const void *,GLfloat []),
+ void (*shovePackedPixel)
+ (const GLfloat [],int, void *),
+ GLint width, GLint height, GLint depth,
+ const void *dataIn, void *dataOut,
+ GLint pixelSizeInBytes,
+ GLint rowSizeInBytes,
+ GLint imageSizeInBytes,
+ GLint isSwap)
+{
+ if (depth == 1) {
+ assert(1 <= width && 1 <= height);
+
+ halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
+ width,height,dataIn,dataOut,pixelSizeInBytes,
+ rowSizeInBytes,isSwap);
+ return;
+ }
+ /* a horizontal or vertical slice viewed from top */
+ else if (width == 1 || height == 1) {
+ assert(1 <= depth);
+
+ halveImagePackedPixelSlice(components,
+ extractPackedPixel,shovePackedPixel,
+ width, height, depth, dataIn, dataOut,
+ pixelSizeInBytes, rowSizeInBytes,
+ imageSizeInBytes, isSwap);
+ return;
+ }
+ {
+ int ii, jj, dd;
+
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ int halfDepth= depth / 2;
+ const char *src= (const char *) dataIn;
+ int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
+ int outIndex= 0;
+
+ for (dd= 0; dd < halfDepth; dd++) {
+ for (ii= 0; ii< halfHeight; ii++) {
+ for (jj= 0; jj< halfWidth; jj++) {
+#define BOX8 8
+ float totals[4]; /* 4 is maximum components */
+ float extractTotals[BOX8][4]; /* 4 is maximum components */
+ int cc;
+
+ (*extractPackedPixel)(isSwap,src,
+ &extractTotals[0][0]);
+ (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
+ &extractTotals[1][0]);
+ (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
+ &extractTotals[2][0]);
+ (*extractPackedPixel)(isSwap,
+ (src+rowSizeInBytes+pixelSizeInBytes),
+ &extractTotals[3][0]);
+
+ (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
+ &extractTotals[4][0]);
+ (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
+ &extractTotals[5][0]);
+ (*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
+ &extractTotals[6][0]);
+ (*extractPackedPixel)(isSwap,
+ (src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
+ &extractTotals[7][0]);
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+
+ /* grab 8 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED]+
+ * extractTotals[4][RED]+extractTotals[5][RED]+
+ * extractTotals[6][RED]+extractTotals[7][RED];
+ * totals[RED]/= 8.0;
+ */
+ for (kk = 0; kk < BOX8; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (float)BOX8;
+ }
+ (*shovePackedPixel)(totals,outIndex,dataOut);
+
+ outIndex++;
+ /* skip over to next square of 4 */
+ src+= pixelSizeInBytes + pixelSizeInBytes;
+ }
+ /* skip past pad bytes, if any, to get to next row */
+ src+= padBytes;
+
+ /* src is at beginning of a row here, but it's the second row of
+ * the square block of 4 pixels that we just worked on so we
+ * need to go one more row.
+ * i.e.,
+ * OO...
+ * here -->OO...
+ * but want -->OO...
+ * OO...
+ * ...
+ */
+ src+= rowSizeInBytes;
+ }
+
+ src+= imageSizeInBytes;
+ } /* for dd */
+
+ /* both pointers must reach one byte after the end */
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
+ assert(outIndex == halfWidth * halfHeight * halfDepth);
+ } /* for dd */
+
+} /* halveImagePackedPixel3D() */
+
+static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei widthPowerOf2,
+ GLsizei heightPowerOf2,
+ GLsizei depthPowerOf2,
+ GLenum format, GLenum type,
+ GLint userLevel,
+ GLint baseLevel,GLint maxLevel,
+ const void *data)
+{
+ GLint newWidth, newHeight, newDepth;
+ GLint level, levels;
+ const void *usersImage;
+ void *srcImage, *dstImage;
+ __GLU_INIT_SWAP_IMAGE;
+ GLint memReq;
+ GLint cmpts;
+
+ GLint myswapBytes, groupsPerLine, elementSize, groupSize;
+ GLint rowsPerImage, imageSize;
+ GLint rowSize, padding;
+ PixelStorageModes psm;
+
+ assert(checkMipmapArgs(internalFormat,format,type) == 0);
+ assert(width >= 1 && height >= 1 && depth >= 1);
+ assert(type != GL_BITMAP);
+
+ srcImage = dstImage = NULL;
+
+ newWidth= widthPowerOf2;
+ newHeight= heightPowerOf2;
+ newDepth= depthPowerOf2;
+ levels = computeLog(newWidth);
+ level = computeLog(newHeight);
+ if (level > levels) levels=level;
+ level = computeLog(newDepth);
+ if (level > levels) levels=level;
+
+ levels+= userLevel;
+
+ retrieveStoreModes3D(&psm);
+ myswapBytes = psm.unpack_swap_bytes;
+ cmpts = elements_per_group(format,type);
+ if (psm.unpack_row_length > 0) {
+ groupsPerLine = psm.unpack_row_length;
+ } else {
+ groupsPerLine = width;
+ }
+
+ elementSize = bytes_per_element(type);
+ groupSize = elementSize * cmpts;
+ if (elementSize == 1) myswapBytes = 0;
+
+ /* 3dstuff begin */
+ if (psm.unpack_image_height > 0) {
+ rowsPerImage= psm.unpack_image_height;
+ }
+ else {
+ rowsPerImage= height;
+ }
+
+ /* 3dstuff end */
+ rowSize = groupsPerLine * groupSize;
+ padding = (rowSize % psm.unpack_alignment);
+ if (padding) {
+ rowSize += psm.unpack_alignment - padding;
+ }
+
+ imageSize= rowsPerImage * rowSize; /* 3dstuff */
+
+ usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
+ psm.unpack_skip_pixels * groupSize +
+ /* 3dstuff */
+ psm.unpack_skip_images * imageSize;
+
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
+
+ level = userLevel;
+
+ if (width == newWidth && height == newHeight && depth == newDepth) {
+ /* Use usersImage for level userLevel */
+ if (baseLevel <= level && level <= maxLevel) {
+ gluTexImage3D(target, level, internalFormat, width,
+ height, depth, 0, format, type,
+ usersImage);
+ }
+ if(levels == 0) { /* we're done. clean up and return */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+ return 0;
+ }
+ {
+ int nextWidth= newWidth/2;
+ int nextHeight= newHeight/2;
+ int nextDepth= newDepth/2;
+
+ /* clamp to 1 */
+ if (nextWidth < 1) nextWidth= 1;
+ if (nextHeight < 1) nextHeight= 1;
+ if (nextDepth < 1) nextDepth= 1;
+ memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
+ }
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memReq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ default:
+ return GLU_INVALID_ENUM; /* assertion */
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+ return GLU_OUT_OF_MEMORY;
+ }
+ else
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractUbyte,shoveUbyte,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize);
+ }
+ break;
+ case GL_BYTE:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractSbyte,shoveSbyte,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_byte(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractUshort,shoveUshort,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_ushort(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_SHORT:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractSshort,shoveSshort,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_short(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractUint,shoveUint,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_uint(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_INT:
+ if (depth > 1) {
+ halveImage3D(cmpts,extractSint,shoveSint,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_int(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_FLOAT:
+ if (depth > 1 ) {
+ halveImage3D(cmpts,extractFloat,shoveFloat,
+ width,height,depth,
+ usersImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_float(cmpts,width,height,usersImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ assert(format == GL_RGB);
+ halveImagePackedPixel3D(3,extract332,shove332,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ assert(format == GL_RGB);
+ halveImagePackedPixel3D(3,extract233rev,shove233rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ halveImagePackedPixel3D(3,extract565,shove565,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ halveImagePackedPixel3D(3,extract565rev,shove565rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ halveImagePackedPixel3D(4,extract4444,shove4444,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ halveImagePackedPixel3D(4,extract5551,shove5551,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ halveImagePackedPixel3D(4,extract8888,shove8888,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ halveImagePackedPixel3D(4,extract1010102,shove1010102,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
+ width,height,depth,usersImage,dstImage,
+ elementSize,rowSize,imageSize,myswapBytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ newWidth = width/2;
+ newHeight = height/2;
+ newDepth = depth/2;
+ /* clamp to 1 */
+ if (newWidth < 1) newWidth= 1;
+ if (newHeight < 1) newHeight= 1;
+ if (newDepth < 1) newDepth= 1;
+
+ myswapBytes = 0;
+ rowSize = newWidth * groupSize;
+ imageSize= rowSize * newHeight; /* 3dstuff */
+ memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
+ /* Swap srcImage and dstImage */
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memReq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ default:
+ return GLU_INVALID_ENUM; /* assertion */
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+ return GLU_OUT_OF_MEMORY;
+ }
+ /* level userLevel+1 is in srcImage; level userLevel already saved */
+ level = userLevel+1;
+ } else {/* user's image is *not* nice power-of-2 sized square */
+ memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memReq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ default:
+ return GLU_INVALID_ENUM; /* assertion */
+ }
+
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+ return GLU_OUT_OF_MEMORY;
+ }
+ /*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
+ width,height,depth,newWidth,newHeight,newDepth);*/
+
+ gluScaleImage3D(format, width, height, depth, type, usersImage,
+ newWidth, newHeight, newDepth, type, dstImage);
+
+ myswapBytes = 0;
+ rowSize = newWidth * groupSize;
+ imageSize = rowSize * newHeight; /* 3dstuff */
+ /* Swap dstImage and srcImage */
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+
+ if(levels != 0) { /* use as little memory as possible */
+ {
+ int nextWidth= newWidth/2;
+ int nextHeight= newHeight/2;
+ int nextDepth= newDepth/2;
+ if (nextWidth < 1) nextWidth= 1;
+ if (nextHeight < 1) nextHeight= 1;
+ if (nextDepth < 1) nextDepth= 1;
+
+ memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
+ }
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_BYTE:
+ dstImage = (GLbyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ case GL_SHORT:
+ dstImage = (GLshort *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_INT:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ case GL_INT:
+ dstImage = (GLint *)malloc(memReq);
+ break;
+ case GL_FLOAT:
+ dstImage = (GLfloat *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ dstImage = (GLubyte *)malloc(memReq);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ 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:
+ dstImage = (GLushort *)malloc(memReq);
+ break;
+ 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:
+ dstImage = (GLuint *)malloc(memReq);
+ break;
+ default:
+ return GLU_INVALID_ENUM; /* assertion */
+ }
+ if (dstImage == NULL) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+ return GLU_OUT_OF_MEMORY;
+ }
+ }
+ /* level userLevel is in srcImage; nothing saved yet */
+ level = userLevel;
+ }
+
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ if (baseLevel <= level && level <= maxLevel) {
+ gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
+ 0,format, type, (void *)srcImage);
+ }
+ level++; /* update current level for the loop */
+ for (; level <= levels; level++) {
+ switch(type) {
+ case GL_UNSIGNED_BYTE:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractUbyte,shoveUbyte,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize);
+ }
+ break;
+ case GL_BYTE:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractSbyte,shoveSbyte,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractUshort,shoveUshort,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_SHORT:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractSshort,shoveSshort,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractUint,shoveUint,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_INT:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractSint,shoveSint,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_FLOAT:
+ if (newDepth > 1) {
+ halveImage3D(cmpts,extractFloat,shoveFloat,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,groupSize,rowSize,
+ imageSize,myswapBytes);
+ }
+ else {
+ halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
+ elementSize,rowSize,groupSize,myswapBytes);
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ halveImagePackedPixel3D(3,extract332,shove332,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ halveImagePackedPixel3D(3,extract233rev,shove233rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ halveImagePackedPixel3D(3,extract565,shove565,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ halveImagePackedPixel3D(3,extract565rev,shove565rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ halveImagePackedPixel3D(4,extract4444,shove4444,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ halveImagePackedPixel3D(4,extract5551,shove5551,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ halveImagePackedPixel3D(4,extract8888,shove8888,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ halveImagePackedPixel3D(4,extract1010102,shove1010102,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
+ newWidth,newHeight,newDepth,
+ srcImage,dstImage,elementSize,rowSize,
+ imageSize,myswapBytes);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ __GLU_SWAP_IMAGE(srcImage,dstImage);
+
+ if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
+ if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
+ if (newDepth > 1) newDepth /= 2;
+ {
+ /* call tex image with srcImage untouched since it's not padded */
+ if (baseLevel <= level && level <= maxLevel) {
+ gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
+ newDepth,0, format, type, (void *) srcImage);
+ }
+ }
+ } /* for level */
+ glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
+
+ free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
+ if (dstImage) { /* if it's non-rectangular and only 1 level */
+ free(dstImage);
+ }
+ return 0;
+} /* gluBuild3DMipmapLevelsCore() */
+
+GLint GLAPIENTRY
+gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ GLint userLevel, GLint baseLevel, GLint maxLevel,
+ const void *data)
+{
+ int level, levels;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1 || height < 1 || depth < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ if(type == GL_BITMAP) {
+ return GLU_INVALID_ENUM;
+ }
+
+ levels = computeLog(width);
+ level = computeLog(height);
+ if (level > levels) levels=level;
+ level = computeLog(depth);
+ if (level > levels) levels=level;
+
+ levels+= userLevel;
+ if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
+ return GLU_INVALID_VALUE;
+
+ return gluBuild3DMipmapLevelsCore(target, internalFormat,
+ width, height, depth,
+ width, height, depth,
+ format, type,
+ userLevel, baseLevel, maxLevel,
+ data);
+} /* gluBuild3DMipmapLevels() */
+
+GLint GLAPIENTRY
+gluBuild3DMipmaps(GLenum target, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const void *data)
+{
+ GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
+ int level, levels;
+
+ int rc= checkMipmapArgs(internalFormat,format,type);
+ if (rc != 0) return rc;
+
+ if (width < 1 || height < 1 || depth < 1) {
+ return GLU_INVALID_VALUE;
+ }
+
+ if(type == GL_BITMAP) {
+ return GLU_INVALID_ENUM;
+ }
+
+ closestFit3D(target,width,height,depth,internalFormat,format,type,
+ &widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
+
+ levels = computeLog(widthPowerOf2);
+ level = computeLog(heightPowerOf2);
+ if (level > levels) levels=level;
+ level = computeLog(depthPowerOf2);
+ if (level > levels) levels=level;
+
+ return gluBuild3DMipmapLevelsCore(target, internalFormat,
+ width, height, depth,
+ widthPowerOf2, heightPowerOf2,
+ depthPowerOf2,
+ format, type, 0, 0, levels,
+ data);
+} /* gluBuild3DMipmaps() */
+
+static GLdouble extractUbyte(int isSwap, const void *ubyte)
+{
+ isSwap= isSwap; /* turn off warnings */
+
+ assert(*((const GLubyte *)ubyte) <= 255);
+
+ return (GLdouble)(*((const GLubyte *)ubyte));
+} /* extractUbyte() */
+
+static void shoveUbyte(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value < 256.0);
+
+ ((GLubyte *)data)[index]= (GLubyte)value;
+} /* shoveUbyte() */
+
+static GLdouble extractSbyte(int isSwap, const void *sbyte)
+{
+ isSwap= isSwap; /* turn off warnings */
+
+ assert(*((const GLbyte *)sbyte) <= 127);
+
+ return (GLdouble)(*((const GLbyte *)sbyte));
+} /* extractSbyte() */
+
+static void shoveSbyte(GLdouble value, int index, void *data)
+{
+ ((GLbyte *)data)[index]= (GLbyte)value;
+} /* shoveSbyte() */
+
+static GLdouble extractUshort(int isSwap, const void *uitem)
+{
+ GLushort ushort;
+
+ if (isSwap) {
+ ushort= __GLU_SWAP_2_BYTES(uitem);
+ }
+ else {
+ ushort= *(const GLushort *)uitem;
+ }
+
+ assert(ushort <= 65535);
+
+ return (GLdouble)ushort;
+} /* extractUshort() */
+
+static void shoveUshort(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value < 65536.0);
+
+ ((GLushort *)data)[index]= (GLushort)value;
+} /* shoveUshort() */
+
+static GLdouble extractSshort(int isSwap, const void *sitem)
+{
+ GLshort sshort;
+
+ if (isSwap) {
+ sshort= __GLU_SWAP_2_BYTES(sitem);
+ }
+ else {
+ sshort= *(const GLshort *)sitem;
+ }
+
+ assert(sshort <= 32767);
+
+ return (GLdouble)sshort;
+} /* extractSshort() */
+
+static void shoveSshort(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value < 32768.0);
+
+ ((GLshort *)data)[index]= (GLshort)value;
+} /* shoveSshort() */
+
+static GLdouble extractUint(int isSwap, const void *uitem)
+{
+ GLuint uint;
+
+ if (isSwap) {
+ uint= __GLU_SWAP_4_BYTES(uitem);
+ }
+ else {
+ uint= *(const GLuint *)uitem;
+ }
+
+ assert(uint <= 0xffffffff);
+
+ return (GLdouble)uint;
+} /* extractUint() */
+
+static void shoveUint(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
+
+ ((GLuint *)data)[index]= (GLuint)value;
+} /* shoveUint() */
+
+static GLdouble extractSint(int isSwap, const void *sitem)
+{
+ GLint sint;
+
+ if (isSwap) {
+ sint= __GLU_SWAP_4_BYTES(sitem);
+ }
+ else {
+ sint= *(const GLint *)sitem;
+ }
+
+ assert(sint <= 0x7fffffff);
+
+ return (GLdouble)sint;
+} /* extractSint() */
+
+static void shoveSint(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value <= (GLdouble) INT_MAX);
+
+ ((GLint *)data)[index]= (GLint)value;
+} /* shoveSint() */
+
+static GLdouble extractFloat(int isSwap, const void *item)
+{
+ GLfloat ffloat;
+
+ if (isSwap) {
+ ffloat= __GLU_SWAP_4_BYTES(item);
+ }
+ else {
+ ffloat= *(const GLfloat *)item;
+ }
+
+ assert(ffloat <= 1.0);
+
+ return (GLdouble)ffloat;
+} /* extractFloat() */
+
+static void shoveFloat(GLdouble value, int index, void *data)
+{
+ assert(0.0 <= value && value <= 1.0);
+
+ ((GLfloat *)data)[index]= value;
+} /* shoveFloat() */
+
+static void halveImageSlice(int components,
+ GLdouble (*extract)(int, const void *),
+ void (*shove)(GLdouble, int, void *),
+ GLint width, GLint height, GLint depth,
+ const void *dataIn, void *dataOut,
+ GLint elementSizeInBytes,
+ GLint groupSizeInBytes,
+ GLint rowSizeInBytes,
+ GLint imageSizeInBytes,
+ GLint isSwap)
+{
+ int ii, jj;
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ int halfDepth= depth / 2;
+ const char *src= (const char *)dataIn;
+ int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
+ int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
+ int outIndex= 0;
+
+ assert((width == 1 || height == 1) && depth >= 2);
+
+ if (width == height) { /* a 1-pixel column viewed from top */
+ /* printf("1-column\n");*/
+ assert(width == 1 && height == 1);
+ assert(depth >= 2);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ int cc;
+
+ for (cc = 0; cc < components; cc++) {
+ double totals[4];
+ double extractTotals[BOX2][4];
+ int kk;
+
+ extractTotals[0][cc]= (*extract)(isSwap,src);
+ extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
+
+ /* average 2 pixels since only a column */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
+ * totals[RED]/= 2.0;
+ */
+ for (kk = 0; kk < BOX2; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (double)BOX2;
+
+ (*shove)(totals[cc],outIndex,dataOut);
+ outIndex++;
+ src+= elementSizeInBytes;
+ } /* for cc */
+
+ /* skip over to next group of 2 */
+ src+= rowSizeInBytes;
+ } /* for ii */
+
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
+ assert(outIndex == halfDepth * components);
+ }
+ else if (height == 1) { /* horizontal slice viewed from top */
+ /* printf("horizontal slice\n"); */
+ assert(width != 1);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ for (jj= 0; jj< halfWidth; jj++) {
+ int cc;
+
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+ double totals[4];
+ double extractTotals[BOX4][4];
+
+ extractTotals[0][cc]=(*extract)(isSwap,src);
+ extractTotals[1][cc]=(*extract)(isSwap,
+ (src+groupSizeInBytes));
+ extractTotals[2][cc]=(*extract)(isSwap,
+ (src+imageSizeInBytes));
+ extractTotals[3][cc]=(*extract)(isSwap,
+ (src+imageSizeInBytes+groupSizeInBytes));
+
+ /* grab 4 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED];
+ * totals[RED]/= 4.0;
+ */
+ for (kk = 0; kk < BOX4; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (double)BOX4;
+
+ (*shove)(totals[cc],outIndex,dataOut);
+ outIndex++;
+
+ src+= elementSizeInBytes;
+ } /* for cc */
+
+ /* skip over to next horizontal square of 4 */
+ src+= groupSizeInBytes;
+ } /* for jj */
+ src+= rowPadBytes;
+
+ src+= rowSizeInBytes;
+ } /* for ii */
+
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
+ assert(outIndex == halfWidth * halfDepth * components);
+ }
+ else if (width == 1) { /* vertical slice viewed from top */
+ /* printf("vertical slice\n"); */
+ assert(height != 1);
+
+ for (ii= 0; ii< halfDepth; ii++) {
+ for (jj= 0; jj< halfHeight; jj++) {
+ int cc;
+
+ for (cc = 0; cc < components; cc++) {
+ int kk;
+ double totals[4];
+ double extractTotals[BOX4][4];
+
+ extractTotals[0][cc]=(*extract)(isSwap,src);
+ extractTotals[1][cc]=(*extract)(isSwap,
+ (src+rowSizeInBytes));
+ extractTotals[2][cc]=(*extract)(isSwap,
+ (src+imageSizeInBytes));
+ extractTotals[3][cc]=(*extract)(isSwap,
+ (src+imageSizeInBytes+rowSizeInBytes));
+
+ /* grab 4 pixels to average */
+ totals[cc]= 0.0;
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED];
+ * totals[RED]/= 4.0;
+ */
+ for (kk = 0; kk < BOX4; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (double)BOX4;
+
+ (*shove)(totals[cc],outIndex,dataOut);
+ outIndex++;
+
+ src+= elementSizeInBytes;
+ } /* for cc */
+ src+= rowPadBytes;
+
+ /* skip over to next vertical square of 4 */
+ src+= rowSizeInBytes;
+ } /* for jj */
+ src+= imagePadBytes;
+
+ src+= imageSizeInBytes;
+ } /* for ii */
+
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
+ assert(outIndex == halfHeight * halfDepth * components);
+ }
+
+} /* halveImageSlice() */
+
+static void halveImage3D(int components,
+ GLdouble (*extract)(int, const void *),
+ void (*shove)(GLdouble, int, void *),
+ GLint width, GLint height, GLint depth,
+ const void *dataIn, void *dataOut,
+ GLint elementSizeInBytes,
+ GLint groupSizeInBytes,
+ GLint rowSizeInBytes,
+ GLint imageSizeInBytes,
+ GLint isSwap)
+{
+ assert(depth > 1);
+
+ /* a horizontal/vertical/one-column slice viewed from top */
+ if (width == 1 || height == 1) {
+ assert(1 <= depth);
+
+ halveImageSlice(components,extract,shove, width, height, depth,
+ dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
+ rowSizeInBytes, imageSizeInBytes, isSwap);
+ return;
+ }
+ {
+ int ii, jj, dd;
+
+ int halfWidth= width / 2;
+ int halfHeight= height / 2;
+ int halfDepth= depth / 2;
+ const char *src= (const char *) dataIn;
+ int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
+ int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
+ int outIndex= 0;
+
+ for (dd= 0; dd < halfDepth; dd++) {
+ for (ii= 0; ii< halfHeight; ii++) {
+ for (jj= 0; jj< halfWidth; jj++) {
+ int cc;
+
+ for (cc= 0; cc < components; cc++) {
+ int kk;
+#define BOX8 8
+ double totals[4]; /* 4 is maximum components */
+ double extractTotals[BOX8][4]; /* 4 is maximum components */
+
+ extractTotals[0][cc]= (*extract)(isSwap,src);
+ extractTotals[1][cc]= (*extract)(isSwap,
+ (src+groupSizeInBytes));
+ extractTotals[2][cc]= (*extract)(isSwap,
+ (src+rowSizeInBytes));
+ extractTotals[3][cc]= (*extract)(isSwap,
+ (src+rowSizeInBytes+groupSizeInBytes));
+
+ extractTotals[4][cc]= (*extract)(isSwap,
+ (src+imageSizeInBytes));
+
+ extractTotals[5][cc]= (*extract)(isSwap,
+ (src+groupSizeInBytes+imageSizeInBytes));
+ extractTotals[6][cc]= (*extract)(isSwap,
+ (src+rowSizeInBytes+imageSizeInBytes));
+ extractTotals[7][cc]= (*extract)(isSwap,
+ (src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
+
+ totals[cc]= 0.0;
+
+ /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
+ * extractTotals[2][RED]+extractTotals[3][RED]+
+ * extractTotals[4][RED]+extractTotals[5][RED]+
+ * extractTotals[6][RED]+extractTotals[7][RED];
+ * totals[RED]/= 8.0;
+ */
+ for (kk = 0; kk < BOX8; kk++) {
+ totals[cc]+= extractTotals[kk][cc];
+ }
+ totals[cc]/= (double)BOX8;
+
+ (*shove)(totals[cc],outIndex,dataOut);
+
+ outIndex++;
+
+ src+= elementSizeInBytes; /* go to next component */
+ } /* for cc */
+
+ /* skip over to next square of 4 */
+ src+= groupSizeInBytes;
+ } /* for jj */
+ /* skip past pad bytes, if any, to get to next row */
+ src+= rowPadBytes;
+
+ /* src is at beginning of a row here, but it's the second row of
+ * the square block of 4 pixels that we just worked on so we
+ * need to go one more row.
+ * i.e.,
+ * OO...
+ * here -->OO...
+ * but want -->OO...
+ * OO...
+ * ...
+ */
+ src+= rowSizeInBytes;
+ } /* for ii */
+
+ /* skip past pad bytes, if any, to get to next image */
+ src+= imagePadBytes;
+
+ src+= imageSizeInBytes;
+ } /* for dd */
+
+ /* both pointers must reach one byte after the end */
+ assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
+ assert(outIndex == halfWidth * halfHeight * halfDepth * components);
+ }
+} /* halveImage3D() */
+
+
+
+/*** mipmap.c ***/
+
diff --git a/mesalib/src/glu/sgi/libutil/project.c b/mesalib/src/glu/sgi/libutil/project.c
new file mode 100644
index 000000000..f4bf8839b
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/project.c
@@ -0,0 +1,359 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "gluos.h"
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "gluint.h"
+
+/*
+** Make m an identity matrix
+*/
+static void __gluMakeIdentityd(GLdouble m[16])
+{
+ m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
+ m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
+ m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
+ m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
+}
+
+static void __gluMakeIdentityf(GLfloat m[16])
+{
+ m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
+ m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
+ m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
+ m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
+}
+
+void GLAPIENTRY
+gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
+{
+ glOrtho(left, right, bottom, top, -1, 1);
+}
+
+#define __glPi 3.14159265358979323846
+
+void GLAPIENTRY
+gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
+{
+ GLdouble m[4][4];
+ double sine, cotangent, deltaZ;
+ double radians = fovy / 2 * __glPi / 180;
+
+ deltaZ = zFar - zNear;
+ sine = sin(radians);
+ if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
+ return;
+ }
+ cotangent = COS(radians) / sine;
+
+ __gluMakeIdentityd(&m[0][0]);
+ m[0][0] = cotangent / aspect;
+ m[1][1] = cotangent;
+ m[2][2] = -(zFar + zNear) / deltaZ;
+ m[2][3] = -1;
+ m[3][2] = -2 * zNear * zFar / deltaZ;
+ m[3][3] = 0;
+ glMultMatrixd(&m[0][0]);
+}
+
+static void normalize(float v[3])
+{
+ float r;
+
+ r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
+ if (r == 0.0) return;
+
+ v[0] /= r;
+ v[1] /= r;
+ v[2] /= r;
+}
+
+static void cross(float v1[3], float v2[3], float result[3])
+{
+ result[0] = v1[1]*v2[2] - v1[2]*v2[1];
+ result[1] = v1[2]*v2[0] - v1[0]*v2[2];
+ result[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+void GLAPIENTRY
+gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
+ GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
+ GLdouble upz)
+{
+ float forward[3], side[3], up[3];
+ GLfloat m[4][4];
+
+ forward[0] = centerx - eyex;
+ forward[1] = centery - eyey;
+ forward[2] = centerz - eyez;
+
+ up[0] = upx;
+ up[1] = upy;
+ up[2] = upz;
+
+ normalize(forward);
+
+ /* Side = forward x up */
+ cross(forward, up, side);
+ normalize(side);
+
+ /* Recompute up as: up = side x forward */
+ cross(side, forward, up);
+
+ __gluMakeIdentityf(&m[0][0]);
+ m[0][0] = side[0];
+ m[1][0] = side[1];
+ m[2][0] = side[2];
+
+ m[0][1] = up[0];
+ m[1][1] = up[1];
+ m[2][1] = up[2];
+
+ m[0][2] = -forward[0];
+ m[1][2] = -forward[1];
+ m[2][2] = -forward[2];
+
+ glMultMatrixf(&m[0][0]);
+ glTranslated(-eyex, -eyey, -eyez);
+}
+
+static void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4],
+ GLdouble out[4])
+{
+ int i;
+
+ for (i=0; i<4; i++) {
+ out[i] =
+ in[0] * matrix[0*4+i] +
+ in[1] * matrix[1*4+i] +
+ in[2] * matrix[2*4+i] +
+ in[3] * matrix[3*4+i];
+ }
+}
+
+/*
+** Invert 4x4 matrix.
+** Contributed by David Moore (See Mesa bug #6748)
+*/
+static int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16])
+{
+ double inv[16], det;
+ int i;
+
+ inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
+ + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
+ inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
+ - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
+ inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
+ + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
+ inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
+ - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
+ inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
+ - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
+ inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
+ + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
+ inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
+ - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
+ inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
+ + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
+ inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
+ + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
+ inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
+ - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
+ inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
+ + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
+ inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
+ - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
+ inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
+ - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
+ inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
+ + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
+ inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
+ - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
+ inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
+ + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
+
+ det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
+ if (det == 0)
+ return GL_FALSE;
+
+ det = 1.0 / det;
+
+ for (i = 0; i < 16; i++)
+ invOut[i] = inv[i] * det;
+
+ return GL_TRUE;
+}
+
+static void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16],
+ GLdouble r[16])
+{
+ int i, j;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ r[i*4+j] =
+ a[i*4+0]*b[0*4+j] +
+ a[i*4+1]*b[1*4+j] +
+ a[i*4+2]*b[2*4+j] +
+ a[i*4+3]*b[3*4+j];
+ }
+ }
+}
+
+GLint GLAPIENTRY
+gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
+ const GLdouble modelMatrix[16],
+ const GLdouble projMatrix[16],
+ const GLint viewport[4],
+ GLdouble *winx, GLdouble *winy, GLdouble *winz)
+{
+ double in[4];
+ double out[4];
+
+ in[0]=objx;
+ in[1]=objy;
+ in[2]=objz;
+ in[3]=1.0;
+ __gluMultMatrixVecd(modelMatrix, in, out);
+ __gluMultMatrixVecd(projMatrix, out, in);
+ if (in[3] == 0.0) return(GL_FALSE);
+ in[0] /= in[3];
+ in[1] /= in[3];
+ in[2] /= in[3];
+ /* Map x, y and z to range 0-1 */
+ in[0] = in[0] * 0.5 + 0.5;
+ in[1] = in[1] * 0.5 + 0.5;
+ in[2] = in[2] * 0.5 + 0.5;
+
+ /* Map x,y to viewport */
+ in[0] = in[0] * viewport[2] + viewport[0];
+ in[1] = in[1] * viewport[3] + viewport[1];
+
+ *winx=in[0];
+ *winy=in[1];
+ *winz=in[2];
+ return(GL_TRUE);
+}
+
+GLint GLAPIENTRY
+gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
+ const GLdouble modelMatrix[16],
+ const GLdouble projMatrix[16],
+ const GLint viewport[4],
+ GLdouble *objx, GLdouble *objy, GLdouble *objz)
+{
+ double finalMatrix[16];
+ double in[4];
+ double out[4];
+
+ __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
+ if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);
+
+ in[0]=winx;
+ in[1]=winy;
+ in[2]=winz;
+ in[3]=1.0;
+
+ /* Map x and y from window coordinates */
+ in[0] = (in[0] - viewport[0]) / viewport[2];
+ in[1] = (in[1] - viewport[1]) / viewport[3];
+
+ /* Map to range -1 to 1 */
+ in[0] = in[0] * 2 - 1;
+ in[1] = in[1] * 2 - 1;
+ in[2] = in[2] * 2 - 1;
+
+ __gluMultMatrixVecd(finalMatrix, in, out);
+ if (out[3] == 0.0) return(GL_FALSE);
+ out[0] /= out[3];
+ out[1] /= out[3];
+ out[2] /= out[3];
+ *objx = out[0];
+ *objy = out[1];
+ *objz = out[2];
+ return(GL_TRUE);
+}
+
+GLint GLAPIENTRY
+gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
+ const GLdouble modelMatrix[16],
+ const GLdouble projMatrix[16],
+ const GLint viewport[4],
+ GLclampd nearVal, GLclampd farVal,
+ GLdouble *objx, GLdouble *objy, GLdouble *objz,
+ GLdouble *objw)
+{
+ double finalMatrix[16];
+ double in[4];
+ double out[4];
+
+ __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
+ if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE);
+
+ in[0]=winx;
+ in[1]=winy;
+ in[2]=winz;
+ in[3]=clipw;
+
+ /* Map x and y from window coordinates */
+ in[0] = (in[0] - viewport[0]) / viewport[2];
+ in[1] = (in[1] - viewport[1]) / viewport[3];
+ in[2] = (in[2] - nearVal) / (farVal - nearVal);
+
+ /* Map to range -1 to 1 */
+ in[0] = in[0] * 2 - 1;
+ in[1] = in[1] * 2 - 1;
+ in[2] = in[2] * 2 - 1;
+
+ __gluMultMatrixVecd(finalMatrix, in, out);
+ if (out[3] == 0.0) return(GL_FALSE);
+ *objx = out[0];
+ *objy = out[1];
+ *objz = out[2];
+ *objw = out[3];
+ return(GL_TRUE);
+}
+
+void GLAPIENTRY
+gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay,
+ GLint viewport[4])
+{
+ if (deltax <= 0 || deltay <= 0) {
+ return;
+ }
+
+ /* Translate and scale the picked region to the entire window */
+ glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax,
+ (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
+ glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0);
+}
diff --git a/mesalib/src/glu/sgi/libutil/quad.c b/mesalib/src/glu/sgi/libutil/quad.c
new file mode 100644
index 000000000..d88b20f55
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/quad.c
@@ -0,0 +1,1155 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "gluos.h"
+#include "gluint.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+/* Make it not a power of two to avoid cache thrashing on the chip */
+#define CACHE_SIZE 240
+
+#undef PI
+#define PI 3.14159265358979323846
+
+struct GLUquadric {
+ GLint normals;
+ GLboolean textureCoords;
+ GLint orientation;
+ GLint drawStyle;
+ void (GLAPIENTRY *errorCallback)( GLint );
+};
+
+GLUquadric * GLAPIENTRY
+gluNewQuadric(void)
+{
+ GLUquadric *newstate;
+
+ newstate = (GLUquadric *) malloc(sizeof(GLUquadric));
+ if (newstate == NULL) {
+ /* Can't report an error at this point... */
+ return NULL;
+ }
+ newstate->normals = GLU_SMOOTH;
+ newstate->textureCoords = GL_FALSE;
+ newstate->orientation = GLU_OUTSIDE;
+ newstate->drawStyle = GLU_FILL;
+ newstate->errorCallback = NULL;
+ return newstate;
+}
+
+
+void GLAPIENTRY
+gluDeleteQuadric(GLUquadric *state)
+{
+ free(state);
+}
+
+static void gluQuadricError(GLUquadric *qobj, GLenum which)
+{
+ if (qobj->errorCallback) {
+ qobj->errorCallback(which);
+ }
+}
+
+void GLAPIENTRY
+gluQuadricCallback(GLUquadric *qobj, GLenum which, _GLUfuncptr fn)
+{
+ switch (which) {
+ case GLU_ERROR:
+ qobj->errorCallback = (void (GLAPIENTRY *)(GLint)) fn;
+ break;
+ default:
+ gluQuadricError(qobj, GLU_INVALID_ENUM);
+ return;
+ }
+}
+
+void GLAPIENTRY
+gluQuadricNormals(GLUquadric *qobj, GLenum normals)
+{
+ switch (normals) {
+ case GLU_SMOOTH:
+ case GLU_FLAT:
+ case GLU_NONE:
+ break;
+ default:
+ gluQuadricError(qobj, GLU_INVALID_ENUM);
+ return;
+ }
+ qobj->normals = normals;
+}
+
+void GLAPIENTRY
+gluQuadricTexture(GLUquadric *qobj, GLboolean textureCoords)
+{
+ qobj->textureCoords = textureCoords;
+}
+
+void GLAPIENTRY
+gluQuadricOrientation(GLUquadric *qobj, GLenum orientation)
+{
+ switch(orientation) {
+ case GLU_OUTSIDE:
+ case GLU_INSIDE:
+ break;
+ default:
+ gluQuadricError(qobj, GLU_INVALID_ENUM);
+ return;
+ }
+ qobj->orientation = orientation;
+}
+
+void GLAPIENTRY
+gluQuadricDrawStyle(GLUquadric *qobj, GLenum drawStyle)
+{
+ switch(drawStyle) {
+ case GLU_POINT:
+ case GLU_LINE:
+ case GLU_FILL:
+ case GLU_SILHOUETTE:
+ break;
+ default:
+ gluQuadricError(qobj, GLU_INVALID_ENUM);
+ return;
+ }
+ qobj->drawStyle = drawStyle;
+}
+
+void GLAPIENTRY
+gluCylinder(GLUquadric *qobj, GLdouble baseRadius, GLdouble topRadius,
+ GLdouble height, GLint slices, GLint stacks)
+{
+ GLint i,j;
+ GLfloat sinCache[CACHE_SIZE];
+ GLfloat cosCache[CACHE_SIZE];
+ GLfloat sinCache2[CACHE_SIZE];
+ GLfloat cosCache2[CACHE_SIZE];
+ GLfloat sinCache3[CACHE_SIZE];
+ GLfloat cosCache3[CACHE_SIZE];
+ GLfloat angle;
+ GLfloat zLow, zHigh;
+ GLfloat sintemp, costemp;
+ GLfloat length;
+ GLfloat deltaRadius;
+ GLfloat zNormal;
+ GLfloat xyNormalRatio;
+ GLfloat radiusLow, radiusHigh;
+ int needCache2, needCache3;
+
+ if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
+
+ if (slices < 2 || stacks < 1 || baseRadius < 0.0 || topRadius < 0.0 ||
+ height < 0.0) {
+ gluQuadricError(qobj, GLU_INVALID_VALUE);
+ return;
+ }
+
+ /* Compute length (needed for normal calculations) */
+ deltaRadius = baseRadius - topRadius;
+ length = SQRT(deltaRadius*deltaRadius + height*height);
+ if (length == 0.0) {
+ gluQuadricError(qobj, GLU_INVALID_VALUE);
+ return;
+ }
+
+ /* Cache is the vertex locations cache */
+ /* Cache2 is the various normals at the vertices themselves */
+ /* Cache3 is the various normals for the faces */
+ needCache2 = needCache3 = 0;
+ if (qobj->normals == GLU_SMOOTH) {
+ needCache2 = 1;
+ }
+
+ if (qobj->normals == GLU_FLAT) {
+ if (qobj->drawStyle != GLU_POINT) {
+ needCache3 = 1;
+ }
+ if (qobj->drawStyle == GLU_LINE) {
+ needCache2 = 1;
+ }
+ }
+
+ zNormal = deltaRadius / length;
+ xyNormalRatio = height / length;
+
+ for (i = 0; i < slices; i++) {
+ angle = 2 * PI * i / slices;
+ if (needCache2) {
+ if (qobj->orientation == GLU_OUTSIDE) {
+ sinCache2[i] = xyNormalRatio * SIN(angle);
+ cosCache2[i] = xyNormalRatio * COS(angle);
+ } else {
+ sinCache2[i] = -xyNormalRatio * SIN(angle);
+ cosCache2[i] = -xyNormalRatio * COS(angle);
+ }
+ }
+ sinCache[i] = SIN(angle);
+ cosCache[i] = COS(angle);
+ }
+
+ if (needCache3) {
+ for (i = 0; i < slices; i++) {
+ angle = 2 * PI * (i-0.5) / slices;
+ if (qobj->orientation == GLU_OUTSIDE) {
+ sinCache3[i] = xyNormalRatio * SIN(angle);
+ cosCache3[i] = xyNormalRatio * COS(angle);
+ } else {
+ sinCache3[i] = -xyNormalRatio * SIN(angle);
+ cosCache3[i] = -xyNormalRatio * COS(angle);
+ }
+ }
+ }
+
+ sinCache[slices] = sinCache[0];
+ cosCache[slices] = cosCache[0];
+ if (needCache2) {
+ sinCache2[slices] = sinCache2[0];
+ cosCache2[slices] = cosCache2[0];
+ }
+ if (needCache3) {
+ sinCache3[slices] = sinCache3[0];
+ cosCache3[slices] = cosCache3[0];
+ }
+
+ switch (qobj->drawStyle) {
+ case GLU_FILL:
+ /* Note:
+ ** An argument could be made for using a TRIANGLE_FAN for the end
+ ** of the cylinder of either radii is 0.0 (a cone). However, a
+ ** TRIANGLE_FAN would not work in smooth shading mode (the common
+ ** case) because the normal for the apex is different for every
+ ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
+ ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
+ ** just let the GL trivially reject one of the two triangles of the
+ ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
+ ** alone.
+ */
+ for (j = 0; j < stacks; j++) {
+ zLow = j * height / stacks;
+ zHigh = (j + 1) * height / stacks;
+ radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
+ radiusHigh = baseRadius - deltaRadius * ((float) (j + 1) / stacks);
+
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ glNormal3f(sinCache3[i], cosCache3[i], zNormal);
+ break;
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2[i], cosCache2[i], zNormal);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->orientation == GLU_OUTSIDE) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], zLow);
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) (j+1) / stacks);
+ }
+ glVertex3f(radiusHigh * sinCache[i],
+ radiusHigh * cosCache[i], zHigh);
+ } else {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) (j+1) / stacks);
+ }
+ glVertex3f(radiusHigh * sinCache[i],
+ radiusHigh * cosCache[i], zHigh);
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], zLow);
+ }
+ }
+ glEnd();
+ }
+ break;
+ case GLU_POINT:
+ glBegin(GL_POINTS);
+ for (i = 0; i < slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2[i], cosCache2[i], zNormal);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ sintemp = sinCache[i];
+ costemp = cosCache[i];
+ for (j = 0; j <= stacks; j++) {
+ zLow = j * height / stacks;
+ radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sintemp,
+ radiusLow * costemp, zLow);
+ }
+ }
+ glEnd();
+ break;
+ case GLU_LINE:
+ for (j = 1; j < stacks; j++) {
+ zLow = j * height / stacks;
+ radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ glNormal3f(sinCache3[i], cosCache3[i], zNormal);
+ break;
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2[i], cosCache2[i], zNormal);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], zLow);
+ }
+ glEnd();
+ }
+ /* Intentionally fall through here... */
+ case GLU_SILHOUETTE:
+ for (j = 0; j <= stacks; j += stacks) {
+ zLow = j * height / stacks;
+ radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ glNormal3f(sinCache3[i], cosCache3[i], zNormal);
+ break;
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2[i], cosCache2[i], zNormal);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i],
+ zLow);
+ }
+ glEnd();
+ }
+ for (i = 0; i < slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2[i], cosCache2[i], 0.0);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ sintemp = sinCache[i];
+ costemp = cosCache[i];
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j <= stacks; j++) {
+ zLow = j * height / stacks;
+ radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ (float) j / stacks);
+ }
+ glVertex3f(radiusLow * sintemp,
+ radiusLow * costemp, zLow);
+ }
+ glEnd();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void GLAPIENTRY
+gluDisk(GLUquadric *qobj, GLdouble innerRadius, GLdouble outerRadius,
+ GLint slices, GLint loops)
+{
+ gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, 0.0, 360.0);
+}
+
+void GLAPIENTRY
+gluPartialDisk(GLUquadric *qobj, GLdouble innerRadius,
+ GLdouble outerRadius, GLint slices, GLint loops,
+ GLdouble startAngle, GLdouble sweepAngle)
+{
+ GLint i,j;
+ GLfloat sinCache[CACHE_SIZE];
+ GLfloat cosCache[CACHE_SIZE];
+ GLfloat angle;
+ GLfloat sintemp, costemp;
+ GLfloat deltaRadius;
+ GLfloat radiusLow, radiusHigh;
+ GLfloat texLow = 0.0, texHigh = 0.0;
+ GLfloat angleOffset;
+ GLint slices2;
+ GLint finish;
+
+ if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
+ if (slices < 2 || loops < 1 || outerRadius <= 0.0 || innerRadius < 0.0 ||
+ innerRadius > outerRadius) {
+ gluQuadricError(qobj, GLU_INVALID_VALUE);
+ return;
+ }
+
+ if (sweepAngle < -360.0) sweepAngle = 360.0;
+ if (sweepAngle > 360.0) sweepAngle = 360.0;
+ if (sweepAngle < 0) {
+ startAngle += sweepAngle;
+ sweepAngle = -sweepAngle;
+ }
+
+ if (sweepAngle == 360.0) {
+ slices2 = slices;
+ } else {
+ slices2 = slices + 1;
+ }
+
+ /* Compute length (needed for normal calculations) */
+ deltaRadius = outerRadius - innerRadius;
+
+ /* Cache is the vertex locations cache */
+
+ angleOffset = startAngle / 180.0 * PI;
+ for (i = 0; i <= slices; i++) {
+ angle = angleOffset + ((PI * sweepAngle) / 180.0) * i / slices;
+ sinCache[i] = SIN(angle);
+ cosCache[i] = COS(angle);
+ }
+
+ if (sweepAngle == 360.0) {
+ sinCache[slices] = sinCache[0];
+ cosCache[slices] = cosCache[0];
+ }
+
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ if (qobj->orientation == GLU_OUTSIDE) {
+ glNormal3f(0.0, 0.0, 1.0);
+ } else {
+ glNormal3f(0.0, 0.0, -1.0);
+ }
+ break;
+ default:
+ case GLU_NONE:
+ break;
+ }
+
+ switch (qobj->drawStyle) {
+ case GLU_FILL:
+ if (innerRadius == 0.0) {
+ finish = loops - 1;
+ /* Triangle strip for inner polygons */
+ glBegin(GL_TRIANGLE_FAN);
+ if (qobj->textureCoords) {
+ glTexCoord2f(0.5, 0.5);
+ }
+ glVertex3f(0.0, 0.0, 0.0);
+ radiusLow = outerRadius -
+ deltaRadius * ((float) (loops-1) / loops);
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ }
+
+ if (qobj->orientation == GLU_OUTSIDE) {
+ for (i = slices; i >= 0; i--) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+ }
+ } else {
+ for (i = 0; i <= slices; i++) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+ }
+ }
+ glEnd();
+ } else {
+ finish = loops;
+ }
+ for (j = 0; j < finish; j++) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+ radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops);
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ texHigh = radiusHigh / outerRadius / 2;
+ }
+
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= slices; i++) {
+ if (qobj->orientation == GLU_OUTSIDE) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(texHigh * sinCache[i] + 0.5,
+ texHigh * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusHigh * sinCache[i],
+ radiusHigh * cosCache[i], 0.0);
+ } else {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texHigh * sinCache[i] + 0.5,
+ texHigh * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusHigh * sinCache[i],
+ radiusHigh * cosCache[i], 0.0);
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+ }
+ }
+ glEnd();
+ }
+ break;
+ case GLU_POINT:
+ glBegin(GL_POINTS);
+ for (i = 0; i < slices2; i++) {
+ sintemp = sinCache[i];
+ costemp = cosCache[i];
+ for (j = 0; j <= loops; j++) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
+ }
+ }
+ glEnd();
+ break;
+ case GLU_LINE:
+ if (innerRadius == outerRadius) {
+ glBegin(GL_LINE_STRIP);
+
+ for (i = 0; i <= slices; i++) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(sinCache[i] / 2 + 0.5,
+ cosCache[i] / 2 + 0.5);
+ }
+ glVertex3f(innerRadius * sinCache[i],
+ innerRadius * cosCache[i], 0.0);
+ }
+ glEnd();
+ break;
+ }
+ for (j = 0; j <= loops; j++) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ }
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0; i <= slices; i++) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+ }
+ glEnd();
+ }
+ for (i=0; i < slices2; i++) {
+ sintemp = sinCache[i];
+ costemp = cosCache[i];
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j <= loops; j++) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ }
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
+ }
+ glEnd();
+ }
+ break;
+ case GLU_SILHOUETTE:
+ if (sweepAngle < 360.0) {
+ for (i = 0; i <= slices; i+= slices) {
+ sintemp = sinCache[i];
+ costemp = cosCache[i];
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j <= loops; j++) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
+ }
+ glEnd();
+ }
+ }
+ for (j = 0; j <= loops; j += loops) {
+ radiusLow = outerRadius - deltaRadius * ((float) j / loops);
+ if (qobj->textureCoords) {
+ texLow = radiusLow / outerRadius / 2;
+ }
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0; i <= slices; i++) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(texLow * sinCache[i] + 0.5,
+ texLow * cosCache[i] + 0.5);
+ }
+ glVertex3f(radiusLow * sinCache[i],
+ radiusLow * cosCache[i], 0.0);
+ }
+ glEnd();
+ if (innerRadius == outerRadius) break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void GLAPIENTRY
+gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
+{
+ GLint i,j;
+ GLfloat sinCache1a[CACHE_SIZE];
+ GLfloat cosCache1a[CACHE_SIZE];
+ GLfloat sinCache2a[CACHE_SIZE];
+ GLfloat cosCache2a[CACHE_SIZE];
+ GLfloat sinCache3a[CACHE_SIZE];
+ GLfloat cosCache3a[CACHE_SIZE];
+ GLfloat sinCache1b[CACHE_SIZE];
+ GLfloat cosCache1b[CACHE_SIZE];
+ GLfloat sinCache2b[CACHE_SIZE];
+ GLfloat cosCache2b[CACHE_SIZE];
+ GLfloat sinCache3b[CACHE_SIZE];
+ GLfloat cosCache3b[CACHE_SIZE];
+ GLfloat angle;
+ GLfloat zLow, zHigh;
+ GLfloat sintemp1 = 0.0, sintemp2 = 0.0, sintemp3 = 0.0, sintemp4 = 0.0;
+ GLfloat costemp1 = 0.0, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
+ GLboolean needCache2, needCache3;
+ GLint start, finish;
+
+ if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
+ if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
+ if (slices < 2 || stacks < 1 || radius < 0.0) {
+ gluQuadricError(qobj, GLU_INVALID_VALUE);
+ return;
+ }
+
+ /* Cache is the vertex locations cache */
+ /* Cache2 is the various normals at the vertices themselves */
+ /* Cache3 is the various normals for the faces */
+ needCache2 = needCache3 = GL_FALSE;
+
+ if (qobj->normals == GLU_SMOOTH) {
+ needCache2 = GL_TRUE;
+ }
+
+ if (qobj->normals == GLU_FLAT) {
+ if (qobj->drawStyle != GLU_POINT) {
+ needCache3 = GL_TRUE;
+ }
+ if (qobj->drawStyle == GLU_LINE) {
+ needCache2 = GL_TRUE;
+ }
+ }
+
+ for (i = 0; i < slices; i++) {
+ angle = 2 * PI * i / slices;
+ sinCache1a[i] = SIN(angle);
+ cosCache1a[i] = COS(angle);
+ if (needCache2) {
+ sinCache2a[i] = sinCache1a[i];
+ cosCache2a[i] = cosCache1a[i];
+ }
+ }
+
+ for (j = 0; j <= stacks; j++) {
+ angle = PI * j / stacks;
+ if (needCache2) {
+ if (qobj->orientation == GLU_OUTSIDE) {
+ sinCache2b[j] = SIN(angle);
+ cosCache2b[j] = COS(angle);
+ } else {
+ sinCache2b[j] = -SIN(angle);
+ cosCache2b[j] = -COS(angle);
+ }
+ }
+ sinCache1b[j] = radius * SIN(angle);
+ cosCache1b[j] = radius * COS(angle);
+ }
+ /* Make sure it comes to a point */
+ sinCache1b[0] = 0;
+ sinCache1b[stacks] = 0;
+
+ if (needCache3) {
+ for (i = 0; i < slices; i++) {
+ angle = 2 * PI * (i-0.5) / slices;
+ sinCache3a[i] = SIN(angle);
+ cosCache3a[i] = COS(angle);
+ }
+ for (j = 0; j <= stacks; j++) {
+ angle = PI * (j - 0.5) / stacks;
+ if (qobj->orientation == GLU_OUTSIDE) {
+ sinCache3b[j] = SIN(angle);
+ cosCache3b[j] = COS(angle);
+ } else {
+ sinCache3b[j] = -SIN(angle);
+ cosCache3b[j] = -COS(angle);
+ }
+ }
+ }
+
+ sinCache1a[slices] = sinCache1a[0];
+ cosCache1a[slices] = cosCache1a[0];
+ if (needCache2) {
+ sinCache2a[slices] = sinCache2a[0];
+ cosCache2a[slices] = cosCache2a[0];
+ }
+ if (needCache3) {
+ sinCache3a[slices] = sinCache3a[0];
+ cosCache3a[slices] = cosCache3a[0];
+ }
+
+ switch (qobj->drawStyle) {
+ case GLU_FILL:
+ /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
+ ** We don't do it when texturing because we need to respecify the
+ ** texture coordinates of the apex for every adjacent vertex (because
+ ** it isn't a constant for that point)
+ */
+ if (!(qobj->textureCoords)) {
+ start = 1;
+ finish = stacks - 1;
+
+ /* Low end first (j == 0 iteration) */
+ sintemp2 = sinCache1b[1];
+ zHigh = cosCache1b[1];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ sintemp3 = sinCache3b[1];
+ costemp3 = cosCache3b[1];
+ break;
+ case GLU_SMOOTH:
+ sintemp3 = sinCache2b[1];
+ costemp3 = cosCache2b[1];
+ glNormal3f(sinCache2a[0] * sinCache2b[0],
+ cosCache2a[0] * sinCache2b[0],
+ cosCache2b[0]);
+ break;
+ default:
+ break;
+ }
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex3f(0.0, 0.0, radius);
+ if (qobj->orientation == GLU_OUTSIDE) {
+ for (i = slices; i >= 0; i--) {
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp3,
+ cosCache2a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_FLAT:
+ if (i != slices) {
+ glNormal3f(sinCache3a[i+1] * sintemp3,
+ cosCache3a[i+1] * sintemp3,
+ costemp3);
+ }
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ }
+ } else {
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp3,
+ cosCache2a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_FLAT:
+ glNormal3f(sinCache3a[i] * sintemp3,
+ cosCache3a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ }
+ }
+ glEnd();
+
+ /* High end next (j == stacks-1 iteration) */
+ sintemp2 = sinCache1b[stacks-1];
+ zHigh = cosCache1b[stacks-1];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ sintemp3 = sinCache3b[stacks];
+ costemp3 = cosCache3b[stacks];
+ break;
+ case GLU_SMOOTH:
+ sintemp3 = sinCache2b[stacks-1];
+ costemp3 = cosCache2b[stacks-1];
+ glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
+ cosCache2a[stacks] * sinCache2b[stacks],
+ cosCache2b[stacks]);
+ break;
+ default:
+ break;
+ }
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex3f(0.0, 0.0, -radius);
+ if (qobj->orientation == GLU_OUTSIDE) {
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp3,
+ cosCache2a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_FLAT:
+ glNormal3f(sinCache3a[i] * sintemp3,
+ cosCache3a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ }
+ } else {
+ for (i = slices; i >= 0; i--) {
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp3,
+ cosCache2a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_FLAT:
+ if (i != slices) {
+ glNormal3f(sinCache3a[i+1] * sintemp3,
+ cosCache3a[i+1] * sintemp3,
+ costemp3);
+ }
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ }
+ }
+ glEnd();
+ } else {
+ start = 0;
+ finish = stacks;
+ }
+ for (j = start; j < finish; j++) {
+ zLow = cosCache1b[j];
+ zHigh = cosCache1b[j+1];
+ sintemp1 = sinCache1b[j];
+ sintemp2 = sinCache1b[j+1];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ sintemp4 = sinCache3b[j+1];
+ costemp4 = cosCache3b[j+1];
+ break;
+ case GLU_SMOOTH:
+ if (qobj->orientation == GLU_OUTSIDE) {
+ sintemp3 = sinCache2b[j+1];
+ costemp3 = cosCache2b[j+1];
+ sintemp4 = sinCache2b[j];
+ costemp4 = cosCache2b[j];
+ } else {
+ sintemp3 = sinCache2b[j];
+ costemp3 = cosCache2b[j];
+ sintemp4 = sinCache2b[j+1];
+ costemp4 = cosCache2b[j+1];
+ }
+ break;
+ default:
+ break;
+ }
+
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp3,
+ cosCache2a[i] * sintemp3,
+ costemp3);
+ break;
+ case GLU_FLAT:
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->orientation == GLU_OUTSIDE) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) (j+1) / stacks);
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ } else {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) j / stacks);
+ }
+ glVertex3f(sintemp1 * sinCache1a[i],
+ sintemp1 * cosCache1a[i], zLow);
+ }
+ switch(qobj->normals) {
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp4,
+ cosCache2a[i] * sintemp4,
+ costemp4);
+ break;
+ case GLU_FLAT:
+ glNormal3f(sinCache3a[i] * sintemp4,
+ cosCache3a[i] * sintemp4,
+ costemp4);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->orientation == GLU_OUTSIDE) {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) j / stacks);
+ }
+ glVertex3f(sintemp1 * sinCache1a[i],
+ sintemp1 * cosCache1a[i], zLow);
+ } else {
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) (j+1) / stacks);
+ }
+ glVertex3f(sintemp2 * sinCache1a[i],
+ sintemp2 * cosCache1a[i], zHigh);
+ }
+ }
+ glEnd();
+ }
+ break;
+ case GLU_POINT:
+ glBegin(GL_POINTS);
+ for (j = 0; j <= stacks; j++) {
+ sintemp1 = sinCache1b[j];
+ costemp1 = cosCache1b[j];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ sintemp2 = sinCache2b[j];
+ costemp2 = cosCache2b[j];
+ break;
+ default:
+ break;
+ }
+ for (i = 0; i < slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp2,
+ cosCache2a[i] * sintemp2,
+ costemp2);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+
+ zLow = j * radius / stacks;
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) j / stacks);
+ }
+ glVertex3f(sintemp1 * sinCache1a[i],
+ sintemp1 * cosCache1a[i], costemp1);
+ }
+ }
+ glEnd();
+ break;
+ case GLU_LINE:
+ case GLU_SILHOUETTE:
+ for (j = 1; j < stacks; j++) {
+ sintemp1 = sinCache1b[j];
+ costemp1 = cosCache1b[j];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ sintemp2 = sinCache2b[j];
+ costemp2 = cosCache2b[j];
+ break;
+ default:
+ break;
+ }
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0; i <= slices; i++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ glNormal3f(sinCache3a[i] * sintemp2,
+ cosCache3a[i] * sintemp2,
+ costemp2);
+ break;
+ case GLU_SMOOTH:
+ glNormal3f(sinCache2a[i] * sintemp2,
+ cosCache2a[i] * sintemp2,
+ costemp2);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) j / stacks);
+ }
+ glVertex3f(sintemp1 * sinCache1a[i],
+ sintemp1 * cosCache1a[i], costemp1);
+ }
+ glEnd();
+ }
+ for (i = 0; i < slices; i++) {
+ sintemp1 = sinCache1a[i];
+ costemp1 = cosCache1a[i];
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ case GLU_SMOOTH:
+ sintemp2 = sinCache2a[i];
+ costemp2 = cosCache2a[i];
+ break;
+ default:
+ break;
+ }
+
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j <= stacks; j++) {
+ switch(qobj->normals) {
+ case GLU_FLAT:
+ glNormal3f(sintemp2 * sinCache3b[j],
+ costemp2 * sinCache3b[j],
+ cosCache3b[j]);
+ break;
+ case GLU_SMOOTH:
+ glNormal3f(sintemp2 * sinCache2b[j],
+ costemp2 * sinCache2b[j],
+ cosCache2b[j]);
+ break;
+ case GLU_NONE:
+ default:
+ break;
+ }
+
+ if (qobj->textureCoords) {
+ glTexCoord2f(1 - (float) i / slices,
+ 1 - (float) j / stacks);
+ }
+ glVertex3f(sintemp1 * sinCache1b[j],
+ costemp1 * sinCache1b[j], cosCache1b[j]);
+ }
+ glEnd();
+ }
+ break;
+ default:
+ break;
+ }
+}
diff --git a/mesalib/src/glu/sgi/libutil/registry.c b/mesalib/src/glu/sgi/libutil/registry.c
new file mode 100644
index 000000000..2e3b574fb
--- /dev/null
+++ b/mesalib/src/glu/sgi/libutil/registry.c
@@ -0,0 +1,91 @@
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#include "gluos.h"
+#include <GL/glu.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const GLubyte versionString[] = "1.3";
+static const GLubyte extensionString[] =
+ "GLU_EXT_nurbs_tessellator "
+ "GLU_EXT_object_space_tess "
+ ;
+
+const GLubyte * GLAPIENTRY
+gluGetString(GLenum name)
+{
+
+ if (name == GLU_VERSION) {
+ return versionString;
+ } else if (name == GLU_EXTENSIONS) {
+ return extensionString;
+ }
+ return NULL;
+}
+
+/* extName is an extension name.
+ * extString is a string of extensions separated by blank(s). There may or
+ * may not be leading or trailing blank(s) in extString.
+ * This works in cases of extensions being prefixes of another like
+ * GL_EXT_texture and GL_EXT_texture3D.
+ * Returns GL_TRUE if extName is found otherwise it returns GL_FALSE.
+ */
+GLboolean GLAPIENTRY
+gluCheckExtension(const GLubyte *extName, const GLubyte *extString)
+{
+ GLboolean flag = GL_FALSE;
+ char *word;
+ char *lookHere;
+ char *deleteThis;
+
+ if (extString == NULL) return GL_FALSE;
+
+ deleteThis = lookHere = (char *)malloc(strlen((const char *)extString)+1);
+ if (lookHere == NULL)
+ return GL_FALSE;
+ /* strtok() will modify string, so copy it somewhere */
+ strcpy(lookHere,(const char *)extString);
+
+ while ((word= strtok(lookHere," ")) != NULL) {
+ if (strcmp(word,(const char *)extName) == 0) {
+ flag = GL_TRUE;
+ break;
+ }
+ lookHere = NULL; /* get next token */
+ }
+ free((void *)deleteThis);
+ return flag;
+} /* gluCheckExtension() */
+
+
+
+/*** registry.c ***/
diff --git a/mesalib/src/mesa/Makefile b/mesalib/src/mesa/Makefile
new file mode 100644
index 000000000..8300b3014
--- /dev/null
+++ b/mesalib/src/mesa/Makefile
@@ -0,0 +1,166 @@
+# src/mesa/Makefile
+
+TOP = ../..
+include $(TOP)/configs/current
+
+include sources.mak
+
+.SUFFIXES : .cpp
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+.cpp.o:
+ $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+
+
+# Default: build dependencies, then asm_subdirs, then convenience
+# libs (.a) and finally the device drivers:
+default: depend asm_subdirs libmesa.a libmesagallium.a libglapi.a \
+ driver_subdirs
+
+
+
+######################################################################
+# Helper libraries used by many drivers:
+
+# Make archive of core mesa object files
+libmesa.a: $(MESA_OBJECTS)
+ @ $(MKLIB) -o mesa -static $(MESA_OBJECTS)
+
+# Make archive of subset of core mesa object files for gallium
+libmesagallium.a: $(MESA_GALLIUM_OBJECTS)
+ @ $(MKLIB) -o mesagallium -static $(MESA_GALLIUM_OBJECTS)
+
+# Make archive of gl* API dispatcher functions only
+libglapi.a: $(GLAPI_OBJECTS)
+ @if [ "${WINDOW_SYSTEM}" = "dri" ] ; then \
+ touch libglapi.a ; \
+ else \
+ $(MKLIB) -o glapi -static $(GLAPI_OBJECTS) ; \
+ fi
+
+######################################################################
+# Device drivers
+driver_subdirs: libmesa.a libglapi.a
+ @ (cd drivers && $(MAKE))
+
+
+######################################################################
+# Assembly subdirs
+asm_subdirs:
+ @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_ASM ; then \
+ (cd x86 && $(MAKE)) || exit 1 ; \
+ fi
+ @ if echo "$(ASM_FLAGS)" | grep -q USE_X86_64_ASM ; then \
+ (cd x86 && $(MAKE)) || exit 1 ; \
+ (cd x86-64 && $(MAKE)) || exit 1 ; \
+ fi
+
+
+######################################################################
+# Dependency generation
+
+depend: $(ALL_SOURCES)
+ @ echo "running $(MKDEP)"
+ @ touch depend
+ @$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \
+ > /dev/null 2>/dev/null
+
+
+######################################################################
+# Installation rules
+
+# this isn't fleshed out yet but is probably the way to go in the future
+new_install:
+ (cd drivers && $(MAKE) install)
+
+
+# XXX replace this with new_install above someday
+install: default
+ @for driver in $(DRIVER_DIRS) ; do \
+ case "$$driver" in \
+ osmesa) if [ "$(DRIVER_DIRS)" = osmesa ]; then \
+ $(MAKE) install-headers install-osmesa || exit 1 ; \
+ else \
+ $(MAKE) install-osmesa || exit 1 ; \
+ fi ;; \
+ dri) $(MAKE) install-libgl install-dri || exit 1 ;; \
+ *) $(MAKE) install-libgl || exit 1 ;; \
+ esac ; \
+ done
+
+
+gl_pcedit = sed \
+ -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \
+ -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \
+ -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \
+ -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
+ -e 's,@GL_PC_REQ_PRIV@,$(GL_PC_REQ_PRIV),' \
+ -e 's,@GL_PC_LIB_PRIV@,$(GL_PC_LIB_PRIV),' \
+ -e 's,@GL_PC_CFLAGS@,$(GL_PC_CFLAGS),' \
+ -e 's,@GL_LIB@,$(GL_LIB),'
+
+gl.pc: gl.pc.in
+ $(gl_pcedit) $< > $@
+
+osmesa_pcedit = sed \
+ -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \
+ -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \
+ -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \
+ -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
+ -e 's,@OSMESA_LIB@,$(OSMESA_LIB),' \
+ -e 's,@OSMESA_PC_REQ@,$(OSMESA_PC_REQ),' \
+ -e 's,@OSMESA_PC_LIB_PRIV@,$(OSMESA_PC_LIB_PRIV),'
+
+osmesa.pc: osmesa.pc.in
+ $(osmesa_pcedit) $< > $@
+
+install-headers:
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/GL
+ $(INSTALL) -m 644 $(TOP)/include/GL/*.h \
+ $(DESTDIR)$(INSTALL_INC_DIR)/GL
+
+install-libgl: default gl.pc install-headers
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(GL_LIB_GLOB) \
+ $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -m 644 gl.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+install-osmesa: default osmesa.pc
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(MINSTALL) $(TOP)/$(LIB_DIR)/$(OSMESA_LIB_GLOB) \
+ $(DESTDIR)$(INSTALL_LIB_DIR)
+ $(INSTALL) -m 644 osmesa.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+install-dri: default
+ cd drivers/dri && $(MAKE) install
+
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` $(TOP)/include/GL/*.h
+
+
+clean:
+ -rm -f */*.o
+ -rm -f */*/*.o
+ -rm -f depend depend.bak libmesa.a libglapi.a
+ -rm -f drivers/*/*.o
+ -rm -f *.pc
+ -@cd drivers/dri && $(MAKE) clean
+ -@cd drivers/x11 && $(MAKE) clean
+ -@cd drivers/osmesa && $(MAKE) clean
+ -@cd x86 && $(MAKE) clean
+ -@cd x86-64 && $(MAKE) clean
+
+
+-include depend
diff --git a/mesalib/src/mesa/Makefile.mgw b/mesalib/src/mesa/Makefile.mgw
new file mode 100644
index 000000000..097c390a8
--- /dev/null
+++ b/mesalib/src/mesa/Makefile.mgw
@@ -0,0 +1,235 @@
+# Mesa 3-D graphics library
+# Version: 7.0
+#
+# Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# MinGW core makefile v1.4 for Mesa
+#
+# Copyright (C) 2002 - Daniel Borca
+# Email : dborca@users.sourceforge.net
+# Web : http://www.geocities.com/dborca
+
+# MinGW core-gl makefile updated for Mesa 7.0
+#
+# updated : by Heromyth, on 2007-7-21
+# Email : zxpmyth@yahoo.com.cn
+# Bugs : 1) All the default settings work fine. But the setting X86=1 can't work.
+# The others havn't been tested yet.
+# 2) The generated DLLs are *not* compatible with the ones built
+# with the other compilers like VC8, especially for GLUT.
+# 3) Although more tests are needed, it can be used individually!
+
+
+#
+# Available options:
+#
+# Environment variables:
+# CFLAGS
+#
+# GLIDE path to Glide3 SDK; used with FX.
+# default = $(TOP)/glide3
+# FX=1 build for 3dfx Glide3. Note that this disables
+# compilation of most WMesa code and requires fxMesa.
+# As a consequence, you'll need the Win32 Glide3
+# library to build any application.
+# default = no
+# ICD=1 build the installable client driver interface
+# (windows opengl driver interface)
+# default = no
+# X86=1 optimize for x86 (if possible, use MMX, SSE, 3DNow).
+# default = no
+#
+# Targets:
+# all: build GL
+# clean: remove object files
+#
+
+
+.PHONY: all clean
+.INTERMEDIATE: x86/gen_matypes.exe
+.SUFFIXES: .rc .res
+
+# Set this to the prefix of your build tools, i.e. mingw32-
+TOOLS_PREFIX = mingw32-
+
+ifeq ($(ICD),1)
+ LIB_NAME = mesa32
+else
+ LIB_NAME = opengl32
+endif
+
+DLL_EXT = .dll
+IMP_EXT = .a
+LIB_PRE = lib
+STRIP = -s
+
+AR = ar
+ARFLAGS = crus
+DLLTOOL = dlltool
+
+TOP = ../..
+GLIDE ?= $(TOP)/glide3
+LIBDIR = $(TOP)/lib
+
+GL_DLL = $(LIB_NAME)$(DLL_EXT)
+GL_IMP = $(LIB_PRE)$(LIB_NAME)$(IMP_EXT)
+
+MESA_LIB = libmesa.a
+CC = $(TOOLS_PREFIX)gcc
+
+LDLIBS = -lgdi32 -luser32 -liberty
+LDFLAGS = $(STRIP) -shared -fPIC -Wl,--kill-at
+
+CFLAGS += -DBUILD_GL32 -D_DLL -DMESA_MINWARN
+CFLAGS += -DNDEBUG -DUSE_EXTERNAL_DXTN_LIB=1
+
+ifeq ($(FX),1)
+ CFLAGS += -I$(GLIDE)/include -DFX
+ LDLIBS += -L$(GLIDE)/lib -lglide3x
+ GL_DEF = drivers/windows/fx/fxopengl.def
+ GL_RES = drivers/windows/fx/fx.rc
+else
+ ifeq ($(ICD),1)
+ CFLAGS += -DUSE_MGL_NAMESPACE
+ GL_DEF = drivers/windows/icd/mesa.def
+ else
+ GL_DEF = $(LIB_NAME).def
+ endif
+endif
+
+
+
+UNLINK = del $(subst /,\,$(1))
+ifneq ($(wildcard $(addsuffix /rm.exe,$(subst ;, ,$(PATH)))),)
+UNLINK = $(RM) $(1)
+endif
+ifneq ($(wildcard $(addsuffix /rm,$(subst :, ,$(PATH)))),)
+UNLINK = $(RM) $(1)
+endif
+
+include sources.mak
+
+CFLAGS += $(INCLUDE_DIRS)
+
+ifeq ($(X86),1)
+CFLAGS += -DUSE_X86_ASM
+CFLAGS += -DUSE_MMX_ASM
+CFLAGS += -DUSE_SSE_ASM
+CFLAGS += -DUSE_3DNOW_ASM
+X86_SOURCES += $(X86_API)
+else
+X86_SOURCES =
+endif
+
+ifeq ($(FX),1)
+DRIVER_SOURCES = \
+ $(GLIDE_DRIVER_SOURCES) \
+ drivers/windows/fx/fxwgl.c
+else
+ifeq ($(ICD),1)
+DRIVER_SOURCES = \
+ drivers/windows/gdi/wmesa.c \
+ drivers/windows/icd/icd.c
+else
+DRIVER_SOURCES = \
+ drivers/windows/gdi/wmesa.c \
+ drivers/windows/gdi/wgl.c
+endif
+endif
+
+SOURCES = $(MESA_SOURCES) $(GLAPI_SOURCES) $(X86_SOURCES) $(DRIVER_SOURCES)
+
+OBJECTS = $(addsuffix .o,$(basename $(SOURCES)))
+
+X86_OBJECTS = $(addsuffix .o,$(basename $(X86_SOURCES)))
+
+RESOURCE = $(GL_RES:.rc=.res)
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) -c $<
+.s.o:
+ $(CC) -o $@ $(CFLAGS) -x assembler-with-cpp -c $<
+
+.rc.res:
+ windres -o $@ -Irc -Ocoff $<
+
+
+all: $(LIBDIR) $(LIBDIR)/$(GL_DLL) $(LIBDIR)/$(GL_IMP)
+
+$(LIBDIR):
+ mkdir -p $(LIBDIR)
+
+$(LIBDIR)/$(GL_DLL) $(LIBDIR)/$(GL_IMP): $(OBJECTS) $(RESOURCE)
+ $(CC) $(LDFLAGS) -o $(LIBDIR)/$(GL_DLL) $^ $(LDLIBS)
+ $(DLLTOOL) --as=as --dllname $(LIB_NAME) --output-def $(LIBDIR)/$(GL_DEF) $^
+ $(DLLTOOL) --as=as -k --dllname $(LIB_NAME) --output-lib $(LIBDIR)/$(GL_IMP) --def $(LIBDIR)/$(GL_DEF)
+
+
+$(X86_OBJECTS): x86/matypes.h
+
+x86/matypes.h: x86/gen_matypes.exe
+ $(subst /,\,$< > $@)
+
+x86/gen_matypes.exe: x86/gen_matypes.c
+ $(CC) -o $@ $(CFLAGS) -s $<
+
+# [dBorca]
+# glapi_x86.S needs some adjustments
+# in order to generate correct entrypoints
+# Trick: change the following condition to
+# be always false if you need C entrypoints
+# with USE_X86_ASM (useful for trace/debug)
+ifeq (1,1)
+x86/glapi_x86.o: x86/glapi_x86.S
+ $(CC) -o $@ $(CFLAGS) -DSTDCALL_API -c $<
+else
+main/dispatch.o: main/dispatch.c
+ $(CC) -o $@ $(CFLAGS) -UUSE_X86_ASM -c $<
+glapi/glapi.o: glapi/glapi.c
+ $(CC) -o $@ $(CFLAGS) -UUSE_X86_ASM -c $<
+endif
+
+# [dBorca]
+# if we want codegen, we have to stdcall
+tnl/t_vtx_x86_gcc.o: tnl/t_vtx_x86_gcc.S
+ $(CC) -o $@ $(CFLAGS) -DSTDCALL_API -c $<
+
+clean:
+ -$(call UNLINK,glapi/*.o)
+ -$(call UNLINK,main/*.o)
+ -$(call UNLINK,math/*.o)
+ -$(call UNLINK,vbo/*.o)
+ -$(call UNLINK,shader/*.o)
+ -$(call UNLINK,shader/slang/*.o)
+ -$(call UNLINK,shader/grammar/*.o)
+ -$(call UNLINK,sparc/*.o)
+ -$(call UNLINK,ppc/*.o)
+ -$(call UNLINK,swrast/*.o)
+ -$(call UNLINK,swrast_setup/*.o)
+ -$(call UNLINK,tnl/*.o)
+ -$(call UNLINK,x86/*.o)
+ -$(call UNLINK,x86/rtasm/*.o)
+ -$(call UNLINK,x86-64/*.o)
+ -$(call UNLINK,drivers/common/*.o)
+ -$(call UNLINK,drivers/glide/*.o)
+ -$(call UNLINK,drivers/windows/fx/*.o)
+ -$(call UNLINK,drivers/windows/fx/*.res)
+ -$(call UNLINK,drivers/windows/gdi/*.o)
+ -$(call UNLINK,drivers/windows/icd/*.o)
diff --git a/mesalib/src/mesa/depend b/mesalib/src/mesa/depend
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/mesalib/src/mesa/depend
diff --git a/mesalib/src/mesa/descrip.mms b/mesalib/src/mesa/descrip.mms
new file mode 100644
index 000000000..dbfa336a9
--- /dev/null
+++ b/mesalib/src/mesa/descrip.mms
@@ -0,0 +1,27 @@
+# Makefile for Mesa for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Date last revision : 7 March 2007
+
+all :
+ set default [.main]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.glapi]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.shader]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.drivers.common]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.x11]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.osmesa]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [--.math]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.tnl]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.swrast]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.swrast_setup]
+ $(MMS)$(MMSQUALIFIERS)
+ set default [-.vbo]
+ $(MMS)$(MMSQUALIFIERS)
diff --git a/mesalib/src/mesa/drivers/Makefile b/mesalib/src/mesa/drivers/Makefile
new file mode 100644
index 000000000..c5998413e
--- /dev/null
+++ b/mesalib/src/mesa/drivers/Makefile
@@ -0,0 +1,29 @@
+# src/mesa/drivers/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+
+default:
+ @for dir in $(DRIVER_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1; \
+ fi \
+ done
+
+
+clean:
+ @for dir in $(DRIVER_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) clean) || exit 1; \
+ fi \
+ done
+
+
+install:
+ @for dir in $(DRIVER_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) install) || exit 1; \
+ fi \
+ done
+
diff --git a/mesalib/src/mesa/drivers/common/descrip.mms b/mesalib/src/mesa/drivers/common/descrip.mms
new file mode 100644
index 000000000..d5bbc69df
--- /dev/null
+++ b/mesalib/src/mesa/drivers/common/descrip.mms
@@ -0,0 +1,42 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 29 September 2008
+
+.first
+ define gl [----.include.gl]
+ define math [--.math]
+ define tnl [--.tnl]
+ define swrast [--.swrast]
+ define glapi [--.glapi]
+ define shader [--.shader]
+ define main [--.main]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi],[--.shader]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)\
+ /float=ieee/ieee=denorm/warn=disable=(PTRMISMATCH)
+
+SOURCES = driverfuncs.c
+
+OBJECTS =driverfuncs.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+driverfuncs.obj : driverfuncs.c
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c
new file mode 100644
index 000000000..a9f3c8e72
--- /dev/null
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.c
@@ -0,0 +1,353 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/imports.h"
+#include "main/arrayobj.h"
+#include "main/buffers.h"
+#include "main/context.h"
+#include "main/framebuffer.h"
+#include "main/mipmap.h"
+#include "main/queryobj.h"
+#include "main/renderbuffer.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+#include "main/texgetimage.h"
+#include "main/teximage.h"
+#include "main/texobj.h"
+#include "main/texstore.h"
+#if FEATURE_ARB_vertex_buffer_object
+#include "main/bufferobj.h"
+#endif
+#if FEATURE_EXT_framebuffer_object
+#include "main/fbobject.h"
+#include "main/texrender.h"
+#endif
+#if FEATURE_ARB_sync
+#include "main/syncobj.h"
+#endif
+
+#include "shader/program.h"
+#include "shader/prog_execute.h"
+#include "shader/shader_api.h"
+#include "tnl/tnl.h"
+#include "swrast/swrast.h"
+
+#include "driverfuncs.h"
+
+
+
+/**
+ * Plug in default functions for all pointers in the dd_function_table
+ * structure.
+ * Device drivers should call this function and then plug in any
+ * functions which it wants to override.
+ * Some functions (pointers) MUST be implemented by all drivers (REQUIRED).
+ *
+ * \param table the dd_function_table to initialize
+ */
+void
+_mesa_init_driver_functions(struct dd_function_table *driver)
+{
+ _mesa_bzero(driver, sizeof(*driver));
+
+ driver->GetString = NULL; /* REQUIRED! */
+ driver->UpdateState = NULL; /* REQUIRED! */
+ driver->GetBufferSize = NULL; /* REQUIRED! */
+ driver->ResizeBuffers = _mesa_resize_framebuffer;
+ driver->Error = NULL;
+
+ driver->Finish = NULL;
+ driver->Flush = NULL;
+
+ /* framebuffer/image functions */
+ driver->Clear = _swrast_Clear;
+ driver->Accum = _swrast_Accum;
+ driver->RasterPos = _tnl_RasterPos;
+ driver->DrawPixels = _swrast_DrawPixels;
+ driver->ReadPixels = _swrast_ReadPixels;
+ driver->CopyPixels = _swrast_CopyPixels;
+ driver->Bitmap = _swrast_Bitmap;
+
+ /* Texture functions */
+ driver->ChooseTextureFormat = _mesa_choose_tex_format;
+ driver->TexImage1D = _mesa_store_teximage1d;
+ driver->TexImage2D = _mesa_store_teximage2d;
+ driver->TexImage3D = _mesa_store_teximage3d;
+ driver->TexSubImage1D = _mesa_store_texsubimage1d;
+ driver->TexSubImage2D = _mesa_store_texsubimage2d;
+ driver->TexSubImage3D = _mesa_store_texsubimage3d;
+ driver->GetTexImage = _mesa_get_teximage;
+ driver->CopyTexImage1D = _swrast_copy_teximage1d;
+ driver->CopyTexImage2D = _swrast_copy_teximage2d;
+ driver->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ driver->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ driver->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ driver->GenerateMipmap = _mesa_generate_mipmap;
+ driver->TestProxyTexImage = _mesa_test_proxy_teximage;
+ driver->CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+ driver->CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+ driver->CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+ driver->CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+ driver->CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+ driver->CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+ driver->GetCompressedTexImage = _mesa_get_compressed_teximage;
+ driver->CompressedTextureSize = _mesa_compressed_texture_size;
+ driver->BindTexture = NULL;
+ driver->NewTextureObject = _mesa_new_texture_object;
+ driver->DeleteTexture = _mesa_delete_texture_object;
+ driver->NewTextureImage = _mesa_new_texture_image;
+ driver->FreeTexImageData = _mesa_free_texture_image_data;
+ driver->MapTexture = NULL;
+ driver->UnmapTexture = NULL;
+ driver->TextureMemCpy = _mesa_memcpy;
+ driver->IsTextureResident = NULL;
+ driver->PrioritizeTexture = NULL;
+ driver->ActiveTexture = NULL;
+ driver->UpdateTexturePalette = NULL;
+
+ /* imaging */
+ driver->CopyColorTable = _swrast_CopyColorTable;
+ driver->CopyColorSubTable = _swrast_CopyColorSubTable;
+ driver->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ driver->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ /* Vertex/fragment programs */
+ driver->BindProgram = NULL;
+ driver->NewProgram = _mesa_new_program;
+ driver->DeleteProgram = _mesa_delete_program;
+
+ /* simple state commands */
+ driver->AlphaFunc = NULL;
+ driver->BlendColor = NULL;
+ driver->BlendEquationSeparate = NULL;
+ driver->BlendFuncSeparate = NULL;
+ driver->ClearColor = NULL;
+ driver->ClearDepth = NULL;
+ driver->ClearIndex = NULL;
+ driver->ClearStencil = NULL;
+ driver->ClipPlane = NULL;
+ driver->ColorMask = NULL;
+ driver->ColorMaterial = NULL;
+ driver->CullFace = NULL;
+ driver->DrawBuffer = NULL;
+ driver->DrawBuffers = NULL;
+ driver->FrontFace = NULL;
+ driver->DepthFunc = NULL;
+ driver->DepthMask = NULL;
+ driver->DepthRange = NULL;
+ driver->Enable = NULL;
+ driver->Fogfv = NULL;
+ driver->Hint = NULL;
+ driver->IndexMask = NULL;
+ driver->Lightfv = NULL;
+ driver->LightModelfv = NULL;
+ driver->LineStipple = NULL;
+ driver->LineWidth = NULL;
+ driver->LogicOpcode = NULL;
+ driver->PointParameterfv = NULL;
+ driver->PointSize = NULL;
+ driver->PolygonMode = NULL;
+ driver->PolygonOffset = NULL;
+ driver->PolygonStipple = NULL;
+ driver->ReadBuffer = NULL;
+ driver->RenderMode = NULL;
+ driver->Scissor = NULL;
+ driver->ShadeModel = NULL;
+ driver->StencilFuncSeparate = NULL;
+ driver->StencilOpSeparate = NULL;
+ driver->StencilMaskSeparate = NULL;
+ driver->TexGen = NULL;
+ driver->TexEnv = NULL;
+ driver->TexParameter = NULL;
+ driver->TextureMatrix = NULL;
+ driver->Viewport = NULL;
+
+ /* vertex arrays */
+ driver->VertexPointer = NULL;
+ driver->NormalPointer = NULL;
+ driver->ColorPointer = NULL;
+ driver->FogCoordPointer = NULL;
+ driver->IndexPointer = NULL;
+ driver->SecondaryColorPointer = NULL;
+ driver->TexCoordPointer = NULL;
+ driver->EdgeFlagPointer = NULL;
+ driver->VertexAttribPointer = NULL;
+ driver->LockArraysEXT = NULL;
+ driver->UnlockArraysEXT = NULL;
+
+ /* state queries */
+ driver->GetBooleanv = NULL;
+ driver->GetDoublev = NULL;
+ driver->GetFloatv = NULL;
+ driver->GetIntegerv = NULL;
+ driver->GetInteger64v = NULL;
+ driver->GetPointerv = NULL;
+
+ /* buffer objects */
+ _mesa_init_buffer_object_functions(driver);
+
+ /* query objects */
+ _mesa_init_query_object_functions(driver);
+
+#if FEATURE_ARB_sync
+ _mesa_init_sync_object_functions(driver);
+#endif
+
+#if FEATURE_EXT_framebuffer_object
+ driver->NewFramebuffer = _mesa_new_framebuffer;
+ driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
+ driver->RenderTexture = _mesa_render_texture;
+ driver->FinishRenderTexture = _mesa_finish_render_texture;
+ driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
+#endif
+
+#if FEATURE_EXT_framebuffer_blit
+ driver->BlitFramebuffer = _swrast_BlitFramebuffer;
+#endif
+
+ /* APPLE_vertex_array_object */
+ driver->NewArrayObject = _mesa_new_array_object;
+ driver->DeleteArrayObject = _mesa_delete_array_object;
+ driver->BindArrayObject = NULL;
+
+ /* T&L stuff */
+ driver->NeedValidate = GL_FALSE;
+ driver->ValidateTnlModule = NULL;
+ driver->CurrentExecPrimitive = 0;
+ driver->CurrentSavePrimitive = 0;
+ driver->NeedFlush = 0;
+ driver->SaveNeedFlush = 0;
+
+ driver->ProgramStringNotify = _tnl_program_string;
+ driver->FlushVertices = NULL;
+ driver->SaveFlushVertices = NULL;
+ driver->NotifySaveBegin = NULL;
+ driver->LightingSpaceChange = NULL;
+
+ /* display list */
+ driver->NewList = NULL;
+ driver->EndList = NULL;
+ driver->BeginCallList = NULL;
+ driver->EndCallList = NULL;
+
+
+ /* XXX temporary here */
+ _mesa_init_glsl_driver_functions(driver);
+}
+
+
+/**
+ * Call the ctx->Driver.* state functions with current values to initialize
+ * driver state.
+ * Only the Intel drivers use this so far.
+ */
+void
+_mesa_init_driver_state(GLcontext *ctx)
+{
+ ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
+
+ ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
+
+ ctx->Driver.BlendEquationSeparate(ctx,
+ ctx->Color.BlendEquationRGB,
+ ctx->Color.BlendEquationA);
+
+ ctx->Driver.BlendFuncSeparate(ctx,
+ ctx->Color.BlendSrcRGB,
+ ctx->Color.BlendDstRGB,
+ ctx->Color.BlendSrcA, ctx->Color.BlendDstA);
+
+ ctx->Driver.ColorMask(ctx,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
+ ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
+ ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
+
+ ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
+ ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
+ ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
+ ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
+ ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
+ ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
+ ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag);
+ ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled);
+ ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled);
+ ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
+ ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
+ ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled);
+ ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil._Enabled);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+ ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+
+ ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
+ ctx->Driver.Fogfv(ctx, GL_FOG_MODE, 0);
+ ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
+ ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
+ ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
+
+ ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+
+ {
+ GLfloat f = (GLfloat) ctx->Light.Model.ColorControl;
+ ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f);
+ }
+
+ ctx->Driver.LineWidth(ctx, ctx->Line.Width);
+ ctx->Driver.LogicOpcode(ctx, ctx->Color.LogicOp);
+ ctx->Driver.PointSize(ctx, ctx->Point.Size);
+ ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple);
+ ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel);
+ ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
+ ctx->Stencil.Function[0],
+ ctx->Stencil.Ref[0],
+ ctx->Stencil.ValueMask[0]);
+ ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
+ ctx->Stencil.Function[1],
+ ctx->Stencil.Ref[1],
+ ctx->Stencil.ValueMask[1]);
+ ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]);
+ ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]);
+ ctx->Driver.StencilOpSeparate(ctx, GL_FRONT,
+ ctx->Stencil.FailFunc[0],
+ ctx->Stencil.ZFailFunc[0],
+ ctx->Stencil.ZPassFunc[0]);
+ ctx->Driver.StencilOpSeparate(ctx, GL_BACK,
+ ctx->Stencil.FailFunc[1],
+ ctx->Stencil.ZFailFunc[1],
+ ctx->Stencil.ZPassFunc[1]);
+
+
+ ctx->Driver.DrawBuffer(ctx, ctx->Color.DrawBuffer[0]);
+}
diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.h b/mesalib/src/mesa/drivers/common/driverfuncs.h
new file mode 100644
index 000000000..4c90ed12f
--- /dev/null
+++ b/mesalib/src/mesa/drivers/common/driverfuncs.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 DRIVERFUNCS_H
+#define DRIVERFUNCS_H
+
+extern void
+_mesa_init_driver_functions(struct dd_function_table *driver);
+
+
+extern void
+_mesa_init_driver_state(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
new file mode 100644
index 000000000..2741a41bf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -0,0 +1,1638 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * Meta operations. Some GL operations can be expressed in terms of
+ * other GL operations. For example, glBlitFramebuffer() can be done
+ * with texture mapping and glClear() can be done with polygon rendering.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "main/arrayobj.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/depth.h"
+#include "main/enable.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/matrix.h"
+#include "main/polygon.h"
+#include "main/readpix.h"
+#include "main/scissor.h"
+#include "main/shaders.h"
+#include "main/stencil.h"
+#include "main/texobj.h"
+#include "main/texenv.h"
+#include "main/teximage.h"
+#include "main/texparam.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "shader/program.h"
+#include "shader/arbprogram.h"
+#include "swrast/swrast.h"
+#include "drivers/common/meta.h"
+
+
+/**
+ * State which we may save/restore across meta ops.
+ * XXX this may be incomplete...
+ */
+struct save_state
+{
+ GLbitfield SavedState; /**< bitmask of META_* flags */
+
+ /** META_ALPHA_TEST */
+ GLboolean AlphaEnabled;
+
+ /** META_BLEND */
+ GLboolean BlendEnabled;
+ GLboolean ColorLogicOpEnabled;
+
+ /** META_COLOR_MASK */
+ GLubyte ColorMask[4];
+
+ /** META_DEPTH_TEST */
+ struct gl_depthbuffer_attrib Depth;
+
+ /** META_FOG */
+ GLboolean Fog;
+
+ /** META_PIXEL_STORE */
+ struct gl_pixelstore_attrib Pack, Unpack;
+
+ /** META_RASTERIZATION */
+ GLenum FrontPolygonMode, BackPolygonMode;
+ GLboolean PolygonOffset;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean PolygonCull;
+
+ /** META_SCISSOR */
+ struct gl_scissor_attrib Scissor;
+
+ /** META_SHADER */
+ GLboolean VertexProgramEnabled;
+ struct gl_vertex_program *VertexProgram;
+ GLboolean FragmentProgramEnabled;
+ struct gl_fragment_program *FragmentProgram;
+ GLuint Shader;
+
+ /** META_STENCIL_TEST */
+ struct gl_stencil_attrib Stencil;
+
+ /** META_TRANSFORM */
+ GLenum MatrixMode;
+ GLfloat ModelviewMatrix[16];
+ GLfloat ProjectionMatrix[16];
+ GLfloat TextureMatrix[16];
+ GLbitfield ClipPlanesEnabled;
+
+ /** META_TEXTURE */
+ GLuint ActiveUnit;
+ GLuint ClientActiveUnit;
+ /** for unit[0] only */
+ struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS];
+ /** mask of TEXTURE_2D_BIT, etc */
+ GLbitfield TexEnabled[MAX_TEXTURE_UNITS];
+ GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS];
+ GLuint EnvMode; /* unit[0] only */
+
+ /** META_VERTEX */
+ struct gl_array_object *ArrayObj;
+ struct gl_buffer_object *ArrayBufferObj;
+
+ /** META_VIEWPORT */
+ GLint ViewportX, ViewportY, ViewportW, ViewportH;
+ GLclampd DepthNear, DepthFar;
+
+ /** Miscellaneous (always disabled) */
+ GLboolean Lighting;
+};
+
+
+/**
+ * State for glBlitFramebufer()
+ */
+struct blit_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+ GLuint DepthFP;
+};
+
+
+/**
+ * State for glClear()
+ */
+struct clear_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glCopyPixels()
+ */
+struct copypix_state
+{
+ GLuint ArrayObj;
+ GLuint VBO;
+};
+
+
+/**
+ * State for glDrawPixels()
+ */
+struct drawpix_state
+{
+ GLuint ArrayObj;
+
+ GLuint StencilFP; /**< Fragment program for drawing stencil images */
+ GLuint DepthFP; /**< Fragment program for drawing depth images */
+};
+
+
+/**
+ * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc.
+ * This is currently shared by all the meta ops. But we could create a
+ * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc.
+ */
+struct temp_texture
+{
+ GLuint TexObj;
+ GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */
+ GLsizei MaxSize; /**< Max possible texture size */
+ GLboolean NPOT; /**< Non-power of two size OK? */
+ GLsizei Width, Height; /**< Current texture size */
+ GLenum IntFormat;
+ GLfloat Sright, Ttop; /**< right, top texcoords */
+};
+
+
+/**
+ * All per-context meta state.
+ */
+struct gl_meta_state
+{
+ struct save_state Save; /**< state saved during meta-ops */
+
+ struct temp_texture TempTex;
+
+ struct blit_state Blit; /**< For _mesa_meta_blit_framebuffer() */
+ struct clear_state Clear; /**< For _mesa_meta_clear() */
+ struct copypix_state CopyPix; /**< For _mesa_meta_copy_pixels() */
+ struct drawpix_state DrawPix; /**< For _mesa_meta_draw_pixels() */
+
+ /* other possible meta-ops:
+ * glBitmap()
+ * glGenerateMipmap()
+ */
+};
+
+
+/**
+ * Initialize meta-ops for a context.
+ * To be called once during context creation.
+ */
+void
+_mesa_meta_init(GLcontext *ctx)
+{
+ ASSERT(!ctx->Meta);
+
+ ctx->Meta = CALLOC_STRUCT(gl_meta_state);
+}
+
+
+/**
+ * Free context meta-op state.
+ * To be called once during context destruction.
+ */
+void
+_mesa_meta_free(GLcontext *ctx)
+{
+ struct gl_meta_state *meta = ctx->Meta;
+
+ if (_mesa_get_current_context()) {
+ /* if there's no current context, these textures, buffers, etc should
+ * still get freed by _mesa_free_context_data().
+ */
+
+ _mesa_DeleteTextures(1, &meta->TempTex.TexObj);
+
+ /* glBlitFramebuffer */
+ _mesa_DeleteBuffersARB(1, & meta->Blit.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->Blit.DepthFP);
+
+ /* glClear */
+ _mesa_DeleteBuffersARB(1, & meta->Clear.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj);
+
+ /* glCopyPixels */
+ _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj);
+
+ /* glDrawPixels */
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->DrawPix.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->DrawPix.DepthFP);
+ _mesa_DeletePrograms(1, &meta->DrawPix.StencilFP);
+ }
+
+ _mesa_free(ctx->Meta);
+ ctx->Meta = NULL;
+}
+
+
+/**
+ * Enter meta state. This is like a light-weight version of glPushAttrib
+ * but it also resets most GL state back to default values.
+ *
+ * \param state bitmask of META_* flags indicating which attribute groups
+ * to save and reset to their defaults
+ */
+static void
+_mesa_meta_begin(GLcontext *ctx, GLbitfield state)
+{
+ struct save_state *save = &ctx->Meta->Save;
+
+ save->SavedState = state;
+
+ if (state & META_ALPHA_TEST) {
+ save->AlphaEnabled = ctx->Color.AlphaEnabled;
+ if (ctx->Color.AlphaEnabled)
+ _mesa_Disable(GL_ALPHA_TEST);
+ }
+
+ if (state & META_BLEND) {
+ save->BlendEnabled = ctx->Color.BlendEnabled;
+ if (ctx->Color.BlendEnabled)
+ _mesa_Disable(GL_BLEND);
+ save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled;
+ if (ctx->Color.ColorLogicOpEnabled)
+ _mesa_Disable(GL_COLOR_LOGIC_OP);
+ }
+
+ if (state & META_COLOR_MASK) {
+ COPY_4V(save->ColorMask, ctx->Color.ColorMask);
+ if (!ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3])
+ _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ if (state & META_DEPTH_TEST) {
+ save->Depth = ctx->Depth; /* struct copy */
+ if (ctx->Depth.Test)
+ _mesa_Disable(GL_DEPTH_TEST);
+ }
+
+ if (state & META_FOG) {
+ save->Fog = ctx->Fog.Enabled;
+ if (ctx->Fog.Enabled)
+ _mesa_set_enable(ctx, GL_FOG, GL_FALSE);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ save->Pack = ctx->Pack;
+ save->Unpack = ctx->Unpack;
+ ctx->Pack = ctx->DefaultPacking;
+ ctx->Unpack = ctx->DefaultPacking;
+ }
+
+ if (state & META_RASTERIZATION) {
+ save->FrontPolygonMode = ctx->Polygon.FrontMode;
+ save->BackPolygonMode = ctx->Polygon.BackMode;
+ save->PolygonOffset = ctx->Polygon.OffsetFill;
+ save->PolygonSmooth = ctx->Polygon.SmoothFlag;
+ save->PolygonStipple = ctx->Polygon.StippleFlag;
+ save->PolygonCull = ctx->Polygon.CullFlag;
+ _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE);
+ }
+
+ if (state & META_SCISSOR) {
+ save->Scissor = ctx->Scissor; /* struct copy */
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ save->VertexProgramEnabled = ctx->VertexProgram.Enabled;
+ save->VertexProgram = ctx->VertexProgram.Current;
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled;
+ save->FragmentProgram = ctx->FragmentProgram.Current;
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE);
+ }
+
+ if (ctx->Extensions.ARB_shader_objects) {
+ save->Shader = ctx->Shader.CurrentProgram ?
+ ctx->Shader.CurrentProgram->Name : 0;
+ _mesa_UseProgramObjectARB(0);
+ }
+ }
+
+ if (state & META_STENCIL_TEST) {
+ save->Stencil = ctx->Stencil; /* struct copy */
+ if (ctx->Stencil.Enabled)
+ _mesa_Disable(GL_STENCIL_TEST);
+ /* NOTE: other stencil state not reset */
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ save->ActiveUnit = ctx->Texture.CurrentUnit;
+ save->ClientActiveUnit = ctx->Array.ActiveTexture;
+ save->EnvMode = ctx->Texture.Unit[0].EnvMode;
+
+ /* Disable all texture units */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled;
+ save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled;
+ if (ctx->Texture.Unit[u].Enabled ||
+ ctx->Texture.Unit[u].TexGenEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
+ }
+ }
+
+ /* save current texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&save->CurrentTexture[tgt],
+ ctx->Texture.Unit[0].CurrentTex[tgt]);
+ }
+
+ /* set defaults for unit[0] */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ _mesa_memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ _mesa_memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m,
+ 16 * sizeof(GLfloat));
+ _mesa_memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m,
+ 16 * sizeof(GLfloat));
+ save->MatrixMode = ctx->Transform.MatrixMode;
+ /* set 1:1 vertex:pixel coordinate transform */
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadIdentity();
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadIdentity();
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0.0F, ctx->DrawBuffer->Width,
+ 0.0F, ctx->DrawBuffer->Height,
+ -1.0F, 1.0F);
+ save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled;
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* save vertex array object state */
+ _mesa_reference_array_object(ctx, &save->ArrayObj,
+ ctx->Array.ArrayObj);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj,
+ ctx->Array.ArrayBufferObj);
+ /* set some default state? */
+ }
+
+ if (state & META_VIEWPORT) {
+ /* save viewport state */
+ save->ViewportX = ctx->Viewport.X;
+ save->ViewportY = ctx->Viewport.Y;
+ save->ViewportW = ctx->Viewport.Width;
+ save->ViewportH = ctx->Viewport.Height;
+ /* set viewport to match window size */
+ if (ctx->Viewport.X != 0 ||
+ ctx->Viewport.Y != 0 ||
+ ctx->Viewport.Width != ctx->DrawBuffer->Width ||
+ ctx->Viewport.Height != ctx->DrawBuffer->Height) {
+ _mesa_set_viewport(ctx, 0, 0,
+ ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
+ }
+ /* save depth range state */
+ save->DepthNear = ctx->Viewport.Near;
+ save->DepthFar = ctx->Viewport.Far;
+ /* set depth range to default */
+ _mesa_DepthRange(0.0, 1.0);
+ }
+
+ /* misc */
+ {
+ save->Lighting = ctx->Light.Enabled;
+ if (ctx->Light.Enabled)
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE);
+ }
+}
+
+
+/**
+ * Leave meta state. This is like a light-weight version of glPopAttrib().
+ */
+static void
+_mesa_meta_end(GLcontext *ctx)
+{
+ struct save_state *save = &ctx->Meta->Save;
+ const GLbitfield state = save->SavedState;
+
+ if (state & META_ALPHA_TEST) {
+ if (ctx->Color.AlphaEnabled != save->AlphaEnabled)
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled);
+ }
+
+ if (state & META_BLEND) {
+ if (ctx->Color.BlendEnabled != save->BlendEnabled)
+ _mesa_set_enable(ctx, GL_BLEND, save->BlendEnabled);
+ if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled)
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled);
+ }
+
+ if (state & META_COLOR_MASK) {
+ if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask))
+ _mesa_ColorMask(save->ColorMask[0], save->ColorMask[1],
+ save->ColorMask[2], save->ColorMask[3]);
+ }
+
+ if (state & META_DEPTH_TEST) {
+ if (ctx->Depth.Test != save->Depth.Test)
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test);
+ _mesa_DepthFunc(save->Depth.Func);
+ _mesa_DepthMask(save->Depth.Mask);
+ }
+
+ if (state & META_FOG) {
+ _mesa_set_enable(ctx, GL_FOG, save->Fog);
+ }
+
+ if (state & META_PIXEL_STORE) {
+ ctx->Pack = save->Pack;
+ ctx->Unpack = save->Unpack;
+ }
+
+ if (state & META_RASTERIZATION) {
+ _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
+ _mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth);
+ _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull);
+ }
+
+ if (state & META_SCISSOR) {
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled);
+ _mesa_Scissor(save->Scissor.X, save->Scissor.Y,
+ save->Scissor.Width, save->Scissor.Height);
+ }
+
+ if (state & META_SHADER) {
+ if (ctx->Extensions.ARB_vertex_program) {
+ _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB,
+ save->VertexProgramEnabled);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ save->VertexProgram);
+ }
+
+ if (ctx->Extensions.ARB_fragment_program) {
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ save->FragmentProgramEnabled);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ save->FragmentProgram);
+ }
+
+ if (ctx->Extensions.ARB_shader_objects) {
+ _mesa_UseProgramObjectARB(save->Shader);
+ }
+ }
+
+ if (state & META_STENCIL_TEST) {
+ const struct gl_stencil_attrib *stencil = &save->Stencil;
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
+ _mesa_ClearStencil(stencil->Clear);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
+ stencil->TestTwoSide);
+ _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
+ ? GL_BACK : GL_FRONT);
+ }
+ /* front state */
+ _mesa_StencilFuncSeparate(GL_FRONT,
+ stencil->Function[0],
+ stencil->Ref[0],
+ stencil->ValueMask[0]);
+ _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
+ _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
+ stencil->ZFailFunc[0],
+ stencil->ZPassFunc[0]);
+ /* back state */
+ _mesa_StencilFuncSeparate(GL_BACK,
+ stencil->Function[1],
+ stencil->Ref[1],
+ stencil->ValueMask[1]);
+ _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
+ _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
+ stencil->ZFailFunc[1],
+ stencil->ZPassFunc[1]);
+ }
+
+ if (state & META_TEXTURE) {
+ GLuint u, tgt;
+
+ ASSERT(ctx->Texture.CurrentUnit == 0);
+
+ /* restore texenv for unit[0] */
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode);
+
+ /* restore texture objects for unit[0] only */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt],
+ save->CurrentTexture[tgt]);
+ }
+
+ /* Re-enable textures, texgen */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ if (save->TexEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexEnabled[u] & TEXTURE_1D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_2D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_3D_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_CUBE_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_TRUE);
+ if (save->TexEnabled[u] & TEXTURE_RECT_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_TRUE);
+ }
+
+ if (save->TexGenEnabled[u]) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + u);
+
+ if (save->TexGenEnabled[u] & S_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_TRUE);
+ if (save->TexGenEnabled[u] & T_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_TRUE);
+ if (save->TexGenEnabled[u] & R_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_TRUE);
+ if (save->TexGenEnabled[u] & Q_BIT)
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
+ }
+ }
+
+ /* restore current unit state */
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit);
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit);
+ }
+
+ if (state & META_TRANSFORM) {
+ GLuint activeTexture = ctx->Texture.CurrentUnit;
+ _mesa_ActiveTextureARB(GL_TEXTURE0);
+ _mesa_MatrixMode(GL_TEXTURE);
+ _mesa_LoadMatrixf(save->TextureMatrix);
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture);
+
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_LoadMatrixf(save->ModelviewMatrix);
+
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_LoadMatrixf(save->ProjectionMatrix);
+
+ _mesa_MatrixMode(save->MatrixMode);
+
+ if (save->ClipPlanesEnabled) {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxClipPlanes; i++) {
+ if (save->ClipPlanesEnabled & (1 << i)) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
+ }
+ }
+ }
+ }
+
+ if (state & META_VERTEX) {
+ /* restore vertex buffer object */
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name);
+ _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL);
+
+ /* restore vertex array object */
+ _mesa_BindVertexArray(save->ArrayObj->Name);
+ _mesa_reference_array_object(ctx, &save->ArrayObj, NULL);
+ }
+
+ if (state & META_VIEWPORT) {
+ if (save->ViewportX != ctx->Viewport.X ||
+ save->ViewportY != ctx->Viewport.Y ||
+ save->ViewportW != ctx->Viewport.Width ||
+ save->ViewportH != ctx->Viewport.Height) {
+ _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY,
+ save->ViewportW, save->ViewportH);
+ }
+ _mesa_DepthRange(save->DepthNear, save->DepthFar);
+ }
+
+ /* misc */
+ if (save->Lighting) {
+ _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE);
+ }
+}
+
+
+/**
+ * Return pointer to temp_texture info. This does some one-time init
+ * if needed.
+ */
+static struct temp_texture *
+get_temp_texture(GLcontext *ctx)
+{
+ struct temp_texture *tex = &ctx->Meta->TempTex;
+
+ if (!tex->TexObj) {
+ /* do one-time init */
+
+ /* prefer texture rectangle */
+ if (ctx->Extensions.NV_texture_rectangle) {
+ tex->Target = GL_TEXTURE_RECTANGLE;
+ tex->MaxSize = ctx->Const.MaxTextureRectSize;
+ tex->NPOT = GL_TRUE;
+ }
+ else {
+ /* use 2D texture, NPOT if possible */
+ tex->Target = GL_TEXTURE_2D;
+ tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two;
+ }
+ assert(tex->MaxSize > 0);
+
+ _mesa_GenTextures(1, &tex->TexObj);
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ }
+
+ return tex;
+}
+
+
+/**
+ * Compute the width/height of texture needed to draw an image of the
+ * given size. Return a flag indicating whether the current texture
+ * can be re-used (glTexSubImage2D) or if a new texture needs to be
+ * allocated (glTexImage2D).
+ * Also, compute s/t texcoords for drawing.
+ *
+ * \return GL_TRUE if new texture is needed, GL_FALSE otherwise
+ */
+static GLboolean
+alloc_texture(struct temp_texture *tex,
+ GLsizei width, GLsizei height, GLenum intFormat)
+{
+ GLboolean newTex = GL_FALSE;
+
+ if (width > tex->Width ||
+ height > tex->Height ||
+ intFormat != tex->IntFormat) {
+ /* alloc new texture (larger or different format) */
+
+ if (tex->NPOT) {
+ /* use non-power of two size */
+ tex->Width = width;
+ tex->Height = height;
+ }
+ else {
+ /* find power of two size */
+ GLsizei w, h;
+ w = h = 16;
+ while (w < width)
+ w *= 2;
+ while (h < height)
+ h *= 2;
+ tex->Width = w;
+ tex->Height = h;
+ }
+
+ tex->IntFormat = intFormat;
+
+ newTex = GL_TRUE;
+ }
+
+ /* compute texcoords */
+ if (tex->Target == GL_TEXTURE_RECTANGLE) {
+ tex->Sright = (GLfloat) width;
+ tex->Ttop = (GLfloat) height;
+ }
+ else {
+ tex->Sright = (GLfloat) width / tex->Width;
+ tex->Ttop = (GLfloat) height / tex->Height;
+ }
+
+ return newTex;
+}
+
+
+/**
+ * Setup/load texture for glCopyPixels or glBlitFramebuffer.
+ */
+static void
+setup_copypix_texture(struct temp_texture *tex,
+ GLboolean newTex,
+ GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height, GLenum intFormat,
+ GLenum filter)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy framebuffer image to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex with framebuffer data */
+ _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat,
+ srcX, srcY, width, height, 0);
+ }
+ else {
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0,
+ intFormat, GL_UNSIGNED_BYTE, NULL);
+ /* load image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_CopyTexSubImage2D(tex->Target, 0,
+ 0, 0, srcX, srcY, width, height);
+ }
+}
+
+
+/**
+ * Setup/load texture for glDrawPixels.
+ */
+static void
+setup_drawpix_texture(struct temp_texture *tex,
+ GLboolean newTex,
+ GLenum texIntFormat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels)
+{
+ _mesa_BindTexture(tex->Target, tex->TexObj);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ /* copy pixel data to texture */
+ if (newTex) {
+ /* create new tex image */
+ if (tex->Width == width && tex->Height == height) {
+ /* create new tex and load image data */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, pixels);
+ }
+ else {
+ /* create empty texture */
+ _mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
+ tex->Width, tex->Height, 0, format, type, NULL);
+ /* load image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+ }
+ else {
+ /* replace existing tex image */
+ _mesa_TexSubImage2D(tex->Target, 0,
+ 0, 0, width, height, format, type, pixels);
+ }
+}
+
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_blit_depth_pixels(GLcontext *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "END \n";
+ char program2[200];
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(blit->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &blit->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_blit_framebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const GLsizei maxTexSize = tex->MaxSize;
+ const GLint srcX = MIN2(srcX0, srcX1);
+ const GLint srcY = MIN2(srcY0, srcY1);
+ const GLint srcW = abs(srcX1 - srcX0);
+ const GLint srcH = abs(srcY1 - srcY0);
+ const GLboolean srcFlipX = srcX1 < srcX0;
+ const GLboolean srcFlipY = srcY1 < srcY0;
+ GLfloat verts[4][4]; /* four verts of X,Y,S,T */
+ GLboolean newTex;
+
+ if (srcW > maxTexSize || srcH > maxTexSize) {
+ /* XXX avoid this fallback */
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ return;
+ }
+
+ if (srcFlipX) {
+ GLint tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+
+ if (srcFlipY) {
+ GLint tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+
+ /* only scissor effects blit so save/clear all other relevant state */
+ _mesa_meta_begin(ctx, ~META_SCISSOR);
+
+ if (blit->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &blit->ArrayObj);
+ _mesa_BindVertexArray(blit->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &blit->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
+ (void *) (2 * sizeof(GLfloat)));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(blit->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
+ }
+
+ newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
+
+ /* vertex positions/texcoords (after texture allocation!) */
+ {
+ verts[0][0] = (GLfloat) dstX0;
+ verts[0][1] = (GLfloat) dstY0;
+ verts[1][0] = (GLfloat) dstX1;
+ verts[1][1] = (GLfloat) dstY0;
+ verts[2][0] = (GLfloat) dstX1;
+ verts[2][1] = (GLfloat) dstY1;
+ verts[3][0] = (GLfloat) dstX0;
+ verts[3][1] = (GLfloat) dstY1;
+
+ verts[0][2] = 0.0F;
+ verts[0][3] = 0.0F;
+ verts[1][2] = tex->Sright;
+ verts[1][3] = 0.0F;
+ verts[2][2] = tex->Sright;
+ verts[2][3] = tex->Ttop;
+ verts[3][2] = 0.0F;
+ verts[3][3] = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ _mesa_Enable(tex->Target);
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH,
+ GL_RGBA, filter);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ GLuint *tmp = (GLuint *) _mesa_malloc(srcW * srcH * sizeof(GLuint));
+ if (tmp) {
+ if (!blit->DepthFP)
+ init_blit_depth_pixels(ctx);
+
+ /* maybe change tex format here */
+ newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
+
+ _mesa_ReadPixels(srcX, srcY, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ setup_drawpix_texture(tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+
+ _mesa_free(tmp);
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ /* XXX can't easily do stencil */
+ }
+
+ _mesa_Disable(tex->Target);
+
+ _mesa_meta_end(ctx);
+
+ if (mask) {
+ _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ }
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
+ */
+void
+_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers)
+{
+ struct clear_state *clear = &ctx->Meta->Clear;
+ GLfloat verts[4][7]; /* four verts of X,Y,Z,R,G,B,A */
+ /* save all state but scissor, pixel pack/unpack */
+ GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
+
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* if clearing color buffers, don't save/restore colormask */
+ metaSave -= META_COLOR_MASK;
+ }
+
+ _mesa_meta_begin(ctx, metaSave);
+
+ if (clear->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &clear->ArrayObj);
+ _mesa_BindVertexArray(clear->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &clear->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(verts[0]),
+ (void *) (3 * sizeof(GLfloat)));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_COLOR_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(clear->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ }
+
+ /* GL_COLOR_BUFFER_BIT */
+ if (buffers & BUFFER_BITS_COLOR) {
+ /* leave colormask, glDrawBuffer state as-is */
+ }
+ else {
+ ASSERT(metaSave & META_COLOR_MASK);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+
+ /* GL_DEPTH_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_DEPTH) {
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+ }
+ else {
+ assert(!ctx->Depth.Test);
+ }
+
+ /* GL_STENCIL_BUFFER_BIT */
+ if (buffers & BUFFER_BIT_STENCIL) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+ _mesa_StencilOpSeparate(GL_FRONT_AND_BACK,
+ GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS,
+ ctx->Stencil.Clear & 0x7fffffff,
+ ctx->Stencil.WriteMask[0]);
+ }
+ else {
+ assert(!ctx->Stencil.Enabled);
+ }
+
+ /* vertex positions/colors */
+ {
+ const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
+ const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
+ const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
+ const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
+ const GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear;
+ GLuint i;
+
+ verts[0][0] = x0;
+ verts[0][1] = y0;
+ verts[0][2] = z;
+ verts[1][0] = x1;
+ verts[1][1] = y0;
+ verts[1][2] = z;
+ verts[2][0] = x1;
+ verts[2][1] = y1;
+ verts[2][2] = z;
+ verts[3][0] = x0;
+ verts[3][1] = y1;
+ verts[3][2] = z;
+
+ /* vertex colors */
+ for (i = 0; i < 4; i++) {
+ COPY_4FV(&verts[i][3], ctx->Color.ClearColor);
+ }
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* draw quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_meta_end(ctx);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.CopyPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcX, GLint srcY,
+ GLsizei width, GLsizei height,
+ GLint dstX, GLint dstY, GLenum type)
+{
+ struct copypix_state *copypix = &ctx->Meta->CopyPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ GLfloat verts[4][5]; /* four verts of X,Y,Z,S,T */
+ GLboolean newTex;
+ GLenum intFormat = GL_RGBA;
+
+ if (type != GL_COLOR ||
+ ctx->_ImageTransferState ||
+ ctx->Fog.Enabled ||
+ width > tex->MaxSize ||
+ height > tex->MaxSize) {
+ /* XXX avoid this fallback */
+ _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type);
+ return;
+ }
+
+ /* Most GL state applies to glCopyPixels, but a there's a few things
+ * we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT));
+
+ if (copypix->ArrayObj == 0) {
+ /* one-time setup */
+
+ /* create vertex array object */
+ _mesa_GenVertexArrays(1, &copypix->ArrayObj);
+ _mesa_BindVertexArray(copypix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &copypix->VBO);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
+ (void *) (3 * sizeof(GLfloat)));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ else {
+ _mesa_BindVertexArray(copypix->ArrayObj);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
+ }
+
+ newTex = alloc_texture(tex, width, height, intFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat dstX0 = (GLfloat) dstX;
+ const GLfloat dstY0 = (GLfloat) dstY;
+ const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX;
+ const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
+ const GLfloat z = ctx->Current.RasterPos[2];
+
+ verts[0][0] = dstX0;
+ verts[0][1] = dstY0;
+ verts[0][2] = z;
+ verts[0][3] = 0.0F;
+ verts[0][4] = 0.0F;
+ verts[1][0] = dstX1;
+ verts[1][1] = dstY0;
+ verts[1][2] = z;
+ verts[1][3] = tex->Sright;
+ verts[1][4] = 0.0F;
+ verts[2][0] = dstX1;
+ verts[2][1] = dstY1;
+ verts[2][2] = z;
+ verts[2][3] = tex->Sright;
+ verts[2][4] = tex->Ttop;
+ verts[3][0] = dstX0;
+ verts[3][1] = dstY1;
+ verts[3][2] = z;
+ verts[3][3] = 0.0F;
+ verts[3][4] = tex->Ttop;
+
+ /* upload new vertex data */
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ /* Alloc/setup texture */
+ setup_copypix_texture(tex, newTex, srcX, srcY, width, height,
+ GL_RGBA, GL_NEAREST);
+
+ _mesa_Enable(tex->Target);
+
+ /* draw textured quad */
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ _mesa_Disable(tex->Target);
+
+ _mesa_meta_end(ctx);
+}
+
+
+
+/**
+ * When the glDrawPixels() image size is greater than the max rectangle
+ * texture size we use this function to break the glDrawPixels() image
+ * into tiles which fit into the max texture size.
+ */
+static void
+tiled_draw_pixels(GLcontext *ctx,
+ GLint tileSize,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct gl_pixelstore_attrib tileUnpack = *unpack;
+ GLint i, j;
+
+ if (tileUnpack.RowLength == 0)
+ tileUnpack.RowLength = width;
+
+ for (i = 0; i < width; i += tileSize) {
+ const GLint tileWidth = MIN2(tileSize, width - i);
+ const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX);
+
+ tileUnpack.SkipPixels = unpack->SkipPixels + i;
+
+ for (j = 0; j < height; j += tileSize) {
+ const GLint tileHeight = MIN2(tileSize, height - j);
+ const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY);
+
+ tileUnpack.SkipRows = unpack->SkipRows + j;
+
+ _mesa_meta_draw_pixels(ctx, tileX, tileY,
+ tileWidth, tileHeight,
+ format, type, &tileUnpack, pixels);
+ }
+ }
+}
+
+
+/**
+ * One-time init for drawing stencil pixels.
+ */
+static void
+init_draw_stencil_pixels(GLcontext *ctx)
+{
+ /* This program is run eight times, once for each stencil bit.
+ * The stencil values to draw are found in an 8-bit alpha texture.
+ * We read the texture/stencil value and test if bit 'b' is set.
+ * If the bit is not set, use KIL to kill the fragment.
+ * Finally, we use the stencil test to update the stencil buffer.
+ *
+ * The basic algorithm for checking if a bit is set is:
+ * if (is_odd(value / (1 << bit)))
+ * result is one (or non-zero).
+ * else
+ * result is zero.
+ * The program parameter contains three values:
+ * parm.x = 255 / (1 << bit)
+ * parm.y = 0.5
+ * parm.z = 0.0
+ */
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM parm = program.local[0]; \n"
+ "TEMP t; \n"
+ "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */
+ "# t = t * 255 / bit \n"
+ "MUL t.x, t.a, parm.x; \n"
+ "# t = (int) t \n"
+ "FRC t.y, t.x; \n"
+ "SUB t.x, t.x, t.y; \n"
+ "# t = t * 0.5 \n"
+ "MUL t.x, t.x, parm.y; \n"
+ "# t = fract(t.x) \n"
+ "FRC t.x, t.x; # if t.x != 0, then the bit is set \n"
+ "# t.x = (t.x == 0 ? 1 : 0) \n"
+ "SGE t.x, -t.x, parm.z; \n"
+ "KIL -t.x; \n"
+ "# for debug only \n"
+ "#MOV result.color, t.x; \n"
+ "END \n";
+ char program2[1000];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->StencilFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->StencilFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_draw_depth_pixels(GLcontext *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "PARAM color = program.local[0]; \n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "MOV result.color, color; \n"
+ "END \n";
+ char program2[200];
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(drawpix->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &drawpix->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
+/**
+ * Meta implementation of ctx->Driver.DrawPixels() in terms
+ * of texture mapping and polygon rendering.
+ */
+void
+_mesa_meta_draw_pixels(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
+ const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
+ GLfloat verts[4][5]; /* four verts of X,Y,Z,S,T */
+ GLenum texIntFormat;
+ GLboolean fallback, newTex;
+ GLbitfield metaExtraSave = 0x0;
+ GLuint vbo;
+
+ /*
+ * Determine if we can do the glDrawPixels with texture mapping.
+ */
+ fallback = GL_FALSE;
+ if (ctx->_ImageTransferState ||
+ ctx->Fog.Enabled) {
+ fallback = GL_TRUE;
+ }
+
+ if (_mesa_is_color_format(format)) {
+ /* use more compact format when possible */
+ /* XXX disable special case for GL_LUMINANCE for now to work around
+ * apparent i965 driver bug (see bug #23670).
+ */
+ if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
+ texIntFormat = format;
+ else
+ texIntFormat = GL_RGBA;
+ }
+ else if (_mesa_is_stencil_format(format)) {
+ if (ctx->Extensions.ARB_fragment_program &&
+ ctx->Pixel.IndexShift == 0 &&
+ ctx->Pixel.IndexOffset == 0 &&
+ type == GL_UNSIGNED_BYTE) {
+ /* We'll store stencil as alpha. This only works for GLubyte
+ * image data because of how incoming values are mapped to alpha
+ * in [0,1].
+ */
+ texIntFormat = GL_ALPHA;
+ metaExtraSave = (META_COLOR_MASK |
+ META_DEPTH_TEST |
+ META_SHADER |
+ META_STENCIL_TEST);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ if (ctx->Extensions.ARB_depth_texture &&
+ ctx->Extensions.ARB_fragment_program) {
+ texIntFormat = GL_DEPTH_COMPONENT;
+ metaExtraSave = (META_SHADER);
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+ }
+ else {
+ fallback = GL_TRUE;
+ }
+
+ if (fallback) {
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /*
+ * Check image size against max texture size, draw as tiles if needed.
+ */
+ if (width > tex->MaxSize || height > tex->MaxSize) {
+ tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height,
+ format, type, unpack, pixels);
+ return;
+ }
+
+ /* Most GL state applies to glDrawPixels (like blending, stencil, etc),
+ * but a there's a few things we need to override:
+ */
+ _mesa_meta_begin(ctx, (META_RASTERIZATION |
+ META_SHADER |
+ META_TEXTURE |
+ META_TRANSFORM |
+ META_VERTEX |
+ META_VIEWPORT |
+ metaExtraSave));
+
+ newTex = alloc_texture(tex, width, height, texIntFormat);
+
+ /* vertex positions, texcoords (after texture allocation!) */
+ {
+ const GLfloat x0 = (GLfloat) x;
+ const GLfloat y0 = (GLfloat) y;
+ const GLfloat x1 = x + width * ctx->Pixel.ZoomX;
+ const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
+ const GLfloat z = ctx->Current.RasterPos[2];
+
+ verts[0][0] = x0;
+ verts[0][1] = y0;
+ verts[0][2] = z;
+ verts[0][3] = 0.0F;
+ verts[0][4] = 0.0F;
+ verts[1][0] = x1;
+ verts[1][1] = y0;
+ verts[1][2] = z;
+ verts[1][3] = tex->Sright;
+ verts[1][4] = 0.0F;
+ verts[2][0] = x1;
+ verts[2][1] = y1;
+ verts[2][2] = z;
+ verts[2][3] = tex->Sright;
+ verts[2][4] = tex->Ttop;
+ verts[3][0] = x0;
+ verts[3][1] = y1;
+ verts[3][2] = z;
+ verts[3][3] = 0.0F;
+ verts[3][4] = tex->Ttop;
+ }
+
+ if (drawpix->ArrayObj == 0) {
+ /* one-time setup: create vertex array object */
+ _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
+ }
+ _mesa_BindVertexArray(drawpix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &vbo);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ verts, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
+ (void *) (3 * sizeof(GLfloat)));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ /* set given unpack params */
+ ctx->Unpack = *unpack;
+
+ _mesa_Enable(tex->Target);
+
+ if (_mesa_is_stencil_format(format)) {
+ /* Drawing stencil */
+ GLint bit;
+
+ if (!drawpix->StencilFP)
+ init_draw_stencil_pixels(ctx);
+
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ GL_ALPHA, type, pixels);
+
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE);
+
+ /* set all stencil bits to 0 */
+ _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ _mesa_StencilFunc(GL_ALWAYS, 0, 255);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ /* set stencil bits to 1 where needed */
+ _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ for (bit = 0; bit < ctx->Visual.stencilBits; bit++) {
+ const GLuint mask = 1 << bit;
+ if (mask & origStencilMask) {
+ _mesa_StencilFunc(GL_ALWAYS, mask, mask);
+ _mesa_StencilMask(mask);
+
+ _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ 255.0 / mask, 0.5, 0.0, 0.0);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ }
+ }
+ else if (_mesa_is_depth_format(format)) {
+ /* Drawing depth */
+ if (!drawpix->DepthFP)
+ init_draw_depth_pixels(ctx);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+
+ /* polygon color = current raster color */
+ _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ ctx->Current.RasterColor);
+
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+ else {
+ /* Drawing RGBA */
+ setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ format, type, pixels);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ _mesa_Disable(tex->Target);
+
+ _mesa_DeleteBuffersARB(1, &vbo);
+
+ /* restore unpack params */
+ ctx->Unpack = unpackSave;
+
+ _mesa_meta_end(ctx);
+}
diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h
new file mode 100644
index 000000000..b03b64c48
--- /dev/null
+++ b/mesalib/src/mesa/drivers/common/meta.h
@@ -0,0 +1,81 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 META_H
+#define META_H
+
+
+/**
+ * Flags passed to _mesa_meta_begin().
+ * XXX these flags may evolve...
+ */
+/*@{*/
+#define META_ALPHA_TEST 0x1
+#define META_BLEND 0x2 /**< includes logicop */
+#define META_COLOR_MASK 0x4
+#define META_DEPTH_TEST 0x8
+#define META_FOG 0x10
+#define META_RASTERIZATION 0x20
+#define META_SCISSOR 0x40
+#define META_SHADER 0x80
+#define META_STENCIL_TEST 0x100
+#define META_TRANSFORM 0x200 /**< modelview, projection */
+#define META_TEXTURE 0x400
+#define META_VERTEX 0x800
+#define META_VIEWPORT 0x1000
+#define META_PIXEL_STORE 0x2000
+#define META_ALL ~0x0
+/*@}*/
+
+
+extern void
+_mesa_meta_init(GLcontext *ctx);
+
+extern void
+_mesa_meta_free(GLcontext *ctx);
+
+extern void
+_mesa_meta_blit_framebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+extern void
+_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers);
+
+extern void
+_mesa_meta_copy_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type);
+
+extern void
+_mesa_meta_draw_pixels(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels);
+
+
+#endif /* META_H */
diff --git a/mesalib/src/mesa/drivers/dri/Makefile b/mesalib/src/mesa/drivers/dri/Makefile
new file mode 100644
index 000000000..32db09786
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/Makefile
@@ -0,0 +1,55 @@
+# src/mesa/drivers/dri/Makefile
+
+TOP = ../../../..
+
+include $(TOP)/configs/current
+
+
+
+default: $(TOP)/$(LIB_DIR) subdirs dri.pc
+
+
+$(TOP)/$(LIB_DIR):
+ -mkdir $(TOP)/$(LIB_DIR)
+
+
+subdirs:
+ @for dir in $(DRI_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE)) || exit 1 ; \
+ fi \
+ done
+
+pcedit = sed \
+ -e 's,@INSTALL_DIR@,$(INSTALL_DIR),' \
+ -e 's,@INSTALL_LIB_DIR@,$(INSTALL_LIB_DIR),' \
+ -e 's,@INSTALL_INC_DIR@,$(INSTALL_INC_DIR),' \
+ -e 's,@VERSION@,$(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY),' \
+ -e 's,@DRI_DRIVER_DIR@,$(DRI_DRIVER_SEARCH_DIR),' \
+ -e 's,@DRI_PC_REQ_PRIV@,$(DRI_PC_REQ_PRIV),'
+
+dri.pc: dri.pc.in
+ $(pcedit) $< > $@
+
+
+install: dri.pc
+ @for dir in $(DRI_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) install) || exit 1 ; \
+ fi \
+ done
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/GL/internal
+ $(INSTALL) -m 0644 $(TOP)/include/GL/internal/dri_interface.h \
+ $(DESTDIR)$(INSTALL_INC_DIR)/GL/internal
+ $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+ $(INSTALL) -m 0644 dri.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig
+
+
+clean:
+ -@for dir in $(DRI_DIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) clean) ; \
+ fi \
+ done
+ -rm -f common/*.o
+ -rm -f *.pc
diff --git a/mesalib/src/mesa/drivers/dri/Makefile.template b/mesalib/src/mesa/drivers/dri/Makefile.template
new file mode 100644
index 000000000..18dbeba24
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/Makefile.template
@@ -0,0 +1,99 @@
+# -*-makefile-*-
+
+MESA_MODULES = $(TOP)/src/mesa/libmesa.a
+
+COMMON_GALLIUM_SOURCES = \
+ ../common/utils.c \
+ ../common/vblank.c \
+ ../common/dri_util.c \
+ ../common/xmlconfig.c
+
+COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
+ ../../common/driverfuncs.c \
+ ../common/texmem.c \
+ ../common/drirenderbuffer.c \
+ ../common/dri_metaops.c
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=
+WINLIB=
+INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+
+else
+# miniglx
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+INCLUDES = $(MINIGLX_INCLUDES) \
+ $(SHARED_INCLUDES) \
+ $(PCIACCESS_CFLAGS)
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+ $(MINIGLX_SOURCES:.c=.o) \
+ $(ASM_SOURCES:.S=.o)
+endif
+
+
+### Include directories
+SHARED_INCLUDES = \
+ -I. \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -Iserver \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/egl/drivers/dri \
+ $(LIBDRM_CFLAGS)
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+.S.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: symlinks depend $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
+
+
+$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
+ $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
+
+
+$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
+ $(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)
+
+
+depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ @ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ $(ASM_SOURCES) > /dev/null 2>/dev/null
+
+
+# Emacs tags
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
+ -rm -f depend depend.bak
+
+
+install: $(LIBNAME)
+ $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+ $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR)
+
+
+-include depend
diff --git a/mesalib/src/mesa/drivers/dri/common/depthtmp.h b/mesalib/src/mesa/drivers/dri/common/depthtmp.h
new file mode 100644
index 000000000..fd2dab3b4
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/depthtmp.h
@@ -0,0 +1,270 @@
+
+/*
+ * Notes:
+ * 1. These functions plug into the gl_renderbuffer structure.
+ * 2. The 'values' parameter always points to GLuint values, regardless of
+ * the actual Z buffer depth.
+ */
+
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HAVE_HW_DEPTH_SPANS
+#define HAVE_HW_DEPTH_SPANS 0
+#endif
+
+#ifndef HAVE_HW_DEPTH_PIXELS
+#define HAVE_HW_DEPTH_PIXELS 0
+#endif
+
+static void TAG(WriteDepthSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n",
+ (int)n, (int)x );
+
+ WRITE_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d) (mask %p)\n",
+ (int)i, (int)n1, (int)x1, mask );
+
+ if ( mask ) {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] );
+ }
+ } else {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ WRITE_DEPTH( x1, y, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+#if HAVE_HW_DEPTH_SPANS
+/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
+static void
+TAG(WriteMonoDepthSpan)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ const GLuint depthVal = *((GLuint *) value);
+ GLuint depths[MAX_WIDTH];
+ GLuint i;
+ for (i = 0; i < n; i++)
+ depths[i] = depthVal;
+ TAG(WriteDepthSpan)(ctx, rb, n, x, y, depths, mask);
+}
+#else
+static void TAG(WriteMonoDepthSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLuint depth = *((GLuint *) value);
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n",
+ __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth );
+
+ if ( mask ) {
+ for ( ; n1>0 ; i++, x1++, n1-- ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth );
+ }
+ } else {
+ for ( ; n1>0 ; x1++, n1-- ) {
+ WRITE_DEPTH( x1, y, depth );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+#endif
+
+
+static void TAG(WriteDepthPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const void *values,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const VALUE_TYPE *depth = (const VALUE_TYPE *) values;
+ GLuint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ WRITE_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ if ( mask ) {
+ for ( i = 0 ; i < n ; i++ ) {
+ if ( mask[i] ) {
+ const int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ WRITE_DEPTH( x[i], fy, depth[i] );
+ }
+ }
+ }
+ else {
+ for ( i = 0 ; i < n ; i++ ) {
+ const int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ WRITE_DEPTH( x[i], fy, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+/* Read depth spans and pixels
+ */
+static void TAG(ReadDepthSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ VALUE_TYPE *depth = (VALUE_TYPE *) values;
+ GLint x1, n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ READ_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+ for ( ; n1>0 ; i++, n1-- ) {
+ READ_DEPTH( depth[i], x+i, y );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(ReadDepthPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ VALUE_TYPE *depth = (VALUE_TYPE *) values;
+ GLuint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ READ_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ for ( i = 0 ; i < n ;i++ ) {
+ int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ READ_DEPTH( depth[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+
+
+/**
+ * Initialize the given renderbuffer's span routines to point to
+ * the depth/z functions we generated above.
+ */
+static void TAG(InitDepthPointers)(struct gl_renderbuffer *rb)
+{
+ rb->GetRow = TAG(ReadDepthSpan);
+ rb->GetValues = TAG(ReadDepthPixels);
+ rb->PutRow = TAG(WriteDepthSpan);
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = TAG(WriteMonoDepthSpan);
+ rb->PutValues = TAG(WriteDepthPixels);
+ rb->PutMonoValues = NULL;
+}
+
+
+#if HAVE_HW_DEPTH_SPANS
+#undef WRITE_DEPTH_SPAN
+#undef WRITE_DEPTH_PIXELS
+#undef READ_DEPTH_SPAN
+#undef READ_DEPTH_PIXELS
+#else
+#undef WRITE_DEPTH
+#undef READ_DEPTH
+#endif
+#undef TAG
+#undef VALUE_TYPE
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_metaops.c b/mesalib/src/mesa/drivers/dri/common/dri_metaops.c
new file mode 100644
index 000000000..c7bea07dc
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/dri_metaops.c
@@ -0,0 +1,298 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/arrayobj.h"
+#include "main/attrib.h"
+#include "main/blend.h"
+#include "main/bufferobj.h"
+#include "main/buffers.h"
+#include "main/depth.h"
+#include "main/enable.h"
+#include "main/matrix.h"
+#include "main/macros.h"
+#include "main/polygon.h"
+#include "main/shaders.h"
+#include "main/stencil.h"
+#include "main/texstate.h"
+#include "main/varray.h"
+#include "main/viewport.h"
+#include "shader/arbprogram.h"
+#include "shader/program.h"
+#include "dri_metaops.h"
+
+void
+meta_set_passthrough_transform(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+
+ meta->saved_vp_x = ctx->Viewport.X;
+ meta->saved_vp_y = ctx->Viewport.Y;
+ meta->saved_vp_width = ctx->Viewport.Width;
+ meta->saved_vp_height = ctx->Viewport.Height;
+ meta->saved_matrix_mode = ctx->Transform.MatrixMode;
+
+ meta->internal_viewport_call = GL_TRUE;
+ _mesa_Viewport(0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height);
+ meta->internal_viewport_call = GL_FALSE;
+
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_PushMatrix();
+ _mesa_LoadIdentity();
+ _mesa_Ortho(0, ctx->DrawBuffer->Width, 0, ctx->DrawBuffer->Height, 1, -1);
+
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_PushMatrix();
+ _mesa_LoadIdentity();
+}
+
+void
+meta_restore_transform(struct dri_metaops *meta)
+{
+ _mesa_MatrixMode(GL_PROJECTION);
+ _mesa_PopMatrix();
+ _mesa_MatrixMode(GL_MODELVIEW);
+ _mesa_PopMatrix();
+
+ _mesa_MatrixMode(meta->saved_matrix_mode);
+
+ meta->internal_viewport_call = GL_TRUE;
+ _mesa_Viewport(meta->saved_vp_x, meta->saved_vp_y,
+ meta->saved_vp_width, meta->saved_vp_height);
+ meta->internal_viewport_call = GL_FALSE;
+}
+
+
+/**
+ * Set up a vertex program to pass through the position and first texcoord
+ * for pixel path.
+ */
+void
+meta_set_passthrough_vertex_program(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+ static const char *vp =
+ "!!ARBvp1.0\n"
+ "TEMP vertexClip;\n"
+ "DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
+ "DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
+ "DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
+ "DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
+ "MOV result.position, vertexClip;\n"
+ "MOV result.texcoord[0], vertex.texcoord[0];\n"
+ "MOV result.color, vertex.color;\n"
+ "END\n";
+
+ assert(meta->saved_vp == NULL);
+
+ _mesa_reference_vertprog(ctx, &meta->saved_vp,
+ ctx->VertexProgram.Current);
+ if (meta->passthrough_vp == NULL) {
+ GLuint prog_name;
+ _mesa_GenPrograms(1, &prog_name);
+ _mesa_BindProgram(GL_VERTEX_PROGRAM_ARB, prog_name);
+ _mesa_ProgramStringARB(GL_VERTEX_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(vp), (const GLubyte *)vp);
+ _mesa_reference_vertprog(ctx, &meta->passthrough_vp,
+ ctx->VertexProgram.Current);
+ _mesa_DeletePrograms(1, &prog_name);
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ meta->passthrough_vp);
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ &meta->passthrough_vp->Base);
+
+ meta->saved_vp_enable = ctx->VertexProgram.Enabled;
+ _mesa_Enable(GL_VERTEX_PROGRAM_ARB);
+}
+
+/**
+ * Restores the previous vertex program after
+ * meta_set_passthrough_vertex_program()
+ */
+void
+meta_restore_vertex_program(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ meta->saved_vp);
+ _mesa_reference_vertprog(ctx, &meta->saved_vp, NULL);
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ &ctx->VertexProgram.Current->Base);
+
+ if (!meta->saved_vp_enable)
+ _mesa_Disable(GL_VERTEX_PROGRAM_ARB);
+}
+
+/**
+ * Binds the given program string to GL_FRAGMENT_PROGRAM_ARB, caching the
+ * program object.
+ */
+void
+meta_set_fragment_program(struct dri_metaops *meta,
+ struct gl_fragment_program **prog,
+ const char *prog_string)
+{
+ GLcontext *ctx = meta->ctx;
+ assert(meta->saved_fp == NULL);
+
+ _mesa_reference_fragprog(ctx, &meta->saved_fp,
+ ctx->FragmentProgram.Current);
+ if (*prog == NULL) {
+ GLuint prog_name;
+ _mesa_GenPrograms(1, &prog_name);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, prog_name);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(prog_string), (const GLubyte *)prog_string);
+ _mesa_reference_fragprog(ctx, prog, ctx->FragmentProgram.Current);
+ /* Note that DeletePrograms unbinds the program on us */
+ _mesa_DeletePrograms(1, &prog_name);
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, *prog);
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, &((*prog)->Base));
+
+ meta->saved_fp_enable = ctx->FragmentProgram.Enabled;
+ _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB);
+}
+
+/**
+ * Restores the previous fragment program after
+ * meta_set_fragment_program()
+ */
+void
+meta_restore_fragment_program(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ meta->saved_fp);
+ _mesa_reference_fragprog(ctx, &meta->saved_fp, NULL);
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ &ctx->FragmentProgram.Current->Base);
+
+ if (!meta->saved_fp_enable)
+ _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
+}
+
+static const float default_texcoords[4][2] = { { 0.0, 0.0 },
+ { 1.0, 0.0 },
+ { 1.0, 1.0 },
+ { 0.0, 1.0 } };
+
+void
+meta_set_default_texrect(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+ struct gl_client_array *old_texcoord_array;
+
+ meta->saved_active_texture = ctx->Texture.CurrentUnit;
+ if (meta->saved_array_vbo == NULL) {
+ _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo,
+ ctx->Array.ArrayBufferObj);
+ }
+
+ old_texcoord_array = &ctx->Array.ArrayObj->TexCoord[0];
+ meta->saved_texcoord_type = old_texcoord_array->Type;
+ meta->saved_texcoord_size = old_texcoord_array->Size;
+ meta->saved_texcoord_stride = old_texcoord_array->Stride;
+ meta->saved_texcoord_enable = old_texcoord_array->Enabled;
+ meta->saved_texcoord_ptr = old_texcoord_array->Ptr;
+ _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo,
+ old_texcoord_array->BufferObj);
+
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0);
+
+ if (meta->texcoord_vbo == NULL) {
+ GLuint vbo_name;
+
+ _mesa_GenBuffersARB(1, &vbo_name);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_name);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(default_texcoords),
+ default_texcoords, GL_STATIC_DRAW_ARB);
+ _mesa_reference_buffer_object(ctx, &meta->texcoord_vbo,
+ ctx->Array.ArrayBufferObj);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->texcoord_vbo->Name);
+ }
+ _mesa_TexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), NULL);
+
+ _mesa_Enable(GL_TEXTURE_COORD_ARRAY);
+}
+
+void
+meta_restore_texcoords(struct dri_metaops *meta)
+{
+ GLcontext *ctx = meta->ctx;
+
+ /* Restore the old TexCoordPointer */
+ if (meta->saved_texcoord_vbo) {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->saved_texcoord_vbo->Name);
+ _mesa_reference_buffer_object(ctx, &meta->saved_texcoord_vbo, NULL);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+ _mesa_TexCoordPointer(meta->saved_texcoord_size,
+ meta->saved_texcoord_type,
+ meta->saved_texcoord_stride,
+ meta->saved_texcoord_ptr);
+ if (!meta->saved_texcoord_enable)
+ _mesa_Disable(GL_TEXTURE_COORD_ARRAY);
+
+ _mesa_ClientActiveTextureARB(GL_TEXTURE0 +
+ meta->saved_active_texture);
+
+ if (meta->saved_array_vbo) {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ meta->saved_array_vbo->Name);
+ _mesa_reference_buffer_object(ctx, &meta->saved_array_vbo, NULL);
+ } else {
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+}
+
+
+void meta_init_metaops(GLcontext *ctx, struct dri_metaops *meta)
+{
+ meta->ctx = ctx;
+}
+
+void meta_destroy_metaops(struct dri_metaops *meta)
+{
+
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_metaops.h b/mesalib/src/mesa/drivers/dri/common/dri_metaops.h
new file mode 100644
index 000000000..248714532
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/dri_metaops.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef DRI_METAOPS_H
+#define DRI_METAOPS_H
+
+
+struct dri_metaops {
+ GLcontext *ctx;
+ GLboolean internal_viewport_call;
+ struct gl_fragment_program *bitmap_fp;
+ struct gl_vertex_program *passthrough_vp;
+ struct gl_buffer_object *texcoord_vbo;
+
+ struct gl_fragment_program *saved_fp;
+ GLboolean saved_fp_enable;
+ struct gl_vertex_program *saved_vp;
+ GLboolean saved_vp_enable;
+
+ struct gl_fragment_program *tex2d_fp;
+
+ GLboolean saved_texcoord_enable;
+ struct gl_buffer_object *saved_array_vbo, *saved_texcoord_vbo;
+ GLenum saved_texcoord_type;
+ GLsizei saved_texcoord_size, saved_texcoord_stride;
+ const void *saved_texcoord_ptr;
+ int saved_active_texture;
+
+ GLint saved_vp_x, saved_vp_y;
+ GLsizei saved_vp_width, saved_vp_height;
+ GLenum saved_matrix_mode;
+};
+
+
+void meta_set_passthrough_transform(struct dri_metaops *meta);
+
+void meta_restore_transform(struct dri_metaops *meta);
+
+void meta_set_passthrough_vertex_program(struct dri_metaops *meta);
+
+void meta_restore_vertex_program(struct dri_metaops *meta);
+
+void meta_set_fragment_program(struct dri_metaops *meta,
+ struct gl_fragment_program **prog,
+ const char *prog_string);
+
+void meta_restore_fragment_program(struct dri_metaops *meta);
+
+void meta_set_default_texrect(struct dri_metaops *meta);
+
+void meta_restore_texcoords(struct dri_metaops *meta);
+
+void meta_init_metaops(GLcontext *ctx, struct dri_metaops *meta);
+void meta_destroy_metaops(struct dri_metaops *meta);
+
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c
new file mode 100644
index 000000000..e48e10d7c
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c
@@ -0,0 +1,957 @@
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ */
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "main/imports.h"
+#define None 0
+
+#include "dri_util.h"
+#include "drm_sarea.h"
+#include "utils.h"
+
+#ifndef GLX_OML_sync_control
+typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
+#endif
+
+static void dri_get_drawable(__DRIdrawable *pdp);
+static void dri_put_drawable(__DRIdrawable *pdp);
+
+/**
+ * This is just a token extension used to signal that the driver
+ * supports setting a read drawable.
+ */
+const __DRIextension driReadDrawableExtension = {
+ __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
+};
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ *
+ * Is called from the drivers.
+ *
+ * \param f \c printf like format string.
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+ va_list args;
+
+ if (getenv("LIBGL_DEBUG")) {
+ fprintf(stderr, "libGL: ");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
+{
+ if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
+ if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
+ if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
+ if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
+
+ if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
+
+ return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
+}
+
+/*****************************************************************/
+/** \name Context (un)binding functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ *
+ * \param scrn the screen.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
+ * return.
+ *
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL.
+ */
+static int driUnbindContext(__DRIcontext *pcp)
+{
+ __DRIscreen *psp;
+ __DRIdrawable *pdp;
+ __DRIdrawable *prp;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext.
+ */
+
+ if (pcp == NULL)
+ return GL_FALSE;
+
+ psp = pcp->driScreenPriv;
+ pdp = pcp->driDrawablePriv;
+ prp = pcp->driReadablePriv;
+
+ /* already unbound */
+ if (!pdp && !prp)
+ return GL_TRUE;
+ /* Let driver unbind drawable from context */
+ (*psp->DriverAPI.UnbindContext)(pcp);
+
+ if (pdp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ dri_put_drawable(pdp);
+
+ if (prp != pdp) {
+ if (prp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ dri_put_drawable(prp);
+ }
+
+
+ /* XXX this is disabled so that if we call SwapBuffers on an unbound
+ * window we can determine the last context bound to the window and
+ * use that context's lock. (BrianP, 2-Dec-2000)
+ */
+ pcp->driDrawablePriv = pcp->driReadablePriv = NULL;
+
+#if 0
+ /* Unbind the drawable */
+ pdp->driContextPriv = &psp->dummyContextPriv;
+#endif
+
+ return GL_TRUE;
+}
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static int driBindContext(__DRIcontext *pcp,
+ __DRIdrawable *pdp,
+ __DRIdrawable *prp)
+{
+ __DRIscreenPrivate *psp = pcp->driScreenPriv;
+
+ /* Bind the drawable to the context */
+
+ if (pcp) {
+ pcp->driDrawablePriv = pdp;
+ pcp->driReadablePriv = prp;
+ if (pdp) {
+ pdp->driContextPriv = pcp;
+ dri_get_drawable(pdp);
+ }
+ if ( prp && pdp != prp ) {
+ dri_get_drawable(prp);
+ }
+ }
+
+ /*
+ ** Now that we have a context associated with this drawable, we can
+ ** initialize the drawable information if has not been done before.
+ */
+
+ if (!psp->dri2.enabled) {
+ if (pdp && !pdp->pStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(pdp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+ if (prp && pdp != prp && !prp->pStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(prp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+ }
+
+ /* Call device-specific MakeCurrent */
+
+ return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ *
+ * This function basically updates the __DRIdrawablePrivate struct's
+ * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
+ * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
+{
+ __DRIscreenPrivate *psp = pdp->driScreenPriv;
+ __DRIcontextPrivate *pcp = pdp->driContextPriv;
+
+ if (!pcp
+ || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
+ /* ERROR!!!
+ * ...but we must ignore it. There can be many contexts bound to a
+ * drawable.
+ */
+ }
+
+ if (pdp->pClipRects) {
+ _mesa_free(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+
+ if (pdp->pBackClipRects) {
+ _mesa_free(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+ if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
+ &pdp->index, &pdp->lastStamp,
+ &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+ &pdp->numClipRects, &pdp->pClipRects,
+ &pdp->backX,
+ &pdp->backY,
+ &pdp->numBackClipRects,
+ &pdp->pBackClipRects,
+ pdp->loaderPrivate)) {
+ /* Error -- eg the window may have been destroyed. Keep going
+ * with no cliprects.
+ */
+ pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+ pdp->numClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->numBackClipRects = 0;
+ pdp->pBackClipRects = NULL;
+ }
+ else
+ pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks */
+/*****************************************************************/
+/*@{*/
+
+static void driReportDamage(__DRIdrawable *pdp,
+ struct drm_clip_rect *pClipRects, int numClipRects)
+{
+ __DRIscreen *psp = pdp->driScreenPriv;
+
+ /* Check that we actually have the new damage report method */
+ if (psp->damage) {
+ /* Report the damage. Currently, all our drivers draw
+ * directly to the front buffer, so we report the damage there
+ * rather than to the backing storein (if any).
+ */
+ (*psp->damage->reportDamage)(pdp,
+ pdp->x, pdp->y,
+ pClipRects, numClipRects,
+ GL_TRUE, pdp->loaderPrivate);
+ }
+}
+
+
+/**
+ * Swap buffers.
+ *
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DRIdrawablePrivate::swapBuffers.
+ *
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers(__DRIdrawable *dPriv)
+{
+ __DRIscreen *psp = dPriv->driScreenPriv;
+ drm_clip_rect_t *rects;
+ int i;
+
+ psp->DriverAPI.SwapBuffers(dPriv);
+
+ if (!dPriv->numClipRects)
+ return;
+
+ rects = _mesa_malloc(sizeof(*rects) * dPriv->numClipRects);
+
+ if (!rects)
+ return;
+
+ for (i = 0; i < dPriv->numClipRects; i++) {
+ rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x;
+ rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y;
+ rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x;
+ rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y;
+ }
+
+ driReportDamage(dPriv, rects, dPriv->numClipRects);
+ _mesa_free(rects);
+}
+
+static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
+ int64_t *msc )
+{
+ return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
+}
+
+
+static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc, int64_t * sbc)
+{
+ __DRIswapInfo sInfo;
+ int status;
+
+ status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+ divisor, remainder,
+ msc );
+
+ /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+ * is supported but GLX_OML_sync_control is not. Therefore, don't return
+ * an error value if GetSwapInfo() is not implemented.
+ */
+ if ( status == 0
+ && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+ }
+
+ return status;
+}
+
+
+const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
+ { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
+ driWaitForMSC,
+ driDrawableGetMSC,
+};
+
+
+static void driCopySubBuffer(__DRIdrawable *dPriv,
+ int x, int y, int w, int h)
+{
+ drm_clip_rect_t rect;
+
+ rect.x1 = x;
+ rect.y1 = dPriv->h - y - h;
+ rect.x2 = x + w;
+ rect.y2 = rect.y1 + h;
+ driReportDamage(dPriv, &rect, 1);
+
+ dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
+}
+
+const __DRIcopySubBufferExtension driCopySubBufferExtension = {
+ { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
+ driCopySubBuffer
+};
+
+static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
+{
+ dPriv->swap_interval = interval;
+}
+
+static unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
+{
+ return dPriv->swap_interval;
+}
+
+const __DRIswapControlExtension driSwapControlExtension = {
+ { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
+ driSetSwapInterval,
+ driGetSwapInterval
+};
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static __DRIdrawable *
+driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
+ drm_drawable_t hwDrawable, int renderType,
+ const int *attrs, void *data)
+{
+ __DRIdrawable *pdp;
+
+ /* Since pbuffers are not yet supported, no drawable attributes are
+ * supported either.
+ */
+ (void) attrs;
+
+ pdp = _mesa_malloc(sizeof *pdp);
+ if (!pdp) {
+ return NULL;
+ }
+
+ pdp->loaderPrivate = data;
+ pdp->hHWDrawable = hwDrawable;
+ pdp->refcount = 1;
+ pdp->pStamp = NULL;
+ pdp->lastStamp = 0;
+ pdp->index = 0;
+ pdp->x = 0;
+ pdp->y = 0;
+ pdp->w = 0;
+ pdp->h = 0;
+ pdp->numClipRects = 0;
+ pdp->numBackClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->pBackClipRects = NULL;
+ pdp->vblSeq = 0;
+ pdp->vblFlags = 0;
+
+ pdp->driScreenPriv = psp;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+
+ if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
+ renderType == GLX_PIXMAP_BIT)) {
+ _mesa_free(pdp);
+ return NULL;
+ }
+
+ pdp->msc_base = 0;
+
+ /* This special default value is replaced with the configured
+ * default value when the drawable is first bound to a direct
+ * rendering context.
+ */
+ pdp->swap_interval = (unsigned)-1;
+
+ return pdp;
+}
+
+
+static __DRIdrawable *
+dri2CreateNewDrawable(__DRIscreen *screen,
+ const __DRIconfig *config,
+ void *loaderPrivate)
+{
+ __DRIdrawable *pdraw;
+
+ pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
+ if (!pdraw)
+ return NULL;
+
+ pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
+ pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
+
+ return pdraw;
+}
+
+static void dri_get_drawable(__DRIdrawable *pdp)
+{
+ pdp->refcount++;
+}
+
+static void dri_put_drawable(__DRIdrawable *pdp)
+{
+ __DRIscreenPrivate *psp;
+
+ pdp->refcount--;
+ if (pdp->refcount)
+ return;
+
+ if (pdp) {
+ psp = pdp->driScreenPriv;
+ (*psp->DriverAPI.DestroyBuffer)(pdp);
+ if (pdp->pClipRects) {
+ _mesa_free(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+ if (pdp->pBackClipRects) {
+ _mesa_free(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+ _mesa_free(pdp);
+ }
+}
+
+static void
+driDestroyDrawable(__DRIdrawable *pdp)
+{
+ dri_put_drawable(pdp);
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void
+driDestroyContext(__DRIcontext *pcp)
+{
+ if (pcp) {
+ (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+ _mesa_free(pcp);
+ }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param render_type Type of rendering target. \c GLX_RGBA is the only
+ * type likely to ever be supported for direct-rendering.
+ * \param shared Context with which to share textures, etc. or NULL
+ *
+ * \returns An opaque pointer to the per-context private information on
+ * success, or \c NULL on failure.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure. It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static __DRIcontext *
+driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
+ int render_type, __DRIcontext *shared,
+ drm_context_t hwContext, void *data)
+{
+ __DRIcontext *pcp;
+ void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
+
+ pcp = _mesa_malloc(sizeof *pcp);
+ if (!pcp)
+ return NULL;
+
+ pcp->driScreenPriv = psp;
+ pcp->driDrawablePriv = NULL;
+
+ /* When the first context is created for a screen, initialize a "dummy"
+ * context.
+ */
+
+ if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) {
+ psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
+ psp->dummyContextPriv.driScreenPriv = psp;
+ psp->dummyContextPriv.driDrawablePriv = NULL;
+ psp->dummyContextPriv.driverPrivate = NULL;
+ /* No other fields should be used! */
+ }
+
+ pcp->hHWContext = hwContext;
+
+ if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) {
+ _mesa_free(pcp);
+ return NULL;
+ }
+
+ return pcp;
+}
+
+
+static __DRIcontext *
+dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+ __DRIcontext *shared, void *data)
+{
+ return driCreateNewContext(screen, config, 0, shared, 0, data);
+}
+
+
+static int
+driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
+{
+ return GL_FALSE;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(__DRIscreen *psp)
+{
+ if (psp) {
+ /* No interaction with the X-server is possible at this point. This
+ * routine is called after XCloseDisplay, so there is no protocol
+ * stream open to the X-server anymore.
+ */
+
+ if (psp->DriverAPI.DestroyScreen)
+ (*psp->DriverAPI.DestroyScreen)(psp);
+
+ if (!psp->dri2.enabled) {
+ (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ (void)drmCloseOnce(psp->fd);
+ }
+
+ _mesa_free(psp);
+ }
+}
+
+static void
+setupLoaderExtensions(__DRIscreen *psp,
+ const __DRIextension **extensions)
+{
+ int i;
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
+ psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
+ psp->damage = (__DRIdamageExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
+ psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
+ if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
+ psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
+ }
+}
+
+/**
+ * This is the bootstrap function for the driver. libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c __GLcontextModes that the driver can support for windows or
+ * pbuffers.
+ *
+ * For legacy DRI.
+ *
+ * \param scrn Index of the screen
+ * \param ddx_version Version of the 2D DDX. This may not be meaningful for
+ * all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ * framebuffer.
+ * \param pSAREA Pointer the the SAREA.
+ * \param fd Device handle for the DRM.
+ * \param extensions ??
+ * \param driver_modes Returns modes suppoted by the driver
+ * \param loaderPrivate ??
+ *
+ * \note There is no need to check the minimum API version in this
+ * function. Since the name of this function is versioned, it is
+ * impossible for a loader that is too old to even load this driver.
+ */
+static __DRIscreen *
+driCreateNewScreen(int scrn,
+ const __DRIversion *ddx_version,
+ const __DRIversion *dri_version,
+ const __DRIversion *drm_version,
+ const __DRIframebuffer *frame_buffer,
+ drmAddress pSAREA, int fd,
+ const __DRIextension **extensions,
+ const __DRIconfig ***driver_modes,
+ void *loaderPrivate)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+
+ psp = _mesa_calloc(sizeof *psp);
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ /*
+ ** NOT_DONE: This is used by the X server to detect when the client
+ ** has died while holding the drawable lock. The client sets the
+ ** drawable lock to this value.
+ */
+ psp->drawLockID = 1;
+
+ psp->drm_version = *drm_version;
+ psp->ddx_version = *ddx_version;
+ psp->dri_version = *dri_version;
+
+ psp->pSAREA = pSAREA;
+ psp->lock = (drmLock *) &psp->pSAREA->lock;
+
+ psp->pFB = frame_buffer->base;
+ psp->fbSize = frame_buffer->size;
+ psp->fbStride = frame_buffer->stride;
+ psp->fbWidth = frame_buffer->width;
+ psp->fbHeight = frame_buffer->height;
+ psp->devPrivSize = frame_buffer->dev_priv_size;
+ psp->pDevPriv = frame_buffer->dev_priv;
+ psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
+
+ psp->extensions = emptyExtensionList;
+ psp->fd = fd;
+ psp->myNum = scrn;
+ psp->dri2.enabled = GL_FALSE;
+
+ /*
+ ** Do not init dummy context here; actual initialization will be
+ ** done when the first DRI context is created. Init screen priv ptr
+ ** to NULL to let CreateContext routine that it needs to be inited.
+ */
+ psp->dummyContextPriv.driScreenPriv = NULL;
+
+ psp->DriverAPI = driDriverAPI;
+
+ *driver_modes = driDriverAPI.InitScreen(psp);
+ if (*driver_modes == NULL) {
+ _mesa_free(psp);
+ return NULL;
+ }
+
+ return psp;
+}
+
+/**
+ * DRI2
+ */
+static __DRIscreen *
+dri2CreateNewScreen(int scrn, int fd,
+ const __DRIextension **extensions,
+ const __DRIconfig ***driver_configs, void *data)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+ drmVersionPtr version;
+
+ if (driDriverAPI.InitScreen2 == NULL)
+ return NULL;
+
+ psp = _mesa_calloc(sizeof(*psp));
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ version = drmGetVersion(fd);
+ if (version) {
+ psp->drm_version.major = version->version_major;
+ psp->drm_version.minor = version->version_minor;
+ psp->drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+
+ psp->extensions = emptyExtensionList;
+ psp->fd = fd;
+ psp->myNum = scrn;
+ psp->dri2.enabled = GL_TRUE;
+
+ psp->DriverAPI = driDriverAPI;
+ *driver_configs = driDriverAPI.InitScreen2(psp);
+ if (*driver_configs == NULL) {
+ _mesa_free(psp);
+ return NULL;
+ }
+
+ psp->DriverAPI = driDriverAPI;
+
+ return psp;
+}
+
+static const __DRIextension **driGetExtensions(__DRIscreen *psp)
+{
+ return psp->extensions;
+}
+
+/** Core interface */
+const __DRIcoreExtension driCoreExtension = {
+ { __DRI_CORE, __DRI_CORE_VERSION },
+ NULL,
+ driDestroyScreen,
+ driGetExtensions,
+ driGetConfigAttrib,
+ driIndexConfigAttrib,
+ NULL,
+ driDestroyDrawable,
+ driSwapBuffers,
+ NULL,
+ driCopyContext,
+ driDestroyContext,
+ driBindContext,
+ driUnbindContext
+};
+
+/** Legacy DRI interface */
+const __DRIlegacyExtension driLegacyExtension = {
+ { __DRI_LEGACY, __DRI_LEGACY_VERSION },
+ driCreateNewScreen,
+ driCreateNewDrawable,
+ driCreateNewContext,
+};
+
+/** Legacy DRI interface */
+const __DRIdri2Extension driDRI2Extension = {
+ { __DRI_DRI2, __DRI_DRI2_VERSION },
+ dri2CreateNewScreen,
+ dri2CreateNewDrawable,
+ dri2CreateNewContext,
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+ &driCoreExtension.base,
+ &driLegacyExtension.base,
+ &driDRI2Extension.base,
+ NULL
+};
+
+static int
+driFrameTracking(__DRIdrawable *drawable, GLboolean enable)
+{
+ return GLX_BAD_CONTEXT;
+}
+
+static int
+driQueryFrameTracking(__DRIdrawable *dpriv,
+ int64_t * sbc, int64_t * missedFrames,
+ float * lastMissedUsage, float * usage)
+{
+ __DRIswapInfo sInfo;
+ int status;
+ int64_t ust;
+ __DRIscreenPrivate *psp = dpriv->driScreenPriv;
+
+ status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
+ if ( status == 0 ) {
+ *sbc = sInfo.swap_count;
+ *missedFrames = sInfo.swap_missed_count;
+ *lastMissedUsage = sInfo.swap_missed_usage;
+
+ (*psp->systemTime->getUST)( & ust );
+ *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
+ }
+
+ return status;
+}
+
+const __DRIframeTrackingExtension driFrameTrackingExtension = {
+ { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
+ driFrameTracking,
+ driQueryFrameTracking
+};
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ *
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ * \f$p = t_d / (i * t_r)\f$
+ *
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ *
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param dPriv Pointer to the private drawable structure.
+ * \return If less than a single swap interval time period was required
+ * between GLX buffer swaps, a number greater than 0 and less than
+ * 1.0 is returned. If exactly one swap interval time period is
+ * required, 1.0 is returned, and if more than one is required then
+ * a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ *
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ * be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
+ int64_t current_ust )
+{
+ int32_t n;
+ int32_t d;
+ int interval;
+ float usage = 1.0;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+ if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
+ interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
+
+
+ /* We want to calculate
+ * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
+ * current_UST by calling __glXGetUST. last_swap_UST is stored in
+ * dPriv->swap_ust. interval has already been calculated.
+ *
+ * The only tricky part is us_per_refresh. us_per_refresh is
+ * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
+ * around and say us_per_refresh = 1000000 * d / n. Since this goes in
+ * the denominator of the final calculation, we calculate
+ * (interval * 1000000 * d) and move n into the numerator.
+ */
+
+ usage = (current_ust - last_swap_ust);
+ usage *= n;
+ usage /= (interval * d);
+ usage /= 1000000.0;
+ }
+
+ return usage;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h
new file mode 100644
index 000000000..c95a5c829
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h
@@ -0,0 +1,555 @@
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#include <GL/gl.h>
+#include <drm.h>
+#include <drm_sarea.h>
+#include <xf86drm.h>
+#include "main/glheader.h"
+#include "GL/internal/glcore.h"
+#include "GL/internal/dri_interface.h"
+
+#define GLX_BAD_CONTEXT 5
+
+typedef struct __DRIswapInfoRec __DRIswapInfo;
+
+/* Typedefs to avoid rewriting the world. */
+typedef struct __DRIscreenRec __DRIscreenPrivate;
+typedef struct __DRIdrawableRec __DRIdrawablePrivate;
+typedef struct __DRIcontextRec __DRIcontextPrivate;
+
+/**
+ * Extensions.
+ */
+extern const __DRIlegacyExtension driLegacyExtension;
+extern const __DRIcoreExtension driCoreExtension;
+extern const __DRIextension driReadDrawableExtension;
+extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
+extern const __DRIswapControlExtension driSwapControlExtension;
+extern const __DRIframeTrackingExtension driFrameTrackingExtension;
+extern const __DRImediaStreamCounterExtension driMediaStreamCounterExtension;
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
+ do { \
+ if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
+ __driUtilUpdateDrawableInfo(pDrawPriv); \
+ } \
+ } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawable::pStamp and __DRIdrawable::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
+do { \
+ while (*(pdp->pStamp) != pdp->lastStamp) { \
+ register unsigned int hwContext = psp->pSAREA->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ \
+ DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
+ } \
+} while (0)
+
+/**
+ * Same as above, but for two drawables simultaneously.
+ *
+ */
+
+#define DRI_VALIDATE_TWO_DRAWABLES_INFO(psp, pdp, prp) \
+do { \
+ while (*((pdp)->pStamp) != (pdp)->lastStamp || \
+ *((prp)->pStamp) != (prp)->lastStamp) { \
+ register unsigned int hwContext = (psp)->pSAREA->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(prp); \
+ DRM_SPINUNLOCK(&(psp)->pSAREA->drawable_lock, (psp)->drawLockID); \
+ \
+ DRM_LIGHT_LOCK((psp)->fd, &(psp)->pSAREA->lock, hwContext); \
+ } \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ *
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+ const __DRIconfig **(*InitScreen) (__DRIscreen * priv);
+
+ /**
+ * Screen destruction callback
+ */
+ void (*DestroyScreen)(__DRIscreen *driScrnPriv);
+
+ /**
+ * Context creation callback
+ */
+ GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+ __DRIcontext *driContextPriv,
+ void *sharedContextPrivate);
+
+ /**
+ * Context destruction callback
+ */
+ void (*DestroyContext)(__DRIcontext *driContextPriv);
+
+ /**
+ * Buffer (drawable) creation callback
+ */
+ GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv,
+ __DRIdrawable *driDrawPriv,
+ const __GLcontextModes *glVis,
+ GLboolean pixmapBuffer);
+
+ /**
+ * Buffer (drawable) destruction callback
+ */
+ void (*DestroyBuffer)(__DRIdrawable *driDrawPriv);
+
+ /**
+ * Buffer swapping callback
+ */
+ void (*SwapBuffers)(__DRIdrawable *driDrawPriv);
+
+ /**
+ * Context activation callback
+ */
+ GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv,
+ __DRIdrawable *driDrawPriv,
+ __DRIdrawable *driReadPriv);
+
+ /**
+ * Context unbinding callback
+ */
+ GLboolean (*UnbindContext)(__DRIcontext *driContextPriv);
+
+ /**
+ * Retrieves statistics about buffer swap operations. Required if
+ * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+ */
+ int (*GetSwapInfo)( __DRIdrawable *dPriv, __DRIswapInfo * sInfo );
+
+
+ /**
+ * These are required if GLX_OML_sync_control is supported.
+ */
+ /*@{*/
+ int (*WaitForMSC)( __DRIdrawable *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc );
+ int (*WaitForSBC)( __DRIdrawable *priv, int64_t target_sbc,
+ int64_t * msc, int64_t * sbc );
+
+ int64_t (*SwapBuffersMSC)( __DRIdrawable *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder );
+ /*@}*/
+ void (*CopySubBuffer)(__DRIdrawable *driDrawPriv,
+ int x, int y, int w, int h);
+
+ /**
+ * New version of GetMSC so we can pass drawable data to the low
+ * level DRM driver (e.g. pipe info). Required if
+ * GLX_SGI_video_sync or GLX_OML_sync_control is supported.
+ */
+ int (*GetDrawableMSC) ( __DRIscreen * priv,
+ __DRIdrawable *drawablePrivate,
+ int64_t *count);
+
+
+
+ /* DRI2 Entry point */
+ const __DRIconfig **(*InitScreen2) (__DRIscreen * priv);
+};
+
+extern const struct __DriverAPIRec driDriverAPI;
+
+
+struct __DRIswapInfoRec {
+ /**
+ * Number of swapBuffers operations that have been *completed*.
+ */
+ uint64_t swap_count;
+
+ /**
+ * Unadjusted system time of the last buffer swap. This is the time
+ * when the swap completed, not the time when swapBuffers was called.
+ */
+ int64_t swap_ust;
+
+ /**
+ * Number of swap operations that occurred after the swap deadline. That
+ * is if a swap happens more than swap_interval frames after the previous
+ * swap, it has missed its deadline. If swap_interval is 0, then the
+ * swap deadline is 1 frame after the previous swap.
+ */
+ uint64_t swap_missed_count;
+
+ /**
+ * Amount of time used by the last swap that missed its deadline. This
+ * is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
+ * time_for_single_vrefresh)). If the actual value of swap_interval is
+ * 0, then 1 is used instead. If swap_missed_count is non-zero, this
+ * should be greater-than 1.0.
+ */
+ float swap_missed_usage;
+};
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawableRec {
+ /**
+ * Kernel drawable handle
+ */
+ drm_drawable_t hHWDrawable;
+
+ /**
+ * Driver's private drawable information.
+ *
+ * This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * Private data from the loader. We just hold on to it and pass
+ * it back when calling into loader provided functions.
+ */
+ void *loaderPrivate;
+
+ /**
+ * Reference count for number of context's currently bound to this
+ * drawable.
+ *
+ * Once it reaches zero, the drawable can be destroyed.
+ *
+ * \note This behavior will change with GLX 1.3.
+ */
+ int refcount;
+
+ /**
+ * Index of this drawable information in the SAREA.
+ */
+ unsigned int index;
+
+ /**
+ * Pointer to the "drawable has changed ID" stamp in the SAREA.
+ */
+ unsigned int *pStamp;
+
+ /**
+ * Last value of the stamp.
+ *
+ * If this differs from the value stored at __DRIdrawable::pStamp,
+ * then the drawable information has been modified by the X server, and the
+ * drawable information (below) should be retrieved from the X server.
+ */
+ unsigned int lastStamp;
+
+ /**
+ * \name Drawable
+ *
+ * Drawable information used in software fallbacks.
+ */
+ /*@{*/
+ int x;
+ int y;
+ int w;
+ int h;
+ int numClipRects;
+ drm_clip_rect_t *pClipRects;
+ /*@}*/
+
+ /**
+ * \name Back and depthbuffer
+ *
+ * Information about the back and depthbuffer where different from above.
+ */
+ /*@{*/
+ int backX;
+ int backY;
+ int backClipRectType;
+ int numBackClipRects;
+ drm_clip_rect_t *pBackClipRects;
+ /*@}*/
+
+ /**
+ * \name Vertical blank tracking information
+ * Used for waiting on vertical blank events.
+ */
+ /*@{*/
+ unsigned int vblSeq;
+ unsigned int vblFlags;
+ /*@}*/
+
+ /**
+ * \name Monotonic MSC tracking
+ *
+ * Low level driver is responsible for updating msc_base and
+ * vblSeq values so that higher level code can calculate
+ * a new msc value or msc target for a WaitMSC call. The new value
+ * will be:
+ * msc = msc_base + get_vblank_count() - vblank_base;
+ *
+ * And for waiting on a value, core code will use:
+ * actual_target = target_msc - msc_base + vblank_base;
+ */
+ /*@{*/
+ int64_t vblank_base;
+ int64_t msc_base;
+ /*@}*/
+
+ /**
+ * Pointer to context to which this drawable is currently bound.
+ */
+ __DRIcontext *driContextPriv;
+
+ /**
+ * Pointer to screen on which this drawable was created.
+ */
+ __DRIscreen *driScreenPriv;
+
+ /**
+ * Controls swap interval as used by GLX_SGI_swap_control and
+ * GLX_MESA_swap_control.
+ */
+ unsigned int swap_interval;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextRec {
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ drm_context_t hHWContext;
+
+ /**
+ * Device driver's private context data. This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * Pointer back to the \c __DRIcontext that contains this structure.
+ */
+ __DRIcontext *pctx;
+
+ /**
+ * Pointer to drawable currently bound to this context for drawing.
+ */
+ __DRIdrawable *driDrawablePriv;
+
+ /**
+ * Pointer to drawable currently bound to this context for reading.
+ */
+ __DRIdrawable *driReadablePriv;
+
+ /**
+ * Pointer to screen on which this context was created.
+ */
+ __DRIscreen *driScreenPriv;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenRec {
+ /**
+ * Current screen's number
+ */
+ int myNum;
+
+ /**
+ * Callback functions into the hardware-specific DRI driver code.
+ */
+ struct __DriverAPIRec DriverAPI;
+
+ const __DRIextension **extensions;
+ /**
+ * DDX / 2D driver version information.
+ */
+ __DRIversion ddx_version;
+
+ /**
+ * DRI X extension version information.
+ */
+ __DRIversion dri_version;
+
+ /**
+ * DRM (kernel module) version information.
+ */
+ __DRIversion drm_version;
+
+ /**
+ * ID used when the client sets the drawable lock.
+ *
+ * The X server uses this value to detect if the client has died while
+ * holding the drawable lock.
+ */
+ int drawLockID;
+
+ /**
+ * File descriptor returned when the kernel device driver is opened.
+ *
+ * Used to:
+ * - authenticate client to kernel
+ * - map the frame buffer, SAREA, etc.
+ * - close the kernel device driver
+ */
+ int fd;
+
+ /**
+ * SAREA pointer
+ *
+ * Used to access:
+ * - the device lock
+ * - the device-independent per-drawable and per-context(?) information
+ */
+ drm_sarea_t *pSAREA;
+
+ /**
+ * \name Direct frame buffer access information
+ * Used for software fallbacks.
+ */
+ /*@{*/
+ unsigned char *pFB;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ int fbWidth;
+ int fbHeight;
+ int fbBPP;
+ /*@}*/
+
+ /**
+ * \name Device-dependent private information (stored in the SAREA).
+ *
+ * This data is accessed by the client driver only.
+ */
+ /*@{*/
+ void *pDevPriv;
+ int devPrivSize;
+ /*@}*/
+
+ /**
+ * Dummy context to which drawables are bound when not bound to any
+ * other context.
+ *
+ * A dummy hHWContext is created for this context, and is used by the GL
+ * core when a hardware lock is required but the drawable is not currently
+ * bound (e.g., potentially during a SwapBuffers request). The dummy
+ * context is created when the first "real" context is created on this
+ * screen.
+ */
+ __DRIcontext dummyContextPriv;
+
+ /**
+ * Device-dependent private information (not stored in the SAREA).
+ *
+ * This pointer is never touched by the DRI layer.
+ */
+ void *private;
+
+ /**
+ * Pointer back to the \c __DRIscreen that contains this structure.
+ */
+ __DRIscreen *psc;
+
+ /* Extensions provided by the loader. */
+ const __DRIgetDrawableInfoExtension *getDrawableInfo;
+ const __DRIsystemTimeExtension *systemTime;
+ const __DRIdamageExtension *damage;
+
+ struct {
+ /* Flag to indicate that this is a DRI2 screen. Many of the above
+ * fields will not be valid or initializaed in that case. */
+ int enabled;
+ __DRIdri2LoaderExtension *loader;
+ } dri2;
+
+ /* The lock actually in use, old sarea or DRI2 */
+ drmLock *lock;
+};
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawable *pdp);
+
+extern float
+driCalculateSwapUsage( __DRIdrawable *dPriv,
+ int64_t last_swap_ust, int64_t current_ust );
+
+extern GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c
new file mode 100644
index 000000000..15af99136
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.c
@@ -0,0 +1,217 @@
+
+#include "main/mtypes.h"
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+#include "main/imports.h"
+#include "drirenderbuffer.h"
+
+
+/**
+ * This will get called when a window (gl_framebuffer) is resized (probably
+ * via driUpdateFramebufferSize(), below).
+ * Just update width, height and internal format fields for now.
+ * There's usually no memory allocation above because the present
+ * DRI drivers use statically-allocated full-screen buffers. If that's not
+ * the case for a DRI driver, a different AllocStorage method should
+ * be used.
+ */
+static GLboolean
+driRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ rb->Width = width;
+ rb->Height = height;
+ rb->InternalFormat = internalFormat;
+ return GL_TRUE;
+}
+
+
+static void
+driDeleteRenderbuffer(struct gl_renderbuffer *rb)
+{
+ /* don't free rb->Data Chances are it's a memory mapped region for
+ * the dri drivers.
+ */
+ _mesa_free(rb);
+}
+
+
+/**
+ * Allocate a new driRenderbuffer object.
+ * Individual drivers are free to implement different versions of
+ * this function.
+ *
+ * At this time, this function can only be used for window-system
+ * renderbuffers, not user-created RBOs.
+ *
+ * \param format Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
+ * GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now).
+ * \param addr address in main memory of the buffer. Probably a memory
+ * mapped region.
+ * \param cpp chars or bytes per pixel
+ * \param offset start of renderbuffer with respect to start of framebuffer
+ * \param pitch pixels per row
+ */
+driRenderbuffer *
+driNewRenderbuffer(GLenum format, GLvoid *addr,
+ GLint cpp, GLint offset, GLint pitch,
+ __DRIdrawablePrivate *dPriv)
+{
+ driRenderbuffer *drb;
+
+ assert(format == GL_RGBA ||
+ format == GL_RGB5 ||
+ format == GL_RGBA8 ||
+ format == GL_DEPTH_COMPONENT16 ||
+ format == GL_DEPTH_COMPONENT24 ||
+ format == GL_DEPTH_COMPONENT32 ||
+ format == GL_STENCIL_INDEX8_EXT);
+
+ assert(cpp > 0);
+ assert(pitch > 0);
+
+ drb = _mesa_calloc(sizeof(driRenderbuffer));
+ if (drb) {
+ const GLuint name = 0;
+
+ _mesa_init_renderbuffer(&drb->Base, name);
+
+ /* Make sure we're using a null-valued GetPointer routine */
+ assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);
+
+ drb->Base.InternalFormat = format;
+
+ if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) {
+ /* Color */
+ drb->Base._BaseFormat = GL_RGBA;
+ drb->Base.DataType = GL_UNSIGNED_BYTE;
+ if (format == GL_RGB5) {
+ drb->Base.RedBits = 5;
+ drb->Base.GreenBits = 6;
+ drb->Base.BlueBits = 5;
+ }
+ else {
+ drb->Base.RedBits =
+ drb->Base.GreenBits =
+ drb->Base.BlueBits =
+ drb->Base.AlphaBits = 8;
+ }
+ }
+ else if (format == GL_DEPTH_COMPONENT16) {
+ /* Depth */
+ drb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ /* we always Get/Put 32-bit Z values */
+ drb->Base.DataType = GL_UNSIGNED_INT;
+ drb->Base.DepthBits = 16;
+ }
+ else if (format == GL_DEPTH_COMPONENT24) {
+ /* Depth */
+ drb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ /* we always Get/Put 32-bit Z values */
+ drb->Base.DataType = GL_UNSIGNED_INT;
+ drb->Base.DepthBits = 24;
+ }
+ else if (format == GL_DEPTH_COMPONENT32) {
+ /* Depth */
+ drb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+ /* we always Get/Put 32-bit Z values */
+ drb->Base.DataType = GL_UNSIGNED_INT;
+ drb->Base.DepthBits = 32;
+ }
+ else {
+ /* Stencil */
+ ASSERT(format == GL_STENCIL_INDEX8_EXT);
+ drb->Base._BaseFormat = GL_STENCIL_INDEX;
+ drb->Base.DataType = GL_UNSIGNED_BYTE;
+ drb->Base.StencilBits = 8;
+ }
+
+ /* XXX if we were allocating a user-created renderbuffer, we'd have
+ * to fill in the Red/Green/Blue/.../Bits values too.
+ */
+
+ drb->Base.AllocStorage = driRenderbufferStorage;
+ drb->Base.Delete = driDeleteRenderbuffer;
+
+ drb->Base.Data = addr;
+
+ /* DRI renderbuffer-specific fields: */
+ drb->dPriv = dPriv;
+ drb->offset = offset;
+ drb->pitch = pitch;
+ drb->cpp = cpp;
+
+ /* may be changed if page flipping is active: */
+ drb->flippedOffset = offset;
+ drb->flippedPitch = pitch;
+ drb->flippedData = addr;
+ }
+ return drb;
+}
+
+
+/**
+ * Update the front and back renderbuffers' flippedPitch/Offset/Data fields.
+ * If stereo, flip both the left and right pairs.
+ * This is used when we do double buffering via page flipping.
+ * \param fb the framebuffer we're page flipping
+ * \param flipped if true, set flipped values, else set non-flipped values
+ */
+void
+driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped)
+{
+ const GLuint count = fb->Visual.stereoMode ? 2 : 1;
+ GLuint lr; /* left or right */
+
+ /* we shouldn't really call this function if single-buffered, but
+ * play it safe.
+ */
+ if (!fb->Visual.doubleBufferMode)
+ return;
+
+ for (lr = 0; lr < count; lr++) {
+ GLuint frontBuf = (lr == 0) ? BUFFER_FRONT_LEFT : BUFFER_FRONT_RIGHT;
+ GLuint backBuf = (lr == 0) ? BUFFER_BACK_LEFT : BUFFER_BACK_RIGHT;
+ driRenderbuffer *front_drb
+ = (driRenderbuffer *) fb->Attachment[frontBuf].Renderbuffer;
+ driRenderbuffer *back_drb
+ = (driRenderbuffer *) fb->Attachment[backBuf].Renderbuffer;
+
+ if (flipped) {
+ front_drb->flippedOffset = back_drb->offset;
+ front_drb->flippedPitch = back_drb->pitch;
+ front_drb->flippedData = back_drb->Base.Data;
+ back_drb->flippedOffset = front_drb->offset;
+ back_drb->flippedPitch = front_drb->pitch;
+ back_drb->flippedData = front_drb->Base.Data;
+ }
+ else {
+ front_drb->flippedOffset = front_drb->offset;
+ front_drb->flippedPitch = front_drb->pitch;
+ front_drb->flippedData = front_drb->Base.Data;
+ back_drb->flippedOffset = back_drb->offset;
+ back_drb->flippedPitch = back_drb->pitch;
+ back_drb->flippedData = back_drb->Base.Data;
+ }
+ }
+}
+
+
+/**
+ * Check that the gl_framebuffer associated with dPriv is the right size.
+ * Resize the gl_framebuffer if needed.
+ * It's expected that the dPriv->driverPrivate member points to a
+ * gl_framebuffer object.
+ */
+void
+driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate;
+ if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) {
+ ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h);
+ /* if the driver needs the hw lock for ResizeBuffers, the drawable
+ might have changed again by now */
+ assert(fb->Width == dPriv->w);
+ assert(fb->Height == dPriv->h);
+ }
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h
new file mode 100644
index 000000000..cf55286b3
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/drirenderbuffer.h
@@ -0,0 +1,78 @@
+
+/**
+ * A driRenderbuffer is dervied from gl_renderbuffer.
+ * It describes a color buffer (front or back), a depth buffer, or stencil
+ * buffer etc.
+ * Specific to DRI drivers are the offset and pitch fields.
+ */
+
+
+#ifndef DRIRENDERBUFFER_H
+#define DRIRENDERBUFFER_H
+
+#include "main/mtypes.h"
+#include "dri_util.h"
+
+
+typedef struct {
+ struct gl_renderbuffer Base;
+
+ /* Chars or bytes per pixel. If Z and Stencil are stored together this
+ * will typically be 32 whether this a depth or stencil renderbuffer.
+ */
+ GLint cpp;
+
+ /* Buffer position and pitch (row stride). Recall that for today's DRI
+ * drivers, we have statically allocated color/depth/stencil buffers.
+ * So this information describes the whole screen, not just a window.
+ * To address pixels in a window, we need to know the window's position
+ * and size with respect to the screen.
+ */
+ GLint offset; /* in bytes */
+ GLint pitch; /* in pixels */
+
+ /* If the driver can do page flipping (full-screen double buffering)
+ * the current front/back buffers may get swapped.
+ * If page flipping is disabled, these fields will be identical to
+ * the offset/pitch/Data above.
+ * If page flipping is enabled, and this is the front(back) renderbuffer,
+ * flippedOffset/Pitch/Data will have the back(front) renderbuffer's values.
+ */
+ GLint flippedOffset;
+ GLint flippedPitch;
+ GLvoid *flippedData; /* mmap'd address of buffer memory, if used */
+
+ /* Pointer to corresponding __DRIdrawablePrivate. This is used to compute
+ * the window's position within the framebuffer.
+ */
+ __DRIdrawablePrivate *dPriv;
+
+ /* XXX this is for radeon/r200 only. We should really create a new
+ * r200Renderbuffer class, derived from this class... not a huge deal.
+ */
+ GLboolean depthHasSurface;
+
+ /**
+ * A handy flag to know if this is the back color buffer.
+ *
+ * \note
+ * This is currently only used by s3v and tdfx.
+ */
+ GLboolean backBuffer;
+} driRenderbuffer;
+
+
+extern driRenderbuffer *
+driNewRenderbuffer(GLenum format, GLvoid *addr,
+ GLint cpp, GLint offset, GLint pitch,
+ __DRIdrawablePrivate *dPriv);
+
+extern void
+driFlipRenderbuffers(struct gl_framebuffer *fb, GLboolean flipped);
+
+
+extern void
+driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv);
+
+
+#endif /* DRIRENDERBUFFER_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/extension_helper.h b/mesalib/src/mesa/drivers/dri/common/extension_helper.h
new file mode 100644
index 000000000..40a030ce0
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/extension_helper.h
@@ -0,0 +1,6609 @@
+/* DO NOT EDIT - This file generated automatically by extension_helper.py (from Mesa) script */
+
+/*
+ * (C) Copyright IBM Corporation 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "utils.h"
+#include "glapi/dispatch.h"
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char UniformMatrix3fvARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix3fv\0"
+ "glUniformMatrix3fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_multisample)
+static const char SampleCoverageARB_names[] =
+ "fi\0" /* Parameter signature */
+ "glSampleCoverage\0"
+ "glSampleCoverageARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionFilter1D_names[] =
+ "iiiiip\0" /* Parameter signature */
+ "glConvolutionFilter1D\0"
+ "glConvolutionFilter1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char BeginQueryARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glBeginQuery\0"
+ "glBeginQueryARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_NV_point_sprite)
+static const char PointParameteriNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glPointParameteri\0"
+ "glPointParameteriNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char GetProgramiv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramiv\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3sARB_names[] =
+ "iiii\0" /* Parameter signature */
+ "glMultiTexCoord3s\0"
+ "glMultiTexCoord3sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3iEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3i\0"
+ "glSecondaryColor3iEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3fMESA_names[] =
+ "fff\0" /* Parameter signature */
+ "glWindowPos3f\0"
+ "glWindowPos3fARB\0"
+ "glWindowPos3fMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char PixelTexGenParameterfvSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glPixelTexGenParameterfvSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char ActiveTextureARB_names[] =
+ "i\0" /* Parameter signature */
+ "glActiveTexture\0"
+ "glActiveTextureARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_blit)
+static const char BlitFramebufferEXT_names[] =
+ "iiiiiiiiii\0" /* Parameter signature */
+ "glBlitFramebuffer\0"
+ "glBlitFramebufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4ubvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4ubvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char GetProgramNamedParameterdvNV_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetProgramNamedParameterdvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char Histogram_names[] =
+ "iiii\0" /* Parameter signature */
+ "glHistogram\0"
+ "glHistogramEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_texture4D)
+static const char TexImage4DSGIS_names[] =
+ "iiiiiiiiiip\0" /* Parameter signature */
+ "glTexImage4DSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2dvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos2dv\0"
+ "glWindowPos2dvARB\0"
+ "glWindowPos2dvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor3fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glReplacementCodeuiColor3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_EXT_blend_equation_separate) || defined(need_GL_ATI_blend_equation_separate)
+static const char BlendEquationSeparateEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glBlendEquationSeparate\0"
+ "glBlendEquationSeparateEXT\0"
+ "glBlendEquationSeparateATI\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char ListParameterfSGIX_names[] =
+ "iif\0" /* Parameter signature */
+ "glListParameterfSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3bEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3b\0"
+ "glSecondaryColor3bEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord4fColor4fNormal3fVertex4fvSUN_names[] =
+ "pppp\0" /* Parameter signature */
+ "glTexCoord4fColor4fNormal3fVertex4fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4svNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char GetBufferSubDataARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetBufferSubData\0"
+ "glGetBufferSubDataARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char BufferSubDataARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glBufferSubData\0"
+ "glBufferSubDataARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor4ubVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glTexCoord2fColor4ubVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char AttachShader_names[] =
+ "ii\0" /* Parameter signature */
+ "glAttachShader\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2fARB_names[] =
+ "iff\0" /* Parameter signature */
+ "glVertexAttrib2f\0"
+ "glVertexAttrib2fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+static const char GetDebugLogLengthMESA_names[] =
+ "iii\0" /* Parameter signature */
+ "glGetDebugLogLengthMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3fARB_names[] =
+ "ifff\0" /* Parameter signature */
+ "glVertexAttrib3f\0"
+ "glVertexAttrib3fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char GetQueryivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetQueryiv\0"
+ "glGetQueryivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture3D)
+static const char TexImage3D_names[] =
+ "iiiiiiiiip\0" /* Parameter signature */
+ "glTexImage3D\0"
+ "glTexImage3DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiVertex3fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glReplacementCodeuiVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char GetQueryObjectivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetQueryObjectiv\0"
+ "glGetQueryObjectivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexSubImage2DARB_names[] =
+ "iiiiiiiip\0" /* Parameter signature */
+ "glCompressedTexSubImage2D\0"
+ "glCompressedTexSubImage2DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerOutputNV_names[] =
+ "iiiiiiiiii\0" /* Parameter signature */
+ "glCombinerOutputNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform2fARB_names[] =
+ "iff\0" /* Parameter signature */
+ "glUniform2f\0"
+ "glUniform2fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1sv\0"
+ "glVertexAttrib1svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs1dvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs1dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform2ivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform2iv\0"
+ "glUniform2ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char GetImageTransformParameterfvHP_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetImageTransformParameterfvHP\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightubvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightubvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1fvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char CopyConvolutionFilter1D_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glCopyConvolutionFilter1D\0"
+ "glCopyConvolutionFilter1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiNormal3fVertex3fSUN_names[] =
+ "iffffff\0" /* Parameter signature */
+ "glReplacementCodeuiNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char DeleteSync_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteSync\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentMaterialfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glFragmentMaterialfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_blend_color)
+static const char BlendColor_names[] =
+ "ffff\0" /* Parameter signature */
+ "glBlendColor\0"
+ "glBlendColorEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char UniformMatrix4fvARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix4fv\0"
+ "glUniformMatrix4fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object) || defined(need_GL_APPLE_vertex_array_object)
+static const char DeleteVertexArraysAPPLE_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteVertexArrays\0"
+ "glDeleteVertexArraysAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char ReadInstrumentsSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glReadInstrumentsSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix2x4fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix2x4fv\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4ubVertex3fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glColor4ubVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_texture_array)
+static const char FramebufferTextureLayerEXT_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glFramebufferTextureLayer\0"
+ "glFramebufferTextureLayerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char GetListParameterfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetListParameterfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NusvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Nusv\0"
+ "glVertexAttrib4NusvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4svMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos4svMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char CreateProgramObjectARB_names[] =
+ "\0" /* Parameter signature */
+ "glCreateProgramObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightModelivSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glFragmentLightModelivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix4x3fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix4x3fv\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char PrioritizeTextures_names[] =
+ "ipp\0" /* Parameter signature */
+ "glPrioritizeTextures\0"
+ "glPrioritizeTexturesEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char AsyncMarkerSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glAsyncMarkerSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactorubSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactorubSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+static const char ClearDebugLogMESA_names[] =
+ "iii\0" /* Parameter signature */
+ "glClearDebugLogMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char ResetHistogram_names[] =
+ "i\0" /* Parameter signature */
+ "glResetHistogram\0"
+ "glResetHistogramEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char GetProgramNamedParameterfvNV_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetProgramNamedParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_point_parameters) || defined(need_GL_EXT_point_parameters) || defined(need_GL_SGIS_point_parameters)
+static const char PointParameterfEXT_names[] =
+ "if\0" /* Parameter signature */
+ "glPointParameterf\0"
+ "glPointParameterfARB\0"
+ "glPointParameterfEXT\0"
+ "glPointParameterfSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const char LoadIdentityDeformationMapSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glLoadIdentityDeformationMapSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char GenFencesNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenFencesNV\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char ImageTransformParameterfHP_names[] =
+ "iif\0" /* Parameter signature */
+ "glImageTransformParameterfHP\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const char MatrixIndexusvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMatrixIndexusvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char DisableVertexAttribArrayARB_names[] =
+ "i\0" /* Parameter signature */
+ "glDisableVertexAttribArray\0"
+ "glDisableVertexAttribArrayARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char StencilMaskSeparate_names[] =
+ "ii\0" /* Parameter signature */
+ "glStencilMaskSeparate\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char ProgramLocalParameter4dARB_names[] =
+ "iidddd\0" /* Parameter signature */
+ "glProgramLocalParameter4dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexImage3DARB_names[] =
+ "iiiiiiiip\0" /* Parameter signature */
+ "glCompressedTexImage3D\0"
+ "glCompressedTexImage3DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char GetConvolutionParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetConvolutionParameteriv\0"
+ "glGetConvolutionParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1fARB_names[] =
+ "if\0" /* Parameter signature */
+ "glVertexAttrib1f\0"
+ "glVertexAttrib1fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char TestFenceNV_names[] =
+ "i\0" /* Parameter signature */
+ "glTestFenceNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord1fv\0"
+ "glMultiTexCoord1fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char ColorFragmentOp2ATI_names[] =
+ "iiiiiiiiii\0" /* Parameter signature */
+ "glColorFragmentOp2ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char SecondaryColorPointerListIBM_names[] =
+ "iiipi\0" /* Parameter signature */
+ "glSecondaryColorPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char GetPixelTexGenParameterivSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetPixelTexGenParameterivSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4fNV_names[] =
+ "iffff\0" /* Parameter signature */
+ "glVertexAttrib4fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeubSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glReplacementCodeubSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char FinishAsyncSGIX_names[] =
+ "p\0" /* Parameter signature */
+ "glFinishAsyncSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+static const char GetDebugLogMESA_names[] =
+ "iiiipp\0" /* Parameter signature */
+ "glGetDebugLogMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
+static const char FogCoorddEXT_names[] =
+ "d\0" /* Parameter signature */
+ "glFogCoordd\0"
+ "glFogCoorddEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4ubVertex3fSUN_names[] =
+ "iiiifff\0" /* Parameter signature */
+ "glColor4ubVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
+static const char FogCoordfEXT_names[] =
+ "f\0" /* Parameter signature */
+ "glFogCoordf\0"
+ "glFogCoordfEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fVertex3fSUN_names[] =
+ "fffff\0" /* Parameter signature */
+ "glTexCoord2fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactoriSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactoriSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2dNV_names[] =
+ "idd\0" /* Parameter signature */
+ "glVertexAttrib2dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char GetProgramInfoLog_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetProgramInfoLog\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NbvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Nbv\0"
+ "glVertexAttrib4NbvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
+static const char GetActiveAttribARB_names[] =
+ "iiipppp\0" /* Parameter signature */
+ "glGetActiveAttrib\0"
+ "glGetActiveAttribARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4ubNV_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glVertexAttrib4ubNV\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_texture_range)
+static const char TextureRangeAPPLE_names[] =
+ "iip\0" /* Parameter signature */
+ "glTextureRangeAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor4fNormal3fVertex3fSUN_names[] =
+ "ffffffffffff\0" /* Parameter signature */
+ "glTexCoord2fColor4fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerParameterfvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glCombinerParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs3dvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs3dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs4fvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs4fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_array_range)
+static const char VertexArrayRangeNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexArrayRangeNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightiSGIX_names[] =
+ "iii\0" /* Parameter signature */
+ "glFragmentLightiSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_polygon_offset)
+static const char PolygonOffsetEXT_names[] =
+ "ff\0" /* Parameter signature */
+ "glPolygonOffsetEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char PollAsyncSGIX_names[] =
+ "p\0" /* Parameter signature */
+ "glPollAsyncSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char DeleteFragmentShaderATI_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteFragmentShaderATI\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fNormal3fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glTexCoord2fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
+static const char MultTransposeMatrixdARB_names[] =
+ "p\0" /* Parameter signature */
+ "glMultTransposeMatrixd\0"
+ "glMultTransposeMatrixdARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2svMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos2sv\0"
+ "glWindowPos2svARB\0"
+ "glWindowPos2svMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexImage1DARB_names[] =
+ "iiiiiip\0" /* Parameter signature */
+ "glCompressedTexImage1D\0"
+ "glCompressedTexImage1DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2sNV_names[] =
+ "iii\0" /* Parameter signature */
+ "glVertexAttrib2sNV\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char NormalPointerListIBM_names[] =
+ "iipi\0" /* Parameter signature */
+ "glNormalPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char IndexPointerEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glIndexPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char NormalPointerEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glNormalPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3dARB_names[] =
+ "iddd\0" /* Parameter signature */
+ "glMultiTexCoord3d\0"
+ "glMultiTexCoord3dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2iARB_names[] =
+ "iii\0" /* Parameter signature */
+ "glMultiTexCoord2i\0"
+ "glMultiTexCoord2iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN_names[] =
+ "iffffffff\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord2sv\0"
+ "glMultiTexCoord2svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeubvSUN_names[] =
+ "p\0" /* Parameter signature */
+ "glReplacementCodeubvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform3iARB_names[] =
+ "iiii\0" /* Parameter signature */
+ "glUniform3i\0"
+ "glUniform3iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char GetFragmentMaterialfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFragmentMaterialfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char GetShaderInfoLog_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetShaderInfoLog\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char PollInstrumentsSGIX_names[] =
+ "p\0" /* Parameter signature */
+ "glPollInstrumentsSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactordSUN_names[] =
+ "d\0" /* Parameter signature */
+ "glGlobalAlphaFactordSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs3fvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs3fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenerateMipmapEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glGenerateMipmap\0"
+ "glGenerateMipmapEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char SetFragmentShaderConstantATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glSetFragmentShaderConstantATI\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char GetMapAttribParameterivNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetMapAttribParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char CreateShaderObjectARB_names[] =
+ "i\0" /* Parameter signature */
+ "glCreateShaderObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_sharpen_texture)
+static const char GetSharpenTexFuncSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetSharpenTexFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char BufferDataARB_names[] =
+ "iipi\0" /* Parameter signature */
+ "glBufferData\0"
+ "glBufferDataARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_array_range)
+static const char FlushVertexArrayRangeNV_names[] =
+ "\0" /* Parameter signature */
+ "glFlushVertexArrayRangeNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char SampleMapATI_names[] =
+ "iii\0" /* Parameter signature */
+ "glSampleMapATI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char VertexPointerEXT_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glVertexPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_texture_filter4)
+static const char GetTexFilterFuncSGIS_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetTexFilterFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetCombinerOutputParameterfvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetCombinerOutputParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_subtexture)
+static const char TexSubImage1D_names[] =
+ "iiiiiip\0" /* Parameter signature */
+ "glTexSubImage1D\0"
+ "glTexSubImage1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1sARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glVertexAttrib1s\0"
+ "glVertexAttrib1sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char FenceSync_names[] =
+ "ii\0" /* Parameter signature */
+ "glFenceSync\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char FinalCombinerInputNV_names[] =
+ "iiii\0" /* Parameter signature */
+ "glFinalCombinerInputNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_flush_raster)
+static const char FlushRasterSGIX_names[] =
+ "\0" /* Parameter signature */
+ "glFlushRasterSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fVertex3fSUN_names[] =
+ "ifffff\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform1fARB_names[] =
+ "if\0" /* Parameter signature */
+ "glUniform1f\0"
+ "glUniform1fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char AreTexturesResident_names[] =
+ "ipp\0" /* Parameter signature */
+ "glAreTexturesResident\0"
+ "glAreTexturesResidentEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ATI_separate_stencil)
+static const char StencilOpSeparate_names[] =
+ "iiii\0" /* Parameter signature */
+ "glStencilOpSeparate\0"
+ "glStencilOpSeparateATI\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table)
+static const char ColorTableParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glColorTableParameteriv\0"
+ "glColorTableParameterivSGI\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char FogCoordPointerListIBM_names[] =
+ "iipi\0" /* Parameter signature */
+ "glFogCoordPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3dMESA_names[] =
+ "ddd\0" /* Parameter signature */
+ "glWindowPos3d\0"
+ "glWindowPos3dARB\0"
+ "glWindowPos3dMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_point_parameters) || defined(need_GL_EXT_point_parameters) || defined(need_GL_SGIS_point_parameters)
+static const char PointParameterfvEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glPointParameterfv\0"
+ "glPointParameterfvARB\0"
+ "glPointParameterfvEXT\0"
+ "glPointParameterfvSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2fvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos2fv\0"
+ "glWindowPos2fvARB\0"
+ "glWindowPos2fvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3bvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3bv\0"
+ "glSecondaryColor3bvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char VertexPointerListIBM_names[] =
+ "iiipi\0" /* Parameter signature */
+ "glVertexPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramLocalParameterfvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramLocalParameterfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentMaterialfSGIX_names[] =
+ "iif\0" /* Parameter signature */
+ "glFragmentMaterialfSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fNormal3fVertex3fSUN_names[] =
+ "ffffffff\0" /* Parameter signature */
+ "glTexCoord2fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char RenderbufferStorageEXT_names[] =
+ "iiii\0" /* Parameter signature */
+ "glRenderbufferStorage\0"
+ "glRenderbufferStorageEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char IsFenceNV_names[] =
+ "i\0" /* Parameter signature */
+ "glIsFenceNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char AttachObjectARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glAttachObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char GetFragmentLightivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFragmentLightivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char UniformMatrix2fvARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix2fv\0"
+ "glUniformMatrix2fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2fARB_names[] =
+ "iff\0" /* Parameter signature */
+ "glMultiTexCoord2f\0"
+ "glMultiTexCoord2fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
+static const char ColorTable_names[] =
+ "iiiiip\0" /* Parameter signature */
+ "glColorTable\0"
+ "glColorTableSGI\0"
+ "glColorTableEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char MapControlPointsNV_names[] =
+ "iiiiiiiip\0" /* Parameter signature */
+ "glMapControlPointsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionFilter2D_names[] =
+ "iiiiiip\0" /* Parameter signature */
+ "glConvolutionFilter2D\0"
+ "glConvolutionFilter2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char MapParameterfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glMapParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3dv\0"
+ "glVertexAttrib3dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_PGI_misc_hints)
+static const char HintPGI_names[] =
+ "ii\0" /* Parameter signature */
+ "glHintPGI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glConvolutionParameteriv\0"
+ "glConvolutionParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_cull_vertex)
+static const char CullParameterdvEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glCullParameterdvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char ProgramNamedParameter4fNV_names[] =
+ "iipffff\0" /* Parameter signature */
+ "glProgramNamedParameter4fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color3fVertex3fSUN_names[] =
+ "ffffff\0" /* Parameter signature */
+ "glColor3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char ProgramEnvParameter4fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glProgramEnvParameter4fvARB\0"
+ "glProgramParameter4fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightModeliSGIX_names[] =
+ "ii\0" /* Parameter signature */
+ "glFragmentLightModeliSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glConvolutionParameterfv\0"
+ "glConvolutionParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_3DFX_tbuffer)
+static const char TbufferMask3DFX_names[] =
+ "i\0" /* Parameter signature */
+ "glTbufferMask3DFX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char LoadProgramNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glLoadProgramNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char WaitSync_names[] =
+ "iii\0" /* Parameter signature */
+ "glWaitSync\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4fvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char GetAttachedObjectsARB_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetAttachedObjectsARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform3fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform3fv\0"
+ "glUniform3fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_draw_range_elements)
+static const char DrawRangeElements_names[] =
+ "iiiiip\0" /* Parameter signature */
+ "glDrawRangeElements\0"
+ "glDrawRangeElementsEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+static const char SpriteParameterfvSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glSpriteParameterfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char CheckFramebufferStatusEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glCheckFramebufferStatus\0"
+ "glCheckFramebufferStatusEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactoruiSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactoruiSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char GetHandleARB_names[] =
+ "i\0" /* Parameter signature */
+ "glGetHandleARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char GetVertexAttribivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribiv\0"
+ "glGetVertexAttribivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetCombinerInputParameterfvNV_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glGetCombinerInputParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char CreateProgram_names[] =
+ "\0" /* Parameter signature */
+ "glCreateProgram\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
+static const char LoadTransposeMatrixdARB_names[] =
+ "p\0" /* Parameter signature */
+ "glLoadTransposeMatrixd\0"
+ "glLoadTransposeMatrixdARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetMinmax_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glGetMinmax\0"
+ "glGetMinmaxEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char StencilFuncSeparate_names[] =
+ "iiii\0" /* Parameter signature */
+ "glStencilFuncSeparate\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3sEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3s\0"
+ "glSecondaryColor3sEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color3fVertex3fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glColor3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactorbSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactorbSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char ImageTransformParameterfvHP_names[] =
+ "iip\0" /* Parameter signature */
+ "glImageTransformParameterfvHP\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4ivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4iv\0"
+ "glVertexAttrib4ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3fNV_names[] =
+ "ifff\0" /* Parameter signature */
+ "glVertexAttrib3fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs2dvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs2dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_timer_query)
+static const char GetQueryObjectui64vEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetQueryObjectui64vEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord3fv\0"
+ "glMultiTexCoord3fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3dEXT_names[] =
+ "ddd\0" /* Parameter signature */
+ "glSecondaryColor3d\0"
+ "glSecondaryColor3dEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetProgramParameterfvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetProgramParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char TangentPointerEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glTangentPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4fNormal3fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glColor4fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char GetInstrumentsSGIX_names[] =
+ "\0" /* Parameter signature */
+ "glGetInstrumentsSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char EvalMapsNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glEvalMapsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_subtexture)
+static const char TexSubImage2D_names[] =
+ "iiiiiiiip\0" /* Parameter signature */
+ "glTexSubImage2D\0"
+ "glTexSubImage2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glFragmentLightivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_texture_range)
+static const char GetTexParameterPointervAPPLE_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetTexParameterPointervAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+static const char PixelTransformParameterfvEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glPixelTransformParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4bvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4bv\0"
+ "glVertexAttrib4bvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char AlphaFragmentOp2ATI_names[] =
+ "iiiiiiiii\0" /* Parameter signature */
+ "glAlphaFragmentOp2ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4sARB_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glMultiTexCoord4s\0"
+ "glMultiTexCoord4sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char GetFragmentMaterialivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFragmentMaterialivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4dMESA_names[] =
+ "dddd\0" /* Parameter signature */
+ "glWindowPos4dMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightPointerARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glWeightPointerARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2dMESA_names[] =
+ "dd\0" /* Parameter signature */
+ "glWindowPos2d\0"
+ "glWindowPos2dARB\0"
+ "glWindowPos2dMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture3DEXT_names[] =
+ "iiiiii\0" /* Parameter signature */
+ "glFramebufferTexture3D\0"
+ "glFramebufferTexture3DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_blend_minmax)
+static const char BlendEquation_names[] =
+ "i\0" /* Parameter signature */
+ "glBlendEquation\0"
+ "glBlendEquationEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3dNV_names[] =
+ "iddd\0" /* Parameter signature */
+ "glVertexAttrib3dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3dARB_names[] =
+ "iddd\0" /* Parameter signature */
+ "glVertexAttrib3d\0"
+ "glVertexAttrib3dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
+ "ppppp\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4fARB_names[] =
+ "iffff\0" /* Parameter signature */
+ "glVertexAttrib4f\0"
+ "glVertexAttrib4fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_index_func)
+static const char IndexFuncEXT_names[] =
+ "if\0" /* Parameter signature */
+ "glIndexFuncEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture2DEXT_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glFramebufferTexture2D\0"
+ "glFramebufferTexture2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord2dv\0"
+ "glMultiTexCoord2dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_cull_vertex)
+static const char CullParameterfvEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glCullParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char ProgramNamedParameter4fvNV_names[] =
+ "iipp\0" /* Parameter signature */
+ "glProgramNamedParameter4fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColorPointerEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glSecondaryColorPointer\0"
+ "glSecondaryColorPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4fv\0"
+ "glVertexAttrib4fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char ColorPointerListIBM_names[] =
+ "iiipi\0" /* Parameter signature */
+ "glColorPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char GetActiveUniformARB_names[] =
+ "iiipppp\0" /* Parameter signature */
+ "glGetActiveUniform\0"
+ "glGetActiveUniformARB\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char ImageTransformParameteriHP_names[] =
+ "iii\0" /* Parameter signature */
+ "glImageTransformParameteriHP\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord1sv\0"
+ "glMultiTexCoord1svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char EndQueryARB_names[] =
+ "i\0" /* Parameter signature */
+ "glEndQuery\0"
+ "glEndQueryARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char DeleteFencesNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteFencesNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const char DeformationMap3dSGIX_names[] =
+ "iddiiddiiddiip\0" /* Parameter signature */
+ "glDeformationMap3dSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char IsShader_names[] =
+ "i\0" /* Parameter signature */
+ "glIsShader\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char GetImageTransformParameterivHP_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetImageTransformParameterivHP\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4ivMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos4ivMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord3sv\0"
+ "glMultiTexCoord3svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4iARB_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glMultiTexCoord4i\0"
+ "glMultiTexCoord4iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3ivEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3ivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_resize_buffers)
+static const char ResizeBuffersMESA_names[] =
+ "\0" /* Parameter signature */
+ "glResizeBuffersMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char GetUniformivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetUniformiv\0"
+ "glGetUniformivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char PixelTexGenParameteriSGIS_names[] =
+ "ii\0" /* Parameter signature */
+ "glPixelTexGenParameteriSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+static const char VertexPointervINTEL_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexPointervINTEL\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor4fNormal3fVertex3fvSUN_names[] =
+ "pppp\0" /* Parameter signature */
+ "glReplacementCodeuiColor4fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3uiEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3ui\0"
+ "glSecondaryColor3uiEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char StartInstrumentsSGIX_names[] =
+ "\0" /* Parameter signature */
+ "glStartInstrumentsSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3usvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3usv\0"
+ "glSecondaryColor3usvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2fvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char ProgramLocalParameter4dvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glProgramLocalParameter4dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const char MatrixIndexuivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMatrixIndexuivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object)
+static const char RenderbufferStorageMultisample_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glRenderbufferStorageMultisample\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3sEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glTangent3sEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactorfSUN_names[] =
+ "f\0" /* Parameter signature */
+ "glGlobalAlphaFactorfSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3iARB_names[] =
+ "iiii\0" /* Parameter signature */
+ "glMultiTexCoord3i\0"
+ "glMultiTexCoord3iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char IsProgram_names[] =
+ "i\0" /* Parameter signature */
+ "glIsProgram\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char TexCoordPointerListIBM_names[] =
+ "iiipi\0" /* Parameter signature */
+ "glTexCoordPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactorusSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactorusSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2dvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferRenderbufferEXT_names[] =
+ "iiii\0" /* Parameter signature */
+ "glFramebufferRenderbuffer\0"
+ "glFramebufferRenderbufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1dvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char GenTextures_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenTextures\0"
+ "glGenTexturesEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char SetFenceNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glSetFenceNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char FramebufferTexture1DEXT_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glFramebufferTexture1D\0"
+ "glFramebufferTexture1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetCombinerOutputParameterivNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetCombinerOutputParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char PixelTexGenParameterivSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glPixelTexGenParameterivSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_perturb_normal)
+static const char TextureNormalEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glTextureNormalEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char IndexPointerListIBM_names[] =
+ "iipi\0" /* Parameter signature */
+ "glIndexPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightfvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4fMESA_names[] =
+ "ffff\0" /* Parameter signature */
+ "glWindowPos4fMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3dvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos3dv\0"
+ "glWindowPos3dvARB\0"
+ "glWindowPos3dvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_timer_query)
+static const char GetQueryObjecti64vEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetQueryObjecti64vEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1dARB_names[] =
+ "id\0" /* Parameter signature */
+ "glMultiTexCoord1d\0"
+ "glMultiTexCoord1dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_NV_point_sprite)
+static const char PointParameterivNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glPointParameteriv\0"
+ "glPointParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform2fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform2fv\0"
+ "glUniform2fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const char BufferParameteriAPPLE_names[] =
+ "iii\0" /* Parameter signature */
+ "glBufferParameteriAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord3dv\0"
+ "glMultiTexCoord3dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN_names[] =
+ "pppp\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char DeleteObjectARB_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const char MatrixIndexPointerARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glMatrixIndexPointerARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char ProgramNamedParameter4dvNV_names[] =
+ "iipp\0" /* Parameter signature */
+ "glProgramNamedParameter4dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3fvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glTangent3fvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object)
+static const char GenVertexArrays_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenVertexArrays\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char BindFramebufferEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glBindFramebuffer\0"
+ "glBindFramebufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_reference_plane)
+static const char ReferencePlaneSGIX_names[] =
+ "p\0" /* Parameter signature */
+ "glReferencePlaneSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char ValidateProgramARB_names[] =
+ "i\0" /* Parameter signature */
+ "glValidateProgram\0"
+ "glValidateProgramARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_compiled_vertex_array)
+static const char UnlockArraysEXT_names[] =
+ "\0" /* Parameter signature */
+ "glUnlockArraysEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor3fVertex3fSUN_names[] =
+ "ffffffff\0" /* Parameter signature */
+ "glTexCoord2fColor3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3fvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos3fv\0"
+ "glWindowPos3fvARB\0"
+ "glWindowPos3fvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1svNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const char CopyTexSubImage3D_names[] =
+ "iiiiiiiii\0" /* Parameter signature */
+ "glCopyTexSubImage3D\0"
+ "glCopyTexSubImage3DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2dARB_names[] =
+ "idd\0" /* Parameter signature */
+ "glVertexAttrib2d\0"
+ "glVertexAttrib2dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char GetInteger64v_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetInteger64v\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_texture_color_mask)
+static const char TextureColorMaskSGIS_names[] =
+ "iiii\0" /* Parameter signature */
+ "glTextureColorMaskSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
+static const char GetColorTable_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetColorTable\0"
+ "glGetColorTableSGI\0"
+ "glGetColorTableEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table)
+static const char CopyColorTable_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glCopyColorTable\0"
+ "glCopyColorTableSGI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetHistogramParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetHistogramParameterfv\0"
+ "glGetHistogramParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+static const char ColorPointervINTEL_names[] =
+ "iip\0" /* Parameter signature */
+ "glColorPointervINTEL\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char AlphaFragmentOp1ATI_names[] =
+ "iiiiii\0" /* Parameter signature */
+ "glAlphaFragmentOp1ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3ivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord3iv\0"
+ "glMultiTexCoord3ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2sARB_names[] =
+ "iii\0" /* Parameter signature */
+ "glMultiTexCoord2s\0"
+ "glMultiTexCoord2sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1dv\0"
+ "glVertexAttrib1dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char DeleteTextures_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteTextures\0"
+ "glDeleteTexturesEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char TexCoordPointerEXT_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glTexCoordPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_texture4D)
+static const char TexSubImage4DSGIS_names[] =
+ "iiiiiiiiiiiip\0" /* Parameter signature */
+ "glTexSubImage4DSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners2)
+static const char CombinerStageParameterfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glCombinerStageParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char StopInstrumentsSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glStopInstrumentsSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord4fColor4fNormal3fVertex4fSUN_names[] =
+ "fffffffffffffff\0" /* Parameter signature */
+ "glTexCoord4fColor4fNormal3fVertex4fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const char DeformSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glDeformSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char GetVertexAttribfvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribfv\0"
+ "glGetVertexAttribfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3ivEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3iv\0"
+ "glSecondaryColor3ivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix4x2fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix4x2fv\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_detail_texture)
+static const char GetDetailTexFuncSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetDetailTexFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners2)
+static const char GetCombinerStageParameterfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetCombinerStageParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object)
+static const char BindVertexArray_names[] =
+ "i\0" /* Parameter signature */
+ "glBindVertexArray\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4ubVertex2fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glColor4ubVertex2fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_texture_filter4)
+static const char TexFilterFuncSGIS_names[] =
+ "iiip\0" /* Parameter signature */
+ "glTexFilterFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_multisample) || defined(need_GL_EXT_multisample)
+static const char SampleMaskSGIS_names[] =
+ "fi\0" /* Parameter signature */
+ "glSampleMaskSGIS\0"
+ "glSampleMaskEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
+static const char GetAttribLocationARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetAttribLocation\0"
+ "glGetAttribLocationARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4ubvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4ubv\0"
+ "glVertexAttrib4ubvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_detail_texture)
+static const char DetailTexFuncSGIS_names[] =
+ "iip\0" /* Parameter signature */
+ "glDetailTexFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Normal3fVertex3fSUN_names[] =
+ "ffffff\0" /* Parameter signature */
+ "glNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const char CopyTexImage2D_names[] =
+ "iiiiiiii\0" /* Parameter signature */
+ "glCopyTexImage2D\0"
+ "glCopyTexImage2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char GetBufferPointervARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetBufferPointerv\0"
+ "glGetBufferPointervARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char ProgramEnvParameter4fARB_names[] =
+ "iiffff\0" /* Parameter signature */
+ "glProgramEnvParameter4fARB\0"
+ "glProgramParameter4fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform3ivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform3iv\0"
+ "glUniform3ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char GetFenceivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFenceivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4dvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos4dvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_color_subtable)
+static const char ColorSubTable_names[] =
+ "iiiiip\0" /* Parameter signature */
+ "glColorSubTable\0"
+ "glColorSubTableEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4ivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord4iv\0"
+ "glMultiTexCoord4ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_gpu_program_parameters)
+static const char ProgramLocalParameters4fvEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glProgramLocalParameters4fvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char GetMapAttribParameterfvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetMapAttribParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4sARB_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glVertexAttrib4s\0"
+ "glVertexAttrib4sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char GetQueryObjectuivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetQueryObjectuiv\0"
+ "glGetQueryObjectuivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char MapParameterivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glMapParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenRenderbuffersEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenRenderbuffers\0"
+ "glGenRenderbuffersEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2dv\0"
+ "glVertexAttrib2dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char EdgeFlagPointerEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glEdgeFlagPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs2svNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs2svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightbvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightbvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2fv\0"
+ "glVertexAttrib2fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char GetBufferParameterivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetBufferParameteriv\0"
+ "glGetBufferParameterivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char ListParameteriSGIX_names[] =
+ "iii\0" /* Parameter signature */
+ "glListParameteriSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor4fNormal3fVertex3fSUN_names[] =
+ "iffffffffff\0" /* Parameter signature */
+ "glReplacementCodeuiColor4fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const char InstrumentsBufferSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glInstrumentsBufferSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Niv\0"
+ "glVertexAttrib4NivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char GetAttachedShaders_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetAttachedShaders\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_vertex_array_object)
+static const char GenVertexArraysAPPLE_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenVertexArraysAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_gpu_program_parameters)
+static const char ProgramEnvParameters4fvEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glProgramEnvParameters4fvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor4fNormal3fVertex3fvSUN_names[] =
+ "pppp\0" /* Parameter signature */
+ "glTexCoord2fColor4fNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2iMESA_names[] =
+ "ii\0" /* Parameter signature */
+ "glWindowPos2i\0"
+ "glWindowPos2iARB\0"
+ "glWindowPos2iMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3fvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3fv\0"
+ "glSecondaryColor3fvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexSubImage1DARB_names[] =
+ "iiiiiip\0" /* Parameter signature */
+ "glCompressedTexSubImage1D\0"
+ "glCompressedTexSubImage1DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetVertexAttribivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramStringARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramStringARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char TexBumpParameterfvATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glTexBumpParameterfvATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char CompileShaderARB_names[] =
+ "i\0" /* Parameter signature */
+ "glCompileShader\0"
+ "glCompileShaderARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char DeleteShader_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteShader\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform3fARB_names[] =
+ "ifff\0" /* Parameter signature */
+ "glUniform3f\0"
+ "glUniform3fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char ListParameterfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glListParameterfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3dvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glTangent3dvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetVertexAttribfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3sMESA_names[] =
+ "iii\0" /* Parameter signature */
+ "glWindowPos3s\0"
+ "glWindowPos3sARB\0"
+ "glWindowPos3sMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2svNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs1fvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs1fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fVertex3fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glTexCoord2fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4sMESA_names[] =
+ "iiii\0" /* Parameter signature */
+ "glWindowPos4sMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NuivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Nuiv\0"
+ "glVertexAttrib4NuivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char ClientActiveTextureARB_names[] =
+ "i\0" /* Parameter signature */
+ "glClientActiveTexture\0"
+ "glClientActiveTextureARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_pixel_texture)
+static const char PixelTexGenSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glPixelTexGenSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeusvSUN_names[] =
+ "p\0" /* Parameter signature */
+ "glReplacementCodeusvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform4fARB_names[] =
+ "iffff\0" /* Parameter signature */
+ "glUniform4f\0"
+ "glUniform4fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_map_buffer_range)
+static const char FlushMappedBufferRange_names[] =
+ "iii\0" /* Parameter signature */
+ "glFlushMappedBufferRange\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char IsProgramNV_names[] =
+ "i\0" /* Parameter signature */
+ "glIsProgramARB\0"
+ "glIsProgramNV\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const char FlushMappedBufferRangeAPPLE_names[] =
+ "iii\0" /* Parameter signature */
+ "glFlushMappedBufferRangeAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodePointerSUN_names[] =
+ "iip\0" /* Parameter signature */
+ "glReplacementCodePointerSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char ProgramEnvParameter4dARB_names[] =
+ "iidddd\0" /* Parameter signature */
+ "glProgramEnvParameter4dARB\0"
+ "glProgramParameter4dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table)
+static const char ColorTableParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glColorTableParameterfv\0"
+ "glColorTableParameterfvSGI\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightModelfSGIX_names[] =
+ "if\0" /* Parameter signature */
+ "glFragmentLightModelfSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3bvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3bvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char IsTexture_names[] =
+ "i\0" /* Parameter signature */
+ "glIsTexture\0"
+ "glIsTextureEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_weighting)
+static const char VertexWeightfvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glVertexWeightfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1dARB_names[] =
+ "id\0" /* Parameter signature */
+ "glVertexAttrib1d\0"
+ "glVertexAttrib1dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const char ImageTransformParameterivHP_names[] =
+ "iip\0" /* Parameter signature */
+ "glImageTransformParameterivHP\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char DeleteQueriesARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteQueries\0"
+ "glDeleteQueriesARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4ubVertex2fSUN_names[] =
+ "iiiiff\0" /* Parameter signature */
+ "glColor4ubVertex2fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentColorMaterialSGIX_names[] =
+ "ii\0" /* Parameter signature */
+ "glFragmentColorMaterialSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const char CurrentPaletteMatrixARB_names[] =
+ "i\0" /* Parameter signature */
+ "glCurrentPaletteMatrixARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_multisample) || defined(need_GL_EXT_multisample)
+static const char SamplePatternSGIS_names[] =
+ "i\0" /* Parameter signature */
+ "glSamplePatternSGIS\0"
+ "glSamplePatternEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char IsQueryARB_names[] =
+ "i\0" /* Parameter signature */
+ "glIsQuery\0"
+ "glIsQueryARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor4ubVertex3fSUN_names[] =
+ "iiiiifff\0" /* Parameter signature */
+ "glReplacementCodeuiColor4ubVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4usvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4usv\0"
+ "glVertexAttrib4usvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char LinkProgramARB_names[] =
+ "i\0" /* Parameter signature */
+ "glLinkProgram\0"
+ "glLinkProgramARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib2fNV_names[] =
+ "iff\0" /* Parameter signature */
+ "glVertexAttrib2fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char ShaderSourceARB_names[] =
+ "iipp\0" /* Parameter signature */
+ "glShaderSource\0"
+ "glShaderSourceARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentMaterialiSGIX_names[] =
+ "iii\0" /* Parameter signature */
+ "glFragmentMaterialiSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3sv\0"
+ "glVertexAttrib3svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexSubImage3DARB_names[] =
+ "iiiiiiiiiip\0" /* Parameter signature */
+ "glCompressedTexSubImage3D\0"
+ "glCompressedTexSubImage3DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2ivMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos2iv\0"
+ "glWindowPos2ivARB\0"
+ "glWindowPos2ivMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char IsFramebufferEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glIsFramebuffer\0"
+ "glIsFramebufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform4ivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform4iv\0"
+ "glUniform4ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char GetVertexAttribdvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribdv\0"
+ "glGetVertexAttribdvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char TexBumpParameterivATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glTexBumpParameterivATI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char GetSeparableFilter_names[] =
+ "iiippp\0" /* Parameter signature */
+ "glGetSeparableFilter\0"
+ "glGetSeparableFilterEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3dEXT_names[] =
+ "ddd\0" /* Parameter signature */
+ "glBinormal3dEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+static const char SpriteParameteriSGIX_names[] =
+ "ii\0" /* Parameter signature */
+ "glSpriteParameteriSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char RequestResidentProgramsNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glRequestResidentProgramsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_tag_sample_buffer)
+static const char TagSampleBufferSGIX_names[] =
+ "\0" /* Parameter signature */
+ "glTagSampleBufferSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeusSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glReplacementCodeusSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char ListParameterivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glListParameterivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_multi_draw_arrays)
+static const char MultiDrawElementsEXT_names[] =
+ "ipipi\0" /* Parameter signature */
+ "glMultiDrawElements\0"
+ "glMultiDrawElementsEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform1ivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform1iv\0"
+ "glUniform1ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2sMESA_names[] =
+ "ii\0" /* Parameter signature */
+ "glWindowPos2s\0"
+ "glWindowPos2sARB\0"
+ "glWindowPos2sMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightusvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightusvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
+static const char FogCoordPointerEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glFogCoordPointer\0"
+ "glFogCoordPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_index_material)
+static const char IndexMaterialEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glIndexMaterialEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3ubvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3ubv\0"
+ "glSecondaryColor3ubvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4dv\0"
+ "glVertexAttrib4dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_shader)
+static const char BindAttribLocationARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glBindAttribLocation\0"
+ "glBindAttribLocationARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2dARB_names[] =
+ "idd\0" /* Parameter signature */
+ "glMultiTexCoord2d\0"
+ "glMultiTexCoord2dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char ExecuteProgramNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glExecuteProgramNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char LightEnviSGIX_names[] =
+ "ii\0" /* Parameter signature */
+ "glLightEnviSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeuiSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glReplacementCodeuiSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribPointerNV_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glVertexAttribPointerNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GetFramebufferAttachmentParameterivEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetFramebufferAttachmentParameteriv\0"
+ "glGetFramebufferAttachmentParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+static const char PixelTransformParameterfEXT_names[] =
+ "iif\0" /* Parameter signature */
+ "glPixelTransformParameterfEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord4dv\0"
+ "glMultiTexCoord4dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+static const char PixelTransformParameteriEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glPixelTransformParameteriEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor4ubVertex3fSUN_names[] =
+ "ffiiiifff\0" /* Parameter signature */
+ "glTexCoord2fColor4ubVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform1iARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glUniform1i\0"
+ "glUniform1iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttribPointerARB_names[] =
+ "iiiiip\0" /* Parameter signature */
+ "glVertexAttribPointer\0"
+ "glVertexAttribPointerARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_sharpen_texture)
+static const char SharpenTexFuncSGIS_names[] =
+ "iip\0" /* Parameter signature */
+ "glSharpenTexFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord4fv\0"
+ "glMultiTexCoord4fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix2x3fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix2x3fv\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char TrackMatrixNV_names[] =
+ "iiii\0" /* Parameter signature */
+ "glTrackMatrixNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerParameteriNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glCombinerParameteriNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char DeleteAsyncMarkersSGIX_names[] =
+ "ii\0" /* Parameter signature */
+ "glDeleteAsyncMarkersSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char IsAsyncMarkerSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glIsAsyncMarkerSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_framezoom)
+static const char FrameZoomSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glFrameZoomSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Normal3fVertex3fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NsvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Nsv\0"
+ "glVertexAttrib4NsvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3fv\0"
+ "glVertexAttrib3fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char GetSynciv_names[] =
+ "iiipp\0" /* Parameter signature */
+ "glGetSynciv\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char DeleteFramebuffersEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteFramebuffers\0"
+ "glDeleteFramebuffersEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const char GlobalAlphaFactorsSUN_names[] =
+ "i\0" /* Parameter signature */
+ "glGlobalAlphaFactorsSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture3D)
+static const char TexSubImage3D_names[] =
+ "iiiiiiiiiip\0" /* Parameter signature */
+ "glTexSubImage3D\0"
+ "glTexSubImage3DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3fEXT_names[] =
+ "fff\0" /* Parameter signature */
+ "glTangent3fEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3uivEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3uiv\0"
+ "glSecondaryColor3uivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const char MatrixIndexubvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMatrixIndexubvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char Color4fNormal3fVertex3fSUN_names[] =
+ "ffffffffff\0" /* Parameter signature */
+ "glColor4fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char PixelTexGenParameterfSGIS_names[] =
+ "if\0" /* Parameter signature */
+ "glPixelTexGenParameterfSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char CreateShader_names[] =
+ "i\0" /* Parameter signature */
+ "glCreateShader\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
+static const char GetColorTableParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetColorTableParameterfv\0"
+ "glGetColorTableParameterfvSGI\0"
+ "glGetColorTableParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightModelfvSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glFragmentLightModelfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord3fARB_names[] =
+ "ifff\0" /* Parameter signature */
+ "glMultiTexCoord3f\0"
+ "glMultiTexCoord3fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const char GetPixelTexGenParameterfvSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetPixelTexGenParameterfvSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GenFramebuffersEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenFramebuffers\0"
+ "glGenFramebuffersEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetProgramParameterdvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetProgramParameterdvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object) || defined(need_GL_APPLE_vertex_array_object)
+static const char IsVertexArrayAPPLE_names[] =
+ "i\0" /* Parameter signature */
+ "glIsVertexArray\0"
+ "glIsVertexArrayAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glFragmentLightfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char DetachShader_names[] =
+ "ii\0" /* Parameter signature */
+ "glDetachShader\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NubARB_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glVertexAttrib4Nub\0"
+ "glVertexAttrib4NubARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramEnvParameterfvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramEnvParameterfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetTrackMatrixivNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetTrackMatrixivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3svNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform4fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform4fv\0"
+ "glUniform4fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
+static const char MultTransposeMatrixfARB_names[] =
+ "p\0" /* Parameter signature */
+ "glMultTransposeMatrixf\0"
+ "glMultTransposeMatrixfARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char ColorFragmentOp1ATI_names[] =
+ "iiiiiii\0" /* Parameter signature */
+ "glColorFragmentOp1ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char GetUniformfvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetUniformfv\0"
+ "glGetUniformfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN_names[] =
+ "iffffffffffff\0" /* Parameter signature */
+ "glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char DetachObjectARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glDetachObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char VertexBlendARB_names[] =
+ "i\0" /* Parameter signature */
+ "glVertexBlendARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3iMESA_names[] =
+ "iii\0" /* Parameter signature */
+ "glWindowPos3i\0"
+ "glWindowPos3iARB\0"
+ "glWindowPos3iMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char SeparableFilter2D_names[] =
+ "iiiiiipp\0" /* Parameter signature */
+ "glSeparableFilter2D\0"
+ "glSeparableFilter2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor4ubVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glReplacementCodeuiColor4ubVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char CompressedTexImage2DARB_names[] =
+ "iiiiiiip\0" /* Parameter signature */
+ "glCompressedTexImage2D\0"
+ "glCompressedTexImage2DARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char ArrayElement_names[] =
+ "i\0" /* Parameter signature */
+ "glArrayElement\0"
+ "glArrayElementEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_depth_bounds_test)
+static const char DepthBoundsEXT_names[] =
+ "dd\0" /* Parameter signature */
+ "glDepthBoundsEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char ProgramParameters4fvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glProgramParameters4fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const char DeformationMap3fSGIX_names[] =
+ "iffiiffiiffiip\0" /* Parameter signature */
+ "glDeformationMap3fSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetProgramivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetMinmaxParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetMinmaxParameteriv\0"
+ "glGetMinmaxParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const char CopyTexImage1D_names[] =
+ "iiiiiii\0" /* Parameter signature */
+ "glCopyTexImage1D\0"
+ "glCopyTexImage1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char AlphaFragmentOp3ATI_names[] =
+ "iiiiiiiiiiii\0" /* Parameter signature */
+ "glAlphaFragmentOp3ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetVertexAttribdvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribdvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3fvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetFinalCombinerInputParameterivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFinalCombinerInputParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char GetMapParameterivNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetMapParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform4iARB_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glUniform4i\0"
+ "glUniform4iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionParameteri_names[] =
+ "iii\0" /* Parameter signature */
+ "glConvolutionParameteri\0"
+ "glConvolutionParameteriEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3sEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glBinormal3sEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char ConvolutionParameterf_names[] =
+ "iif\0" /* Parameter signature */
+ "glConvolutionParameterf\0"
+ "glConvolutionParameterfEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGI_color_table) || defined(need_GL_EXT_paletted_texture)
+static const char GetColorTableParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetColorTableParameteriv\0"
+ "glGetColorTableParameterivSGI\0"
+ "glGetColorTableParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char ProgramEnvParameter4dvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glProgramEnvParameter4dvARB\0"
+ "glProgramParameter4dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs2fvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs2fvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char UseProgramObjectARB_names[] =
+ "i\0" /* Parameter signature */
+ "glUseProgram\0"
+ "glUseProgramObjectARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char GetMapParameterfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetMapParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char PassTexCoordATI_names[] =
+ "iii\0" /* Parameter signature */
+ "glPassTexCoordATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char DeleteProgram_names[] =
+ "i\0" /* Parameter signature */
+ "glDeleteProgram\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3ivEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glTangent3ivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3dEXT_names[] =
+ "ddd\0" /* Parameter signature */
+ "glTangent3dEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3dvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3dv\0"
+ "glSecondaryColor3dvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_multi_draw_arrays)
+static const char MultiDrawArraysEXT_names[] =
+ "ippi\0" /* Parameter signature */
+ "glMultiDrawArrays\0"
+ "glMultiDrawArraysEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char BindRenderbufferEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glBindRenderbuffer\0"
+ "glBindRenderbufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4dARB_names[] =
+ "idddd\0" /* Parameter signature */
+ "glMultiTexCoord4d\0"
+ "glMultiTexCoord4dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3usEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3us\0"
+ "glSecondaryColor3usEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char ProgramLocalParameter4fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glProgramLocalParameter4fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char DeleteProgramsNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteProgramsARB\0"
+ "glDeleteProgramsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1sARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glMultiTexCoord1s\0"
+ "glMultiTexCoord1sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiColor3fVertex3fSUN_names[] =
+ "iffffff\0" /* Parameter signature */
+ "glReplacementCodeuiColor3fVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char GetVertexAttribPointervNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetVertexAttribPointerv\0"
+ "glGetVertexAttribPointervARB\0"
+ "glGetVertexAttribPointervNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1dvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord1dv\0"
+ "glMultiTexCoord1dvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform2iARB_names[] =
+ "iii\0" /* Parameter signature */
+ "glUniform2i\0"
+ "glUniform2iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char GetProgramStringNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramStringNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char ColorPointerEXT_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glColorPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char MapBufferARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glMapBuffer\0"
+ "glMapBufferARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3svEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3svEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_light_texture)
+static const char ApplyTextureEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glApplyTextureEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_light_texture)
+static const char TextureMaterialEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glTextureMaterialEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_light_texture)
+static const char TextureLightEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glTextureLightEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char ResetMinmax_names[] =
+ "i\0" /* Parameter signature */
+ "glResetMinmax\0"
+ "glResetMinmaxEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+static const char SpriteParameterfSGIX_names[] =
+ "if\0" /* Parameter signature */
+ "glSpriteParameterfSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4sNV_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glVertexAttrib4sNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char GetConvolutionParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetConvolutionParameterfv\0"
+ "glGetConvolutionParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs4dvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs4dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_multimode_draw_arrays)
+static const char MultiModeDrawArraysIBM_names[] =
+ "pppii\0" /* Parameter signature */
+ "glMultiModeDrawArraysIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4dARB_names[] =
+ "idddd\0" /* Parameter signature */
+ "glVertexAttrib4d\0"
+ "glVertexAttrib4dARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char GetTexBumpParameterfvATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetTexBumpParameterfvATI\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const char ProgramNamedParameter4dNV_names[] =
+ "iipdddd\0" /* Parameter signature */
+ "glProgramNamedParameter4dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_weighting)
+static const char VertexWeightfEXT_names[] =
+ "f\0" /* Parameter signature */
+ "glVertexWeightfEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3fEXT_names[] =
+ "fff\0" /* Parameter signature */
+ "glBinormal3fEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
+static const char FogCoordfvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glFogCoordfv\0"
+ "glFogCoordfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1ivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord1iv\0"
+ "glMultiTexCoord1ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3ubEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glSecondaryColor3ub\0"
+ "glSecondaryColor3ubEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2ivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord2iv\0"
+ "glMultiTexCoord2ivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_fog_function)
+static const char FogFuncSGIS_names[] =
+ "ip\0" /* Parameter signature */
+ "glFogFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const char CopyTexSubImage2D_names[] =
+ "iiiiiiii\0" /* Parameter signature */
+ "glCopyTexSubImage2D\0"
+ "glCopyTexSubImage2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char GetObjectParameterivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetObjectParameterivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord4fVertex4fSUN_names[] =
+ "ffffffff\0" /* Parameter signature */
+ "glTexCoord4fVertex4fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_APPLE_vertex_array_object)
+static const char BindVertexArrayAPPLE_names[] =
+ "i\0" /* Parameter signature */
+ "glBindVertexArrayAPPLE\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramLocalParameterdvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramLocalParameterdvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetHistogramParameteriv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetHistogramParameteriv\0"
+ "glGetHistogramParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1iARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glMultiTexCoord1i\0"
+ "glMultiTexCoord1iARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char GetConvolutionFilter_names[] =
+ "iiip\0" /* Parameter signature */
+ "glGetConvolutionFilter\0"
+ "glGetConvolutionFilterEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramivARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_blend_func_separate) || defined(need_GL_INGR_blend_func_separate)
+static const char BlendFuncSeparateEXT_names[] =
+ "iiii\0" /* Parameter signature */
+ "glBlendFuncSeparate\0"
+ "glBlendFuncSeparateEXT\0"
+ "glBlendFuncSeparateINGR\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_map_buffer_range)
+static const char MapBufferRange_names[] =
+ "iiii\0" /* Parameter signature */
+ "glMapBufferRange\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char ProgramParameters4dvNV_names[] =
+ "iiip\0" /* Parameter signature */
+ "glProgramParameters4dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord2fColor3fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glTexCoord2fColor3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3dvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3dvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_fence)
+static const char FinishFenceNV_names[] =
+ "i\0" /* Parameter signature */
+ "glFinishFenceNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIS_fog_function)
+static const char GetFogFuncSGIS_names[] =
+ "p\0" /* Parameter signature */
+ "glGetFogFuncSGIS\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char GetUniformLocationARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetUniformLocation\0"
+ "glGetUniformLocationARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3fEXT_names[] =
+ "fff\0" /* Parameter signature */
+ "glSecondaryColor3f\0"
+ "glSecondaryColor3fEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerInputNV_names[] =
+ "iiiiii\0" /* Parameter signature */
+ "glCombinerInputNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib3sARB_names[] =
+ "iiii\0" /* Parameter signature */
+ "glVertexAttrib3s\0"
+ "glVertexAttrib3sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiNormal3fVertex3fvSUN_names[] =
+ "ppp\0" /* Parameter signature */
+ "glReplacementCodeuiNormal3fVertex3fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char ProgramStringARB_names[] =
+ "iiip\0" /* Parameter signature */
+ "glProgramStringARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char TexCoord4fVertex4fvSUN_names[] =
+ "pp\0" /* Parameter signature */
+ "glTexCoord4fVertex4fvSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3sNV_names[] =
+ "iiii\0" /* Parameter signature */
+ "glVertexAttrib3sNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1fNV_names[] =
+ "if\0" /* Parameter signature */
+ "glVertexAttrib1fNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentLightfSGIX_names[] =
+ "iif\0" /* Parameter signature */
+ "glFragmentLightfSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_texture_compression)
+static const char GetCompressedTexImageARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetCompressedTexImage\0"
+ "glGetCompressedTexImageARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_weighting)
+static const char VertexWeightPointerEXT_names[] =
+ "iiip\0" /* Parameter signature */
+ "glVertexWeightPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetHistogram_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glGetHistogram\0"
+ "glGetHistogramEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_stencil_two_side)
+static const char ActiveStencilFaceEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glActiveStencilFaceEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_separate_stencil)
+static const char StencilFuncSeparateATI_names[] =
+ "iiii\0" /* Parameter signature */
+ "glStencilFuncSeparateATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char GetShaderSourceARB_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetShaderSource\0"
+ "glGetShaderSourceARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_igloo_interface)
+static const char IglooInterfaceSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glIglooInterfaceSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4dNV_names[] =
+ "idddd\0" /* Parameter signature */
+ "glVertexAttrib4dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_multimode_draw_arrays)
+static const char MultiModeDrawElementsIBM_names[] =
+ "ppipii\0" /* Parameter signature */
+ "glMultiModeDrawElementsIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord4sv\0"
+ "glMultiTexCoord4svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_occlusion_query)
+static const char GenQueriesARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenQueries\0"
+ "glGenQueriesARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const char ReplacementCodeuiVertex3fSUN_names[] =
+ "ifff\0" /* Parameter signature */
+ "glReplacementCodeuiVertex3fSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3iEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glTangent3iEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_mesh_array)
+static const char DrawMeshArraysSUN_names[] =
+ "iiii\0" /* Parameter signature */
+ "glDrawMeshArraysSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char IsSync_names[] =
+ "i\0" /* Parameter signature */
+ "glIsSync\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const char GetMapControlPointsNV_names[] =
+ "iiiiiip\0" /* Parameter signature */
+ "glGetMapControlPointsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_draw_buffers) || defined(need_GL_ATI_draw_buffers)
+static const char DrawBuffersARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glDrawBuffers\0"
+ "glDrawBuffersARB\0"
+ "glDrawBuffersATI\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char ProgramLocalParameter4fARB_names[] =
+ "iiffff\0" /* Parameter signature */
+ "glProgramLocalParameter4fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+static const char SpriteParameterivSGIX_names[] =
+ "ip\0" /* Parameter signature */
+ "glSpriteParameterivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_provoking_vertex)
+static const char ProvokingVertexEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glProvokingVertexEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord1fARB_names[] =
+ "if\0" /* Parameter signature */
+ "glMultiTexCoord1f\0"
+ "glMultiTexCoord1fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs4ubvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs4ubvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightsvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightsvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_shader_objects)
+static const char Uniform1fvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glUniform1fv\0"
+ "glUniform1fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const char CopyTexSubImage1D_names[] =
+ "iiiiii\0" /* Parameter signature */
+ "glCopyTexSubImage1D\0"
+ "glCopyTexSubImage1DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const char BindTexture_names[] =
+ "ii\0" /* Parameter signature */
+ "glBindTexture\0"
+ "glBindTextureEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char BeginFragmentShaderATI_names[] =
+ "\0" /* Parameter signature */
+ "glBeginFragmentShaderATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord4fARB_names[] =
+ "iffff\0" /* Parameter signature */
+ "glMultiTexCoord4f\0"
+ "glMultiTexCoord4fARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs3svNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs3svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const char ReplacementCodeuivSUN_names[] =
+ "p\0" /* Parameter signature */
+ "glReplacementCodeuivSUN\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char EnableVertexAttribArrayARB_names[] =
+ "i\0" /* Parameter signature */
+ "glEnableVertexAttribArray\0"
+ "glEnableVertexAttribArrayARB\0"
+ "";
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+static const char NormalPointervINTEL_names[] =
+ "ip\0" /* Parameter signature */
+ "glNormalPointervINTEL\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const char CopyConvolutionFilter2D_names[] =
+ "iiiiii\0" /* Parameter signature */
+ "glCopyConvolutionFilter2D\0"
+ "glCopyConvolutionFilter2DEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3ivMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos3iv\0"
+ "glWindowPos3ivARB\0"
+ "glWindowPos3ivMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_copy_buffer)
+static const char CopyBufferSubData_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glCopyBufferSubData\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char IsBufferARB_names[] =
+ "i\0" /* Parameter signature */
+ "glIsBuffer\0"
+ "glIsBufferARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4iMESA_names[] =
+ "iiii\0" /* Parameter signature */
+ "glWindowPos4iMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4uivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4uiv\0"
+ "glVertexAttrib4uivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3bvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glTangent3bvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix3x4fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix3x4fv\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3fvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glBinormal3fvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+static const char TexCoordPointervINTEL_names[] =
+ "iip\0" /* Parameter signature */
+ "glTexCoordPointervINTEL\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char DeleteBuffersARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteBuffers\0"
+ "glDeleteBuffersARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const char WindowPos4fvMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos4fvMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1sNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glVertexAttrib1sNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_secondary_color)
+static const char SecondaryColor3svEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glSecondaryColor3sv\0"
+ "glSecondaryColor3svEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3) || defined(need_GL_ARB_transpose_matrix)
+static const char LoadTransposeMatrixfARB_names[] =
+ "p\0" /* Parameter signature */
+ "glLoadTransposeMatrixf\0"
+ "glLoadTransposeMatrixfARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char GetPointerv_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetPointerv\0"
+ "glGetPointervEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3bEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glTangent3bEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerParameterfNV_names[] =
+ "if\0" /* Parameter signature */
+ "glCombinerParameterfNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char BindProgramNV_names[] =
+ "ii\0" /* Parameter signature */
+ "glBindProgramARB\0"
+ "glBindProgramNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4sv\0"
+ "glVertexAttrib4svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+static const char CreateDebugObjectMESA_names[] =
+ "\0" /* Parameter signature */
+ "glCreateDebugObjectMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const char GetShaderiv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetShaderiv\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const char ClientWaitSync_names[] =
+ "iii\0" /* Parameter signature */
+ "glClientWaitSync\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char BindFragmentShaderATI_names[] =
+ "i\0" /* Parameter signature */
+ "glBindFragmentShaderATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char UnmapBufferARB_names[] =
+ "i\0" /* Parameter signature */
+ "glUnmapBuffer\0"
+ "glUnmapBufferARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char Minmax_names[] =
+ "iii\0" /* Parameter signature */
+ "glMinmax\0"
+ "glMinmaxEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_EXT_fog_coord)
+static const char FogCoorddvEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glFogCoorddv\0"
+ "glFogCoorddvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SUNX_constant_data)
+static const char FinishTextureSUNX_names[] =
+ "\0" /* Parameter signature */
+ "glFinishTextureSUNX\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char GetFragmentLightfvSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFragmentLightfvSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetFinalCombinerInputParameterfvNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetFinalCombinerInputParameterfvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char ColorFragmentOp3ATI_names[] =
+ "iiiiiiiiiiiii\0" /* Parameter signature */
+ "glColorFragmentOp3ATI\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2svARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib2sv\0"
+ "glVertexAttrib2svARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char AreProgramsResidentNV_names[] =
+ "ipp\0" /* Parameter signature */
+ "glAreProgramsResidentNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos3svMESA_names[] =
+ "p\0" /* Parameter signature */
+ "glWindowPos3sv\0"
+ "glWindowPos3svARB\0"
+ "glWindowPos3svMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_color_subtable)
+static const char CopyColorSubTable_names[] =
+ "iiiii\0" /* Parameter signature */
+ "glCopyColorSubTable\0"
+ "glCopyColorSubTableEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightdvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightdvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char DeleteRenderbuffersEXT_names[] =
+ "ip\0" /* Parameter signature */
+ "glDeleteRenderbuffers\0"
+ "glDeleteRenderbuffersEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib4NubvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4Nubv\0"
+ "glVertexAttrib4NubvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib3dvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib3dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char GetObjectParameterfvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetObjectParameterfvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const char GetProgramEnvParameterdvARB_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetProgramEnvParameterdvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_compiled_vertex_array)
+static const char LockArraysEXT_names[] =
+ "ii\0" /* Parameter signature */
+ "glLockArraysEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+static const char PixelTransformParameterivEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glPixelTransformParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char BinormalPointerEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glBinormalPointerEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib1dNV_names[] =
+ "id\0" /* Parameter signature */
+ "glVertexAttrib1dNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char GetCombinerInputParameterivNV_names[] =
+ "iiiip\0" /* Parameter signature */
+ "glGetCombinerInputParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const char MultiTexCoord2fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glMultiTexCoord2fv\0"
+ "glMultiTexCoord2fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char GetRenderbufferParameterivEXT_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetRenderbufferParameteriv\0"
+ "glGetRenderbufferParameterivEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const char CombinerParameterivNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glCombinerParameterivNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char GenFragmentShadersATI_names[] =
+ "i\0" /* Parameter signature */
+ "glGenFragmentShadersATI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const char DrawArrays_names[] =
+ "iii\0" /* Parameter signature */
+ "glDrawArrays\0"
+ "glDrawArraysEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const char WeightuivARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glWeightuivARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib2sARB_names[] =
+ "iii\0" /* Parameter signature */
+ "glVertexAttrib2s\0"
+ "glVertexAttrib2sARB\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const char GenAsyncMarkersSGIX_names[] =
+ "i\0" /* Parameter signature */
+ "glGenAsyncMarkersSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Tangent3svEXT_names[] =
+ "p\0" /* Parameter signature */
+ "glTangent3svEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const char GetListParameterivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetListParameterivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char BindBufferARB_names[] =
+ "ii\0" /* Parameter signature */
+ "glBindBuffer\0"
+ "glBindBufferARB\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const char GetInfoLogARB_names[] =
+ "iipp\0" /* Parameter signature */
+ "glGetInfoLogARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs4svNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs4svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const char EdgeFlagPointerListIBM_names[] =
+ "ipi\0" /* Parameter signature */
+ "glEdgeFlagPointerListIBM\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const char UniformMatrix3x2fv_names[] =
+ "iiip\0" /* Parameter signature */
+ "glUniformMatrix3x2fv\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const char GetMinmaxParameterfv_names[] =
+ "iip\0" /* Parameter signature */
+ "glGetMinmaxParameterfv\0"
+ "glGetMinmaxParameterfvEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_2_0) || defined(need_GL_ARB_vertex_program)
+static const char VertexAttrib1fvARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib1fv\0"
+ "glVertexAttrib1fvARB\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_5) || defined(need_GL_ARB_vertex_buffer_object)
+static const char GenBuffersARB_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenBuffers\0"
+ "glGenBuffersARB\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttribs1svNV_names[] =
+ "iip\0" /* Parameter signature */
+ "glVertexAttribs1svNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const char GetTexBumpParameterivATI_names[] =
+ "ip\0" /* Parameter signature */
+ "glGetTexBumpParameterivATI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3bEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glBinormal3bEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const char FragmentMaterialivSGIX_names[] =
+ "iip\0" /* Parameter signature */
+ "glFragmentMaterialivSGIX\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object) || defined(need_GL_EXT_framebuffer_object)
+static const char IsRenderbufferEXT_names[] =
+ "i\0" /* Parameter signature */
+ "glIsRenderbuffer\0"
+ "glIsRenderbufferEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_ARB_vertex_program) || defined(need_GL_NV_vertex_program)
+static const char GenProgramsNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glGenProgramsARB\0"
+ "glGenProgramsNV\0"
+ "";
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const char VertexAttrib4dvNV_names[] =
+ "ip\0" /* Parameter signature */
+ "glVertexAttrib4dvNV\0"
+ "";
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const char EndFragmentShaderATI_names[] =
+ "\0" /* Parameter signature */
+ "glEndFragmentShaderATI\0"
+ "";
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const char Binormal3iEXT_names[] =
+ "iii\0" /* Parameter signature */
+ "glBinormal3iEXT\0"
+ "";
+#endif
+
+#if defined(need_GL_VERSION_1_4) || defined(need_GL_ARB_window_pos) || defined(need_GL_MESA_window_pos)
+static const char WindowPos2fMESA_names[] =
+ "ff\0" /* Parameter signature */
+ "glWindowPos2f\0"
+ "glWindowPos2fARB\0"
+ "glWindowPos2fMESA\0"
+ "";
+#endif
+
+#if defined(need_GL_3DFX_tbuffer)
+static const struct dri_extension_function GL_3DFX_tbuffer_functions[] = {
+ { TbufferMask3DFX_names, TbufferMask3DFX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_APPLE_flush_buffer_range)
+static const struct dri_extension_function GL_APPLE_flush_buffer_range_functions[] = {
+ { BufferParameteriAPPLE_names, BufferParameteriAPPLE_remap_index, -1 },
+ { FlushMappedBufferRangeAPPLE_names, FlushMappedBufferRangeAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_APPLE_texture_range)
+static const struct dri_extension_function GL_APPLE_texture_range_functions[] = {
+ { TextureRangeAPPLE_names, TextureRangeAPPLE_remap_index, -1 },
+ { GetTexParameterPointervAPPLE_names, GetTexParameterPointervAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_APPLE_vertex_array_object)
+static const struct dri_extension_function GL_APPLE_vertex_array_object_functions[] = {
+ { DeleteVertexArraysAPPLE_names, DeleteVertexArraysAPPLE_remap_index, -1 },
+ { GenVertexArraysAPPLE_names, GenVertexArraysAPPLE_remap_index, -1 },
+ { IsVertexArrayAPPLE_names, IsVertexArrayAPPLE_remap_index, -1 },
+ { BindVertexArrayAPPLE_names, BindVertexArrayAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_copy_buffer)
+static const struct dri_extension_function GL_ARB_copy_buffer_functions[] = {
+ { CopyBufferSubData_names, CopyBufferSubData_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_draw_buffers)
+static const struct dri_extension_function GL_ARB_draw_buffers_functions[] = {
+ { DrawBuffersARB_names, DrawBuffersARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_framebuffer_object)
+static const struct dri_extension_function GL_ARB_framebuffer_object_functions[] = {
+ { BlitFramebufferEXT_names, BlitFramebufferEXT_remap_index, -1 },
+ { FramebufferTextureLayerEXT_names, FramebufferTextureLayerEXT_remap_index, -1 },
+ { GenerateMipmapEXT_names, GenerateMipmapEXT_remap_index, -1 },
+ { RenderbufferStorageEXT_names, RenderbufferStorageEXT_remap_index, -1 },
+ { CheckFramebufferStatusEXT_names, CheckFramebufferStatusEXT_remap_index, -1 },
+ { FramebufferTexture3DEXT_names, FramebufferTexture3DEXT_remap_index, -1 },
+ { FramebufferTexture2DEXT_names, FramebufferTexture2DEXT_remap_index, -1 },
+ { RenderbufferStorageMultisample_names, RenderbufferStorageMultisample_remap_index, -1 },
+ { FramebufferRenderbufferEXT_names, FramebufferRenderbufferEXT_remap_index, -1 },
+ { FramebufferTexture1DEXT_names, FramebufferTexture1DEXT_remap_index, -1 },
+ { BindFramebufferEXT_names, BindFramebufferEXT_remap_index, -1 },
+ { GenRenderbuffersEXT_names, GenRenderbuffersEXT_remap_index, -1 },
+ { IsFramebufferEXT_names, IsFramebufferEXT_remap_index, -1 },
+ { GetFramebufferAttachmentParameterivEXT_names, GetFramebufferAttachmentParameterivEXT_remap_index, -1 },
+ { DeleteFramebuffersEXT_names, DeleteFramebuffersEXT_remap_index, -1 },
+ { GenFramebuffersEXT_names, GenFramebuffersEXT_remap_index, -1 },
+ { BindRenderbufferEXT_names, BindRenderbufferEXT_remap_index, -1 },
+ { DeleteRenderbuffersEXT_names, DeleteRenderbuffersEXT_remap_index, -1 },
+ { GetRenderbufferParameterivEXT_names, GetRenderbufferParameterivEXT_remap_index, -1 },
+ { IsRenderbufferEXT_names, IsRenderbufferEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_map_buffer_range)
+static const struct dri_extension_function GL_ARB_map_buffer_range_functions[] = {
+ { FlushMappedBufferRange_names, FlushMappedBufferRange_remap_index, -1 },
+ { MapBufferRange_names, MapBufferRange_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_matrix_palette)
+static const struct dri_extension_function GL_ARB_matrix_palette_functions[] = {
+ { MatrixIndexusvARB_names, MatrixIndexusvARB_remap_index, -1 },
+ { MatrixIndexuivARB_names, MatrixIndexuivARB_remap_index, -1 },
+ { MatrixIndexPointerARB_names, MatrixIndexPointerARB_remap_index, -1 },
+ { CurrentPaletteMatrixARB_names, CurrentPaletteMatrixARB_remap_index, -1 },
+ { MatrixIndexubvARB_names, MatrixIndexubvARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_multisample)
+static const struct dri_extension_function GL_ARB_multisample_functions[] = {
+ { SampleCoverageARB_names, SampleCoverageARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_occlusion_query)
+static const struct dri_extension_function GL_ARB_occlusion_query_functions[] = {
+ { BeginQueryARB_names, BeginQueryARB_remap_index, -1 },
+ { GetQueryivARB_names, GetQueryivARB_remap_index, -1 },
+ { GetQueryObjectivARB_names, GetQueryObjectivARB_remap_index, -1 },
+ { EndQueryARB_names, EndQueryARB_remap_index, -1 },
+ { GetQueryObjectuivARB_names, GetQueryObjectuivARB_remap_index, -1 },
+ { DeleteQueriesARB_names, DeleteQueriesARB_remap_index, -1 },
+ { IsQueryARB_names, IsQueryARB_remap_index, -1 },
+ { GenQueriesARB_names, GenQueriesARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_point_parameters)
+static const struct dri_extension_function GL_ARB_point_parameters_functions[] = {
+ { PointParameterfEXT_names, PointParameterfEXT_remap_index, -1 },
+ { PointParameterfvEXT_names, PointParameterfvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_shader_objects)
+static const struct dri_extension_function GL_ARB_shader_objects_functions[] = {
+ { UniformMatrix3fvARB_names, UniformMatrix3fvARB_remap_index, -1 },
+ { Uniform2fARB_names, Uniform2fARB_remap_index, -1 },
+ { Uniform2ivARB_names, Uniform2ivARB_remap_index, -1 },
+ { UniformMatrix4fvARB_names, UniformMatrix4fvARB_remap_index, -1 },
+ { CreateProgramObjectARB_names, CreateProgramObjectARB_remap_index, -1 },
+ { Uniform3iARB_names, Uniform3iARB_remap_index, -1 },
+ { CreateShaderObjectARB_names, CreateShaderObjectARB_remap_index, -1 },
+ { Uniform1fARB_names, Uniform1fARB_remap_index, -1 },
+ { AttachObjectARB_names, AttachObjectARB_remap_index, -1 },
+ { UniformMatrix2fvARB_names, UniformMatrix2fvARB_remap_index, -1 },
+ { GetAttachedObjectsARB_names, GetAttachedObjectsARB_remap_index, -1 },
+ { Uniform3fvARB_names, Uniform3fvARB_remap_index, -1 },
+ { GetHandleARB_names, GetHandleARB_remap_index, -1 },
+ { GetActiveUniformARB_names, GetActiveUniformARB_remap_index, -1 },
+ { GetUniformivARB_names, GetUniformivARB_remap_index, -1 },
+ { Uniform2fvARB_names, Uniform2fvARB_remap_index, -1 },
+ { DeleteObjectARB_names, DeleteObjectARB_remap_index, -1 },
+ { ValidateProgramARB_names, ValidateProgramARB_remap_index, -1 },
+ { Uniform3ivARB_names, Uniform3ivARB_remap_index, -1 },
+ { CompileShaderARB_names, CompileShaderARB_remap_index, -1 },
+ { Uniform3fARB_names, Uniform3fARB_remap_index, -1 },
+ { Uniform4fARB_names, Uniform4fARB_remap_index, -1 },
+ { LinkProgramARB_names, LinkProgramARB_remap_index, -1 },
+ { ShaderSourceARB_names, ShaderSourceARB_remap_index, -1 },
+ { Uniform4ivARB_names, Uniform4ivARB_remap_index, -1 },
+ { Uniform1ivARB_names, Uniform1ivARB_remap_index, -1 },
+ { Uniform1iARB_names, Uniform1iARB_remap_index, -1 },
+ { Uniform4fvARB_names, Uniform4fvARB_remap_index, -1 },
+ { GetUniformfvARB_names, GetUniformfvARB_remap_index, -1 },
+ { DetachObjectARB_names, DetachObjectARB_remap_index, -1 },
+ { Uniform4iARB_names, Uniform4iARB_remap_index, -1 },
+ { UseProgramObjectARB_names, UseProgramObjectARB_remap_index, -1 },
+ { Uniform2iARB_names, Uniform2iARB_remap_index, -1 },
+ { GetObjectParameterivARB_names, GetObjectParameterivARB_remap_index, -1 },
+ { GetUniformLocationARB_names, GetUniformLocationARB_remap_index, -1 },
+ { GetShaderSourceARB_names, GetShaderSourceARB_remap_index, -1 },
+ { Uniform1fvARB_names, Uniform1fvARB_remap_index, -1 },
+ { GetObjectParameterfvARB_names, GetObjectParameterfvARB_remap_index, -1 },
+ { GetInfoLogARB_names, GetInfoLogARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_sync)
+static const struct dri_extension_function GL_ARB_sync_functions[] = {
+ { DeleteSync_names, DeleteSync_remap_index, -1 },
+ { FenceSync_names, FenceSync_remap_index, -1 },
+ { WaitSync_names, WaitSync_remap_index, -1 },
+ { GetInteger64v_names, GetInteger64v_remap_index, -1 },
+ { GetSynciv_names, GetSynciv_remap_index, -1 },
+ { IsSync_names, IsSync_remap_index, -1 },
+ { ClientWaitSync_names, ClientWaitSync_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_texture_compression)
+static const struct dri_extension_function GL_ARB_texture_compression_functions[] = {
+ { CompressedTexSubImage2DARB_names, CompressedTexSubImage2DARB_remap_index, -1 },
+ { CompressedTexImage3DARB_names, CompressedTexImage3DARB_remap_index, -1 },
+ { CompressedTexImage1DARB_names, CompressedTexImage1DARB_remap_index, -1 },
+ { CompressedTexSubImage1DARB_names, CompressedTexSubImage1DARB_remap_index, -1 },
+ { CompressedTexSubImage3DARB_names, CompressedTexSubImage3DARB_remap_index, -1 },
+ { CompressedTexImage2DARB_names, CompressedTexImage2DARB_remap_index, -1 },
+ { GetCompressedTexImageARB_names, GetCompressedTexImageARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_transpose_matrix)
+static const struct dri_extension_function GL_ARB_transpose_matrix_functions[] = {
+ { MultTransposeMatrixdARB_names, MultTransposeMatrixdARB_remap_index, -1 },
+ { LoadTransposeMatrixdARB_names, LoadTransposeMatrixdARB_remap_index, -1 },
+ { MultTransposeMatrixfARB_names, MultTransposeMatrixfARB_remap_index, -1 },
+ { LoadTransposeMatrixfARB_names, LoadTransposeMatrixfARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_vertex_array_object)
+static const struct dri_extension_function GL_ARB_vertex_array_object_functions[] = {
+ { DeleteVertexArraysAPPLE_names, DeleteVertexArraysAPPLE_remap_index, -1 },
+ { GenVertexArrays_names, GenVertexArrays_remap_index, -1 },
+ { BindVertexArray_names, BindVertexArray_remap_index, -1 },
+ { IsVertexArrayAPPLE_names, IsVertexArrayAPPLE_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_vertex_blend)
+static const struct dri_extension_function GL_ARB_vertex_blend_functions[] = {
+ { WeightubvARB_names, WeightubvARB_remap_index, -1 },
+ { WeightivARB_names, WeightivARB_remap_index, -1 },
+ { WeightPointerARB_names, WeightPointerARB_remap_index, -1 },
+ { WeightfvARB_names, WeightfvARB_remap_index, -1 },
+ { WeightbvARB_names, WeightbvARB_remap_index, -1 },
+ { WeightusvARB_names, WeightusvARB_remap_index, -1 },
+ { VertexBlendARB_names, VertexBlendARB_remap_index, -1 },
+ { WeightsvARB_names, WeightsvARB_remap_index, -1 },
+ { WeightdvARB_names, WeightdvARB_remap_index, -1 },
+ { WeightuivARB_names, WeightuivARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_vertex_buffer_object)
+static const struct dri_extension_function GL_ARB_vertex_buffer_object_functions[] = {
+ { GetBufferSubDataARB_names, GetBufferSubDataARB_remap_index, -1 },
+ { BufferSubDataARB_names, BufferSubDataARB_remap_index, -1 },
+ { BufferDataARB_names, BufferDataARB_remap_index, -1 },
+ { GetBufferPointervARB_names, GetBufferPointervARB_remap_index, -1 },
+ { GetBufferParameterivARB_names, GetBufferParameterivARB_remap_index, -1 },
+ { MapBufferARB_names, MapBufferARB_remap_index, -1 },
+ { IsBufferARB_names, IsBufferARB_remap_index, -1 },
+ { DeleteBuffersARB_names, DeleteBuffersARB_remap_index, -1 },
+ { UnmapBufferARB_names, UnmapBufferARB_remap_index, -1 },
+ { BindBufferARB_names, BindBufferARB_remap_index, -1 },
+ { GenBuffersARB_names, GenBuffersARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_vertex_program)
+static const struct dri_extension_function GL_ARB_vertex_program_functions[] = {
+ { VertexAttrib2fARB_names, VertexAttrib2fARB_remap_index, -1 },
+ { VertexAttrib3fARB_names, VertexAttrib3fARB_remap_index, -1 },
+ { VertexAttrib1svARB_names, VertexAttrib1svARB_remap_index, -1 },
+ { VertexAttrib4NusvARB_names, VertexAttrib4NusvARB_remap_index, -1 },
+ { DisableVertexAttribArrayARB_names, DisableVertexAttribArrayARB_remap_index, -1 },
+ { ProgramLocalParameter4dARB_names, ProgramLocalParameter4dARB_remap_index, -1 },
+ { VertexAttrib1fARB_names, VertexAttrib1fARB_remap_index, -1 },
+ { VertexAttrib4NbvARB_names, VertexAttrib4NbvARB_remap_index, -1 },
+ { VertexAttrib1sARB_names, VertexAttrib1sARB_remap_index, -1 },
+ { GetProgramLocalParameterfvARB_names, GetProgramLocalParameterfvARB_remap_index, -1 },
+ { VertexAttrib3dvARB_names, VertexAttrib3dvARB_remap_index, -1 },
+ { ProgramEnvParameter4fvARB_names, ProgramEnvParameter4fvARB_remap_index, -1 },
+ { GetVertexAttribivARB_names, GetVertexAttribivARB_remap_index, -1 },
+ { VertexAttrib4ivARB_names, VertexAttrib4ivARB_remap_index, -1 },
+ { VertexAttrib4bvARB_names, VertexAttrib4bvARB_remap_index, -1 },
+ { VertexAttrib3dARB_names, VertexAttrib3dARB_remap_index, -1 },
+ { VertexAttrib4fARB_names, VertexAttrib4fARB_remap_index, -1 },
+ { VertexAttrib4fvARB_names, VertexAttrib4fvARB_remap_index, -1 },
+ { ProgramLocalParameter4dvARB_names, ProgramLocalParameter4dvARB_remap_index, -1 },
+ { VertexAttrib2dARB_names, VertexAttrib2dARB_remap_index, -1 },
+ { VertexAttrib1dvARB_names, VertexAttrib1dvARB_remap_index, -1 },
+ { GetVertexAttribfvARB_names, GetVertexAttribfvARB_remap_index, -1 },
+ { VertexAttrib4ubvARB_names, VertexAttrib4ubvARB_remap_index, -1 },
+ { ProgramEnvParameter4fARB_names, ProgramEnvParameter4fARB_remap_index, -1 },
+ { VertexAttrib4sARB_names, VertexAttrib4sARB_remap_index, -1 },
+ { VertexAttrib2dvARB_names, VertexAttrib2dvARB_remap_index, -1 },
+ { VertexAttrib2fvARB_names, VertexAttrib2fvARB_remap_index, -1 },
+ { VertexAttrib4NivARB_names, VertexAttrib4NivARB_remap_index, -1 },
+ { GetProgramStringARB_names, GetProgramStringARB_remap_index, -1 },
+ { VertexAttrib4NuivARB_names, VertexAttrib4NuivARB_remap_index, -1 },
+ { IsProgramNV_names, IsProgramNV_remap_index, -1 },
+ { ProgramEnvParameter4dARB_names, ProgramEnvParameter4dARB_remap_index, -1 },
+ { VertexAttrib1dARB_names, VertexAttrib1dARB_remap_index, -1 },
+ { VertexAttrib4usvARB_names, VertexAttrib4usvARB_remap_index, -1 },
+ { VertexAttrib3svARB_names, VertexAttrib3svARB_remap_index, -1 },
+ { GetVertexAttribdvARB_names, GetVertexAttribdvARB_remap_index, -1 },
+ { VertexAttrib4dvARB_names, VertexAttrib4dvARB_remap_index, -1 },
+ { VertexAttribPointerARB_names, VertexAttribPointerARB_remap_index, -1 },
+ { VertexAttrib4NsvARB_names, VertexAttrib4NsvARB_remap_index, -1 },
+ { VertexAttrib3fvARB_names, VertexAttrib3fvARB_remap_index, -1 },
+ { VertexAttrib4NubARB_names, VertexAttrib4NubARB_remap_index, -1 },
+ { GetProgramEnvParameterfvARB_names, GetProgramEnvParameterfvARB_remap_index, -1 },
+ { ProgramEnvParameter4dvARB_names, ProgramEnvParameter4dvARB_remap_index, -1 },
+ { ProgramLocalParameter4fvARB_names, ProgramLocalParameter4fvARB_remap_index, -1 },
+ { DeleteProgramsNV_names, DeleteProgramsNV_remap_index, -1 },
+ { GetVertexAttribPointervNV_names, GetVertexAttribPointervNV_remap_index, -1 },
+ { VertexAttrib4dARB_names, VertexAttrib4dARB_remap_index, -1 },
+ { GetProgramLocalParameterdvARB_names, GetProgramLocalParameterdvARB_remap_index, -1 },
+ { GetProgramivARB_names, GetProgramivARB_remap_index, -1 },
+ { VertexAttrib3sARB_names, VertexAttrib3sARB_remap_index, -1 },
+ { ProgramStringARB_names, ProgramStringARB_remap_index, -1 },
+ { ProgramLocalParameter4fARB_names, ProgramLocalParameter4fARB_remap_index, -1 },
+ { EnableVertexAttribArrayARB_names, EnableVertexAttribArrayARB_remap_index, -1 },
+ { VertexAttrib4uivARB_names, VertexAttrib4uivARB_remap_index, -1 },
+ { BindProgramNV_names, BindProgramNV_remap_index, -1 },
+ { VertexAttrib4svARB_names, VertexAttrib4svARB_remap_index, -1 },
+ { VertexAttrib2svARB_names, VertexAttrib2svARB_remap_index, -1 },
+ { VertexAttrib4NubvARB_names, VertexAttrib4NubvARB_remap_index, -1 },
+ { GetProgramEnvParameterdvARB_names, GetProgramEnvParameterdvARB_remap_index, -1 },
+ { VertexAttrib2sARB_names, VertexAttrib2sARB_remap_index, -1 },
+ { VertexAttrib1fvARB_names, VertexAttrib1fvARB_remap_index, -1 },
+ { GenProgramsNV_names, GenProgramsNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_vertex_shader)
+static const struct dri_extension_function GL_ARB_vertex_shader_functions[] = {
+ { GetActiveAttribARB_names, GetActiveAttribARB_remap_index, -1 },
+ { GetAttribLocationARB_names, GetAttribLocationARB_remap_index, -1 },
+ { BindAttribLocationARB_names, BindAttribLocationARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ARB_window_pos)
+static const struct dri_extension_function GL_ARB_window_pos_functions[] = {
+ { WindowPos3fMESA_names, WindowPos3fMESA_remap_index, -1 },
+ { WindowPos2dvMESA_names, WindowPos2dvMESA_remap_index, -1 },
+ { WindowPos2svMESA_names, WindowPos2svMESA_remap_index, -1 },
+ { WindowPos3dMESA_names, WindowPos3dMESA_remap_index, -1 },
+ { WindowPos2fvMESA_names, WindowPos2fvMESA_remap_index, -1 },
+ { WindowPos2dMESA_names, WindowPos2dMESA_remap_index, -1 },
+ { WindowPos3dvMESA_names, WindowPos3dvMESA_remap_index, -1 },
+ { WindowPos3fvMESA_names, WindowPos3fvMESA_remap_index, -1 },
+ { WindowPos2iMESA_names, WindowPos2iMESA_remap_index, -1 },
+ { WindowPos3sMESA_names, WindowPos3sMESA_remap_index, -1 },
+ { WindowPos2ivMESA_names, WindowPos2ivMESA_remap_index, -1 },
+ { WindowPos2sMESA_names, WindowPos2sMESA_remap_index, -1 },
+ { WindowPos3iMESA_names, WindowPos3iMESA_remap_index, -1 },
+ { WindowPos3ivMESA_names, WindowPos3ivMESA_remap_index, -1 },
+ { WindowPos3svMESA_names, WindowPos3svMESA_remap_index, -1 },
+ { WindowPos2fMESA_names, WindowPos2fMESA_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ATI_blend_equation_separate)
+static const struct dri_extension_function GL_ATI_blend_equation_separate_functions[] = {
+ { BlendEquationSeparateEXT_names, BlendEquationSeparateEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ATI_draw_buffers)
+static const struct dri_extension_function GL_ATI_draw_buffers_functions[] = {
+ { DrawBuffersARB_names, DrawBuffersARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ATI_envmap_bumpmap)
+static const struct dri_extension_function GL_ATI_envmap_bumpmap_functions[] = {
+ { TexBumpParameterfvATI_names, TexBumpParameterfvATI_remap_index, -1 },
+ { TexBumpParameterivATI_names, TexBumpParameterivATI_remap_index, -1 },
+ { GetTexBumpParameterfvATI_names, GetTexBumpParameterfvATI_remap_index, -1 },
+ { GetTexBumpParameterivATI_names, GetTexBumpParameterivATI_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ATI_fragment_shader)
+static const struct dri_extension_function GL_ATI_fragment_shader_functions[] = {
+ { ColorFragmentOp2ATI_names, ColorFragmentOp2ATI_remap_index, -1 },
+ { DeleteFragmentShaderATI_names, DeleteFragmentShaderATI_remap_index, -1 },
+ { SetFragmentShaderConstantATI_names, SetFragmentShaderConstantATI_remap_index, -1 },
+ { SampleMapATI_names, SampleMapATI_remap_index, -1 },
+ { AlphaFragmentOp2ATI_names, AlphaFragmentOp2ATI_remap_index, -1 },
+ { AlphaFragmentOp1ATI_names, AlphaFragmentOp1ATI_remap_index, -1 },
+ { ColorFragmentOp1ATI_names, ColorFragmentOp1ATI_remap_index, -1 },
+ { AlphaFragmentOp3ATI_names, AlphaFragmentOp3ATI_remap_index, -1 },
+ { PassTexCoordATI_names, PassTexCoordATI_remap_index, -1 },
+ { BeginFragmentShaderATI_names, BeginFragmentShaderATI_remap_index, -1 },
+ { BindFragmentShaderATI_names, BindFragmentShaderATI_remap_index, -1 },
+ { ColorFragmentOp3ATI_names, ColorFragmentOp3ATI_remap_index, -1 },
+ { GenFragmentShadersATI_names, GenFragmentShadersATI_remap_index, -1 },
+ { EndFragmentShaderATI_names, EndFragmentShaderATI_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_ATI_separate_stencil)
+static const struct dri_extension_function GL_ATI_separate_stencil_functions[] = {
+ { StencilOpSeparate_names, StencilOpSeparate_remap_index, -1 },
+ { StencilFuncSeparateATI_names, StencilFuncSeparateATI_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_blend_color)
+static const struct dri_extension_function GL_EXT_blend_color_functions[] = {
+ { BlendColor_names, -1, 336 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_blend_equation_separate)
+static const struct dri_extension_function GL_EXT_blend_equation_separate_functions[] = {
+ { BlendEquationSeparateEXT_names, BlendEquationSeparateEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_blend_func_separate)
+static const struct dri_extension_function GL_EXT_blend_func_separate_functions[] = {
+ { BlendFuncSeparateEXT_names, BlendFuncSeparateEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_blend_minmax)
+static const struct dri_extension_function GL_EXT_blend_minmax_functions[] = {
+ { BlendEquation_names, -1, 337 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_color_subtable)
+static const struct dri_extension_function GL_EXT_color_subtable_functions[] = {
+ { ColorSubTable_names, -1, 346 },
+ { CopyColorSubTable_names, -1, 347 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_compiled_vertex_array)
+static const struct dri_extension_function GL_EXT_compiled_vertex_array_functions[] = {
+ { UnlockArraysEXT_names, UnlockArraysEXT_remap_index, -1 },
+ { LockArraysEXT_names, LockArraysEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_convolution)
+static const struct dri_extension_function GL_EXT_convolution_functions[] = {
+ { ConvolutionFilter1D_names, -1, 348 },
+ { CopyConvolutionFilter1D_names, -1, 354 },
+ { GetConvolutionParameteriv_names, -1, 358 },
+ { ConvolutionFilter2D_names, -1, 349 },
+ { ConvolutionParameteriv_names, -1, 353 },
+ { ConvolutionParameterfv_names, -1, 351 },
+ { GetSeparableFilter_names, -1, 359 },
+ { SeparableFilter2D_names, -1, 360 },
+ { ConvolutionParameteri_names, -1, 352 },
+ { ConvolutionParameterf_names, -1, 350 },
+ { GetConvolutionParameterfv_names, -1, 357 },
+ { GetConvolutionFilter_names, -1, 356 },
+ { CopyConvolutionFilter2D_names, -1, 355 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_coordinate_frame)
+static const struct dri_extension_function GL_EXT_coordinate_frame_functions[] = {
+ { TangentPointerEXT_names, TangentPointerEXT_remap_index, -1 },
+ { Binormal3ivEXT_names, Binormal3ivEXT_remap_index, -1 },
+ { Tangent3sEXT_names, Tangent3sEXT_remap_index, -1 },
+ { Tangent3fvEXT_names, Tangent3fvEXT_remap_index, -1 },
+ { Tangent3dvEXT_names, Tangent3dvEXT_remap_index, -1 },
+ { Binormal3bvEXT_names, Binormal3bvEXT_remap_index, -1 },
+ { Binormal3dEXT_names, Binormal3dEXT_remap_index, -1 },
+ { Tangent3fEXT_names, Tangent3fEXT_remap_index, -1 },
+ { Binormal3sEXT_names, Binormal3sEXT_remap_index, -1 },
+ { Tangent3ivEXT_names, Tangent3ivEXT_remap_index, -1 },
+ { Tangent3dEXT_names, Tangent3dEXT_remap_index, -1 },
+ { Binormal3svEXT_names, Binormal3svEXT_remap_index, -1 },
+ { Binormal3fEXT_names, Binormal3fEXT_remap_index, -1 },
+ { Binormal3dvEXT_names, Binormal3dvEXT_remap_index, -1 },
+ { Tangent3iEXT_names, Tangent3iEXT_remap_index, -1 },
+ { Tangent3bvEXT_names, Tangent3bvEXT_remap_index, -1 },
+ { Binormal3fvEXT_names, Binormal3fvEXT_remap_index, -1 },
+ { Tangent3bEXT_names, Tangent3bEXT_remap_index, -1 },
+ { BinormalPointerEXT_names, BinormalPointerEXT_remap_index, -1 },
+ { Tangent3svEXT_names, Tangent3svEXT_remap_index, -1 },
+ { Binormal3bEXT_names, Binormal3bEXT_remap_index, -1 },
+ { Binormal3iEXT_names, Binormal3iEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_copy_texture)
+static const struct dri_extension_function GL_EXT_copy_texture_functions[] = {
+ { CopyTexSubImage3D_names, -1, 373 },
+ { CopyTexImage2D_names, -1, 324 },
+ { CopyTexImage1D_names, -1, 323 },
+ { CopyTexSubImage2D_names, -1, 326 },
+ { CopyTexSubImage1D_names, -1, 325 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_cull_vertex)
+static const struct dri_extension_function GL_EXT_cull_vertex_functions[] = {
+ { CullParameterdvEXT_names, CullParameterdvEXT_remap_index, -1 },
+ { CullParameterfvEXT_names, CullParameterfvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_depth_bounds_test)
+static const struct dri_extension_function GL_EXT_depth_bounds_test_functions[] = {
+ { DepthBoundsEXT_names, DepthBoundsEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_draw_range_elements)
+static const struct dri_extension_function GL_EXT_draw_range_elements_functions[] = {
+ { DrawRangeElements_names, -1, 338 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_fog_coord)
+static const struct dri_extension_function GL_EXT_fog_coord_functions[] = {
+ { FogCoorddEXT_names, FogCoorddEXT_remap_index, -1 },
+ { FogCoordfEXT_names, FogCoordfEXT_remap_index, -1 },
+ { FogCoordPointerEXT_names, FogCoordPointerEXT_remap_index, -1 },
+ { FogCoordfvEXT_names, FogCoordfvEXT_remap_index, -1 },
+ { FogCoorddvEXT_names, FogCoorddvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_framebuffer_blit)
+static const struct dri_extension_function GL_EXT_framebuffer_blit_functions[] = {
+ { BlitFramebufferEXT_names, BlitFramebufferEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_framebuffer_object)
+static const struct dri_extension_function GL_EXT_framebuffer_object_functions[] = {
+ { GenerateMipmapEXT_names, GenerateMipmapEXT_remap_index, -1 },
+ { RenderbufferStorageEXT_names, RenderbufferStorageEXT_remap_index, -1 },
+ { CheckFramebufferStatusEXT_names, CheckFramebufferStatusEXT_remap_index, -1 },
+ { FramebufferTexture3DEXT_names, FramebufferTexture3DEXT_remap_index, -1 },
+ { FramebufferTexture2DEXT_names, FramebufferTexture2DEXT_remap_index, -1 },
+ { FramebufferRenderbufferEXT_names, FramebufferRenderbufferEXT_remap_index, -1 },
+ { FramebufferTexture1DEXT_names, FramebufferTexture1DEXT_remap_index, -1 },
+ { BindFramebufferEXT_names, BindFramebufferEXT_remap_index, -1 },
+ { GenRenderbuffersEXT_names, GenRenderbuffersEXT_remap_index, -1 },
+ { IsFramebufferEXT_names, IsFramebufferEXT_remap_index, -1 },
+ { GetFramebufferAttachmentParameterivEXT_names, GetFramebufferAttachmentParameterivEXT_remap_index, -1 },
+ { DeleteFramebuffersEXT_names, DeleteFramebuffersEXT_remap_index, -1 },
+ { GenFramebuffersEXT_names, GenFramebuffersEXT_remap_index, -1 },
+ { BindRenderbufferEXT_names, BindRenderbufferEXT_remap_index, -1 },
+ { DeleteRenderbuffersEXT_names, DeleteRenderbuffersEXT_remap_index, -1 },
+ { GetRenderbufferParameterivEXT_names, GetRenderbufferParameterivEXT_remap_index, -1 },
+ { IsRenderbufferEXT_names, IsRenderbufferEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_gpu_program_parameters)
+static const struct dri_extension_function GL_EXT_gpu_program_parameters_functions[] = {
+ { ProgramLocalParameters4fvEXT_names, ProgramLocalParameters4fvEXT_remap_index, -1 },
+ { ProgramEnvParameters4fvEXT_names, ProgramEnvParameters4fvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_histogram)
+static const struct dri_extension_function GL_EXT_histogram_functions[] = {
+ { Histogram_names, -1, 367 },
+ { ResetHistogram_names, -1, 369 },
+ { GetMinmax_names, -1, 364 },
+ { GetHistogramParameterfv_names, -1, 362 },
+ { GetMinmaxParameteriv_names, -1, 366 },
+ { ResetMinmax_names, -1, 370 },
+ { GetHistogramParameteriv_names, -1, 363 },
+ { GetHistogram_names, -1, 361 },
+ { Minmax_names, -1, 368 },
+ { GetMinmaxParameterfv_names, -1, 365 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_index_func)
+static const struct dri_extension_function GL_EXT_index_func_functions[] = {
+ { IndexFuncEXT_names, IndexFuncEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_index_material)
+static const struct dri_extension_function GL_EXT_index_material_functions[] = {
+ { IndexMaterialEXT_names, IndexMaterialEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_light_texture)
+static const struct dri_extension_function GL_EXT_light_texture_functions[] = {
+ { ApplyTextureEXT_names, ApplyTextureEXT_remap_index, -1 },
+ { TextureMaterialEXT_names, TextureMaterialEXT_remap_index, -1 },
+ { TextureLightEXT_names, TextureLightEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_multi_draw_arrays)
+static const struct dri_extension_function GL_EXT_multi_draw_arrays_functions[] = {
+ { MultiDrawElementsEXT_names, MultiDrawElementsEXT_remap_index, -1 },
+ { MultiDrawArraysEXT_names, MultiDrawArraysEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_multisample)
+static const struct dri_extension_function GL_EXT_multisample_functions[] = {
+ { SampleMaskSGIS_names, SampleMaskSGIS_remap_index, -1 },
+ { SamplePatternSGIS_names, SamplePatternSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_paletted_texture)
+static const struct dri_extension_function GL_EXT_paletted_texture_functions[] = {
+ { ColorTable_names, -1, 339 },
+ { GetColorTable_names, -1, 343 },
+ { GetColorTableParameterfv_names, -1, 344 },
+ { GetColorTableParameteriv_names, -1, 345 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_pixel_transform)
+static const struct dri_extension_function GL_EXT_pixel_transform_functions[] = {
+ { PixelTransformParameterfvEXT_names, PixelTransformParameterfvEXT_remap_index, -1 },
+ { PixelTransformParameterfEXT_names, PixelTransformParameterfEXT_remap_index, -1 },
+ { PixelTransformParameteriEXT_names, PixelTransformParameteriEXT_remap_index, -1 },
+ { PixelTransformParameterivEXT_names, PixelTransformParameterivEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_point_parameters)
+static const struct dri_extension_function GL_EXT_point_parameters_functions[] = {
+ { PointParameterfEXT_names, PointParameterfEXT_remap_index, -1 },
+ { PointParameterfvEXT_names, PointParameterfvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_polygon_offset)
+static const struct dri_extension_function GL_EXT_polygon_offset_functions[] = {
+ { PolygonOffsetEXT_names, PolygonOffsetEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_provoking_vertex)
+static const struct dri_extension_function GL_EXT_provoking_vertex_functions[] = {
+ { ProvokingVertexEXT_names, ProvokingVertexEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_secondary_color)
+static const struct dri_extension_function GL_EXT_secondary_color_functions[] = {
+ { SecondaryColor3iEXT_names, SecondaryColor3iEXT_remap_index, -1 },
+ { SecondaryColor3bEXT_names, SecondaryColor3bEXT_remap_index, -1 },
+ { SecondaryColor3bvEXT_names, SecondaryColor3bvEXT_remap_index, -1 },
+ { SecondaryColor3sEXT_names, SecondaryColor3sEXT_remap_index, -1 },
+ { SecondaryColor3dEXT_names, SecondaryColor3dEXT_remap_index, -1 },
+ { SecondaryColorPointerEXT_names, SecondaryColorPointerEXT_remap_index, -1 },
+ { SecondaryColor3uiEXT_names, SecondaryColor3uiEXT_remap_index, -1 },
+ { SecondaryColor3usvEXT_names, SecondaryColor3usvEXT_remap_index, -1 },
+ { SecondaryColor3ivEXT_names, SecondaryColor3ivEXT_remap_index, -1 },
+ { SecondaryColor3fvEXT_names, SecondaryColor3fvEXT_remap_index, -1 },
+ { SecondaryColor3ubvEXT_names, SecondaryColor3ubvEXT_remap_index, -1 },
+ { SecondaryColor3uivEXT_names, SecondaryColor3uivEXT_remap_index, -1 },
+ { SecondaryColor3dvEXT_names, SecondaryColor3dvEXT_remap_index, -1 },
+ { SecondaryColor3usEXT_names, SecondaryColor3usEXT_remap_index, -1 },
+ { SecondaryColor3ubEXT_names, SecondaryColor3ubEXT_remap_index, -1 },
+ { SecondaryColor3fEXT_names, SecondaryColor3fEXT_remap_index, -1 },
+ { SecondaryColor3svEXT_names, SecondaryColor3svEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_stencil_two_side)
+static const struct dri_extension_function GL_EXT_stencil_two_side_functions[] = {
+ { ActiveStencilFaceEXT_names, ActiveStencilFaceEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_subtexture)
+static const struct dri_extension_function GL_EXT_subtexture_functions[] = {
+ { TexSubImage1D_names, -1, 332 },
+ { TexSubImage2D_names, -1, 333 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_texture3D)
+static const struct dri_extension_function GL_EXT_texture3D_functions[] = {
+ { TexImage3D_names, -1, 371 },
+ { TexSubImage3D_names, -1, 372 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_texture_array)
+static const struct dri_extension_function GL_EXT_texture_array_functions[] = {
+ { FramebufferTextureLayerEXT_names, FramebufferTextureLayerEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_texture_object)
+static const struct dri_extension_function GL_EXT_texture_object_functions[] = {
+ { PrioritizeTextures_names, -1, 331 },
+ { AreTexturesResident_names, -1, 322 },
+ { GenTextures_names, -1, 328 },
+ { DeleteTextures_names, -1, 327 },
+ { IsTexture_names, -1, 330 },
+ { BindTexture_names, -1, 307 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_texture_perturb_normal)
+static const struct dri_extension_function GL_EXT_texture_perturb_normal_functions[] = {
+ { TextureNormalEXT_names, TextureNormalEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_timer_query)
+static const struct dri_extension_function GL_EXT_timer_query_functions[] = {
+ { GetQueryObjectui64vEXT_names, GetQueryObjectui64vEXT_remap_index, -1 },
+ { GetQueryObjecti64vEXT_names, GetQueryObjecti64vEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_vertex_array)
+static const struct dri_extension_function GL_EXT_vertex_array_functions[] = {
+ { IndexPointerEXT_names, IndexPointerEXT_remap_index, -1 },
+ { NormalPointerEXT_names, NormalPointerEXT_remap_index, -1 },
+ { VertexPointerEXT_names, VertexPointerEXT_remap_index, -1 },
+ { TexCoordPointerEXT_names, TexCoordPointerEXT_remap_index, -1 },
+ { EdgeFlagPointerEXT_names, EdgeFlagPointerEXT_remap_index, -1 },
+ { ArrayElement_names, -1, 306 },
+ { ColorPointerEXT_names, ColorPointerEXT_remap_index, -1 },
+ { GetPointerv_names, -1, 329 },
+ { DrawArrays_names, -1, 310 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_EXT_vertex_weighting)
+static const struct dri_extension_function GL_EXT_vertex_weighting_functions[] = {
+ { VertexWeightfvEXT_names, VertexWeightfvEXT_remap_index, -1 },
+ { VertexWeightfEXT_names, VertexWeightfEXT_remap_index, -1 },
+ { VertexWeightPointerEXT_names, VertexWeightPointerEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_HP_image_transform)
+static const struct dri_extension_function GL_HP_image_transform_functions[] = {
+ { GetImageTransformParameterfvHP_names, GetImageTransformParameterfvHP_remap_index, -1 },
+ { ImageTransformParameterfHP_names, ImageTransformParameterfHP_remap_index, -1 },
+ { ImageTransformParameterfvHP_names, ImageTransformParameterfvHP_remap_index, -1 },
+ { ImageTransformParameteriHP_names, ImageTransformParameteriHP_remap_index, -1 },
+ { GetImageTransformParameterivHP_names, GetImageTransformParameterivHP_remap_index, -1 },
+ { ImageTransformParameterivHP_names, ImageTransformParameterivHP_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_IBM_multimode_draw_arrays)
+static const struct dri_extension_function GL_IBM_multimode_draw_arrays_functions[] = {
+ { MultiModeDrawArraysIBM_names, MultiModeDrawArraysIBM_remap_index, -1 },
+ { MultiModeDrawElementsIBM_names, MultiModeDrawElementsIBM_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_IBM_vertex_array_lists)
+static const struct dri_extension_function GL_IBM_vertex_array_lists_functions[] = {
+ { SecondaryColorPointerListIBM_names, SecondaryColorPointerListIBM_remap_index, -1 },
+ { NormalPointerListIBM_names, NormalPointerListIBM_remap_index, -1 },
+ { FogCoordPointerListIBM_names, FogCoordPointerListIBM_remap_index, -1 },
+ { VertexPointerListIBM_names, VertexPointerListIBM_remap_index, -1 },
+ { ColorPointerListIBM_names, ColorPointerListIBM_remap_index, -1 },
+ { TexCoordPointerListIBM_names, TexCoordPointerListIBM_remap_index, -1 },
+ { IndexPointerListIBM_names, IndexPointerListIBM_remap_index, -1 },
+ { EdgeFlagPointerListIBM_names, EdgeFlagPointerListIBM_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_INGR_blend_func_separate)
+static const struct dri_extension_function GL_INGR_blend_func_separate_functions[] = {
+ { BlendFuncSeparateEXT_names, BlendFuncSeparateEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_INTEL_parallel_arrays)
+static const struct dri_extension_function GL_INTEL_parallel_arrays_functions[] = {
+ { VertexPointervINTEL_names, VertexPointervINTEL_remap_index, -1 },
+ { ColorPointervINTEL_names, ColorPointervINTEL_remap_index, -1 },
+ { NormalPointervINTEL_names, NormalPointervINTEL_remap_index, -1 },
+ { TexCoordPointervINTEL_names, TexCoordPointervINTEL_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_MESA_resize_buffers)
+static const struct dri_extension_function GL_MESA_resize_buffers_functions[] = {
+ { ResizeBuffersMESA_names, ResizeBuffersMESA_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_MESA_shader_debug)
+static const struct dri_extension_function GL_MESA_shader_debug_functions[] = {
+ { GetDebugLogLengthMESA_names, GetDebugLogLengthMESA_remap_index, -1 },
+ { ClearDebugLogMESA_names, ClearDebugLogMESA_remap_index, -1 },
+ { GetDebugLogMESA_names, GetDebugLogMESA_remap_index, -1 },
+ { CreateDebugObjectMESA_names, CreateDebugObjectMESA_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_MESA_window_pos)
+static const struct dri_extension_function GL_MESA_window_pos_functions[] = {
+ { WindowPos3fMESA_names, WindowPos3fMESA_remap_index, -1 },
+ { WindowPos2dvMESA_names, WindowPos2dvMESA_remap_index, -1 },
+ { WindowPos4svMESA_names, WindowPos4svMESA_remap_index, -1 },
+ { WindowPos2svMESA_names, WindowPos2svMESA_remap_index, -1 },
+ { WindowPos3dMESA_names, WindowPos3dMESA_remap_index, -1 },
+ { WindowPos2fvMESA_names, WindowPos2fvMESA_remap_index, -1 },
+ { WindowPos4dMESA_names, WindowPos4dMESA_remap_index, -1 },
+ { WindowPos2dMESA_names, WindowPos2dMESA_remap_index, -1 },
+ { WindowPos4ivMESA_names, WindowPos4ivMESA_remap_index, -1 },
+ { WindowPos4fMESA_names, WindowPos4fMESA_remap_index, -1 },
+ { WindowPos3dvMESA_names, WindowPos3dvMESA_remap_index, -1 },
+ { WindowPos3fvMESA_names, WindowPos3fvMESA_remap_index, -1 },
+ { WindowPos4dvMESA_names, WindowPos4dvMESA_remap_index, -1 },
+ { WindowPos2iMESA_names, WindowPos2iMESA_remap_index, -1 },
+ { WindowPos3sMESA_names, WindowPos3sMESA_remap_index, -1 },
+ { WindowPos4sMESA_names, WindowPos4sMESA_remap_index, -1 },
+ { WindowPos2ivMESA_names, WindowPos2ivMESA_remap_index, -1 },
+ { WindowPos2sMESA_names, WindowPos2sMESA_remap_index, -1 },
+ { WindowPos3iMESA_names, WindowPos3iMESA_remap_index, -1 },
+ { WindowPos3ivMESA_names, WindowPos3ivMESA_remap_index, -1 },
+ { WindowPos4iMESA_names, WindowPos4iMESA_remap_index, -1 },
+ { WindowPos4fvMESA_names, WindowPos4fvMESA_remap_index, -1 },
+ { WindowPos3svMESA_names, WindowPos3svMESA_remap_index, -1 },
+ { WindowPos2fMESA_names, WindowPos2fMESA_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_evaluators)
+static const struct dri_extension_function GL_NV_evaluators_functions[] = {
+ { GetMapAttribParameterivNV_names, GetMapAttribParameterivNV_remap_index, -1 },
+ { MapControlPointsNV_names, MapControlPointsNV_remap_index, -1 },
+ { MapParameterfvNV_names, MapParameterfvNV_remap_index, -1 },
+ { EvalMapsNV_names, EvalMapsNV_remap_index, -1 },
+ { GetMapAttribParameterfvNV_names, GetMapAttribParameterfvNV_remap_index, -1 },
+ { MapParameterivNV_names, MapParameterivNV_remap_index, -1 },
+ { GetMapParameterivNV_names, GetMapParameterivNV_remap_index, -1 },
+ { GetMapParameterfvNV_names, GetMapParameterfvNV_remap_index, -1 },
+ { GetMapControlPointsNV_names, GetMapControlPointsNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_fence)
+static const struct dri_extension_function GL_NV_fence_functions[] = {
+ { GenFencesNV_names, GenFencesNV_remap_index, -1 },
+ { TestFenceNV_names, TestFenceNV_remap_index, -1 },
+ { IsFenceNV_names, IsFenceNV_remap_index, -1 },
+ { DeleteFencesNV_names, DeleteFencesNV_remap_index, -1 },
+ { SetFenceNV_names, SetFenceNV_remap_index, -1 },
+ { GetFenceivNV_names, GetFenceivNV_remap_index, -1 },
+ { FinishFenceNV_names, FinishFenceNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_fragment_program)
+static const struct dri_extension_function GL_NV_fragment_program_functions[] = {
+ { GetProgramNamedParameterdvNV_names, GetProgramNamedParameterdvNV_remap_index, -1 },
+ { GetProgramNamedParameterfvNV_names, GetProgramNamedParameterfvNV_remap_index, -1 },
+ { ProgramNamedParameter4fNV_names, ProgramNamedParameter4fNV_remap_index, -1 },
+ { ProgramNamedParameter4fvNV_names, ProgramNamedParameter4fvNV_remap_index, -1 },
+ { ProgramNamedParameter4dvNV_names, ProgramNamedParameter4dvNV_remap_index, -1 },
+ { ProgramNamedParameter4dNV_names, ProgramNamedParameter4dNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_point_sprite)
+static const struct dri_extension_function GL_NV_point_sprite_functions[] = {
+ { PointParameteriNV_names, PointParameteriNV_remap_index, -1 },
+ { PointParameterivNV_names, PointParameterivNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_register_combiners)
+static const struct dri_extension_function GL_NV_register_combiners_functions[] = {
+ { CombinerOutputNV_names, CombinerOutputNV_remap_index, -1 },
+ { CombinerParameterfvNV_names, CombinerParameterfvNV_remap_index, -1 },
+ { GetCombinerOutputParameterfvNV_names, GetCombinerOutputParameterfvNV_remap_index, -1 },
+ { FinalCombinerInputNV_names, FinalCombinerInputNV_remap_index, -1 },
+ { GetCombinerInputParameterfvNV_names, GetCombinerInputParameterfvNV_remap_index, -1 },
+ { GetCombinerOutputParameterivNV_names, GetCombinerOutputParameterivNV_remap_index, -1 },
+ { CombinerParameteriNV_names, CombinerParameteriNV_remap_index, -1 },
+ { GetFinalCombinerInputParameterivNV_names, GetFinalCombinerInputParameterivNV_remap_index, -1 },
+ { CombinerInputNV_names, CombinerInputNV_remap_index, -1 },
+ { CombinerParameterfNV_names, CombinerParameterfNV_remap_index, -1 },
+ { GetFinalCombinerInputParameterfvNV_names, GetFinalCombinerInputParameterfvNV_remap_index, -1 },
+ { GetCombinerInputParameterivNV_names, GetCombinerInputParameterivNV_remap_index, -1 },
+ { CombinerParameterivNV_names, CombinerParameterivNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_register_combiners2)
+static const struct dri_extension_function GL_NV_register_combiners2_functions[] = {
+ { CombinerStageParameterfvNV_names, CombinerStageParameterfvNV_remap_index, -1 },
+ { GetCombinerStageParameterfvNV_names, GetCombinerStageParameterfvNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_vertex_array_range)
+static const struct dri_extension_function GL_NV_vertex_array_range_functions[] = {
+ { VertexArrayRangeNV_names, VertexArrayRangeNV_remap_index, -1 },
+ { FlushVertexArrayRangeNV_names, FlushVertexArrayRangeNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_NV_vertex_program)
+static const struct dri_extension_function GL_NV_vertex_program_functions[] = {
+ { VertexAttrib4ubvNV_names, VertexAttrib4ubvNV_remap_index, -1 },
+ { VertexAttrib4svNV_names, VertexAttrib4svNV_remap_index, -1 },
+ { VertexAttribs1dvNV_names, VertexAttribs1dvNV_remap_index, -1 },
+ { VertexAttrib1fvNV_names, VertexAttrib1fvNV_remap_index, -1 },
+ { VertexAttrib4fNV_names, VertexAttrib4fNV_remap_index, -1 },
+ { VertexAttrib2dNV_names, VertexAttrib2dNV_remap_index, -1 },
+ { VertexAttrib4ubNV_names, VertexAttrib4ubNV_remap_index, -1 },
+ { VertexAttribs3dvNV_names, VertexAttribs3dvNV_remap_index, -1 },
+ { VertexAttribs4fvNV_names, VertexAttribs4fvNV_remap_index, -1 },
+ { VertexAttrib2sNV_names, VertexAttrib2sNV_remap_index, -1 },
+ { VertexAttribs3fvNV_names, VertexAttribs3fvNV_remap_index, -1 },
+ { ProgramEnvParameter4fvARB_names, ProgramEnvParameter4fvARB_remap_index, -1 },
+ { LoadProgramNV_names, LoadProgramNV_remap_index, -1 },
+ { VertexAttrib4fvNV_names, VertexAttrib4fvNV_remap_index, -1 },
+ { VertexAttrib3fNV_names, VertexAttrib3fNV_remap_index, -1 },
+ { VertexAttribs2dvNV_names, VertexAttribs2dvNV_remap_index, -1 },
+ { GetProgramParameterfvNV_names, GetProgramParameterfvNV_remap_index, -1 },
+ { VertexAttrib3dNV_names, VertexAttrib3dNV_remap_index, -1 },
+ { VertexAttrib2fvNV_names, VertexAttrib2fvNV_remap_index, -1 },
+ { VertexAttrib2dvNV_names, VertexAttrib2dvNV_remap_index, -1 },
+ { VertexAttrib1dvNV_names, VertexAttrib1dvNV_remap_index, -1 },
+ { VertexAttrib1svNV_names, VertexAttrib1svNV_remap_index, -1 },
+ { ProgramEnvParameter4fARB_names, ProgramEnvParameter4fARB_remap_index, -1 },
+ { VertexAttribs2svNV_names, VertexAttribs2svNV_remap_index, -1 },
+ { GetVertexAttribivNV_names, GetVertexAttribivNV_remap_index, -1 },
+ { GetVertexAttribfvNV_names, GetVertexAttribfvNV_remap_index, -1 },
+ { VertexAttrib2svNV_names, VertexAttrib2svNV_remap_index, -1 },
+ { VertexAttribs1fvNV_names, VertexAttribs1fvNV_remap_index, -1 },
+ { IsProgramNV_names, IsProgramNV_remap_index, -1 },
+ { ProgramEnvParameter4dARB_names, ProgramEnvParameter4dARB_remap_index, -1 },
+ { VertexAttrib2fNV_names, VertexAttrib2fNV_remap_index, -1 },
+ { RequestResidentProgramsNV_names, RequestResidentProgramsNV_remap_index, -1 },
+ { ExecuteProgramNV_names, ExecuteProgramNV_remap_index, -1 },
+ { VertexAttribPointerNV_names, VertexAttribPointerNV_remap_index, -1 },
+ { TrackMatrixNV_names, TrackMatrixNV_remap_index, -1 },
+ { GetProgramParameterdvNV_names, GetProgramParameterdvNV_remap_index, -1 },
+ { GetTrackMatrixivNV_names, GetTrackMatrixivNV_remap_index, -1 },
+ { VertexAttrib3svNV_names, VertexAttrib3svNV_remap_index, -1 },
+ { ProgramParameters4fvNV_names, ProgramParameters4fvNV_remap_index, -1 },
+ { GetProgramivNV_names, GetProgramivNV_remap_index, -1 },
+ { GetVertexAttribdvNV_names, GetVertexAttribdvNV_remap_index, -1 },
+ { VertexAttrib3fvNV_names, VertexAttrib3fvNV_remap_index, -1 },
+ { ProgramEnvParameter4dvARB_names, ProgramEnvParameter4dvARB_remap_index, -1 },
+ { VertexAttribs2fvNV_names, VertexAttribs2fvNV_remap_index, -1 },
+ { DeleteProgramsNV_names, DeleteProgramsNV_remap_index, -1 },
+ { GetVertexAttribPointervNV_names, GetVertexAttribPointervNV_remap_index, -1 },
+ { GetProgramStringNV_names, GetProgramStringNV_remap_index, -1 },
+ { VertexAttrib4sNV_names, VertexAttrib4sNV_remap_index, -1 },
+ { VertexAttribs4dvNV_names, VertexAttribs4dvNV_remap_index, -1 },
+ { ProgramParameters4dvNV_names, ProgramParameters4dvNV_remap_index, -1 },
+ { VertexAttrib3sNV_names, VertexAttrib3sNV_remap_index, -1 },
+ { VertexAttrib1fNV_names, VertexAttrib1fNV_remap_index, -1 },
+ { VertexAttrib4dNV_names, VertexAttrib4dNV_remap_index, -1 },
+ { VertexAttribs4ubvNV_names, VertexAttribs4ubvNV_remap_index, -1 },
+ { VertexAttribs3svNV_names, VertexAttribs3svNV_remap_index, -1 },
+ { VertexAttrib1sNV_names, VertexAttrib1sNV_remap_index, -1 },
+ { BindProgramNV_names, BindProgramNV_remap_index, -1 },
+ { AreProgramsResidentNV_names, AreProgramsResidentNV_remap_index, -1 },
+ { VertexAttrib3dvNV_names, VertexAttrib3dvNV_remap_index, -1 },
+ { VertexAttrib1dNV_names, VertexAttrib1dNV_remap_index, -1 },
+ { VertexAttribs4svNV_names, VertexAttribs4svNV_remap_index, -1 },
+ { VertexAttribs1svNV_names, VertexAttribs1svNV_remap_index, -1 },
+ { GenProgramsNV_names, GenProgramsNV_remap_index, -1 },
+ { VertexAttrib4dvNV_names, VertexAttrib4dvNV_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_PGI_misc_hints)
+static const struct dri_extension_function GL_PGI_misc_hints_functions[] = {
+ { HintPGI_names, HintPGI_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_detail_texture)
+static const struct dri_extension_function GL_SGIS_detail_texture_functions[] = {
+ { GetDetailTexFuncSGIS_names, GetDetailTexFuncSGIS_remap_index, -1 },
+ { DetailTexFuncSGIS_names, DetailTexFuncSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_fog_function)
+static const struct dri_extension_function GL_SGIS_fog_function_functions[] = {
+ { FogFuncSGIS_names, FogFuncSGIS_remap_index, -1 },
+ { GetFogFuncSGIS_names, GetFogFuncSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_multisample)
+static const struct dri_extension_function GL_SGIS_multisample_functions[] = {
+ { SampleMaskSGIS_names, SampleMaskSGIS_remap_index, -1 },
+ { SamplePatternSGIS_names, SamplePatternSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_pixel_texture)
+static const struct dri_extension_function GL_SGIS_pixel_texture_functions[] = {
+ { PixelTexGenParameterfvSGIS_names, PixelTexGenParameterfvSGIS_remap_index, -1 },
+ { GetPixelTexGenParameterivSGIS_names, GetPixelTexGenParameterivSGIS_remap_index, -1 },
+ { PixelTexGenParameteriSGIS_names, PixelTexGenParameteriSGIS_remap_index, -1 },
+ { PixelTexGenParameterivSGIS_names, PixelTexGenParameterivSGIS_remap_index, -1 },
+ { PixelTexGenParameterfSGIS_names, PixelTexGenParameterfSGIS_remap_index, -1 },
+ { GetPixelTexGenParameterfvSGIS_names, GetPixelTexGenParameterfvSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_point_parameters)
+static const struct dri_extension_function GL_SGIS_point_parameters_functions[] = {
+ { PointParameterfEXT_names, PointParameterfEXT_remap_index, -1 },
+ { PointParameterfvEXT_names, PointParameterfvEXT_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_sharpen_texture)
+static const struct dri_extension_function GL_SGIS_sharpen_texture_functions[] = {
+ { GetSharpenTexFuncSGIS_names, GetSharpenTexFuncSGIS_remap_index, -1 },
+ { SharpenTexFuncSGIS_names, SharpenTexFuncSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_texture4D)
+static const struct dri_extension_function GL_SGIS_texture4D_functions[] = {
+ { TexImage4DSGIS_names, TexImage4DSGIS_remap_index, -1 },
+ { TexSubImage4DSGIS_names, TexSubImage4DSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_texture_color_mask)
+static const struct dri_extension_function GL_SGIS_texture_color_mask_functions[] = {
+ { TextureColorMaskSGIS_names, TextureColorMaskSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIS_texture_filter4)
+static const struct dri_extension_function GL_SGIS_texture_filter4_functions[] = {
+ { GetTexFilterFuncSGIS_names, GetTexFilterFuncSGIS_remap_index, -1 },
+ { TexFilterFuncSGIS_names, TexFilterFuncSGIS_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_async)
+static const struct dri_extension_function GL_SGIX_async_functions[] = {
+ { AsyncMarkerSGIX_names, AsyncMarkerSGIX_remap_index, -1 },
+ { FinishAsyncSGIX_names, FinishAsyncSGIX_remap_index, -1 },
+ { PollAsyncSGIX_names, PollAsyncSGIX_remap_index, -1 },
+ { DeleteAsyncMarkersSGIX_names, DeleteAsyncMarkersSGIX_remap_index, -1 },
+ { IsAsyncMarkerSGIX_names, IsAsyncMarkerSGIX_remap_index, -1 },
+ { GenAsyncMarkersSGIX_names, GenAsyncMarkersSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_flush_raster)
+static const struct dri_extension_function GL_SGIX_flush_raster_functions[] = {
+ { FlushRasterSGIX_names, FlushRasterSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_fragment_lighting)
+static const struct dri_extension_function GL_SGIX_fragment_lighting_functions[] = {
+ { FragmentMaterialfvSGIX_names, FragmentMaterialfvSGIX_remap_index, -1 },
+ { FragmentLightModelivSGIX_names, FragmentLightModelivSGIX_remap_index, -1 },
+ { FragmentLightiSGIX_names, FragmentLightiSGIX_remap_index, -1 },
+ { GetFragmentMaterialfvSGIX_names, GetFragmentMaterialfvSGIX_remap_index, -1 },
+ { FragmentMaterialfSGIX_names, FragmentMaterialfSGIX_remap_index, -1 },
+ { GetFragmentLightivSGIX_names, GetFragmentLightivSGIX_remap_index, -1 },
+ { FragmentLightModeliSGIX_names, FragmentLightModeliSGIX_remap_index, -1 },
+ { FragmentLightivSGIX_names, FragmentLightivSGIX_remap_index, -1 },
+ { GetFragmentMaterialivSGIX_names, GetFragmentMaterialivSGIX_remap_index, -1 },
+ { FragmentLightModelfSGIX_names, FragmentLightModelfSGIX_remap_index, -1 },
+ { FragmentColorMaterialSGIX_names, FragmentColorMaterialSGIX_remap_index, -1 },
+ { FragmentMaterialiSGIX_names, FragmentMaterialiSGIX_remap_index, -1 },
+ { LightEnviSGIX_names, LightEnviSGIX_remap_index, -1 },
+ { FragmentLightModelfvSGIX_names, FragmentLightModelfvSGIX_remap_index, -1 },
+ { FragmentLightfvSGIX_names, FragmentLightfvSGIX_remap_index, -1 },
+ { FragmentLightfSGIX_names, FragmentLightfSGIX_remap_index, -1 },
+ { GetFragmentLightfvSGIX_names, GetFragmentLightfvSGIX_remap_index, -1 },
+ { FragmentMaterialivSGIX_names, FragmentMaterialivSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_framezoom)
+static const struct dri_extension_function GL_SGIX_framezoom_functions[] = {
+ { FrameZoomSGIX_names, FrameZoomSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_igloo_interface)
+static const struct dri_extension_function GL_SGIX_igloo_interface_functions[] = {
+ { IglooInterfaceSGIX_names, IglooInterfaceSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_instruments)
+static const struct dri_extension_function GL_SGIX_instruments_functions[] = {
+ { ReadInstrumentsSGIX_names, ReadInstrumentsSGIX_remap_index, -1 },
+ { PollInstrumentsSGIX_names, PollInstrumentsSGIX_remap_index, -1 },
+ { GetInstrumentsSGIX_names, GetInstrumentsSGIX_remap_index, -1 },
+ { StartInstrumentsSGIX_names, StartInstrumentsSGIX_remap_index, -1 },
+ { StopInstrumentsSGIX_names, StopInstrumentsSGIX_remap_index, -1 },
+ { InstrumentsBufferSGIX_names, InstrumentsBufferSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_list_priority)
+static const struct dri_extension_function GL_SGIX_list_priority_functions[] = {
+ { ListParameterfSGIX_names, ListParameterfSGIX_remap_index, -1 },
+ { GetListParameterfvSGIX_names, GetListParameterfvSGIX_remap_index, -1 },
+ { ListParameteriSGIX_names, ListParameteriSGIX_remap_index, -1 },
+ { ListParameterfvSGIX_names, ListParameterfvSGIX_remap_index, -1 },
+ { ListParameterivSGIX_names, ListParameterivSGIX_remap_index, -1 },
+ { GetListParameterivSGIX_names, GetListParameterivSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_pixel_texture)
+static const struct dri_extension_function GL_SGIX_pixel_texture_functions[] = {
+ { PixelTexGenSGIX_names, PixelTexGenSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_polynomial_ffd)
+static const struct dri_extension_function GL_SGIX_polynomial_ffd_functions[] = {
+ { LoadIdentityDeformationMapSGIX_names, LoadIdentityDeformationMapSGIX_remap_index, -1 },
+ { DeformationMap3dSGIX_names, DeformationMap3dSGIX_remap_index, -1 },
+ { DeformSGIX_names, DeformSGIX_remap_index, -1 },
+ { DeformationMap3fSGIX_names, DeformationMap3fSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_reference_plane)
+static const struct dri_extension_function GL_SGIX_reference_plane_functions[] = {
+ { ReferencePlaneSGIX_names, ReferencePlaneSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_sprite)
+static const struct dri_extension_function GL_SGIX_sprite_functions[] = {
+ { SpriteParameterfvSGIX_names, SpriteParameterfvSGIX_remap_index, -1 },
+ { SpriteParameteriSGIX_names, SpriteParameteriSGIX_remap_index, -1 },
+ { SpriteParameterfSGIX_names, SpriteParameterfSGIX_remap_index, -1 },
+ { SpriteParameterivSGIX_names, SpriteParameterivSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGIX_tag_sample_buffer)
+static const struct dri_extension_function GL_SGIX_tag_sample_buffer_functions[] = {
+ { TagSampleBufferSGIX_names, TagSampleBufferSGIX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SGI_color_table)
+static const struct dri_extension_function GL_SGI_color_table_functions[] = {
+ { ColorTableParameteriv_names, -1, 341 },
+ { ColorTable_names, -1, 339 },
+ { GetColorTable_names, -1, 343 },
+ { CopyColorTable_names, -1, 342 },
+ { ColorTableParameterfv_names, -1, 340 },
+ { GetColorTableParameterfv_names, -1, 344 },
+ { GetColorTableParameteriv_names, -1, 345 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SUNX_constant_data)
+static const struct dri_extension_function GL_SUNX_constant_data_functions[] = {
+ { FinishTextureSUNX_names, FinishTextureSUNX_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SUN_global_alpha)
+static const struct dri_extension_function GL_SUN_global_alpha_functions[] = {
+ { GlobalAlphaFactorubSUN_names, GlobalAlphaFactorubSUN_remap_index, -1 },
+ { GlobalAlphaFactoriSUN_names, GlobalAlphaFactoriSUN_remap_index, -1 },
+ { GlobalAlphaFactordSUN_names, GlobalAlphaFactordSUN_remap_index, -1 },
+ { GlobalAlphaFactoruiSUN_names, GlobalAlphaFactoruiSUN_remap_index, -1 },
+ { GlobalAlphaFactorbSUN_names, GlobalAlphaFactorbSUN_remap_index, -1 },
+ { GlobalAlphaFactorfSUN_names, GlobalAlphaFactorfSUN_remap_index, -1 },
+ { GlobalAlphaFactorusSUN_names, GlobalAlphaFactorusSUN_remap_index, -1 },
+ { GlobalAlphaFactorsSUN_names, GlobalAlphaFactorsSUN_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SUN_mesh_array)
+static const struct dri_extension_function GL_SUN_mesh_array_functions[] = {
+ { DrawMeshArraysSUN_names, DrawMeshArraysSUN_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SUN_triangle_list)
+static const struct dri_extension_function GL_SUN_triangle_list_functions[] = {
+ { ReplacementCodeubSUN_names, ReplacementCodeubSUN_remap_index, -1 },
+ { ReplacementCodeubvSUN_names, ReplacementCodeubvSUN_remap_index, -1 },
+ { ReplacementCodeusvSUN_names, ReplacementCodeusvSUN_remap_index, -1 },
+ { ReplacementCodePointerSUN_names, ReplacementCodePointerSUN_remap_index, -1 },
+ { ReplacementCodeusSUN_names, ReplacementCodeusSUN_remap_index, -1 },
+ { ReplacementCodeuiSUN_names, ReplacementCodeuiSUN_remap_index, -1 },
+ { ReplacementCodeuivSUN_names, ReplacementCodeuivSUN_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_SUN_vertex)
+static const struct dri_extension_function GL_SUN_vertex_functions[] = {
+ { ReplacementCodeuiColor3fVertex3fvSUN_names, ReplacementCodeuiColor3fVertex3fvSUN_remap_index, -1 },
+ { TexCoord4fColor4fNormal3fVertex4fvSUN_names, TexCoord4fColor4fNormal3fVertex4fvSUN_remap_index, -1 },
+ { TexCoord2fColor4ubVertex3fvSUN_names, TexCoord2fColor4ubVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiVertex3fvSUN_names, ReplacementCodeuiVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fVertex3fvSUN_names, ReplacementCodeuiTexCoord2fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiNormal3fVertex3fSUN_names, ReplacementCodeuiNormal3fVertex3fSUN_remap_index, -1 },
+ { Color4ubVertex3fvSUN_names, Color4ubVertex3fvSUN_remap_index, -1 },
+ { Color4ubVertex3fSUN_names, Color4ubVertex3fSUN_remap_index, -1 },
+ { TexCoord2fVertex3fSUN_names, TexCoord2fVertex3fSUN_remap_index, -1 },
+ { TexCoord2fColor4fNormal3fVertex3fSUN_names, TexCoord2fColor4fNormal3fVertex3fSUN_remap_index, -1 },
+ { TexCoord2fNormal3fVertex3fvSUN_names, TexCoord2fNormal3fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN_names, ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fVertex3fSUN_names, ReplacementCodeuiTexCoord2fVertex3fSUN_remap_index, -1 },
+ { TexCoord2fNormal3fVertex3fSUN_names, TexCoord2fNormal3fVertex3fSUN_remap_index, -1 },
+ { Color3fVertex3fSUN_names, Color3fVertex3fSUN_remap_index, -1 },
+ { Color3fVertex3fvSUN_names, Color3fVertex3fvSUN_remap_index, -1 },
+ { Color4fNormal3fVertex3fvSUN_names, Color4fNormal3fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN_names, ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiColor4fNormal3fVertex3fvSUN_names, ReplacementCodeuiColor4fNormal3fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN_names, ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN_remap_index, -1 },
+ { TexCoord2fColor3fVertex3fSUN_names, TexCoord2fColor3fVertex3fSUN_remap_index, -1 },
+ { TexCoord4fColor4fNormal3fVertex4fSUN_names, TexCoord4fColor4fNormal3fVertex4fSUN_remap_index, -1 },
+ { Color4ubVertex2fvSUN_names, Color4ubVertex2fvSUN_remap_index, -1 },
+ { Normal3fVertex3fSUN_names, Normal3fVertex3fSUN_remap_index, -1 },
+ { ReplacementCodeuiColor4fNormal3fVertex3fSUN_names, ReplacementCodeuiColor4fNormal3fVertex3fSUN_remap_index, -1 },
+ { TexCoord2fColor4fNormal3fVertex3fvSUN_names, TexCoord2fColor4fNormal3fVertex3fvSUN_remap_index, -1 },
+ { TexCoord2fVertex3fvSUN_names, TexCoord2fVertex3fvSUN_remap_index, -1 },
+ { Color4ubVertex2fSUN_names, Color4ubVertex2fSUN_remap_index, -1 },
+ { ReplacementCodeuiColor4ubVertex3fSUN_names, ReplacementCodeuiColor4ubVertex3fSUN_remap_index, -1 },
+ { TexCoord2fColor4ubVertex3fSUN_names, TexCoord2fColor4ubVertex3fSUN_remap_index, -1 },
+ { Normal3fVertex3fvSUN_names, Normal3fVertex3fvSUN_remap_index, -1 },
+ { Color4fNormal3fVertex3fSUN_names, Color4fNormal3fVertex3fSUN_remap_index, -1 },
+ { ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN_names, ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN_remap_index, -1 },
+ { ReplacementCodeuiColor4ubVertex3fvSUN_names, ReplacementCodeuiColor4ubVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiColor3fVertex3fSUN_names, ReplacementCodeuiColor3fVertex3fSUN_remap_index, -1 },
+ { TexCoord4fVertex4fSUN_names, TexCoord4fVertex4fSUN_remap_index, -1 },
+ { TexCoord2fColor3fVertex3fvSUN_names, TexCoord2fColor3fVertex3fvSUN_remap_index, -1 },
+ { ReplacementCodeuiNormal3fVertex3fvSUN_names, ReplacementCodeuiNormal3fVertex3fvSUN_remap_index, -1 },
+ { TexCoord4fVertex4fvSUN_names, TexCoord4fVertex4fvSUN_remap_index, -1 },
+ { ReplacementCodeuiVertex3fSUN_names, ReplacementCodeuiVertex3fSUN_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_VERSION_1_3)
+static const struct dri_extension_function GL_VERSION_1_3_functions[] = {
+ { SampleCoverageARB_names, SampleCoverageARB_remap_index, -1 },
+ { MultiTexCoord3sARB_names, -1, 398 },
+ { ActiveTextureARB_names, -1, 374 },
+ { CompressedTexSubImage2DARB_names, CompressedTexSubImage2DARB_remap_index, -1 },
+ { CompressedTexImage3DARB_names, CompressedTexImage3DARB_remap_index, -1 },
+ { MultiTexCoord1fvARB_names, -1, 379 },
+ { MultTransposeMatrixdARB_names, MultTransposeMatrixdARB_remap_index, -1 },
+ { CompressedTexImage1DARB_names, CompressedTexImage1DARB_remap_index, -1 },
+ { MultiTexCoord3dARB_names, -1, 392 },
+ { MultiTexCoord2iARB_names, -1, 388 },
+ { MultiTexCoord2svARB_names, -1, 391 },
+ { MultiTexCoord2fARB_names, -1, 386 },
+ { LoadTransposeMatrixdARB_names, LoadTransposeMatrixdARB_remap_index, -1 },
+ { MultiTexCoord3fvARB_names, -1, 395 },
+ { MultiTexCoord4sARB_names, -1, 406 },
+ { MultiTexCoord2dvARB_names, -1, 385 },
+ { MultiTexCoord1svARB_names, -1, 383 },
+ { MultiTexCoord3svARB_names, -1, 399 },
+ { MultiTexCoord4iARB_names, -1, 404 },
+ { MultiTexCoord3iARB_names, -1, 396 },
+ { MultiTexCoord1dARB_names, -1, 376 },
+ { MultiTexCoord3dvARB_names, -1, 393 },
+ { MultiTexCoord3ivARB_names, -1, 397 },
+ { MultiTexCoord2sARB_names, -1, 390 },
+ { MultiTexCoord4ivARB_names, -1, 405 },
+ { CompressedTexSubImage1DARB_names, CompressedTexSubImage1DARB_remap_index, -1 },
+ { ClientActiveTextureARB_names, -1, 375 },
+ { CompressedTexSubImage3DARB_names, CompressedTexSubImage3DARB_remap_index, -1 },
+ { MultiTexCoord2dARB_names, -1, 384 },
+ { MultiTexCoord4dvARB_names, -1, 401 },
+ { MultiTexCoord4fvARB_names, -1, 403 },
+ { MultiTexCoord3fARB_names, -1, 394 },
+ { MultTransposeMatrixfARB_names, MultTransposeMatrixfARB_remap_index, -1 },
+ { CompressedTexImage2DARB_names, CompressedTexImage2DARB_remap_index, -1 },
+ { MultiTexCoord4dARB_names, -1, 400 },
+ { MultiTexCoord1sARB_names, -1, 382 },
+ { MultiTexCoord1dvARB_names, -1, 377 },
+ { MultiTexCoord1ivARB_names, -1, 381 },
+ { MultiTexCoord2ivARB_names, -1, 389 },
+ { MultiTexCoord1iARB_names, -1, 380 },
+ { GetCompressedTexImageARB_names, GetCompressedTexImageARB_remap_index, -1 },
+ { MultiTexCoord4svARB_names, -1, 407 },
+ { MultiTexCoord1fARB_names, -1, 378 },
+ { MultiTexCoord4fARB_names, -1, 402 },
+ { LoadTransposeMatrixfARB_names, LoadTransposeMatrixfARB_remap_index, -1 },
+ { MultiTexCoord2fvARB_names, -1, 387 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_VERSION_1_4)
+static const struct dri_extension_function GL_VERSION_1_4_functions[] = {
+ { PointParameteriNV_names, PointParameteriNV_remap_index, -1 },
+ { SecondaryColor3iEXT_names, SecondaryColor3iEXT_remap_index, -1 },
+ { WindowPos3fMESA_names, WindowPos3fMESA_remap_index, -1 },
+ { WindowPos2dvMESA_names, WindowPos2dvMESA_remap_index, -1 },
+ { SecondaryColor3bEXT_names, SecondaryColor3bEXT_remap_index, -1 },
+ { PointParameterfEXT_names, PointParameterfEXT_remap_index, -1 },
+ { FogCoorddEXT_names, FogCoorddEXT_remap_index, -1 },
+ { FogCoordfEXT_names, FogCoordfEXT_remap_index, -1 },
+ { WindowPos2svMESA_names, WindowPos2svMESA_remap_index, -1 },
+ { WindowPos3dMESA_names, WindowPos3dMESA_remap_index, -1 },
+ { PointParameterfvEXT_names, PointParameterfvEXT_remap_index, -1 },
+ { WindowPos2fvMESA_names, WindowPos2fvMESA_remap_index, -1 },
+ { SecondaryColor3bvEXT_names, SecondaryColor3bvEXT_remap_index, -1 },
+ { SecondaryColor3sEXT_names, SecondaryColor3sEXT_remap_index, -1 },
+ { SecondaryColor3dEXT_names, SecondaryColor3dEXT_remap_index, -1 },
+ { WindowPos2dMESA_names, WindowPos2dMESA_remap_index, -1 },
+ { SecondaryColorPointerEXT_names, SecondaryColorPointerEXT_remap_index, -1 },
+ { SecondaryColor3uiEXT_names, SecondaryColor3uiEXT_remap_index, -1 },
+ { SecondaryColor3usvEXT_names, SecondaryColor3usvEXT_remap_index, -1 },
+ { WindowPos3dvMESA_names, WindowPos3dvMESA_remap_index, -1 },
+ { PointParameterivNV_names, PointParameterivNV_remap_index, -1 },
+ { WindowPos3fvMESA_names, WindowPos3fvMESA_remap_index, -1 },
+ { SecondaryColor3ivEXT_names, SecondaryColor3ivEXT_remap_index, -1 },
+ { WindowPos2iMESA_names, WindowPos2iMESA_remap_index, -1 },
+ { SecondaryColor3fvEXT_names, SecondaryColor3fvEXT_remap_index, -1 },
+ { WindowPos3sMESA_names, WindowPos3sMESA_remap_index, -1 },
+ { WindowPos2ivMESA_names, WindowPos2ivMESA_remap_index, -1 },
+ { MultiDrawElementsEXT_names, MultiDrawElementsEXT_remap_index, -1 },
+ { WindowPos2sMESA_names, WindowPos2sMESA_remap_index, -1 },
+ { FogCoordPointerEXT_names, FogCoordPointerEXT_remap_index, -1 },
+ { SecondaryColor3ubvEXT_names, SecondaryColor3ubvEXT_remap_index, -1 },
+ { SecondaryColor3uivEXT_names, SecondaryColor3uivEXT_remap_index, -1 },
+ { WindowPos3iMESA_names, WindowPos3iMESA_remap_index, -1 },
+ { SecondaryColor3dvEXT_names, SecondaryColor3dvEXT_remap_index, -1 },
+ { MultiDrawArraysEXT_names, MultiDrawArraysEXT_remap_index, -1 },
+ { SecondaryColor3usEXT_names, SecondaryColor3usEXT_remap_index, -1 },
+ { FogCoordfvEXT_names, FogCoordfvEXT_remap_index, -1 },
+ { SecondaryColor3ubEXT_names, SecondaryColor3ubEXT_remap_index, -1 },
+ { BlendFuncSeparateEXT_names, BlendFuncSeparateEXT_remap_index, -1 },
+ { SecondaryColor3fEXT_names, SecondaryColor3fEXT_remap_index, -1 },
+ { WindowPos3ivMESA_names, WindowPos3ivMESA_remap_index, -1 },
+ { SecondaryColor3svEXT_names, SecondaryColor3svEXT_remap_index, -1 },
+ { FogCoorddvEXT_names, FogCoorddvEXT_remap_index, -1 },
+ { WindowPos3svMESA_names, WindowPos3svMESA_remap_index, -1 },
+ { WindowPos2fMESA_names, WindowPos2fMESA_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_VERSION_1_5)
+static const struct dri_extension_function GL_VERSION_1_5_functions[] = {
+ { BeginQueryARB_names, BeginQueryARB_remap_index, -1 },
+ { GetBufferSubDataARB_names, GetBufferSubDataARB_remap_index, -1 },
+ { BufferSubDataARB_names, BufferSubDataARB_remap_index, -1 },
+ { GetQueryivARB_names, GetQueryivARB_remap_index, -1 },
+ { GetQueryObjectivARB_names, GetQueryObjectivARB_remap_index, -1 },
+ { BufferDataARB_names, BufferDataARB_remap_index, -1 },
+ { EndQueryARB_names, EndQueryARB_remap_index, -1 },
+ { GetBufferPointervARB_names, GetBufferPointervARB_remap_index, -1 },
+ { GetQueryObjectuivARB_names, GetQueryObjectuivARB_remap_index, -1 },
+ { GetBufferParameterivARB_names, GetBufferParameterivARB_remap_index, -1 },
+ { DeleteQueriesARB_names, DeleteQueriesARB_remap_index, -1 },
+ { IsQueryARB_names, IsQueryARB_remap_index, -1 },
+ { MapBufferARB_names, MapBufferARB_remap_index, -1 },
+ { GenQueriesARB_names, GenQueriesARB_remap_index, -1 },
+ { IsBufferARB_names, IsBufferARB_remap_index, -1 },
+ { DeleteBuffersARB_names, DeleteBuffersARB_remap_index, -1 },
+ { UnmapBufferARB_names, UnmapBufferARB_remap_index, -1 },
+ { BindBufferARB_names, BindBufferARB_remap_index, -1 },
+ { GenBuffersARB_names, GenBuffersARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_VERSION_2_0)
+static const struct dri_extension_function GL_VERSION_2_0_functions[] = {
+ { UniformMatrix3fvARB_names, UniformMatrix3fvARB_remap_index, -1 },
+ { GetProgramiv_names, GetProgramiv_remap_index, -1 },
+ { BlendEquationSeparateEXT_names, BlendEquationSeparateEXT_remap_index, -1 },
+ { AttachShader_names, AttachShader_remap_index, -1 },
+ { VertexAttrib2fARB_names, VertexAttrib2fARB_remap_index, -1 },
+ { VertexAttrib3fARB_names, VertexAttrib3fARB_remap_index, -1 },
+ { Uniform2fARB_names, Uniform2fARB_remap_index, -1 },
+ { VertexAttrib1svARB_names, VertexAttrib1svARB_remap_index, -1 },
+ { Uniform2ivARB_names, Uniform2ivARB_remap_index, -1 },
+ { UniformMatrix4fvARB_names, UniformMatrix4fvARB_remap_index, -1 },
+ { VertexAttrib4NusvARB_names, VertexAttrib4NusvARB_remap_index, -1 },
+ { DisableVertexAttribArrayARB_names, DisableVertexAttribArrayARB_remap_index, -1 },
+ { StencilMaskSeparate_names, StencilMaskSeparate_remap_index, -1 },
+ { VertexAttrib1fARB_names, VertexAttrib1fARB_remap_index, -1 },
+ { GetProgramInfoLog_names, GetProgramInfoLog_remap_index, -1 },
+ { VertexAttrib4NbvARB_names, VertexAttrib4NbvARB_remap_index, -1 },
+ { GetActiveAttribARB_names, GetActiveAttribARB_remap_index, -1 },
+ { Uniform3iARB_names, Uniform3iARB_remap_index, -1 },
+ { GetShaderInfoLog_names, GetShaderInfoLog_remap_index, -1 },
+ { VertexAttrib1sARB_names, VertexAttrib1sARB_remap_index, -1 },
+ { Uniform1fARB_names, Uniform1fARB_remap_index, -1 },
+ { StencilOpSeparate_names, StencilOpSeparate_remap_index, -1 },
+ { UniformMatrix2fvARB_names, UniformMatrix2fvARB_remap_index, -1 },
+ { VertexAttrib3dvARB_names, VertexAttrib3dvARB_remap_index, -1 },
+ { Uniform3fvARB_names, Uniform3fvARB_remap_index, -1 },
+ { GetVertexAttribivARB_names, GetVertexAttribivARB_remap_index, -1 },
+ { CreateProgram_names, CreateProgram_remap_index, -1 },
+ { StencilFuncSeparate_names, StencilFuncSeparate_remap_index, -1 },
+ { VertexAttrib4ivARB_names, VertexAttrib4ivARB_remap_index, -1 },
+ { VertexAttrib4bvARB_names, VertexAttrib4bvARB_remap_index, -1 },
+ { VertexAttrib3dARB_names, VertexAttrib3dARB_remap_index, -1 },
+ { VertexAttrib4fARB_names, VertexAttrib4fARB_remap_index, -1 },
+ { VertexAttrib4fvARB_names, VertexAttrib4fvARB_remap_index, -1 },
+ { GetActiveUniformARB_names, GetActiveUniformARB_remap_index, -1 },
+ { IsShader_names, IsShader_remap_index, -1 },
+ { GetUniformivARB_names, GetUniformivARB_remap_index, -1 },
+ { IsProgram_names, IsProgram_remap_index, -1 },
+ { Uniform2fvARB_names, Uniform2fvARB_remap_index, -1 },
+ { ValidateProgramARB_names, ValidateProgramARB_remap_index, -1 },
+ { VertexAttrib2dARB_names, VertexAttrib2dARB_remap_index, -1 },
+ { VertexAttrib1dvARB_names, VertexAttrib1dvARB_remap_index, -1 },
+ { GetVertexAttribfvARB_names, GetVertexAttribfvARB_remap_index, -1 },
+ { GetAttribLocationARB_names, GetAttribLocationARB_remap_index, -1 },
+ { VertexAttrib4ubvARB_names, VertexAttrib4ubvARB_remap_index, -1 },
+ { Uniform3ivARB_names, Uniform3ivARB_remap_index, -1 },
+ { VertexAttrib4sARB_names, VertexAttrib4sARB_remap_index, -1 },
+ { VertexAttrib2dvARB_names, VertexAttrib2dvARB_remap_index, -1 },
+ { VertexAttrib2fvARB_names, VertexAttrib2fvARB_remap_index, -1 },
+ { VertexAttrib4NivARB_names, VertexAttrib4NivARB_remap_index, -1 },
+ { GetAttachedShaders_names, GetAttachedShaders_remap_index, -1 },
+ { CompileShaderARB_names, CompileShaderARB_remap_index, -1 },
+ { DeleteShader_names, DeleteShader_remap_index, -1 },
+ { Uniform3fARB_names, Uniform3fARB_remap_index, -1 },
+ { VertexAttrib4NuivARB_names, VertexAttrib4NuivARB_remap_index, -1 },
+ { Uniform4fARB_names, Uniform4fARB_remap_index, -1 },
+ { VertexAttrib1dARB_names, VertexAttrib1dARB_remap_index, -1 },
+ { VertexAttrib4usvARB_names, VertexAttrib4usvARB_remap_index, -1 },
+ { LinkProgramARB_names, LinkProgramARB_remap_index, -1 },
+ { ShaderSourceARB_names, ShaderSourceARB_remap_index, -1 },
+ { VertexAttrib3svARB_names, VertexAttrib3svARB_remap_index, -1 },
+ { Uniform4ivARB_names, Uniform4ivARB_remap_index, -1 },
+ { GetVertexAttribdvARB_names, GetVertexAttribdvARB_remap_index, -1 },
+ { Uniform1ivARB_names, Uniform1ivARB_remap_index, -1 },
+ { VertexAttrib4dvARB_names, VertexAttrib4dvARB_remap_index, -1 },
+ { BindAttribLocationARB_names, BindAttribLocationARB_remap_index, -1 },
+ { Uniform1iARB_names, Uniform1iARB_remap_index, -1 },
+ { VertexAttribPointerARB_names, VertexAttribPointerARB_remap_index, -1 },
+ { VertexAttrib4NsvARB_names, VertexAttrib4NsvARB_remap_index, -1 },
+ { VertexAttrib3fvARB_names, VertexAttrib3fvARB_remap_index, -1 },
+ { CreateShader_names, CreateShader_remap_index, -1 },
+ { DetachShader_names, DetachShader_remap_index, -1 },
+ { VertexAttrib4NubARB_names, VertexAttrib4NubARB_remap_index, -1 },
+ { Uniform4fvARB_names, Uniform4fvARB_remap_index, -1 },
+ { GetUniformfvARB_names, GetUniformfvARB_remap_index, -1 },
+ { Uniform4iARB_names, Uniform4iARB_remap_index, -1 },
+ { UseProgramObjectARB_names, UseProgramObjectARB_remap_index, -1 },
+ { DeleteProgram_names, DeleteProgram_remap_index, -1 },
+ { GetVertexAttribPointervNV_names, GetVertexAttribPointervNV_remap_index, -1 },
+ { Uniform2iARB_names, Uniform2iARB_remap_index, -1 },
+ { VertexAttrib4dARB_names, VertexAttrib4dARB_remap_index, -1 },
+ { GetUniformLocationARB_names, GetUniformLocationARB_remap_index, -1 },
+ { VertexAttrib3sARB_names, VertexAttrib3sARB_remap_index, -1 },
+ { GetShaderSourceARB_names, GetShaderSourceARB_remap_index, -1 },
+ { DrawBuffersARB_names, DrawBuffersARB_remap_index, -1 },
+ { Uniform1fvARB_names, Uniform1fvARB_remap_index, -1 },
+ { EnableVertexAttribArrayARB_names, EnableVertexAttribArrayARB_remap_index, -1 },
+ { VertexAttrib4uivARB_names, VertexAttrib4uivARB_remap_index, -1 },
+ { VertexAttrib4svARB_names, VertexAttrib4svARB_remap_index, -1 },
+ { GetShaderiv_names, GetShaderiv_remap_index, -1 },
+ { VertexAttrib2svARB_names, VertexAttrib2svARB_remap_index, -1 },
+ { VertexAttrib4NubvARB_names, VertexAttrib4NubvARB_remap_index, -1 },
+ { VertexAttrib2sARB_names, VertexAttrib2sARB_remap_index, -1 },
+ { VertexAttrib1fvARB_names, VertexAttrib1fvARB_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
+#if defined(need_GL_VERSION_2_1)
+static const struct dri_extension_function GL_VERSION_2_1_functions[] = {
+ { UniformMatrix2x4fv_names, UniformMatrix2x4fv_remap_index, -1 },
+ { UniformMatrix4x3fv_names, UniformMatrix4x3fv_remap_index, -1 },
+ { UniformMatrix4x2fv_names, UniformMatrix4x2fv_remap_index, -1 },
+ { UniformMatrix2x3fv_names, UniformMatrix2x3fv_remap_index, -1 },
+ { UniformMatrix3x4fv_names, UniformMatrix3x4fv_remap_index, -1 },
+ { UniformMatrix3x2fv_names, UniformMatrix3x2fv_remap_index, -1 },
+ { NULL, 0, 0 }
+};
+#endif
+
diff --git a/mesalib/src/mesa/drivers/dri/common/memops.h b/mesalib/src/mesa/drivers/dri/common/memops.h
new file mode 100644
index 000000000..9cd1d8ec3
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/memops.h
@@ -0,0 +1,17 @@
+#ifndef DRIMEMSETIO_H
+#define DRIMEMSETIO_H
+/*
+* memset an area in I/O space
+* We need to be careful about this on some archs
+*/
+static INLINE void drimemsetio(void* address, int c, int size)
+{
+#if defined(__powerpc__) || defined(__ia64__)
+ int i;
+ for(i=0;i<size;i++)
+ *((char *)address + i)=c;
+#else
+ memset(address,c,size);
+#endif
+}
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/mmio.h b/mesalib/src/mesa/drivers/dri/common/mmio.h
new file mode 100644
index 000000000..ce95d8c90
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/mmio.h
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file mmio.h
+ * Functions for properly handling memory mapped IO on various platforms.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+#ifndef MMIO_H
+#define MMIO_H
+
+#include "main/glheader.h"
+
+#if defined( __powerpc__ )
+
+static INLINE uint32_t
+read_MMIO_LE32( volatile void * base, unsigned long offset )
+{
+ uint32_t val;
+
+ __asm__ __volatile__( "lwbrx %0, %1, %2 ; eieio"
+ : "=r" (val)
+ : "b" (base), "r" (offset) );
+ return val;
+}
+
+#else
+
+static INLINE uint32_t
+read_MMIO_LE32( volatile void * base, unsigned long offset )
+{
+ volatile uint32_t * p = (volatile uint32_t *) (((volatile char *) base) + offset);
+ return LE32_TO_CPU( p[0] );
+}
+
+#endif
+
+#endif /* MMIO_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/mmx.h b/mesalib/src/mesa/drivers/dri/common/mmx.h
new file mode 100644
index 000000000..49ce7e3e3
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/mmx.h
@@ -0,0 +1,560 @@
+/* mmx.h
+
+ MultiMedia eXtensions GCC interface library for IA32.
+
+ To use this library, simply include this header file
+ and compile with GCC. You MUST have inlining enabled
+ in order for mmx_ok() to work; this can be done by
+ simply using -O on the GCC command line.
+
+ Compiling with -DMMX_TRACE will cause detailed trace
+ output to be sent to stderr for each mmx operation.
+ This adds lots of code, and obviously slows execution to
+ a crawl, but can be very useful for debugging.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR ANY PARTICULAR PURPOSE.
+
+ 1997-98 by H. Dietz and R. Fisher
+
+ History:
+ 97-98* R.Fisher Early versions
+ 980501 R.Fisher Original Release
+ 980611* H.Dietz Rewrite, correctly implementing inlines, and
+ R.Fisher including direct register accesses.
+ 980616 R.Fisher Release of 980611 as 980616.
+ 980714 R.Fisher Minor corrections to Makefile, etc.
+ 980715 R.Fisher mmx_ok() now prevents optimizer from using
+ clobbered values.
+ mmx_ok() now checks if cpuid instruction is
+ available before trying to use it.
+ 980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix
+ Extended MMX, and standard MMX. It returns a
+ value which is positive if any of these are
+ supported, and can be masked with constants to
+ see which. mmx_ok() is now a call to this
+ 980726* R.Fisher Added i2r support for shift functions
+ 980919 R.Fisher Fixed AMD extended feature recognition bug.
+ 980921 R.Fisher Added definition/check for _MMX_H.
+ Added "float s[2]" to mmx_t for use with
+ 3DNow and EMMX. So same mmx_t can be used.
+ 981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg)
+ Fixed psllq_i2r error in mmxtest.c
+
+ * Unreleased (internal or interim) versions
+
+ Notes:
+ It appears that the latest gas has the pand problem fixed, therefore
+ I'll undefine BROKEN_PAND by default.
+ String compares may be quicker than the multiple test/jumps in vendor
+ test sequence in mmx_ok(), but I'm not concerned with that right now.
+
+ Acknowledgments:
+ Jussi Laako for pointing out the errors ultimately found to be
+ connected to the failure to notify the optimizer of clobbered values.
+ Roger Hardiman for reminding us that CPUID isn't everywhere, and that
+ someone may actually try to use this on a machine without CPUID.
+ Also for suggesting code for checking this.
+ Robert Dale for pointing out the AMD recognition bug.
+ Jimmy Mayfield and Carl Witty for pointing out the Intel recognition
+ bug.
+ Carl Witty for pointing out the psllq_i2r test bug.
+*/
+
+#ifndef _MMX_H
+#define _MMX_H
+
+//#define MMX_TRACE
+
+/* Warning: at this writing, the version of GAS packaged
+ with most Linux distributions does not handle the
+ parallel AND operation mnemonic correctly. If the
+ symbol BROKEN_PAND is defined, a slower alternative
+ coding will be used. If execution of mmxtest results
+ in an illegal instruction fault, define this symbol.
+*/
+#undef BROKEN_PAND
+
+
+/* The type of an value that fits in an MMX register
+ (note that long long constant values MUST be suffixed
+ by LL and unsigned long long values by ULL, lest
+ they be truncated by the compiler)
+*/
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} mmx_t;
+
+/* Helper functions for the instruction macros that follow...
+ (note that memory-to-register, m2r, instructions are nearly
+ as efficient as register-to-register, r2r, instructions;
+ however, memory-to-memory instructions are really simulated
+ as a convenience, and are only 1/3 as efficient)
+*/
+#ifdef MMX_TRACE
+
+/* Include the stuff for printing a trace to stderr...
+*/
+
+#include <stdio.h>
+
+#define mmx_i2r(op, imm, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (imm); \
+ fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (imm)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_m2r(op, mem, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mem); \
+ fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_r2m(op, reg, mem) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ ); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_r2r(op, regs, regd) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #regs ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_m2m(op, mems, memd) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mems); \
+ fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (memd) \
+ : "X" (mems)); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#else
+
+/* These macros are a lot simpler without the tracing...
+*/
+
+#define mmx_i2r(op, imm, reg) \
+ __asm__ __volatile__ (#op " $" #imm ", %%" #reg \
+ : /* nothing */ \
+ : /* nothing */);
+
+#define mmx_m2r(op, mem, reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem))
+
+#define mmx_r2m(op, reg, mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op, regs, regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+#define mmx_m2m(op, mems, memd) \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (memd) \
+ : "X" (mems))
+
+#endif
+
+
+/* 1x64 MOVe Quadword
+ (this is both a load and a store...
+ in fact, it is the only way to store)
+*/
+#define movq_m2r(var, reg) mmx_m2r(movq, var, reg)
+#define movq_r2m(reg, var) mmx_r2m(movq, reg, var)
+#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd)
+#define movq(vars, vard) \
+ __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 1x32 MOVe Doubleword
+ (like movq, this is both load and store...
+ but is most useful for moving things between
+ mmx registers and ordinary registers)
+*/
+#define movd_m2r(var, reg) mmx_m2r(movd, var, reg)
+#define movd_r2m(reg, var) mmx_r2m(movd, reg, var)
+#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd)
+#define movd(vars, vard) \
+ __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
+ "movd %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 2x32, 4x16, and 8x8 Parallel ADDs
+*/
+#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg)
+#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd)
+#define paddd(vars, vard) mmx_m2m(paddd, vars, vard)
+
+#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg)
+#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd)
+#define paddw(vars, vard) mmx_m2m(paddw, vars, vard)
+
+#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg)
+#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd)
+#define paddb(vars, vard) mmx_m2m(paddb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic
+*/
+#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg)
+#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd)
+#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard)
+
+#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg)
+#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd)
+#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
+*/
+#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg)
+#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
+#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard)
+
+#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg)
+#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
+#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel SUBs
+*/
+#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg)
+#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd)
+#define psubd(vars, vard) mmx_m2m(psubd, vars, vard)
+
+#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg)
+#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd)
+#define psubw(vars, vard) mmx_m2m(psubw, vars, vard)
+
+#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg)
+#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd)
+#define psubb(vars, vard) mmx_m2m(psubb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic
+*/
+#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg)
+#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd)
+#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard)
+
+#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg)
+#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd)
+#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
+*/
+#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg)
+#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
+#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard)
+
+#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg)
+#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
+#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard)
+
+
+/* 4x16 Parallel MULs giving Low 4x16 portions of results
+*/
+#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg)
+#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd)
+#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard)
+
+
+/* 4x16 Parallel MULs giving High 4x16 portions of results
+*/
+#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg)
+#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd)
+#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard)
+
+
+/* 4x16->2x32 Parallel Mul-ADD
+ (muls like pmullw, then adds adjacent 16-bit fields
+ in the multiply result to make the final 2x32 result)
+*/
+#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg)
+#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
+#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard)
+
+
+/* 1x64 bitwise AND
+*/
+#ifdef BROKEN_PAND
+#define pand_m2r(var, reg) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, reg); \
+ mmx_m2r(pandn, var, reg); \
+ }
+#define pand_r2r(regs, regd) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, regd); \
+ mmx_r2r(pandn, regs, regd) \
+ }
+#define pand(vars, vard) \
+ { \
+ movq_m2r(vard, mm0); \
+ mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
+ mmx_m2r(pandn, vars, mm0); \
+ movq_r2m(mm0, vard); \
+ }
+#else
+#define pand_m2r(var, reg) mmx_m2r(pand, var, reg)
+#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd)
+#define pand(vars, vard) mmx_m2m(pand, vars, vard)
+#endif
+
+
+/* 1x64 bitwise AND with Not the destination
+*/
+#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg)
+#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd)
+#define pandn(vars, vard) mmx_m2m(pandn, vars, vard)
+
+
+/* 1x64 bitwise OR
+*/
+#define por_m2r(var, reg) mmx_m2r(por, var, reg)
+#define por_r2r(regs, regd) mmx_r2r(por, regs, regd)
+#define por(vars, vard) mmx_m2m(por, vars, vard)
+
+
+/* 1x64 bitwise eXclusive OR
+*/
+#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg)
+#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd)
+#define pxor(vars, vard) mmx_m2m(pxor, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
+#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard)
+
+#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
+#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard)
+
+#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
+#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
+#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard)
+
+#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
+#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard)
+
+#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
+#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical
+*/
+#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg)
+#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg)
+#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd)
+#define psllq(vars, vard) mmx_m2m(psllq, vars, vard)
+
+#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg)
+#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg)
+#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd)
+#define pslld(vars, vard) mmx_m2m(pslld, vars, vard)
+
+#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg)
+#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg)
+#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd)
+#define psllw(vars, vard) mmx_m2m(psllw, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical
+*/
+#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg)
+#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg)
+#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd)
+#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard)
+
+#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg)
+#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg)
+#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd)
+#define psrld(vars, vard) mmx_m2m(psrld, vars, vard)
+
+#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg)
+#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg)
+#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd)
+#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard)
+
+
+/* 2x32 and 4x16 Parallel Shift Right Arithmetic
+*/
+#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg)
+#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg)
+#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd)
+#define psrad(vars, vard) mmx_m2m(psrad, vars, vard)
+
+#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg)
+#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg)
+#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd)
+#define psraw(vars, vard) mmx_m2m(psraw, vars, vard)
+
+
+/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg)
+#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
+#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard)
+
+#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg)
+#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
+#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard)
+
+
+/* 4x16->8x8 PACK and Unsigned Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg)
+#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
+#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
+ (interleaves low half of dest with low half of source
+ as padding in each result field)
+*/
+#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
+#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
+#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard)
+
+#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
+#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
+#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard)
+
+#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
+#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
+#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
+ (interleaves high half of dest with high half of source
+ as padding in each result field)
+*/
+#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
+#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
+#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard)
+
+#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
+#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
+#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard)
+
+#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
+#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
+#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard)
+
+
+/* Empty MMx State
+ (used to clean-up when going from mmx to float use
+ of the registers that are shared by both; note that
+ there is no float-to-mmx operation needed, because
+ only the float tag word info is corruptible)
+*/
+#ifdef MMX_TRACE
+
+#define emms() \
+ { \
+ fprintf(stderr, "emms()\n"); \
+ __asm__ __volatile__ ("emms"); \
+ }
+
+#else
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#endif
+
+#endif
+
diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp.h b/mesalib/src/mesa/drivers/dri/common/spantmp.h
new file mode 100644
index 000000000..d5608b880
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/spantmp.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2002, 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_READ_CLIPLOOP
+#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifndef HW_WRITE_CLIPLOOP
+#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+
+static void TAG(WriteRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLuint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++)
+ {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ y = Y_FLIP( y );
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_PIXEL( x1, y, p );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_PIXEL( x1, y, p );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLuint i;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(ReadRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,x1++,n1--)
+ READ_RGBA( rgba[i], x1, y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+static void TAG(ReadRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ const GLubyte *mask = NULL; /* remove someday */
+ GLuint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+static void TAG(InitPointers)(struct gl_renderbuffer *rb)
+{
+ rb->PutRow = TAG(WriteRGBASpan);
+ rb->PutRowRGB = TAG(WriteRGBSpan);
+ rb->PutMonoRow = TAG(WriteMonoRGBASpan);
+ rb->PutValues = TAG(WriteRGBAPixels);
+ rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
+ rb->GetValues = TAG(ReadRGBAPixels);
+ rb->GetRow = TAG(ReadRGBASpan);
+}
+
+
+#undef WRITE_PIXEL
+#undef WRITE_RGBA
+#undef READ_RGBA
+#undef TAG
diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp2.h b/mesalib/src/mesa/drivers/dri/common/spantmp2.h
new file mode 100644
index 000000000..89c815722
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/spantmp2.h
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file spantmp2.h
+ *
+ * Template file of span read / write functions.
+ *
+ * \author Keith Whitwell <keithw@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@nvidia.com>
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "main/colormac.h"
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_READ_CLIPLOOP
+#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifndef HW_WRITE_CLIPLOOP
+#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#if (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
+
+/**
+ ** GL_RGB, GL_UNSIGNED_SHORT_5_6_5
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, ((((int)r & 0xf8) << 8) | \
+ (((int)g & 0xfc) << 3) | \
+ (((int)b & 0xf8) >> 3))) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_4_4_4_4_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_4444(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_4444(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 8) & 0xf) * 0x11; \
+ rgba[1] = ((p >> 4) & 0xf) * 0x11; \
+ rgba[2] = ((p >> 0) & 0xf) * 0x11; \
+ rgba[3] = ((p >> 12) & 0xf) * 0x11; \
+ } while (0)
+
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_1_5_5_5_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) (buf + (_x) * 2 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_1555(color[3], color[0], color[1], color[2])
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ PUT_VALUE(_x, _y, PACK_COLOR_1555(a, r, g, b)) \
+
+#define WRITE_PIXEL( _x, _y, p ) PUT_VALUE(_x, _y, p)
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = GET_VALUE(_x, _y); \
+ rgba[0] = ((p >> 7) & 0xf8) * 255 / 0xf8; \
+ rgba[1] = ((p >> 2) & 0xf8) * 255 / 0xf8; \
+ rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ rgba[3] = ((p >> 15) & 0x1) * 0xff; \
+ } while (0)
+
+#elif (SPANTMP_PIXEL_FMT == GL_BGRA) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+
+/**
+ ** GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV
+ **/
+
+#ifndef GET_VALUE
+#ifndef GET_PTR
+#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch)
+#endif
+
+#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y))
+#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v)
+#endif /* GET_VALUE */
+
+# define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888(color[3], color[0], color[1], color[2])
+
+# define WRITE_RGBA(_x, _y, r, g, b, a) \
+ PUT_VALUE(_x, _y, ((r << 16) | \
+ (g << 8) | \
+ (b << 0) | \
+ (a << 24)))
+
+#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p)
+
+# if defined( USE_X86_ASM )
+# define READ_RGBA(rgba, _x, _y) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ __asm__ __volatile__( "bswap %0; rorl $8, %0" \
+ : "=r" (p) : "0" (p) ); \
+ ((GLuint *)rgba)[0] = p; \
+ } while (0)
+# elif defined( MESA_BIG_ENDIAN )
+ /* On PowerPC with GCC 3.4.2 the shift madness below becomes a single
+ * rotlwi instruction. It also produces good code on SPARC.
+ */
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ GLuint t = p; \
+ *((uint32_t *) rgba) = (t >> 24) | (p << 8); \
+ } while (0)
+# else
+# define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = GET_VALUE(_x, _y); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+ } while (0)
+# endif
+
+#else
+#error SPANTMP_PIXEL_FMT must be set to a valid value!
+#endif
+
+
+
+/**
+ ** Assembly routines.
+ **/
+
+#if defined( USE_MMX_ASM ) || defined( USE_SSE_ASM )
+#include "x86/read_rgba_span_x86.h"
+#include "x86/common_x86_asm.h"
+#endif
+
+static void TAG(WriteRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++)
+ {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ y = Y_FLIP( y );
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_PIXEL( x1, y, p );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_PIXEL( x1, y, p );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *color = (const GLubyte *) value;
+ GLint i;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(ReadRGBASpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,x1++,n1--)
+ READ_RGBA( rgba[i], x1, y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+#if defined(GET_PTR) && \
+ defined(USE_MMX_ASM) && \
+ (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
+ ((SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
+static void TAG2(ReadRGBASpan,_MMX)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, void *values)
+{
+#ifndef USE_INNER_EMMS
+ /* The EMMS instruction is directly in-lined here because using GCC's
+ * built-in _mm_empty function was found to utterly destroy performance.
+ */
+ __asm__ __volatile__( "emms" );
+#endif
+
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+#if (SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)
+ _generic_read_RGBA_span_RGB565_MMX( src, rgba[i], n1 );
+#else
+ _generic_read_RGBA_span_BGRA8888_REV_MMX( src, rgba[i], n1 );
+#endif
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+#ifndef USE_INNER_EMMS
+ __asm__ __volatile__( "emms" );
+#endif
+}
+#endif
+
+
+#if defined(GET_PTR) && \
+ defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+static void TAG2(ReadRGBASpan,_SSE2)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+ _generic_read_RGBA_span_BGRA8888_REV_SSE2( src, rgba[i], n1 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+#endif
+
+#if defined(GET_PTR) && \
+ defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+static void TAG2(ReadRGBASpan,_SSE)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+#ifndef USE_INNER_EMMS
+ /* The EMMS instruction is directly in-lined here because using GCC's
+ * built-in _mm_empty function was found to utterly destroy performance.
+ */
+ __asm__ __volatile__( "emms" );
+#endif
+
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ {
+ const void * src = GET_PTR( x1, y );
+ _generic_read_RGBA_span_BGRA8888_REV_SSE( src, rgba[i], n1 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+#ifndef USE_INNER_EMMS
+ __asm__ __volatile__( "emms" );
+#endif
+}
+#endif
+
+
+static void TAG(ReadRGBAPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
+ GLubyte *mask = NULL; /* remove someday */
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(InitPointers)(struct gl_renderbuffer *rb)
+{
+ rb->PutRow = TAG(WriteRGBASpan);
+ rb->PutRowRGB = TAG(WriteRGBSpan);
+ rb->PutMonoRow = TAG(WriteMonoRGBASpan);
+ rb->PutValues = TAG(WriteRGBAPixels);
+ rb->PutMonoValues = TAG(WriteMonoRGBAPixels);
+ rb->GetValues = TAG(ReadRGBAPixels);
+
+#if defined(GET_PTR)
+#if defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+ if ( cpu_has_xmm2 ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE2" );
+ rb->GetRow = TAG2(ReadRGBASpan, _SSE2);
+ }
+ else
+#endif
+#if defined(USE_SSE_ASM) && \
+ (SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)
+ if ( cpu_has_xmm ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "SSE" );
+ rb->GetRow = TAG2(ReadRGBASpan, _SSE);
+ }
+ else
+#endif
+#if defined(USE_MMX_ASM) && \
+ (((SPANTMP_PIXEL_FMT == GL_BGRA) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_INT_8_8_8_8_REV)) || \
+ ((SPANTMP_PIXEL_FMT == GL_RGB) && \
+ (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5)))
+ if ( cpu_has_mmx ) {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "MMX" );
+ rb->GetRow = TAG2(ReadRGBASpan, _MMX);
+ }
+ else
+#endif
+#endif /* GET_PTR */
+ {
+ if (DBG) fprintf( stderr, "Using %s version of GetRow\n", "C" );
+ rb->GetRow = TAG(ReadRGBASpan);
+ }
+
+}
+
+
+#undef INIT_MONO_PIXEL
+#undef WRITE_PIXEL
+#undef WRITE_RGBA
+#undef READ_RGBA
+#undef TAG
+#undef TAG2
+#undef GET_VALUE
+#undef PUT_VALUE
+#undef GET_PTR
+#undef SPANTMP_PIXEL_FMT
+#undef SPANTMP_PIXEL_TYPE
diff --git a/mesalib/src/mesa/drivers/dri/common/spantmp_common.h b/mesalib/src/mesa/drivers/dri/common/spantmp_common.h
new file mode 100644
index 000000000..a4509a569
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/spantmp_common.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file spantmp_common.h
+ *
+ * common macros for span read / write functions to be used in the depth,
+ * stencil and pixel span templates.
+ */
+
+#ifndef HW_WRITE_LOCK
+#define HW_WRITE_LOCK() HW_LOCK()
+#endif
+
+#ifndef HW_WRITE_UNLOCK
+#define HW_WRITE_UNLOCK() HW_UNLOCK()
+#endif
+
+#ifndef HW_READ_LOCK
+#define HW_READ_LOCK() HW_LOCK()
+#endif
+
+#ifndef HW_READ_UNLOCK
+#define HW_READ_UNLOCK() HW_UNLOCK()
+#endif
+
+#ifndef HW_CLIPLOOP
+#define HW_CLIPLOOP() \
+ do { \
+ int _nc = dPriv->numClipRects; \
+ while ( _nc-- ) { \
+ int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
+ int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
+ int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
+ int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+#endif
+
+#ifndef HW_ENDCLIPLOOP
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+#endif
+
+#ifndef CLIPPIXEL
+#define CLIPPIXEL( _x, _y ) \
+ ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+#endif
+
+#ifndef CLIPSPAN
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy /*|| _x + n < minx || _x >=maxx*/ ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+ if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
+ }
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/stenciltmp.h b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h
new file mode 100644
index 000000000..2b10b9ecf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/stenciltmp.h
@@ -0,0 +1,245 @@
+
+#include "spantmp_common.h"
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HAVE_HW_STENCIL_SPANS
+#define HAVE_HW_STENCIL_SPANS 0
+#endif
+
+#ifndef HAVE_HW_STENCIL_PIXELS
+#define HAVE_HW_STENCIL_PIXELS 0
+#endif
+
+static void TAG(WriteStencilSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *stencil = (const GLubyte *) values;
+ GLint x1;
+ GLint n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+#if HAVE_HW_STENCIL_SPANS
+ (void) x1; (void) n1;
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan 0..%d (x1 %d)\n",
+ (int)n1, (int)x1);
+
+ WRITE_STENCIL_SPAN();
+#else /* HAVE_HW_STENCIL_SPANS */
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_SPANS */
+ }
+ HW_WRITE_UNLOCK();
+}
+
+#if HAVE_HW_STENCIL_SPANS
+/* implement MonoWriteDepthSpan() in terms of WriteDepthSpan() */
+static void
+TAG(WriteMonoStencilSpan)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+ const GLuint stenVal = *((GLuint *) value);
+ GLuint stens[MAX_WIDTH];
+ GLuint i;
+ for (i = 0; i < n; i++)
+ stens[i] = stenVal;
+ TAG(WriteStencilSpan)(ctx, rb, n, x, y, stens, mask);
+}
+#else /* HAVE_HW_STENCIL_SPANS */
+static void TAG(WriteMonoStencilSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const void *value,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte stencil = *((const GLubyte *) value);
+ GLint x1;
+ GLint n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_STENCIL( x1, y, stencil );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_STENCIL( x1, y, stencil );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+#endif /* !HAVE_HW_STENCIL_SPANS */
+
+
+static void TAG(WriteStencilPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ const GLubyte *stencil = (const GLubyte *) values;
+ GLuint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteStencilPixels\n");
+
+#if HAVE_HW_STENCIL_PIXELS
+ (void) i;
+
+ WRITE_STENCIL_PIXELS();
+#else /* HAVE_HW_STENCIL_PIXELS */
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_STENCIL( x[i], fy, stencil[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_PIXELS */
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+/* Read stencil spans and pixels
+ */
+static void TAG(ReadStencilSpan)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ void *values)
+{
+ HW_READ_LOCK()
+ {
+ GLubyte *stencil = (GLubyte *) values;
+ GLint x1,n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadStencilSpan\n");
+
+#if HAVE_HW_STENCIL_SPANS
+ (void) x1; (void) n1;
+
+ READ_STENCIL_SPAN();
+#else /* HAVE_HW_STENCIL_SPANS */
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,n1--)
+ READ_STENCIL( stencil[i], (x+i), y );
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_SPANS */
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(ReadStencilPixels)( GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ void *values )
+{
+ HW_READ_LOCK()
+ {
+ GLubyte *stencil = (GLubyte *) values;
+ GLuint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadStencilPixels\n");
+
+#if HAVE_HW_STENCIL_PIXELS
+ (void) i;
+
+ READ_STENCIL_PIXELS();
+#else /* HAVE_HW_STENCIL_PIXELS */
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_STENCIL( stencil[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif /* !HAVE_HW_STENCIL_PIXELS */
+ }
+ HW_READ_UNLOCK();
+}
+
+
+
+/**
+ * Initialize the given renderbuffer's span routines to point to
+ * the stencil functions we generated above.
+ */
+static void TAG(InitStencilPointers)(struct gl_renderbuffer *rb)
+{
+ rb->GetRow = TAG(ReadStencilSpan);
+ rb->GetValues = TAG(ReadStencilPixels);
+ rb->PutRow = TAG(WriteStencilSpan);
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = TAG(WriteMonoStencilSpan);
+ rb->PutValues = TAG(WriteStencilPixels);
+ rb->PutMonoValues = NULL;
+}
+
+
+#undef WRITE_STENCIL
+#undef READ_STENCIL
+#undef TAG
diff --git a/mesalib/src/mesa/drivers/dri/common/texmem.c b/mesalib/src/mesa/drivers/dri/common/texmem.c
new file mode 100644
index 000000000..b64618a03
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/texmem.c
@@ -0,0 +1,1347 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2002, 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+/** \file texmem.c
+ * Implements all of the device-independent texture memory management.
+ *
+ * Currently, only a simple LRU texture memory management policy is
+ * implemented. In the (hopefully very near) future, better policies will be
+ * implemented. The idea is that the DRI should be able to run in one of two
+ * modes. In the default mode the DRI will dynamically attempt to discover
+ * the best texture management policy for the running application. In the
+ * other mode, the user (via some sort of as yet TBD mechanism) will select
+ * a texture management policy that is known to work well with the
+ * application.
+ */
+
+#include "texmem.h"
+#include "main/simple_list.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+
+#include <assert.h>
+
+
+
+static unsigned dummy_swap_counter;
+
+
+/**
+ * Calculate \f$\log_2\f$ of a value. This is a particularly poor
+ * implementation of this function. However, since system performance is in
+ * no way dependent on this function, the slowness of the implementation is
+ * irrelevent.
+ *
+ * \param n Value whose \f$\log_2\f$ is to be calculated
+ */
+
+static GLuint
+driLog2( GLuint n )
+{
+ GLuint log2;
+
+ for ( log2 = 1 ; n > 1 ; log2++ ) {
+ n >>= 1;
+ }
+
+ return log2;
+}
+
+
+
+
+/**
+ * Determine if a texture is resident in textureable memory. Depending on
+ * the driver, this may or may not be on-card memory. It could be AGP memory
+ * or anyother type of memory from which the hardware can directly read
+ * texels.
+ *
+ * This function is intended to be used as the \c IsTextureResident function
+ * in the device's \c dd_function_table.
+ *
+ * \param ctx GL context pointer (currently unused)
+ * \param texObj Texture object to be tested
+ */
+
+GLboolean
+driIsTextureResident( GLcontext * ctx,
+ struct gl_texture_object * texObj )
+{
+ driTextureObject * t;
+
+
+ t = (driTextureObject *) texObj->DriverData;
+ return( (t != NULL) && (t->memBlock != NULL) );
+}
+
+
+
+
+/**
+ * (Re)initialize the global circular LRU list. The last element
+ * in the array (\a heap->nrRegions) is the sentinal. Keeping it
+ * at the end of the array allows the other elements of the array
+ * to be addressed rationally when looking up objects at a particular
+ * location in texture memory.
+ *
+ * \param heap Texture heap to be reset
+ */
+
+static void resetGlobalLRU( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << heap->logGranularity;
+ unsigned i;
+
+ for (i = 0 ; (i+1) * sz <= heap->size ; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = heap->nrRegions;
+ list[i].prev = i-1;
+ list[i].next = heap->nrRegions;
+ list[heap->nrRegions].prev = i;
+ list[heap->nrRegions].next = 0;
+ heap->global_age[0] = 0;
+}
+
+/**
+ * Print out debugging information about the local texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printLocalLRU( driTexHeap * heap, const char *callername )
+{
+ driTextureObject *t;
+ unsigned sz = 1U << heap->logGranularity;
+
+ fprintf( stderr, "%s in %s:\nLocal LRU, heap %d:\n",
+ __FUNCTION__, callername, heap->heapId );
+
+ foreach ( t, &heap->texture_objects ) {
+ if (!t->memBlock)
+ continue;
+ if (!t->tObj) {
+ fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs / sz,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ } else {
+ fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ }
+ }
+ foreach ( t, heap->swapped_objects ) {
+ if (!t->tObj) {
+ fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );
+ } else {
+ fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+/**
+ * Print out debugging information about the global texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printGlobalLRU( driTexHeap * heap, const char *callername )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned int i, j;
+
+ fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n",
+ __FUNCTION__, callername, heap->heapId, (void *)list );
+
+ for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ j, list[j].age, list[j].next, list[j].prev, list[j].in_use );
+ j = list[j].next;
+ if ( j == heap->nrRegions ) break;
+ }
+
+ if ( j != heap->nrRegions ) {
+ fprintf( stderr, "Loop detected in global LRU\n" );
+ for ( i = 0 ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ i, list[i].age, list[i].next, list[i].prev, list[i].in_use );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+
+/**
+ * Called by the client whenever it touches a local texture.
+ *
+ * \param t Texture object that the client has accessed
+ */
+
+void driUpdateTextureLRU( driTextureObject * t )
+{
+ driTexHeap * heap;
+ drmTextureRegionPtr list;
+ unsigned shift;
+ unsigned start;
+ unsigned end;
+ unsigned i;
+
+
+ heap = t->heap;
+ if ( heap != NULL ) {
+ shift = heap->logGranularity;
+ start = t->memBlock->ofs >> shift;
+ end = (t->memBlock->ofs + t->memBlock->size - 1) >> shift;
+
+
+ heap->local_age = ++heap->global_age[0];
+ list = heap->global_regions;
+
+
+ /* Update the context's local LRU
+ */
+
+ move_to_head( & heap->texture_objects, t );
+
+
+ for (i = start ; i <= end ; i++) {
+ list[i].age = heap->local_age;
+
+ /* remove_from_list(i)
+ */
+ list[(unsigned)list[i].next].prev = list[i].prev;
+ list[(unsigned)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i)
+ */
+ list[i].prev = heap->nrRegions;
+ list[i].next = list[heap->nrRegions].next;
+ list[(unsigned)list[heap->nrRegions].next].prev = i;
+ list[heap->nrRegions].next = i;
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+ }
+}
+
+
+
+
+/**
+ * Keep track of swapped out texture objects.
+ *
+ * \param t Texture object to be "swapped" out of its texture heap
+ */
+
+void driSwapOutTextureObject( driTextureObject * t )
+{
+ unsigned face;
+
+
+ if ( t->memBlock != NULL ) {
+ assert( t->heap != NULL );
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ t->heap->texture_swaps[0]++;
+ move_to_tail( t->heap->swapped_objects, t );
+ t->heap = NULL;
+ }
+ else {
+ assert( t->heap == NULL );
+ }
+
+
+ for ( face = 0 ; face < 6 ; face++ ) {
+ t->dirty_images[face] = ~0;
+ }
+}
+
+
+
+
+/**
+ * Destroy hardware state associated with texture \a t. Calls the
+ * \a destroy_texture_object method associated with the heap from which
+ * \a t was allocated.
+ *
+ * \param t Texture object to be destroyed
+ */
+
+void driDestroyTextureObject( driTextureObject * t )
+{
+ driTexHeap * heap;
+
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",
+ __FILE__, __LINE__,
+ (void *)t,
+ (void *)((t != NULL) ? t->tObj : NULL),
+ (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));
+ }
+
+ if ( t != NULL ) {
+ if ( t->memBlock ) {
+ heap = t->heap;
+ assert( heap != NULL );
+
+ heap->texture_swaps[0]++;
+
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ heap->destroy_texture_object( heap->driverContext, t );
+ t->heap = NULL;
+ }
+
+ if ( t->tObj != NULL ) {
+ assert( t->tObj->DriverData == t );
+ t->tObj->DriverData = NULL;
+ }
+
+ remove_from_list( t );
+ FREE( t );
+ }
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );
+ }
+}
+
+
+
+
+/**
+ * Update the local heap's representation of texture memory based on
+ * data in the SAREA. This is done each time it is detected that some other
+ * direct rendering client has held the lock. This pertains to both our local
+ * textures and the textures belonging to other clients. Keep track of other
+ * client's textures by pushing a placeholder texture onto the LRU list --
+ * these are denoted by \a tObj being \a NULL.
+ *
+ * \param heap Heap whose state is to be updated
+ * \param offset Byte offset in the heap that has been stolen
+ * \param size Size, in bytes, of the stolen block
+ * \param in_use Non-zero if the block is pinned/reserved by the kernel
+ */
+
+static void driTexturesGone( driTexHeap * heap, int offset, int size,
+ int in_use )
+{
+ driTextureObject * t;
+ driTextureObject * tmp;
+
+
+ foreach_s ( t, tmp, & heap->texture_objects ) {
+ if ( (t->memBlock->ofs < (offset + size))
+ && ((t->memBlock->ofs + t->memBlock->size) > offset) ) {
+ /* It overlaps - kick it out. If the texture object is just a
+ * place holder, then destroy it all together. Otherwise, mark
+ * it as being swapped out.
+ */
+
+ if ( t->tObj != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ driDestroyTextureObject( t );
+ }
+ }
+ }
+
+
+ {
+ t = (driTextureObject *) CALLOC( heap->texture_object_size );
+ if ( t == NULL ) return;
+
+ t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );
+ if ( t->memBlock == NULL ) {
+ fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,
+ (int)size, (int)offset );
+ mmDumpMemInfo( heap->memory_heap );
+ FREE(t);
+ return;
+ }
+ t->heap = heap;
+ if (in_use)
+ t->reserved = 1;
+ insert_at_head( & heap->texture_objects, t );
+ }
+}
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ */
+
+void driAgeTextures( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << (heap->logGranularity);
+ unsigned i, nr = 0;
+
+
+ /* Have to go right round from the back to ensure stuff ends up
+ * LRU in the local list... Fix with a cursor pointer.
+ */
+
+ for (i = list[heap->nrRegions].prev ;
+ i != heap->nrRegions && nr < heap->nrRegions ;
+ i = list[i].prev, nr++) {
+ /* If switching texturing schemes, then the SAREA might not have been
+ * properly cleared, so we need to reset the global texture LRU.
+ */
+
+ if ( (i * sz) > heap->size ) {
+ nr = heap->nrRegions;
+ break;
+ }
+
+ if (list[i].age > heap->local_age)
+ driTexturesGone( heap, i * sz, sz, list[i].in_use);
+ }
+
+ /* Loop or uninitialized heap detected. Reset.
+ */
+
+ if (nr == heap->nrRegions) {
+ driTexturesGone( heap, 0, heap->size, 0);
+ resetGlobalLRU( heap );
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+
+ heap->local_age = heap->global_age[0];
+}
+
+
+
+
+#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps */
+
+/**
+ * Allocate memory from a texture heap to hold a texture object. This
+ * routine will attempt to allocate memory for the texture from the heaps
+ * specified by \c heap_array in order. That is, first it will try to
+ * allocate from \c heap_array[0], then \c heap_array[1], and so on.
+ *
+ * \param heap_array Array of pointers to texture heaps to use
+ * \param nr_heaps Number of heap pointer in \a heap_array
+ * \param t Texture object for which space is needed
+ * \return The ID of the heap from which memory was allocated, or -1 if
+ * memory could not be allocated.
+ *
+ * \bug The replacement policy implemented by this function is horrible.
+ */
+
+
+int
+driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t )
+{
+ driTexHeap * heap;
+ driTextureObject * temp;
+ driTextureObject * cursor;
+ unsigned id;
+
+
+ /* In case it already has texture space, initialize heap. This also
+ * prevents GCC from issuing a warning that heap might be used
+ * uninitialized.
+ */
+
+ heap = t->heap;
+
+
+ /* Run through each of the existing heaps and try to allocate a buffer
+ * to hold the texture.
+ */
+
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
+ heap = heap_array[ id ];
+ if ( heap != NULL ) {
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+ }
+ }
+
+
+ /* Kick textures out until the requested texture fits.
+ */
+
+ if ( t->memBlock == NULL ) {
+ unsigned index[INDEX_ARRAY_SIZE];
+ unsigned nrGoodHeaps = 0;
+
+ /* Trying to avoid dynamic memory allocation. If you have more
+ * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any
+ * drivers with more than 2 tex heaps. */
+ assert( nr_heaps < INDEX_ARRAY_SIZE );
+
+ /* Sort large enough heaps by duty. Insertion sort should be
+ * fast enough for such a short array. */
+ for ( id = 0 ; id < nr_heaps ; id++ ) {
+ heap = heap_array[ id ];
+
+ if ( heap != NULL && t->totalSize <= heap->size ) {
+ unsigned j;
+
+ for ( j = 0 ; j < nrGoodHeaps; j++ ) {
+ if ( heap->duty > heap_array[ index[ j ] ]->duty )
+ break;
+ }
+
+ if ( j < nrGoodHeaps ) {
+ memmove( &index[ j+1 ], &index[ j ],
+ sizeof(index[ 0 ]) * (nrGoodHeaps - j) );
+ }
+
+ index[ j ] = id;
+
+ nrGoodHeaps++;
+ }
+ }
+
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) {
+ heap = heap_array[ index[ id ] ];
+
+ for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
+ cursor != &heap->texture_objects ;
+ cursor = temp, temp = cursor->prev ) {
+
+ /* The the LRU element. If the texture is bound to one of
+ * the texture units, then we cannot kick it out.
+ */
+ if ( cursor->bound || cursor->reserved ) {
+ continue;
+ }
+
+ if ( cursor->memBlock )
+ heap->duty -= cursor->memBlock->size;
+
+ /* If this is a placeholder, there's no need to keep it */
+ if (cursor->tObj)
+ driSwapOutTextureObject( cursor );
+ else
+ driDestroyTextureObject( cursor );
+
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+
+ if (t->memBlock)
+ break;
+ }
+ }
+
+ /* Rebalance duties. If a heap kicked more data than its duty,
+ * then all other heaps get that amount multiplied with their
+ * relative weight added to their duty. The negative duty is
+ * reset to 0. In the end all heaps have a duty >= 0.
+ *
+ * CAUTION: we must not change the heap pointer here, because it
+ * is used below to update the texture object.
+ */
+ for ( id = 0 ; id < nr_heaps ; id++ )
+ if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) {
+ int duty = -heap_array[ id ]->duty;
+ double weight = heap_array[ id ]->weight;
+ unsigned j;
+
+ for ( j = 0 ; j < nr_heaps ; j++ )
+ if ( j != id && heap_array[ j ] != NULL ) {
+ heap_array[ j ]->duty += (double) duty *
+ heap_array[ j ]->weight / weight;
+ }
+
+ heap_array[ id ]->duty = 0;
+ }
+ }
+
+
+ if ( t->memBlock != NULL ) {
+ /* id and heap->heapId may or may not be the same value here.
+ */
+
+ assert( heap != NULL );
+ assert( (t->heap == NULL) || (t->heap == heap) );
+
+ t->heap = heap;
+ return heap->heapId;
+ }
+ else {
+ assert( t->heap == NULL );
+
+ fprintf( stderr, "[%s:%d] unable to allocate texture\n",
+ __FUNCTION__, __LINE__ );
+ return -1;
+ }
+}
+
+
+
+
+
+
+/**
+ * Set the location where the texture-swap counter is stored.
+ */
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter )
+{
+ heap->texture_swaps = (counter == NULL) ? & dummy_swap_counter : counter;
+}
+
+
+
+
+/**
+ * Create a new heap for texture data.
+ *
+ * \param heap_id Device-dependent heap identifier. This value
+ * will returned by driAllocateTexture when memory
+ * is allocated from this heap.
+ * \param context Device-dependent driver context. This is
+ * supplied as the first parameter to the
+ * \c destroy_tex_obj function.
+ * \param size Size, in bytes, of the texture region
+ * \param alignmentShift Alignment requirement for textures. If textures
+ * must be allocated on a 4096 byte boundry, this
+ * would be 12.
+ * \param nr_regions Number of regions into which this texture space
+ * should be partitioned
+ * \param global_regions Array of \c drmTextureRegion structures in the SAREA
+ * \param global_age Pointer to the global texture age in the SAREA
+ * \param swapped_objects Pointer to the list of texture objects that are
+ * not in texture memory (i.e., have been swapped
+ * out).
+ * \param texture_object_size Size, in bytes, of a device-dependent texture
+ * object
+ * \param destroy_tex_obj Function used to destroy a device-dependent
+ * texture object
+ *
+ * \sa driDestroyTextureHeap
+ */
+
+driTexHeap *
+driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
+ unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects,
+ unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj
+ )
+{
+ driTexHeap * heap;
+ unsigned l;
+
+
+ if ( 0 )
+ fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",
+ __FUNCTION__,
+ heap_id, (void *)context, size, alignmentShift, nr_regions );
+
+ heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );
+ if ( heap != NULL ) {
+ l = driLog2( (size - 1) / nr_regions );
+ if ( l < alignmentShift )
+ {
+ l = alignmentShift;
+ }
+
+ heap->logGranularity = l;
+ heap->size = size & ~((1L << l) - 1);
+
+ heap->memory_heap = mmInit( 0, heap->size );
+ if ( heap->memory_heap != NULL ) {
+ heap->heapId = heap_id;
+ heap->driverContext = context;
+
+ heap->alignmentShift = alignmentShift;
+ heap->nrRegions = nr_regions;
+ heap->global_regions = global_regions;
+ heap->global_age = global_age;
+ heap->swapped_objects = swapped_objects;
+ heap->texture_object_size = texture_object_size;
+ heap->destroy_texture_object = destroy_tex_obj;
+
+ /* Force global heap init */
+ if (heap->global_age[0] == 0)
+ heap->local_age = ~0;
+ else
+ heap->local_age = 0;
+
+ make_empty_list( & heap->texture_objects );
+ driSetTextureSwapCounterLocation( heap, NULL );
+
+ heap->weight = heap->size;
+ heap->duty = 0;
+ }
+ else {
+ FREE( heap );
+ heap = NULL;
+ }
+ }
+
+
+ if ( 0 )
+ fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );
+
+ return heap;
+}
+
+
+
+
+/** Destroys a texture heap
+ *
+ * \param heap Texture heap to be destroyed
+ */
+
+void
+driDestroyTextureHeap( driTexHeap * heap )
+{
+ driTextureObject * t;
+ driTextureObject * temp;
+
+
+ if ( heap != NULL ) {
+ foreach_s( t, temp, & heap->texture_objects ) {
+ driDestroyTextureObject( t );
+ }
+ foreach_s( t, temp, heap->swapped_objects ) {
+ driDestroyTextureObject( t );
+ }
+
+ mmDestroy( heap->memory_heap );
+ FREE( heap );
+ }
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Determine how many texels (including all mipmap levels) would be required
+ * for a texture map of size \f$2^^\c base_size_log2\f$ would require.
+ *
+ * \param base_size_log2 \f$log_2\f$ of the size of a side of the texture
+ * \param dimensions Number of dimensions of the texture. Either 2 or 3.
+ * \param faces Number of faces of the texture. Either 1 or 6 (for cube maps).
+ * \return Number of texels
+ */
+
+static unsigned
+texels_this_map_size( int base_size_log2, unsigned dimensions, unsigned faces )
+{
+ unsigned texels;
+
+
+ assert( (faces == 1) || (faces == 6) );
+ assert( (dimensions == 2) || (dimensions == 3) );
+
+ texels = 0;
+ if ( base_size_log2 >= 0 ) {
+ texels = (1U << (dimensions * base_size_log2));
+
+ /* See http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg03636.html
+ * for the complete explaination of why this formulation is used.
+ * Basically, the smaller mipmap levels sum to 0.333 the size of the
+ * level 0 map. The total size is therefore the size of the map
+ * multipled by 1.333. The +2 is there to round up.
+ */
+
+ texels = (texels * 4 * faces + 2) / 3;
+ }
+
+ return texels;
+}
+
+
+
+
+struct maps_per_heap {
+ unsigned c[32];
+};
+
+static void
+fill_in_maximums( driTexHeap * const * heaps, unsigned nr_heaps,
+ unsigned max_bytes_per_texel, unsigned max_size,
+ unsigned mipmaps_at_once, unsigned dimensions,
+ unsigned faces, struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+ unsigned mask;
+
+
+ /* Determine how many textures of each size can be stored in each
+ * texture heap.
+ */
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ ) {
+ if ( heaps[ heap ] == NULL ) {
+ (void) memset( max_textures[ heap ].c, 0,
+ sizeof( max_textures[ heap ].c ) );
+ continue;
+ }
+
+ mask = (1U << heaps[ heap ]->logGranularity) - 1;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] heap[%u] = %u bytes, mask = 0x%08x\n",
+ __FILE__, __LINE__,
+ heap, heaps[ heap ]->size, mask );
+ }
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total;
+
+
+ /* Determine the total number of bytes required by a texture of
+ * size log2_size.
+ */
+
+ total = texels_this_map_size( log2_size, dimensions, faces )
+ - texels_this_map_size( log2_size - mipmaps_at_once,
+ dimensions, faces );
+ total *= max_bytes_per_texel;
+ total = (total + mask) & ~mask;
+
+ /* The number of textures of a given size that will fit in a heap
+ * is equal to the size of the heap divided by the size of the
+ * texture.
+ */
+
+ max_textures[ heap ].c[ log2_size ] = heaps[ heap ]->size / total;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] "
+ "= 0x%08x / 0x%08x "
+ "= %u (%u)\n",
+ __FILE__, __LINE__,
+ heap, log2_size,
+ heaps[ heap ]->size, total,
+ heaps[ heap ]->size / total,
+ max_textures[ heap ].c[ log2_size ] );
+ }
+ }
+ }
+}
+
+
+static unsigned
+get_max_size( unsigned nr_heaps,
+ unsigned texture_units,
+ unsigned max_size,
+ int all_textures_one_heap,
+ struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+
+
+ /* Determine the largest texture size such that a texture of that size
+ * can be bound to each texture unit at the same time. Some hardware
+ * may require that all textures be in the same texture heap for
+ * multitexturing.
+ */
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total = 0;
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ )
+ {
+ total += max_textures[ heap ].c[ log2_size ];
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] = %u, "
+ "total = %u\n", __FILE__, __LINE__, heap, log2_size,
+ max_textures[ heap ].c[ log2_size ], total );
+ }
+
+ if ( (max_textures[ heap ].c[ log2_size ] >= texture_units)
+ || (!all_textures_one_heap && (total >= texture_units)) ) {
+ /* The number of mipmap levels is the log-base-2 of the
+ * maximum texture size plus 1. If the maximum texture size
+ * is 1x1, the log-base-2 is 0 and 1 mipmap level (the base
+ * level) is available.
+ */
+
+ return log2_size + 1;
+ }
+ }
+ }
+
+ /* This should NEVER happen. It should always be possible to have at
+ * *least* a 1x1 texture in memory!
+ */
+ assert( log2_size != 0 );
+ return 0;
+}
+
+#define SET_MAX(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 )
+
+#define SET_MAX_RECT(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << (max_sizes[v] - 1); } } while( 0 )
+
+
+/**
+ * Given the amount of texture memory, the number of texture units, and the
+ * maximum size of a texel, calculate the maximum texture size the driver can
+ * advertise.
+ *
+ * \param heaps Texture heaps for this card
+ * \param nr_heap Number of texture heaps
+ * \param limits OpenGL contants. MaxTextureUnits must be set.
+ * \param max_bytes_per_texel Maximum size of a single texel, in bytes
+ * \param max_2D_size \f$\log_2\f$ of the maximum 2D texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_3D_size \f$\log_2\f$ of the maximum 3D texture size (i.e.,
+ * 1024x1024x1024 textures, this would be 10)
+ * \param max_cube_size \f$\log_2\f$ of the maximum cube texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_rect_size \f$\log_2\f$ of the maximum texture rectangle size
+ * (i.e., 1024x1024 textures, this would be 10). This is a power-of-2
+ * even though texture rectangles need not be a power-of-2.
+ * \param mipmaps_at_once Total number of mipmaps that can be used
+ * at one time. For most hardware this will be \f$\c max_size + 1\f$.
+ * For hardware that does not support mipmapping, this will be 1.
+ * \param all_textures_one_heap True if the hardware requires that all
+ * textures be in a single texture heap for multitexturing.
+ * \param allow_larger_textures 0 conservative, 1 calculate limits
+ * so at least one worst-case texture can fit, 2 just use hw limits.
+ */
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap,
+ int allow_larger_textures )
+{
+ struct maps_per_heap max_textures[8];
+ unsigned i;
+ const unsigned dimensions[4] = { 2, 3, 2, 2 };
+ const unsigned faces[4] = { 1, 1, 6, 1 };
+ unsigned max_sizes[4];
+ unsigned mipmaps[4];
+
+
+ max_sizes[0] = max_2D_size;
+ max_sizes[1] = max_3D_size;
+ max_sizes[2] = max_cube_size;
+ max_sizes[3] = max_rect_size;
+
+ mipmaps[0] = mipmaps_at_once;
+ mipmaps[1] = mipmaps_at_once;
+ mipmaps[2] = mipmaps_at_once;
+ mipmaps[3] = 1;
+
+
+ /* Calculate the maximum number of texture levels in two passes. The
+ * first pass determines how many textures of each power-of-two size
+ * (including all mipmap levels for that size) can fit in each texture
+ * heap. The second pass finds the largest texture size that allows
+ * a texture of that size to be bound to every texture unit.
+ */
+
+ for ( i = 0 ; i < 4 ; i++ ) {
+ if ( (allow_larger_textures != 2) && (max_sizes[ i ] != 0) ) {
+ fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel,
+ max_sizes[ i ], mipmaps[ i ],
+ dimensions[ i ], faces[ i ],
+ max_textures );
+
+ max_sizes[ i ] = get_max_size( nr_heaps,
+ allow_larger_textures == 1 ?
+ 1 : limits->MaxTextureUnits,
+ max_sizes[ i ],
+ all_textures_one_heap,
+ max_textures );
+ }
+ else if (max_sizes[ i ] != 0) {
+ max_sizes[ i ] += 1;
+ }
+ }
+
+ SET_MAX( MaxTextureLevels, 0 );
+ SET_MAX( Max3DTextureLevels, 1 );
+ SET_MAX( MaxCubeTextureLevels, 2 );
+ SET_MAX_RECT( MaxTextureRectSize, 3 );
+}
+
+
+
+
+/**
+ * Perform initial binding of default textures objects on a per unit, per
+ * texture target basis.
+ *
+ * \param ctx Current OpenGL context
+ * \param swapped List of swapped-out textures
+ * \param targets Bit-mask of value texture targets
+ */
+
+void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
+ GLuint targets )
+{
+ struct gl_texture_object *texObj;
+ GLuint tmp = ctx->Texture.CurrentUnit;
+ unsigned i;
+
+
+ for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
+ ctx->Texture.CurrentUnit = i;
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_1D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_2D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_3D_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_CUBE_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_RECT_INDEX];
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+ }
+
+ ctx->Texture.CurrentUnit = tmp;
+}
+
+
+
+
+/**
+ * Verify that the specified texture is in the specificed heap.
+ *
+ * \param tex Texture to be tested.
+ * \param heap Texture memory heap to be tested.
+ * \return True if the texture is in the heap, false otherwise.
+ */
+
+static GLboolean
+check_in_heap( const driTextureObject * tex, const driTexHeap * heap )
+{
+#if 1
+ return tex->heap == heap;
+#else
+ driTextureObject * curr;
+
+ foreach( curr, & heap->texture_objects ) {
+ if ( curr == tex ) {
+ break;
+ }
+ }
+
+ return curr == tex;
+#endif
+}
+
+
+
+/****************************************************************************/
+/**
+ * Validate the consistency of a set of texture heaps.
+ * Original version by Keith Whitwell in r200/r200_sanity.c.
+ */
+
+GLboolean
+driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped )
+{
+ driTextureObject *t;
+ unsigned i;
+
+ for ( i = 0 ; i < nr_heaps ; i++ ) {
+ int last_end = 0;
+ unsigned textures_in_heap = 0;
+ unsigned blocks_in_mempool = 0;
+ const driTexHeap * heap = texture_heaps[i];
+ const struct mem_block *p = heap->memory_heap;
+
+ /* Check each texture object has a MemBlock, and is linked into
+ * the correct heap.
+ *
+ * Check the texobj base address corresponds to the MemBlock
+ * range. Check the texobj size (recalculate?) fits within
+ * the MemBlock.
+ *
+ * Count the number of texobj's using this heap.
+ */
+
+ foreach ( t, &heap->texture_objects ) {
+ if ( !check_in_heap( t, heap ) ) {
+ fprintf( stderr, "%s memory block for texture object @ %p not "
+ "found in heap #%d\n",
+ __FUNCTION__, (void *)t, i );
+ return GL_FALSE;
+ }
+
+
+ if ( t->totalSize > t->memBlock->size ) {
+ fprintf( stderr, "%s: Memory block for texture object @ %p is "
+ "only %u bytes, but %u are required\n",
+ __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size );
+ return GL_FALSE;
+ }
+
+ textures_in_heap++;
+ }
+
+ /* Validate the contents of the heap:
+ * - Ordering
+ * - Overlaps
+ * - Bounds
+ */
+
+ while ( p != NULL ) {
+ if (p->reserved) {
+ fprintf( stderr, "%s: Block (%08x,%x), is reserved?!\n",
+ __FUNCTION__, p->ofs, p->size );
+ return GL_FALSE;
+ }
+
+ if (p->ofs != last_end) {
+ fprintf( stderr, "%s: blocks_in_mempool = %d, last_end = %d, p->ofs = %d\n",
+ __FUNCTION__, blocks_in_mempool, last_end, p->ofs );
+ return GL_FALSE;
+ }
+
+ if (!p->reserved && !p->free) {
+ blocks_in_mempool++;
+ }
+
+ last_end = p->ofs + p->size;
+ p = p->next;
+ }
+
+ if (textures_in_heap != blocks_in_mempool) {
+ fprintf( stderr, "%s: Different number of textures objects (%u) and "
+ "inuse memory blocks (%u)\n",
+ __FUNCTION__, textures_in_heap, blocks_in_mempool );
+ return GL_FALSE;
+ }
+
+#if 0
+ fprintf( stderr, "%s: textures_in_heap = %u\n",
+ __FUNCTION__, textures_in_heap );
+#endif
+ }
+
+
+ /* Check swapped texobj's have zero memblocks
+ */
+ i = 0;
+ foreach ( t, swapped ) {
+ if ( t->memBlock != NULL ) {
+ fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n",
+ __FUNCTION__, (void *)t, (void *)t->memBlock );
+ return GL_FALSE;
+ }
+ i++;
+ }
+
+#if 0
+ fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );
+#endif
+
+ return GL_TRUE;
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+
+void
+driCalculateTextureFirstLastLevel( driTextureObject * t )
+{
+ struct gl_texture_object * const tObj = t->tObj;
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[0][tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, t->tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, t->tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+}
+
+
+
+
+/**
+ * \name DRI texture formats. Pointers initialized to either the big- or
+ * little-endian Mesa formats.
+ */
+/*@{*/
+const struct gl_texture_format *_dri_texformat_rgba8888 = NULL;
+const struct gl_texture_format *_dri_texformat_argb8888 = NULL;
+const struct gl_texture_format *_dri_texformat_rgb565 = NULL;
+const struct gl_texture_format *_dri_texformat_argb4444 = NULL;
+const struct gl_texture_format *_dri_texformat_argb1555 = NULL;
+const struct gl_texture_format *_dri_texformat_al88 = NULL;
+const struct gl_texture_format *_dri_texformat_a8 = &_mesa_texformat_a8;
+const struct gl_texture_format *_dri_texformat_ci8 = &_mesa_texformat_ci8;
+const struct gl_texture_format *_dri_texformat_i8 = &_mesa_texformat_i8;
+const struct gl_texture_format *_dri_texformat_l8 = &_mesa_texformat_l8;
+/*@}*/
+
+
+/**
+ * Initialize little endian target, host byte order independent texture formats
+ */
+void
+driInitTextureFormats(void)
+{
+ const GLuint ui = 1;
+ const GLubyte littleEndian = *((const GLubyte *) &ui);
+
+ if (littleEndian) {
+ _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888;
+ _dri_texformat_argb8888 = &_mesa_texformat_argb8888;
+ _dri_texformat_rgb565 = &_mesa_texformat_rgb565;
+ _dri_texformat_argb4444 = &_mesa_texformat_argb4444;
+ _dri_texformat_argb1555 = &_mesa_texformat_argb1555;
+ _dri_texformat_al88 = &_mesa_texformat_al88;
+ }
+ else {
+ _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888_rev;
+ _dri_texformat_argb8888 = &_mesa_texformat_argb8888_rev;
+ _dri_texformat_rgb565 = &_mesa_texformat_rgb565_rev;
+ _dri_texformat_argb4444 = &_mesa_texformat_argb4444_rev;
+ _dri_texformat_argb1555 = &_mesa_texformat_argb1555_rev;
+ _dri_texformat_al88 = &_mesa_texformat_al88_rev;
+ }
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/texmem.h b/mesalib/src/mesa/drivers/dri/common/texmem.h
new file mode 100644
index 000000000..9c065da8b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/texmem.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+
+/** \file texmem.h
+ * Public interface to the DRI texture memory management routines.
+ *
+ * \sa texmem.c
+ */
+
+#ifndef DRI_TEXMEM_H
+#define DRI_TEXMEM_H
+
+#include "main/mtypes.h"
+#include "main/mm.h"
+#include "xf86drm.h"
+
+struct dri_tex_heap;
+typedef struct dri_tex_heap driTexHeap;
+
+struct dri_texture_object;
+typedef struct dri_texture_object driTextureObject;
+
+
+/**
+ * Base texture object type. Each driver will extend this type with its own
+ * private data members.
+ */
+
+struct dri_texture_object {
+ struct dri_texture_object * next;
+ struct dri_texture_object * prev;
+
+ driTexHeap * heap; /**< Texture heap currently stored in */
+ struct gl_texture_object * tObj;/**< Pointer to Mesa texture object
+ * If NULL, this texture object is a
+ * "placeholder" object representing
+ * texture memory in use by another context.
+ * A placeholder should have a heap and a memBlock.
+ */
+ struct mem_block *memBlock; /**< Memory block containing texture */
+
+ unsigned reserved; /**< Cannot be swapped out by user contexts. */
+
+ unsigned bound; /**< Bitmask indicating which tex units
+ * this texture object is bound to.
+ * Bit 0 = unit 0, Bit 1 = unit 1, etc
+ */
+
+ unsigned totalSize; /**< Total size of the texture,
+ * including all mipmap levels
+ */
+
+ unsigned dirty_images[6]; /**< Flags for whether or not images
+ * need to be uploaded to local or
+ * AGP texture space. One flag set
+ * for each cube face for cubic
+ * textures. Bit zero corresponds to
+ * the base-level, which may or may
+ * not be the level zero mipmap.
+ */
+
+ unsigned timestamp; /**< Timestamp used to
+ * synchronize with 3d engine
+ * in hardware where textures
+ * are uploaded directly to
+ * the framebuffer.
+ */
+
+ unsigned firstLevel; /**< Image in \c tObj->Image[0] that
+ * corresponds to the base-level of
+ * this texture object.
+ */
+
+ unsigned lastLevel; /**< Last image in \c tObj->Image[0]
+ * used by the
+ * current LOD settings of
+ * this texture object. This
+ * value must be greater than
+ * or equal to \c firstLevel.
+ */
+};
+
+
+typedef void (destroy_texture_object_t)( void * driverContext,
+ driTextureObject * t );
+
+/**
+ * Client-private representation of texture memory state.
+ *
+ * Clients will place one or more of these structs in their driver
+ * context struct to manage one or more global texture heaps.
+ */
+
+struct dri_tex_heap {
+
+ /** Client-supplied heap identifier
+ */
+ unsigned heapId;
+
+ /** Pointer to the client's private context
+ */
+ void *driverContext;
+
+ /** Total size of the heap, in bytes
+ */
+ unsigned size;
+
+ /** \brief \f$log_2\f$ of size of single heap region
+ *
+ * Each context takes memory from the global texture heap in
+ * \f$2^{logGranularity}\f$ byte blocks. The value of
+ * \a logGranularity is based on the amount of memory represented
+ * by the heap and the maximum number of regions in the SAREA. Given
+ * \a b bytes of texture memory an \a n regions in the SAREA,
+ * \a logGranularity will be \f$\lfloor\log_2( b / n )\rfloor\f$.
+ */
+ unsigned logGranularity;
+
+ /** \brief Required alignment of allocations in this heap
+ *
+ * The alignment shift is supplied to \a mmAllocMem when memory is
+ * allocated from this heap. The value of \a alignmentShift will
+ * typically reflect some require of the hardware. This value has
+ * \b no \b relation to \a logGranularity. \a alignmentShift is a
+ * per-context value.
+ *
+ * \sa mmAllocMem
+ */
+ unsigned alignmentShift;
+
+ /** Number of elements in global list (the SAREA).
+ */
+ unsigned nrRegions;
+
+ /** Pointer to SAREA \a driTexRegion array
+ */
+ drmTextureRegionPtr global_regions;
+
+ /** Pointer to the texture state age (generation number) in the SAREA
+ */
+ unsigned * global_age;
+
+ /** Local age (generation number) of texture state
+ */
+ unsigned local_age;
+
+ /** Memory heap used to manage texture memory represented by
+ * this texture heap.
+ */
+ struct mem_block * memory_heap;
+
+ /** List of objects that we currently believe to be in texture
+ * memory.
+ */
+ driTextureObject texture_objects;
+
+ /** Pointer to the list of texture objects that are not in
+ * texture memory.
+ */
+ driTextureObject * swapped_objects;
+
+ /** Size of the driver-speicific texture object.
+ */
+ unsigned texture_object_size;
+
+
+ /**
+ * \brief Function to destroy driver-specific texture object data.
+ *
+ * This function is supplied by the driver so that the texture manager
+ * can release all resources associated with a texture object. This
+ * function should only release driver-specific data. That is,
+ * \a driDestroyTextureObject will release the texture memory
+ * associated with the texture object, it will release the memory
+ * for the texture object itself, and it will unlink the texture
+ * object from the texture object lists.
+ *
+ * \param driverContext Pointer to the driver supplied context
+ * \param t Texture object that is to be destroyed
+ * \sa driDestroyTextureObject
+ */
+
+ destroy_texture_object_t * destroy_texture_object;
+
+
+ /**
+ */
+ unsigned * texture_swaps;
+
+ /**
+ * Timestamp used to synchronize with 3d engine in hardware
+ * where textures are uploaded directly to the
+ * framebuffer.
+ */
+ unsigned timestamp;
+
+ /** \brief Kick/upload weight
+ *
+ * When not enough free space is available this weight
+ * influences the choice of the heap from which textures are
+ * kicked. By default the weight is equal to the heap size.
+ */
+ double weight;
+
+ /** \brief Kick/upload duty
+ *
+ * The heap with the highest duty will be chosen for kicking
+ * textures if not enough free space is available. The duty is
+ * reduced by the amount of data kicked. Rebalancing of
+ * negative duties takes the weights into account.
+ */
+ int duty;
+};
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ * \hideinitializer
+ */
+
+#define DRI_AGE_TEXTURES( heap ) \
+ do { \
+ if ( ((heap) != NULL) \
+ && ((heap)->local_age != (heap)->global_age[0]) ) \
+ driAgeTextures( heap ); \
+ } while( 0 )
+
+
+
+
+/* This should be called whenever there has been contention on the hardware
+ * lock. driAgeTextures should not be called directly. Instead, clients
+ * should use DRI_AGE_TEXTURES, above.
+ */
+
+void driAgeTextures( driTexHeap * heap );
+
+void driUpdateTextureLRU( driTextureObject * t );
+void driSwapOutTextureObject( driTextureObject * t );
+void driDestroyTextureObject( driTextureObject * t );
+int driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t );
+
+GLboolean driIsTextureResident( GLcontext * ctx,
+ struct gl_texture_object * texObj );
+
+driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
+ unsigned size, unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects, unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj );
+void driDestroyTextureHeap( driTexHeap * heap );
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap,
+ int allow_larger_textures );
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter );
+
+#define DRI_TEXMGR_DO_TEXTURE_1D 0x0001
+#define DRI_TEXMGR_DO_TEXTURE_2D 0x0002
+#define DRI_TEXMGR_DO_TEXTURE_3D 0x0004
+#define DRI_TEXMGR_DO_TEXTURE_CUBE 0x0008
+#define DRI_TEXMGR_DO_TEXTURE_RECT 0x0010
+
+void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
+ GLuint targets );
+
+GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped );
+
+extern void driCalculateTextureFirstLastLevel( driTextureObject * t );
+
+
+extern const struct gl_texture_format *_dri_texformat_rgba8888;
+extern const struct gl_texture_format *_dri_texformat_argb8888;
+extern const struct gl_texture_format *_dri_texformat_rgb565;
+extern const struct gl_texture_format *_dri_texformat_argb4444;
+extern const struct gl_texture_format *_dri_texformat_argb1555;
+extern const struct gl_texture_format *_dri_texformat_al88;
+extern const struct gl_texture_format *_dri_texformat_a8;
+extern const struct gl_texture_format *_dri_texformat_ci8;
+extern const struct gl_texture_format *_dri_texformat_i8;
+extern const struct gl_texture_format *_dri_texformat_l8;
+
+extern void driInitTextureFormats( void );
+
+#endif /* DRI_TEXMEM_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c
new file mode 100644
index 000000000..66f277c10
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/utils.c
@@ -0,0 +1,839 @@
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file utils.c
+ * Utility functions for DRI drivers.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "main/mtypes.h"
+#include "main/cpuinfo.h"
+#include "main/extensions.h"
+#include "glapi/dispatch.h"
+#include "utils.h"
+
+
+int driDispatchRemapTable[ driDispatchRemapTable_size ];
+
+
+unsigned
+driParseDebugString( const char * debug,
+ const struct dri_debug_control * control )
+{
+ unsigned flag;
+
+
+ flag = 0;
+ if ( debug != NULL ) {
+ while( control->string != NULL ) {
+ if ( !strcmp( debug, "all" ) ||
+ strstr( debug, control->string ) != NULL ) {
+ flag |= control->flag;
+ }
+
+ control++;
+ }
+ }
+
+ return flag;
+}
+
+
+
+/**
+ * Create the \c GL_RENDERER string for DRI drivers.
+ *
+ * Almost all DRI drivers use a \c GL_RENDERER string of the form:
+ *
+ * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
+ *
+ * Using the supplied chip name, driver data, and AGP speed, this function
+ * creates the string.
+ *
+ * \param buffer Buffer to hold the \c GL_RENDERER string.
+ * \param hardware_name Name of the hardware.
+ * \param driver_date Driver date.
+ * \param agp_mode AGP mode (speed).
+ *
+ * \returns
+ * The length of the string stored in \c buffer. This does \b not include
+ * the terminating \c NUL character.
+ */
+unsigned
+driGetRendererString( char * buffer, const char * hardware_name,
+ const char * driver_date, GLuint agp_mode )
+{
+ unsigned offset;
+ char *cpu;
+
+ offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
+
+ /* Append any AGP-specific information.
+ */
+ switch ( agp_mode ) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
+ break;
+
+ default:
+ break;
+ }
+
+ /* Append any CPU-specific information.
+ */
+ cpu = _mesa_get_cpu_string();
+ if (cpu) {
+ offset += sprintf(buffer + offset, " %s", cpu);
+ _mesa_free(cpu);
+ }
+
+ return offset;
+}
+
+
+
+
+#define need_GL_ARB_draw_buffers
+#define need_GL_ARB_multisample
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_transpose_matrix
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_compiled_vertex_array
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_polygon_offset
+#define need_GL_EXT_texture_object
+#define need_GL_EXT_vertex_array
+#define need_GL_IBM_multimode_draw_arrays
+#define need_GL_MESA_window_pos
+
+/* These are needed in *all* drivers because Mesa internally implements
+ * certain functionality in terms of functions provided by these extensions.
+ * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT.
+ */
+#define need_GL_EXT_blend_func_separate
+#define need_GL_NV_vertex_program
+
+#include "extension_helper.h"
+
+static const struct dri_extension all_mesa_extensions[] = {
+ { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions },
+ { "GL_ARB_multisample", GL_ARB_multisample_functions },
+ { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
+ { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions },
+ { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+ { "GL_ARB_window_pos", GL_ARB_window_pos_functions },
+ { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions },
+ { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
+ { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
+ { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions },
+ { "GL_EXT_texture_object", GL_EXT_texture_object_functions },
+ { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions },
+ { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
+ { "GL_MESA_window_pos", GL_MESA_window_pos_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { NULL, NULL }
+};
+
+
+/**
+ * Enable extensions supported by the driver.
+ *
+ * \bug
+ * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also
+ * enables all the sub-extensions that are folded into it. This means that
+ * we need to add entry-points (via \c driInitSingleExtension) for those
+ * new functions here.
+ */
+void driInitExtensions( GLcontext * ctx,
+ const struct dri_extension * extensions_to_enable,
+ GLboolean enable_imaging )
+{
+ static int first_time = 1;
+ unsigned i;
+
+ if ( first_time ) {
+ for ( i = 0 ; i < driDispatchRemapTable_size ; i++ ) {
+ driDispatchRemapTable[i] = -1;
+ }
+
+ first_time = 0;
+ driInitExtensions( ctx, all_mesa_extensions, GL_FALSE );
+ }
+
+ if ( (ctx != NULL) && enable_imaging ) {
+ _mesa_enable_imaging_extensions( ctx );
+ }
+
+ for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) {
+ driInitSingleExtension( ctx, & extensions_to_enable[i] );
+ }
+}
+
+
+
+
+/**
+ * Enable and add dispatch functions for a single extension
+ *
+ * \param ctx Context where extension is to be enabled.
+ * \param ext Extension that is to be enabled.
+ *
+ * \sa driInitExtensions, _mesa_enable_extension, _glapi_add_entrypoint
+ *
+ * \todo
+ * Determine if it would be better to use \c strlen instead of the hardcoded
+ * for-loops.
+ */
+void driInitSingleExtension( GLcontext * ctx,
+ const struct dri_extension * ext )
+{
+ unsigned i;
+
+
+ if ( ext->functions != NULL ) {
+ for ( i = 0 ; ext->functions[i].strings != NULL ; i++ ) {
+ const char * functions[16];
+ const char * parameter_signature;
+ const char * str = ext->functions[i].strings;
+ unsigned j;
+ unsigned offset;
+
+
+ /* Separate the parameter signature from the rest of the string.
+ * If the parameter signature is empty (i.e., the string starts
+ * with a NUL character), then the function has a void parameter
+ * list.
+ */
+ parameter_signature = str;
+ while ( str[0] != '\0' ) {
+ str++;
+ }
+ str++;
+
+
+ /* Divide the string into the substrings that name each
+ * entry-point for the function.
+ */
+ for ( j = 0 ; j < 16 ; j++ ) {
+ if ( str[0] == '\0' ) {
+ functions[j] = NULL;
+ break;
+ }
+
+ functions[j] = str;
+
+ while ( str[0] != '\0' ) {
+ str++;
+ }
+ str++;
+ }
+
+
+ /* Add each entry-point to the dispatch table.
+ */
+ offset = _glapi_add_dispatch( functions, parameter_signature );
+ if (offset == -1) {
+#if 0 /* this causes noise with egl */
+ fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed "
+ "to add %s!\n", functions[0]);
+#endif
+ }
+ else if (ext->functions[i].remap_index != -1) {
+ driDispatchRemapTable[ ext->functions[i].remap_index ] =
+ offset;
+ }
+ else if (ext->functions[i].offset != offset) {
+ fprintf(stderr, "DISPATCH ERROR! %s -> %u != %u\n",
+ functions[0], offset, ext->functions[i].offset);
+ }
+ }
+ }
+
+ if ( ctx != NULL ) {
+ _mesa_enable_extension( ctx, ext->name );
+ }
+}
+
+
+/**
+ * Utility function used by drivers to test the verions of other components.
+ *
+ * If one of the version requirements is not met, a message is logged using
+ * \c __driUtilMessage.
+ *
+ * \param driver_name Name of the driver. Used in error messages.
+ * \param driActual Actual DRI version supplied __driCreateNewScreen.
+ * \param driExpected Minimum DRI version required by the driver.
+ * \param ddxActual Actual DDX version supplied __driCreateNewScreen.
+ * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver.
+ * \param drmActual Actual DRM version supplied __driCreateNewScreen.
+ * \param drmExpected Minimum DRM version required by the driver.
+ *
+ * \returns \c GL_TRUE if all version requirements are met. Otherwise,
+ * \c GL_FALSE is returned.
+ *
+ * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage
+ *
+ * \todo
+ * Now that the old \c driCheckDriDdxDrmVersions function is gone, this
+ * function and \c driCheckDriDdxDrmVersions2 should be renamed.
+ */
+GLboolean
+driCheckDriDdxDrmVersions3(const char * driver_name,
+ const __DRIversion * driActual,
+ const __DRIversion * driExpected,
+ const __DRIversion * ddxActual,
+ const __DRIutilversion2 * ddxExpected,
+ const __DRIversion * drmActual,
+ const __DRIversion * drmExpected)
+{
+ static const char format[] = "%s DRI driver expected %s version %d.%d.x "
+ "but got version %d.%d.%d\n";
+ static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
+ "but got version %d.%d.%d\n";
+
+
+ /* Check the DRI version */
+ if ( (driActual->major != driExpected->major)
+ || (driActual->minor < driExpected->minor) ) {
+ fprintf(stderr, format, driver_name, "DRI",
+ driExpected->major, driExpected->minor,
+ driActual->major, driActual->minor, driActual->patch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DDX driver version is compatible */
+ /* for miniglx we pass in -1 so we can ignore the DDX version */
+ if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min)
+ || (ddxActual->major > ddxExpected->major_max)
+ || (ddxActual->minor < ddxExpected->minor)) ) {
+ fprintf(stderr, format2, driver_name, "DDX",
+ ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
+ ddxActual->major, ddxActual->minor, ddxActual->patch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DRM driver version is compatible */
+ if ( (drmActual->major != drmExpected->major)
+ || (drmActual->minor < drmExpected->minor) ) {
+ fprintf(stderr, format, driver_name, "DRM",
+ drmExpected->major, drmExpected->minor,
+ drmActual->major, drmActual->minor, drmActual->patch);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual,
+ const __DRIversion * driExpected,
+ const __DRIversion * ddxActual,
+ const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual,
+ const __DRIversion * drmExpected)
+{
+ __DRIutilversion2 ddx_expected;
+ ddx_expected.major_min = ddxExpected->major;
+ ddx_expected.major_max = ddxExpected->major;
+ ddx_expected.minor = ddxExpected->minor;
+ ddx_expected.patch = ddxExpected->patch;
+ return driCheckDriDdxDrmVersions3(driver_name, driActual,
+ driExpected, ddxActual, & ddx_expected,
+ drmActual, drmExpected);
+}
+
+GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height )
+{
+ /* left clipping */
+ if (*x < buffer->_Xmin) {
+ *width -= (buffer->_Xmin - *x);
+ *x = buffer->_Xmin;
+ }
+
+ /* right clipping */
+ if (*x + *width > buffer->_Xmax)
+ *width -= (*x + *width - buffer->_Xmax - 1);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*y < buffer->_Ymin) {
+ *height -= (buffer->_Ymin - *y);
+ *y = buffer->_Ymin;
+ }
+
+ /* top clipping */
+ if (*y + *height > buffer->_Ymax)
+ *height -= (*y + *height - buffer->_Ymax - 1);
+
+ if (*height <= 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/**
+ * Creates a set of \c __GLcontextModes that a driver will expose.
+ *
+ * A set of \c __GLcontextModes will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c __GLcontextModes element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param ptr_to_modes Pointer to a pointer to a linked list of
+ * \c __GLcontextModes. Upon completion, a pointer to
+ * the next element to be process will be stored here.
+ * If the function fails and returns \c GL_FALSE, this
+ * value will be unmodified, but some elements in the
+ * linked list may be modified.
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param msaa_samples Array of msaa sample count. 0 represents a visual
+ * without a multisample buffer.
+ * \param num_msaa_modes Number of entries in \c msaa_samples.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+__DRIconfig **
+driCreateConfigs(GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes)
+{
+ static const uint8_t bits_table[4][4] = {
+ /* R G B A */
+ { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ static const uint32_t masks_table_rgb[6][4] = {
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_rgba[6][4] = {
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgr[6][4] = {
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgra[6][4] = {
+ { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */
+ { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const uint8_t bytes_per_pixel[6] = {
+ 1, /* 3_3_2 */
+ 1, /* 2_3_3_REV */
+ 2, /* 5_6_5 */
+ 2, /* 5_6_5_REV */
+ 4, /* 8_8_8_8 */
+ 4 /* 8_8_8_8_REV */
+ };
+
+ const uint8_t * bits;
+ const uint32_t * masks;
+ int index;
+ __DRIconfig **configs, **c;
+ __GLcontextModes *modes;
+ unsigned i, j, k, h;
+ unsigned num_modes;
+ unsigned num_accum_bits = 2;
+
+ switch ( fb_type ) {
+ case GL_UNSIGNED_BYTE_3_3_2:
+ index = 0;
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ index = 1;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ index = 2;
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ index = 3;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ index = 4;
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ index = 5;
+ break;
+ default:
+ fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n",
+ __FUNCTION__, __LINE__, fb_type );
+ return NULL;
+ }
+
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+
+ switch ( fb_format ) {
+ case GL_RGB:
+ masks = masks_table_rgb[ index ];
+ break;
+
+ case GL_RGBA:
+ masks = masks_table_rgba[ index ];
+ break;
+
+ case GL_BGR:
+ masks = masks_table_bgr[ index ];
+ break;
+
+ case GL_BGRA:
+ masks = masks_table_bgra[ index ];
+ break;
+
+ default:
+ fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n",
+ __FUNCTION__, __LINE__, fb_format );
+ return NULL;
+ }
+
+ switch ( bytes_per_pixel[ index ] ) {
+ case 1:
+ bits = bits_table[0];
+ break;
+ case 2:
+ bits = bits_table[1];
+ break;
+ default:
+ bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR))
+ ? bits_table[2]
+ : bits_table[3];
+ break;
+ }
+
+ num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
+ configs = _mesa_calloc((num_modes + 1) * sizeof *configs);
+ if (configs == NULL)
+ return NULL;
+
+ c = configs;
+ for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
+ for ( i = 0 ; i < num_db_modes ; i++ ) {
+ for ( h = 0 ; h < num_msaa_modes; h++ ) {
+ for ( j = 0 ; j < num_accum_bits ; j++ ) {
+ *c = _mesa_malloc (sizeof **c);
+ modes = &(*c)->modes;
+ c++;
+
+ memset(modes, 0, sizeof *modes);
+ modes->redBits = bits[0];
+ modes->greenBits = bits[1];
+ modes->blueBits = bits[2];
+ modes->alphaBits = bits[3];
+ modes->redMask = masks[0];
+ modes->greenMask = masks[1];
+ modes->blueMask = masks[2];
+ modes->alphaMask = masks[3];
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
+
+ modes->accumRedBits = 16 * j;
+ modes->accumGreenBits = 16 * j;
+ modes->accumBlueBits = 16 * j;
+ modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
+ modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+ modes->stencilBits = stencil_bits[k];
+ modes->depthBits = depth_bits[k];
+
+ modes->transparentPixel = GLX_NONE;
+ modes->transparentRed = GLX_DONT_CARE;
+ modes->transparentGreen = GLX_DONT_CARE;
+ modes->transparentBlue = GLX_DONT_CARE;
+ modes->transparentAlpha = GLX_DONT_CARE;
+ modes->transparentIndex = GLX_DONT_CARE;
+ modes->visualType = GLX_DONT_CARE;
+ modes->renderType = GLX_RGBA_BIT;
+ modes->drawableType = GLX_WINDOW_BIT;
+ modes->rgbMode = GL_TRUE;
+
+ if ( db_modes[i] == GLX_NONE ) {
+ modes->doubleBufferMode = GL_FALSE;
+ }
+ else {
+ modes->doubleBufferMode = GL_TRUE;
+ modes->swapMethod = db_modes[i];
+ }
+
+ modes->samples = msaa_samples[h];
+ modes->sampleBuffers = modes->samples ? 1 : 0;
+
+
+ modes->haveAccumBuffer = ((modes->accumRedBits +
+ modes->accumGreenBits +
+ modes->accumBlueBits +
+ modes->accumAlphaBits) > 0);
+ modes->haveDepthBuffer = (modes->depthBits > 0);
+ modes->haveStencilBuffer = (modes->stencilBits > 0);
+
+ modes->bindToTextureRgb = GL_TRUE;
+ modes->bindToTextureRgba = GL_TRUE;
+ modes->bindToMipmapTexture = GL_FALSE;
+ modes->bindToTextureTargets = modes->rgbMode ?
+ __DRI_ATTRIB_TEXTURE_1D_BIT |
+ __DRI_ATTRIB_TEXTURE_2D_BIT |
+ __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT :
+ 0;
+ }
+ }
+ }
+ }
+ *c = NULL;
+
+ return configs;
+}
+
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b)
+{
+ __DRIconfig **all;
+ int i, j, index;
+
+ i = 0;
+ while (a[i] != NULL)
+ i++;
+ j = 0;
+ while (b[j] != NULL)
+ j++;
+
+ all = _mesa_malloc((i + j + 1) * sizeof *all);
+ index = 0;
+ for (i = 0; a[i] != NULL; i++)
+ all[index++] = a[i];
+ for (j = 0; b[j] != NULL; j++)
+ all[index++] = b[j];
+ all[index++] = NULL;
+
+ _mesa_free(a);
+ _mesa_free(b);
+
+ return all;
+}
+
+#define __ATTRIB(attrib, field) \
+ { attrib, offsetof(__GLcontextModes, field) }
+
+static const struct { unsigned int attrib, offset; } attribMap[] = {
+ __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
+ __ATTRIB(__DRI_ATTRIB_LEVEL, level),
+ __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
+ __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
+ __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
+ __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
+ __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
+ __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
+ __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
+ __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
+ __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
+ __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
+ __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
+ __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
+ __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode),
+ __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
+ __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
+ __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
+ __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
+ __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
+ __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
+ __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets),
+ __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
+
+ /* The struct field doesn't matter here, these are handled by the
+ * switch in driGetConfigAttribIndex. We need them in the array
+ * so the iterator includes them though.*/
+ __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level),
+ __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level),
+ __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level)
+};
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+static int
+driGetConfigAttribIndex(const __DRIconfig *config,
+ unsigned int index, unsigned int *value)
+{
+ switch (attribMap[index].attrib) {
+ case __DRI_ATTRIB_RENDER_TYPE:
+ if (config->modes.rgbMode)
+ *value = __DRI_ATTRIB_RGBA_BIT;
+ else
+ *value = __DRI_ATTRIB_COLOR_INDEX_BIT;
+ break;
+ case __DRI_ATTRIB_CONFIG_CAVEAT:
+ if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
+ *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
+ else if (config->modes.visualRating == GLX_SLOW_CONFIG)
+ *value = __DRI_ATTRIB_SLOW_BIT;
+ else
+ *value = 0;
+ break;
+ case __DRI_ATTRIB_SWAP_METHOD:
+ break;
+
+ case __DRI_ATTRIB_FLOAT_MODE:
+ *value = config->modes.floatMode;
+ break;
+
+ default:
+ *value = *(unsigned int *)
+ ((char *) &config->modes + attribMap[index].offset);
+
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+int
+driGetConfigAttrib(const __DRIconfig *config,
+ unsigned int attrib, unsigned int *value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(attribMap); i++)
+ if (attribMap[i].attrib == attrib)
+ return driGetConfigAttribIndex(config, i, value);
+
+ return GL_FALSE;
+}
+
+int
+driIndexConfigAttrib(const __DRIconfig *config, int index,
+ unsigned int *attrib, unsigned int *value)
+{
+ if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
+ *attrib = attribMap[index].attrib;
+ return driGetConfigAttribIndex(config, index, value);
+ }
+
+ return GL_FALSE;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.h b/mesalib/src/mesa/drivers/dri/common/utils.h
new file mode 100644
index 000000000..9e9e5bc22
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/utils.h
@@ -0,0 +1,147 @@
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef DRI_DEBUG_H
+#define DRI_DEBUG_H
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include "main/context.h"
+
+typedef struct __DRIutilversionRec2 __DRIutilversion2;
+
+struct dri_debug_control {
+ const char * string;
+ unsigned flag;
+};
+
+/**
+ * Description of the entry-points and parameters for an OpenGL function.
+ */
+struct dri_extension_function {
+ /**
+ * \brief
+ * Packed string describing the parameter signature and the entry-point
+ * names.
+ *
+ * The parameter signature and the names of the entry-points for this
+ * function are packed into a single string. The substrings are
+ * separated by NUL characters. The whole string is terminated by
+ * two consecutive NUL characters.
+ */
+ const char * strings;
+
+
+ /**
+ * Location in the remap table where the dispatch offset should be
+ * stored.
+ */
+ int remap_index;
+
+ /**
+ * Offset of the function in the dispatch table.
+ */
+ int offset;
+};
+
+/**
+ * Description of the API for an extension to OpenGL.
+ */
+struct dri_extension {
+ /**
+ * Name of the extension.
+ */
+ const char * name;
+
+
+ /**
+ * Pointer to a list of \c dri_extension_function structures. The list
+ * is terminated by a structure with a \c NULL
+ * \c dri_extension_function::strings pointer.
+ */
+ const struct dri_extension_function * functions;
+};
+
+/**
+ * Used to store a version which includes a major range instead of a single
+ * major version number.
+ */
+struct __DRIutilversionRec2 {
+ int major_min; /** min allowed Major version number. */
+ int major_max; /** max allowed Major version number. */
+ int minor; /**< Minor version number. */
+ int patch; /**< Patch-level. */
+};
+
+extern unsigned driParseDebugString( const char * debug,
+ const struct dri_debug_control * control );
+
+extern unsigned driGetRendererString( char * buffer,
+ const char * hardware_name, const char * driver_date, GLuint agp_mode );
+
+extern void driInitExtensions( GLcontext * ctx,
+ const struct dri_extension * card_extensions, GLboolean enable_imaging );
+
+extern void driInitSingleExtension( GLcontext * ctx,
+ const struct dri_extension * ext );
+
+extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual, const __DRIversion * driExpected,
+ const __DRIversion * ddxActual, const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual, const __DRIversion * drmExpected);
+
+extern GLboolean driCheckDriDdxDrmVersions3(const char * driver_name,
+ const __DRIversion * driActual, const __DRIversion * driExpected,
+ const __DRIversion * ddxActual, const __DRIutilversion2 * ddxExpected,
+ const __DRIversion * drmActual, const __DRIversion * drmExpected);
+
+extern GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height );
+
+struct __DRIconfigRec {
+ __GLcontextModes modes;
+};
+
+extern __DRIconfig **
+driCreateConfigs(GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ const uint8_t * msaa_samples, unsigned num_msaa_modes);
+
+__DRIconfig **driConcatConfigs(__DRIconfig **a,
+ __DRIconfig **b);
+
+int
+driGetConfigAttrib(const __DRIconfig *config,
+ unsigned int attrib, unsigned int *value);
+int
+driIndexConfigAttrib(const __DRIconfig *config, int index,
+ unsigned int *attrib, unsigned int *value);
+
+#endif /* DRI_DEBUG_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/vblank.c b/mesalib/src/mesa/drivers/dri/common/vblank.c
new file mode 100644
index 000000000..12aeaa108
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/vblank.c
@@ -0,0 +1,434 @@
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "main/glheader.h"
+#include "xf86drm.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/dd.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+static unsigned int msc_to_vblank(__DRIdrawablePrivate * dPriv, int64_t msc)
+{
+ return (unsigned int)(msc - dPriv->msc_base + dPriv->vblank_base);
+}
+
+static int64_t vblank_to_msc(__DRIdrawablePrivate * dPriv, unsigned int vblank)
+{
+ return (int64_t)(vblank - dPriv->vblank_base + dPriv->msc_base);
+}
+
+
+/****************************************************************************/
+/**
+ * Get the current MSC refresh counter.
+ *
+ * Stores the 64-bit count of vertical refreshes since some (arbitrary)
+ * point in time in \c count. Unless the value wraps around, which it
+ * may, it will never decrease for a given drawable.
+ *
+ * \warning This function is called from \c glXGetVideoSyncSGI, which expects
+ * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which
+ * expects a \c count of type \c int64_t (signed 64-bit). The kernel ioctl
+ * currently always returns a \c sequence of type \c unsigned.
+ *
+ * \param priv Pointer to the DRI screen private struct.
+ * \param dPriv Pointer to the DRI drawable private struct
+ * \param count Storage to hold MSC counter.
+ * \return Zero is returned on success. A negative errno value
+ * is returned on failure.
+ */
+int driDrawableGetMSC32( __DRIscreenPrivate * priv,
+ __DRIdrawablePrivate * dPriv,
+ int64_t * count)
+{
+ drmVBlank vbl;
+ int ret;
+
+ /* Don't wait for anything. Just get the current refresh count. */
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.sequence = 0;
+ if ( dPriv && dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ ret = drmWaitVBlank( priv->fd, &vbl );
+
+ if (dPriv) {
+ *count = vblank_to_msc(dPriv, vbl.reply.sequence);
+ } else {
+ /* Old driver (no knowledge of drawable MSC callback) */
+ *count = vbl.reply.sequence;
+ }
+
+ return ret;
+}
+
+/****************************************************************************/
+/**
+ * Wait for a specified refresh count. This implements most of the
+ * functionality of \c glXWaitForMscOML from the GLX_OML_sync_control spec.
+ * Waits for the \c target_msc refresh. If that has already passed, it
+ * waits until \f$(MSC \bmod divisor)\f$ is equal to \c remainder. If
+ * \c target_msc is 0, use the behavior of glXWaitVideoSyncSGI(), which
+ * omits the initial check against a target MSC value.
+ *
+ * This function is actually something of a hack. The problem is that, at
+ * the time of this writing, none of the existing DRM modules support an
+ * ioctl that returns a 64-bit count (at least not on 32-bit platforms).
+ * However, this function exists to support a GLX function that requires
+ * the use of 64-bit counts. As such, there is a little bit of ugly
+ * hackery at the end of this function to make the 32-bit count act like
+ * a 64-bit count. There are still some cases where this will break, but
+ * I believe it catches the most common cases.
+ *
+ * The real solution is to provide an ioctl that uses a 64-bit count.
+ *
+ * \param dpy Pointer to the \c Display.
+ * \param priv Pointer to the DRI drawable private.
+ * \param target_msc Desired refresh count to wait for. A value of 0
+ * means to use the glXWaitVideoSyncSGI() behavior.
+ * \param divisor MSC divisor if \c target_msc is already reached.
+ * \param remainder Desired MSC remainder if \c target_msc is already
+ * reached.
+ * \param msc Buffer to hold MSC when done waiting.
+ *
+ * \return Zero on success or \c GLX_BAD_CONTEXT on failure.
+ */
+
+int driWaitForMSC32( __DRIdrawablePrivate *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder,
+ int64_t * msc )
+{
+ drmVBlank vbl;
+
+
+ if ( divisor != 0 ) {
+ int64_t next = target_msc;
+ int64_t r;
+ int dont_wait = (target_msc == 0);
+
+ do {
+ /* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
+ * The first time around, just get the current count and proceed
+ * to the test for (MSC % divisor) == remainder.
+ */
+ vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
+ DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = next ? msc_to_vblank(priv, next) : 0;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+
+ *msc = vblank_to_msc(priv, vbl.reply.sequence);
+
+ if (!dont_wait && *msc == next)
+ break;
+ dont_wait = 0;
+
+ /* Assuming the wait-done test fails, the next refresh to wait for
+ * will be one that satisfies (MSC % divisor) == remainder. The
+ * value (MSC - (MSC % divisor) + remainder) is the refresh value
+ * closest to the current value that would satisfy the equation.
+ * If this refresh has already happened, we add divisor to obtain
+ * the next refresh after the current one that will satisfy it.
+ */
+ r = ((uint64_t)*msc % divisor);
+ next = (*msc - r + remainder);
+ if (next <= *msc)
+ next += divisor;
+
+ } while (r != remainder);
+ }
+ else {
+ /* If the \c divisor is zero, just wait until the MSC is greater
+ * than or equal to \c target_msc.
+ */
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = target_msc ? msc_to_vblank(priv, target_msc) : 0;
+
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+ }
+
+ *msc = vblank_to_msc(priv, vbl.reply.sequence);
+
+ if ( *msc < target_msc ) {
+ *msc += 0x0000000100000000LL;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Gets a set of default vertical-blank-wait flags based on the internal GLX
+ * API version and several configuration options.
+ */
+
+GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
+{
+ GLuint flags = VBLANK_FLAG_INTERVAL;
+ int vblank_mode;
+
+
+ if ( driCheckOption( optionCache, "vblank_mode", DRI_ENUM ) )
+ vblank_mode = driQueryOptioni( optionCache, "vblank_mode" );
+ else
+ vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+ switch (vblank_mode) {
+ case DRI_CONF_VBLANK_NEVER:
+ flags = 0;
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+ flags |= VBLANK_FLAG_THROTTLE;
+ break;
+ case DRI_CONF_VBLANK_ALWAYS_SYNC:
+ flags |= VBLANK_FLAG_SYNC;
+ break;
+ }
+
+ return flags;
+}
+
+
+/****************************************************************************/
+/**
+ * Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
+ * wrap the error message logging. The error message should only be logged
+ * the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
+ * successful, \c vbl_seq will be set the sequence value in the reply.
+ *
+ * \param vbl Pointer to drmVBlank packet desribing how to wait.
+ * \param vbl_seq Location to store the current refresh counter.
+ * \param fd File descriptor use to call into the DRM.
+ * \return Zero on success or -1 on failure.
+ */
+
+static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
+{
+ int ret;
+
+
+ ret = drmWaitVBlank( fd, vbl );
+ if ( ret != 0 ) {
+ static GLboolean first_time = GL_TRUE;
+
+ if ( first_time ) {
+ fprintf(stderr,
+ "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
+ " working correctly.\nTry adjusting the vblank_mode"
+ " configuration parameter.\n", __FUNCTION__, ret);
+ first_time = GL_FALSE;
+ }
+
+ return -1;
+ }
+
+ *vbl_seq = vbl->reply.sequence;
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the default swap interval of the given drawable.
+ */
+
+static unsigned
+driGetDefaultVBlankInterval( const __DRIdrawablePrivate *priv )
+{
+ if ( (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+/****************************************************************************/
+/**
+ * Sets the default swap interval when the drawable is first bound to a
+ * direct rendering context.
+ */
+
+void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
+{
+ if ( priv->swap_interval == (unsigned)-1 &&
+ !( priv->vblFlags & VBLANK_FLAG_NO_IRQ ) ) {
+ /* Get current vertical blank sequence */
+ drmVBlank vbl;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+ priv->vblank_base = priv->vblSeq;
+
+ priv->swap_interval = driGetDefaultVBlankInterval( priv );
+ }
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the current swap interval of the given drawable.
+ */
+
+unsigned
+driGetVBlankInterval( const __DRIdrawablePrivate *priv )
+{
+ if ( (priv->vblFlags & VBLANK_FLAG_INTERVAL) != 0 ) {
+ /* this must have been initialized when the drawable was first bound
+ * to a direct rendering context. */
+ assert ( priv->swap_interval != (unsigned)-1 );
+
+ return priv->swap_interval;
+ }
+ else
+ return driGetDefaultVBlankInterval( priv );
+}
+
+
+/****************************************************************************/
+/**
+ * Returns the current vertical blank sequence number of the given drawable.
+ */
+
+void
+driGetCurrentVBlank( __DRIdrawablePrivate *priv )
+{
+ drmVBlank vbl;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = 0;
+
+ (void) do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+}
+
+
+/****************************************************************************/
+/**
+ * Waits for the vertical blank for use with glXSwapBuffers.
+ *
+ * \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
+ * than the "target" based on \c priv->vblFlags. The idea is
+ * that if \c missed_deadline is set, then the application is
+ * not achieving its desired framerate.
+ * \return Zero on success, -1 on error.
+ */
+
+int
+driWaitForVBlank( __DRIdrawablePrivate *priv, GLboolean * missed_deadline )
+{
+ drmVBlank vbl;
+ unsigned original_seq;
+ unsigned deadline;
+ unsigned interval;
+ unsigned diff;
+
+ *missed_deadline = GL_FALSE;
+ if ( (priv->vblFlags & (VBLANK_FLAG_INTERVAL |
+ VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) == 0 ||
+ (priv->vblFlags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+ return 0;
+ }
+
+
+ /* VBLANK_FLAG_SYNC means to wait for at least one vertical blank. If
+ * that flag is not set, do a fake wait for zero vertical blanking
+ * periods so that we can get the current MSC.
+ *
+ * VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
+ * least one vertical blank since the last wait. Since do_wait modifies
+ * priv->vblSeq, we have to save the original value of priv->vblSeq for the
+ * VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
+ */
+
+ original_seq = priv->vblSeq;
+ interval = driGetVBlankInterval(priv);
+ deadline = original_seq + interval;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = ((priv->vblFlags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
+
+ if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+
+ diff = priv->vblSeq - deadline;
+
+ /* No need to wait again if we've already reached the target */
+ if (diff <= (1 << 23)) {
+ *missed_deadline = (priv->vblFlags & VBLANK_FLAG_SYNC) ? (diff > 0) :
+ GL_TRUE;
+ return 0;
+ }
+
+ /* Wait until the target vertical blank. */
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+ if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ }
+ vbl.request.sequence = deadline;
+
+ if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+
+ diff = priv->vblSeq - deadline;
+ *missed_deadline = diff > 0 && diff <= (1 << 23);
+
+ return 0;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/vblank.h b/mesalib/src/mesa/drivers/dri/common/vblank.h
new file mode 100644
index 000000000..8b2c761a1
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/vblank.h
@@ -0,0 +1,75 @@
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef DRI_VBLANK_H
+#define DRI_VBLANK_H
+
+#include "main/context.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
+ */
+#define VBLANK_FLAG_THROTTLE (1U << 1) /* Wait 1 refresh since last call.
+ */
+#define VBLANK_FLAG_SYNC (1U << 2) /* Sync to the next refresh.
+ */
+#define VBLANK_FLAG_NO_IRQ (1U << 7) /* DRM has no IRQ to wait on.
+ */
+#define VBLANK_FLAG_SECONDARY (1U << 8) /* Wait for secondary vblank.
+ */
+
+extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
+extern int driDrawableGetMSC32( __DRIscreenPrivate * priv,
+ __DRIdrawablePrivate * drawablePrivate,
+ int64_t * count);
+extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
+extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
+extern void driDrawableInitVBlank ( __DRIdrawablePrivate *priv );
+extern unsigned driGetVBlankInterval( const __DRIdrawablePrivate *priv );
+extern void driGetCurrentVBlank( __DRIdrawablePrivate *priv );
+extern int driWaitForVBlank( __DRIdrawablePrivate *priv,
+ GLboolean * missed_deadline );
+
+#undef usleep
+#include <unistd.h> /* for usleep() */
+#include <sched.h> /* for sched_yield() */
+
+#ifdef linux
+#include <sched.h> /* for sched_yield() */
+#endif
+
+#define DO_USLEEP(nr) \
+ do { \
+ if (0) fprintf(stderr, "%s: usleep for %u\n", __FUNCTION__, nr ); \
+ if (1) usleep( nr ); \
+ sched_yield(); \
+ } while( 0 )
+
+#endif /* DRI_VBLANK_H */
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
new file mode 100644
index 000000000..46ba2ffbf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
@@ -0,0 +1,1008 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file xmlconfig.c
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#include "main/glheader.h"
+
+#include <string.h>
+#include <assert.h>
+#include <expat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "main/imports.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+/*
+ * OS dependent ways of getting the name of the running program
+ */
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
+
+#undef GET_PROGRAM_NAME
+
+#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__)
+# if !defined(__GLIBC__) || (__GLIBC__ < 2)
+/* These aren't declared in any libc5 header */
+extern char *program_invocation_name, *program_invocation_short_name;
+# endif
+# define GET_PROGRAM_NAME() program_invocation_short_name
+#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+# include <osreldate.h>
+# if (__FreeBSD_version >= 440000)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+# endif
+#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+#elif defined(__sun)
+/* Solaris has getexecname() which returns the full path - return just
+ the basename to match BSD getprogname() */
+# include <stdlib.h>
+# include <libgen.h>
+# define GET_PROGRAM_NAME() basename(getexecname())
+#endif
+
+#if !defined(GET_PROGRAM_NAME)
+# if defined(OpenBSD) || defined(NetBSD) || defined(__UCLIBC__)
+/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU.
+ * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's
+ * used as a last resort, if there is no documented facility available. */
+static const char *__getProgramName () {
+ extern const char *__progname;
+ char * arg = strrchr(__progname, '/');
+ if (arg)
+ return arg+1;
+ else
+ return __progname;
+}
+# define GET_PROGRAM_NAME() __getProgramName()
+# else
+# define GET_PROGRAM_NAME() ""
+# warning "Per application configuration won't work with your OS version."
+# endif
+#endif
+
+/** \brief Find an option in an option cache with the name as key */
+static GLuint findOption (const driOptionCache *cache, const char *name) {
+ GLuint len = strlen (name);
+ GLuint size = 1 << cache->tableSize, mask = size - 1;
+ GLuint hash = 0;
+ GLuint i, shift;
+
+ /* compute a hash from the variable length name */
+ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
+ hash += (GLuint)name[i] << shift;
+ hash *= hash;
+ hash = (hash >> (16-cache->tableSize/2)) & mask;
+
+ /* this is just the starting point of the linear search for the option */
+ for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
+ /* if we hit an empty entry then the option is not defined (yet) */
+ if (cache->info[hash].name == 0)
+ break;
+ else if (!strcmp (name, cache->info[hash].name))
+ break;
+ }
+ /* this assertion fails if the hash table is full */
+ assert (i < size);
+
+ return hash;
+}
+
+/** \brief Count the real number of options in an option cache */
+static GLuint countOptions (const driOptionCache *cache) {
+ GLuint size = 1 << cache->tableSize;
+ GLuint i, count = 0;
+ for (i = 0; i < size; ++i)
+ if (cache->info[i].name)
+ count++;
+ return count;
+}
+
+/** \brief Like strdup but using MALLOC and with error checking. */
+#define XSTRDUP(dest,source) do { \
+ GLuint len = strlen (source); \
+ if (!(dest = MALLOC (len+1))) { \
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ memcpy (dest, source, len+1); \
+} while (0)
+
+static int compare (const void *a, const void *b) {
+ return strcmp (*(char *const*)a, *(char *const*)b);
+}
+/** \brief Binary search in a string array. */
+static GLuint bsearchStr (const XML_Char *name,
+ const XML_Char *elems[], GLuint count) {
+ const XML_Char **found;
+ found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
+ if (found)
+ return found - elems;
+ else
+ return count;
+}
+
+/** \brief Locale-independent integer parser.
+ *
+ * Works similar to strtol. Leading space is NOT skipped. The input
+ * number may have an optional sign. Radix is specified by base. If
+ * base is 0 then decimal is assumed unless the input number is
+ * prefixed by 0x or 0X for hexadecimal or 0 for octal. After
+ * returning tail points to the first character that is not part of
+ * the integer number. If no number was found then tail points to the
+ * start of the input string. */
+static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
+ GLint radix = base == 0 ? 10 : base;
+ GLint result = 0;
+ GLint sign = 1;
+ GLboolean numberFound = GL_FALSE;
+ const XML_Char *start = string;
+
+ assert (radix >= 2 && radix <= 36);
+
+ if (*string == '-') {
+ sign = -1;
+ string++;
+ } else if (*string == '+')
+ string++;
+ if (base == 0 && *string == '0') {
+ numberFound = GL_TRUE;
+ if (*(string+1) == 'x' || *(string+1) == 'X') {
+ radix = 16;
+ string += 2;
+ } else {
+ radix = 8;
+ string++;
+ }
+ }
+ do {
+ GLint digit = -1;
+ if (radix <= 10) {
+ if (*string >= '0' && *string < '0' + radix)
+ digit = *string - '0';
+ } else {
+ if (*string >= '0' && *string <= '9')
+ digit = *string - '0';
+ else if (*string >= 'a' && *string < 'a' + radix - 10)
+ digit = *string - 'a' + 10;
+ else if (*string >= 'A' && *string < 'A' + radix - 10)
+ digit = *string - 'A' + 10;
+ }
+ if (digit != -1) {
+ numberFound = GL_TRUE;
+ result = radix*result + digit;
+ string++;
+ } else
+ break;
+ } while (GL_TRUE);
+ *tail = numberFound ? string : start;
+ return sign * result;
+}
+
+/** \brief Locale-independent floating-point parser.
+ *
+ * Works similar to strtod. Leading space is NOT skipped. The input
+ * number may have an optional sign. '.' is interpreted as decimal
+ * point and may occor at most once. Optionally the number may end in
+ * [eE]<exponent>, where <exponent> is an integer as recognized by
+ * strToI. In that case the result is number * 10^exponent. After
+ * returning tail points to the first character that is not part of
+ * the floating point number. If no number was found then tail points
+ * to the start of the input string.
+ *
+ * Uses two passes for maximum accuracy. */
+static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
+ GLint nDigits = 0, pointPos, exponent;
+ GLfloat sign = 1.0f, result = 0.0f, scale;
+ const XML_Char *start = string, *numStart;
+
+ /* sign */
+ if (*string == '-') {
+ sign = -1.0f;
+ string++;
+ } else if (*string == '+')
+ string++;
+
+ /* first pass: determine position of decimal point, number of
+ * digits, exponent and the end of the number. */
+ numStart = string;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ pointPos = nDigits;
+ if (*string == '.') {
+ string++;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ }
+ if (nDigits == 0) {
+ /* no digits, no number */
+ *tail = start;
+ return 0.0f;
+ }
+ *tail = string;
+ if (*string == 'e' || *string == 'E') {
+ const XML_Char *expTail;
+ exponent = strToI (string+1, &expTail, 10);
+ if (expTail == string+1)
+ exponent = 0;
+ else
+ *tail = expTail;
+ } else
+ exponent = 0;
+ string = numStart;
+
+ /* scale of the first digit */
+ scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent));
+
+ /* second pass: parse digits */
+ do {
+ if (*string != '.') {
+ assert (*string >= '0' && *string <= '9');
+ result += scale * (GLfloat)(*string - '0');
+ scale *= 0.1f;
+ nDigits--;
+ }
+ string++;
+ } while (nDigits > 0);
+
+ return result;
+}
+
+/** \brief Parse a value of a given type. */
+static GLboolean parseValue (driOptionValue *v, driOptionType type,
+ const XML_Char *string) {
+ const XML_Char *tail = NULL;
+ /* skip leading white-space */
+ string += strspn (string, " \f\n\r\t\v");
+ switch (type) {
+ case DRI_BOOL:
+ if (!strcmp (string, "false")) {
+ v->_bool = GL_FALSE;
+ tail = string + 5;
+ } else if (!strcmp (string, "true")) {
+ v->_bool = GL_TRUE;
+ tail = string + 4;
+ }
+ else
+ return GL_FALSE;
+ break;
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ v->_int = strToI (string, &tail, 0);
+ break;
+ case DRI_FLOAT:
+ v->_float = strToF (string, &tail);
+ break;
+ }
+
+ if (tail == string)
+ return GL_FALSE; /* empty string (or containing only white-space) */
+ /* skip trailing white space */
+ if (*tail)
+ tail += strspn (tail, " \f\n\r\t\v");
+ if (*tail)
+ return GL_FALSE; /* something left over that is not part of value */
+
+ return GL_TRUE;
+}
+
+/** \brief Parse a list of ranges of type info->type. */
+static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
+ XML_Char *cp, *range;
+ GLuint nRanges, i;
+ driOptionRange *ranges;
+
+ XSTRDUP (cp, string);
+ /* pass 1: determine the number of ranges (number of commas + 1) */
+ range = cp;
+ for (nRanges = 1; *range; ++range)
+ if (*range == ',')
+ ++nRanges;
+
+ if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ /* pass 2: parse all ranges into preallocated array */
+ range = cp;
+ for (i = 0; i < nRanges; ++i) {
+ XML_Char *end, *sep;
+ assert (range);
+ end = strchr (range, ',');
+ if (end)
+ *end = '\0';
+ sep = strchr (range, ':');
+ if (sep) { /* non-empty interval */
+ *sep = '\0';
+ if (!parseValue (&ranges[i].start, info->type, range) ||
+ !parseValue (&ranges[i].end, info->type, sep+1))
+ break;
+ if (info->type == DRI_INT &&
+ ranges[i].start._int > ranges[i].end._int)
+ break;
+ if (info->type == DRI_FLOAT &&
+ ranges[i].start._float > ranges[i].end._float)
+ break;
+ } else { /* empty interval */
+ if (!parseValue (&ranges[i].start, info->type, range))
+ break;
+ ranges[i].end = ranges[i].start;
+ }
+ if (end)
+ range = end+1;
+ else
+ range = NULL;
+ }
+ FREE (cp);
+ if (i < nRanges) {
+ FREE (ranges);
+ return GL_FALSE;
+ } else
+ assert (range == NULL);
+
+ info->nRanges = nRanges;
+ info->ranges = ranges;
+ return GL_TRUE;
+}
+
+/** \brief Check if a value is in one of info->ranges. */
+static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
+ GLuint i;
+ assert (info->type != DRI_BOOL); /* should be caught by the parser */
+ if (info->nRanges == 0)
+ return GL_TRUE;
+ switch (info->type) {
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_int >= info->ranges[i].start._int &&
+ v->_int <= info->ranges[i].end._int)
+ return GL_TRUE;
+ break;
+ case DRI_FLOAT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_float >= info->ranges[i].start._float &&
+ v->_float <= info->ranges[i].end._float)
+ return GL_TRUE;
+ break;
+ default:
+ assert (0); /* should never happen */
+ }
+ return GL_FALSE;
+}
+
+/** \brief Output a warning message. */
+#define XML_WARNING1(msg) do {\
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_WARNING(msg,args...) do { \
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output an error message. */
+#define XML_ERROR1(msg) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_ERROR(msg,args...) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output a fatal error message and abort. */
+#define XML_FATAL1(msg) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser)); \
+ abort();\
+} while (0)
+#define XML_FATAL(msg,args...) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ (int) XML_GetCurrentLineNumber(data->parser), \
+ (int) XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+ abort();\
+} while (0)
+
+/** \brief Parser context for __driConfigOptions. */
+struct OptInfoData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLboolean inDriInfo;
+ GLboolean inSection;
+ GLboolean inDesc;
+ GLboolean inOption;
+ GLboolean inEnum;
+ int curOption;
+};
+
+/** \brief Elements in __driConfigOptions. */
+enum OptInfoElem {
+ OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
+};
+static const XML_Char *OptInfoElems[] = {
+ "description", "driinfo", "enum", "option", "section"
+};
+
+/** \brief Parse attributes of an enum element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *value = NULL, *text = NULL;
+ driOptionValue v;
+ GLuint opt = data->curOption;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal enum attribute: %s.", attr[i]);
+ }
+ if (!value) XML_FATAL1 ("value attribute missing in enum.");
+ if (!text) XML_FATAL1 ("text attribute missing in enum.");
+ if (!parseValue (&v, data->cache->info[opt].type, value))
+ XML_FATAL ("illegal enum value: %s.", value);
+ if (!checkValue (&v, &data->cache->info[opt]))
+ XML_FATAL ("enum value out of valid range: %s.", value);
+}
+
+/** \brief Parse attributes of a description element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *lang = NULL, *text = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "lang")) lang = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal description attribute: %s.", attr[i]);
+ }
+ if (!lang) XML_FATAL1 ("lang attribute missing in description.");
+ if (!text) XML_FATAL1 ("text attribute missing in description.");
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
+ enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
+ static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
+ const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
+ const char *defaultVal;
+ driOptionCache *cache = data->cache;
+ GLuint opt, i;
+ for (i = 0; attr[i]; i += 2) {
+ GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
+ if (attrName >= OA_COUNT)
+ XML_FATAL ("illegal option attribute: %s", attr[i]);
+ attrVal[attrName] = attr[i+1];
+ }
+ if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option.");
+ if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option.");
+ if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option.");
+
+ opt = findOption (cache, attrVal[OA_NAME]);
+ if (cache->info[opt].name)
+ XML_FATAL ("option %s redefined.", attrVal[OA_NAME]);
+ data->curOption = opt;
+
+ XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]);
+
+ if (!strcmp (attrVal[OA_TYPE], "bool"))
+ cache->info[opt].type = DRI_BOOL;
+ else if (!strcmp (attrVal[OA_TYPE], "enum"))
+ cache->info[opt].type = DRI_ENUM;
+ else if (!strcmp (attrVal[OA_TYPE], "int"))
+ cache->info[opt].type = DRI_INT;
+ else if (!strcmp (attrVal[OA_TYPE], "float"))
+ cache->info[opt].type = DRI_FLOAT;
+ else
+ XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
+
+ defaultVal = getenv (cache->info[opt].name);
+ if (defaultVal != NULL) {
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr,
+ "ATTENTION: default value of option %s overridden by environment.\n",
+ cache->info[opt].name);
+ } else
+ defaultVal = attrVal[OA_DEFAULT];
+ if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
+ XML_FATAL ("illegal default value: %s.", defaultVal);
+
+ if (attrVal[OA_VALID]) {
+ if (cache->info[opt].type == DRI_BOOL)
+ XML_FATAL1 ("boolean option with valid attribute.");
+ if (!parseRanges (&cache->info[opt], attrVal[OA_VALID]))
+ XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]);
+ if (!checkValue (&cache->values[opt], &cache->info[opt]))
+ XML_FATAL ("default value out of valid range '%s': %s.",
+ attrVal[OA_VALID], defaultVal);
+ } else if (cache->info[opt].type == DRI_ENUM) {
+ XML_FATAL1 ("valid attribute missing in option (mandatory for enums).");
+ } else {
+ cache->info[opt].nRanges = 0;
+ cache->info[opt].ranges = NULL;
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optInfoStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ if (data->inDriInfo)
+ XML_FATAL1 ("nested <driinfo> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <driinfo> element.");
+ data->inDriInfo = GL_TRUE;
+ break;
+ case OI_SECTION:
+ if (!data->inDriInfo)
+ XML_FATAL1 ("<section> must be inside <driinfo>.");
+ if (data->inSection)
+ XML_FATAL1 ("nested <section> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <section> element.");
+ data->inSection = GL_TRUE;
+ break;
+ case OI_DESCRIPTION:
+ if (!data->inSection && !data->inOption)
+ XML_FATAL1 ("<description> must be inside <description> or <option.");
+ if (data->inDesc)
+ XML_FATAL1 ("nested <description> elements.");
+ data->inDesc = GL_TRUE;
+ parseDescAttr (data, attr);
+ break;
+ case OI_OPTION:
+ if (!data->inSection)
+ XML_FATAL1 ("<option> must be inside <section>.");
+ if (data->inDesc)
+ XML_FATAL1 ("<option> nested in <description> element.");
+ if (data->inOption)
+ XML_FATAL1 ("nested <option> elements.");
+ data->inOption = GL_TRUE;
+ parseOptInfoAttr (data, attr);
+ break;
+ case OI_ENUM:
+ if (!(data->inOption && data->inDesc))
+ XML_FATAL1 ("<enum> must be inside <option> and <description>.");
+ if (data->inEnum)
+ XML_FATAL1 ("nested <enum> elements.");
+ data->inEnum = GL_TRUE;
+ parseEnumAttr (data, attr);
+ break;
+ default:
+ XML_FATAL ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optInfoEndElem (void *userData, const XML_Char *name) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ data->inDriInfo = GL_FALSE;
+ break;
+ case OI_SECTION:
+ data->inSection = GL_FALSE;
+ break;
+ case OI_DESCRIPTION:
+ data->inDesc = GL_FALSE;
+ break;
+ case OI_OPTION:
+ data->inOption = GL_FALSE;
+ break;
+ case OI_ENUM:
+ data->inEnum = GL_FALSE;
+ break;
+ default:
+ assert (0); /* should have been caught by StartElem */
+ }
+}
+
+void driParseOptionInfo (driOptionCache *info,
+ const char *configOptions, GLuint nConfigOptions) {
+ XML_Parser p;
+ int status;
+ struct OptInfoData userData;
+ struct OptInfoData *data = &userData;
+ GLuint realNoptions;
+
+ /* determine hash table size and allocate memory:
+ * 3/2 of the number of options, rounded up, so there remains always
+ * at least one free entry. This is needed for detecting undefined
+ * options in configuration files without getting a hash table overflow.
+ * Round this up to a power of two. */
+ GLuint minSize = (nConfigOptions*3 + 1) / 2;
+ GLuint size, log2size;
+ for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size);
+ info->tableSize = log2size;
+ info->info = CALLOC (size * sizeof (driOptionInfo));
+ info->values = CALLOC (size * sizeof (driOptionValue));
+ if (info->info == NULL || info->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */
+ XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem);
+ XML_SetUserData (p, data);
+
+ userData.name = "__driConfigOptions";
+ userData.parser = p;
+ userData.cache = info;
+ userData.inDriInfo = GL_FALSE;
+ userData.inSection = GL_FALSE;
+ userData.inDesc = GL_FALSE;
+ userData.inOption = GL_FALSE;
+ userData.inEnum = GL_FALSE;
+ userData.curOption = -1;
+
+ status = XML_Parse (p, configOptions, strlen (configOptions), 1);
+ if (!status)
+ XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+
+ XML_ParserFree (p);
+
+ /* Check if the actual number of options matches nConfigOptions.
+ * A mismatch is not fatal (a hash table overflow would be) but we
+ * want the driver developer's attention anyway. */
+ realNoptions = countOptions (info);
+ if (realNoptions != nConfigOptions) {
+ fprintf (stderr,
+ "Error: nConfigOptions (%u) does not match the actual number of options in\n"
+ " __driConfigOptions (%u).\n",
+ nConfigOptions, realNoptions);
+ }
+}
+
+/** \brief Parser context for configuration files. */
+struct OptConfData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLint screenNum;
+ const char *driverName, *execName;
+ GLuint ignoringDevice;
+ GLuint ignoringApp;
+ GLuint inDriConf;
+ GLuint inDevice;
+ GLuint inApp;
+ GLuint inOption;
+};
+
+/** \brief Elements in configuration files. */
+enum OptConfElem {
+ OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT
+};
+static const XML_Char *OptConfElems[] = {
+ "application", "device", "driconf", "option"
+};
+
+/** \brief Parse attributes of a device element. */
+static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *driver = NULL, *screen = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "driver")) driver = attr[i+1];
+ else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
+ else XML_WARNING("unkown device attribute: %s.", attr[i]);
+ }
+ if (driver && strcmp (driver, data->driverName))
+ data->ignoringDevice = data->inDevice;
+ else if (screen) {
+ driOptionValue screenNum;
+ if (!parseValue (&screenNum, DRI_INT, screen))
+ XML_WARNING("illegal screen number: %s.", screen);
+ else if (screenNum._int != data->screenNum)
+ data->ignoringDevice = data->inDevice;
+ }
+}
+
+/** \brief Parse attributes of an application element. */
+static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *exec = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
+ else XML_WARNING("unkown application attribute: %s.", attr[i]);
+ }
+ if (exec && strcmp (exec, data->execName))
+ data->ignoringApp = data->inApp;
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *value = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else XML_WARNING("unkown option attribute: %s.", attr[i]);
+ }
+ if (!name) XML_WARNING1 ("name attribute missing in option.");
+ if (!value) XML_WARNING1 ("value attribute missing in option.");
+ if (name && value) {
+ driOptionCache *cache = data->cache;
+ GLuint opt = findOption (cache, name);
+ if (cache->info[opt].name == NULL)
+ XML_WARNING ("undefined option: %s.", name);
+ else if (getenv (cache->info[opt].name))
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
+ cache->info[opt].name);
+ else if (!parseValue (&cache->values[opt], cache->info[opt].type, value))
+ XML_WARNING ("illegal option value: %s.", value);
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optConfStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ if (data->inDriConf)
+ XML_WARNING1 ("nested <driconf> elements.");
+ if (attr[0])
+ XML_WARNING1 ("attributes specified on <driconf> element.");
+ data->inDriConf++;
+ break;
+ case OC_DEVICE:
+ if (!data->inDriConf)
+ XML_WARNING1 ("<device> should be inside <driconf>.");
+ if (data->inDevice)
+ XML_WARNING1 ("nested <device> elements.");
+ data->inDevice++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseDeviceAttr (data, attr);
+ break;
+ case OC_APPLICATION:
+ if (!data->inDevice)
+ XML_WARNING1 ("<application> should be inside <device>.");
+ if (data->inApp)
+ XML_WARNING1 ("nested <application> elements.");
+ data->inApp++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseAppAttr (data, attr);
+ break;
+ case OC_OPTION:
+ if (!data->inApp)
+ XML_WARNING1 ("<option> should be inside <application>.");
+ if (data->inOption)
+ XML_WARNING1 ("nested <option> elements.");
+ data->inOption++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseOptConfAttr (data, attr);
+ break;
+ default:
+ XML_WARNING ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optConfEndElem (void *userData, const XML_Char *name) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ data->inDriConf--;
+ break;
+ case OC_DEVICE:
+ if (data->inDevice-- == data->ignoringDevice)
+ data->ignoringDevice = 0;
+ break;
+ case OC_APPLICATION:
+ if (data->inApp-- == data->ignoringApp)
+ data->ignoringApp = 0;
+ break;
+ case OC_OPTION:
+ data->inOption--;
+ break;
+ default:
+ /* unknown element, warning was produced on start tag */;
+ }
+}
+
+/** \brief Initialize an option cache based on info */
+static void initOptionCache (driOptionCache *cache, const driOptionCache *info) {
+ cache->info = info->info;
+ cache->tableSize = info->tableSize;
+ cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
+ if (cache->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+ memcpy (cache->values, info->values,
+ (1<<info->tableSize) * sizeof (driOptionValue));
+}
+
+/** \brief Parse the named configuration file */
+static void parseOneConfigFile (XML_Parser p) {
+#define BUF_SIZE 0x1000
+ struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p);
+ int status;
+ int fd;
+
+ if ((fd = open (data->name, O_RDONLY)) == -1) {
+ __driUtilMessage ("Can't open configuration file %s: %s.",
+ data->name, strerror (errno));
+ return;
+ }
+
+ while (1) {
+ int bytesRead;
+ void *buffer = XML_GetBuffer (p, BUF_SIZE);
+ if (!buffer) {
+ __driUtilMessage ("Can't allocate parser buffer.");
+ break;
+ }
+ bytesRead = read (fd, buffer, BUF_SIZE);
+ if (bytesRead == -1) {
+ __driUtilMessage ("Error reading from configuration file %s: %s.",
+ data->name, strerror (errno));
+ break;
+ }
+ status = XML_ParseBuffer (p, bytesRead, bytesRead == 0);
+ if (!status) {
+ XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+ break;
+ }
+ if (bytesRead == 0)
+ break;
+ }
+
+ close (fd);
+#undef BUF_SIZE
+}
+
+void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
+ GLint screenNum, const char *driverName) {
+ char *filenames[2] = {"/etc/drirc", NULL};
+ char *home;
+ GLuint i;
+ struct OptConfData userData;
+
+ initOptionCache (cache, info);
+
+ userData.cache = cache;
+ userData.screenNum = screenNum;
+ userData.driverName = driverName;
+ userData.execName = GET_PROGRAM_NAME();
+
+ if ((home = getenv ("HOME"))) {
+ GLuint len = strlen (home);
+ filenames[1] = MALLOC (len + 7+1);
+ if (filenames[1] == NULL)
+ __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
+ else {
+ memcpy (filenames[1], home, len);
+ memcpy (filenames[1] + len, "/.drirc", 7+1);
+ }
+ }
+
+ for (i = 0; i < 2; ++i) {
+ XML_Parser p;
+ if (filenames[i] == NULL)
+ continue;
+
+ p = XML_ParserCreate (NULL); /* use encoding specified by file */
+ XML_SetElementHandler (p, optConfStartElem, optConfEndElem);
+ XML_SetUserData (p, &userData);
+ userData.parser = p;
+ userData.name = filenames[i];
+ userData.ignoringDevice = 0;
+ userData.ignoringApp = 0;
+ userData.inDriConf = 0;
+ userData.inDevice = 0;
+ userData.inApp = 0;
+ userData.inOption = 0;
+
+ parseOneConfigFile (p);
+ XML_ParserFree (p);
+ }
+
+ if (filenames[1])
+ FREE (filenames[1]);
+}
+
+void driDestroyOptionInfo (driOptionCache *info) {
+ driDestroyOptionCache (info);
+ if (info->info) {
+ GLuint i, size = 1 << info->tableSize;
+ for (i = 0; i < size; ++i) {
+ if (info->info[i].name) {
+ FREE (info->info[i].name);
+ if (info->info[i].ranges)
+ FREE (info->info[i].ranges);
+ }
+ }
+ FREE (info->info);
+ }
+}
+
+void driDestroyOptionCache (driOptionCache *cache) {
+ if (cache->values)
+ FREE (cache->values);
+}
+
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type) {
+ GLuint i = findOption (cache, name);
+ return cache->info[i].name != NULL && cache->info[i].type == type;
+}
+
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_BOOL);
+ return cache->values[i]._bool;
+}
+
+GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
+ return cache->values[i]._int;
+}
+
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_FLOAT);
+ return cache->values[i]._float;
+}
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.h b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h
new file mode 100644
index 000000000..c363af764
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h
@@ -0,0 +1,124 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file xmlconfig.h
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#ifndef __XMLCONFIG_H
+#define __XMLCONFIG_H
+
+/** \brief Option data types */
+typedef enum driOptionType {
+ DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT
+} driOptionType;
+
+/** \brief Option value */
+typedef union driOptionValue {
+ GLboolean _bool; /**< \brief Boolean */
+ GLint _int; /**< \brief Integer or Enum */
+ GLfloat _float; /**< \brief Floating-point */
+} driOptionValue;
+
+/** \brief Single range of valid values
+ *
+ * For empty ranges (a single value) start == end */
+typedef struct driOptionRange {
+ driOptionValue start; /**< \brief Start */
+ driOptionValue end; /**< \brief End */
+} driOptionRange;
+
+/** \brief Information about an option */
+typedef struct driOptionInfo {
+ char *name; /**< \brief Name */
+ driOptionType type; /**< \brief Type */
+ driOptionRange *ranges; /**< \brief Array of ranges */
+ GLuint nRanges; /**< \brief Number of ranges */
+} driOptionInfo;
+
+/** \brief Option cache
+ *
+ * \li One in <driver>Screen caching option info and the default values
+ * \li One in each <driver>Context with the actual values for that context */
+typedef struct driOptionCache {
+ driOptionInfo *info;
+ /**< \brief Array of option infos
+ *
+ * Points to the same array in the screen and all contexts */
+ driOptionValue *values;
+ /**< \brief Array of option values
+ *
+ * \li Default values in screen
+ * \li Actual values in contexts
+ */
+ GLuint tableSize;
+ /**< \brief Size of the arrays
+ *
+ * Depending on the hash function this may differ from __driNConfigOptions.
+ * In the current implementation it's not actually a size but log2(size).
+ * The value is the same in the screen and all contexts. */
+} driOptionCache;
+
+/** \brief Parse XML option info from configOptions
+ *
+ * To be called in <driver>CreateScreen
+ *
+ * \param info pointer to a driOptionCache that will store the option info
+ * \param configOptions XML document describing available configuration opts
+ * \param nConfigOptions number of options, used to choose a hash table size
+ *
+ * For the option information to be available to external configuration tools
+ * it must be a public symbol __driConfigOptions. It is also passed as a
+ * parameter to driParseOptionInfo in order to avoid driver-independent code
+ * depending on symbols in driver-specific code. */
+void driParseOptionInfo (driOptionCache *info,
+ const char *configOptions, GLuint nConfigOptions);
+/** \brief Initialize option cache from info and parse configuration files
+ *
+ * To be called in <driver>CreateContext. screenNum and driverName select
+ * device sections. */
+void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
+ GLint screenNum, const char *driverName);
+/** \brief Destroy option info
+ *
+ * To be called in <driver>DestroyScreen */
+void driDestroyOptionInfo (driOptionCache *info);
+/** \brief Destroy option cache
+ *
+ * To be called in <driver>DestroyContext */
+void driDestroyOptionCache (driOptionCache *cache);
+
+/** \brief Check if there exists a certain option */
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type);
+
+/** \brief Query a boolean option value */
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name);
+/** \brief Query an integer option value */
+GLint driQueryOptioni (const driOptionCache *cache, const char *name);
+/** \brief Query a floating-point option value */
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name);
+
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool.h b/mesalib/src/mesa/drivers/dri/common/xmlpool.h
new file mode 100644
index 000000000..587517ea1
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool.h
@@ -0,0 +1,98 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file xmlpool.h
+ * \brief Pool of common options
+ * \author Felix Kuehling
+ *
+ * This file defines macros that can be used to construct
+ * driConfigOptions in the drivers. Common options are defined in
+ * xmlpool/t_options.h from which xmlpool/options.h is generated with
+ * translations. This file defines generic helper macros and includes
+ * xmlpool/options.h.
+ */
+
+#ifndef __XMLPOOL_H
+#define __XMLPOOL_H
+
+/*
+ * generic macros
+ */
+
+/** \brief Begin __driConfigOptions */
+#define DRI_CONF_BEGIN \
+"<driinfo>\n"
+
+/** \brief End __driConfigOptions */
+#define DRI_CONF_END \
+"</driinfo>\n"
+
+/** \brief Begin a section of related options */
+#define DRI_CONF_SECTION_BEGIN \
+"<section>\n"
+
+/** \brief End a section of related options */
+#define DRI_CONF_SECTION_END \
+"</section>\n"
+
+/** \brief Begin an option definition */
+#define DRI_CONF_OPT_BEGIN(name,type,def) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n"
+
+/** \brief Begin an option definition with qouted default value */
+#define DRI_CONF_OPT_BEGIN_Q(name,type,def) \
+"<option name=\""#name"\" type=\""#type"\" default="#def">\n"
+
+/** \brief Begin an option definition with restrictions on valid values */
+#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n"
+
+/** \brief End an option description */
+#define DRI_CONF_OPT_END \
+"</option>\n"
+
+/** \brief A verbal description in a specified language (empty version) */
+#define DRI_CONF_DESC(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\"/>\n"
+
+/** \brief A verbal description in a specified language */
+#define DRI_CONF_DESC_BEGIN(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\">\n"
+
+/** \brief End a description */
+#define DRI_CONF_DESC_END \
+"</description>\n"
+
+/** \brief A verbal description of an enum value */
+#define DRI_CONF_ENUM(value,text) \
+"<enum value=\""#value"\" text=\""text"\"/>\n"
+
+
+/*
+ * Predefined option sections and options with multi-lingual descriptions
+ * are now automatically generated.
+ */
+#include "xmlpool/options.h"
+
+#endif
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile
new file mode 100644
index 000000000..62ec919ea
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile
@@ -0,0 +1,96 @@
+# Convenient makefile for managing translations.
+
+# Prerequisites:
+# - GNU gettext
+# - Python
+
+# Adding new translations
+# -----------------------
+
+# To start working on a new translation edit the POS=... line
+# below. If you want to add for example a french translation, add
+# fr.po.
+
+# Then run "make po" to generate a fresh .po file from translatable
+# strings in t_options.h. Now you can edit the new .po file (fr.po in
+# the example above) to translate the strings. Please make sure that
+# your editor encodes the file in UTF-8.
+
+# Updating existing translations
+# ------------------------------
+
+# Run "make po" to update .po files with new translatable strings from
+# t_options.h. Now you can edit the .po files you're interested
+# in. Please make sure that your editor encodes the file in UTF-8.
+
+# Updating options.h
+# ------------------
+
+# Finally run "make" to generate options.h from t_options.h with all
+# translations. Now you can rebuild the drivers. Any common options
+# used by the drivers will have option descriptions with the latest
+# translations.
+
+# Publishing translations
+# -----------------------
+
+# To get your translation(s) into Mesa CVS, please send me your
+# <lang>.po file.
+
+# More information:
+# - info gettext
+
+# The set of supported languages. Add languages as needed.
+POS=de.po es.po nl.po fr.po sv.po
+
+#
+# Don't change anything below, unless you know what you're doing.
+#
+LANGS=$(POS:%.po=%)
+MOS=$(POS:%.po=%/LC_MESSAGES/options.mo)
+POT=xmlpool.pot
+
+.PHONY: all clean pot po mo
+
+all: options.h
+
+# Only intermediate files are cleaned up. options.h is not deleted because
+# it's in CVS.
+clean:
+ -rm -f $(POT) *~
+ -rm -rf $(LANGS)
+
+# Default target options.h
+options.h: t_options.h mo
+ python gen_xmlpool.py $(LANGS) > options.h
+
+# Update .mo files from the corresponding .po files.
+mo:
+ @for mo in $(MOS); do \
+ lang=$${mo%%/*}; \
+ echo "Updating $$mo from $$lang.po."; \
+ mkdir -p $${mo%/*}; \
+ msgfmt -o $$mo $$lang.po; \
+ done
+
+# Use this target to create or update .po files with new messages in
+# driconf.py.
+po: $(POS)
+
+pot: $(POT)
+
+# Extract message catalog from driconf.py.
+$(POT): t_options.h
+ xgettext -L C --from-code utf-8 -o $(POT) t_options.h
+
+# Create or update a .po file for a specific language.
+%.po: $(POT)
+ @if [ -f $@ ]; then \
+ echo "Merging new strings from $(POT) into $@."; \
+ mv $@ $@~; \
+ msgmerge -o $@ $@~ $(POT); \
+ else \
+ echo "Initializing $@ from $(POT)."; \
+ msginit -i $(POT) -o $@~ --locale=$*; \
+ sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $@~ > $@; \
+ fi
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/de.po b/mesalib/src/mesa/drivers/dri/common/xmlpool/de.po
new file mode 100644
index 000000000..4ea82f901
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/de.po
@@ -0,0 +1,240 @@
+# German translations for DRI driver options.
+# Copyright (C) 2005 Felix Kuehling
+# This file is distributed under the same license as the Mesa package.
+# Felix Kuehling <fxkuehl@gmx.de>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Mesa 6.3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-04-11 23:19+0200\n"
+"PO-Revision-Date: 2005-04-11 01:34+0200\n"
+"Last-Translator: Felix Kuehling <fxkuehl@gmx.de>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: t_options.h:53
+msgid "Debugging"
+msgstr "Fehlersuche"
+
+#: t_options.h:57
+msgid "Disable 3D acceleration"
+msgstr "3D-Beschleunigung abschalten"
+
+#: t_options.h:62
+msgid "Show performance boxes"
+msgstr "Zeige Performanceboxen"
+
+#: t_options.h:69
+msgid "Image Quality"
+msgstr "Bildqualität"
+
+#: t_options.h:77
+msgid "Texture color depth"
+msgstr "Texturfarbtiefe"
+
+#: t_options.h:78
+msgid "Prefer frame buffer color depth"
+msgstr "Bevorzuge Farbtiefe des Framebuffers"
+
+#: t_options.h:79
+msgid "Prefer 32 bits per texel"
+msgstr "Bevorzuge 32 bits pro Texel"
+
+#: t_options.h:80
+msgid "Prefer 16 bits per texel"
+msgstr "Bevorzuge 16 bits pro Texel"
+
+#: t_options.h:81
+msgid "Force 16 bits per texel"
+msgstr "Erzwinge 16 bits pro Texel"
+
+#: t_options.h:87
+msgid "Initial maximum value for anisotropic texture filtering"
+msgstr "Initialer Maximalwert für anisotropische Texturfilterung"
+
+#: t_options.h:92
+msgid "Forbid negative texture LOD bias"
+msgstr "Verbiete negative Textur-Detailgradverschiebung"
+
+#: t_options.h:97
+msgid ""
+"Enable S3TC texture compression even if software support is not available"
+msgstr ""
+"Aktiviere S3TC Texturkomprimierung auch wenn die nötige "
+"Softwareunterstützung fehlt"
+
+#: t_options.h:104
+msgid "Initial color reduction method"
+msgstr "Initiale Farbreduktionsmethode"
+
+#: t_options.h:105
+msgid "Round colors"
+msgstr "Farben runden"
+
+#: t_options.h:106
+msgid "Dither colors"
+msgstr "Farben rastern"
+
+#: t_options.h:114
+msgid "Color rounding method"
+msgstr "Farbrundungsmethode"
+
+#: t_options.h:115
+msgid "Round color components downward"
+msgstr "Farbkomponenten abrunden"
+
+#: t_options.h:116
+msgid "Round to nearest color"
+msgstr "Zur ähnlichsten Farbe runden"
+
+#: t_options.h:125
+msgid "Color dithering method"
+msgstr "Farbrasterungsmethode"
+
+#: t_options.h:126
+msgid "Horizontal error diffusion"
+msgstr "Horizontale Fehlerstreuung"
+
+#: t_options.h:127
+msgid "Horizontal error diffusion, reset error at line start"
+msgstr "Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen"
+
+#: t_options.h:128
+msgid "Ordered 2D color dithering"
+msgstr "Geordnete 2D Farbrasterung"
+
+#: t_options.h:134
+msgid "Floating point depth buffer"
+msgstr "Fließkomma z-Puffer"
+
+#: t_options.h:140
+msgid "Performance"
+msgstr "Leistung"
+
+#: t_options.h:148
+msgid "TCL mode (Transformation, Clipping, Lighting)"
+msgstr "TCL-Modus (Transformation, Clipping, Licht)"
+
+#: t_options.h:149
+msgid "Use software TCL pipeline"
+msgstr "Benutze die Software-TCL-Pipeline"
+
+#: t_options.h:150
+msgid "Use hardware TCL as first TCL pipeline stage"
+msgstr "Benutze Hardware TCL als erste Stufe der TCL-Pipeline"
+
+#: t_options.h:151
+msgid "Bypass the TCL pipeline"
+msgstr "Umgehe die TCL-Pipeline"
+
+#: t_options.h:152
+msgid ""
+"Bypass the TCL pipeline with state-based machine code generated on-the-fly"
+msgstr ""
+"Umgehe die TCL-Pipeline mit zur Laufzeit erzeugtem, zustandsbasiertem "
+"Maschinencode"
+
+#: t_options.h:161
+msgid "Method to limit rendering latency"
+msgstr "Methode zur Begrenzung der Bildverzögerung"
+
+#: t_options.h:162
+msgid "Busy waiting for the graphics hardware"
+msgstr "Aktives Warten auf die Grafikhardware"
+
+#: t_options.h:163
+msgid "Sleep for brief intervals while waiting for the graphics hardware"
+msgstr "Kurze Schlafintervalle beim Warten auf die Grafikhardware"
+
+#: t_options.h:164
+msgid "Let the graphics hardware emit a software interrupt and sleep"
+msgstr ""
+"Die Grafikhardware eine Softwareunterbrechnung erzeugen lassen und schlafen"
+
+#: t_options.h:174
+msgid "Synchronization with vertical refresh (swap intervals)"
+msgstr "Synchronisation mit der vertikalen Bildwiederholung"
+
+#: t_options.h:175
+msgid "Never synchronize with vertical refresh, ignore application's choice"
+msgstr ""
+"Niemals mit der Bildwiederholung synchronisieren, Anweisungen der Anwendung "
+"ignorieren"
+
+#: t_options.h:176
+msgid "Initial swap interval 0, obey application's choice"
+msgstr "Initiales Bildinterval 0, Anweisungen der Anwendung gehorchen"
+
+#: t_options.h:177
+msgid "Initial swap interval 1, obey application's choice"
+msgstr "Initiales Bildinterval 1, Anweisungen der Anwendung gehorchen"
+
+#: t_options.h:178
+msgid ""
+"Always synchronize with vertical refresh, application chooses the minimum "
+"swap interval"
+msgstr ""
+"Immer mit der Bildwiederholung synchronisieren, Anwendung wählt das minimale "
+"Bildintervall"
+
+#: t_options.h:186
+msgid "Use HyperZ to boost performance"
+msgstr "HyperZ zur Leistungssteigerung verwenden"
+
+#: t_options.h:191
+msgid "Number of texture units used"
+msgstr "Anzahl der benutzten Textureinheiten"
+
+#: t_options.h:196
+msgid "Support larger textures not guaranteed to fit into graphics memory"
+msgstr "Unterstütze grosse Texturen die evtl. nicht in den Grafikspeicher passen"
+
+#: t_options.h:197
+msgid "No"
+msgstr "Nein"
+
+#: t_options.h:198
+msgid "At least 1 texture must fit under worst-case assumptions"
+msgstr "Mindestens 1 Textur muss auch im schlechtesten Fall Platz haben"
+
+#: t_options.h:199
+msgid "Announce hardware limits"
+msgstr "Benutze Hardware-Limits"
+
+#: t_options.h:205
+msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering"
+msgstr ""
+"Texturfilterqualität versus -geschwindigkeit, auch bekannt als „brilineare“ "
+"Texturfilterung"
+
+#: t_options.h:213
+msgid "Used types of texture memory"
+msgstr "Benutzte Arten von Texturspeicher"
+
+#: t_options.h:214
+msgid "All available memory"
+msgstr "Aller verfügbarer Speicher"
+
+#: t_options.h:215
+msgid "Only card memory (if available)"
+msgstr "Nur Grafikspeicher (falls verfügbar)"
+
+#: t_options.h:216
+msgid "Only GART (AGP/PCIE) memory (if available)"
+msgstr "Nur GART-Speicher (AGP/PCIE) (falls verfügbar)"
+
+#: t_options.h:224
+msgid "Features that are not hardware-accelerated"
+msgstr "Funktionalität, die nicht hardwarebeschleunigt ist"
+
+#: t_options.h:228
+msgid "Enable extension GL_ARB_vertex_program"
+msgstr "Erweiterung GL_ARB_vertex_program aktivieren"
+
+#: t_options.h:233
+msgid "Enable extension GL_NV_vertex_program"
+msgstr "Erweiterung GL_NV_vertex_program aktivieren"
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/es.po b/mesalib/src/mesa/drivers/dri/common/xmlpool/es.po
new file mode 100644
index 000000000..82ad177cb
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/es.po
@@ -0,0 +1,219 @@
+# translation of es.po to Spanish
+# Spanish translations for PACKAGE package.
+# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# David <deifo@ono.com>, 2005.
+# David Rubio Miguélez <deifo@ono.com>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: es\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-04-12 12:18+0200\n"
+"PO-Revision-Date: 2005-04-12 20:26+0200\n"
+"Last-Translator: David Rubio Miguélez <deifo@ono.com>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.10\n"
+
+#: t_options.h:53
+msgid "Debugging"
+msgstr "Depurando"
+
+#: t_options.h:57
+msgid "Disable 3D acceleration"
+msgstr "Desactivar aceleración 3D"
+
+#: t_options.h:62
+msgid "Show performance boxes"
+msgstr "Mostrar cajas de rendimiento"
+
+#: t_options.h:69
+msgid "Image Quality"
+msgstr "Calidad de imagen"
+
+#: t_options.h:77
+msgid "Texture color depth"
+msgstr "Profundidad de color de textura"
+
+#: t_options.h:78
+msgid "Prefer frame buffer color depth"
+msgstr "Preferir profundidad de color del \"framebuffer\""
+
+#: t_options.h:79
+msgid "Prefer 32 bits per texel"
+msgstr "Preferir 32 bits por texel"
+
+#: t_options.h:80
+msgid "Prefer 16 bits per texel"
+msgstr "Preferir 16 bits por texel"
+
+#: t_options.h:81
+msgid "Force 16 bits per texel"
+msgstr "Forzar a 16 bits por texel"
+
+#: t_options.h:87
+msgid "Initial maximum value for anisotropic texture filtering"
+msgstr "Valor máximo inicial para filtrado anisotrópico de textura"
+
+#: t_options.h:92
+msgid "Forbid negative texture LOD bias"
+msgstr "Prohibir valores negativos de Nivel De Detalle (LOD) de texturas"
+
+#: t_options.h:97
+msgid "Enable S3TC texture compression even if software support is not available"
+msgstr "Activar la compresión de texturas S3TC incluso si el soporte por software no está disponible"
+
+#: t_options.h:104
+msgid "Initial color reduction method"
+msgstr "Método inicial de reducción de color"
+
+#: t_options.h:105
+msgid "Round colors"
+msgstr "Colores redondeados"
+
+#: t_options.h:106
+msgid "Dither colors"
+msgstr "Colores suavizados"
+
+#: t_options.h:114
+msgid "Color rounding method"
+msgstr "Método de redondeo de colores"
+
+#: t_options.h:115
+msgid "Round color components downward"
+msgstr "Redondear hacia abajo los componentes de color"
+
+#: t_options.h:116
+msgid "Round to nearest color"
+msgstr "Redondear al color más cercano"
+
+#: t_options.h:125
+msgid "Color dithering method"
+msgstr "Método de suavizado de color"
+
+#: t_options.h:126
+msgid "Horizontal error diffusion"
+msgstr "Difusión de error horizontal"
+
+#: t_options.h:127
+msgid "Horizontal error diffusion, reset error at line start"
+msgstr "Difusión de error horizontal, reiniciar error al comienzo de línea"
+
+#: t_options.h:128
+msgid "Ordered 2D color dithering"
+msgstr "Suavizado de color 2D ordenado"
+
+#: t_options.h:134
+msgid "Floating point depth buffer"
+msgstr "Búfer de profundidad en coma flotante"
+
+#: t_options.h:140
+msgid "Performance"
+msgstr "Rendimiento"
+
+#: t_options.h:148
+msgid "TCL mode (Transformation, Clipping, Lighting)"
+msgstr "Modo TCL (Transformación, Recorte, Iluminación)"
+
+#: t_options.h:149
+msgid "Use software TCL pipeline"
+msgstr "Usar tubería TCL por software"
+
+#: t_options.h:150
+msgid "Use hardware TCL as first TCL pipeline stage"
+msgstr "Usar TCL por hardware en la primera fase de la tubería TCL"
+
+#: t_options.h:151
+msgid "Bypass the TCL pipeline"
+msgstr "Pasar por alto la tubería TCL"
+
+#: t_options.h:152
+msgid "Bypass the TCL pipeline with state-based machine code generated on-the-fly"
+msgstr "Pasar por alto la tubería TCL con código máquina basado en estados generado al vuelo"
+
+#: t_options.h:161
+msgid "Method to limit rendering latency"
+msgstr "Método para limitar la latencia de rénder"
+
+#: t_options.h:162
+msgid "Busy waiting for the graphics hardware"
+msgstr "Esperar activamente al hardware gráfico"
+
+#: t_options.h:163
+msgid "Sleep for brief intervals while waiting for the graphics hardware"
+msgstr "Dormir en intervalos cortos mientras se espera al hardware gráfico"
+
+#: t_options.h:164
+msgid "Let the graphics hardware emit a software interrupt and sleep"
+msgstr "Permitir que el hardware gráfico emita una interrupción de software y duerma"
+
+#: t_options.h:174
+msgid "Synchronization with vertical refresh (swap intervals)"
+msgstr "Sincronización con el refresco vertical (intervalos de intercambio)"
+
+#: t_options.h:175
+msgid "Never synchronize with vertical refresh, ignore application's choice"
+msgstr "No sincronizar nunca con el refresco vertical, ignorar la elección de la aplicación"
+
+#: t_options.h:176
+msgid "Initial swap interval 0, obey application's choice"
+msgstr "Intervalo de intercambio inicial 0, obedecer la elección de la aplicación"
+
+#: t_options.h:177
+msgid "Initial swap interval 1, obey application's choice"
+msgstr "Intervalo de intercambio inicial 1, obedecer la elección de la aplicación"
+
+#: t_options.h:178
+msgid ""
+"Always synchronize with vertical refresh, application chooses the minimum "
+"swap interval"
+msgstr "Sincronizar siempre con el refresco vertical, la aplicación elige el intervalo de intercambio mínimo"
+
+#: t_options.h:186
+msgid "Use HyperZ to boost performance"
+msgstr "Usar HyperZ para potenciar rendimiento"
+
+#: t_options.h:191
+msgid "Number of texture units used"
+msgstr "Número de unidades de textura usadas"
+
+#: t_options.h:196
+msgid "Enable hack to allow larger textures with texture compression on radeon/r200"
+msgstr "Activar \"hack\" para permitir texturas más grandes con compresión de textura activada en la Radeon/r200"
+
+#: t_options.h:201
+msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering"
+msgstr "Calidad de filtrado de textura vs. velocidad, alias filtrado \"brilinear\" de textura"
+
+#: t_options.h:209
+msgid "Used types of texture memory"
+msgstr "Tipos de memoria de textura usados"
+
+#: t_options.h:210
+msgid "All available memory"
+msgstr "Toda la memoria disponible"
+
+#: t_options.h:211
+msgid "Only card memory (if available)"
+msgstr "Sólo la memoria de la tarjeta (si disponible)"
+
+#: t_options.h:212
+msgid "Only GART (AGP/PCIE) memory (if available)"
+msgstr "Sólo memoria GART (AGP/PCIE) (si disponible)"
+
+#: t_options.h:220
+msgid "Features that are not hardware-accelerated"
+msgstr "Características no aceleradas por hardware"
+
+#: t_options.h:224
+msgid "Enable extension GL_ARB_vertex_program"
+msgstr "Activar la extensión GL_ARB_vertex_program"
+
+#: t_options.h:229
+msgid "Enable extension GL_NV_vertex_program"
+msgstr "Activar extensión GL_NV_vertex_program"
+
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/fr.po b/mesalib/src/mesa/drivers/dri/common/xmlpool/fr.po
new file mode 100644
index 000000000..19f3b4a4e
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/fr.po
@@ -0,0 +1,225 @@
+# French translations for DRI driver options.
+# Copyright (C) 2005 Stephane Marchesin
+# This file is distributed under the same license as the Mesa package.
+# Stephane Marchesin <marchesin@icps.u-strasbg.fr>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Mesa 6.3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-04-11 23:19+0200\n"
+"PO-Revision-Date: 2005-04-11 01:34+0200\n"
+"Last-Translator: Stephane Marchesin <marchesin@icps.u-strasbg.fr>\n"
+"Language-Team: French <fr@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: t_options.h:53
+msgid "Debugging"
+msgstr "Debogage"
+
+#: t_options.h:57
+msgid "Disable 3D acceleration"
+msgstr "Désactiver l'accélération 3D"
+
+#: t_options.h:62
+msgid "Show performance boxes"
+msgstr "Afficher les boîtes de performance"
+
+#: t_options.h:69
+msgid "Image Quality"
+msgstr "Qualité d'image"
+
+#: t_options.h:77
+msgid "Texture color depth"
+msgstr "Profondeur de texture"
+
+#: t_options.h:78
+msgid "Prefer frame buffer color depth"
+msgstr "Profondeur de couleur"
+
+#: t_options.h:79
+msgid "Prefer 32 bits per texel"
+msgstr "Préférer 32 bits par texel"
+
+#: t_options.h:80
+msgid "Prefer 16 bits per texel"
+msgstr "Prérérer 16 bits par texel"
+
+#: t_options.h:81
+msgid "Force 16 bits per texel"
+msgstr "Forcer 16 bits par texel"
+
+#: t_options.h:87
+msgid "Initial maximum value for anisotropic texture filtering"
+msgstr "Valeur maximale initiale pour le filtrage anisotropique de texture"
+
+#: t_options.h:92
+msgid "Forbid negative texture LOD bias"
+msgstr "Interdire le LOD bias negatif"
+
+#: t_options.h:97
+msgid ""
+"Enable S3TC texture compression even if software support is not available"
+msgstr ""
+"Activer la compression de texture S3TC même si le support logiciel est absent"
+
+#: t_options.h:104
+msgid "Initial color reduction method"
+msgstr "Technique de réduction de couleurs"
+
+#: t_options.h:105
+msgid "Round colors"
+msgstr "Arrondir les valeurs de couleur"
+
+#: t_options.h:106
+msgid "Dither colors"
+msgstr "Tramer les couleurs"
+
+#: t_options.h:114
+msgid "Color rounding method"
+msgstr "Méthode d'arrondi des couleurs"
+
+#: t_options.h:115
+msgid "Round color components downward"
+msgstr "Arrondi à l'inférieur"
+
+#: t_options.h:116
+msgid "Round to nearest color"
+msgstr "Arrondi au plus proche"
+
+#: t_options.h:125
+msgid "Color dithering method"
+msgstr "Méthode de tramage"
+
+#: t_options.h:126
+msgid "Horizontal error diffusion"
+msgstr "Diffusion d'erreur horizontale"
+
+#: t_options.h:127
+msgid "Horizontal error diffusion, reset error at line start"
+msgstr "Diffusion d'erreur horizontale, réinitialisé pour chaque ligne"
+
+#: t_options.h:128
+msgid "Ordered 2D color dithering"
+msgstr "Tramage ordonné des couleurs"
+
+#: t_options.h:134
+msgid "Floating point depth buffer"
+msgstr "Z-buffer en virgule flottante"
+
+#: t_options.h:140
+msgid "Performance"
+msgstr "Performance"
+
+#: t_options.h:148
+msgid "TCL mode (Transformation, Clipping, Lighting)"
+msgstr "Mode de TCL (Transformation, Clipping, Eclairage)"
+
+#: t_options.h:149
+msgid "Use software TCL pipeline"
+msgstr "Utiliser un pipeline TCL logiciel"
+
+#: t_options.h:150
+msgid "Use hardware TCL as first TCL pipeline stage"
+msgstr "Utiliser le TCL matériel pour le premier niveau de pipeline"
+
+#: t_options.h:151
+msgid "Bypass the TCL pipeline"
+msgstr "Court-circuiter le pipeline TCL"
+
+#: t_options.h:152
+msgid ""
+"Bypass the TCL pipeline with state-based machine code generated on-the-fly"
+msgstr ""
+"Court-circuiter le pipeline TCL par une machine à états qui génère le code"
+"de TCL à la volée"
+
+#: t_options.h:161
+msgid "Method to limit rendering latency"
+msgstr "Méthode d'attente de la carte graphique"
+
+#: t_options.h:162
+msgid "Busy waiting for the graphics hardware"
+msgstr "Attente active de la carte graphique"
+
+#: t_options.h:163
+msgid "Sleep for brief intervals while waiting for the graphics hardware"
+msgstr "Attente utilisant usleep()"
+
+#: t_options.h:164
+msgid "Let the graphics hardware emit a software interrupt and sleep"
+msgstr "Utiliser les interruptions"
+
+#: t_options.h:174
+msgid "Synchronization with vertical refresh (swap intervals)"
+msgstr "Synchronisation de l'affichage avec le balayage vertical"
+
+#: t_options.h:175
+msgid "Never synchronize with vertical refresh, ignore application's choice"
+msgstr "Ne jamais synchroniser avec le balayage vertical, ignorer le choix de l'application"
+
+#: t_options.h:176
+msgid "Initial swap interval 0, obey application's choice"
+msgstr "Ne pas synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application"
+
+#: t_options.h:177
+msgid "Initial swap interval 1, obey application's choice"
+msgstr "Synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application"
+
+#: t_options.h:178
+msgid ""
+"Always synchronize with vertical refresh, application chooses the minimum "
+"swap interval"
+msgstr ""
+"Toujours synchroniser avec le balayage vertical, l'application choisit l'intervalle minimal"
+
+#: t_options.h:186
+msgid "Use HyperZ to boost performance"
+msgstr "Utiliser le HyperZ pour améliorer les performances"
+
+#: t_options.h:191
+msgid "Number of texture units used"
+msgstr "Nombre d'unités de texture"
+
+#: t_options.h:196
+msgid ""
+"Enable hack to allow larger textures with texture compression on radeon/r200"
+msgstr ""
+"Activer le hack permettant l'utilisation de textures de grande taille avec la "
+"compression de textures sur radeon/r200"
+
+#: t_options.h:201
+msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering"
+msgstr ""
+"Qualité/performance du filtrage trilinéaire de texture (filtrage brilinéaire)"
+
+#: t_options.h:209
+msgid "Used types of texture memory"
+msgstr "Types de mémoire de texture"
+
+#: t_options.h:210
+msgid "All available memory"
+msgstr "Utiliser toute la mémoire disponible"
+
+#: t_options.h:211
+msgid "Only card memory (if available)"
+msgstr "Utiliser uniquement la mémoire graphique (si disponible)"
+
+#: t_options.h:212
+msgid "Only GART (AGP/PCIE) memory (if available)"
+msgstr "Utiliser uniquement la mémoire GART (AGP/PCIE) (si disponible)"
+
+#: t_options.h:220
+msgid "Features that are not hardware-accelerated"
+msgstr "Fonctionnalités ne bénéficiant pas d'une accélération matérielle"
+
+#: t_options.h:224
+msgid "Enable extension GL_ARB_vertex_program"
+msgstr "Activer l'extension GL_ARB_vertex_program"
+
+#: t_options.h:229
+msgid "Enable extension GL_NV_vertex_program"
+msgstr "Activer l'extension GL_NV_vertex_program"
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/nl.po b/mesalib/src/mesa/drivers/dri/common/xmlpool/nl.po
new file mode 100644
index 000000000..1e4cf167b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/nl.po
@@ -0,0 +1,230 @@
+# Dutch translations for PACKAGE package.
+# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# <manfred.stienstra@dwerg.net>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-04-12 20:09+0200\n"
+"PO-Revision-Date: 2005-04-12 20:09+0200\n"
+"Last-Translator: Manfred Stienstra <manfred.stienstra@dwerg.net>\n"
+"Language-Team: Dutch <vertaling@nl.linux.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: t_options.h:53
+msgid "Debugging"
+msgstr "Debuggen"
+
+#: t_options.h:57
+msgid "Disable 3D acceleration"
+msgstr "3D versnelling uitschakelen"
+
+#: t_options.h:62
+msgid "Show performance boxes"
+msgstr "Laat prestatie boxjes zien"
+
+#: t_options.h:69
+msgid "Image Quality"
+msgstr "Beeldkwaliteit"
+
+#: t_options.h:77
+msgid "Texture color depth"
+msgstr "Textuurkleurendiepte"
+
+#: t_options.h:78
+msgid "Prefer frame buffer color depth"
+msgstr "Prefereer kaderbufferkleurdiepte"
+
+#: t_options.h:79
+msgid "Prefer 32 bits per texel"
+msgstr "Prefereer 32 bits per texel"
+
+#: t_options.h:80
+msgid "Prefer 16 bits per texel"
+msgstr "Prefereer 16 bits per texel"
+
+#: t_options.h:81
+msgid "Force 16 bits per texel"
+msgstr "Dwing 16 bits per texel af"
+
+#: t_options.h:87
+msgid "Initial maximum value for anisotropic texture filtering"
+msgstr "Initïele maximum waarde voor anisotrophische textuur filtering"
+
+#: t_options.h:92
+msgid "Forbid negative texture LOD bias"
+msgstr "Verbied negatief niveau detailonderscheid (LOD) van texturen"
+
+#: t_options.h:97
+msgid ""
+"Enable S3TC texture compression even if software support is not available"
+msgstr ""
+"Schakel S3TC textuurcompressie in, zelfs als softwareondersteuning niet "
+"aanwezig is"
+
+#: t_options.h:104
+msgid "Initial color reduction method"
+msgstr "Initïele kleurreductie methode"
+
+#: t_options.h:105
+msgid "Round colors"
+msgstr "Rond kleuren af"
+
+#: t_options.h:106
+msgid "Dither colors"
+msgstr "Rasteriseer kleuren"
+
+#: t_options.h:114
+msgid "Color rounding method"
+msgstr "Kleurafrondingmethode"
+
+#: t_options.h:115
+msgid "Round color components downward"
+msgstr "Rond kleurencomponenten af naar beneden"
+
+#: t_options.h:116
+msgid "Round to nearest color"
+msgstr "Rond af naar dichtsbijzijnde kleur"
+
+#: t_options.h:125
+msgid "Color dithering method"
+msgstr "Kleurrasteriseringsmethode"
+
+#: t_options.h:126
+msgid "Horizontal error diffusion"
+msgstr "Horizontale foutdiffusie"
+
+#: t_options.h:127
+msgid "Horizontal error diffusion, reset error at line start"
+msgstr "Horizontale foutdiffusie, zet fout bij lijnbegin terug"
+
+#: t_options.h:128
+msgid "Ordered 2D color dithering"
+msgstr "Geordende 2D kleurrasterisering"
+
+#: t_options.h:134
+msgid "Floating point depth buffer"
+msgstr "Dieptebuffer als commagetal"
+
+#: t_options.h:140
+msgid "Performance"
+msgstr "Prestatie"
+
+#: t_options.h:148
+msgid "TCL mode (Transformation, Clipping, Lighting)"
+msgstr "TCL-modus (Transformatie, Clipping, Licht)"
+
+#: t_options.h:149
+msgid "Use software TCL pipeline"
+msgstr "Gebruik software TCL pijpleiding"
+
+#: t_options.h:150
+msgid "Use hardware TCL as first TCL pipeline stage"
+msgstr "Gebruik hardware TCL as eerste TCL pijpleiding trap"
+
+#: t_options.h:151
+msgid "Bypass the TCL pipeline"
+msgstr "Omzeil de TCL pijpleiding"
+
+#: t_options.h:152
+msgid ""
+"Bypass the TCL pipeline with state-based machine code generated on-the-fly"
+msgstr ""
+"Omzeil de TCL pijpleiding met staatgebaseerde machinecode die tijdens "
+"executie gegenereerd wordt"
+
+#: t_options.h:161
+msgid "Method to limit rendering latency"
+msgstr "Methode om beeldopbouwvertraging te onderdrukken"
+
+#: t_options.h:162
+msgid "Busy waiting for the graphics hardware"
+msgstr "Actief wachten voor de grafische hardware"
+
+#: t_options.h:163
+msgid "Sleep for brief intervals while waiting for the graphics hardware"
+msgstr "Slaap voor korte intervallen tijdens het wachten op de grafische "
+"hardware"
+
+#: t_options.h:164
+msgid "Let the graphics hardware emit a software interrupt and sleep"
+msgstr "Laat de grafische hardware een software onderbreking uitzenden en in "
+"slaap vallen"
+
+#: t_options.h:174
+msgid "Synchronization with vertical refresh (swap intervals)"
+msgstr "Synchronisatie met verticale verversing (interval omwisselen)"
+
+#: t_options.h:175
+msgid "Never synchronize with vertical refresh, ignore application's choice"
+msgstr "Nooit synchroniseren met verticale verversing, negeer de keuze van de "
+"applicatie"
+
+#: t_options.h:176
+msgid "Initial swap interval 0, obey application's choice"
+msgstr "Initïeel omwisselingsinterval 0, honoreer de keuze van de applicatie"
+
+#: t_options.h:177
+msgid "Initial swap interval 1, obey application's choice"
+msgstr "Initïeel omwisselingsinterval 1, honoreer de keuze van de applicatie"
+
+#: t_options.h:178
+msgid ""
+"Always synchronize with vertical refresh, application chooses the minimum "
+"swap interval"
+msgstr ""
+"Synchroniseer altijd met verticale verversing, de applicatie kiest het "
+"minimum omwisselingsinterval"
+
+#: t_options.h:186
+msgid "Use HyperZ to boost performance"
+msgstr "Gebruik HyperZ om de prestaties te verbeteren"
+
+#: t_options.h:191
+msgid "Number of texture units used"
+msgstr "Aantal textuureenheden in gebruik"
+
+#: t_options.h:196
+msgid ""
+"Enable hack to allow larger textures with texture compression on radeon/r200"
+msgstr ""
+"Schakel hack in om met textuurcompressie grotere texturen toe te staan op "
+"een radeon/r200"
+
+#: t_options.h:201
+msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering"
+msgstr "Textuurfilterkwaliteit versus -snelheid, ookwel bekend als "
+"“brilineaire” textuurfiltering"
+
+#: t_options.h:209
+msgid "Used types of texture memory"
+msgstr "Gebruikte soorten textuurgeheugen"
+
+#: t_options.h:210
+msgid "All available memory"
+msgstr "Al het beschikbaar geheugen"
+
+#: t_options.h:211
+msgid "Only card memory (if available)"
+msgstr "Alleen geheugen op de kaart (als het aanwezig is)"
+
+#: t_options.h:212
+msgid "Only GART (AGP/PCIE) memory (if available)"
+msgstr "Alleen GART (AGP/PCIE) geheugen (als het aanwezig is)"
+
+#: t_options.h:220
+msgid "Features that are not hardware-accelerated"
+msgstr "Eigenschappen die niet hardwareversneld zijn"
+
+#: t_options.h:224
+msgid "Enable extension GL_ARB_vertex_program"
+msgstr "Zet uitbreiding GL_ARB_vertex_program aan"
+
+#: t_options.h:229
+msgid "Enable extension GL_NV_vertex_program"
+msgstr "Zet uitbreiding GL_NV_vertex_program aan"
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/options.h b/mesalib/src/mesa/drivers/dri/common/xmlpool/options.h
new file mode 100644
index 000000000..d76595578
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/options.h
@@ -0,0 +1,568 @@
+/***********************************************************************
+ *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***
+ ***********************************************************************/
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file t_options.h
+ * \brief Templates of common options
+ * \author Felix Kuehling
+ *
+ * This file defines macros for common options that can be used to
+ * construct driConfigOptions in the drivers. This file is only a
+ * template containing English descriptions for options wrapped in
+ * gettext(). xgettext can be used to extract translatable
+ * strings. These strings can then be translated by anyone familiar
+ * with GNU gettext. gen_xmlpool.py takes this template and fills in
+ * all the translations. The result (options.h) is included by
+ * xmlpool.h which in turn can be included by drivers.
+ *
+ * The macros used to describe otions in this file are defined in
+ * ../xmlpool.h.
+ */
+
+/* This is needed for xgettext to extract translatable strings.
+ * gen_xmlpool.py will discard this line. */
+/* #include <libintl.h>
+ * commented out by gen_xmlpool.py */
+
+/*
+ * predefined option sections and options with multi-lingual descriptions
+ */
+
+/** \brief Debugging options */
+#define DRI_CONF_SECTION_DEBUG \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Debugging") \
+ DRI_CONF_DESC(de,"Fehlersuche") \
+ DRI_CONF_DESC(es,"Depurando") \
+ DRI_CONF_DESC(nl,"Debuggen") \
+ DRI_CONF_DESC(fr,"Debogage") \
+ DRI_CONF_DESC(sv,"Felsökning")
+
+#define DRI_CONF_NO_RAST(def) \
+DRI_CONF_OPT_BEGIN(no_rast,bool,def) \
+ DRI_CONF_DESC(en,"Disable 3D acceleration") \
+ DRI_CONF_DESC(de,"3D-Beschleunigung abschalten") \
+ DRI_CONF_DESC(es,"Desactivar aceleración 3D") \
+ DRI_CONF_DESC(nl,"3D versnelling uitschakelen") \
+ DRI_CONF_DESC(fr,"Désactiver l'accélération 3D") \
+ DRI_CONF_DESC(sv,"Inaktivera 3D-accelerering") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_PERFORMANCE_BOXES(def) \
+DRI_CONF_OPT_BEGIN(performance_boxes,bool,def) \
+ DRI_CONF_DESC(en,"Show performance boxes") \
+ DRI_CONF_DESC(de,"Zeige Performanceboxen") \
+ DRI_CONF_DESC(es,"Mostrar cajas de rendimiento") \
+ DRI_CONF_DESC(nl,"Laat prestatie boxjes zien") \
+ DRI_CONF_DESC(fr,"Afficher les boîtes de performance") \
+ DRI_CONF_DESC(sv,"Visa prestandarutor") \
+DRI_CONF_OPT_END
+
+
+/** \brief Texture-related options */
+#define DRI_CONF_SECTION_QUALITY \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Image Quality") \
+ DRI_CONF_DESC(de,"Bildqualität") \
+ DRI_CONF_DESC(es,"Calidad de imagen") \
+ DRI_CONF_DESC(nl,"Beeldkwaliteit") \
+ DRI_CONF_DESC(fr,"Qualité d'image") \
+ DRI_CONF_DESC(sv,"Bildkvalitet")
+
+#define DRI_CONF_EXCESS_MIPMAP(def) \
+DRI_CONF_OPT_BEGIN(excess_mipmap,bool,def) \
+ DRI_CONF_DESC(en,"Enable extra mipmap level") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_DEPTH_FB 0
+#define DRI_CONF_TEXTURE_DEPTH_32 1
+#define DRI_CONF_TEXTURE_DEPTH_16 2
+#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3
+#define DRI_CONF_TEXTURE_DEPTH(def) \
+DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"Texture color depth") \
+ DRI_CONF_ENUM(0,"Prefer frame buffer color depth") \
+ DRI_CONF_ENUM(1,"Prefer 32 bits per texel") \
+ DRI_CONF_ENUM(2,"Prefer 16 bits per texel") \
+ DRI_CONF_ENUM(3,"Force 16 bits per texel") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Texturfarbtiefe") \
+ DRI_CONF_ENUM(0,"Bevorzuge Farbtiefe des Framebuffers") \
+ DRI_CONF_ENUM(1,"Bevorzuge 32 bits pro Texel") \
+ DRI_CONF_ENUM(2,"Bevorzuge 16 bits pro Texel") \
+ DRI_CONF_ENUM(3,"Erzwinge 16 bits pro Texel") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Profundidad de color de textura") \
+ DRI_CONF_ENUM(0,"Preferir profundidad de color del ”framebuffer“") \
+ DRI_CONF_ENUM(1,"Preferir 32 bits por texel") \
+ DRI_CONF_ENUM(2,"Preferir 16 bits por texel") \
+ DRI_CONF_ENUM(3,"Forzar a 16 bits por texel") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Textuurkleurendiepte") \
+ DRI_CONF_ENUM(0,"Prefereer kaderbufferkleurdiepte") \
+ DRI_CONF_ENUM(1,"Prefereer 32 bits per texel") \
+ DRI_CONF_ENUM(2,"Prefereer 16 bits per texel") \
+ DRI_CONF_ENUM(3,"Dwing 16 bits per texel af") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Profondeur de texture") \
+ DRI_CONF_ENUM(0,"Profondeur de couleur") \
+ DRI_CONF_ENUM(1,"Préférer 32 bits par texel") \
+ DRI_CONF_ENUM(2,"Prérérer 16 bits par texel") \
+ DRI_CONF_ENUM(3,"Forcer 16 bits par texel") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Färgdjup för texturer") \
+ DRI_CONF_ENUM(0,"Föredra färgdjupet för framebuffer") \
+ DRI_CONF_ENUM(1,"Föredra 32 bitar per texel") \
+ DRI_CONF_ENUM(2,"Föredra 16 bitar per texel") \
+ DRI_CONF_ENUM(3,"Tvinga 16 bitar per texel") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \
+DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \
+ DRI_CONF_DESC(en,"Initial maximum value for anisotropic texture filtering") \
+ DRI_CONF_DESC(de,"Initialer Maximalwert für anisotropische Texturfilterung") \
+ DRI_CONF_DESC(es,"Valor máximo inicial para filtrado anisotrópico de textura") \
+ DRI_CONF_DESC(nl,"Initïele maximum waarde voor anisotrophische textuur filtering") \
+ DRI_CONF_DESC(fr,"Valeur maximale initiale pour le filtrage anisotropique de texture") \
+ DRI_CONF_DESC(sv,"Initialt maximalt värde för anisotropisk texturfiltrering") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NO_NEG_LOD_BIAS(def) \
+DRI_CONF_OPT_BEGIN(no_neg_lod_bias,bool,def) \
+ DRI_CONF_DESC(en,"Forbid negative texture LOD bias") \
+ DRI_CONF_DESC(de,"Verbiete negative Textur-Detailgradverschiebung") \
+ DRI_CONF_DESC(es,"Prohibir valores negativos de Nivel De Detalle (LOD) de texturas") \
+ DRI_CONF_DESC(nl,"Verbied negatief niveau detailonderscheid (LOD) van texturen") \
+ DRI_CONF_DESC(fr,"Interdire le LOD bias negatif") \
+ DRI_CONF_DESC(sv,"Förbjud negativ LOD-kompensation för texturer") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FORCE_S3TC_ENABLE(def) \
+DRI_CONF_OPT_BEGIN(force_s3tc_enable,bool,def) \
+ DRI_CONF_DESC(en,"Enable S3TC texture compression even if software support is not available") \
+ DRI_CONF_DESC(de,"Aktiviere S3TC Texturkomprimierung auch wenn die nötige Softwareunterstützung fehlt") \
+ DRI_CONF_DESC(es,"Activar la compresión de texturas S3TC incluso si el soporte por software no está disponible") \
+ DRI_CONF_DESC(nl,"Schakel S3TC textuurcompressie in, zelfs als softwareondersteuning niet aanwezig is") \
+ DRI_CONF_DESC(fr,"Activer la compression de texture S3TC même si le support logiciel est absent") \
+ DRI_CONF_DESC(sv,"Aktivera S3TC-texturkomprimering även om programvarustöd saknas") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_COLOR_REDUCTION_ROUND 0
+#define DRI_CONF_COLOR_REDUCTION_DITHER 1
+#define DRI_CONF_COLOR_REDUCTION(def) \
+DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,"Initial color reduction method") \
+ DRI_CONF_ENUM(0,"Round colors") \
+ DRI_CONF_ENUM(1,"Dither colors") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Initiale Farbreduktionsmethode") \
+ DRI_CONF_ENUM(0,"Farben runden") \
+ DRI_CONF_ENUM(1,"Farben rastern") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Método inicial de reducción de color") \
+ DRI_CONF_ENUM(0,"Colores redondeados") \
+ DRI_CONF_ENUM(1,"Colores suavizados") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Initïele kleurreductie methode") \
+ DRI_CONF_ENUM(0,"Rond kleuren af") \
+ DRI_CONF_ENUM(1,"Rasteriseer kleuren") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Technique de réduction de couleurs") \
+ DRI_CONF_ENUM(0,"Arrondir les valeurs de couleur") \
+ DRI_CONF_ENUM(1,"Tramer les couleurs") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Initial färgminskningsmetod") \
+ DRI_CONF_ENUM(0,"Avrunda färger") \
+ DRI_CONF_ENUM(1,"Utjämna färger") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ROUND_TRUNC 0
+#define DRI_CONF_ROUND_ROUND 1
+#define DRI_CONF_ROUND_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,"Color rounding method") \
+ DRI_CONF_ENUM(0,"Round color components downward") \
+ DRI_CONF_ENUM(1,"Round to nearest color") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Farbrundungsmethode") \
+ DRI_CONF_ENUM(0,"Farbkomponenten abrunden") \
+ DRI_CONF_ENUM(1,"Zur ähnlichsten Farbe runden") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Método de redondeo de colores") \
+ DRI_CONF_ENUM(0,"Redondear hacia abajo los componentes de color") \
+ DRI_CONF_ENUM(1,"Redondear al color más cercano") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Kleurafrondingmethode") \
+ DRI_CONF_ENUM(0,"Rond kleurencomponenten af naar beneden") \
+ DRI_CONF_ENUM(1,"Rond af naar dichtsbijzijnde kleur") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Méthode d'arrondi des couleurs") \
+ DRI_CONF_ENUM(0,"Arrondi à l'inférieur") \
+ DRI_CONF_ENUM(1,"Arrondi au plus proche") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Färgavrundningsmetod") \
+ DRI_CONF_ENUM(0,"Avrunda färdkomponenter nedåt") \
+ DRI_CONF_ENUM(1,"Avrunda till närmsta färg") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DITHER_XERRORDIFF 0
+#define DRI_CONF_DITHER_XERRORDIFFRESET 1
+#define DRI_CONF_DITHER_ORDERED 2
+#define DRI_CONF_DITHER_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Color dithering method") \
+ DRI_CONF_ENUM(0,"Horizontal error diffusion") \
+ DRI_CONF_ENUM(1,"Horizontal error diffusion, reset error at line start") \
+ DRI_CONF_ENUM(2,"Ordered 2D color dithering") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Farbrasterungsmethode") \
+ DRI_CONF_ENUM(0,"Horizontale Fehlerstreuung") \
+ DRI_CONF_ENUM(1,"Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen") \
+ DRI_CONF_ENUM(2,"Geordnete 2D Farbrasterung") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Método de suavizado de color") \
+ DRI_CONF_ENUM(0,"Difusión de error horizontal") \
+ DRI_CONF_ENUM(1,"Difusión de error horizontal, reiniciar error al comienzo de línea") \
+ DRI_CONF_ENUM(2,"Suavizado de color 2D ordenado") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Kleurrasteriseringsmethode") \
+ DRI_CONF_ENUM(0,"Horizontale foutdiffusie") \
+ DRI_CONF_ENUM(1,"Horizontale foutdiffusie, zet fout bij lijnbegin terug") \
+ DRI_CONF_ENUM(2,"Geordende 2D kleurrasterisering") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Méthode de tramage") \
+ DRI_CONF_ENUM(0,"Diffusion d'erreur horizontale") \
+ DRI_CONF_ENUM(1,"Diffusion d'erreur horizontale, réinitialisé pour chaque ligne") \
+ DRI_CONF_ENUM(2,"Tramage ordonné des couleurs") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Färgutjämningsmetod") \
+ DRI_CONF_ENUM(0,"Horisontell felspridning") \
+ DRI_CONF_ENUM(1,"Horisontell felspridning, återställ fel vid radbörjan") \
+ DRI_CONF_ENUM(2,"Ordnad 2D-färgutjämning") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FLOAT_DEPTH(def) \
+DRI_CONF_OPT_BEGIN(float_depth,bool,def) \
+ DRI_CONF_DESC(en,"Floating point depth buffer") \
+ DRI_CONF_DESC(de,"Fließkomma z-Puffer") \
+ DRI_CONF_DESC(es,"Búfer de profundidad en coma flotante") \
+ DRI_CONF_DESC(nl,"Dieptebuffer als commagetal") \
+ DRI_CONF_DESC(fr,"Z-buffer en virgule flottante") \
+ DRI_CONF_DESC(sv,"Buffert för flytande punktdjup") \
+DRI_CONF_OPT_END
+
+/** \brief Performance-related options */
+#define DRI_CONF_SECTION_PERFORMANCE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Performance") \
+ DRI_CONF_DESC(de,"Leistung") \
+ DRI_CONF_DESC(es,"Rendimiento") \
+ DRI_CONF_DESC(nl,"Prestatie") \
+ DRI_CONF_DESC(fr,"Performance") \
+ DRI_CONF_DESC(sv,"Prestanda")
+
+#define DRI_CONF_TCL_SW 0
+#define DRI_CONF_TCL_PIPELINED 1
+#define DRI_CONF_TCL_VTXFMT 2
+#define DRI_CONF_TCL_CODEGEN 3
+#define DRI_CONF_TCL_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"TCL mode (Transformation, Clipping, Lighting)") \
+ DRI_CONF_ENUM(0,"Use software TCL pipeline") \
+ DRI_CONF_ENUM(1,"Use hardware TCL as first TCL pipeline stage") \
+ DRI_CONF_ENUM(2,"Bypass the TCL pipeline") \
+ DRI_CONF_ENUM(3,"Bypass the TCL pipeline with state-based machine code generated on-the-fly") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"TCL-Modus (Transformation, Clipping, Licht)") \
+ DRI_CONF_ENUM(0,"Benutze die Software-TCL-Pipeline") \
+ DRI_CONF_ENUM(1,"Benutze Hardware TCL als erste Stufe der TCL-Pipeline") \
+ DRI_CONF_ENUM(2,"Umgehe die TCL-Pipeline") \
+ DRI_CONF_ENUM(3,"Umgehe die TCL-Pipeline mit zur Laufzeit erzeugtem, zustandsbasiertem Maschinencode") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Modo TCL (Transformación, Recorte, Iluminación)") \
+ DRI_CONF_ENUM(0,"Usar tubería TCL por software") \
+ DRI_CONF_ENUM(1,"Usar TCL por hardware en la primera fase de la tubería TCL") \
+ DRI_CONF_ENUM(2,"Pasar por alto la tubería TCL") \
+ DRI_CONF_ENUM(3,"Pasar por alto la tubería TCL con código máquina basado en estados generado al vuelo") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"TCL-modus (Transformatie, Clipping, Licht)") \
+ DRI_CONF_ENUM(0,"Gebruik software TCL pijpleiding") \
+ DRI_CONF_ENUM(1,"Gebruik hardware TCL as eerste TCL pijpleiding trap") \
+ DRI_CONF_ENUM(2,"Omzeil de TCL pijpleiding") \
+ DRI_CONF_ENUM(3,"Omzeil de TCL pijpleiding met staatgebaseerde machinecode die tijdens executie gegenereerd wordt") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Mode de TCL (Transformation, Clipping, Eclairage)") \
+ DRI_CONF_ENUM(0,"Utiliser un pipeline TCL logiciel") \
+ DRI_CONF_ENUM(1,"Utiliser le TCL matériel pour le premier niveau de pipeline") \
+ DRI_CONF_ENUM(2,"Court-circuiter le pipeline TCL") \
+ DRI_CONF_ENUM(3,"Court-circuiter le pipeline TCL par une machine à états qui génère le codede TCL à la volée") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"TCL-läge (Transformation, Clipping, Lighting)") \
+ DRI_CONF_ENUM(0,"Använd programvaru-TCL-rörledning") \
+ DRI_CONF_ENUM(1,"Använd maskinvaru-TCL som första TCL-rörledningssteg") \
+ DRI_CONF_ENUM(2,"Kringgå TCL-rörledningen") \
+ DRI_CONF_ENUM(3,"Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FTHROTTLE_BUSY 0
+#define DRI_CONF_FTHROTTLE_USLEEPS 1
+#define DRI_CONF_FTHROTTLE_IRQS 2
+#define DRI_CONF_FTHROTTLE_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Method to limit rendering latency") \
+ DRI_CONF_ENUM(0,"Busy waiting for the graphics hardware") \
+ DRI_CONF_ENUM(1,"Sleep for brief intervals while waiting for the graphics hardware") \
+ DRI_CONF_ENUM(2,"Let the graphics hardware emit a software interrupt and sleep") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Methode zur Begrenzung der Bildverzögerung") \
+ DRI_CONF_ENUM(0,"Aktives Warten auf die Grafikhardware") \
+ DRI_CONF_ENUM(1,"Kurze Schlafintervalle beim Warten auf die Grafikhardware") \
+ DRI_CONF_ENUM(2,"Die Grafikhardware eine Softwareunterbrechnung erzeugen lassen und schlafen") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Método para limitar la latencia de rénder") \
+ DRI_CONF_ENUM(0,"Esperar activamente al hardware gráfico") \
+ DRI_CONF_ENUM(1,"Dormir en intervalos cortos mientras se espera al hardware gráfico") \
+ DRI_CONF_ENUM(2,"Permitir que el hardware gráfico emita una interrupción de software y duerma") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Methode om beeldopbouwvertraging te onderdrukken") \
+ DRI_CONF_ENUM(0,"Actief wachten voor de grafische hardware") \
+ DRI_CONF_ENUM(1,"Slaap voor korte intervallen tijdens het wachten op de grafische hardware") \
+ DRI_CONF_ENUM(2,"Laat de grafische hardware een software onderbreking uitzenden en in slaap vallen") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Méthode d'attente de la carte graphique") \
+ DRI_CONF_ENUM(0,"Attente active de la carte graphique") \
+ DRI_CONF_ENUM(1,"Attente utilisant usleep()") \
+ DRI_CONF_ENUM(2,"Utiliser les interruptions") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Metod för att begränsa renderingslatens") \
+ DRI_CONF_ENUM(0,"Upptagen med att vänta på grafikhårdvaran") \
+ DRI_CONF_ENUM(1,"Sov i korta intervall under väntan på grafikhårdvaran") \
+ DRI_CONF_ENUM(2,"Låt grafikhårdvaran sända ut ett programvaruavbrott och sov") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+#define DRI_CONF_VBLANK_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"Synchronization with vertical refresh (swap intervals)") \
+ DRI_CONF_ENUM(0,"Never synchronize with vertical refresh, ignore application's choice") \
+ DRI_CONF_ENUM(1,"Initial swap interval 0, obey application's choice") \
+ DRI_CONF_ENUM(2,"Initial swap interval 1, obey application's choice") \
+ DRI_CONF_ENUM(3,"Always synchronize with vertical refresh, application chooses the minimum swap interval") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Synchronisation mit der vertikalen Bildwiederholung") \
+ DRI_CONF_ENUM(0,"Niemals mit der Bildwiederholung synchronisieren, Anweisungen der Anwendung ignorieren") \
+ DRI_CONF_ENUM(1,"Initiales Bildinterval 0, Anweisungen der Anwendung gehorchen") \
+ DRI_CONF_ENUM(2,"Initiales Bildinterval 1, Anweisungen der Anwendung gehorchen") \
+ DRI_CONF_ENUM(3,"Immer mit der Bildwiederholung synchronisieren, Anwendung wählt das minimale Bildintervall") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Sincronización con el refresco vertical (intervalos de intercambio)") \
+ DRI_CONF_ENUM(0,"No sincronizar nunca con el refresco vertical, ignorar la elección de la aplicación") \
+ DRI_CONF_ENUM(1,"Intervalo de intercambio inicial 0, obedecer la elección de la aplicación") \
+ DRI_CONF_ENUM(2,"Intervalo de intercambio inicial 1, obedecer la elección de la aplicación") \
+ DRI_CONF_ENUM(3,"Sincronizar siempre con el refresco vertical, la aplicación elige el intervalo de intercambio mínimo") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Synchronisatie met verticale verversing (interval omwisselen)") \
+ DRI_CONF_ENUM(0,"Nooit synchroniseren met verticale verversing, negeer de keuze van de applicatie") \
+ DRI_CONF_ENUM(1,"Initïeel omwisselingsinterval 0, honoreer de keuze van de applicatie") \
+ DRI_CONF_ENUM(2,"Initïeel omwisselingsinterval 1, honoreer de keuze van de applicatie") \
+ DRI_CONF_ENUM(3,"Synchroniseer altijd met verticale verversing, de applicatie kiest het minimum omwisselingsinterval") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Synchronisation de l'affichage avec le balayage vertical") \
+ DRI_CONF_ENUM(0,"Ne jamais synchroniser avec le balayage vertical, ignorer le choix de l'application") \
+ DRI_CONF_ENUM(1,"Ne pas synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application") \
+ DRI_CONF_ENUM(2,"Synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application") \
+ DRI_CONF_ENUM(3,"Toujours synchroniser avec le balayage vertical, l'application choisit l'intervalle minimal") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Synkronisering med vertikal uppdatering (växlingsintervall)") \
+ DRI_CONF_ENUM(0,"Synkronisera aldrig med vertikal uppdatering, ignorera programmets val") \
+ DRI_CONF_ENUM(1,"Initialt växlingsintervall 0, följ programmets val") \
+ DRI_CONF_ENUM(2,"Initialt växlingsintervall 1, följ programmets val") \
+ DRI_CONF_ENUM(3,"Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta växlingsintervallen") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_HYPERZ_DISABLED 0
+#define DRI_CONF_HYPERZ_ENABLED 1
+#define DRI_CONF_HYPERZ(def) \
+DRI_CONF_OPT_BEGIN(hyperz,bool,def) \
+ DRI_CONF_DESC(en,"Use HyperZ to boost performance") \
+ DRI_CONF_DESC(de,"HyperZ zur Leistungssteigerung verwenden") \
+ DRI_CONF_DESC(es,"Usar HyperZ para potenciar rendimiento") \
+ DRI_CONF_DESC(nl,"Gebruik HyperZ om de prestaties te verbeteren") \
+ DRI_CONF_DESC(fr,"Utiliser le HyperZ pour améliorer les performances") \
+ DRI_CONF_DESC(sv,"Använd HyperZ för att maximera prestandan") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \
+DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \
+ DRI_CONF_DESC(en,"Number of texture units used") \
+ DRI_CONF_DESC(de,"Anzahl der benutzten Textureinheiten") \
+ DRI_CONF_DESC(es,"Número de unidades de textura usadas") \
+ DRI_CONF_DESC(nl,"Aantal textuureenheden in gebruik") \
+ DRI_CONF_DESC(fr,"Nombre d'unités de texture") \
+ DRI_CONF_DESC(sv,"Antal använda texturenheter") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALLOW_LARGE_TEXTURES(def) \
+DRI_CONF_OPT_BEGIN_V(allow_large_textures,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Support larger textures not guaranteed to fit into graphics memory") \
+ DRI_CONF_ENUM(0,"No") \
+ DRI_CONF_ENUM(1,"At least 1 texture must fit under worst-case assumptions") \
+ DRI_CONF_ENUM(2,"Announce hardware limits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Unterstütze grosse Texturen die evtl. nicht in den Grafikspeicher passen") \
+ DRI_CONF_ENUM(0,"Nein") \
+ DRI_CONF_ENUM(1,"Mindestens 1 Textur muss auch im schlechtesten Fall Platz haben") \
+ DRI_CONF_ENUM(2,"Benutze Hardware-Limits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Support larger textures not guaranteed to fit into graphics memory") \
+ DRI_CONF_ENUM(0,"No") \
+ DRI_CONF_ENUM(1,"At least 1 texture must fit under worst-case assumptions") \
+ DRI_CONF_ENUM(2,"Announce hardware limits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Support larger textures not guaranteed to fit into graphics memory") \
+ DRI_CONF_ENUM(0,"No") \
+ DRI_CONF_ENUM(1,"At least 1 texture must fit under worst-case assumptions") \
+ DRI_CONF_ENUM(2,"Announce hardware limits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Support larger textures not guaranteed to fit into graphics memory") \
+ DRI_CONF_ENUM(0,"No") \
+ DRI_CONF_ENUM(1,"At least 1 texture must fit under worst-case assumptions") \
+ DRI_CONF_ENUM(2,"Announce hardware limits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Stöd för större texturer är inte garanterat att passa i grafikminnet") \
+ DRI_CONF_ENUM(0,"Nej") \
+ DRI_CONF_ENUM(1,"Åtminstone en textur måste passa för antaget sämsta förhållande") \
+ DRI_CONF_ENUM(2,"Annonsera hårdvarubegränsningar") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \
+DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \
+ DRI_CONF_DESC(en,"Texture filtering quality vs. speed, AKA “brilinear” texture filtering") \
+ DRI_CONF_DESC(de,"Texturfilterqualität versus -geschwindigkeit, auch bekannt als „brilineare“ Texturfilterung") \
+ DRI_CONF_DESC(es,"Calidad de filtrado de textura vs. velocidad, alias filtrado ”brilinear“ de textura") \
+ DRI_CONF_DESC(nl,"Textuurfilterkwaliteit versus -snelheid, ookwel bekend als “brilineaire” textuurfiltering") \
+ DRI_CONF_DESC(fr,"Qualité/performance du filtrage trilinéaire de texture (filtrage brilinéaire)") \
+ DRI_CONF_DESC(sv,"Texturfiltreringskvalitet mot hastighet, även kallad ”brilinear”-texturfiltrering") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_HEAPS_ALL 0
+#define DRI_CONF_TEXTURE_HEAPS_CARD 1
+#define DRI_CONF_TEXTURE_HEAPS_GART 2
+#define DRI_CONF_TEXTURE_HEAPS(def) \
+DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Used types of texture memory") \
+ DRI_CONF_ENUM(0,"All available memory") \
+ DRI_CONF_ENUM(1,"Only card memory (if available)") \
+ DRI_CONF_ENUM(2,"Only GART (AGP/PCIE) memory (if available)") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Benutzte Arten von Texturspeicher") \
+ DRI_CONF_ENUM(0,"Aller verfügbarer Speicher") \
+ DRI_CONF_ENUM(1,"Nur Grafikspeicher (falls verfügbar)") \
+ DRI_CONF_ENUM(2,"Nur GART-Speicher (AGP/PCIE) (falls verfügbar)") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(es,"Tipos de memoria de textura usados") \
+ DRI_CONF_ENUM(0,"Toda la memoria disponible") \
+ DRI_CONF_ENUM(1,"Sólo la memoria de la tarjeta (si disponible)") \
+ DRI_CONF_ENUM(2,"Sólo memoria GART (AGP/PCIE) (si disponible)") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(nl,"Gebruikte soorten textuurgeheugen") \
+ DRI_CONF_ENUM(0,"Al het beschikbaar geheugen") \
+ DRI_CONF_ENUM(1,"Alleen geheugen op de kaart (als het aanwezig is)") \
+ DRI_CONF_ENUM(2,"Alleen GART (AGP/PCIE) geheugen (als het aanwezig is)") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(fr,"Types de mémoire de texture") \
+ DRI_CONF_ENUM(0,"Utiliser toute la mémoire disponible") \
+ DRI_CONF_ENUM(1,"Utiliser uniquement la mémoire graphique (si disponible)") \
+ DRI_CONF_ENUM(2,"Utiliser uniquement la mémoire GART (AGP/PCIE) (si disponible)") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(sv,"Använda typer av texturminne") \
+ DRI_CONF_ENUM(0,"Allt tillgängligt minne") \
+ DRI_CONF_ENUM(1,"Endast kortminne (om tillgängligt)") \
+ DRI_CONF_ENUM(2,"Endast GART-minne (AGP/PCIE) (om tillgängligt)") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+/* Options for features that are not done in hardware by the driver (like GL_ARB_vertex_program
+ On cards where there is no documentation (r200) or on rasterization-only hardware). */
+#define DRI_CONF_SECTION_SOFTWARE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Features that are not hardware-accelerated") \
+ DRI_CONF_DESC(de,"Funktionalität, die nicht hardwarebeschleunigt ist") \
+ DRI_CONF_DESC(es,"Características no aceleradas por hardware") \
+ DRI_CONF_DESC(nl,"Eigenschappen die niet hardwareversneld zijn") \
+ DRI_CONF_DESC(fr,"Fonctionnalités ne bénéficiant pas d'une accélération matérielle") \
+ DRI_CONF_DESC(sv,"Funktioner som inte är hårdvaruaccelererade")
+
+#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(arb_vertex_program,bool,def) \
+ DRI_CONF_DESC(en,"Enable extension GL_ARB_vertex_program") \
+ DRI_CONF_DESC(de,"Erweiterung GL_ARB_vertex_program aktivieren") \
+ DRI_CONF_DESC(es,"Activar la extensión GL_ARB_vertex_program") \
+ DRI_CONF_DESC(nl,"Zet uitbreiding GL_ARB_vertex_program aan") \
+ DRI_CONF_DESC(fr,"Activer l'extension GL_ARB_vertex_program") \
+ DRI_CONF_DESC(sv,"Aktivera tillägget GL_ARB_vertex_program") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NV_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(nv_vertex_program,bool,def) \
+ DRI_CONF_DESC(en,"Enable extension GL_NV_vertex_program") \
+ DRI_CONF_DESC(de,"Erweiterung GL_NV_vertex_program aktivieren") \
+ DRI_CONF_DESC(es,"Activar extensión GL_NV_vertex_program") \
+ DRI_CONF_DESC(nl,"Zet uitbreiding GL_NV_vertex_program aan") \
+ DRI_CONF_DESC(fr,"Activer l'extension GL_NV_vertex_program") \
+ DRI_CONF_DESC(sv,"Aktivera tillägget GL_NV_vertex_program") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \
+DRI_CONF_OPT_BEGIN(always_flush_batch,bool,def) \
+ DRI_CONF_DESC(en,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(de,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(es,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(nl,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(fr,"Enable flushing batchbuffer after each draw call") \
+ DRI_CONF_DESC(sv,"Enable flushing batchbuffer after each draw call") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \
+DRI_CONF_OPT_BEGIN(always_flush_cache,bool,def) \
+ DRI_CONF_DESC(en,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(de,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(es,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(nl,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(fr,"Enable flushing GPU caches with each draw call") \
+ DRI_CONF_DESC(sv,"Enable flushing GPU caches with each draw call") \
+DRI_CONF_OPT_END
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/sv.po b/mesalib/src/mesa/drivers/dri/common/xmlpool/sv.po
new file mode 100644
index 000000000..ba32b2ff1
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/sv.po
@@ -0,0 +1,226 @@
+# Swedish translation of DRI driver options.
+# Copyright (C) Free Software Foundation, Inc.
+# This file is distributed under the same license as the Mesa package.
+# Daniel Nylander <po@danielnylander.se>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Mesa DRI\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-04-11 23:19+0200\n"
+"PO-Revision-Date: 2006-09-18 10:56+0100\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: t_options.h:53
+msgid "Debugging"
+msgstr "Felsökning"
+
+#: t_options.h:57
+msgid "Disable 3D acceleration"
+msgstr "Inaktivera 3D-accelerering"
+
+#: t_options.h:62
+msgid "Show performance boxes"
+msgstr "Visa prestandarutor"
+
+#: t_options.h:69
+msgid "Image Quality"
+msgstr "Bildkvalitet"
+
+#: t_options.h:77
+msgid "Texture color depth"
+msgstr "Färgdjup för texturer"
+
+#: t_options.h:78
+msgid "Prefer frame buffer color depth"
+msgstr "Föredra färgdjupet för framebuffer"
+
+#: t_options.h:79
+msgid "Prefer 32 bits per texel"
+msgstr "Föredra 32 bitar per texel"
+
+#: t_options.h:80
+msgid "Prefer 16 bits per texel"
+msgstr "Föredra 16 bitar per texel"
+
+#: t_options.h:81
+msgid "Force 16 bits per texel"
+msgstr "Tvinga 16 bitar per texel"
+
+#: t_options.h:87
+msgid "Initial maximum value for anisotropic texture filtering"
+msgstr "Initialt maximalt värde för anisotropisk texturfiltrering"
+
+#: t_options.h:92
+msgid "Forbid negative texture LOD bias"
+msgstr "Förbjud negativ LOD-kompensation för texturer"
+
+#: t_options.h:97
+msgid "Enable S3TC texture compression even if software support is not available"
+msgstr "Aktivera S3TC-texturkomprimering även om programvarustöd saknas"
+
+#: t_options.h:104
+msgid "Initial color reduction method"
+msgstr "Initial färgminskningsmetod"
+
+#: t_options.h:105
+msgid "Round colors"
+msgstr "Avrunda färger"
+
+#: t_options.h:106
+msgid "Dither colors"
+msgstr "Utjämna färger"
+
+#: t_options.h:114
+msgid "Color rounding method"
+msgstr "Färgavrundningsmetod"
+
+#: t_options.h:115
+msgid "Round color components downward"
+msgstr "Avrunda färdkomponenter nedåt"
+
+#: t_options.h:116
+msgid "Round to nearest color"
+msgstr "Avrunda till närmsta färg"
+
+#: t_options.h:125
+msgid "Color dithering method"
+msgstr "Färgutjämningsmetod"
+
+#: t_options.h:126
+msgid "Horizontal error diffusion"
+msgstr "Horisontell felspridning"
+
+#: t_options.h:127
+msgid "Horizontal error diffusion, reset error at line start"
+msgstr "Horisontell felspridning, återställ fel vid radbörjan"
+
+#: t_options.h:128
+msgid "Ordered 2D color dithering"
+msgstr "Ordnad 2D-färgutjämning"
+
+#: t_options.h:134
+msgid "Floating point depth buffer"
+msgstr "Buffert för flytande punktdjup"
+
+#: t_options.h:140
+msgid "Performance"
+msgstr "Prestanda"
+
+#: t_options.h:148
+msgid "TCL mode (Transformation, Clipping, Lighting)"
+msgstr "TCL-läge (Transformation, Clipping, Lighting)"
+
+#: t_options.h:149
+msgid "Use software TCL pipeline"
+msgstr "Använd programvaru-TCL-rörledning"
+
+#: t_options.h:150
+msgid "Use hardware TCL as first TCL pipeline stage"
+msgstr "Använd maskinvaru-TCL som första TCL-rörledningssteg"
+
+#: t_options.h:151
+msgid "Bypass the TCL pipeline"
+msgstr "Kringgå TCL-rörledningen"
+
+#: t_options.h:152
+msgid "Bypass the TCL pipeline with state-based machine code generated on-the-fly"
+msgstr "Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras"
+
+#: t_options.h:161
+msgid "Method to limit rendering latency"
+msgstr "Metod för att begränsa renderingslatens"
+
+#: t_options.h:162
+msgid "Busy waiting for the graphics hardware"
+msgstr "Upptagen med att vänta på grafikhårdvaran"
+
+#: t_options.h:163
+msgid "Sleep for brief intervals while waiting for the graphics hardware"
+msgstr "Sov i korta intervall under väntan på grafikhårdvaran"
+
+#: t_options.h:164
+msgid "Let the graphics hardware emit a software interrupt and sleep"
+msgstr "Låt grafikhårdvaran sända ut ett programvaruavbrott och sov"
+
+#: t_options.h:174
+msgid "Synchronization with vertical refresh (swap intervals)"
+msgstr "Synkronisering med vertikal uppdatering (växlingsintervall)"
+
+#: t_options.h:175
+msgid "Never synchronize with vertical refresh, ignore application's choice"
+msgstr "Synkronisera aldrig med vertikal uppdatering, ignorera programmets val"
+
+#: t_options.h:176
+msgid "Initial swap interval 0, obey application's choice"
+msgstr "Initialt växlingsintervall 0, följ programmets val"
+
+#: t_options.h:177
+msgid "Initial swap interval 1, obey application's choice"
+msgstr "Initialt växlingsintervall 1, följ programmets val"
+
+#: t_options.h:178
+msgid "Always synchronize with vertical refresh, application chooses the minimum swap interval"
+msgstr "Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta växlingsintervallen"
+
+#: t_options.h:186
+msgid "Use HyperZ to boost performance"
+msgstr "Använd HyperZ för att maximera prestandan"
+
+#: t_options.h:191
+msgid "Number of texture units used"
+msgstr "Antal använda texturenheter"
+
+#: t_options.h:196
+msgid "Support larger textures not guaranteed to fit into graphics memory"
+msgstr "Stöd för större texturer är inte garanterat att passa i grafikminnet"
+
+#: t_options.h:197
+msgid "No"
+msgstr "Nej"
+
+#: t_options.h:198
+msgid "At least 1 texture must fit under worst-case assumptions"
+msgstr "Åtminstone en textur måste passa för antaget sämsta förhållande"
+
+#: t_options.h:199
+msgid "Announce hardware limits"
+msgstr "Annonsera hårdvarubegränsningar"
+
+#: t_options.h:205
+msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering"
+msgstr "Texturfiltreringskvalitet mot hastighet, även kallad \"brilinear\"-texturfiltrering"
+
+#: t_options.h:213
+msgid "Used types of texture memory"
+msgstr "Använda typer av texturminne"
+
+#: t_options.h:214
+msgid "All available memory"
+msgstr "Allt tillgängligt minne"
+
+#: t_options.h:215
+msgid "Only card memory (if available)"
+msgstr "Endast kortminne (om tillgängligt)"
+
+#: t_options.h:216
+msgid "Only GART (AGP/PCIE) memory (if available)"
+msgstr "Endast GART-minne (AGP/PCIE) (om tillgängligt)"
+
+#: t_options.h:224
+msgid "Features that are not hardware-accelerated"
+msgstr "Funktioner som inte är hårdvaruaccelererade"
+
+#: t_options.h:228
+msgid "Enable extension GL_ARB_vertex_program"
+msgstr "Aktivera tillägget GL_ARB_vertex_program"
+
+#: t_options.h:233
+msgid "Enable extension GL_NV_vertex_program"
+msgstr "Aktivera tillägget GL_NV_vertex_program"
+
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h b/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h
new file mode 100644
index 000000000..5fd6ec65b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h
@@ -0,0 +1,249 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/**
+ * \file t_options.h
+ * \brief Templates of common options
+ * \author Felix Kuehling
+ *
+ * This file defines macros for common options that can be used to
+ * construct driConfigOptions in the drivers. This file is only a
+ * template containing English descriptions for options wrapped in
+ * gettext(). xgettext can be used to extract translatable
+ * strings. These strings can then be translated by anyone familiar
+ * with GNU gettext. gen_xmlpool.py takes this template and fills in
+ * all the translations. The result (options.h) is included by
+ * xmlpool.h which in turn can be included by drivers.
+ *
+ * The macros used to describe otions in this file are defined in
+ * ../xmlpool.h.
+ */
+
+/* This is needed for xgettext to extract translatable strings.
+ * gen_xmlpool.py will discard this line. */
+#include <libintl.h>
+
+/*
+ * predefined option sections and options with multi-lingual descriptions
+ */
+
+/** \brief Debugging options */
+#define DRI_CONF_SECTION_DEBUG \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,gettext("Debugging"))
+
+#define DRI_CONF_NO_RAST(def) \
+DRI_CONF_OPT_BEGIN(no_rast,bool,def) \
+ DRI_CONF_DESC(en,gettext("Disable 3D acceleration")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_PERFORMANCE_BOXES(def) \
+DRI_CONF_OPT_BEGIN(performance_boxes,bool,def) \
+ DRI_CONF_DESC(en,gettext("Show performance boxes")) \
+DRI_CONF_OPT_END
+
+
+/** \brief Texture-related options */
+#define DRI_CONF_SECTION_QUALITY \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,gettext("Image Quality"))
+
+#define DRI_CONF_EXCESS_MIPMAP(def) \
+DRI_CONF_OPT_BEGIN(excess_mipmap,bool,def) \
+ DRI_CONF_DESC(en,"Enable extra mipmap level") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_DEPTH_FB 0
+#define DRI_CONF_TEXTURE_DEPTH_32 1
+#define DRI_CONF_TEXTURE_DEPTH_16 2
+#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3
+#define DRI_CONF_TEXTURE_DEPTH(def) \
+DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Texture color depth")) \
+ DRI_CONF_ENUM(0,gettext("Prefer frame buffer color depth")) \
+ DRI_CONF_ENUM(1,gettext("Prefer 32 bits per texel")) \
+ DRI_CONF_ENUM(2,gettext("Prefer 16 bits per texel")) \
+ DRI_CONF_ENUM(3,gettext("Force 16 bits per texel")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \
+DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \
+ DRI_CONF_DESC(en,gettext("Initial maximum value for anisotropic texture filtering")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NO_NEG_LOD_BIAS(def) \
+DRI_CONF_OPT_BEGIN(no_neg_lod_bias,bool,def) \
+ DRI_CONF_DESC(en,gettext("Forbid negative texture LOD bias")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FORCE_S3TC_ENABLE(def) \
+DRI_CONF_OPT_BEGIN(force_s3tc_enable,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable S3TC texture compression even if software support is not available")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_COLOR_REDUCTION_ROUND 0
+#define DRI_CONF_COLOR_REDUCTION_DITHER 1
+#define DRI_CONF_COLOR_REDUCTION(def) \
+DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Initial color reduction method")) \
+ DRI_CONF_ENUM(0,gettext("Round colors")) \
+ DRI_CONF_ENUM(1,gettext("Dither colors")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ROUND_TRUNC 0
+#define DRI_CONF_ROUND_ROUND 1
+#define DRI_CONF_ROUND_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Color rounding method")) \
+ DRI_CONF_ENUM(0,gettext("Round color components downward")) \
+ DRI_CONF_ENUM(1,gettext("Round to nearest color")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DITHER_XERRORDIFF 0
+#define DRI_CONF_DITHER_XERRORDIFFRESET 1
+#define DRI_CONF_DITHER_ORDERED 2
+#define DRI_CONF_DITHER_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Color dithering method")) \
+ DRI_CONF_ENUM(0,gettext("Horizontal error diffusion")) \
+ DRI_CONF_ENUM(1,gettext("Horizontal error diffusion, reset error at line start")) \
+ DRI_CONF_ENUM(2,gettext("Ordered 2D color dithering")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FLOAT_DEPTH(def) \
+DRI_CONF_OPT_BEGIN(float_depth,bool,def) \
+ DRI_CONF_DESC(en,gettext("Floating point depth buffer")) \
+DRI_CONF_OPT_END
+
+/** \brief Performance-related options */
+#define DRI_CONF_SECTION_PERFORMANCE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,gettext("Performance"))
+
+#define DRI_CONF_TCL_SW 0
+#define DRI_CONF_TCL_PIPELINED 1
+#define DRI_CONF_TCL_VTXFMT 2
+#define DRI_CONF_TCL_CODEGEN 3
+#define DRI_CONF_TCL_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,gettext("TCL mode (Transformation, Clipping, Lighting)")) \
+ DRI_CONF_ENUM(0,gettext("Use software TCL pipeline")) \
+ DRI_CONF_ENUM(1,gettext("Use hardware TCL as first TCL pipeline stage")) \
+ DRI_CONF_ENUM(2,gettext("Bypass the TCL pipeline")) \
+ DRI_CONF_ENUM(3,gettext("Bypass the TCL pipeline with state-based machine code generated on-the-fly")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FTHROTTLE_BUSY 0
+#define DRI_CONF_FTHROTTLE_USLEEPS 1
+#define DRI_CONF_FTHROTTLE_IRQS 2
+#define DRI_CONF_FTHROTTLE_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Method to limit rendering latency")) \
+ DRI_CONF_ENUM(0,gettext("Busy waiting for the graphics hardware")) \
+ DRI_CONF_ENUM(1,gettext("Sleep for brief intervals while waiting for the graphics hardware")) \
+ DRI_CONF_ENUM(2,gettext("Let the graphics hardware emit a software interrupt and sleep")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+#define DRI_CONF_VBLANK_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Synchronization with vertical refresh (swap intervals)")) \
+ DRI_CONF_ENUM(0,gettext("Never synchronize with vertical refresh, ignore application's choice")) \
+ DRI_CONF_ENUM(1,gettext("Initial swap interval 0, obey application's choice")) \
+ DRI_CONF_ENUM(2,gettext("Initial swap interval 1, obey application's choice")) \
+ DRI_CONF_ENUM(3,gettext("Always synchronize with vertical refresh, application chooses the minimum swap interval")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_HYPERZ_DISABLED 0
+#define DRI_CONF_HYPERZ_ENABLED 1
+#define DRI_CONF_HYPERZ(def) \
+DRI_CONF_OPT_BEGIN(hyperz,bool,def) \
+ DRI_CONF_DESC(en,gettext("Use HyperZ to boost performance")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \
+DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \
+ DRI_CONF_DESC(en,gettext("Number of texture units used")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALLOW_LARGE_TEXTURES(def) \
+DRI_CONF_OPT_BEGIN_V(allow_large_textures,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Support larger textures not guaranteed to fit into graphics memory")) \
+ DRI_CONF_ENUM(0,gettext("No")) \
+ DRI_CONF_ENUM(1,gettext("At least 1 texture must fit under worst-case assumptions")) \
+ DRI_CONF_ENUM(2,gettext("Announce hardware limits")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \
+DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \
+ DRI_CONF_DESC(en,gettext("Texture filtering quality vs. speed, AKA “brilinear” texture filtering")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_TEXTURE_HEAPS_ALL 0
+#define DRI_CONF_TEXTURE_HEAPS_CARD 1
+#define DRI_CONF_TEXTURE_HEAPS_GART 2
+#define DRI_CONF_TEXTURE_HEAPS(def) \
+DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,gettext("Used types of texture memory")) \
+ DRI_CONF_ENUM(0,gettext("All available memory")) \
+ DRI_CONF_ENUM(1,gettext("Only card memory (if available)")) \
+ DRI_CONF_ENUM(2,gettext("Only GART (AGP/PCIE) memory (if available)")) \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+/* Options for features that are not done in hardware by the driver (like GL_ARB_vertex_program
+ On cards where there is no documentation (r200) or on rasterization-only hardware). */
+#define DRI_CONF_SECTION_SOFTWARE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,gettext("Features that are not hardware-accelerated"))
+
+#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(arb_vertex_program,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable extension GL_ARB_vertex_program")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NV_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(nv_vertex_program,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable extension GL_NV_vertex_program")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \
+DRI_CONF_OPT_BEGIN(always_flush_batch,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable flushing batchbuffer after each draw call")) \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \
+DRI_CONF_OPT_BEGIN(always_flush_cache,bool,def) \
+ DRI_CONF_DESC(en,gettext("Enable flushing GPU caches with each draw call")) \
+DRI_CONF_OPT_END
diff --git a/mesalib/src/mesa/drivers/dri/dri.pc.in b/mesalib/src/mesa/drivers/dri/dri.pc.in
new file mode 100644
index 000000000..695aa6cfd
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/dri.pc.in
@@ -0,0 +1,11 @@
+prefix=@INSTALL_DIR@
+exec_prefix=${prefix}
+libdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+dridriverdir=@DRI_DRIVER_DIR@
+
+Name: dri
+Description: Direct Rendering Infrastructure
+Version: @VERSION@
+Requires.private: @DRI_PC_REQ_PRIV@
+Cflags: -I${includedir}
diff --git a/mesalib/src/mesa/drivers/dri/swrast/Makefile b/mesalib/src/mesa/drivers/dri/swrast/Makefile
new file mode 100644
index 000000000..5f3a4f219
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/swrast/Makefile
@@ -0,0 +1,24 @@
+# src/mesa/drivers/dri/swrast/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = swrast_dri.so
+
+DRIVER_SOURCES = \
+ swrast.c \
+ swrast_span.c
+
+C_SOURCES = \
+ $(SWRAST_COMMON_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+SWRAST_COMMON_SOURCES = \
+ ../../common/driverfuncs.c \
+ ../common/utils.c
+
+include ../Makefile.template
+
+symlinks:
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
new file mode 100644
index 000000000..a858af30c
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr>
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+/*
+ * DRI software rasterizer
+ *
+ * This is the mesa swrast module packaged into a DRI driver structure.
+ *
+ * The front-buffer is allocated by the loader. The loader provides read/write
+ * callbacks for access to the front-buffer. The driver uses a scratch row for
+ * front-buffer rendering to avoid repeated calls to the loader.
+ *
+ * The back-buffer is allocated by the driver and is private.
+ */
+
+#include "main/context.h"
+#include "main/extensions.h"
+#include "main/framebuffer.h"
+#include "main/imports.h"
+#include "main/renderbuffer.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "vbo/vbo.h"
+#include "drivers/common/driverfuncs.h"
+#include "utils.h"
+
+#include "swrast_priv.h"
+
+
+#define need_GL_VERSION_1_3
+#define need_GL_VERSION_1_4
+#define need_GL_VERSION_1_5
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+
+/* sw extensions for imaging */
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_convolution
+#define need_GL_EXT_histogram
+#define need_GL_SGI_color_table
+
+/* sw extensions not associated with some GL version */
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_vertex_array_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_sync
+#define need_GL_APPLE_vertex_array_object
+#define need_GL_ATI_fragment_shader
+#define need_GL_ATI_separate_stencil
+#define need_GL_EXT_depth_bounds_test
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_framebuffer_blit
+#define need_GL_EXT_gpu_program_parameters
+#define need_GL_EXT_paletted_texture
+#define need_GL_EXT_stencil_two_side
+#define need_GL_MESA_resize_buffers
+#define need_GL_NV_vertex_program
+#define need_GL_NV_fragment_program
+
+#include "extension_helper.h"
+
+const struct dri_extension card_extensions[] =
+{
+ { "GL_VERSION_1_3", GL_VERSION_1_3_functions },
+ { "GL_VERSION_1_4", GL_VERSION_1_4_functions },
+ { "GL_VERSION_1_5", GL_VERSION_1_5_functions },
+ { "GL_VERSION_2_0", GL_VERSION_2_0_functions },
+ { "GL_VERSION_2_1", GL_VERSION_2_1_functions },
+
+ { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
+ { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
+ { "GL_EXT_convolution", GL_EXT_convolution_functions },
+ { "GL_EXT_histogram", GL_EXT_histogram_functions },
+ { "GL_SGI_color_table", GL_SGI_color_table_functions },
+
+ { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+ { "GL_ARB_vertex_array_object", GL_ARB_vertex_array_object_functions },
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { "GL_ARB_sync", GL_ARB_sync_functions },
+ { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
+ { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
+ { "GL_ATI_separate_stencil", GL_ATI_separate_stencil_functions },
+ { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions },
+ { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+ { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
+ { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
+ { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
+ { "GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions },
+ { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { "GL_NV_fragment_program", GL_NV_fragment_program_functions },
+ { NULL, NULL }
+};
+
+
+/**
+ * Screen and config-related functions
+ */
+
+static void
+setupLoaderExtensions(__DRIscreen *psp,
+ const __DRIextension **extensions)
+{
+ int i;
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
+ psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
+ }
+}
+
+static __DRIconfig **
+swrastFillInModes(__DRIscreen *psp,
+ unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer)
+{
+ __DRIconfig **configs;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML
+ };
+
+ uint8_t depth_bits_array[4];
+ uint8_t stencil_bits_array[4];
+ uint8_t msaa_samples_array[1];
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = 0;
+ depth_bits_array[2] = depth_bits;
+ depth_bits_array[3] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ stencil_bits_array[2] = 0;
+ stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ msaa_samples_array[0] = 0;
+
+ depth_buffer_factor = 4;
+ back_buffer_factor = 2;
+
+ switch (pixel_bits) {
+ case 8:
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_BYTE_2_3_3_REV;
+ break;
+ case 16:
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case 24:
+ fb_format = GL_BGR;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case 32:
+ fb_format = GL_BGRA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ default:
+ fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
+ pixel_bits);
+ return NULL;
+ }
+
+ configs = driCreateConfigs(fb_format, fb_type,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor, msaa_samples_array, 1);
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+ __LINE__);
+ return NULL;
+ }
+
+ return configs;
+}
+
+static __DRIscreen *
+driCreateNewScreen(int scrn, const __DRIextension **extensions,
+ const __DRIconfig ***driver_configs, void *data)
+{
+ static const __DRIextension *emptyExtensionList[] = { NULL };
+ __DRIscreen *psp;
+ __DRIconfig **configs8, **configs16, **configs24, **configs32;
+
+ (void) data;
+
+ TRACE;
+
+ psp = _mesa_calloc(sizeof(*psp));
+ if (!psp)
+ return NULL;
+
+ setupLoaderExtensions(psp, extensions);
+
+ psp->num = scrn;
+ psp->extensions = emptyExtensionList;
+
+ configs8 = swrastFillInModes(psp, 8, 8, 0, 1);
+ configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
+ configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
+ configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
+
+ configs16 = driConcatConfigs(configs8, configs16);
+ configs24 = driConcatConfigs(configs16, configs24);
+ *driver_configs = (const __DRIconfig **)
+ driConcatConfigs(configs24, configs32);
+
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+
+ return psp;
+}
+
+static void driDestroyScreen(__DRIscreen *psp)
+{
+ TRACE;
+
+ if (psp) {
+ _mesa_free(psp);
+ }
+}
+
+static const __DRIextension **driGetExtensions(__DRIscreen *psp)
+{
+ TRACE;
+
+ return psp->extensions;
+}
+
+
+/**
+ * Framebuffer and renderbuffer-related functions.
+ */
+
+static GLuint
+choose_pixel_format(const GLvisual *v)
+{
+ if (v->rgbMode) {
+ int depth = v->rgbBits;
+
+ if (depth == 32
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_A8R8G8B8;
+ else if (depth == 24
+ && v->redMask == 0xff0000
+ && v->greenMask == 0x00ff00
+ && v->blueMask == 0x0000ff)
+ return PF_X8R8G8B8;
+ else if (depth == 16
+ && v->redMask == 0xf800
+ && v->greenMask == 0x07e0
+ && v->blueMask == 0x001f)
+ return PF_R5G6B5;
+ else if (depth == 8
+ && v->redMask == 0x07
+ && v->greenMask == 0x38
+ && v->blueMask == 0xc0)
+ return PF_R3G3B2;
+ }
+ else {
+ if (v->indexBits == 8)
+ return PF_CI8;
+ }
+
+ _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
+ return 0;
+}
+
+static void
+swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ TRACE;
+
+ _mesa_free(rb->Data);
+ _mesa_free(rb);
+}
+
+static GLboolean
+swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+ unsigned mask = PITCH_ALIGN_BITS - 1;
+
+ TRACE;
+
+ rb->Data = NULL;
+ rb->Width = width;
+ rb->Height = height;
+
+ /* always pad to PITCH_ALIGN_BITS */
+ xrb->pitch = ((width * xrb->bpp + mask) & ~mask) / 8;
+
+ return GL_TRUE;
+}
+
+static GLboolean
+swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+
+ TRACE;
+
+ _mesa_free(rb->Data);
+
+ swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
+
+ rb->Data = _mesa_malloc(height * xrb->pitch);
+
+ return GL_TRUE;
+}
+
+static struct swrast_renderbuffer *
+swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
+{
+ struct swrast_renderbuffer *xrb = _mesa_calloc(sizeof *xrb);
+ GLuint pixel_format;
+
+ TRACE;
+
+ if (!xrb)
+ return NULL;
+
+ _mesa_init_renderbuffer(&xrb->Base, 0);
+
+ pixel_format = choose_pixel_format(visual);
+
+ xrb->Base.Delete = swrast_delete_renderbuffer;
+ if (front) {
+ xrb->Base.AllocStorage = swrast_alloc_front_storage;
+ swrast_set_span_funcs_front(xrb, pixel_format);
+ }
+ else {
+ xrb->Base.AllocStorage = swrast_alloc_back_storage;
+ swrast_set_span_funcs_back(xrb, pixel_format);
+ }
+
+ switch (pixel_format) {
+ case PF_A8R8G8B8:
+ xrb->Base.InternalFormat = GL_RGBA;
+ xrb->Base._BaseFormat = GL_RGBA;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 8 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 8 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 8 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
+ xrb->bpp = 32;
+ break;
+ case PF_X8R8G8B8:
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 8 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 8 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 8 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 0;
+ xrb->bpp = 32;
+ break;
+ case PF_R5G6B5:
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 5 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 6 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 5 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 0;
+ xrb->bpp = 16;
+ break;
+ case PF_R3G3B2:
+ xrb->Base.InternalFormat = GL_RGB;
+ xrb->Base._BaseFormat = GL_RGB;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.RedBits = 3 * sizeof(GLubyte);
+ xrb->Base.GreenBits = 3 * sizeof(GLubyte);
+ xrb->Base.BlueBits = 2 * sizeof(GLubyte);
+ xrb->Base.AlphaBits = 0;
+ xrb->bpp = 8;
+ break;
+ case PF_CI8:
+ xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
+ xrb->Base._BaseFormat = GL_COLOR_INDEX;
+ xrb->Base.DataType = GL_UNSIGNED_BYTE;
+ xrb->Base.IndexBits = 8 * sizeof(GLubyte);
+ xrb->bpp = 8;
+ break;
+ default:
+ return NULL;
+ }
+
+ return xrb;
+}
+
+static __DRIdrawable *
+driCreateNewDrawable(__DRIscreen *screen,
+ const __DRIconfig *config, void *data)
+{
+ __DRIdrawable *buf;
+ struct swrast_renderbuffer *frontrb, *backrb;
+
+ TRACE;
+
+ buf = _mesa_calloc(sizeof *buf);
+ if (!buf)
+ return NULL;
+
+ buf->loaderPrivate = data;
+
+ buf->driScreenPriv = screen;
+
+ buf->row = _mesa_malloc(MAX_WIDTH * 4);
+
+ /* basic framebuffer setup */
+ _mesa_initialize_framebuffer(&buf->Base, &config->modes);
+
+ /* add front renderbuffer */
+ frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE);
+ _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base);
+
+ /* add back renderbuffer */
+ if (config->modes.doubleBufferMode) {
+ backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE);
+ _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base);
+ }
+
+ /* add software renderbuffers */
+ _mesa_add_soft_renderbuffers(&buf->Base,
+ GL_FALSE, /* color */
+ config->modes.haveDepthBuffer,
+ config->modes.haveStencilBuffer,
+ config->modes.haveAccumBuffer,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux bufs */);
+
+ return buf;
+}
+
+static void
+driDestroyDrawable(__DRIdrawable *buf)
+{
+ TRACE;
+
+ if (buf) {
+ struct gl_framebuffer *fb = &buf->Base;
+
+ _mesa_free(buf->row);
+
+ fb->DeletePending = GL_TRUE;
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+}
+
+static void driSwapBuffers(__DRIdrawable *buf)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct swrast_renderbuffer *frontrb =
+ swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ struct swrast_renderbuffer *backrb =
+ swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+
+ __DRIscreen *screen = buf->driScreenPriv;
+
+ TRACE;
+
+ /* check for signle-buffered */
+ if (backrb == NULL)
+ return;
+
+ /* check if swapping currently bound buffer */
+ if (ctx && ctx->DrawBuffer == &(buf->Base)) {
+ /* flush pending rendering */
+ _mesa_notifySwapBuffers(ctx);
+ }
+
+ screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP,
+ 0, 0,
+ frontrb->Base.Width,
+ frontrb->Base.Height,
+ backrb->Base.Data,
+ buf->loaderPrivate);
+}
+
+
+/**
+ * General device driver functions.
+ */
+
+static void
+get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h )
+{
+ __DRIdrawable *buf = swrast_drawable(fb);
+ __DRIscreen *screen = buf->driScreenPriv;
+ int x, y;
+
+ screen->swrast_loader->getDrawableInfo(buf,
+ &x, &y, w, h,
+ buf->loaderPrivate);
+}
+
+static void
+swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb )
+{
+ GLsizei width, height;
+
+ get_window_size(fb, &width, &height);
+ if (fb->Width != width || fb->Height != height) {
+ _mesa_resize_framebuffer(ctx, fb, width, height);
+ }
+}
+
+static const GLubyte *
+get_string(GLcontext *ctx, GLenum pname)
+{
+ (void) ctx;
+ switch (pname) {
+ case GL_VENDOR:
+ return (const GLubyte *) "Mesa Project";
+ case GL_RENDERER:
+ return (const GLubyte *) "Software Rasterizer";
+ default:
+ return NULL;
+ }
+}
+
+static void
+update_state( GLcontext *ctx, GLuint new_state )
+{
+ /* not much to do here - pass it on */
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+static void
+viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ GLframebuffer *draw = ctx->WinSysDrawBuffer;
+ GLframebuffer *read = ctx->WinSysReadBuffer;
+
+ swrast_check_and_update_window_size(ctx, draw);
+ swrast_check_and_update_window_size(ctx, read);
+}
+
+static void
+swrast_init_driver_functions(struct dd_function_table *driver)
+{
+ driver->GetString = get_string;
+ driver->UpdateState = update_state;
+ driver->GetBufferSize = NULL;
+ driver->Viewport = viewport;
+}
+
+
+/**
+ * Context-related functions.
+ */
+
+static __DRIcontext *
+driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+ __DRIcontext *shared, void *data)
+{
+ __DRIcontext *ctx;
+ GLcontext *mesaCtx;
+ struct dd_function_table functions;
+
+ TRACE;
+
+ ctx = _mesa_calloc(sizeof *ctx);
+ if (!ctx)
+ return NULL;
+
+ ctx->loaderPrivate = data;
+
+ ctx->driScreenPriv = screen;
+
+ /* build table of device driver functions */
+ _mesa_init_driver_functions(&functions);
+ swrast_init_driver_functions(&functions);
+
+ if (!_mesa_initialize_context(&ctx->Base, &config->modes,
+ shared ? &shared->Base : NULL,
+ &functions, (void *) ctx)) {
+ _mesa_free(ctx);
+ return NULL;
+ }
+
+ mesaCtx = &ctx->Base;
+
+ /* do bounds checking to prevent segfaults and server crashes! */
+ mesaCtx->Const.CheckArrayBounds = GL_TRUE;
+
+ /* create module contexts */
+ _swrast_CreateContext( mesaCtx );
+ _vbo_CreateContext( mesaCtx );
+ _tnl_CreateContext( mesaCtx );
+ _swsetup_CreateContext( mesaCtx );
+ _swsetup_Wakeup( mesaCtx );
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(mesaCtx);
+ _mesa_enable_1_3_extensions(mesaCtx);
+ _mesa_enable_1_4_extensions(mesaCtx);
+ _mesa_enable_1_5_extensions(mesaCtx);
+ _mesa_enable_2_0_extensions(mesaCtx);
+ _mesa_enable_2_1_extensions(mesaCtx);
+
+ return ctx;
+}
+
+static void
+driDestroyContext(__DRIcontext *ctx)
+{
+ GLcontext *mesaCtx;
+ TRACE;
+
+ if (ctx) {
+ mesaCtx = &ctx->Base;
+ _swsetup_DestroyContext( mesaCtx );
+ _swrast_DestroyContext( mesaCtx );
+ _tnl_DestroyContext( mesaCtx );
+ _vbo_DestroyContext( mesaCtx );
+ _mesa_destroy_context( mesaCtx );
+ }
+}
+
+static int
+driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
+{
+ TRACE;
+
+ _mesa_copy_context(&src->Base, &dst->Base, mask);
+ return GL_TRUE;
+}
+
+static int driBindContext(__DRIcontext *ctx,
+ __DRIdrawable *draw,
+ __DRIdrawable *read)
+{
+ GLcontext *mesaCtx;
+ GLframebuffer *mesaDraw;
+ GLframebuffer *mesaRead;
+ TRACE;
+
+ if (ctx) {
+ if (!draw || !read)
+ return GL_FALSE;
+
+ mesaCtx = &ctx->Base;
+ mesaDraw = &draw->Base;
+ mesaRead = &read->Base;
+
+ /* check for same context and buffer */
+ if (mesaCtx == _mesa_get_current_context()
+ && mesaCtx->DrawBuffer == mesaDraw
+ && mesaCtx->ReadBuffer == mesaRead) {
+ return GL_TRUE;
+ }
+
+ _glapi_check_multithread();
+
+ swrast_check_and_update_window_size(mesaCtx, mesaDraw);
+ if (read != draw)
+ swrast_check_and_update_window_size(mesaCtx, mesaRead);
+
+ _mesa_make_current( mesaCtx,
+ mesaDraw,
+ mesaRead );
+ }
+ else {
+ /* unbind */
+ _mesa_make_current( NULL, NULL, NULL );
+ }
+
+ return GL_TRUE;
+}
+
+static int driUnbindContext(__DRIcontext *ctx)
+{
+ TRACE;
+ (void) ctx;
+ return GL_TRUE;
+}
+
+
+static const __DRIcoreExtension driCoreExtension = {
+ { __DRI_CORE, __DRI_CORE_VERSION },
+ NULL, /* driCreateNewScreen */
+ driDestroyScreen,
+ driGetExtensions,
+ driGetConfigAttrib,
+ driIndexConfigAttrib,
+ NULL, /* driCreateNewDrawable */
+ driDestroyDrawable,
+ driSwapBuffers,
+ driCreateNewContext,
+ driCopyContext,
+ driDestroyContext,
+ driBindContext,
+ driUnbindContext
+};
+
+static const __DRIswrastExtension driSWRastExtension = {
+ { __DRI_SWRAST, __DRI_SWRAST_VERSION },
+ driCreateNewScreen,
+ driCreateNewDrawable
+};
+
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+ &driCoreExtension.base,
+ &driSWRastExtension.base,
+ NULL
+};
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
new file mode 100644
index 000000000..1a5fb31d5
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
@@ -0,0 +1,144 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * George Sapountzis <gsap7@yahoo.gr>
+ */
+
+
+#ifndef _SWRAST_PRIV_H
+#define _SWRAST_PRIV_H
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include "main/mtypes.h"
+
+
+/**
+ * Debugging
+ */
+#define DEBUG_CORE 0
+#define DEBUG_SPAN 0
+
+#if DEBUG_CORE
+#define TRACE _mesa_printf("--> %s\n", __FUNCTION__)
+#else
+#define TRACE
+#endif
+
+#if DEBUG_SPAN
+#define TRACE_SPAN _mesa_printf("--> %s\n", __FUNCTION__)
+#else
+#define TRACE_SPAN
+#endif
+
+
+/**
+ * Data types
+ */
+struct __DRIscreenRec {
+ int num;
+
+ const __DRIextension **extensions;
+
+ const __DRIswrastLoaderExtension *swrast_loader;
+};
+
+struct __DRIcontextRec {
+ GLcontext Base;
+
+ void *loaderPrivate;
+
+ __DRIscreen *driScreenPriv;
+};
+
+struct __DRIdrawableRec {
+ GLframebuffer Base;
+
+ void *loaderPrivate;
+
+ __DRIscreen *driScreenPriv;
+
+ /* scratch row for optimized front-buffer rendering */
+ char *row;
+};
+
+struct swrast_renderbuffer {
+ struct gl_renderbuffer Base;
+
+ /* renderbuffer pitch (in bytes) */
+ GLuint pitch;
+ /* bits per pixel of storage */
+ GLuint bpp;
+};
+
+static INLINE __DRIcontext *
+swrast_context(GLcontext *ctx)
+{
+ return (__DRIcontext *) ctx;
+}
+
+static INLINE __DRIdrawable *
+swrast_drawable(GLframebuffer *fb)
+{
+ return (__DRIdrawable *) fb;
+}
+
+static INLINE struct swrast_renderbuffer *
+swrast_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct swrast_renderbuffer *) rb;
+}
+
+
+/**
+ * Pixel formats we support
+ */
+#define PF_CI8 1 /**< Color Index mode */
+#define PF_A8R8G8B8 2 /**< 32bpp TrueColor: 8-A, 8-R, 8-G, 8-B bits */
+#define PF_R5G6B5 3 /**< 16bpp TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_R3G3B2 4 /**< 8bpp TrueColor: 3-R, 3-G, 2-B bits */
+#define PF_X8R8G8B8 5 /**< 32bpp TrueColor: 8-R, 8-G, 8-B bits */
+
+/**
+ * Renderbuffer pitch alignment (in bits).
+ *
+ * The xorg loader requires padding images to 32 bits. However, this should
+ * become a screen/drawable parameter XXX
+ */
+#define PITCH_ALIGN_BITS 32
+
+
+/* swrast_span.c */
+
+extern void
+swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format);
+
+extern void
+swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format);
+
+#endif /* _SWRAST_PRIV_H_ */
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c b/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c
new file mode 100644
index 000000000..2d3c25dcb
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_span.c
@@ -0,0 +1,439 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * George Sapountzis <gsap7@yahoo.gr>
+ */
+
+#include "swrast_priv.h"
+
+#define YFLIP(_xrb, Y) ((_xrb)->Base.Height - (Y) - 1)
+
+/*
+ * Dithering support takes the "computation" extreme in the "computation vs.
+ * storage" trade-off. This approach is very simple to implement and any
+ * computational overhead should be acceptable. XMesa uses table lookups for
+ * around 8KB of storage overhead per visual.
+ */
+#define DITHER 1
+
+static const GLubyte kernel[16] = {
+ 0*16, 8*16, 2*16, 10*16,
+ 12*16, 4*16, 14*16, 6*16,
+ 3*16, 11*16, 1*16, 9*16,
+ 15*16, 7*16, 13*16, 5*16,
+};
+
+#if DITHER
+#define DITHER_COMP(X, Y) kernel[((X) & 0x3) | (((Y) & 0x3) << 2)]
+
+#define DITHER_CLAMP(X) (((X) < CHAN_MAX) ? (X) : CHAN_MAX)
+#else
+#define DITHER_COMP(X, Y) 0
+
+#define DITHER_CLAMP(X) (X)
+#endif
+
+
+/*
+ * Pixel macros shared across front/back buffer span functions.
+ */
+
+/* 32-bit BGRA */
+#define STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = VALUE[ACOMP]; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = 0xff; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL_A8R8G8B8(DST, SRC) \
+ DST[ACOMP] = SRC[3]; \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]
+
+
+/* 32-bit BGRX */
+#define STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = 0xff; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE) \
+ DST[3] = 0xff; \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL_X8R8G8B8(DST, SRC) \
+ DST[ACOMP] = 0xff; \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]
+
+
+/* 16-bit BGR */
+#define STORE_PIXEL_R5G6B5(DST, X, Y, VALUE) \
+ do { \
+ int d = DITHER_COMP(X, Y) >> 6; \
+ GLushort *p = (GLushort *)DST; \
+ *p = ( ((DITHER_CLAMP((VALUE[RCOMP]) + d) & 0xf8) << 8) | \
+ ((DITHER_CLAMP((VALUE[GCOMP]) + d) & 0xfc) << 3) | \
+ ((DITHER_CLAMP((VALUE[BCOMP]) + d) & 0xf8) >> 3) ); \
+ } while(0)
+#define FETCH_PIXEL_R5G6B5(DST, SRC) \
+ do { \
+ GLushort p = *(GLushort *)SRC; \
+ DST[ACOMP] = 0xff; \
+ DST[RCOMP] = ((p >> 8) & 0xf8) * 255 / 0xf8; \
+ DST[GCOMP] = ((p >> 3) & 0xfc) * 255 / 0xfc; \
+ DST[BCOMP] = ((p << 3) & 0xf8) * 255 / 0xf8; \
+ } while(0)
+
+
+/* 8-bit BGR */
+#define STORE_PIXEL_R3G3B2(DST, X, Y, VALUE) \
+ do { \
+ int d = DITHER_COMP(X, Y) >> 3; \
+ GLubyte *p = (GLubyte *)DST; \
+ *p = ( ((DITHER_CLAMP((VALUE[RCOMP]) + d) & 0xe0) >> 5) | \
+ ((DITHER_CLAMP((VALUE[GCOMP]) + d) & 0xe0) >> 2) | \
+ ((DITHER_CLAMP((VALUE[BCOMP]) + d) & 0xc0) >> 0) ); \
+ } while(0)
+#define FETCH_PIXEL_R3G3B2(DST, SRC) \
+ do { \
+ GLubyte p = *(GLubyte *)SRC; \
+ DST[ACOMP] = 0xff; \
+ DST[RCOMP] = ((p << 5) & 0xe0) * 255 / 0xe0; \
+ DST[GCOMP] = ((p << 2) & 0xe0) * 255 / 0xe0; \
+ DST[BCOMP] = ((p << 0) & 0xc0) * 255 / 0xc0; \
+ } while(0)
+
+
+/*
+ * Generate code for back-buffer span functions.
+ */
+
+/* 32-bit BGRA */
+#define NAME(FUNC) FUNC##_A8R8G8B8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 4;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_A8R8G8B8(DST, SRC)
+
+#include "swrast/s_spantemp.h"
+
+
+/* 32-bit BGRX */
+#define NAME(FUNC) FUNC##_X8R8G8B8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 4;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_X8R8G8B8(DST, SRC)
+
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit BGR */
+#define NAME(FUNC) FUNC##_R5G6B5
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 2;
+#define INC_PIXEL_PTR(P) P += 2
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_R5G6B5(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_R5G6B5(DST, SRC)
+
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit BGR */
+#define NAME(FUNC) FUNC##_R3G3B2
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X) * 1;
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_R3G3B2(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_R3G3B2(DST, SRC)
+
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit color index */
+#define NAME(FUNC) FUNC##_CI8
+#define CI_MODE
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)xrb->Base.Data + YFLIP(xrb, Y) * xrb->pitch + (X);
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ *DST = VALUE[0]
+#define FETCH_PIXEL(DST, SRC) \
+ DST = SRC[0]
+
+#include "swrast/s_spantemp.h"
+
+
+/*
+ * Generate code for front-buffer span functions.
+ */
+
+/* 32-bit BGRA */
+#define NAME(FUNC) FUNC##_A8R8G8B8_front
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_A8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_A8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_A8R8G8B8(DST, SRC)
+
+#include "swrast_spantemp.h"
+
+
+/* 32-bit BGRX */
+#define NAME(FUNC) FUNC##_X8R8G8B8_front
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_X8R8G8B8(DST, X, Y, VALUE)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ STORE_PIXEL_RGB_X8R8G8B8(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_X8R8G8B8(DST, SRC)
+
+#include "swrast_spantemp.h"
+
+
+/* 16-bit BGR */
+#define NAME(FUNC) FUNC##_R5G6B5_front
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 2
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_R5G6B5(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_R5G6B5(DST, SRC)
+
+#include "swrast_spantemp.h"
+
+
+/* 8-bit BGR */
+#define NAME(FUNC) FUNC##_R3G3B2_front
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ STORE_PIXEL_R3G3B2(DST, X, Y, VALUE)
+#define FETCH_PIXEL(DST, SRC) \
+ FETCH_PIXEL_R3G3B2(DST, SRC)
+
+#include "swrast_spantemp.h"
+
+
+/* 8-bit color index */
+#define NAME(FUNC) FUNC##_CI8_front
+#define CI_MODE
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *)row;
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ *DST = VALUE[0]
+#define FETCH_PIXEL(DST, SRC) \
+ DST = SRC[0]
+
+#include "swrast_spantemp.h"
+
+
+/*
+ * Back-buffers are malloced memory and always private.
+ *
+ * BACK_PIXMAP (not supported)
+ * BACK_XIMAGE
+ */
+void
+swrast_set_span_funcs_back(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format)
+{
+ switch (pixel_format) {
+ case PF_A8R8G8B8:
+ xrb->Base.GetRow = get_row_A8R8G8B8;
+ xrb->Base.GetValues = get_values_A8R8G8B8;
+ xrb->Base.PutRow = put_row_A8R8G8B8;
+ xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8;
+ xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8;
+ xrb->Base.PutValues = put_values_A8R8G8B8;
+ xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8;
+ break;
+ case PF_X8R8G8B8:
+ xrb->Base.GetRow = get_row_X8R8G8B8;
+ xrb->Base.GetValues = get_values_X8R8G8B8;
+ xrb->Base.PutRow = put_row_X8R8G8B8;
+ xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8;
+ xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8;
+ xrb->Base.PutValues = put_values_X8R8G8B8;
+ xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8;
+ break;
+ case PF_R5G6B5:
+ xrb->Base.GetRow = get_row_R5G6B5;
+ xrb->Base.GetValues = get_values_R5G6B5;
+ xrb->Base.PutRow = put_row_R5G6B5;
+ xrb->Base.PutRowRGB = put_row_rgb_R5G6B5;
+ xrb->Base.PutMonoRow = put_mono_row_R5G6B5;
+ xrb->Base.PutValues = put_values_R5G6B5;
+ xrb->Base.PutMonoValues = put_mono_values_R5G6B5;
+ break;
+ case PF_R3G3B2:
+ xrb->Base.GetRow = get_row_R3G3B2;
+ xrb->Base.GetValues = get_values_R3G3B2;
+ xrb->Base.PutRow = put_row_R3G3B2;
+ xrb->Base.PutRowRGB = put_row_rgb_R3G3B2;
+ xrb->Base.PutMonoRow = put_mono_row_R3G3B2;
+ xrb->Base.PutValues = put_values_R3G3B2;
+ xrb->Base.PutMonoValues = put_mono_values_R3G3B2;
+ break;
+ case PF_CI8:
+ xrb->Base.GetRow = get_row_CI8;
+ xrb->Base.GetValues = get_values_CI8;
+ xrb->Base.PutRow = put_row_CI8;
+ xrb->Base.PutMonoRow = put_mono_row_CI8;
+ xrb->Base.PutValues = put_values_CI8;
+ xrb->Base.PutMonoValues = put_mono_values_CI8;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+}
+
+
+/*
+ * Front-buffers are provided by the loader, the xorg loader uses pixmaps.
+ *
+ * WINDOW, An X window
+ * GLXWINDOW, GLX window
+ * PIXMAP, GLX pixmap
+ * PBUFFER GLX Pbuffer
+ */
+void
+swrast_set_span_funcs_front(struct swrast_renderbuffer *xrb,
+ GLuint pixel_format)
+{
+ switch (pixel_format) {
+ case PF_A8R8G8B8:
+ xrb->Base.GetRow = get_row_A8R8G8B8_front;
+ xrb->Base.GetValues = get_values_A8R8G8B8_front;
+ xrb->Base.PutRow = put_row_A8R8G8B8_front;
+ xrb->Base.PutRowRGB = put_row_rgb_A8R8G8B8_front;
+ xrb->Base.PutMonoRow = put_mono_row_A8R8G8B8_front;
+ xrb->Base.PutValues = put_values_A8R8G8B8_front;
+ xrb->Base.PutMonoValues = put_mono_values_A8R8G8B8_front;
+ break;
+ case PF_X8R8G8B8:
+ xrb->Base.GetRow = get_row_X8R8G8B8_front;
+ xrb->Base.GetValues = get_values_X8R8G8B8_front;
+ xrb->Base.PutRow = put_row_X8R8G8B8_front;
+ xrb->Base.PutRowRGB = put_row_rgb_X8R8G8B8_front;
+ xrb->Base.PutMonoRow = put_mono_row_X8R8G8B8_front;
+ xrb->Base.PutValues = put_values_X8R8G8B8_front;
+ xrb->Base.PutMonoValues = put_mono_values_X8R8G8B8_front;
+ break;
+ case PF_R5G6B5:
+ xrb->Base.GetRow = get_row_R5G6B5_front;
+ xrb->Base.GetValues = get_values_R5G6B5_front;
+ xrb->Base.PutRow = put_row_R5G6B5_front;
+ xrb->Base.PutRowRGB = put_row_rgb_R5G6B5_front;
+ xrb->Base.PutMonoRow = put_mono_row_R5G6B5_front;
+ xrb->Base.PutValues = put_values_R5G6B5_front;
+ xrb->Base.PutMonoValues = put_mono_values_R5G6B5_front;
+ break;
+ case PF_R3G3B2:
+ xrb->Base.GetRow = get_row_R3G3B2_front;
+ xrb->Base.GetValues = get_values_R3G3B2_front;
+ xrb->Base.PutRow = put_row_R3G3B2_front;
+ xrb->Base.PutRowRGB = put_row_rgb_R3G3B2_front;
+ xrb->Base.PutMonoRow = put_mono_row_R3G3B2_front;
+ xrb->Base.PutValues = put_values_R3G3B2_front;
+ xrb->Base.PutMonoValues = put_mono_values_R3G3B2_front;
+ break;
+ case PF_CI8:
+ xrb->Base.GetRow = get_row_CI8_front;
+ xrb->Base.GetValues = get_values_CI8_front;
+ xrb->Base.PutRow = put_row_CI8_front;
+ xrb->Base.PutMonoRow = put_mono_row_CI8_front;
+ xrb->Base.PutValues = put_values_CI8_front;
+ xrb->Base.PutMonoValues = put_mono_values_CI8_front;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+}
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h
new file mode 100644
index 000000000..e0cb24142
--- /dev/null
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_spantemp.h
@@ -0,0 +1,328 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * Modified version of swrast/s_spantemp.h for front-buffer rendering. The
+ * no-mask paths use a scratch row to avoid repeated calls to the loader.
+ *
+ * For the mask paths we always use an array of 4 elements of RB_TYPE. This is
+ * to satisfy the xorg loader requirement of an image pitch of 32 bits and
+ * should be ok for other loaders also.
+ */
+
+
+#ifndef _SWRAST_SPANTEMP_ONCE
+#define _SWRAST_SPANTEMP_ONCE
+
+static INLINE void
+PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p )
+{
+ __DRIcontext *ctx = swrast_context(glCtx);
+ __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer);
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
+ x, y, 1, 1, (char *)p,
+ draw->loaderPrivate);
+}
+
+
+static INLINE void
+GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p )
+{
+ __DRIcontext *ctx = swrast_context(glCtx);
+ __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer);
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->getImage(read, x, y, 1, 1, (char *)p,
+ read->loaderPrivate);
+}
+
+static INLINE void
+PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row )
+{
+ __DRIcontext *ctx = swrast_context(glCtx);
+ __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer);
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->putImage(draw, __DRI_SWRAST_IMAGE_OP_DRAW,
+ x, y, n, 1, row,
+ draw->loaderPrivate);
+}
+
+static INLINE void
+GET_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row )
+{
+ __DRIcontext *ctx = swrast_context(glCtx);
+ __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer);
+
+ __DRIscreen *screen = ctx->driScreenPriv;
+
+ screen->swrast_loader->getImage(read, x, y, n, 1, row,
+ read->loaderPrivate);
+}
+
+#endif /* _SWRAST_SPANTEMP_ONCE */
+
+
+/*
+ * Templates for the span/pixel-array write/read functions called via
+ * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues
+ * and PutMonoValues functions.
+ *
+ * Define the following macros before including this file:
+ * NAME(BASE) to generate the function name (i.e. add prefix or suffix)
+ * RB_TYPE the renderbuffer DataType
+ * CI_MODE if set, color index mode, else RGBA
+ * SPAN_VARS to declare any local variables
+ * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel
+ * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel
+ * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer
+ * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer
+ *
+ * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates
+ * for the pixels to be stored. This is useful when dithering and probably
+ * ignored otherwise.
+ */
+
+#include "main/macros.h"
+
+
+#ifdef CI_MODE
+#define RB_COMPONENTS 1
+#elif !defined(RB_COMPONENTS)
+#define RB_COMPONENTS 4
+#endif
+
+
+static void
+NAME(get_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y, void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+#ifdef CI_MODE
+ RB_TYPE *dest = (RB_TYPE *) values;
+#else
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+#endif
+ GLuint i;
+ char *row = swrast_drawable(ctx->ReadBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ GET_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ for (i = 0; i < count; i++) {
+ FETCH_PIXEL(dest[i], pixel);
+ INC_PIXEL_PTR(pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(get_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[], void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+#ifdef CI_MODE
+ RB_TYPE *dest = (RB_TYPE *) values;
+#else
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+#endif
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ RB_TYPE pixel[4];
+ GET_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ FETCH_PIXEL(dest[i], pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE pixel[4];
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+
+
+#if !defined(CI_MODE)
+static void
+NAME(put_row_rgb)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE pixel[4];
+#ifdef STORE_PIXEL_RGB
+ STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
+#else
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+#endif
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+#ifdef STORE_PIXEL_RGB
+ STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
+#else
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+#endif
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+#endif
+
+
+static void
+NAME(put_mono_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE pixel[4];
+ STORE_PIXEL(pixel, x + i, y, src);
+ PUT_PIXEL(ctx, x + i, YFLIP(xrb, y), pixel);
+ }
+ }
+ }
+ else {
+ char *row = swrast_drawable(ctx->DrawBuffer)->row;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src);
+ INC_PIXEL_PTR(pixel);
+ }
+ PUT_ROW( ctx, x, YFLIP(xrb, y), count, row );
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE pixel[4];
+ STORE_PIXEL(pixel, x[i], y[i], src[i]);
+ PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_mono_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ RB_TYPE pixel[4];
+ STORE_PIXEL(pixel, x[i], y[i], src);
+ PUT_PIXEL(ctx, x[i], YFLIP(xrb, y[i]), pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+#undef NAME
+#undef RB_TYPE
+#undef RB_COMPONENTS
+#undef CI_MODE
+#undef SPAN_VARS
+#undef INIT_PIXEL_PTR
+#undef INC_PIXEL_PTR
+#undef STORE_PIXEL
+#undef STORE_PIXEL_RGB
+#undef FETCH_PIXEL
diff --git a/mesalib/src/mesa/drivers/windows/fx/fxopengl.def b/mesalib/src/mesa/drivers/windows/fx/fxopengl.def
new file mode 100644
index 000000000..d65b763d2
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/fx/fxopengl.def
@@ -0,0 +1,955 @@
+LIBRARY OpenGL32
+DESCRIPTION "Mesa 5.1"
+EXPORTS
+ glAccum
+ glActiveStencilFaceEXT
+ glActiveTexture
+ glActiveTextureARB
+ glAlphaFunc
+ glAreProgramsResidentNV
+ glAreTexturesResident
+ glAreTexturesResidentEXT
+ glArrayElement
+ glArrayElementEXT
+ glBegin
+ glBeginQueryARB
+ glBindBufferARB
+ glBindProgramARB
+ glBindProgramNV
+ glBindTexture
+ glBindTextureEXT
+ glBitmap
+;glBlendColor
+;glBlendColorEXT
+ glBlendEquation
+ glBlendEquationEXT
+ glBlendFunc
+ glBlendFuncSeparate
+ glBlendFuncSeparateEXT
+ glBlendFuncSeparateINGR
+ glBufferDataARB
+ glBufferSubDataARB
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClientActiveTexture
+ glClientActiveTextureARB
+ glClipPlane
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorPointerEXT
+ glColorSubTable
+ glColorSubTableEXT
+ glColorTable
+ glColorTableEXT
+ glColorTableParameterfv
+ glColorTableParameterfvSGI
+ glColorTableParameteriv
+ glColorTableParameterivSGI
+ glColorTableSGI
+ 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
+ glCombinerInputNV
+ glCombinerOutputNV
+ glCombinerParameterfNV
+ glCombinerParameterfvNV
+ glCombinerParameteriNV
+ glCombinerParameterivNV
+ glCompressedTexImage1D
+ glCompressedTexImage1DARB
+ glCompressedTexImage2D
+ glCompressedTexImage2DARB
+ glCompressedTexImage3D
+ glCompressedTexImage3DARB
+ glCompressedTexSubImage1D
+ glCompressedTexSubImage1DARB
+ glCompressedTexSubImage2D
+ glCompressedTexSubImage2DARB
+ glCompressedTexSubImage3D
+ glCompressedTexSubImage3DARB
+ glConvolutionFilter1D
+ glConvolutionFilter1DEXT
+ glConvolutionFilter2D
+ glConvolutionFilter2DEXT
+ glConvolutionParameterf
+ glConvolutionParameterfEXT
+ glConvolutionParameterfv
+ glConvolutionParameterfvEXT
+ glConvolutionParameteri
+ glConvolutionParameteriEXT
+ glConvolutionParameteriv
+ glConvolutionParameterivEXT
+ glCopyColorSubTable
+ glCopyColorSubTableEXT
+ glCopyColorTable
+ glCopyColorTableSGI
+ glCopyConvolutionFilter1D
+ glCopyConvolutionFilter1DEXT
+ glCopyConvolutionFilter2D
+ glCopyConvolutionFilter2DEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage1DEXT
+ glCopyTexImage2D
+ glCopyTexImage2DEXT
+ glCopyTexSubImage1D
+ glCopyTexSubImage1DEXT
+ glCopyTexSubImage2D
+ glCopyTexSubImage2DEXT
+ glCopyTexSubImage3D
+ glCopyTexSubImage3DEXT
+ glCullFace
+ glCullParameterdvEXT
+ glCullParameterfvEXT
+ glDeleteBuffersARB
+ glDeleteFencesNV
+ glDeleteLists
+ glDeleteProgramsARB
+ glDeleteProgramsNV
+ glDeleteQueriesARB
+ glDeleteTextures
+ glDeleteTexturesEXT
+ glDepthBoundsEXT
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDetailTexFuncSGIS
+ glDisable
+ glDisableClientState
+ glDisableVertexAttribArrayARB
+ glDrawArrays
+ glDrawArraysEXT
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glDrawRangeElements
+ glDrawRangeElementsEXT
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagPointerEXT
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnableVertexAttribArrayARB
+ glEnd
+ glEndList
+ glEndQueryARB
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glExecuteProgramNV
+ glFeedbackBuffer
+ glFinalCombinerInputNV
+ glFinish
+ glFinishFenceNV
+ glFlush
+ glFlushRasterSGIX
+ glFlushVertexArrayRangeNV
+ glFogCoordd
+ glFogCoorddEXT
+ glFogCoorddv
+ glFogCoorddvEXT
+ glFogCoordf
+ glFogCoordfEXT
+ glFogCoordfv
+ glFogCoordfvEXT
+ glFogCoordPointer
+ glFogCoordPointerEXT
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFragmentColorMaterialSGIX
+ glFragmentLightfSGIX
+ glFragmentLightfvSGIX
+ glFragmentLightiSGIX
+ glFragmentLightivSGIX
+ glFragmentLightModelfSGIX
+ glFragmentLightModelfvSGIX
+ glFragmentLightModeliSGIX
+ glFragmentLightModelivSGIX
+ glFragmentMaterialfSGIX
+ glFragmentMaterialfvSGIX
+ glFragmentMaterialiSGIX
+ glFragmentMaterialivSGIX
+ glFrameZoomSGIX
+ glFrontFace
+ glFrustum
+ glGenBuffersARB
+ glGenFencesNV
+ glGenLists
+ glGenProgramsARB
+ glGenProgramsNV
+ glGenQueriesARB
+ glGenTextures
+ glGenTexturesEXT
+ glGetBooleanv
+ glGetBufferParameterivARB
+ glGetBufferPointervARB
+ glGetBufferSubDataARB
+ glGetClipPlane
+ glGetColorTable
+ glGetColorTableEXT
+ glGetColorTableParameterfv
+ glGetColorTableParameterfvEXT
+ glGetColorTableParameterfvSGI
+ glGetColorTableParameteriv
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterivSGI
+ glGetColorTableSGI
+ glGetCombinerInputParameterfvNV
+ glGetCombinerInputParameterivNV
+ glGetCombinerOutputParameterfvNV
+ glGetCombinerOutputParameterivNV
+ glGetCompressedTexImage
+ glGetCompressedTexImageARB
+ glGetConvolutionFilter
+ glGetConvolutionFilterEXT
+ glGetConvolutionParameterfv
+ glGetConvolutionParameterfvEXT
+ glGetConvolutionParameteriv
+ glGetConvolutionParameterivEXT
+ glGetDetailTexFuncSGIS
+ glGetDoublev
+ glGetError
+ glGetFenceivNV
+ glGetFinalCombinerInputParameterfvNV
+ glGetFinalCombinerInputParameterivNV
+ glGetFloatv
+ glGetFragmentLightfvSGIX
+ glGetFragmentLightivSGIX
+ glGetFragmentMaterialfvSGIX
+ glGetFragmentMaterialivSGIX
+ glGetHistogram
+ glGetHistogramEXT
+ glGetHistogramParameterfv
+ glGetHistogramParameterfvEXT
+ glGetHistogramParameteriv
+ glGetHistogramParameterivEXT
+ glGetInstrumentsSGIX
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetListParameterfvSGIX
+ glGetListParameterivSGIX
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetMinmax
+ glGetMinmaxEXT
+ glGetMinmaxParameterfv
+ glGetMinmaxParameterfvEXT
+ glGetMinmaxParameteriv
+ glGetMinmaxParameterivEXT
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPixelTexGenParameterfvSGIS
+ glGetPixelTexGenParameterivSGIS
+ glGetPointerv
+ glGetPointervEXT
+ glGetPolygonStipple
+ glGetProgramEnvParameterdvARB
+ glGetProgramEnvParameterfvARB
+ glGetProgramivARB
+ glGetProgramivNV
+ glGetProgramLocalParameterdvARB
+ glGetProgramLocalParameterfvARB
+ glGetProgramNamedParameterdvNV
+ glGetProgramNamedParameterfvNV
+ glGetProgramParameterdvNV
+ glGetProgramParameterfvNV
+ glGetProgramStringARB
+ glGetProgramStringNV
+ glGetQueryivARB
+ glGetQueryObjectivARB
+ glGetQueryObjectuivARB
+ glGetSeparableFilter
+ glGetSeparableFilterEXT
+ glGetSharpenTexFuncSGIS
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexFilterFuncSGIS
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glGetTrackMatrixivNV
+ glGetVertexAttribdvARB
+ glGetVertexAttribdvNV
+ glGetVertexAttribfvARB
+ glGetVertexAttribfvNV
+ glGetVertexAttribivARB
+ glGetVertexAttribivNV
+ glGetVertexAttribPointervARB
+ glGetVertexAttribPointervNV
+ glHint
+ glHintPGI
+ glHistogram
+ glHistogramEXT
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexFuncEXT
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexMask
+ glIndexMaterialEXT
+ glIndexPointer
+ glIndexPointerEXT
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInstrumentsBufferSGIX
+ glInterleavedArrays
+ glIsBufferARB
+ glIsEnabled
+ glIsFenceNV
+ glIsList
+ glIsProgramARB
+ glIsProgramNV
+ glIsQueryARB
+ glIsTexture
+ glIsTextureEXT
+ glLightEnviSGIX
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glListParameterfSGIX
+ glListParameterfvSGIX
+ glListParameteriSGIX
+ glListParameterivSGIX
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLoadProgramNV
+ glLoadTransposeMatrixd
+ glLoadTransposeMatrixdARB
+ glLoadTransposeMatrixf
+ glLoadTransposeMatrixfARB
+ glLockArraysEXT
+ glLogicOp
+ glMapBufferARB
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMinmax
+ glMinmaxEXT
+ glMultiDrawArrays
+ glMultiDrawArraysEXT
+ glMultiDrawElements
+ glMultiDrawElementsEXT
+ glMultiModeDrawArraysIBM
+ glMultiModeDrawElementsIBM
+ glMultiTexCoord1d
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dv
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1f
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fv
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1i
+ glMultiTexCoord1iARB
+ glMultiTexCoord1iv
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1s
+ glMultiTexCoord1sARB
+ glMultiTexCoord1sv
+ glMultiTexCoord1svARB
+ glMultiTexCoord2d
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dv
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2f
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fv
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2i
+ glMultiTexCoord2iARB
+ glMultiTexCoord2iv
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2s
+ glMultiTexCoord2sARB
+ glMultiTexCoord2sv
+ glMultiTexCoord2svARB
+ glMultiTexCoord3d
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dv
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3f
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fv
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3i
+ glMultiTexCoord3iARB
+ glMultiTexCoord3iv
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3s
+ glMultiTexCoord3sARB
+ glMultiTexCoord3sv
+ glMultiTexCoord3svARB
+ glMultiTexCoord4d
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dv
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4f
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fv
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4i
+ glMultiTexCoord4iARB
+ glMultiTexCoord4iv
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4s
+ glMultiTexCoord4sARB
+ glMultiTexCoord4sv
+ glMultiTexCoord4svARB
+ glMultMatrixd
+ glMultMatrixf
+ glMultTransposeMatrixd
+ glMultTransposeMatrixdARB
+ glMultTransposeMatrixf
+ glMultTransposeMatrixfARB
+ glNewList
+ glNormalPointer
+ glNormalPointerEXT
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTexGenParameterfSGIS
+ glPixelTexGenParameterfvSGIS
+ glPixelTexGenParameteriSGIS
+ glPixelTexGenParameterivSGIS
+ glPixelTexGenSGIX
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointParameterf
+ glPointParameterfARB
+ glPointParameterfEXT
+ glPointParameterfSGIS
+ glPointParameterfv
+ glPointParameterfvARB
+ glPointParameterfvEXT
+ glPointParameterfvSGIS
+ glPointParameteri
+ glPointParameteriNV
+ glPointParameteriv
+ glPointParameterivNV
+ glPointSize
+ glPollInstrumentsSGIX
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPrioritizeTexturesEXT
+ glProgramEnvParameter4dARB
+ glProgramEnvParameter4dvARB
+ glProgramEnvParameter4fARB
+ glProgramEnvParameter4fvARB
+ glProgramLocalParameter4dARB
+ glProgramLocalParameter4dvARB
+ glProgramLocalParameter4fARB
+ glProgramLocalParameter4fvARB
+ glProgramNamedParameter4dNV
+ glProgramNamedParameter4dvNV
+ glProgramNamedParameter4fNV
+ glProgramNamedParameter4fvNV
+ glProgramParameters4dvNV
+ glProgramParameters4fvNV
+ glProgramParameter4dNV
+ glProgramParameter4dvNV
+ glProgramParameter4fNV
+ glProgramParameter4fvNV
+ glProgramStringARB
+ 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
+ glReadInstrumentsSGIX
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glReferencePlaneSGIX
+ glRenderMode
+ glRequestResidentProgramsNV
+ glResetHistogram
+ glResetHistogramEXT
+ glResetMinmax
+ glResetMinmaxEXT
+ glResizeBuffersMESA
+ glRotated
+ glRotatef
+ glSampleCoverage
+ glSampleCoverageARB
+ glSampleMaskEXT
+ glSampleMaskSGIS
+ glSamplePatternEXT
+ glSamplePatternSGIS
+ glScaled
+ glScalef
+ glScissor
+ glSecondaryColorPointer
+ glSecondaryColorPointerEXT
+ glSecondaryColor3b
+ glSecondaryColor3bEXT
+ glSecondaryColor3bv
+ glSecondaryColor3bvEXT
+ glSecondaryColor3d
+ glSecondaryColor3dEXT
+ glSecondaryColor3dv
+ glSecondaryColor3dvEXT
+ glSecondaryColor3f
+ glSecondaryColor3fEXT
+ glSecondaryColor3fv
+ glSecondaryColor3fvEXT
+ glSecondaryColor3i
+ glSecondaryColor3iEXT
+ glSecondaryColor3iv
+ glSecondaryColor3ivEXT
+ glSecondaryColor3s
+ glSecondaryColor3sEXT
+ glSecondaryColor3sv
+ glSecondaryColor3svEXT
+ glSecondaryColor3ub
+ glSecondaryColor3ubEXT
+ glSecondaryColor3ubv
+ glSecondaryColor3ubvEXT
+ glSecondaryColor3ui
+ glSecondaryColor3uiEXT
+ glSecondaryColor3uiv
+ glSecondaryColor3uivEXT
+ glSecondaryColor3us
+ glSecondaryColor3usEXT
+ glSecondaryColor3usv
+ glSecondaryColor3usvEXT
+ glSelectBuffer
+ glSeparableFilter2D
+ glSeparableFilter2DEXT
+ glSetFenceNV
+ glShadeModel
+ glSharpenTexFuncSGIS
+ glSpriteParameterfSGIX
+ glSpriteParameterfvSGIX
+ glSpriteParameteriSGIX
+ glSpriteParameterivSGIX
+ glStartInstrumentsSGIX
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glStopInstrumentsSGIX
+ glTagSampleBufferSGIX
+ glTbufferMask3DFX
+ glTestFenceNV
+ glTexCoordPointer
+ glTexCoordPointerEXT
+ 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
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexFilterFuncSGIS
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexImage3D
+ glTexImage3DEXT
+ glTexImage4DSGIS
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage1DEXT
+ glTexSubImage2D
+ glTexSubImage2DEXT
+ glTexSubImage3D
+ glTexSubImage3DEXT
+ glTexSubImage4DSGIS
+ glTrackMatrixNV
+ glTranslated
+ glTranslatef
+ glUnlockArraysEXT
+ glUnmapBufferARB
+ glVertexArrayRangeNV
+ glVertexAttribPointerARB
+ glVertexAttribPointerNV
+ glVertexAttribs1dvNV
+ glVertexAttribs1fvNV
+ glVertexAttribs1svNV
+ glVertexAttribs2dvNV
+ glVertexAttribs2fvNV
+ glVertexAttribs2svNV
+ glVertexAttribs3dvNV
+ glVertexAttribs3fvNV
+ glVertexAttribs3svNV
+ glVertexAttribs4dvNV
+ glVertexAttribs4fvNV
+ glVertexAttribs4svNV
+ glVertexAttribs4ubvNV
+ glVertexAttrib1dARB
+ glVertexAttrib1dNV
+ glVertexAttrib1dvARB
+ glVertexAttrib1dvNV
+ glVertexAttrib1fARB
+ glVertexAttrib1fNV
+ glVertexAttrib1fvARB
+ glVertexAttrib1fvNV
+ glVertexAttrib1sARB
+ glVertexAttrib1sNV
+ glVertexAttrib1svARB
+ glVertexAttrib1svNV
+ glVertexAttrib2dARB
+ glVertexAttrib2dNV
+ glVertexAttrib2dvARB
+ glVertexAttrib2dvNV
+ glVertexAttrib2fARB
+ glVertexAttrib2fNV
+ glVertexAttrib2fvARB
+ glVertexAttrib2fvNV
+ glVertexAttrib2sARB
+ glVertexAttrib2sNV
+ glVertexAttrib2svARB
+ glVertexAttrib2svNV
+ glVertexAttrib3dARB
+ glVertexAttrib3dNV
+ glVertexAttrib3dvARB
+ glVertexAttrib3dvNV
+ glVertexAttrib3fARB
+ glVertexAttrib3fNV
+ glVertexAttrib3fvARB
+ glVertexAttrib3fvNV
+ glVertexAttrib3sARB
+ glVertexAttrib3sNV
+ glVertexAttrib3svARB
+ glVertexAttrib3svNV
+ glVertexAttrib4bvARB
+ glVertexAttrib4dARB
+ glVertexAttrib4dNV
+ glVertexAttrib4dvARB
+ glVertexAttrib4dvNV
+ glVertexAttrib4fARB
+ glVertexAttrib4fNV
+ glVertexAttrib4fvARB
+ glVertexAttrib4fvNV
+ glVertexAttrib4ivARB
+ glVertexAttrib4NbvARB
+ glVertexAttrib4NivARB
+ glVertexAttrib4NsvARB
+ glVertexAttrib4NubARB
+ glVertexAttrib4NubvARB
+ glVertexAttrib4NuivARB
+ glVertexAttrib4NusvARB
+ glVertexAttrib4sARB
+ glVertexAttrib4sNV
+ glVertexAttrib4svARB
+ glVertexAttrib4svNV
+ glVertexAttrib4ubNV
+ glVertexAttrib4ubvARB
+ glVertexAttrib4ubvNV
+ glVertexAttrib4uivARB
+ glVertexAttrib4usvARB
+ glVertexPointer
+ glVertexPointerEXT
+ glVertexWeightfEXT
+ glVertexWeightfvEXT
+ glVertexWeightPointerEXT
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glViewport
+ glWindowPos2d
+ glWindowPos2dARB
+ glWindowPos2dMESA
+ glWindowPos2dv
+ glWindowPos2dvARB
+ glWindowPos2dvMESA
+ glWindowPos2f
+ glWindowPos2fARB
+ glWindowPos2fMESA
+ glWindowPos2fv
+ glWindowPos2fvARB
+ glWindowPos2fvMESA
+ glWindowPos2i
+ glWindowPos2iARB
+ glWindowPos2iMESA
+ glWindowPos2iv
+ glWindowPos2ivARB
+ glWindowPos2ivMESA
+ glWindowPos2s
+ glWindowPos2sARB
+ glWindowPos2sMESA
+ glWindowPos2sv
+ glWindowPos2svARB
+ glWindowPos2svMESA
+ glWindowPos3d
+ glWindowPos3dARB
+ glWindowPos3dMESA
+ glWindowPos3dv
+ glWindowPos3dvARB
+ glWindowPos3dvMESA
+ glWindowPos3f
+ glWindowPos3fARB
+ glWindowPos3fMESA
+ glWindowPos3fv
+ glWindowPos3fvARB
+ glWindowPos3fvMESA
+ glWindowPos3i
+ glWindowPos3iARB
+ glWindowPos3iMESA
+ glWindowPos3iv
+ glWindowPos3ivARB
+ glWindowPos3ivMESA
+ glWindowPos3s
+ glWindowPos3sARB
+ glWindowPos3sMESA
+ glWindowPos3sv
+ glWindowPos3svARB
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+ fxCloseHardware
+;fxGetScreenGeometry
+ fxMesaCreateBestContext
+ fxMesaCreateContext
+ fxMesaDestroyContext
+ fxMesaGetCurrentContext
+ fxMesaMakeCurrent
+ fxMesaSelectCurrentBoard
+;fxMesaSetNearFar
+ fxMesaSwapBuffers
+ fxMesaUpdateScreenSize
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetDefaultProcAddress
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ ChoosePixelFormat
+ DescribePixelFormat
+ GetPixelFormat
+ SetPixelFormat
+ SwapBuffers
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvReleaseContext
+ DrvRealizeLayerPalette
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
diff --git a/mesalib/src/mesa/drivers/windows/fx/fxwgl.c b/mesalib/src/mesa/drivers/windows/fx/fxwgl.c
new file mode 100644
index 000000000..ce76ecd15
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/fx/fxwgl.c
@@ -0,0 +1,1307 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Authors:
+ * David Bucciarelli
+ * Brian Paul
+ * Keith Whitwell
+ * Hiroshi Morii
+ * Daniel Borca
+ */
+
+/* fxwgl.c - Microsoft wgl functions emulation for
+ * 3Dfx VooDoo/Mesa interface
+ */
+
+
+#ifdef _WIN32
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "GL/fxmesa.h"
+#include "glheader.h"
+#include "glapi.h"
+#include "imports.h"
+#include "../../glide/fxdrv.h"
+
+#define MAX_MESA_ATTRS 20
+
+#if (_MSC_VER >= 1200)
+#pragma warning( push )
+#pragma warning( disable : 4273 )
+#endif
+
+struct __extensions__ {
+ PROC proc;
+ char *name;
+};
+
+struct __pixelformat__ {
+ PIXELFORMATDESCRIPTOR pfd;
+ GLint mesaAttr[MAX_MESA_ATTRS];
+};
+
+WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *);
+static GLushort gammaTable[3 * 256];
+
+struct __pixelformat__ pix[] = {
+ /* 16bit RGB565 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 6, 5, 5, 11, 0, 0,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 16,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit RGB565 double buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER | PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 6, 5, 5, 11, 0, 0,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 16,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit ARGB1555 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 5, 5, 5, 10, 1, 15,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 15,
+ FXMESA_ALPHA_SIZE, 1,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit ARGB1555 double buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER | PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 5, 5, 5, 10, 1, 15,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 15,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 1,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 32bit ARGB8888 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 32,
+ 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0,
+ 24,
+ 8,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 32,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 24,
+ FXMESA_STENCIL_SIZE, 8,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 32bit ARGB8888 double buffer with 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, 8, 24,
+ 0, 0, 0, 0, 0,
+ 24,
+ 8,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 32,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 24,
+ FXMESA_STENCIL_SIZE, 8,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+};
+
+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 */
+
+#ifndef GR_CONTROL_RESIZE
+/* Apparently GR_CONTROL_RESIZE can be ignored. OK? */
+#define GR_CONTROL_RESIZE -1
+#endif
+
+static GLboolean gdiWindowHack;
+static void *dibSurfacePtr;
+static BITMAPINFO *dibBMI;
+static HBITMAP dibHBM;
+static HWND dibWnd;
+
+static int
+env_check (const char *var, int val)
+{
+ const char *env = getenv(var);
+ return (env && (env[0] == val));
+}
+
+static LRESULT APIENTRY
+__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 0
+ if (wParam != SIZE_MINIMIZED) {
+ static int moving = 0;
+ if (!moving) {
+ if (!FX_grSstControl(GR_CONTROL_RESIZE)) {
+ moving = 1;
+ SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE | SWP_NOZORDER);
+ moving = 0;
+ if (!FX_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, FX_grSstScreenWidth(), FX_grSstScreenHeight());
+ /* And let the new size set in the context */
+ fxMesaUpdateScreenSize(ctx);
+ }
+ }
+#endif
+ break;
+ case WM_ACTIVATE:
+ break;
+ case WM_SHOWWINDOW:
+ break;
+ case WM_SYSKEYDOWN:
+ case WM_SYSCHAR:
+ break;
+ }
+ }
+
+ /* Finally call the hWNDOldProc, which handles the resize with the
+ * now changed window sizes */
+ ret = CallWindowProc(hWNDOldProc, hwnd, message, wParam, lParam);
+
+ return ret;
+}
+
+static void
+wgl_error (long error)
+{
+#define WGL_INVALID_PIXELFORMAT ERROR_INVALID_PIXEL_FORMAT
+ SetLastError(0xC0000000 /* error severity */
+ |0x00070000 /* error facility (who we are) */
+ |error);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglCopyContext (HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
+{
+ return FALSE;
+}
+
+GLAPI 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) {
+ wgl_error(WGL_INVALID_PIXELFORMAT);
+ return NULL;
+ }
+
+ if ((oldProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC)) != __wglMonitor) {
+ hWNDOldProc = oldProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)__wglMonitor);
+ }
+
+ /* always log when debugging, or if user demands */
+ if (TDFX_DEBUG || env_check("MESA_FX_INFO", 'r')) {
+ freopen("MESA.LOG", "w", stderr);
+ }
+
+ {
+ RECT cliRect;
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hWnd);
+ Sleep(100); /* a hack for win95 */
+ if (env_check("MESA_GLX_FX", 'w') && !(GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP)) {
+ /* XXX todo - windowed modes */
+ error = !(ctx = fxMesaCreateContext((GLuint) hWnd, GR_RESOLUTION_NONE, GR_REFRESH_NONE, pix[curPFD - 1].mesaAttr));
+ } else {
+ GetClientRect(hWnd, &cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint) hWnd, cliRect.right, cliRect.bottom, 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;
+}
+
+GLAPI HGLRC GLAPIENTRY
+wglCreateLayerContext (HDC hdc, int iLayerPlane)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDeleteContext (HGLRC hglrc)
+{
+ if (ctx && hglrc == (HGLRC)1) {
+
+ fxMesaDestroyContext(ctx);
+
+ SetWindowLong(WindowFromDC(hDC), GWL_WNDPROC, (LONG) hWNDOldProc);
+
+ ctx = NULL;
+ hDC = 0;
+ return TRUE;
+ }
+
+ SetLastError(0);
+
+ return FALSE;
+}
+
+GLAPI HGLRC GLAPIENTRY
+wglGetCurrentContext (VOID)
+{
+ if (ctx)
+ return (HGLRC)1;
+
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI HDC GLAPIENTRY
+wglGetCurrentDC (VOID)
+{
+ if (ctx)
+ return hDC;
+
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSwapIntervalEXT (int interval)
+{
+ if (ctx == NULL) {
+ return FALSE;
+ }
+ if (interval < 0) {
+ interval = 0;
+ } else if (interval > 3) {
+ interval = 3;
+ }
+ ctx->swapInterval = interval;
+ return TRUE;
+}
+
+GLAPI int GLAPIENTRY
+wglGetSwapIntervalEXT (void)
+{
+ return (ctx == NULL) ? -1 : ctx->swapInterval;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglGetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays)
+{
+ /* gammaTable should be per-context */
+ memcpy(arrays, gammaTable, 3 * 256 * sizeof(GLushort));
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays)
+{
+ GLint i, tableSize, inc, index;
+ GLushort *red, *green, *blue;
+ FxU32 gammaTableR[256], gammaTableG[256], gammaTableB[256];
+
+ /* gammaTable should be per-context */
+ memcpy(gammaTable, arrays, 3 * 256 * sizeof(GLushort));
+
+ tableSize = FX_grGetInteger(GR_GAMMA_TABLE_ENTRIES);
+ inc = 256 / tableSize;
+ red = (GLushort *)arrays;
+ green = (GLushort *)arrays + 256;
+ blue = (GLushort *)arrays + 512;
+ for (i = 0, index = 0; i < tableSize; i++, index += inc) {
+ gammaTableR[i] = red[index] >> 8;
+ gammaTableG[i] = green[index] >> 8;
+ gammaTableB[i] = blue[index] >> 8;
+ }
+
+ grLoadGammaTable(tableSize, gammaTableR, gammaTableG, gammaTableB);
+
+ return TRUE;
+}
+
+typedef void *HPBUFFERARB;
+
+/* WGL_ARB_pixel_format */
+GLAPI BOOL GLAPIENTRY
+wglGetPixelFormatAttribivARB (HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ int *piValues)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglGetPixelFormatAttribfvARB (HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ FLOAT *pfValues)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglChoosePixelFormatARB (HDC hdc,
+ const int *piAttribIList,
+ const FLOAT *pfAttribFList,
+ UINT nMaxFormats,
+ int *piFormats,
+ UINT *nNumFormats)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+/* WGL_ARB_render_texture */
+GLAPI BOOL GLAPIENTRY
+wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetPbufferAttribARB (HPBUFFERARB hPbuffer,
+ const int *piAttribList)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+/* WGL_ARB_pbuffer */
+GLAPI HPBUFFERARB GLAPIENTRY
+wglCreatePbufferARB (HDC hDC,
+ int iPixelFormat,
+ int iWidth,
+ int iHeight,
+ const int *piAttribList)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI HDC GLAPIENTRY
+wglGetPbufferDCARB (HPBUFFERARB hPbuffer)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI int GLAPIENTRY
+wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC)
+{
+ SetLastError(0);
+ return -1;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDestroyPbufferARB (HPBUFFERARB hPbuffer)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglQueryPbufferARB (HPBUFFERARB hPbuffer,
+ int iAttribute,
+ int *piValue)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI const char * GLAPIENTRY
+wglGetExtensionsStringEXT (void)
+{
+ return "WGL_3DFX_gamma_control "
+ "WGL_EXT_swap_control "
+ "WGL_EXT_extensions_string WGL_ARB_extensions_string"
+ /*WGL_ARB_pixel_format WGL_ARB_render_texture WGL_ARB_pbuffer*/;
+}
+
+GLAPI const char * GLAPIENTRY
+wglGetExtensionsStringARB (HDC hdc)
+{
+ return wglGetExtensionsStringEXT();
+}
+
+static struct {
+ const char *name;
+ PROC func;
+} wgl_ext[] = {
+ {"wglGetExtensionsStringARB", (PROC)wglGetExtensionsStringARB},
+ {"wglGetExtensionsStringEXT", (PROC)wglGetExtensionsStringEXT},
+ {"wglSwapIntervalEXT", (PROC)wglSwapIntervalEXT},
+ {"wglGetSwapIntervalEXT", (PROC)wglGetSwapIntervalEXT},
+ {"wglGetDeviceGammaRamp3DFX", (PROC)wglGetDeviceGammaRamp3DFX},
+ {"wglSetDeviceGammaRamp3DFX", (PROC)wglSetDeviceGammaRamp3DFX},
+ /* WGL_ARB_pixel_format */
+ {"wglGetPixelFormatAttribivARB", (PROC)wglGetPixelFormatAttribivARB},
+ {"wglGetPixelFormatAttribfvARB", (PROC)wglGetPixelFormatAttribfvARB},
+ {"wglChoosePixelFormatARB", (PROC)wglChoosePixelFormatARB},
+ /* WGL_ARB_render_texture */
+ {"wglBindTexImageARB", (PROC)wglBindTexImageARB},
+ {"wglReleaseTexImageARB", (PROC)wglReleaseTexImageARB},
+ {"wglSetPbufferAttribARB", (PROC)wglSetPbufferAttribARB},
+ /* WGL_ARB_pbuffer */
+ {"wglCreatePbufferARB", (PROC)wglCreatePbufferARB},
+ {"wglGetPbufferDCARB", (PROC)wglGetPbufferDCARB},
+ {"wglReleasePbufferDCARB", (PROC)wglReleasePbufferDCARB},
+ {"wglDestroyPbufferARB", (PROC)wglDestroyPbufferARB},
+ {"wglQueryPbufferARB", (PROC)wglQueryPbufferARB},
+ {NULL, NULL}
+};
+
+GLAPI PROC GLAPIENTRY
+wglGetProcAddress (LPCSTR lpszProc)
+{
+ int i;
+ PROC p = (PROC)_glapi_get_proc_address((const char *)lpszProc);
+
+ /* we can't BlendColor. work around buggy applications */
+ if (p && strcmp(lpszProc, "glBlendColor")
+ && strcmp(lpszProc, "glBlendColorEXT"))
+ return p;
+
+ for (i = 0; wgl_ext[i].name; i++) {
+ if (!strcmp(lpszProc, wgl_ext[i].name)) {
+ return wgl_ext[i].func;
+ }
+ }
+
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI PROC GLAPIENTRY
+wglGetDefaultProcAddress (LPCSTR lpszProc)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI 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;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglShareLists (HGLRC hglrc1, HGLRC hglrc2)
+{
+ if (!ctx || hglrc1 != (HGLRC)1 || hglrc1 != hglrc2) {
+ SetLastError(0);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL
+wglUseFontBitmaps_FX (HDC fontDevice, DWORD firstChar, DWORD numChars,
+ DWORD listBase)
+{
+ TEXTMETRIC metric;
+ BITMAPINFO *dibInfo;
+ HDC bitDevice;
+ COLORREF tempColor;
+ int i;
+
+ 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);
+
+ /* 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 */
+ SetTextAlign(bitDevice, TA_BASELINE);
+
+ for (i = 0; i < (int)numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth, charHeight, bmapWidth, bmapHeight, numBytes, res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = (char)(i + firstChar); /* [koolsmoky] explicit cast */
+
+ /* Find how high/wide this character is */
+ 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);
+
+ PatBlt(bitDevice, 0, 0, bmapWidth, bmapHeight, BLACKNESS);
+
+ /* Use our source font on the device */
+ SelectObject(bitDevice, GetCurrentObject(fontDevice, OBJ_FONT));
+
+ /* Draw the character */
+ TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1);
+
+ /* Unselect our bmap object */
+ 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);
+
+ /* 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 */
+ DeleteDC(bitDevice);
+
+ FREE(dibInfo);
+
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontBitmapsW (HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontOutlinesA (HDC hdc, DWORD first, DWORD count,
+ DWORD listBase, FLOAT deviation,
+ FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontOutlinesW (HDC hdc, DWORD first, DWORD count,
+ DWORD listBase, FLOAT deviation,
+ FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+
+GLAPI BOOL GLAPIENTRY
+wglSwapLayerBuffers (HDC hdc, UINT fuPlanes)
+{
+ if (ctx && WindowFromDC(hdc) == hWND) {
+ fxMesaSwapBuffers();
+
+ return TRUE;
+ }
+
+ SetLastError(0);
+ return FALSE;
+}
+
+static int
+pfd_tablen (void)
+{
+ /* we should take an envvar for `fxMesaSelectCurrentBoard' */
+ return (fxMesaSelectCurrentBoard(0) < GR_SSTTYPE_Voodoo4)
+ ? 2 /* only 16bit entries */
+ : sizeof(pix) / sizeof(pix[0]); /* full table */
+}
+
+GLAPI int GLAPIENTRY
+wglChoosePixelFormat (HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i, best = -1, qt_valid_pix;
+ PIXELFORMATDESCRIPTOR pfd = *ppfd;
+
+ qt_valid_pix = pfd_tablen();
+
+#if 1 || QUAKE2 || GORE
+ /* QUAKE2: 24+32 */
+ /* GORE : 24+16 */
+ if ((pfd.cColorBits == 24) || (pfd.cColorBits == 32)) {
+ /* the first 2 entries are 16bit */
+ pfd.cColorBits = (qt_valid_pix > 2) ? 32 : 16;
+ }
+ if (pfd.cColorBits == 32) {
+ pfd.cDepthBits = 24;
+ } else if (pfd.cColorBits == 16) {
+ pfd.cDepthBits = 16;
+ }
+#endif
+
+ if (pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR) || pfd.nVersion != 1) {
+ SetLastError(0);
+ return 0;
+ }
+
+ for (i = 0; i < qt_valid_pix; i++) {
+ if (pfd.cColorBits > 0 && pix[i].pfd.cColorBits != pfd.cColorBits)
+ continue;
+
+ if ((pfd.dwFlags & PFD_DRAW_TO_WINDOW)
+ && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue;
+ if ((pfd.dwFlags & PFD_DRAW_TO_BITMAP)
+ && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) continue;
+ if ((pfd.dwFlags & PFD_SUPPORT_GDI)
+ && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) continue;
+ if ((pfd.dwFlags & PFD_SUPPORT_OPENGL)
+ && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue;
+ if (!(pfd.dwFlags & PFD_DOUBLEBUFFER_DONTCARE)
+ && ((pfd.dwFlags & PFD_DOUBLEBUFFER) !=
+ (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) continue;
+#if 1 /* Doom3 fails here! */
+ if (!(pfd.dwFlags & PFD_STEREO_DONTCARE)
+ && ((pfd.dwFlags & PFD_STEREO) !=
+ (pix[i].pfd.dwFlags & PFD_STEREO))) continue;
+#endif
+
+ if (pfd.cDepthBits > 0 && pix[i].pfd.cDepthBits == 0)
+ continue; /* need depth buffer */
+
+ if (pfd.cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0)
+ continue; /* need alpha buffer */
+
+#if 0 /* regression bug? */
+ if (pfd.cStencilBits > 0 && pix[i].pfd.cStencilBits == 0)
+ continue; /* need stencil buffer */
+#endif
+
+ if (pfd.iPixelType == pix[i].pfd.iPixelType) {
+ best = i + 1;
+ break;
+ }
+ }
+
+ if (best == -1) {
+ FILE *err = fopen("MESA.LOG", "w");
+ if (err != NULL) {
+ fprintf(err, "wglChoosePixelFormat failed\n");
+ fprintf(err, "\tnSize = %d\n", ppfd->nSize);
+ fprintf(err, "\tnVersion = %d\n", ppfd->nVersion);
+ fprintf(err, "\tdwFlags = %lu\n", ppfd->dwFlags);
+ fprintf(err, "\tiPixelType = %d\n", ppfd->iPixelType);
+ fprintf(err, "\tcColorBits = %d\n", ppfd->cColorBits);
+ fprintf(err, "\tcRedBits = %d\n", ppfd->cRedBits);
+ fprintf(err, "\tcRedShift = %d\n", ppfd->cRedShift);
+ fprintf(err, "\tcGreenBits = %d\n", ppfd->cGreenBits);
+ fprintf(err, "\tcGreenShift = %d\n", ppfd->cGreenShift);
+ fprintf(err, "\tcBlueBits = %d\n", ppfd->cBlueBits);
+ fprintf(err, "\tcBlueShift = %d\n", ppfd->cBlueShift);
+ fprintf(err, "\tcAlphaBits = %d\n", ppfd->cAlphaBits);
+ fprintf(err, "\tcAlphaShift = %d\n", ppfd->cAlphaShift);
+ fprintf(err, "\tcAccumBits = %d\n", ppfd->cAccumBits);
+ fprintf(err, "\tcAccumRedBits = %d\n", ppfd->cAccumRedBits);
+ fprintf(err, "\tcAccumGreenBits = %d\n", ppfd->cAccumGreenBits);
+ fprintf(err, "\tcAccumBlueBits = %d\n", ppfd->cAccumBlueBits);
+ fprintf(err, "\tcAccumAlphaBits = %d\n", ppfd->cAccumAlphaBits);
+ fprintf(err, "\tcDepthBits = %d\n", ppfd->cDepthBits);
+ fprintf(err, "\tcStencilBits = %d\n", ppfd->cStencilBits);
+ fprintf(err, "\tcAuxBuffers = %d\n", ppfd->cAuxBuffers);
+ fprintf(err, "\tiLayerType = %d\n", ppfd->iLayerType);
+ fprintf(err, "\tbReserved = %d\n", ppfd->bReserved);
+ fprintf(err, "\tdwLayerMask = %lu\n", ppfd->dwLayerMask);
+ fprintf(err, "\tdwVisibleMask = %lu\n", ppfd->dwVisibleMask);
+ fprintf(err, "\tdwDamageMask = %lu\n", ppfd->dwDamageMask);
+ fclose(err);
+ }
+
+ SetLastError(0);
+ return 0;
+ }
+
+ return best;
+}
+
+GLAPI int GLAPIENTRY
+ChoosePixelFormat (HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+
+ return wglChoosePixelFormat(hdc, ppfd);
+}
+
+GLAPI int GLAPIENTRY
+wglDescribePixelFormat (HDC hdc, int iPixelFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = pfd_tablen();
+
+ if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix ||
+ ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) {
+ SetLastError(0);
+ return qt_valid_pix;
+ }
+
+ if (nBytes != 0)
+ *ppfd = pix[iPixelFormat - 1].pfd;
+
+ return qt_valid_pix;
+}
+
+GLAPI int GLAPIENTRY
+DescribePixelFormat (HDC hdc, int iPixelFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ return wglDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
+}
+
+GLAPI int GLAPIENTRY
+wglGetPixelFormat (HDC hdc)
+{
+ if (curPFD == 0) {
+ SetLastError(0);
+ return 0;
+ }
+
+ return curPFD;
+}
+
+GLAPI int GLAPIENTRY
+GetPixelFormat (HDC hdc)
+{
+ return wglGetPixelFormat(hdc);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetPixelFormat (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = pfd_tablen();
+
+ if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix) {
+ if (ppfd == NULL) {
+ PIXELFORMATDESCRIPTOR my_pfd;
+ if (!wglDescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &my_pfd)) {
+ SetLastError(0);
+ return FALSE;
+ }
+ } else if (ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ SetLastError(0);
+ return FALSE;
+ }
+ }
+ curPFD = iPixelFormat;
+
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSwapBuffers (HDC hdc)
+{
+ if (!ctx) {
+ SetLastError(0);
+ return FALSE;
+ }
+
+ fxMesaSwapBuffers();
+
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+SetPixelFormat (HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd)
+{
+ return wglSetPixelFormat(hdc, iPixelFormat, ppfd);
+}
+
+GLAPI BOOL GLAPIENTRY
+SwapBuffers(HDC hdc)
+{
+ return wglSwapBuffers(hdc);
+}
+
+static FIXED
+FixedFromDouble (double d)
+{
+ struct {
+ FIXED f;
+ long l;
+ } pun;
+ pun.l = (long)(d * 65536L);
+ return pun.f;
+}
+
+/*
+** This was yanked from windows/gdi/wgl.c
+*/
+GLAPI BOOL GLAPIENTRY
+wglUseFontBitmapsA (HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ int i;
+ GLuint font_list;
+ DWORD size;
+ GLYPHMETRICS gm;
+ HANDLE hBits;
+ LPSTR lpBits;
+ MAT2 mat;
+ int success = TRUE;
+
+ font_list = listBase;
+
+ mat.eM11 = FixedFromDouble(1);
+ mat.eM12 = FixedFromDouble(0);
+ mat.eM21 = FixedFromDouble(0);
+ mat.eM22 = FixedFromDouble(-1);
+
+ memset(&gm, 0, sizeof(gm));
+
+ /*
+ ** If we can't get the glyph outline, it may be because this is a fixed
+ ** font. Try processing it that way.
+ */
+ if (GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat) == GDI_ERROR) {
+ return wglUseFontBitmaps_FX(hdc, first, count, listBase);
+ }
+
+ /*
+ ** Otherwise process all desired characters.
+ */
+ for (i = 0; i < count; i++) {
+ DWORD err;
+
+ 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) {
+ glEndList();
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ hBits = GlobalAlloc(GHND, size + 1);
+ lpBits = GlobalLock(hBits);
+
+ err = 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 (err == GDI_ERROR) {
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList();
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
+ -gm.gmptGlyphOrigin.x,
+ gm.gmptGlyphOrigin.y,
+ gm.gmCellIncX, gm.gmCellIncY,
+ (const GLubyte *)lpBits);
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList();
+ }
+
+ return success;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDescribeLayerPlane (HDC hdc, int iPixelFormat, int iLayerPlane,
+ UINT nBytes, LPLAYERPLANEDESCRIPTOR ppfd)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI int GLAPIENTRY
+wglGetLayerPaletteEntries (HDC hdc, int iLayerPlane, int iStart,
+ int cEntries, COLORREF *pcr)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglRealizeLayerPalette (HDC hdc, int iLayerPlane, BOOL bRealize)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+GLAPI int GLAPIENTRY
+wglSetLayerPaletteEntries (HDC hdc, int iLayerPlane, int iStart,
+ int cEntries, CONST COLORREF *pcr)
+{
+ SetLastError(0);
+ return FALSE;
+}
+
+
+/***************************************************************************
+ * [dBorca] simplistic ICD implementation, based on ICD code by Gregor Anich
+ */
+
+typedef struct _icdTable {
+ DWORD size;
+ PROC table[336];
+} ICDTABLE, *PICDTABLE;
+
+#ifdef USE_MGL_NAMESPACE
+#define GL_FUNC(func) mgl##func
+#else
+#define GL_FUNC(func) gl##func
+#endif
+
+static ICDTABLE icdTable = { 336, {
+#define ICD_ENTRY(func) (PROC)GL_FUNC(func),
+#include "../icd/icdlist.h"
+#undef ICD_ENTRY
+} };
+
+
+GLAPI BOOL GLAPIENTRY
+DrvCopyContext (HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
+{
+ return wglCopyContext(hglrcSrc, hglrcDst, mask);
+}
+
+
+GLAPI HGLRC GLAPIENTRY
+DrvCreateContext (HDC hdc)
+{
+ return wglCreateContext(hdc);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvDeleteContext (HGLRC hglrc)
+{
+ return wglDeleteContext(hglrc);
+}
+
+
+GLAPI HGLRC GLAPIENTRY
+DrvCreateLayerContext (HDC hdc, int iLayerPlane)
+{
+ return wglCreateContext(hdc);
+}
+
+
+GLAPI PICDTABLE GLAPIENTRY
+DrvSetContext (HDC hdc, HGLRC hglrc, void *callback)
+{
+ return wglMakeCurrent(hdc, hglrc) ? &icdTable : NULL;
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvReleaseContext (HGLRC hglrc)
+{
+ return TRUE;
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvShareLists (HGLRC hglrc1, HGLRC hglrc2)
+{
+ return wglShareLists(hglrc1, hglrc2);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvDescribeLayerPlane (HDC hdc, int iPixelFormat,
+ int iLayerPlane, UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ return wglDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
+}
+
+
+GLAPI int GLAPIENTRY
+DrvSetLayerPaletteEntries (HDC hdc, int iLayerPlane,
+ int iStart, int cEntries, CONST COLORREF *pcr)
+{
+ return wglSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
+}
+
+
+GLAPI int GLAPIENTRY
+DrvGetLayerPaletteEntries (HDC hdc, int iLayerPlane,
+ int iStart, int cEntries, COLORREF *pcr)
+{
+ return wglGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvRealizeLayerPalette (HDC hdc, int iLayerPlane, BOOL bRealize)
+{
+ return wglRealizeLayerPalette(hdc, iLayerPlane, bRealize);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvSwapLayerBuffers (HDC hdc, UINT fuPlanes)
+{
+ return wglSwapLayerBuffers(hdc, fuPlanes);
+}
+
+GLAPI int GLAPIENTRY
+DrvDescribePixelFormat (HDC hdc, int iPixelFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ return wglDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
+}
+
+
+GLAPI PROC GLAPIENTRY
+DrvGetProcAddress (LPCSTR lpszProc)
+{
+ return wglGetProcAddress(lpszProc);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvSetPixelFormat (HDC hdc, int iPixelFormat)
+{
+ return wglSetPixelFormat(hdc, iPixelFormat, NULL);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvSwapBuffers (HDC hdc)
+{
+ return wglSwapBuffers(hdc);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+DrvValidateVersion (DWORD version)
+{
+ (void)version;
+ return TRUE;
+}
+
+
+#if (_MSC_VER >= 1200)
+#pragma warning( pop )
+#endif
+
+#endif /* FX */
diff --git a/mesalib/src/mesa/drivers/windows/gdi/colors.h b/mesalib/src/mesa/drivers/windows/gdi/colors.h
new file mode 100644
index 000000000..03e512c1f
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/colors.h
@@ -0,0 +1,29 @@
+/* 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
+
+
+#define BGR8(r,g,b) (unsigned)(((BYTE)((b & 0xc0) | ((g & 0xe0)>>2) | \
+ ((r & 0xe0)>>5))))
+
+/* Windows uses 5,5,5 for 16-bit */
+#define BGR16(r,g,b) ( (((unsigned short)b ) >> 3) | \
+ (((unsigned short)g & 0xf8) << 2) | \
+ (((unsigned short)r & 0xf8) << 7) )
+
+#define BGR24(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)| \
+ ((WORD)((BYTE)(g))<<8))| \
+ (((DWORD)(BYTE)(r))<<16)))
+
+#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)| \
+ ((WORD)((BYTE)(g))<<8))| \
+ (((DWORD)(BYTE)(r))<<16)))
+
+
diff --git a/mesalib/src/mesa/drivers/windows/gdi/mesa.def b/mesalib/src/mesa/drivers/windows/gdi/mesa.def
new file mode 100644
index 000000000..bd3e5b213
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/mesa.def
@@ -0,0 +1,979 @@
+; DO NOT EDIT - This file generated automatically by mesadef.py script
+;DESCRIPTION 'Mesa (OpenGL work-alike) for Win32'
+VERSION 6.5
+;
+; Module definition file for Mesa (OPENGL32.DLL)
+;
+; Note: The OpenGL functions use the STDCALL
+; function calling convention. Microsoft's
+; OPENGL32 uses this convention and so must the
+; Mesa OPENGL32 so that the Mesa DLL can be used
+; as a drop-in replacement.
+;
+; The linker exports STDCALL entry points with
+; 'decorated' names; e.g., _glBegin@0, where the
+; trailing number is the number of bytes of
+; parameter data pushed onto the stack. The
+; callee is responsible for popping this data
+; off the stack, usually via a RETF n instruction.
+;
+; However, the Microsoft OPENGL32.DLL does not export
+; the decorated names, even though the calling convention
+; is STDCALL. So, this module definition file is
+; needed to force the Mesa OPENGL32.DLL to export the
+; symbols in the same manner as the Microsoft DLL.
+; Were it not for this problem, this file would not
+; be needed (for the gl* functions) since the entry
+; points are compiled with dllexport declspec.
+;
+; However, this file is still needed to export "internal"
+; Mesa symbols for the benefit of the OSMESA32.DLL.
+;
+EXPORTS
+ glNewList
+ glEndList
+ glCallList
+ glCallLists
+ glDeleteLists
+ glGenLists
+ glListBase
+ glBegin
+ glBitmap
+ 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
+ glEdgeFlag
+ glEdgeFlagv
+ glEnd
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexs
+ glIndexsv
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ 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
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glClipPlane
+ glColorMaterial
+ glCullFace
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glHint
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glPointSize
+ glPolygonMode
+ glPolygonStipple
+ glScissor
+ glShadeModel
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexImage1D
+ glTexImage2D
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glFeedbackBuffer
+ glSelectBuffer
+ glRenderMode
+ glInitNames
+ glLoadName
+ glPassThrough
+ glPopName
+ glPushName
+ glDrawBuffer
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearStencil
+ glClearDepth
+ glStencilMask
+ glColorMask
+ glDepthMask
+ glIndexMask
+ glAccum
+ glDisable
+ glEnable
+ glFinish
+ glFlush
+ glPopAttrib
+ glPushAttrib
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalPoint1
+ glEvalMesh2
+ glEvalPoint2
+ glAlphaFunc
+ glBlendFunc
+ glLogicOp
+ glStencilFunc
+ glStencilOp
+ glDepthFunc
+ glPixelZoom
+ glPixelTransferf
+ glPixelTransferi
+ glPixelStoref
+ glPixelStorei
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glReadBuffer
+ glCopyPixels
+ glReadPixels
+ glDrawPixels
+ glGetBooleanv
+ glGetClipPlane
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glIsEnabled
+ glIsList
+ glDepthRange
+ glFrustum
+ glLoadIdentity
+ glLoadMatrixf
+ glLoadMatrixd
+ glMatrixMode
+ glMultMatrixf
+ glMultMatrixd
+ glOrtho
+ glPopMatrix
+ glPushMatrix
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glTranslated
+ glTranslatef
+ glViewport
+ glArrayElement
+ glColorPointer
+ glDisableClientState
+ glDrawArrays
+ glDrawElements
+ glEdgeFlagPointer
+ glEnableClientState
+ glGetPointerv
+ glIndexPointer
+ glInterleavedArrays
+ glNormalPointer
+ glTexCoordPointer
+ glVertexPointer
+ glPolygonOffset
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glTexSubImage1D
+ glTexSubImage2D
+ glAreTexturesResident
+ glBindTexture
+ glDeleteTextures
+ glGenTextures
+ glIsTexture
+ glPrioritizeTextures
+ glIndexub
+ glIndexubv
+ glPopClientAttrib
+ glPushClientAttrib
+ glBlendColor
+ glBlendEquation
+ glDrawRangeElements
+ glColorTable
+ glColorTableParameterfv
+ glColorTableParameteriv
+ glCopyColorTable
+ glGetColorTable
+ glGetColorTableParameterfv
+ glGetColorTableParameteriv
+ glColorSubTable
+ glCopyColorSubTable
+ glConvolutionFilter1D
+ glConvolutionFilter2D
+ glConvolutionParameterf
+ glConvolutionParameterfv
+ glConvolutionParameteri
+ glConvolutionParameteriv
+ glCopyConvolutionFilter1D
+ glCopyConvolutionFilter2D
+ glGetConvolutionFilter
+ glGetConvolutionParameterfv
+ glGetConvolutionParameteriv
+ glGetSeparableFilter
+ glSeparableFilter2D
+ glGetHistogram
+ glGetHistogramParameterfv
+ glGetHistogramParameteriv
+ glGetMinmax
+ glGetMinmaxParameterfv
+ glGetMinmaxParameteriv
+ glHistogram
+ glMinmax
+ glResetHistogram
+ glResetMinmax
+ glTexImage3D
+ glTexSubImage3D
+ glCopyTexSubImage3D
+ 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
+ glLoadTransposeMatrixfARB
+ glLoadTransposeMatrixdARB
+ glMultTransposeMatrixfARB
+ glMultTransposeMatrixdARB
+ glSampleCoverageARB
+ glCompressedTexImage3DARB
+ glCompressedTexImage2DARB
+ glCompressedTexImage1DARB
+ glCompressedTexSubImage3DARB
+ glCompressedTexSubImage2DARB
+ glCompressedTexSubImage1DARB
+ glGetCompressedTexImageARB
+ glActiveTexture
+ glClientActiveTexture
+ glMultiTexCoord1d
+ glMultiTexCoord1dv
+ glMultiTexCoord1f
+ glMultiTexCoord1fv
+ glMultiTexCoord1i
+ glMultiTexCoord1iv
+ glMultiTexCoord1s
+ glMultiTexCoord1sv
+ glMultiTexCoord2d
+ glMultiTexCoord2dv
+ glMultiTexCoord2f
+ glMultiTexCoord2fv
+ glMultiTexCoord2i
+ glMultiTexCoord2iv
+ glMultiTexCoord2s
+ glMultiTexCoord2sv
+ glMultiTexCoord3d
+ glMultiTexCoord3dv
+ glMultiTexCoord3f
+ glMultiTexCoord3fv
+ glMultiTexCoord3i
+ glMultiTexCoord3iv
+ glMultiTexCoord3s
+ glMultiTexCoord3sv
+ glMultiTexCoord4d
+ glMultiTexCoord4dv
+ glMultiTexCoord4f
+ glMultiTexCoord4fv
+ glMultiTexCoord4i
+ glMultiTexCoord4iv
+ glMultiTexCoord4s
+ glMultiTexCoord4sv
+ glLoadTransposeMatrixf
+ glLoadTransposeMatrixd
+ glMultTransposeMatrixf
+ glMultTransposeMatrixd
+ glSampleCoverage
+ glCompressedTexImage3D
+ glCompressedTexImage2D
+ glCompressedTexImage1D
+ glCompressedTexSubImage3D
+ glCompressedTexSubImage2D
+ glCompressedTexSubImage1D
+ glGetCompressedTexImage
+ glBlendColorEXT
+ glPolygonOffsetEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+ glTexSubImage1DEXT
+ glTexSubImage2DEXT
+ glCopyTexImage1DEXT
+ glCopyTexImage2DEXT
+ glCopyTexSubImage1DEXT
+ glCopyTexSubImage2DEXT
+ glCopyTexSubImage3DEXT
+ glAreTexturesResidentEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glIsTextureEXT
+ glPrioritizeTexturesEXT
+ glArrayElementEXT
+ glColorPointerEXT
+ glDrawArraysEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glIndexPointerEXT
+ glNormalPointerEXT
+ glTexCoordPointerEXT
+ glVertexPointerEXT
+ glBlendEquationEXT
+ glPointParameterfEXT
+ glPointParameterfvEXT
+ glPointParameterfARB
+ glPointParameterfvARB
+ glColorTableEXT
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glLockArraysEXT
+ glUnlockArraysEXT
+ glDrawRangeElementsEXT
+ glSecondaryColor3bEXT
+ glSecondaryColor3bvEXT
+ glSecondaryColor3dEXT
+ glSecondaryColor3dvEXT
+ glSecondaryColor3fEXT
+ glSecondaryColor3fvEXT
+ glSecondaryColor3iEXT
+ glSecondaryColor3ivEXT
+ glSecondaryColor3sEXT
+ glSecondaryColor3svEXT
+ glSecondaryColor3ubEXT
+ glSecondaryColor3ubvEXT
+ glSecondaryColor3uiEXT
+ glSecondaryColor3uivEXT
+ glSecondaryColor3usEXT
+ glSecondaryColor3usvEXT
+ glSecondaryColorPointerEXT
+ glMultiDrawArraysEXT
+ glMultiDrawElementsEXT
+ glFogCoordfEXT
+ glFogCoordfvEXT
+ glFogCoorddEXT
+ glFogCoorddvEXT
+ glFogCoordPointerEXT
+ glBlendFuncSeparateEXT
+ glFlushVertexArrayRangeNV
+ glVertexArrayRangeNV
+ glCombinerParameterfvNV
+ glCombinerParameterfNV
+ glCombinerParameterivNV
+ glCombinerParameteriNV
+ glCombinerInputNV
+ glCombinerOutputNV
+ glFinalCombinerInputNV
+ glGetCombinerInputParameterfvNV
+ glGetCombinerInputParameterivNV
+ glGetCombinerOutputParameterfvNV
+ glGetCombinerOutputParameterivNV
+ glGetFinalCombinerInputParameterfvNV
+ glGetFinalCombinerInputParameterivNV
+ glResizeBuffersMESA
+ glWindowPos2dMESA
+ glWindowPos2dvMESA
+ glWindowPos2fMESA
+ glWindowPos2fvMESA
+ glWindowPos2iMESA
+ glWindowPos2ivMESA
+ glWindowPos2sMESA
+ glWindowPos2svMESA
+ glWindowPos3dMESA
+ glWindowPos3dvMESA
+ glWindowPos3fMESA
+ glWindowPos3fvMESA
+ glWindowPos3iMESA
+ glWindowPos3ivMESA
+ glWindowPos3sMESA
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+ glWindowPos2dARB
+ glWindowPos2fARB
+ glWindowPos2iARB
+ glWindowPos2sARB
+ glWindowPos2dvARB
+ glWindowPos2fvARB
+ glWindowPos2ivARB
+ glWindowPos2svARB
+ glWindowPos3dARB
+ glWindowPos3fARB
+ glWindowPos3iARB
+ glWindowPos3sARB
+ glWindowPos3dvARB
+ glWindowPos3fvARB
+ glWindowPos3ivARB
+ glWindowPos3svARB
+ glAreProgramsResidentNV
+ glBindProgramNV
+ glDeleteProgramsNV
+ glExecuteProgramNV
+ glGenProgramsNV
+ glGetProgramParameterdvNV
+ glGetProgramParameterfvNV
+ glGetProgramivNV
+ glGetProgramStringNV
+ glGetTrackMatrixivNV
+ glGetVertexAttribdvNV
+ glGetVertexAttribfvNV
+ glGetVertexAttribivNV
+ glGetVertexAttribPointervNV
+ glIsProgramNV
+ glLoadProgramNV
+ glProgramParameter4dNV
+ glProgramParameter4dvNV
+ glProgramParameter4fNV
+ glProgramParameter4fvNV
+ glProgramParameters4dvNV
+ glProgramParameters4fvNV
+ glRequestResidentProgramsNV
+ glTrackMatrixNV
+ glVertexAttribPointerNV
+ glVertexAttrib1dNV
+ glVertexAttrib1dvNV
+ glVertexAttrib1fNV
+ glVertexAttrib1fvNV
+ glVertexAttrib1sNV
+ glVertexAttrib1svNV
+ glVertexAttrib2dNV
+ glVertexAttrib2dvNV
+ glVertexAttrib2fNV
+ glVertexAttrib2fvNV
+ glVertexAttrib2sNV
+ glVertexAttrib2svNV
+ glVertexAttrib3dNV
+ glVertexAttrib3dvNV
+ glVertexAttrib3fNV
+ glVertexAttrib3fvNV
+ glVertexAttrib3sNV
+ glVertexAttrib3svNV
+ glVertexAttrib4dNV
+ glVertexAttrib4dvNV
+ glVertexAttrib4fNV
+ glVertexAttrib4fvNV
+ glVertexAttrib4sNV
+ glVertexAttrib4svNV
+ glVertexAttrib4ubNV
+ glVertexAttrib4ubvNV
+ glVertexAttribs1dvNV
+ glVertexAttribs1fvNV
+ glVertexAttribs1svNV
+ glVertexAttribs2dvNV
+ glVertexAttribs2fvNV
+ glVertexAttribs2svNV
+ glVertexAttribs3dvNV
+ glVertexAttribs3fvNV
+ glVertexAttribs3svNV
+ glVertexAttribs4dvNV
+ glVertexAttribs4fvNV
+ glVertexAttribs4svNV
+ glVertexAttribs4ubvNV
+ glPointParameteriNV
+ glPointParameterivNV
+ glFogCoordf
+ glFogCoordfv
+ glFogCoordd
+ glFogCoorddv
+ glFogCoordPointer
+ glMultiDrawArrays
+ glMultiDrawElements
+ glPointParameterf
+ glPointParameterfv
+ glPointParameteri
+ glPointParameteriv
+ glSecondaryColor3b
+ glSecondaryColor3bv
+ glSecondaryColor3d
+ glSecondaryColor3dv
+ glSecondaryColor3f
+ glSecondaryColor3fv
+ glSecondaryColor3i
+ glSecondaryColor3iv
+ glSecondaryColor3s
+ glSecondaryColor3sv
+ glSecondaryColor3ub
+ glSecondaryColor3ubv
+ glSecondaryColor3ui
+ glSecondaryColor3uiv
+ glSecondaryColor3us
+ glSecondaryColor3usv
+ glSecondaryColorPointer
+ glWindowPos2d
+ glWindowPos2dv
+ glWindowPos2f
+ glWindowPos2fv
+ glWindowPos2i
+ glWindowPos2iv
+ glWindowPos2s
+ glWindowPos2sv
+ glWindowPos3d
+ glWindowPos3dv
+ glWindowPos3f
+ glWindowPos3fv
+ glWindowPos3i
+ glWindowPos3iv
+ glWindowPos3s
+ glWindowPos3sv
+ glVertexAttrib1sARB
+ glVertexAttrib1fARB
+ glVertexAttrib1dARB
+ glVertexAttrib2sARB
+ glVertexAttrib2fARB
+ glVertexAttrib2dARB
+ glVertexAttrib3sARB
+ glVertexAttrib3fARB
+ glVertexAttrib3dARB
+ glVertexAttrib4sARB
+ glVertexAttrib4fARB
+ glVertexAttrib4dARB
+ glVertexAttrib4NubARB
+ glVertexAttrib1svARB
+ glVertexAttrib1fvARB
+ glVertexAttrib1dvARB
+ glVertexAttrib2svARB
+ glVertexAttrib2fvARB
+ glVertexAttrib2dvARB
+ glVertexAttrib3svARB
+ glVertexAttrib3fvARB
+ glVertexAttrib3dvARB
+ glVertexAttrib4bvARB
+ glVertexAttrib4svARB
+ glVertexAttrib4ivARB
+ glVertexAttrib4ubvARB
+ glVertexAttrib4usvARB
+ glVertexAttrib4uivARB
+ glVertexAttrib4fvARB
+ glVertexAttrib4dvARB
+ glVertexAttrib4NbvARB
+ glVertexAttrib4NsvARB
+ glVertexAttrib4NivARB
+ glVertexAttrib4NubvARB
+ glVertexAttrib4NusvARB
+ glVertexAttrib4NuivARB
+ glVertexAttribPointerARB
+ glEnableVertexAttribArrayARB
+ glDisableVertexAttribArrayARB
+ glProgramStringARB
+ glBindProgramARB
+ glDeleteProgramsARB
+ glGenProgramsARB
+ glIsProgramARB
+ glProgramEnvParameter4dARB
+ glProgramEnvParameter4dvARB
+ glProgramEnvParameter4fARB
+ glProgramEnvParameter4fvARB
+ glProgramLocalParameter4dARB
+ glProgramLocalParameter4dvARB
+ glProgramLocalParameter4fARB
+ glProgramLocalParameter4fvARB
+ glGetProgramEnvParameterdvARB
+ glGetProgramEnvParameterfvARB
+ glGetProgramLocalParameterdvARB
+ glGetProgramLocalParameterfvARB
+ glGetProgramivARB
+ glGetProgramStringARB
+ glGetVertexAttribdvARB
+ glGetVertexAttribfvARB
+ glGetVertexAttribivARB
+ glGetVertexAttribPointervARB
+ glProgramNamedParameter4fNV
+ glProgramNamedParameter4dNV
+ glProgramNamedParameter4fvNV
+ glProgramNamedParameter4dvNV
+ glGetProgramNamedParameterfvNV
+ glGetProgramNamedParameterdvNV
+ glBindBufferARB
+ glBufferDataARB
+ glBufferSubDataARB
+ glDeleteBuffersARB
+ glGenBuffersARB
+ glGetBufferParameterivARB
+ glGetBufferPointervARB
+ glGetBufferSubDataARB
+ glIsBufferARB
+ glMapBufferARB
+ glUnmapBufferARB
+ glGenQueriesARB
+ glDeleteQueriesARB
+ glIsQueryARB
+ glBeginQueryARB
+ glEndQueryARB
+ glGetQueryivARB
+ glGetQueryObjectivARB
+ glGetQueryObjectuivARB
+ glBindBuffer
+ glBufferData
+ glBufferSubData
+ glDeleteBuffers
+ glGenBuffers
+ glGetBufferParameteriv
+ glGetBufferPointerv
+ glGetBufferSubData
+ glIsBuffer
+ glMapBuffer
+ glUnmapBuffer
+ glGenQueries
+ glDeleteQueries
+ glIsQuery
+ glBeginQuery
+ glEndQuery
+ glGetQueryiv
+ glGetQueryObjectiv
+ glGetQueryObjectuiv
+;
+; WGL API
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglGetExtensionsStringARB
+;
+; Mesa internals - mostly for OSMESA
+ _vbo_CreateContext
+ _vbo_DestroyContext
+ _vbo_InvalidateState
+ _glapi_check_multithread
+ _glapi_get_context
+ _glapi_get_proc_address
+ _mesa_add_soft_renderbuffers
+ _mesa_add_renderbuffer
+ _mesa_begin_query
+ _mesa_buffer_data
+ _mesa_buffer_get_subdata
+ _mesa_buffer_map
+ _mesa_buffer_subdata
+ _mesa_buffer_unmap
+ _mesa_bzero
+ _mesa_calloc
+ _mesa_choose_tex_format
+ _mesa_compressed_texture_size
+ _mesa_create_framebuffer
+ _mesa_create_visual
+ _mesa_delete_array_object
+ _mesa_delete_buffer_object
+ _mesa_delete_program
+ _mesa_delete_query
+ _mesa_delete_texture_object
+ _mesa_destroy_framebuffer
+ _mesa_destroy_visual
+ _mesa_enable_1_3_extensions
+ _mesa_enable_1_4_extensions
+ _mesa_enable_1_5_extensions
+ _mesa_enable_2_0_extensions
+ _mesa_enable_2_1_extensions
+ _mesa_enable_sw_extensions
+ _mesa_end_query
+ _mesa_error
+ _mesa_finish_render_texture
+ _mesa_framebuffer_renderbuffer
+ _mesa_free
+ _mesa_free_context_data
+ _mesa_free_texture_image_data
+ _mesa_generate_mipmap
+ _mesa_get_compressed_teximage
+ _mesa_get_current_context
+ _mesa_get_teximage
+ _mesa_init_driver_functions
+ _mesa_init_glsl_driver_functions
+ _mesa_init_renderbuffer
+ _mesa_initialize_context
+ _mesa_make_current
+ _mesa_memcpy
+ _mesa_memset
+ _mesa_new_array_object
+ _mesa_new_buffer_object
+ _mesa_new_framebuffer
+ _mesa_new_program
+ _mesa_new_query_object
+ _mesa_new_renderbuffer
+ _mesa_new_soft_renderbuffer
+ _mesa_new_texture_image
+ _mesa_new_texture_object
+ _mesa_problem
+ _mesa_reference_renderbuffer
+ _mesa_remove_renderbuffer
+ _mesa_render_texture
+ _mesa_ResizeBuffersMESA
+ _mesa_resize_framebuffer
+ _mesa_store_compressed_teximage1d
+ _mesa_store_compressed_teximage2d
+ _mesa_store_compressed_teximage3d
+ _mesa_store_compressed_texsubimage1d
+ _mesa_store_compressed_texsubimage2d
+ _mesa_store_compressed_texsubimage3d
+ _mesa_store_teximage1d
+ _mesa_store_teximage2d
+ _mesa_store_teximage3d
+ _mesa_store_texsubimage1d
+ _mesa_store_texsubimage2d
+ _mesa_store_texsubimage3d
+ _mesa_strcmp
+ _mesa_test_proxy_teximage
+ _mesa_reference_framebuffer
+ _mesa_update_framebuffer_visual
+ _mesa_use_program
+ _mesa_Viewport
+ _mesa_wait_query
+ _swrast_Accum
+ _swrast_Bitmap
+ _swrast_BlitFramebuffer
+ _swrast_CopyPixels
+ _swrast_DrawPixels
+ _swrast_GetDeviceDriverReference
+ _swrast_Clear
+ _swrast_choose_line
+ _swrast_choose_triangle
+ _swrast_CopyColorSubTable
+ _swrast_CopyColorTable
+ _swrast_CopyConvolutionFilter1D
+ _swrast_CopyConvolutionFilter2D
+ _swrast_copy_teximage1d
+ _swrast_copy_teximage2d
+ _swrast_copy_texsubimage1d
+ _swrast_copy_texsubimage2d
+ _swrast_copy_texsubimage3d
+ _swrast_CreateContext
+ _swrast_DestroyContext
+ _swrast_exec_fragment_program
+ _swrast_InvalidateState
+ _swrast_ReadPixels
+ _swsetup_Wakeup
+ _swsetup_CreateContext
+ _swsetup_DestroyContext
+ _swsetup_InvalidateState
+ _tnl_CreateContext
+ _tnl_DestroyContext
+ _tnl_InvalidateState
+ _tnl_run_pipeline
+ _tnl_program_string
+ _tnl_RasterPos \ No newline at end of file
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wgl.c b/mesalib/src/mesa/drivers/windows/gdi/wgl.c
new file mode 100644
index 000000000..8d8087067
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/wgl.c
@@ -0,0 +1,707 @@
+
+/*
+ * 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
+ */
+
+/*
+ * This file contains the implementation of the wgl* functions for
+ * Mesa on Windows. Since these functions are provided by Windows in
+ * GDI/OpenGL, we must supply our versions that work with Mesa here.
+ */
+
+
+/* We're essentially building part of GDI here, so define this so that
+ * we get the right export linkage. */
+#ifdef __MINGW32__
+
+#include <stdarg.h>
+#include <windef.h>
+#include <wincon.h>
+#include <winbase.h>
+
+# if defined(BUILD_GL32)
+# define WINGDIAPI __declspec(dllexport)
+# else
+# define __W32API_USE_DLLIMPORT__
+# endif
+
+#include <wingdi.h>
+#include "GL/mesa_wgl.h"
+#include <stdlib.h>
+
+#else
+
+#define _GDI32_
+#include <windows.h>
+
+#endif
+#include "config.h"
+#include "glapi.h"
+#include "GL/wmesa.h" /* protos for wmesa* functions */
+
+/*
+ * Pixel Format Descriptors
+ */
+
+/* Extend the PFD to include DB flag */
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLboolean doubleBuffered;
+};
+
+
+
+/* These are the PFD's supported by this driver. */
+struct __pixelformat__ pfd[] =
+{
+#if 0
+ /* Double Buffer, alpha */
+ {
+ {
+ 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,
+ DEFAULT_SOFTWARE_DEPTH_BITS, 8,
+ 0, 0, 0,
+ 0, 0, 0
+ },
+ GL_TRUE
+ },
+ /* Single Buffer, alpha */
+ {
+ {
+ 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,
+ DEFAULT_SOFTWARE_DEPTH_BITS, 8,
+ 0, 0, 0,
+ 0, 0, 0
+ },
+ GL_FALSE
+ },
+#endif
+ /* Double Buffer, no alpha */
+ {
+ {
+ 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,
+ 0, 0,
+ 0, 0, 0, 0, 0,
+ DEFAULT_SOFTWARE_DEPTH_BITS, 8,
+ 0, 0, 0,
+ 0, 0, 0
+ },
+ GL_TRUE
+ },
+ /* Single Buffer, no alpha */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_GENERIC_FORMAT,
+ PFD_TYPE_RGBA,
+ 24,
+ 8, 0,
+ 8, 8,
+ 8, 16,
+ 0, 0,
+ 0, 0, 0, 0, 0,
+ DEFAULT_SOFTWARE_DEPTH_BITS, 8,
+ 0, 0, 0,
+ 0, 0, 0
+ },
+ GL_FALSE
+ },
+};
+
+int npfd = sizeof(pfd) / sizeof(pfd[0]);
+
+
+/*
+ * Contexts
+ */
+
+typedef struct {
+ WMesaContext ctx;
+} MesaWglCtx;
+
+#define MESAWGL_CTX_MAX_COUNT 20
+
+static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
+
+static unsigned ctx_count = 0;
+static int ctx_current = -1;
+static unsigned curPFD = 0;
+
+static HDC CurrentHDC = 0;
+
+
+WINGDIAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc)
+{
+ int i = 0;
+ if (!ctx_count) {
+ for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++) {
+ wgl_ctx[i].ctx = NULL;
+ }
+ }
+ for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) {
+ if ( wgl_ctx[i].ctx == NULL ) {
+ wgl_ctx[i].ctx =
+ WMesaCreateContext(hdc, NULL, (GLboolean)GL_TRUE,
+ (GLboolean) (pfd[curPFD-1].doubleBuffered ?
+ GL_TRUE : GL_FALSE),
+ (GLboolean)(pfd[curPFD-1].pfd.cAlphaBits ?
+ GL_TRUE : GL_FALSE) );
+ if (wgl_ctx[i].ctx == NULL)
+ break;
+ ctx_count++;
+ return ((HGLRC)wgl_ctx[i].ctx);
+ }
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc)
+{
+ int i;
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) {
+ if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ){
+ WMesaMakeCurrent((WMesaContext) hglrc, NULL);
+ WMesaDestroyContext(wgl_ctx[i].ctx);
+ wgl_ctx[i].ctx = NULL;
+ ctx_count--;
+ return(TRUE);
+ }
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID)
+{
+ if (ctx_current < 0)
+ return 0;
+ else
+ return (HGLRC) wgl_ctx[ctx_current].ctx;
+}
+
+WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID)
+{
+ return CurrentHDC;
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc)
+{
+ int i;
+
+ CurrentHDC = hdc;
+
+ if (!hdc || !hglrc) {
+ WMesaMakeCurrent(NULL, NULL);
+ ctx_current = -1;
+ return TRUE;
+ }
+
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) {
+ if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ) {
+ WMesaMakeCurrent( (WMesaContext) hglrc, hdc );
+ ctx_current = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+WINGDIAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc,
+ CONST
+ PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i,best = -1,bestdelta = 0x7FFFFFFF,delta;
+ (void) hdc;
+
+ if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ for(i = 0; i < npfd;i++)
+ {
+ delta = 0;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) &&
+ !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) &&
+ !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_GDI) &&
+ !(pfd[i].pfd.dwFlags & PFD_SUPPORT_GDI))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_OPENGL) &&
+ !(pfd[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
+ (pfd[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_STEREO) !=
+ (pfd[i].pfd.dwFlags & PFD_STEREO)))
+ continue;
+ if(ppfd->iPixelType != pfd[i].pfd.iPixelType)
+ delta++;
+ if(ppfd->cAlphaBits != pfd[i].pfd.cAlphaBits)
+ delta++;
+ if(delta < bestdelta)
+ {
+ best = i + 1;
+ bestdelta = delta;
+ if(bestdelta == 0)
+ break;
+ }
+ }
+ if(best == -1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ return(best);
+}
+
+WINGDIAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc,
+ int iPixelFormat,
+ UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ (void) hdc;
+
+ if(ppfd == NULL)
+ return(npfd);
+ if(iPixelFormat < 1 || iPixelFormat > npfd ||
+ nBytes != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(0);
+ }
+ *ppfd = pfd[iPixelFormat - 1].pfd;
+ return(npfd);
+}
+
+WINGDIAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc)
+{
+ PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc);
+ if (p)
+ return p;
+
+ SetLastError(0);
+ return(NULL);
+}
+
+WINGDIAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc)
+{
+ (void) hdc;
+ if(curPFD == 0) {
+ SetLastError(0);
+ return(0);
+ }
+ return(curPFD);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
+ const PIXELFORMATDESCRIPTOR *ppfd)
+{
+ (void) hdc;
+
+ if(iPixelFormat < 1 || iPixelFormat > npfd ||
+ ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+ return(TRUE);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
+{
+ WMesaSwapBuffers(hdc);
+ return TRUE;
+}
+
+static FIXED FixedFromDouble(double d)
+{
+ long l = (long) (d * 65536L);
+ return *(FIXED *) (void *) &l;
+}
+
+
+/*
+** This is cribbed from FX/fxwgl.c, and seems to implement support
+** for bitmap fonts where the wglUseFontBitmapsA() code implements
+** support for outline fonts. In combination they hopefully give
+** fairly generic support for fonts.
+*/
+static BOOL wglUseFontBitmaps_FX(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);
+
+ /* 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) != GDI_ERROR ? 1 : 0);
+
+ for(i = 0; i < (int)numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = (char)(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;
+ /* Round up to the next multiple of 32 bits */
+ bmapWidth = ((charWidth + 31) / 32) * 32;
+ bmapHeight = charHeight;
+ bitObject = CreateCompatibleBitmap(bitDevice,
+ bmapWidth,
+ bmapHeight);
+ /* VERIFY(bitObject); */
+
+ /* Assign the output bitmap to the device */
+ origBmap = SelectObject(bitDevice, bitObject);
+ (void) 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, (GLfloat)metric.tmDescent,
+ (GLfloat)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
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first,
+ DWORD count, DWORD listBase)
+{
+ int i;
+ GLuint font_list;
+ DWORD size;
+ GLYPHMETRICS gm;
+ HANDLE hBits;
+ LPSTR lpBits;
+ MAT2 mat;
+ int success = TRUE;
+
+ if (count == 0)
+ return FALSE;
+
+ font_list = listBase;
+
+ mat.eM11 = FixedFromDouble(1);
+ mat.eM12 = FixedFromDouble(0);
+ mat.eM21 = FixedFromDouble(0);
+ mat.eM22 = FixedFromDouble(-1);
+
+ memset(&gm,0,sizeof(gm));
+
+ /*
+ ** If we can't get the glyph outline, it may be because this is a fixed
+ ** font. Try processing it that way.
+ */
+ if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat)
+ == GDI_ERROR ) {
+ return wglUseFontBitmaps_FX( hdc, first, count, listBase );
+ }
+
+ /*
+ ** Otherwise process all desired characters.
+ */
+ for (i = 0; i < (int)count; i++) {
+ DWORD err;
+
+ 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) {
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ hBits = GlobalAlloc(GHND, size+1);
+ lpBits = GlobalLock(hBits);
+
+ err =
+ GetGlyphOutline(hdc, /* handle to device context */
+ first + i, /* character to query */
+ GGO_BITMAP, /* format of data to return */
+ &gm, /* ptr to structure for metrics*/
+ size, /* size of buffer for data */
+ lpBits, /* pointer to buffer for data */
+ &mat /* pointer to transformation */
+ /* matrix structure */
+ );
+
+ if (err == GDI_ERROR) {
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
+ (GLfloat)-gm.gmptGlyphOrigin.x,
+ (GLfloat)gm.gmptGlyphOrigin.y,
+ (GLfloat)gm.gmCellIncX,
+ (GLfloat)gm.gmCellIncY,
+ (const GLubyte * )lpBits);
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ }
+
+ return success;
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,
+ HGLRC hglrc2)
+{
+ WMesaShareLists((WMesaContext)hglrc1, (WMesaContext)hglrc2);
+ return(TRUE);
+}
+
+
+
+/* NOT IMPLEMENTED YET */
+WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,
+ HGLRC hglrcDst,
+ UINT mask)
+{
+ (void) hglrcSrc; (void) hglrcDst; (void) mask;
+ return(FALSE);
+}
+
+WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,
+ int iLayerPlane)
+{
+ SetLastError(0);
+ if (iLayerPlane == 0)
+ return wglCreateContext( hdc );
+ return(NULL);
+}
+
+
+WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ (void) hdc; (void) first; (void) count; (void) listBase;
+ return FALSE;
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ (void) hdc; (void) first; (void) count;
+ (void) listBase; (void) deviation; (void) extrusion; (void) format;
+ (void) lpgmf;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ (void) hdc; (void) first; (void) count;
+ (void) listBase; (void) deviation; (void) extrusion; (void) format;
+ (void) lpgmf;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ (void) hdc; (void) iPixelFormat; (void) iLayerPlane;
+ (void) nBytes; (void) plpd;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc,
+ int iLayerPlane,
+ int iStart,
+ int cEntries,
+ CONST COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart;
+ (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WINGDIAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc,
+ int iLayerPlane,
+ int iStart,
+ int cEntries,
+ COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc,
+ int iLayerPlane,
+ BOOL bRealize)
+{
+ (void) hdc; (void) iLayerPlane; (void) bRealize;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,
+ UINT fuPlanes)
+{
+ (void) hdc; (void) fuPlanes;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WINGDIAPI const char * GLAPIENTRY wglGetExtensionsStringARB(HDC hdc)
+{
+ return "WGL_ARB_extensions_string";
+}
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
new file mode 100644
index 000000000..e1971db69
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
@@ -0,0 +1,1681 @@
+/*
+ * Windows (Win32/Win64) device driver for Mesa
+ *
+ */
+
+#include "wmesadef.h"
+#include "colors.h"
+#include <GL/wmesa.h>
+#include <winuser.h>
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "drivers/common/driverfuncs.h"
+#include "vbo/vbo.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+/* linked list of our Framebuffers (windows) */
+static WMesaFramebuffer FirstFramebuffer = NULL;
+
+
+/**
+ * Create a new WMesaFramebuffer object which will correspond to the
+ * given HDC (Window handle).
+ */
+WMesaFramebuffer
+wmesa_new_framebuffer(HDC hdc, GLvisual *visual)
+{
+ WMesaFramebuffer pwfb
+ = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
+ if (pwfb) {
+ _mesa_initialize_framebuffer(&pwfb->Base, visual);
+ pwfb->hDC = hdc;
+ /* insert at head of list */
+ pwfb->next = FirstFramebuffer;
+ FirstFramebuffer = pwfb;
+ }
+ return pwfb;
+}
+
+/**
+ * Given an hdc, free the corresponding WMesaFramebuffer
+ */
+void
+wmesa_free_framebuffer(HDC hdc)
+{
+ WMesaFramebuffer pwfb, prev;
+ for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+ if (pwfb->hDC == hdc)
+ break;
+ prev = pwfb;
+ }
+ if (pwfb) {
+ struct gl_framebuffer *fb;
+ if (pwfb == FirstFramebuffer)
+ FirstFramebuffer = pwfb->next;
+ else
+ prev->next = pwfb->next;
+ fb = &pwfb->Base;
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+}
+
+/**
+ * Given an hdc, return the corresponding WMesaFramebuffer
+ */
+WMesaFramebuffer
+wmesa_lookup_framebuffer(HDC hdc)
+{
+ WMesaFramebuffer pwfb;
+ for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
+ if (pwfb->hDC == hdc)
+ return pwfb;
+ }
+ return NULL;
+}
+
+
+/**
+ * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
+ */
+static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb)
+{
+ return (WMesaFramebuffer) fb;
+}
+
+
+/**
+ * Given a GLcontext, return the corresponding WMesaContext.
+ */
+static WMesaContext wmesa_context(const GLcontext *ctx)
+{
+ return (WMesaContext) ctx;
+}
+
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
+{
+ return (name == GL_RENDERER) ?
+ (GLubyte *) "Mesa Windows GDI Driver" : NULL;
+}
+
+
+/*
+ * Determine the pixel format based on the pixel size.
+ */
+static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
+{
+ pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+
+ /* Only 16 and 32 bit targets are supported now */
+ assert(pwfb->cColorBits == 0 ||
+ pwfb->cColorBits == 16 ||
+ pwfb->cColorBits == 24 ||
+ pwfb->cColorBits == 32);
+
+ switch(pwfb->cColorBits){
+ case 8:
+ pwfb->pixelformat = PF_INDEX8;
+ break;
+ case 16:
+ pwfb->pixelformat = PF_5R6G5B;
+ break;
+ case 24:
+ case 32:
+ pwfb->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ pwfb->pixelformat = PF_BADFORMAT;
+ }
+}
+
+
+/**
+ * Create DIB for back buffer.
+ * We write into this memory with the span routines and then blit it
+ * to the window on a buffer swap.
+ */
+BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
+{
+ HDC hdc = pwfb->hDC;
+ LPBITMAPINFO pbmi = &(pwfb->bmi);
+ HDC hic;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->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;
+
+ pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwfb->dib_hDC = CreateCompatibleDC(hic);
+
+ pwfb->hbmDIB = CreateDIBSection(hic,
+ &pwfb->bmi,
+ DIB_RGB_COLORS,
+ (void **)&(pwfb->pbPixels),
+ 0,
+ 0);
+ pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
+
+ DeleteDC(hic);
+
+ wmSetPixelFormat(pwfb, pwfb->hDC);
+ return TRUE;
+}
+
+
+static wmDeleteBackingStore(WMesaFramebuffer pwfb)
+{
+ if (pwfb->hbmDIB) {
+ SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
+ DeleteDC(pwfb->dib_hDC);
+ DeleteObject(pwfb->hbmDIB);
+ }
+}
+
+
+/**
+ * Find the width and height of the window named by hdc.
+ */
+static void
+get_window_size(HDC hdc, GLuint *width, GLuint *height)
+{
+ if (WindowFromDC(hdc)) {
+ RECT rect;
+ GetClientRect(WindowFromDC(hdc), &rect);
+ *width = rect.right - rect.left;
+ *height = rect.bottom - rect.top;
+ }
+ else { /* Memory context */
+ /* From contributed code - use the size of the desktop
+ * for the size of a memory context (?) */
+ *width = GetDeviceCaps(hdc, HORZRES);
+ *height = GetDeviceCaps(hdc, VERTRES);
+ }
+}
+
+
+static void
+wmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+ get_window_size(pwfb->hDC, width, height);
+}
+
+
+static void wmesa_flush(GLcontext *ctx)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
+
+ if (ctx->Visual.doubleBufferMode == 1) {
+ BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+ pwfb->dib_hDC, 0, 0, SRCCOPY);
+ }
+ else {
+ /* Do nothing for single buffer */
+ }
+}
+
+
+/**********************************************************************/
+/***** CLEAR Functions *****/
+/**********************************************************************/
+
+/* If we do not implement these, Mesa clears the buffers via the pixel
+ * span writing interface, which is very slow for a clear operation.
+ */
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext *ctx, GLuint index)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ /* Note that indexed mode is not supported yet */
+ pwc->clearColorRef = RGB(0,0,0);
+}
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color(GLcontext *ctx, const GLfloat color[4])
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLubyte col[3];
+ UINT bytesPerPixel = pwfb->cColorBits / 8;
+
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ pwc->clearColorRef = RGB(col[0], col[1], col[2]);
+ DeleteObject(pwc->clearPen);
+ DeleteObject(pwc->clearBrush);
+ pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
+ pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
+}
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ */
+
+static void clear(GLcontext *ctx, GLbitfield mask)
+{
+#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ int done = 0;
+
+ /* Let swrast do all the work if the masks are not set to
+ * clear all channels. */
+ if (ctx->Color.ColorMask[0] != 0xff ||
+ ctx->Color.ColorMask[1] != 0xff ||
+ ctx->Color.ColorMask[2] != 0xff ||
+ ctx->Color.ColorMask[3] != 0xff) {
+ _swrast_Clear(ctx, mask);
+ return;
+ }
+
+ /* Back buffer */
+ if (mask & BUFFER_BIT_BACK_LEFT) {
+
+ int i, rowSize;
+ UINT bytesPerPixel = pwfb->cColorBits / 8;
+ LPBYTE lpb, clearRow;
+ LPWORD lpw;
+ BYTE bColor;
+ WORD wColor;
+ BYTE r, g, b;
+ DWORD dwColor;
+ LPDWORD lpdw;
+
+ /* Try for a fast clear - clearing entire buffer with a single
+ * byte value. */
+ if (width == ctx->DrawBuffer->Width &&
+ height == ctx->DrawBuffer->Height) { /* entire buffer */
+ /* Now check for an easy clear value */
+ switch (bytesPerPixel) {
+ case 1:
+ bColor = BGR8(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ memset(pwfb->pbPixels, bColor,
+ pwfb->ScanWidth * height);
+ done = 1;
+ break;
+ case 2:
+ wColor = BGR16(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
+ memset(pwfb->pbPixels, wColor & 0xff,
+ pwfb->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ case 3:
+ /* fall through */
+ case 4:
+ if (GetRValue(pwc->clearColorRef) ==
+ GetGValue(pwc->clearColorRef) &&
+ GetRValue(pwc->clearColorRef) ==
+ GetBValue(pwc->clearColorRef)) {
+ memset(pwfb->pbPixels,
+ GetRValue(pwc->clearColorRef),
+ pwfb->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ } /* all */
+
+ if (!done) {
+ /* Need to clear a row at a time. Begin by setting the first
+ * row in the area to be cleared to the clear color. */
+
+ clearRow = pwfb->pbPixels +
+ pwfb->ScanWidth * FLIP(y) +
+ bytesPerPixel * x;
+ switch (bytesPerPixel) {
+ case 1:
+ lpb = clearRow;
+ bColor = BGR8(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ memset(lpb, bColor, width);
+ break;
+ case 2:
+ lpw = (LPWORD)clearRow;
+ wColor = BGR16(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpw++ = wColor;
+ break;
+ case 3:
+ lpb = clearRow;
+ r = GetRValue(pwc->clearColorRef);
+ g = GetGValue(pwc->clearColorRef);
+ b = GetBValue(pwc->clearColorRef);
+ for (i=0; i<width; i++) {
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb++ = r;
+ }
+ break;
+ case 4:
+ lpdw = (LPDWORD)clearRow;
+ dwColor = BGR32(GetRValue(pwc->clearColorRef),
+ GetGValue(pwc->clearColorRef),
+ GetBValue(pwc->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpdw++ = dwColor;
+ break;
+ default:
+ break;
+ } /* switch */
+
+ /* copy cleared row to other rows in buffer */
+ lpb = clearRow - pwfb->ScanWidth;
+ rowSize = width * bytesPerPixel;
+ for (i=1; i<height; i++) {
+ memcpy(lpb, clearRow, rowSize);
+ lpb -= pwfb->ScanWidth;
+ }
+ } /* not done */
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ } /* back buffer */
+
+ /* front buffer */
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
+ HDC DC = pwc->hDC;
+ HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
+ HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
+ Rectangle(DC,
+ x,
+ FLIP(y) + 1,
+ x + width + 1,
+ FLIP(y) - height + 1);
+ SelectObject(DC, Old_Pen);
+ SelectObject(DC, Old_Brush);
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ } /* front buffer */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear(ctx, mask);
+
+#undef FLIP
+}
+
+
+/**********************************************************************/
+/***** PIXEL Functions *****/
+/**********************************************************************/
+
+#define FLIP(Y) (rb->Height - (Y) - 1)
+
+
+/**
+ ** Front Buffer reading/writing
+ ** These are slow, but work with all non-indexed visual types.
+ **/
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+ CONST BITMAPINFO bmi=
+ {
+ {
+ sizeof(BITMAPINFOHEADER),
+ n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
+ }
+ };
+ HBITMAP bmp=0;
+ HDC mdc=0;
+ typedef union
+ {
+ unsigned i;
+ struct {
+ unsigned b:8, g:8, r:8, a:8;
+ };
+ } BGRA;
+ BGRA *bgra, c;
+ int i;
+
+ if (n < 16) { // the value 16 is just guessed
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y,
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y,
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ }
+ else {
+ if (!pwfb) {
+ _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
+ return;
+ }
+ bgra=malloc(n*sizeof(BGRA));
+ if (!bgra) {
+ _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
+ return;
+ }
+ c.a=0;
+ if (mask) {
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ c.r=rgba[i][RCOMP];
+ c.g=rgba[i][GCOMP];
+ c.b=rgba[i][BCOMP];
+ c.a=rgba[i][ACOMP];
+ bgra[i]=c;
+ }
+ else
+ bgra[i].i=0;
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ c.r=rgba[i][RCOMP];
+ c.g=rgba[i][GCOMP];
+ c.b=rgba[i][BCOMP];
+ c.a=rgba[i][ACOMP];
+ bgra[i]=c;
+ }
+ }
+ bmp=CreateBitmap(n, 1, 1, 32, bgra);
+ mdc=CreateCompatibleDC(pwfb->hDC);
+ SelectObject(mdc, bmp);
+ y=FLIP(y);
+ BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
+ SelectObject(mdc, 0);
+ DeleteObject(bmp);
+ DeleteDC(mdc);
+ free(bgra);
+ }
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+
+ (void) ctx;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ COLORREF colorref;
+
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, colorref);
+ }
+ else
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, colorref);
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]),
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ COLORREF colorref;
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+ COLORREF Color;
+ y = FLIP(y);
+ for (i=0; i<n; i++) {
+ Color = GetPixel(pwc->hDC, x+i, y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_front(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint i;
+ COLORREF Color;
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ Color = GetPixel(pwc->hDC, x[i], y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 32-bit */
+
+#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
+LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpdw = BGR32((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPDWORD lpdw;
+ DWORD pixel;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpdw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpdw[i];
+ rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
+ rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
+ rgba[i][BCOMP] = (pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_32(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+ pixel = *lpdw;
+ rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
+ rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
+ rgba[i][BCOMP] = (pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 24-bit */
+
+#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
+LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
+lpb[0] = (b); \
+lpb[1] = (g); \
+lpb[2] = (r); }
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPBYTE lpb;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = rgba[i][BCOMP];
+ lpb[3*i+1] = rgba[i][GCOMP];
+ lpb[3*i+2] = rgba[i][RCOMP];
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ *lpb++ = rgba[i][BCOMP];
+ *lpb++ = rgba[i][GCOMP];
+ *lpb++ = rgba[i][RCOMP];
+ }
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPBYTE lpb;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = rgb[i][BCOMP];
+ lpb[3*i+1] = rgb[i][GCOMP];
+ lpb[3*i+2] = rgb[i][RCOMP];
+ }
+ }
+ else {
+ for (i=0; i<n; i++) {
+ *lpb++ = rgb[i][BCOMP];
+ *lpb++ = rgb[i][GCOMP];
+ *lpb++ = rgb[i][RCOMP];
+ }
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPBYTE lpb;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i]) {
+ lpb[3*i] = color[BCOMP];
+ lpb[3*i+1] = color[GCOMP];
+ lpb[3*i+2] = color[RCOMP];
+ }
+ }
+ else
+ for (i=0; i<n; i++) {
+ *lpb++ = color[BCOMP];
+ *lpb++ = color[GCOMP];
+ *lpb++ = color[RCOMP];
+ }
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ LPBYTE lpb;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
+ for (i=0; i<n; i++) {
+ rgba[i][RCOMP] = lpb[3*i+2];
+ rgba[i][GCOMP] = lpb[3*i+1];
+ rgba[i][BCOMP] = lpb[3*i];
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_24(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ LPBYTE lpb;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
+ rgba[i][RCOMP] = lpb[3*i+2];
+ rgba[i][GCOMP] = lpb[3*i+1];
+ rgba[i][BCOMP] = lpb[3*i];
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 16-bit */
+
+#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
+LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpw = BGR16((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPWORD lpw;
+ WORD pixel;
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ y = FLIP(y);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpw[i];
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_16(const GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
+ pixel = *lpw;
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** BUFFER Functions *****/
+/**********************************************************************/
+
+
+
+
+static void
+wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ _mesa_free(rb);
+}
+
+
+/**
+ * This is called by Mesa whenever it determines that the window size
+ * has changed. Do whatever's needed to cope with that.
+ */
+static GLboolean
+wmesa_renderbuffer_storage(GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width,
+ GLuint height)
+{
+ rb->Width = width;
+ rb->Height = height;
+ return GL_TRUE;
+}
+
+
+/**
+ * Plug in the Get/PutRow/Values functions for a renderbuffer depending
+ * on if we're drawing to the front or back color buffer.
+ */
+void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
+ BYTE cColorBits, int double_buffer)
+{
+ if (double_buffer) {
+ /* back buffer */
+ /* Picking the correct span functions is important because
+ * the DIB was allocated with the indicated depth. */
+ switch(pixelformat) {
+ case PF_5R6G5B:
+ rb->PutRow = write_rgba_span_16;
+ rb->PutRowRGB = write_rgb_span_16;
+ rb->PutMonoRow = write_mono_rgba_span_16;
+ rb->PutValues = write_rgba_pixels_16;
+ rb->PutMonoValues = write_mono_rgba_pixels_16;
+ rb->GetRow = read_rgba_span_16;
+ rb->GetValues = read_rgba_pixels_16;
+ rb->RedBits = 5;
+ rb->GreenBits = 6;
+ rb->BlueBits = 5;
+ break;
+ case PF_8R8G8B:
+ if (cColorBits == 24)
+ {
+ rb->PutRow = write_rgba_span_24;
+ rb->PutRowRGB = write_rgb_span_24;
+ rb->PutMonoRow = write_mono_rgba_span_24;
+ rb->PutValues = write_rgba_pixels_24;
+ rb->PutMonoValues = write_mono_rgba_pixels_24;
+ rb->GetRow = read_rgba_span_24;
+ rb->GetValues = read_rgba_pixels_24;
+ rb->RedBits = 8;
+ rb->GreenBits = 8;
+ rb->BlueBits = 8;
+ }
+ else
+ {
+ rb->PutRow = write_rgba_span_32;
+ rb->PutRowRGB = write_rgb_span_32;
+ rb->PutMonoRow = write_mono_rgba_span_32;
+ rb->PutValues = write_rgba_pixels_32;
+ rb->PutMonoValues = write_mono_rgba_pixels_32;
+ rb->GetRow = read_rgba_span_32;
+ rb->GetValues = read_rgba_pixels_32;
+ rb->RedBits = 8;
+ rb->GreenBits = 8;
+ rb->BlueBits = 8;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ /* front buffer (actual Windows window) */
+ rb->PutRow = write_rgba_span_front;
+ rb->PutRowRGB = write_rgb_span_front;
+ rb->PutMonoRow = write_mono_rgba_span_front;
+ rb->PutValues = write_rgba_pixels_front;
+ rb->PutMonoValues = write_mono_rgba_pixels_front;
+ rb->GetRow = read_rgba_span_front;
+ rb->GetValues = read_rgba_pixels_front;
+ rb->RedBits = 8; /* XXX fix these (565?) */
+ rb->GreenBits = 8;
+ rb->BlueBits = 8;
+ }
+}
+
+/**
+ * Called by ctx->Driver.ResizeBuffers()
+ * Resize the front/back colorbuffers to match the latest window size.
+ */
+static void
+wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
+ GLuint width, GLuint height)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
+
+ if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
+ /* Realloc back buffer */
+ if (ctx->Visual.doubleBufferMode == 1) {
+ wmDeleteBackingStore(pwfb);
+ wmCreateBackingStore(pwfb, width, height);
+ }
+ }
+ _mesa_resize_framebuffer(ctx, buffer, width, height);
+}
+
+
+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * resize events since the driver has no event loop.
+ * Thus, we poll.
+ * MakeCurrent also ends up making a call here, so that ensures
+ * we get the viewport set correctly, even if the app does not call
+ * glViewport and relies on the defaults.
+ */
+static void wmesa_viewport(GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ WMesaContext pwc = wmesa_context(ctx);
+ GLuint new_width, new_height;
+
+ wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
+
+ /**
+ * Resize buffers if the window size changed.
+ */
+ wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
+ ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
+}
+
+
+
+
+/**
+ * Called when the driver should update it's state, based on the new_state
+ * flags.
+ */
+static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
+{
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _vbo_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /* TODO - This code is not complete yet because I
+ * don't know what to do for all state updates.
+ */
+
+ if (new_state & _NEW_BUFFERS) {
+ }
+}
+
+
+
+
+
+/**********************************************************************/
+/***** WMESA Functions *****/
+/**********************************************************************/
+
+WMesaContext WMesaCreateContext(HDC hDC,
+ HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag,
+ GLboolean alpha_flag)
+{
+ WMesaContext c;
+ struct dd_function_table functions;
+ GLint red_bits, green_bits, blue_bits, alpha_bits;
+ GLcontext *ctx;
+ GLvisual *visual;
+
+ (void) Pal;
+
+ /* Indexed mode not supported */
+ if (!rgb_flag)
+ return NULL;
+
+ /* Allocate wmesa context */
+ c = CALLOC_STRUCT(wmesa_context);
+ if (!c)
+ return NULL;
+
+#if 0
+ /* I do not understand this contributed code */
+ /* Support memory and device contexts */
+ if(WindowFromDC(hDC) != NULL) {
+ c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
+ }
+ else {
+ c->hDC = hDC;
+ }
+#else
+ c->hDC = hDC;
+#endif
+
+ /* Get data for visual */
+ /* Dealing with this is actually a bit of overkill because Mesa will end
+ * up treating all color component size requests less than 8 by using
+ * a single byte per channel. In addition, the interface to the span
+ * routines passes colors as an entire byte per channel anyway, so there
+ * is nothing to be saved by telling the visual to be 16 bits if the device
+ * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
+ * channel anyway.
+ * But we go through the motions here anyway.
+ */
+ switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
+ case 16:
+ red_bits = green_bits = blue_bits = 5;
+ alpha_bits = 0;
+ break;
+ default:
+ red_bits = green_bits = blue_bits = 8;
+ alpha_bits = 8;
+ break;
+ }
+ /* Create visual based on flags */
+ visual = _mesa_create_visual(rgb_flag,
+ db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ red_bits, green_bits, blue_bits, /* color RGB */
+ alpha_flag ? alpha_bits : 0, /* color A */
+ 0, /* index bits */
+ DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16, /* accum RGB */
+ alpha_flag ? 16 : 0, /* accum A */
+ 1); /* num samples */
+
+ if (!visual) {
+ _mesa_free(c);
+ return NULL;
+ }
+
+ /* Set up driver functions */
+ _mesa_init_driver_functions(&functions);
+ functions.GetString = wmesa_get_string;
+ functions.UpdateState = wmesa_update_state;
+ functions.GetBufferSize = wmesa_get_buffer_size;
+ functions.Flush = wmesa_flush;
+ functions.Clear = clear;
+ functions.ClearIndex = clear_index;
+ functions.ClearColor = clear_color;
+ functions.ResizeBuffers = wmesa_resize_buffers;
+ functions.Viewport = wmesa_viewport;
+
+ /* initialize the Mesa context data */
+ ctx = &c->gl_ctx;
+ _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
+
+ /* visual no longer needed - it was copied by _mesa_initialize_context() */
+ _mesa_destroy_visual(visual);
+
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+ _mesa_enable_1_5_extensions(ctx);
+ _mesa_enable_2_0_extensions(ctx);
+ _mesa_enable_2_1_extensions(ctx);
+
+ /* Initialize the software rasterizer and helper modules. */
+ if (!_swrast_CreateContext(ctx) ||
+ !_vbo_CreateContext(ctx) ||
+ !_tnl_CreateContext(ctx) ||
+ !_swsetup_CreateContext(ctx)) {
+ _mesa_free_context_data(ctx);
+ _mesa_free(c);
+ return NULL;
+ }
+ _swsetup_Wakeup(ctx);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+
+ return c;
+}
+
+
+void WMesaDestroyContext( WMesaContext pwc )
+{
+ GLcontext *ctx = &pwc->gl_ctx;
+ WMesaFramebuffer pwfb;
+ GET_CURRENT_CONTEXT(cur_ctx);
+
+ if (cur_ctx == ctx) {
+ /* unbind current if deleting current context */
+ WMesaMakeCurrent(NULL, NULL);
+ }
+
+ /* clean up frame buffer resources */
+ pwfb = wmesa_lookup_framebuffer(pwc->hDC);
+ if (pwfb) {
+ if (ctx->Visual.doubleBufferMode == 1)
+ wmDeleteBackingStore(pwfb);
+ wmesa_free_framebuffer(pwc->hDC);
+ }
+
+ /* Release for device, not memory contexts */
+ if (WindowFromDC(pwc->hDC) != NULL)
+ {
+ ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
+ }
+ DeleteObject(pwc->clearPen);
+ DeleteObject(pwc->clearBrush);
+
+ _swsetup_DestroyContext(ctx);
+ _tnl_DestroyContext(ctx);
+ _vbo_DestroyContext(ctx);
+ _swrast_DestroyContext(ctx);
+
+ _mesa_free_context_data(ctx);
+ _mesa_free(pwc);
+}
+
+
+/**
+ * Create a new color renderbuffer.
+ */
+struct gl_renderbuffer *
+wmesa_new_renderbuffer(void)
+{
+ struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
+ if (!rb)
+ return NULL;
+
+ _mesa_init_renderbuffer(rb, (GLuint)0);
+
+ rb->_BaseFormat = GL_RGBA;
+ rb->InternalFormat = GL_RGBA;
+ rb->DataType = CHAN_TYPE;
+ rb->Delete = wmesa_delete_renderbuffer;
+ rb->AllocStorage = wmesa_renderbuffer_storage;
+ return rb;
+}
+
+
+void WMesaMakeCurrent(WMesaContext c, HDC hdc)
+{
+ WMesaFramebuffer pwfb;
+
+ {
+ /* return if already current */
+ GET_CURRENT_CONTEXT(ctx);
+ WMesaContext pwc = wmesa_context(ctx);
+ if (pwc && c == pwc && pwc->hDC == hdc)
+ return;
+ }
+
+ pwfb = wmesa_lookup_framebuffer(hdc);
+
+ /* Lazy creation of framebuffers */
+ if (c && !pwfb && hdc) {
+ struct gl_renderbuffer *rb;
+ GLvisual *visual = &c->gl_ctx.Visual;
+ GLuint width, height;
+
+ get_window_size(hdc, &width, &height);
+
+ c->clearPen = CreatePen(PS_SOLID, 1, 0);
+ c->clearBrush = CreateSolidBrush(0);
+
+ pwfb = wmesa_new_framebuffer(hdc, visual);
+
+ /* Create back buffer if double buffered */
+ if (visual->doubleBufferMode == 1) {
+ wmCreateBackingStore(pwfb, width, height);
+ }
+
+ /* make render buffers */
+ if (visual->doubleBufferMode == 1) {
+ rb = wmesa_new_renderbuffer();
+ _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
+ wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
+ }
+ rb = wmesa_new_renderbuffer();
+ _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
+ wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
+
+ /* Let Mesa own the Depth, Stencil, and Accum buffers */
+ _mesa_add_soft_renderbuffers(&pwfb->Base,
+ GL_FALSE, /* color */
+ visual->depthBits > 0,
+ visual->stencilBits > 0,
+ visual->accumRedBits > 0,
+ visual->alphaBits >0,
+ GL_FALSE);
+ }
+
+ if (c && pwfb)
+ _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
+ else
+ _mesa_make_current(NULL, NULL, NULL);
+}
+
+
+void WMesaSwapBuffers( HDC hdc )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ WMesaContext pwc = wmesa_context(ctx);
+ WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
+
+ if (!pwfb) {
+ _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
+ return;
+ }
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (pwc->hDC == hdc) {
+ _mesa_notifySwapBuffers(ctx);
+
+ BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
+ pwfb->dib_hDC, 0, 0, SRCCOPY);
+ }
+ else {
+ /* XXX for now only allow swapping current window */
+ _mesa_problem(NULL, "wmesa: can't swap non-current window");
+ }
+}
+
+void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
+{
+ _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
+}
+
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h b/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h
new file mode 100644
index 000000000..83a42e608
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesadef.h
@@ -0,0 +1,43 @@
+#ifndef WMESADEF_H
+#define WMESADEF_H
+#ifdef __MINGW32__
+#include <windows.h>
+#endif
+#include "context.h"
+
+
+/**
+ * The Windows Mesa rendering context, derived from GLcontext.
+ */
+struct wmesa_context {
+ GLcontext gl_ctx; /* The core GL/Mesa context */
+ HDC hDC;
+ COLORREF clearColorRef;
+ HPEN clearPen;
+ HBRUSH clearBrush;
+};
+
+
+/**
+ * Windows framebuffer, derived from gl_framebuffer
+ */
+struct wmesa_framebuffer
+{
+ struct gl_framebuffer Base;
+ HDC hDC;
+ int pixelformat;
+ GLuint ScanWidth;
+ BYTE cColorBits;
+ /* back buffer DIB fields */
+ HDC dib_hDC;
+ BITMAPINFO bmi;
+ HBITMAP hbmDIB;
+ HBITMAP hOldBitmap;
+ PBYTE pbPixels;
+ struct wmesa_framebuffer *next;
+};
+
+typedef struct wmesa_framebuffer *WMesaFramebuffer;
+
+
+#endif /* WMESADEF_H */
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/ddlog.c b/mesalib/src/mesa/drivers/windows/gldirect/ddlog.c
new file mode 100644
index 000000000..4ae79e2fd
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/ddlog.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#define STRICT
+#include <windows.h>
+
+#include "ddlog.h"
+#include "gld_driver.h"
+
+// ***********************************************************************
+
+static char ddlogbuf[256];
+static FILE* fpDDLog = NULL; // Log file pointer
+static char szDDLogName[_MAX_PATH] = {"gldirect.log"}; // Filename of the log
+static DDLOG_loggingMethodType ddlogLoggingMethod = DDLOG_NONE; // Default to No Logging
+static DDLOG_severityType ddlogDebugLevel;
+static BOOL bUIWarning = FALSE; // MessageBox warning ?
+
+// ***********************************************************************
+
+void ddlogOpen(
+ DDLOG_loggingMethodType LoggingMethod,
+ DDLOG_severityType Severity)
+{
+ if (fpDDLog != NULL) {
+ // Tried to re-open the log
+ ddlogMessage(DDLOG_WARN, "Tried to re-open the log file\n");
+ return;
+ }
+
+ ddlogLoggingMethod = LoggingMethod;
+ ddlogDebugLevel = Severity;
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fpDDLog = fopen(szDDLogName, "wt");
+ if (fpDDLog == NULL)
+ return;
+ }
+
+ ddlogMessage(DDLOG_SYSTEM, "\n");
+ ddlogMessage(DDLOG_SYSTEM, "-> Logging Started\n");
+}
+
+// ***********************************************************************
+
+void ddlogClose()
+{
+ // Determine whether the log is already closed
+ if (fpDDLog == NULL && ddlogLoggingMethod == DDLOG_NORMAL)
+ return; // Nothing to do.
+
+ ddlogMessage(DDLOG_SYSTEM, "<- Logging Ended\n");
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+}
+
+// ***********************************************************************
+
+void ddlogMessage(
+ DDLOG_severityType severity,
+ LPSTR message)
+{
+ char buf[256];
+
+ // Bail if logging is disabled
+ if (ddlogLoggingMethod == DDLOG_NONE)
+ return;
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF)
+ fpDDLog = fopen(szDDLogName, "at");
+
+ if (fpDDLog == NULL)
+ return;
+
+ if (severity >= ddlogDebugLevel) {
+ sprintf(buf, "DDLog: (%s) %s", ddlogSeverityMessages[severity], message);
+ fputs(buf, fpDDLog); // Write string to file
+ OutputDebugString(buf); // Echo to debugger
+ }
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF) {
+ fflush(fpDDLog); // Write info to disk
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+
+ // Popup message box if critical error
+ if (bUIWarning && severity == DDLOG_CRITICAL) {
+ MessageBox(NULL, buf, "GLDirect", MB_OK | MB_ICONWARNING | MB_TASKMODAL);
+ }
+}
+
+// ***********************************************************************
+
+// Write a string value to the log file
+void ddlogError(
+ DDLOG_severityType severity,
+ LPSTR message,
+ HRESULT hResult)
+{
+#ifdef _USE_GLD3_WGL
+ char dxErrStr[1024];
+ _gldDriver.GetDXErrorString(hResult, &dxErrStr[0], sizeof(dxErrStr));
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, dxErrStr);
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#else
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, DDErrorToString(hResult));
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#endif
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogPrintf(
+ DDLOG_severityType severity,
+ LPSTR message,
+ ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ vsprintf(ddlogbuf, message, args);
+ va_end(args);
+
+ lstrcat(ddlogbuf, "\n");
+
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogWarnOption(
+ BOOL bWarnOption)
+{
+ bUIWarning = bWarnOption;
+}
+
+// ***********************************************************************
+
+void ddlogPathOption(
+ LPSTR szPath)
+{
+ char szPathName[_MAX_PATH];
+
+ strcpy(szPathName, szPath);
+ strcat(szPathName, "\\");
+ strcat(szPathName, szDDLogName);
+ strcpy(szDDLogName, szPathName);
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/ddlog.h b/mesalib/src/mesa/drivers/windows/gldirect/ddlog.h
new file mode 100644
index 000000000..d64067e22
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/ddlog.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#ifndef __DDLOG_H
+#define __DDLOG_H
+
+#include <stdio.h>
+
+#ifndef _USE_GLD3_WGL
+#include "dderrstr.h" // ddraw/d3d error string
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DDLOG_NONE = 0, // No log output
+ DDLOG_NORMAL = 1, // Log is kept open
+ DDLOG_CRASHPROOF = 2, // Log is closed and flushed
+ DDLOG_METHOD_FORCE_DWORD = 0x7fffffff,
+} DDLOG_loggingMethodType;
+
+// Denotes type of message sent to the logging functions
+typedef enum {
+ DDLOG_INFO = 0, // Information only
+ DDLOG_WARN = 1, // Warning only
+ DDLOG_ERROR = 2, // Notify user of an error
+ DDLOG_CRITICAL = 3, // Exceptionally severe error
+ DDLOG_SYSTEM = 4, // System message. Not an error
+ // but must always be printed.
+ DDLOG_SEVERITY_FORCE_DWORD = 0x7fffffff, // Make enum dword
+} DDLOG_severityType;
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define GLDLOG_INFO DDLOG_INFO
+#define GLDLOG_WARN DDLOG_WARN
+#define GLDLOG_ERROR DDLOG_ERROR
+#define GLDLOG_CRITICAL DDLOG_CRITICAL
+#define GLDLOG_SYSTEM DDLOG_SYSTEM
+#endif
+
+// The message that will be output to the log
+static const char *ddlogSeverityMessages[] = {
+ "INFO",
+ "WARN",
+ "ERROR",
+ "*CRITICAL*",
+ "System",
+};
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ddlogOpen(DDLOG_loggingMethodType LoggingMethod, DDLOG_severityType Severity);
+void ddlogClose();
+void ddlogMessage(DDLOG_severityType severity, LPSTR message);
+void ddlogError(DDLOG_severityType severity, LPSTR message, HRESULT hResult);
+void ddlogPrintf(DDLOG_severityType severity, LPSTR message, ...);
+void ddlogWarnOption(BOOL bWarnOption);
+void ddlogPathOption(LPSTR szPath);
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define gldLogMessage ddlogMessage
+#define gldLogError ddlogError
+#define gldLogPrintf ddlogPrintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
new file mode 100644
index 000000000..e9c23d1cc
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -0,0 +1,2214 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Context handling.
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+
+// Get compile errors without this. KeithH
+//#include "scitech.h" // ibool, etc.
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+#endif // _USE_GLD3_WGL
+
+// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
+// if it is no longer being built as part of GLDirect. (DaveM)
+
+// ***********************************************************************
+
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+
+char szResourceWarning[] =
+"GLDirect does not have enough video memory resources\n"
+"to support the requested OpenGL rendering context.\n\n"
+"You may have to reduce the current display resolution\n"
+"to obtain satisfactory OpenGL performance.\n";
+
+char szDDrawWarning[] =
+"GLDirect is unable to initialize DirectDraw for the\n"
+"requested OpenGL rendering context.\n\n"
+"You will have to check the DirectX control panel\n"
+"for further information.\n";
+
+char szD3DWarning[] =
+"GLDirect is unable to initialize Direct3D for the\n"
+"requested OpenGL rendering context.\n\n"
+"You may have to change the display mode resolution\n"
+"color depth or check the DirectX control panel for\n"
+"further information.\n";
+
+char szBPPWarning[] =
+"GLDirect is unable to use the selected color depth for\n"
+"the requested OpenGL rendering context.\n\n"
+"You will have to change the display mode resolution\n"
+"color depth with the Display Settings control panel.\n";
+
+int nContextError = GLDERR_NONE;
+
+// ***********************************************************************
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+extern DWORD dwLogging;
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
+CRITICAL_SECTION CriticalSection; // for serialized access
+DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context
+DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format
+#endif
+HGLRC iCurrentContext = 0; // Index of current context (static)
+BOOL bContextReady = FALSE; // Context state ready ?
+
+DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list
+
+// ***********************************************************************
+
+static BOOL bHaveWin95 = FALSE;
+static BOOL bHaveWinNT = FALSE;
+static BOOL bHaveWin2K = FALSE;
+
+/****************************************************************************
+REMARKS:
+Detect the installed OS type.
+****************************************************************************/
+static void DetectOS(void)
+{
+ OSVERSIONINFO VersionInformation;
+ LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
+
+ VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
+
+ GetVersionEx(lpVersionInformation);
+
+ switch (VersionInformation.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ bHaveWin95 = TRUE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ bHaveWin95 = FALSE;
+ if (VersionInformation.dwMajorVersion <= 4) {
+ bHaveWinNT = TRUE;
+ bHaveWin2K = FALSE;
+ }
+ else {
+ bHaveWinNT = FALSE;
+ bHaveWin2K = TRUE;
+ }
+ break;
+ case VER_PLATFORM_WIN32s:
+ bHaveWin95 = FALSE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ }
+}
+
+// ***********************************************************************
+
+HWND hWndEvent = NULL; // event monitor window
+HWND hWndLastActive = NULL; // last active client window
+LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
+
+// ***********************************************************************
+
+// Checks if the HGLRC is valid in range of context list.
+BOOL dglIsValidContext(
+ HGLRC a)
+{
+ return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
+}
+
+// ***********************************************************************
+
+// Convert a HGLRC to a pointer into the context list.
+DGL_ctx* dglGetContextAddress(
+ const HGLRC a)
+{
+ if (dglIsValidContext(a))
+ return &ctxlist[(int)a-1];
+ return NULL;
+}
+
+// ***********************************************************************
+
+// Return the current HGLRC (however it may be stored for multi-threading).
+HGLRC dglGetCurrentContext(void)
+{
+#ifdef GLD_THREADS
+ HGLRC hGLRC;
+ // load from thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ hGLRC = iCurrentContext;
+ }
+ }
+ // load from global static var
+ else {
+ hGLRC = iCurrentContext;
+ }
+ return hGLRC;
+#else
+ return iCurrentContext;
+#endif
+}
+
+// ***********************************************************************
+
+// Set the current HGLRC (however it may be stored for multi-threading).
+void dglSetCurrentContext(HGLRC hGLRC)
+{
+#ifdef GLD_THREADS
+ // store in thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iCurrentContext = hGLRC;
+ }
+ }
+ // store in global static var
+ else {
+ iCurrentContext = hGLRC;
+ }
+#else
+ iCurrentContext = hGLRC;
+#endif
+}
+
+// ***********************************************************************
+
+// Return the current HDC only for a currently active HGLRC.
+HDC dglGetCurrentDC(void)
+{
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+
+ hGLRC = dglGetCurrentContext();
+ if (hGLRC) {
+ lpCtx = dglGetContextAddress(hGLRC);
+ return lpCtx->hDC;
+ }
+ return 0;
+}
+
+// ***********************************************************************
+
+void dglInitContextState()
+{
+ int i;
+ WNDCLASS wc;
+
+#ifdef GLD_THREADS
+ // Allocate thread local storage indexes for current context and pixel format
+ dwTLSCurrentContext = TlsAlloc();
+ dwTLSPixelFormat = TlsAlloc();
+#endif
+
+ dglSetCurrentContext(NULL); // No current rendering context
+
+ // Clear all context data
+ ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++)
+ ctxlist[i].bAllocated = FALSE; // Flag context as unused
+
+ // This section of code crashes the dll in circumstances where the app
+ // creates and destroys contexts.
+/*
+ // Register the class for our event monitor window
+ wc.style = 0;
+ wc.lpfnWndProc = GLD_EventWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "GLDIRECT";
+ RegisterClass(&wc);
+
+ // Create the non-visible window to monitor all broadcast messages
+ hWndEvent = CreateWindowEx(
+ WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
+ 0,0,0,0,
+ NULL,NULL,GetModuleHandle(NULL),NULL);
+*/
+
+#ifdef GLD_THREADS
+ // Create a critical section object for serializing access to
+ // DirectDraw and DDStereo create/destroy functions in multiple threads
+ if (glb.bMultiThreaded)
+ InitializeCriticalSection(&CriticalSection);
+#endif
+
+ // Context state is now initialized and ready
+ bContextReady = TRUE;
+}
+
+// ***********************************************************************
+
+void dglDeleteContextState()
+{
+ int i;
+ static BOOL bOnceIsEnough = FALSE;
+
+ // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
+ if (bOnceIsEnough)
+ return;
+ bOnceIsEnough = TRUE;
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated == TRUE) {
+ ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ }
+
+ // Context state is no longer ready
+ bContextReady = FALSE;
+
+ // If executed when DLL unloads, DDraw objects may be invalid.
+ // So catch any page faults with this exception handler.
+__try {
+
+ // Release final DirectDraw interfaces
+ if (glb.bDirectDrawPersistant) {
+// RELEASE(glb.lpGlobalPalette);
+// RELEASE(glb.lpDepth4);
+// RELEASE(glb.lpBack4);
+// RELEASE(glb.lpPrimary4);
+// RELEASE(glb.lpDD4);
+ }
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
+}
+
+ // Destroy our event monitor window
+ if (hWndEvent) {
+ DestroyWindow(hWndEvent);
+ hWndEvent = hWndLastActive = NULL;
+ }
+
+#ifdef GLD_THREADS
+ // Destroy the critical section object
+ if (glb.bMultiThreaded)
+ DeleteCriticalSection(&CriticalSection);
+
+ // Release thread local storage indexes for current HGLRC and pixel format
+ TlsFree(dwTLSPixelFormat);
+ TlsFree(dwTLSCurrentContext);
+#endif
+}
+
+// ***********************************************************************
+
+// Application Window message handler interception
+static LONG __stdcall dglWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DGL_ctx* lpCtx = NULL;
+ LONG lpfnWndProc = 0L;
+ int i;
+ HGLRC hGLRC;
+ RECT rect;
+ PAINTSTRUCT ps;
+ BOOL bQuit = FALSE;
+ BOOL bMain = FALSE;
+ LONG rc;
+
+ // Get the window's message handler *before* it is unhooked in WM_DESTROY
+
+ // Is this the main window?
+ if (hwnd == glb.hWndActive) {
+ bMain = TRUE;
+ lpfnWndProc = glb.lpfnWndProc;
+ }
+ // Search for DGL context matching window handle
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].hWnd == hwnd) {
+ lpCtx = &ctxlist[i];
+ lpfnWndProc = lpCtx->lpfnWndProc;
+ break;
+ }
+ }
+ // Not one of ours...
+ if (!lpfnWndProc)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ // Intercept messages amd process *before* passing on to window
+ switch (msg) {
+#ifdef _USE_GLD3_WGL
+ case WM_DISPLAYCHANGE:
+ glb.bPixelformatsDirty = TRUE;
+ break;
+#endif
+ case WM_ACTIVATEAPP:
+ glb.bAppActive = (BOOL)wParam;
+ ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
+ break;
+ case WM_ERASEBKGND:
+ // Eat the GDI erase event for the GL window
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ lpCtx->bGDIEraseBkgnd = TRUE;
+ return TRUE;
+ case WM_PAINT:
+ // Eat the invalidated update region if render scene is in progress
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ if (lpCtx->bFrameStarted) {
+ if (GetUpdateRect(hwnd, &rect, FALSE)) {
+ BeginPaint(hwnd, &ps);
+ EndPaint(hwnd, &ps);
+ ValidateRect(hwnd, &rect);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ // Call the appropriate window message handler
+ rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
+
+ // Intercept messages and process *after* passing on to window
+ switch (msg) {
+ case WM_QUIT:
+ case WM_DESTROY:
+ bQuit = TRUE;
+ if (lpCtx && lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ break;
+#if 0
+ case WM_SIZE:
+ // Resize surfaces to fit window but not viewport (in case app did not bother)
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ w = LOWORD(lParam);
+ h = HIWORD(lParam);
+ if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
+ if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
+ dglWglResizeBuffers(lpCtx->glCtx, FALSE);
+ }
+ break;
+#endif
+ }
+
+ // If the main window is quitting, then so should we...
+ if (bMain && bQuit) {
+ ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
+ dglDeleteContextState();
+ dglExitDriver();
+ }
+
+ return rc;
+}
+
+// ***********************************************************************
+
+// Driver Window message handler
+static LONG __stdcall GLD_EventWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (msg) {
+ // May be sent by splash screen dialog on exit
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
+ SetForegroundWindow(glb.hWndActive);
+ return 0;
+ }
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+// ***********************************************************************
+
+// Intercepted Keyboard handler for detecting hot keys.
+LRESULT CALLBACK dglKeyProc(
+ int code,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hWnd, hWndFrame;
+ HGLRC hGLRC = NULL;
+ DGL_ctx* lpCtx = NULL;
+ int cmd = 0, dx1 = 0, dx2 = 0, i;
+ static BOOL bAltPressed = FALSE;
+ static BOOL bCtrlPressed = FALSE;
+ static BOOL bShiftPressed = FALSE;
+ RECT r, rf, rc;
+ POINT pt;
+ BOOL bForceReshape = FALSE;
+
+ return CallNextHookEx(hKeyHook, code, wParam, lParam);
+}
+
+// ***********************************************************************
+
+HWND hWndMatch;
+
+// Window handle enumeration procedure.
+BOOL CALLBACK dglEnumChildProc(
+ HWND hWnd,
+ LPARAM lParam)
+{
+ RECT rect;
+
+ // Find window handle with matching client rect.
+ GetClientRect(hWnd, &rect);
+ if (EqualRect(&rect, (RECT*)lParam)) {
+ hWndMatch = hWnd;
+ return FALSE;
+ }
+ // Continue with next child window.
+ return TRUE;
+}
+
+// ***********************************************************************
+
+// Find window handle with matching client rect.
+HWND dglFindWindowRect(
+ RECT* pRect)
+{
+ hWndMatch = NULL;
+ EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
+ return hWndMatch;
+}
+
+// ***********************************************************************
+#ifndef _USE_GLD3_WGL
+void dglChooseDisplayMode(
+ DGL_ctx *lpCtx)
+{
+ // Note: Choose an exact match if possible.
+
+ int i;
+ DWORD area;
+ DWORD bestarea;
+ DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer
+ DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best
+
+ lpDDSD = glb.lpDisplayModes;
+ for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
+ if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight == lpCtx->dwHeight))
+ goto matched; // Mode has been exactly matched
+ // Choose modes that are larger in both dimensions than
+ // the window, but smaller in area than the current best.
+ if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight >= lpCtx->dwHeight))
+ {
+ if (lpBestDDSD == NULL) {
+ lpBestDDSD = lpDDSD;
+ bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ continue;
+ }
+ area = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ if (area < bestarea) {
+ lpBestDDSD = lpDDSD;
+ bestarea = area;
+ }
+ }
+ }
+
+ // Safety check
+ if (lpBestDDSD == NULL) {
+ ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
+ return;
+ }
+
+ lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
+ lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
+matched:
+ ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
+ lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
+}
+#endif // _USE_GLD3_WGL
+// ***********************************************************************
+
+static BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+void dglTestForBrokenCards(
+ DGL_ctx *lpCtx)
+{
+#ifndef _GLD3
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+
+ // Sanity check.
+ if (lpCtx == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
+ return;
+ }
+
+ if (lpCtx->lpDD4 == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
+ return;
+ }
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
+ return;
+
+ // Useful info. Log it.
+ ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
+
+ // Vendor 1: ATI
+ if (dddi.dwVendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
+ glb.bUseMipmaps = FALSE;
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
+ glb.bEmulateAlphaTest = TRUE;
+ }
+
+ // Vendor 2: Matrox
+ if (dddi.dwVendorId == 0x102B) {
+ // Test: Matrox G400 stencil buffer support does not work for AutoCAD
+ if (dddi.dwDeviceId == 0x0525) {
+ lpCtx->lpPF->pfd.cStencilBits = 0;
+ if (lpCtx->lpPF->iZBufferPF != -1) {
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
+ }
+ }
+ }
+#endif // _GLD3
+}
+
+// ***********************************************************************
+
+BOOL dglCreateContextBuffers(
+ HDC a,
+ DGL_ctx *lpCtx,
+ BOOL bFallback)
+{
+ HRESULT hResult;
+
+ int i;
+// HGLRC hGLRC;
+// DGL_ctx* lpCtx;
+
+#ifndef _USE_GLD3_WGL
+ DWORD dwFlags;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description
+ D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer
+#endif // _USE_GLD3_WGL
+
+ float inv_aspect;
+
+ GLenum bDoubleBuffer; // TRUE if double buffer required
+ GLenum bDepthBuffer; // TRUE if depth buffer required
+
+ const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd;
+
+ // Vars for Mesa visual
+ DWORD dwDepthBits = 0;
+ DWORD dwStencilBits = 0;
+ DWORD dwAlphaBits = 0;
+ DWORD bAlphaSW = GL_FALSE;
+ DWORD bDouble = GL_FALSE;
+
+ DDSURFACEDESC2 ddsd2DisplayMode;
+ BOOL bFullScrnWin = FALSE; // fullscreen-size window ?
+ DDBLTFX ddbltfx;
+ DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
+ BOOL bBogusWindow = FALSE; // non-drawable window ?
+ DWORD dwColorRef = 0; // GDI background color
+ RECT rcDst; // GDI window rect
+ POINT pt; // GDI window point
+
+ // Palette used for creating default global palette
+ PALETTEENTRY ppe[256];
+
+#ifndef _USE_GLD3_WGL
+ // Vertex buffer description. Used for creation of vertex buffers
+ D3DVERTEXBUFFERDESC vbufdesc;
+#endif // _USE_GLD3_WGL
+
+#define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
+ nContextError = GLDERR_NONE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw object creation or DDS start
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check for back buffer
+ bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+ // Since we always do back buffering, check if we emulate front buffering
+ lpCtx->EmulateSingle =
+ (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+#if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
+ lpCtx->EmulateSingle |=
+ (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
+#endif
+
+ // Check for depth buffer
+ bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
+
+ lpCtx->bDoubleBuffer = bDoubleBuffer;
+ lpCtx->bDepthBuffer = bDepthBuffer;
+
+ // Set the Fullscreen flag for the context.
+// lpCtx->bFullscreen = glb.bFullscreen;
+
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
+ // Check for non-window DC = memory DC ?
+ if (lpCtx->hWnd == NULL) {
+ // bitmap memory contexts are always single-buffered
+ lpCtx->EmulateSingle = TRUE;
+ bBogusWindow = TRUE;
+ ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
+ if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ bBogusWindow = TRUE;
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
+ lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
+
+ ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
+ lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // What if app only zeroes one dimension instead of both? (DaveM)
+ if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
+ // Make the buffer size something sensible
+ lpCtx->dwWidth = 8;
+ lpCtx->dwHeight = 8;
+ }
+
+ // Set defaults
+ lpCtx->dwModeWidth = lpCtx->dwWidth;
+ lpCtx->dwModeHeight = lpCtx->dwHeight;
+/*
+ // Find best display mode for fullscreen
+ if (glb.bFullscreen || !glb.bPrimary) {
+ dglChooseDisplayMode(lpCtx);
+ }
+*/
+ // Misc initialisation
+ lpCtx->bCanRender = FALSE; // No rendering allowed yet
+ lpCtx->bSceneStarted = FALSE;
+ lpCtx->bFrameStarted = FALSE;
+
+ // Detect OS (specifically 'Windows 2000' or 'Windows XP')
+ DetectOS();
+
+ // NOTE: WinNT not supported
+ ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
+
+ // Test for Fullscreen
+ if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
+ if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
+ (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
+ {
+ // Workaround for some apps that crash when going fullscreen.
+ //lpCtx->bFullscreen = TRUE;
+ }
+
+ }
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
+#else
+ // Check if DirectDraw has already been created by original GLRC (DaveM)
+ if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
+ lpCtx->lpDD4 = glb.lpDD4;
+ IDirectDraw4_AddRef(lpCtx->lpDD4);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create DirectDraw object
+ if (glb.bPrimary)
+ hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
+ else {
+ // A non-primary device is to be used.
+ // Force context to be Fullscreen, secondary adaptors can not
+ // be used in a window.
+ hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
+ lpCtx->bFullscreen = TRUE;
+ }
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpCtx->lpDD4);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Cache DirectDraw interface for subsequent GLRCs
+ if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
+ glb.lpDD4 = lpCtx->lpDD4;
+ IDirectDraw4_AddRef(glb.lpDD4);
+ glb.bDirectDraw = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Now we have a DD4 interface we can check for broken cards
+ dglTestForBrokenCards(lpCtx);
+
+ // Test if primary device can use flipping instead of blitting
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ lpCtx->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ // We have a fullscreen-size window
+ bFullScrnWin = TRUE;
+ // OK to use DirectDraw fullscreen mode ?
+ if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
+ lpCtx->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
+ }
+ }
+ // Cache the display mode dimensions
+ lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
+ lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
+ lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
+
+ // Check for non-RGB desktop resolution
+ if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
+ ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
+ ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
+ nContextError = GLDERR_BPP;
+ goto return_with_error;
+ }
+#endif // _USE_GLD3_WGL
+
+ ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
+ lpCtx->dwWidth,
+ lpCtx->dwHeight,
+ lpCtx->bFullscreen ? "fullscreen" : "windowed");
+
+#ifndef _USE_GLD3_WGL
+ // Obtain ddraw caps
+ ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
+ lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
+ if (glb.bHardware) {
+ // Get HAL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
+ } else {
+ // Get HEL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
+ }
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_INFO,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ // Query for DX6 Direct3D3 interface
+ hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpCtx->lpD3D3);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Context creation
+ if (lpCtx->bFullscreen) {
+ // FULLSCREEN
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release persistant primary surface if fullscreen mode
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
+ lpCtx->dwModeWidth,
+ lpCtx->dwModeHeight,
+ lpPFD->cColorBits,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
+ goto return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ lpCtx->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
+ lpCtx->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
+ goto return_with_error;
+ }
+ // Has Primary surface already been created for original GLRC ?
+ // Note this can only be applicable for windowed modes
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ lpCtx->lpFront4 = glb.lpPrimary4;
+ IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
+ // Update the window on the default clipper
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+ goto SkipPrimaryCreate;
+ }
+
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Cache Primary surface for subsequent GLRCs
+ // Note this can only be applicable to subsequent windowed modes
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = lpCtx->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
+ goto return_with_error;
+ }
+SkipPrimaryCreate:
+
+ if (bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+ // Re-use original back buffer if persistant buffers exist
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
+ IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
+ } else {
+ lpCtx->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Z-buffer
+ //
+ lpCtx->bStencil = FALSE; // Default to no stencil buffer
+ if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Create a z-buffer
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
+ IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
+ else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ lpCtx->lpDepth4),
+ "dglCreateContext: Attach Zbuffer");
+ if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
+ lpCtx->bStencil = TRUE;
+ ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
+ }
+ }
+
+ // Clear all back buffers and Z-buffers in case of memory recycling.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+ if (lpCtx->lpDepth4)
+ IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+
+ // Now that we have a Z-buffer we can create the 3D device
+ hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
+ &glb.d3dGuid,
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ &lpCtx->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(lpCtx);
+
+ // Obtain the D3D Device Description
+ D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
+ TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
+ &D3DHWDevDesc,
+ &D3DHELDevDesc),
+ "dglCreateContext: GetCaps failed");
+
+ // Choose the relevant description and cache it in the context.
+ // We will use this description later for caps checking
+ memcpy( &lpCtx->D3DDevDesc,
+ glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
+ sizeof(D3DDEVICEDESC));
+
+ // Now we can examine the texture formats
+ if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
+ goto return_with_error;
+ }
+
+ // Get the pixel format of the back buffer
+ lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
+ if (bDoubleBuffer)
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpBack4,
+ &lpCtx->ddpfRender);
+ else
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpFront4,
+ &lpCtx->ddpfRender);
+
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
+ goto return_with_error;
+ }
+ // Find a pixel packing function suitable for this surface
+ pxClassifyPixelFormat(&lpCtx->ddpfRender,
+ &lpCtx->fnPackFunc,
+ &lpCtx->fnUnpackFunc,
+ &lpCtx->fnPackSpanFunc);
+
+ // Viewport
+ hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ // Initialise the viewport
+ // Note screen coordinates are used for viewport clipping since D3D
+ // transform operations are not used in the GLD CAD driver. (DaveM)
+ inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
+
+ lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
+ lpCtx->d3dViewport.dwX = 0;
+ lpCtx->d3dViewport.dwY = 0;
+ lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
+ lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
+ lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
+ lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
+ lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
+ lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
+ lpCtx->d3dViewport.dvMinZ = 0.0f;
+ lpCtx->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ lpCtx->dwBPP = lpPFD->cColorBits;
+ lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
+
+ // Set last texture to NULL
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ lpCtx->ColorOp[i] = D3DTOP_DISABLE;
+ lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
+ lpCtx->tObj[i] = NULL;
+ }
+
+ // Default to perspective correct texture mapping
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
+
+ // Set the default culling mode
+ lpCtx->cullmode = D3DCULL_NONE;
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
+
+ // Disable specular
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
+ // Disable subpixel correction
+// dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
+ // Disable dithering
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
+
+ // Initialise the primitive caches
+// lpCtx->dwNextLineVert = 0;
+// lpCtx->dwNextTriVert = 0;
+
+ // Init the global texture palette
+ lpCtx->lpGlobalPalette = NULL;
+
+ // Init the HW/SW usage counters
+// lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
+
+ //
+ // Create two D3D vertex buffers.
+ // One will hold the pre-transformed data with the other one
+ // being used to hold the post-transformed & clipped verts.
+ //
+#if 0 // never used (DaveM)
+ vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
+ vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+ if (glb.bHardware == FALSE)
+ vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vbufdesc.dwNumVertices = 32768; // For the time being
+
+ // Source vertex buffer
+ vbufdesc.dwFVF = DGL_LVERTEX;
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
+ goto return_with_error;
+ }
+
+ // Destination vertex buffer
+ vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
+ if(FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
+ goto return_with_error;
+ }
+#endif
+
+#endif _USE_GLD3_WGL
+
+ //
+ // Now create the Mesa context
+ //
+
+ // Create the Mesa visual
+ if (lpPFD->cDepthBits)
+ dwDepthBits = 16;
+ if (lpPFD->cStencilBits)
+ dwStencilBits = 8;
+ if (lpPFD->cAlphaBits) {
+ dwAlphaBits = 8;
+ bAlphaSW = GL_TRUE;
+ }
+ if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
+ bDouble = GL_TRUE;
+// lpCtx->EmulateSingle =
+// (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glVis = _mesa_create_visual(
+ GL_TRUE, // RGB mode
+ bDouble, /* double buffer */
+ GL_FALSE, // stereo
+ lpPFD->cRedBits,
+ lpPFD->cGreenBits,
+ lpPFD->cBlueBits,
+ dwAlphaBits,
+ 0, // index bits
+ dwDepthBits,
+ dwStencilBits,
+ lpPFD->cAccumRedBits, // accum bits
+ lpPFD->cAccumGreenBits, // accum bits
+ lpPFD->cAccumBlueBits, // accum bits
+ lpPFD->cAccumAlphaBits, // accum alpha bits
+ 1 // num samples
+ );
+#else // _USE_GLD3_WGL
+ lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
+ GL_TRUE, // RGB mode
+ bAlphaSW, // Is an alpha buffer required?
+ bDouble, // Is an double-buffering required?
+ GL_FALSE, // stereo
+ dwDepthBits, // depth_size
+ dwStencilBits, // stencil_size
+ lpPFD->cAccumBits, // accum_size
+ 0, // colour-index bits
+ lpPFD->cRedBits, // Red bit count
+ lpPFD->cGreenBits, // Green bit count
+ lpPFD->cBlueBits, // Blue bit count
+ dwAlphaBits // Alpha bit count
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glVis == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+#else
+ // Create the Mesa context
+ lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
+ lpCtx->glVis, // Mesa visual
+ NULL, // share list context
+ (void *)lpCtx, // Pointer to our driver context
+ GL_TRUE // Direct context flag
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glCtx == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
+ goto return_with_error;
+ }
+
+ // Create the Mesa framebuffer
+#ifdef _USE_GLD3_WGL
+ lpCtx->glBuffer = _mesa_create_framebuffer(
+ lpCtx->glVis,
+ lpCtx->glVis->depthBits > 0,
+ lpCtx->glVis->stencilBits > 0,
+ lpCtx->glVis->accumRedBits > 0,
+ GL_FALSE //swalpha
+ );
+#else
+ lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glBuffer == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Init Mesa internals
+ _swrast_CreateContext( lpCtx->glCtx );
+ _vbo_CreateContext( lpCtx->glCtx );
+ _tnl_CreateContext( lpCtx->glCtx );
+ _swsetup_CreateContext( lpCtx->glCtx );
+
+ _gldDriver.InitialiseMesa(lpCtx);
+
+ lpCtx->glCtx->imports.warning = _gld_mesa_warning;
+ lpCtx->glCtx->imports.fatal = _gld_mesa_fatal;
+
+#else
+ // Tell Mesa how many texture stages we have
+ glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
+ // Only use as many Units as the spec requires
+ if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
+ glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
+ lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
+ ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures);
+
+ // Set the max texture size.
+ // NOTE: clamped to a max of 1024 for extra performance!
+ lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
+
+// Texture resize takes place elsewhere. KH
+// NOTE: This was added to workaround an issue with the Intel app.
+#if 0
+ lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
+#else
+ lpCtx->glCtx->Const.MaxTextureSize = 1024;
+#endif
+ lpCtx->glCtx->Const.MaxDrawBuffers = 1;
+
+ // Setup the Display Driver pointers
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Initialise all the Direct3D renderstates
+ dglInitStateD3D(lpCtx->glCtx);
+
+#if 0
+ // Signal a reload of texture state on next glBegin
+ lpCtx->m_texHandleValid = FALSE;
+ lpCtx->m_mtex = FALSE;
+ lpCtx->m_texturing = FALSE;
+#else
+ // Set default texture unit state
+// dglSetTexture(lpCtx, 0, NULL);
+// dglSetTexture(lpCtx, 1, NULL);
+#endif
+
+ //
+ // Set the global texture palette to default values.
+ //
+
+ // Clear the entire palette
+ ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
+
+ // Fill the palette with a default colour.
+ // A garish colour is used to catch bugs. Here Magenta is used.
+ for (i=0; i < 256; i++) {
+ ppe[i].peRed = 255;
+ ppe[i].peGreen = 0;
+ ppe[i].peBlue = 255;
+ }
+
+ RELEASE(lpCtx->lpGlobalPalette);
+
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
+ hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
+ else
+ hResult = IDirectDraw4_CreatePalette(
+ lpCtx->lpDD4,
+ DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ ppe,
+ &(lpCtx->lpGlobalPalette),
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
+ lpCtx->lpGlobalPalette = NULL;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
+ IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
+
+#endif // _USE_GLD3_WGL
+
+ // ** If we have made it to here then we can enable rendering **
+ lpCtx->bCanRender = TRUE;
+
+// ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+
+return_with_error:
+ // Clean up before returning.
+ // This is critical for secondary devices.
+
+ lpCtx->bCanRender = FALSE;
+
+#ifdef _USE_GLD3_WGL
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ // Destroy driver data
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
+ RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
+
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ RELEASE(lpCtx->lpBack4);
+ RELEASE(lpCtx->lpFront4);
+ else
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ RELEASE(lpCtx->lpD3D3);
+ RELEASE(lpCtx->lpDD4);
+ RELEASE(lpCtx->lpDD1);
+#endif // _USE_GLD3_WGL
+
+ lpCtx->bAllocated = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+
+#undef DDLOG_CRITICAL_OR_WARN
+}
+
+// ***********************************************************************
+
+HGLRC dglCreateContext(
+ HDC a,
+ const DGL_pixelFormat *lpPF)
+{
+ int i;
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+ static BOOL bWarnOnce = TRUE;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char szMsg[256];
+ HWND hWnd;
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return NULL;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
+
+ // Find next free context.
+ // Also ensure that only one Fullscreen context is created at any one time.
+ hGLRC = 0; // Default to Not Found
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated) {
+ if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
+ break;
+ } else {
+ hGLRC = (HGLRC)(i+1);
+ break;
+ }
+ }
+
+ // Bail if no GLRC was found
+ if (!hGLRC)
+ return NULL;
+
+ // Set the context pointer
+ lpCtx = dglGetContextAddress(hGLRC);
+ // Make sure that context is zeroed before we do anything.
+ // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
+ // even though only one context is ever used by the app, so keep it clean. (DaveM)
+ ZeroMemory(lpCtx, sizeof(DGL_ctx));
+ lpCtx->bAllocated = TRUE;
+ // Flag that buffers need creating on next wglMakeCurrent call.
+ lpCtx->bHasBeenCurrent = FALSE;
+ lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
+ lpCtx->bCanRender = FALSE;
+
+ // Create all the internal resources here, not in dglMakeCurrent().
+ // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
+ // We now try context allocations twice, first with video memory,
+ // then again with system memory. This is similar to technique
+ // used for dglWglResizeBuffers(). (DaveM)
+ if (lpCtx->bHasBeenCurrent == FALSE) {
+ if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
+ if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
+ bWarnOnce = FALSE;
+ switch (nContextError) {
+ case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
+ case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
+ case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
+ case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
+ default: strcpy(szMsg, "");
+ }
+ if (strlen(szMsg))
+ MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ // Only need to try again if memory error
+ if (nContextError == GLDERR_MEM) {
+ ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
+ }
+ else {
+ ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
+ return NULL;
+ }
+ }
+ }
+
+ // Now that we have a hWnd, we can intercept the WindowProc.
+ hWnd = lpCtx->hWnd;
+ if (hWnd) {
+ // Only hook individual window handler once if not hooked before.
+ lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
+ if (lpfnWndProc != (LONG)dglWndProc) {
+ lpCtx->lpfnWndProc = lpfnWndProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ // Find the parent window of the app too.
+ if (glb.hWndActive == NULL) {
+ while (hWnd != NULL) {
+ glb.hWndActive = hWnd;
+ hWnd = GetParent(hWnd);
+ }
+ // Hook the parent window too.
+ lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
+ if (glb.hWndActive == lpCtx->hWnd)
+ glb.lpfnWndProc = lpCtx->lpfnWndProc;
+ else if (lpfnWndProc != (LONG)dglWndProc)
+ glb.lpfnWndProc = lpfnWndProc;
+ if (glb.lpfnWndProc)
+ SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
+
+ return hGLRC;
+}
+
+// ***********************************************************************
+// Make a DirectGL context current
+// Used by wgl functions and dgl functions
+BOOL dglMakeCurrent(
+ HDC a,
+ HGLRC b)
+{
+ int context;
+ DGL_ctx* lpCtx;
+ HWND hWnd;
+ BOOL bNeedResize = FALSE;
+ BOOL bWindowChanged, bContextChanged;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ DWORD dwThreadId = GetCurrentThreadId();
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ context = (int)b; // This is as a result of STRICT!
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
+
+ // If the HGLRC is NULL then make no context current;
+ // Ditto if the HDC is NULL either. (DaveM)
+ if (context == 0 || a == 0) {
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(NULL, NULL);
+#else
+ (*mesaFuncs.gl_make_current)(NULL, NULL);
+#endif
+ dglSetCurrentContext(0);
+ return TRUE;
+ }
+
+ // Make sure the HGLRC is in range
+ if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Find address of context and make sure that it has been allocated
+ lpCtx = dglGetContextAddress(b);
+ if (!lpCtx->bAllocated) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check if window has changed
+ hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
+ bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
+ bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
+
+ // If the window has changed, make sure the clipper is updated. (DaveM)
+ if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
+ lpCtx->hWnd = hWnd;
+#ifndef _USE_GLD3_WGL
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+#endif // _USE_GLD3_WGL
+ }
+
+ // Make sure hDC and hWnd is current. (DaveM)
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = hWnd;
+ hWndLastActive = hWnd;
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ // Check if buffers need to be re-sized;
+ // If so, wait until Mesa GL stuff is setup before re-sizing;
+ if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
+ lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
+ bNeedResize = TRUE;
+
+ // Now we can update our globals
+ dglSetCurrentContext(b);
+
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#else
+ (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
+
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Insure DirectDraw surfaces fit current window DC
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#endif // _USE_GLD3_WGL
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // We have to clear D3D back buffer and render state if emulated front buffering
+ // for different window (but not context) like in Solid Edge.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
+ && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
+#ifdef _USE_GLD3_WGL
+// IDirect3DDevice8_EndScene(lpCtx->pDev);
+// lpCtx->bSceneStarted = FALSE;
+ lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ }
+
+ // The first time we call MakeCurrent we set the initial viewport size
+ if (lpCtx->bHasBeenCurrent == FALSE)
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ lpCtx->bHasBeenCurrent = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglDeleteContext(
+ HGLRC a)
+{
+ DGL_ctx* lpCtx;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char argstr[256];
+
+#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
+
+ // Make sure the HGLRC is in range
+ if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Make sure context is valid
+ lpCtx = dglGetContextAddress(a);
+ if (!lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+ // Make sure context is de-activated
+ if (a == dglGetCurrentContext()) {
+ ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
+ dglMakeCurrent(NULL, NULL);
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // We are about to destroy all Direct3D objects.
+ // Therefore we must disable rendering
+ lpCtx->bCanRender = FALSE;
+
+ // This exception handler was installed to catch some
+ // particularly nasty apps. Console apps that call exit()
+ // fall into this catagory (i.e. Win32 Glut).
+
+ // VC cannot successfully implement multiple exception handlers
+ // if more than one exception occurs. Therefore reverting back to
+ // single exception handler as Keith originally had it. (DaveM)
+
+#define WARN_MESSAGE(p) strcpy(argstr, (#p));
+#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
+
+__try {
+#ifdef _USE_GLD3_WGL
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
+ SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
+
+ // Delete the global palette
+ SAFE_RELEASE(lpCtx->lpGlobalPalette);
+
+ // Clean up.
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ SAFE_RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ SAFE_RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ SAFE_RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ SAFE_RELEASE(lpCtx->lpBack4);
+ SAFE_RELEASE(lpCtx->lpFront4);
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ SAFE_RELEASE(lpCtx->lpD3D3);
+ SAFE_RELEASE(lpCtx->lpDD4);
+ SAFE_RELEASE(lpCtx->lpDD1);
+#endif // _ULSE_GLD3_WGL
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
+}
+
+ // Restore the window message handler because this context may be used
+ // again by another window with a *different* message handler. (DaveM)
+ if (lpCtx->lpfnWndProc) {
+ SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
+ lpCtx->lpfnWndProc = (LONG)NULL;
+ }
+
+ lpCtx->bAllocated = FALSE; // This context is now free for use
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglSwapBuffers(
+ HDC hDC)
+{
+ RECT rSrcRect; // Source rectangle
+ RECT rDstRect; // Destination rectangle
+ POINT pt;
+ HRESULT hResult;
+
+ DDBLTFX bltFX;
+ DWORD dwBlitFlags;
+ DDBLTFX *lpBltFX;
+
+// DWORD dwThreadId = GetCurrentThreadId();
+ HGLRC hGLRC = dglGetCurrentContext();
+ DGL_ctx *lpCtx = dglGetContextAddress(hGLRC);
+ HWND hWnd;
+
+ HDC hDCAux; // for memory DC
+ int x,y,w,h; // for memory DC BitBlt
+
+#if 0 // Perhaps not a good idea. Called too often. KH
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ if (!lpCtx) {
+ return TRUE; //FALSE; // No current context
+ }
+
+ if (!lpCtx->bCanRender) {
+ // Don't return false else some apps will bail.
+ return TRUE;
+ }
+
+ hWnd = lpCtx->hWnd;
+ if (hDC != lpCtx->hDC) {
+ ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
+ hWnd = WindowFromDC(hDC);
+ }
+
+#ifndef _USE_GLD3_WGL
+ // Ensure that the surfaces exist before we tell
+ // the device to render to them.
+ IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
+
+ // Make sure that the vertex caches have been emptied
+// dglStateChange(lpCtx);
+
+ // Some OpenGL programs don't issue a glFinish - check for it here.
+ if (lpCtx->bSceneStarted) {
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ }
+#endif
+
+#if 0
+ // If the calling app is not active then we don't need to Blit/Flip.
+ // We can therefore simply return TRUE.
+ if (!glb.bAppActive)
+ return TRUE;
+ // Addendum: This is WRONG! We should bail if the app is *minimized*,
+ // not merely if the app is just plain 'not active'.
+ // KeithH, 27/May/2000.
+#endif
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(hDC, &rSrcRect) == ERROR)
+ return TRUE;
+ // Use GDI BitBlt instead from compatible DirectDraw DC
+ x = rSrcRect.left;
+ y = rSrcRect.top;
+ w = rSrcRect.right - rSrcRect.left;
+ h = rSrcRect.bottom - rSrcRect.top;
+
+ // Ack. DX8 does not have a GetDC() function...
+ // TODO: Defer to DX7 or DX9 drivers... (DaveM)
+ return TRUE;
+ }
+
+ // Bail if window client region is not drawable, like in Solid Edge
+ if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
+ return TRUE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifdef _USE_GLD3_WGL
+ // Notify Mesa of impending swap, so Mesa can flush internal buffers.
+ _mesa_notifySwapBuffers(lpCtx->glCtx);
+ // Now perform driver buffer swap
+ _gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
+#else
+ if (lpCtx->bFullscreen) {
+ // Sync with retrace if required
+ if (glb.bWaitForRetrace) {
+ IDirectDraw4_WaitForVerticalBlank(
+ lpCtx->lpDD4,
+ DDWAITVB_BLOCKBEGIN,
+ 0);
+ }
+
+ // Perform the fullscreen flip
+ TRY(IDirectDrawSurface4_Flip(
+ lpCtx->lpFront4,
+ NULL,
+ DDFLIP_WAIT),
+ "dglSwapBuffers: Flip");
+ } else {
+ // Calculate current window position and size
+ pt.x = pt.y = 0;
+ ClientToScreen(hWnd, &pt);
+ GetClientRect(hWnd, &rDstRect);
+ if (rDstRect.right > lpCtx->dwModeWidth)
+ rDstRect.right = lpCtx->dwModeWidth;
+ if (rDstRect.bottom > lpCtx->dwModeHeight)
+ rDstRect.bottom = lpCtx->dwModeHeight;
+ OffsetRect(&rDstRect, pt.x, pt.y);
+ rSrcRect.left = rSrcRect.top = 0;
+ rSrcRect.right = lpCtx->dwWidth;
+ rSrcRect.bottom = lpCtx->dwHeight;
+ if (rSrcRect.right > lpCtx->dwModeWidth)
+ rSrcRect.right = lpCtx->dwModeWidth;
+ if (rSrcRect.bottom > lpCtx->dwModeHeight)
+ rSrcRect.bottom = lpCtx->dwModeHeight;
+
+ if (glb.bWaitForRetrace) {
+ // Sync the blit to the vertical retrace
+ ZeroMemory(&bltFX, sizeof(bltFX));
+ bltFX.dwSize = sizeof(bltFX);
+ bltFX.dwDDFX = DDBLTFX_NOTEARING;
+ dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
+ lpBltFX = &bltFX;
+ } else {
+ dwBlitFlags = DDBLT_WAIT;
+ lpBltFX = NULL;
+ }
+
+ // Perform the actual blit
+ TRY(IDirectDrawSurface4_Blt(
+ lpCtx->lpFront4,
+ &rDstRect,
+ lpCtx->lpBack4, // Blit source
+ &rSrcRect,
+ dwBlitFlags,
+ lpBltFX),
+ "dglSwapBuffers: Blt");
+ }
+#endif // _USE_GLD3_WGL
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
+
+ // Render frame is completed
+ ValidateRect(hWnd, NULL);
+ lpCtx->bFrameStarted = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h
new file mode 100644
index 000000000..5c433b857
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglcontext.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL context handling.
+*
+****************************************************************************/
+
+#ifndef __DGLCONTEXT_H
+#define __DGLCONTEXT_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <GL\gl.h>
+
+#ifdef _USE_GLD3_WGL
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "context.h" // Mesa context
+#else
+ #include <ddraw.h>
+ #include <d3d.h>
+
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "d3dvertex.h"
+
+ #include "DirectGL.h"
+
+ #include "context.h" // Mesa context
+ #include "vb.h" // Mesa vertex buffer
+#endif // _USE_GLD3_WGL
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+// TODO: Use a list instead of this constant!
+#define DGL_MAX_CONTEXTS 32
+
+// Structure for describing an OpenGL context
+#ifdef _USE_GLD3_WGL
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+
+ // Pointer to private driver data (this also contains the drawable).
+ void *glPriv;
+
+ // Mesa vars:
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+
+ // Shared driver vars:
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+ BOOL bStencil; // TRUE if this context has stencil
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+} DGL_ctx;
+
+#define GLD_context DGL_ctx
+#define GLD_GET_CONTEXT(c) (GLD_context*)(c)->DriverCtx
+
+#else // _USE_GLD3_WGL
+
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+ //
+ // Mesa context vars:
+ //
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+ int iZBufferPF; // Index of Zbuffer pixel format
+
+ // Vertex buffer: one-to-one correlation with Mesa's vertex buffer.
+ // This will be filled by our setup function (see d3dvsetup.c)
+ DGL_TLvertex gWin[VB_SIZE]; // Transformed and lit vertices
+// DGL_Lvertex gObj[VB_SIZE]; // Lit vertices in object coordinates.
+
+ // Indices for DrawIndexedPrimitive.
+ // Clipped quads are drawn seperately, so use VB_SIZE.
+ // 6 indices are needed to make 2 triangles for each possible quad
+// WORD wIndices[(VB_SIZE / 4) * 6];
+ WORD wIndices[32768];
+
+ //
+ // Device driver vars:
+ //
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+
+ // DirectX COM interfaces, postfixed with the interface number
+ IDirectDraw *lpDD1;
+ IDirectDraw4 *lpDD4;
+ IDirect3D3 *lpD3D3;
+ IDirect3DDevice3 *lpDev3;
+ IDirect3DViewport3 *lpViewport3;
+ IDirectDrawSurface4 *lpFront4;
+ IDirectDrawSurface4 *lpBack4;
+ IDirectDrawSurface4 *lpDepth4;
+
+ // Vertex buffers
+ BOOL bD3DPipeline; // True if using D3D geometry pipeline
+ IDirect3DVertexBuffer *m_vbuf; // Unprocessed vertices
+ IDirect3DVertexBuffer *m_pvbuf; // Processed vertices ready to be rendered
+
+ D3DTEXTUREOP ColorOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ D3DTEXTUREOP AlphaOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ struct gl_texture_object *tObj[MAX_TEXTURE_UNITS];
+
+ DDCAPS ddCaps; // DirectDraw caps
+ D3DDEVICEDESC D3DDevDesc; // Direct3D Device description
+
+ DDPIXELFORMAT ddpfRender; // Pixel format of the render buffer
+ DDPIXELFORMAT ddpfDepth; // Pixel format of the depth buffer
+
+ BOOL bStencil; // TRUE is this context has stencil
+
+ PX_packFunc fnPackFunc; // Pixel packing function for SW
+ PX_unpackFunc fnUnpackFunc; // Pixel unpacking function for SW
+ PX_packSpanFunc fnPackSpanFunc; // Pixel span packer
+
+ D3DVIEWPORT2 d3dViewport; // D3D Viewport object
+
+ D3DCULL cullmode; // Direct3D cull mode
+ D3DCOLOR curcolor; // Current color
+ DWORD dwColorPF; // Current color, in format of target surface
+ D3DCOLOR d3dClearColor; // Clear color
+ D3DCOLOR ConstantColor; // For flat shading
+ DWORD dwClearColorPF; // Clear color, in format of target surface
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Primitive caches
+// DGL_vertex LineCache[DGL_MAX_LINE_VERTS];
+// DGL_vertex TriCache[DGL_MAX_TRI_VERTS];
+// DWORD dwNextLineVert;
+// DWORD dwNextTriVert;
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+ // Shared texture palette
+ IDirectDrawPalette *lpGlobalPalette;
+
+ // Usage counters.
+ // One of these counters will be incremented when we choose
+ // between hardware and software rendering functions.
+// DWORD dwHWUsageCount; // Hardware usage count
+// DWORD dwSWUsageCount; // Software usage count
+
+ // Texture state flags.
+// BOOL m_texturing; // TRUE is texturing
+// BOOL m_mtex; // TRUE if multitexture
+// BOOL m_texHandleValid; // TRUE if tex state valid
+
+ // Renderstate caches to ensure no redundant state changes
+ DWORD dwRS[256]; // Renderstates
+ DWORD dwTSS[2][24]; // Texture-stage states
+ LPDIRECT3DTEXTURE2 lpTex[2]; // Texture (1 per stage)
+
+ DWORD dwMaxTextureSize; // Max texture size:
+ // clamped to 1024.
+
+} DGL_ctx;
+#endif // _USE_GLD3_WGL
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HHOOK hKeyHook;
+LRESULT CALLBACK dglKeyProc(int code,WPARAM wParam,LPARAM lParam);
+
+void dglInitContextState();
+void dglDeleteContextState();
+BOOL dglIsValidContext(HGLRC a);
+DGL_ctx* dglGetContextAddress(const HGLRC a);
+HDC dglGetCurrentDC(void);
+HGLRC dglGetCurrentContext(void);
+HGLRC dglCreateContext(HDC a, const DGL_pixelFormat *lpPF);
+BOOL dglMakeCurrent(HDC a, HGLRC b);
+BOOL dglDeleteContext(HGLRC a);
+BOOL dglSwapBuffers(HDC hDC);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.c b/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.c
new file mode 100644
index 000000000..c633e3bcf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Global variables.
+*
+****************************************************************************/
+
+#include "dglglobals.h"
+
+// =======================================================================
+// Global Variables
+// =======================================================================
+
+char szCopyright[] = "Copyright (c) 1998 SciTech Software, Inc.";
+char szDllName[] = "Scitech GLDirect";
+char szErrorTitle[] = "GLDirect Error";
+
+DGL_globals glb;
+
+// Shared result variable
+HRESULT hResult;
+
+// ***********************************************************************
+
+// Patch function for missing function in Mesa
+int finite(
+ double x)
+{
+ return _finite(x);
+};
+
+// ***********************************************************************
+
+void dglInitGlobals()
+{
+ // Zero all fields just in case
+ memset(&glb, 0, sizeof(glb));
+
+ // Set the global defaults
+ glb.bPrimary = FALSE; // Not the primary device
+ glb.bHardware = FALSE; // Not a hardware device
+// glb.bFullscreen = FALSE; // Not running fullscreen
+ glb.bSquareTextures = FALSE; // Device does not need sq
+ glb.bPAL8 = FALSE; // Device cannot do 8bit
+ glb.dwMemoryType = DDSCAPS_SYSTEMMEMORY;
+ glb.dwRendering = DGL_RENDER_D3D;
+
+ glb.bWaitForRetrace = TRUE; // Sync to vertical retrace
+ glb.bFullscreenBlit = FALSE;
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL; // Pixel format list
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+ glb.nTextureFormatCount = 0;
+ glb.lpTextureFormat = NULL;
+#endif // _USE_GLD3_WGL
+
+ glb.wMaxSimultaneousTextures = 1;
+
+ // Enable support for multitexture, if available.
+ glb.bMultitexture = TRUE;
+
+ // Enable support for mipmapping
+ glb.bUseMipmaps = TRUE;
+
+ // Alpha emulation via chroma key
+ glb.bEmulateAlphaTest = FALSE;
+
+ // Use Mesa pipeline always (for compatibility)
+ glb.bForceMesaPipeline = FALSE;
+
+ // Init support for multiple GLRCs
+ glb.bDirectDraw = FALSE;
+ glb.bDirectDrawPrimary = FALSE;
+ glb.bDirect3D = FALSE;
+ glb.bDirect3DDevice = FALSE;
+ glb.bDirectDrawStereo = FALSE;
+ glb.iDirectDrawStereo = 0;
+ glb.hWndActive = NULL;
+ // Init DirectX COM interfaces for multiple GLRCs
+// glb.lpDD4 = NULL;
+// glb.lpPrimary4 = NULL;
+// glb.lpBack4 = NULL;
+// glb.lpDepth4 = NULL;
+// glb.lpGlobalPalette = NULL;
+
+ // Init special support options
+ glb.bMessageBoxWarnings = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+
+ // Do not assume single-precision-only FPU (for compatibility)
+ glb.bFastFPU = FALSE;
+
+ // Allow hot-key support
+ glb.bHotKeySupport = TRUE;
+
+ // Default to single-threaded support (for simplicity)
+ glb.bMultiThreaded = FALSE;
+
+ // Use application-specific customizations (for end-user convenience)
+ glb.bAppCustomizations = TRUE;
+
+#ifdef _USE_GLD3_WGL
+ // Registry/ini-file settings for GLDirect 3.x
+ glb.dwAdapter = 0; // Primary DX8 adapter
+ glb.dwTnL = 1; // MesaSW TnL
+ glb.dwMultisample = 0; // Multisample Off
+ glb.dwDriver = 2; // Direct3D HW
+
+ // Signal a pixelformat list rebuild
+ glb.bPixelformatsDirty = TRUE;
+#endif
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.h b/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.h
new file mode 100644
index 000000000..995f1cd5e
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglglobals.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Globals.
+*
+****************************************************************************/
+
+#ifndef __DGLGLOBALS_H
+#define __DGLGLOBALS_H
+
+#include "dglcontext.h"
+#include "dglpf.h" // Pixel format
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DGL_RENDER_MESASW = 0,
+ DGL_RENDER_D3D = 1,
+ DGL_RENDER_FORCE_DWORD = 0x7ffffff,
+} DGL_renderType;
+
+#ifdef _USE_GLD3_WGL
+
+// Same as DGL_renderType? KeithH
+typedef enum {
+ GLDS_DRIVER_MESA_SW = 0, // Mesa SW rendering
+ GLDS_DRIVER_REF = 1, // Direct3D Reference Rasteriser
+ GLDS_DRIVER_HAL = 2, // Direct3D HW rendering
+} GLDS_DRIVER;
+
+typedef enum {
+ GLDS_TNL_DEFAULT = 0, // Choose best TnL method
+ GLDS_TNL_MESA = 1, // Mesa TnL
+ GLDS_TNL_D3DSW = 2, // D3D Software TnL
+ GLDS_TNL_D3DHW = 3, // D3D Hardware TnL
+} GLDS_TNL;
+
+typedef enum {
+ GLDS_MULTISAMPLE_NONE = 0,
+ GLDS_MULTISAMPLE_FASTEST = 1,
+ GLDS_MULTISAMPLE_NICEST = 2,
+} GLDS_MULTISAMPLE;
+#endif
+
+typedef struct {
+ // Registry settings
+ char szDDName[MAX_DDDEVICEID_STRING]; // DirectDraw device name
+ char szD3DName[MAX_DDDEVICEID_STRING]; // Direct3D driver name
+ BOOL bPrimary; // Is ddraw device the Primary device?
+ BOOL bHardware; // Is the d3d driver a Hardware driver?
+#ifndef _USE_GLD3_WGL
+ GUID ddGuid; // GUID of the ddraw device
+ GUID d3dGuid; // GUID of the direct3d driver
+#endif // _USE_GLD3_WGL
+// BOOL bFullscreen; // Force fullscreen - only useful for primary adaptors.
+ BOOL bSquareTextures; // Does this driver require square textures?
+ DWORD dwRendering; // Type of rendering required
+
+ BOOL bWaitForRetrace; // Sync to vertical retrace
+ BOOL bFullscreenBlit; // Use Blt instead of Flip in fullscreen modes
+
+ // Multitexture
+ BOOL bMultitexture;
+
+ BOOL bUseMipmaps;
+
+ DWORD dwMemoryType; // Sysmem or Vidmem
+
+ // Global palette
+ BOOL bPAL8;
+ DDPIXELFORMAT ddpfPAL8;
+
+ // Multitexture
+ WORD wMaxSimultaneousTextures;
+
+ // Win32 internals
+ BOOL bAppActive; // Keep track of Alt-Tab
+ LONG lpfnWndProc; // WndProc of calling app
+
+ // Pixel Format Descriptior list.
+ int nPixelFormatCount;
+ DGL_pixelFormat *lpPF;
+#ifndef _USE_GLD3_WGL
+ // ZBuffer pixel formats
+ int nZBufferPFCount; // Count of Zbuffer pixel formats
+ DDPIXELFORMAT *lpZBufferPF; // ZBuffer pixel formats
+
+ // Display modes (for secondary devices)
+ int nDisplayModeCount;
+ DDSURFACEDESC2 *lpDisplayModes;
+
+ // Texture pixel formats
+ int nTextureFormatCount;
+ DGL_textureFormat *lpTextureFormat;
+#endif // _USE_GLD3_WGL
+ // Alpha emulation via chroma key
+ BOOL bEmulateAlphaTest;
+
+ // Geom pipeline override.
+ // If this is set TRUE then the D3D pipeline will never be used,
+ // and the Mesa pipline will always be used.
+ BOOL bForceMesaPipeline;
+
+#ifdef _USE_GLD3_WGL
+ BOOL bPixelformatsDirty; // Signal a list rebuild
+#endif
+
+ // Additional globals to support multiple GL rendering contexts, GLRCs
+ BOOL bDirectDraw; // DirectDraw interface exists ?
+ BOOL bDirectDrawPrimary; // DirectDraw primary surface exists ?
+ BOOL bDirect3D; // Direct3D interface exists ?
+ BOOL bDirect3DDevice; // Direct3D device exists ?
+
+ BOOL bDirectDrawStereo; // DirectDraw Stereo driver started ?
+ int iDirectDrawStereo; // DirectDraw Stereo driver reference count
+ HWND hWndActive; // copy of active window
+
+ // Copies of DirectX COM interfaces for re-referencing across multiple GLRCs
+// IDirectDraw4 *lpDD4; // copy of DirectDraw interface
+// IDirectDrawSurface4 *lpPrimary4; // copy of DirectDraw primary surface
+// IDirectDrawSurface4 *lpBack4;
+// IDirectDrawSurface4 *lpDepth4;
+// IDirectDrawPalette *lpGlobalPalette;
+
+ // Aids for heavy-duty MFC-windowed OGL apps, like AutoCAD
+ BOOL bMessageBoxWarnings; // popup message box warning
+ BOOL bDirectDrawPersistant; // DirectDraw is persisitant
+ BOOL bPersistantBuffers; // DirectDraw buffers persisitant
+
+ // FPU setup option for CAD precision (AutoCAD) vs GAME speed (Quake)
+ BOOL bFastFPU; // single-precision-only FPU ?
+
+ // Hot-Key support, like for real-time stereo parallax adjustments
+ BOOL bHotKeySupport; // hot-key support ?
+
+ // Multi-threaded support, for apps like 3DStudio
+ BOOL bMultiThreaded; // multi-threaded ?
+
+ // Detect and use app-specific customizations for apps like 3DStudio
+ BOOL bAppCustomizations; // app customizations ?
+
+#ifdef _USE_GLD3_WGL
+ DWORD dwAdapter; // Primary DX8 adapter
+ DWORD dwTnL; // MesaSW TnL
+ DWORD dwMultisample; // Multisample Off
+ DWORD dwDriver; // Direct3D HW
+ void *pDrvPrivate; // Driver-specific data
+#endif
+
+} DGL_globals;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DGL_globals glb;
+
+void dglInitGlobals();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglmacros.h b/mesalib/src/mesa/drivers/windows/gldirect/dglmacros.h
new file mode 100644
index 000000000..aed0f2110
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglmacros.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Useful generic macros.
+*
+****************************************************************************/
+
+#ifndef __DGLMACROS_H
+#define __DGLMACROS_H
+
+#include <ddraw.h>
+
+// Define the relevant RELEASE macro depending on C or C++
+#if !defined(__cplusplus) || defined(CINTERFACE)
+ // Standard C version
+ #define RELEASE(x) if (x!=NULL) { x->lpVtbl->Release(x); x=NULL; }
+#else
+ // C++ version
+ #define RELEASE(x) if (x!=NULL) { x->Release(); x=NULL; }
+#endif
+
+// We don't want a message *every* time we call an unsupported function
+#define UNSUPPORTED(x) \
+ { \
+ static BOOL bFirstTime = TRUE; \
+ if (bFirstTime) { \
+ bFirstTime = FALSE; \
+ ddlogError(DDLOG_WARN, (x), DDERR_CURRENTLYNOTAVAIL); \
+ } \
+ }
+
+#define DGL_CHECK_CONTEXT \
+ if (ctx == NULL) return;
+
+// Don't render if bCanRender is not TRUE.
+#define DGL_CHECK_RENDER \
+ if (!dgl->bCanRender) return;
+
+#if 0
+#define TRY(a,b) (a)
+#define TRY_ERR(a,b) (a)
+#else
+// hResult should be defined in the function
+// Return codes should be checked via SUCCEDDED and FAILED macros
+#define TRY(a,b) \
+ { \
+ if (FAILED(hResult=(a))) \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ }
+
+// hResult is a global
+// The label exit_with_error should be defined within the calling scope
+#define TRY_ERR(a,b) \
+ { \
+ if (FAILED(hResult=(a))) { \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ goto exit_with_error; \
+ } \
+ }
+#endif // #if 1
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglpf.c b/mesalib/src/mesa/drivers/windows/gldirect/dglpf.c
new file mode 100644
index 000000000..4cd4d0334
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglpf.c
@@ -0,0 +1,620 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#include "dglpf.h"
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// ***********************************************************************
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 5, // Green bits, shift
+ 5, 10, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ -1, // No depth/stencil buffer
+};
+
+// ***********************************************************************
+// Return the count of the number of bits in a Bit Mask.
+int BitCount(
+ DWORD dw)
+{
+ int i;
+
+ if (dw == 0)
+ return 0; // account for non-RGB mode
+
+ for (i=0; dw; dw=dw>>1)
+ i += (dw & 1);
+ return i;
+}
+
+// ***********************************************************************
+
+DWORD BitShift(
+ DWORD dwMaskIn)
+{
+ DWORD dwShift, dwMask;
+
+ if (dwMaskIn == 0)
+ return 0; // account for non-RGB mode
+
+ for (dwShift=0, dwMask=dwMaskIn; !(dwMask&1); dwShift++, dwMask>>=1);
+
+ return dwShift;
+}
+
+// ***********************************************************************
+
+BOOL IsValidPFD(int iPFD)
+{
+ DGL_pixelFormat *lpPF;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if ((glb.lpPF == NULL) ||
+ (glb.nPixelFormatCount == 0))
+ return FALSE;
+
+ // Check PFD range
+ if ( (iPFD < 1) || (iPFD > glb.nPixelFormatCount) ) {
+ ddlogMessage(DDLOG_ERROR, "PFD out of range\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Make a pointer to the pixel format
+ lpPF = &glb.lpPF[iPFD-1];
+
+ // Check size
+ if (lpPF->pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ ddlogMessage(DDLOG_ERROR, "Bad PFD size\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Check version
+ if (lpPF->pfd.nVersion != 1) {
+ ddlogMessage(DDLOG_ERROR, "PFD is not Version 1\n");
+ return FALSE; // PFD is invalid
+ }
+
+ return TRUE; // PFD is valid
+}
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+
+int iEnumCount; // Enumeration count
+DWORD dwDisplayBitDepth; // Bit depth of current display mode
+
+// ***********************************************************************
+
+HRESULT WINAPI EnumDisplayModesCallback(
+ DDSURFACEDESC2* pddsd,
+ void *pvContext)
+{
+ DWORD dwModeDepth;
+ DDSURFACEDESC2 *lpDisplayMode;
+ char buf[32];
+
+ // Check parameters
+ if (pddsd == NULL)
+ return DDENUMRET_CANCEL;
+
+ dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
+ lpDisplayMode = (DDSURFACEDESC2 *)pvContext;
+
+ // Check mode for compatability with device.
+ if (dwModeDepth != dwDisplayBitDepth)
+ return DDENUMRET_OK;
+
+ if (lpDisplayMode != NULL) {
+ memcpy(&lpDisplayMode[iEnumCount], pddsd, sizeof(DDSURFACEDESC2));
+ sprintf(buf, TEXT("Mode: %ld x %ld x %ld\n"),
+ pddsd->dwWidth, pddsd->dwHeight, dwModeDepth);
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+
+ iEnumCount++;
+
+ return DDENUMRET_OK;
+}
+
+// ***********************************************************************
+
+HRESULT CALLBACK d3dEnumZBufferFormatsCallback(
+ DDPIXELFORMAT* pddpf,
+ VOID* lpZBufferPF )
+{
+ char buf[64];
+
+ if(pddpf == NULL)
+ return D3DENUMRET_CANCEL;
+
+ if (pddpf->dwFlags & DDPF_ZBUFFER) {
+ if (lpZBufferPF == NULL) {
+ // Pass 1. Merely counting the PF
+ glb.nZBufferPFCount++;
+ } else {
+ // Pass 2. Save the PF
+ if (pddpf->dwFlags & DDPF_STENCILBUFFER) {
+ sprintf(buf, " %d: Z=%d S=%d\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth,
+ pddpf->dwStencilBitDepth);
+ } else {
+ sprintf(buf, " %d: Z=%d S=0\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth);
+ }
+ ddlogMessage(DDLOG_INFO, buf);
+
+ memcpy(&glb.lpZBufferPF[iEnumCount++],
+ pddpf,
+ sizeof(DDPIXELFORMAT));
+ }
+ }
+
+ return D3DENUMRET_OK;
+}
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+BOOL IsStencilSupportBroken(LPDIRECTDRAW4 lpDD4)
+{
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+ BOOL bBroken = FALSE;
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return FALSE;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpDD4, &dddi, 0)))
+ return FALSE;
+
+ // Matrox G400 stencil buffer support does not draw anything in AutoCAD,
+ // but ordinary Z buffers draw shaded models fine. (DaveM)
+ if (dddi.dwVendorId == 0x102B) { // Matrox
+ if (dddi.dwDeviceId == 0x0525) { // G400
+ bBroken = TRUE;
+ }
+ }
+
+ return bBroken;
+}
+
+// ***********************************************************************
+
+void dglBuildPixelFormatList()
+{
+ int i;
+ char buf[128];
+ char cat[8];
+ DGL_pixelFormat *lpPF;
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.BuildPixelformatList();
+#else
+ HRESULT hRes;
+ IDirectDraw *lpDD1 = NULL;
+ IDirectDraw4 *lpDD4 = NULL;
+ IDirect3D3 *lpD3D3 = NULL;
+ DDSURFACEDESC2 ddsdDisplayMode;
+
+ DWORD dwRb, dwGb, dwBb, dwAb; // Bit counts
+ DWORD dwRs, dwGs, dwBs, dwAs; // Bit shifts
+ DWORD dwPixelType; // RGB or color index
+
+ // Set defaults
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+
+ //
+ // Examine the hardware for depth and stencil
+ //
+
+ if (glb.bPrimary)
+ hRes = DirectDrawCreate(NULL, &lpDD1, NULL);
+ else
+ hRes = DirectDrawCreate(&glb.ddGuid, &lpDD1, NULL);
+
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: DirectDrawCreate failed", hRes);
+ return;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hRes = IDirectDraw_QueryInterface(
+ lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpDD4);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (DD4) failed", hRes);
+ goto clean_up;
+ }
+
+
+ // Retrieve caps of current display mode
+ ZeroMemory(&ddsdDisplayMode, sizeof(ddsdDisplayMode));
+ ddsdDisplayMode.dwSize = sizeof(ddsdDisplayMode);
+ hRes = IDirectDraw4_GetDisplayMode(lpDD4, &ddsdDisplayMode);
+ if (FAILED(hRes))
+ goto clean_up;
+
+ dwDisplayBitDepth = ddsdDisplayMode.ddpfPixelFormat.dwRGBBitCount;
+ dwPixelType = (dwDisplayBitDepth <= 8) ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
+ dwRb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+ dwRs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+
+ if (BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask)) {
+ dwAb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ dwAs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ } else {
+ dwAb = 0;
+ dwAs = 0;
+ }
+
+ // Query for available display modes
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Display Modes:\n");
+
+ // Pass 1: Determine count
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ NULL,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ if (iEnumCount == 0) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: No display modes found");
+ goto clean_up;
+ }
+ glb.lpDisplayModes = (DDSURFACEDESC2 *)calloc(iEnumCount,
+ sizeof(DDSURFACEDESC2));
+ if (glb.lpDisplayModes == NULL) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: DDSURFACEDESC2 calloc failed");
+ goto clean_up;
+ }
+ glb.nDisplayModeCount = iEnumCount;
+ // Pass 2: Save modes
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ (void *)glb.lpDisplayModes,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ // Query for IDirect3D3 interface
+ hRes = IDirectDraw4_QueryInterface(
+ lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpD3D3);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (D3D3) failed", hRes);
+ goto clean_up;
+ }
+
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "ZBuffer formats:\n");
+
+ // Pass 1. Count the ZBuffer pixel formats
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ NULL);
+
+ if (FAILED(hRes))
+ goto clean_up;
+
+ if (glb.nZBufferPFCount) {
+ glb.lpZBufferPF = (DDPIXELFORMAT *)calloc(glb.nZBufferPFCount,
+ sizeof(DDPIXELFORMAT));
+ if(glb.lpZBufferPF == NULL)
+ goto clean_up;
+
+ // Pass 2. Cache the ZBuffer pixel formats
+ iEnumCount = 0; // (Used by the enum function)
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ glb.lpZBufferPF);
+
+ if (FAILED(hRes))
+ goto clean_up;
+ }
+
+ // Remove stencil support for boards which don't work for AutoCAD;
+ // Matrox G400 does not work, but NVidia TNT2 and ATI Rage128 do... (DaveM)
+ if (IsStencilSupportBroken(lpDD4)) {
+ for (i=0; i<iEnumCount; i++)
+ if (glb.lpZBufferPF[i].dwFlags & DDPF_STENCILBUFFER)
+ glb.nZBufferPFCount--;
+ }
+
+ // One each for every ZBuffer pixel format (including no depth buffer)
+ // Times-two because duplicated for single buffering (as opposed to double)
+ glb.nPixelFormatCount = 2 * (glb.nZBufferPFCount + 1);
+ glb.lpPF = (DGL_pixelFormat *)calloc(glb.nPixelFormatCount,
+ sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ goto clean_up;
+ //
+ // Fill in the pixel formats
+ // Note: Depth buffer bits are really (dwZBufferBitDepth-dwStencilBitDepth)
+ // but this will pass wierd numbers to the OpenGL app. (?)
+ //
+
+ pfTemplateHW.pfd.iPixelType = dwPixelType;
+ pfTemplateHW.pfd.cColorBits = dwDisplayBitDepth;
+ pfTemplateHW.pfd.cRedBits = dwRb;
+ pfTemplateHW.pfd.cGreenBits = dwGb;
+ pfTemplateHW.pfd.cBlueBits = dwBb;
+ pfTemplateHW.pfd.cAlphaBits = dwAb;
+ pfTemplateHW.pfd.cRedShift = dwRs;
+ pfTemplateHW.pfd.cGreenShift = dwGs;
+ pfTemplateHW.pfd.cBlueShift = dwBs;
+ pfTemplateHW.pfd.cAlphaShift = dwAs;
+
+ lpPF = glb.lpPF;
+
+ // Fill in the double-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ }
+ // Fill in the single-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ // Remove double-buffer flag. Could use XOR instead...
+ lpPF->pfd.dwFlags &= (~(PFD_DOUBLEBUFFER));
+ // Insert GDI flag for single buffered format only.
+ lpPF->pfd.dwFlags |= PFD_SUPPORT_GDI;
+ }
+#endif // _USE_GLD3_WGL
+
+ // Lets dump the list to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Pixel Formats:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ for (i=0, lpPF = glb.lpPF; i<glb.nPixelFormatCount; i++, lpPF++) {
+ sprintf(buf, "0x%02x ", i+1);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+ if(lpPF->pfd.dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(lpPF->pfd.dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(lpPF->pfd.bReserved) sprintf(cat, " %d ", lpPF->pfd.bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cRedBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cGreenBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cBlueBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAlphaBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAuxBuffers) sprintf(cat, "%2d ", lpPF->pfd.cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cDepthBits) sprintf(cat, "%2d ", lpPF->pfd.cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cStencilBits) sprintf(cat, "%2d ", lpPF->pfd.cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumRedBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumGreenBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumBlueBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumAlphaBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+#ifndef _USE_GLD3_WGL
+clean_up:
+ // Release COM objects
+ RELEASE(lpD3D3);
+ RELEASE(lpDD4);
+ RELEASE(lpDD1);
+
+ // Popup warning message if non RGB color mode
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
+
+void dglReleasePixelFormatList()
+{
+ glb.nPixelFormatCount = 0;
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ glb.lpPF = NULL;
+ }
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ if (glb.lpZBufferPF) {
+ free(glb.lpZBufferPF);
+ glb.lpZBufferPF = NULL;
+ }
+ glb.nDisplayModeCount = 0;
+ if (glb.lpDisplayModes) {
+ free(glb.lpDisplayModes);
+ glb.lpDisplayModes = NULL;
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglpf.h b/mesalib/src/mesa/drivers/windows/gldirect/dglpf.h
new file mode 100644
index 000000000..8a7e38c4b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglpf.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#ifndef __DGLPF_H
+#define __DGLPF_H
+
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PIXELFORMATDESCRIPTOR pfd; // Win32 Pixel Format Descriptor
+#ifdef _USE_GLD3_WGL
+ // Driver-specific data.
+ // Example: The DX8 driver uses this to hold an index into a
+ // list of depth-stencil descriptions.
+ DWORD dwDriverData;
+#else
+ int iZBufferPF; // Index of depth buffer pixel format
+#endif
+} DGL_pixelFormat;
+
+#include "dglglobals.h"
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL IsValidPFD(int iPFD);
+void dglBuildPixelFormatList();
+void dglReleasePixelFormatList();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c
new file mode 100644
index 000000000..74ecb01a5
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.c
@@ -0,0 +1,2964 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#include "dglwgl.h"
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+#include "gl/glu.h" // MUST USE MICROSOFT'S GLU32!
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+// Need to export wgl* functions if using GLD3,
+// otherwise export GLD2 DGL_* functions.
+#ifdef _USE_GLD3_WGL
+#define _GLD_WGL_EXPORT(a) wgl##a
+#else
+#define _GLD_WGL_EXPORT(a) DGL_##a
+#endif
+
+// Calls into Mesa 4.x are different
+#ifdef _USE_GLD3_WGL
+#include "dlist.h"
+#include "drawpix.h"
+#include "get.h"
+#include "matrix.h"
+// NOTE: All the _GLD* macros now call the gl* functions direct.
+// This ensures that the correct internal pathway is taken. KeithH
+#define _GLD_glNewList glNewList
+#define _GLD_glBitmap glBitmap
+#define _GLD_glEndList glEndList
+#define _GLD_glDeleteLists glDeleteLists
+#define _GLD_glGetError glGetError
+#define _GLD_glTranslatef glTranslatef
+#define _GLD_glBegin glBegin
+#define _GLD_glVertex2fv glVertex2fv
+#define _GLD_glEnd glEnd
+#define _GLD_glNormal3f glNormal3f
+#define _GLD_glVertex3f glVertex3f
+#define _GLD_glVertex3fv glVertex3fv
+#else // _USE_GLD3_WGL
+#define _GLD_glNewList (*mesaFuncs.glNewList)
+#define _GLD_glBitmap (*mesaFuncs.glBitmap)
+#define _GLD_glEndList (*mesaFuncs.glEndList)
+#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
+#define _GLD_glGetError (*mesaFuncs.glGetError)
+#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
+#define _GLD_glBegin (*mesaFuncs.glBegin)
+#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
+#define _GLD_glEnd (*mesaFuncs.glEnd)
+#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
+#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
+#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+// Emulate SGI DDK calls.
+#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
+#define __wglFree(a) GlobalFree((a))
+
+// ***********************************************************************
+
+// Mesa glu.h and MS glu.h call these different things...
+//#define GLUtesselator GLUtriangulatorObj
+//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
+
+// For wglFontOutlines
+
+typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
+typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
+typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
+typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
+typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
+
+static HINSTANCE gluModuleHandle;
+static gluNewTessProto gluNewTessProc;
+static gluDeleteTessProto gluDeleteTessProc;
+static gluTessBeginPolygonProto gluTessBeginPolygonProc;
+static gluTessBeginContourProto gluTessBeginContourProc;
+static gluTessVertexProto gluTessVertexProc;
+static gluTessEndContourProto gluTessEndContourProc;
+static gluTessEndPolygonProto gluTessEndPolygonProc;
+static gluTessPropertyProto gluTessPropertyProc;
+static gluTessNormalProto gluTessNormalProc;
+static gluTessCallbackProto gluTessCallbackProc;
+
+static HFONT hNewFont, hOldFont;
+static FLOAT ScaleFactor;
+
+#define LINE_BUF_QUANT 4000
+#define VERT_BUF_QUANT 4000
+
+static FLOAT* LineBuf;
+static DWORD LineBufSize;
+static DWORD LineBufIndex;
+static FLOAT* VertBuf;
+static DWORD VertBufSize;
+static DWORD VertBufIndex;
+static GLenum TessErrorOccurred;
+
+static int AppendToLineBuf(
+ FLOAT value);
+
+static int AppendToVertBuf(
+ FLOAT value);
+
+static int DrawGlyph(
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static void FreeLineBuf(void);
+
+static void FreeVertBuf(void);
+
+static long GetWord(
+ UCHAR** p);
+
+static long GetDWord(
+ UCHAR** p);
+
+static double GetFixed(
+ UCHAR** p);
+
+static int InitLineBuf(void);
+
+static int InitVertBuf(void);
+
+static HFONT CreateHighResolutionFont(
+ HDC hDC);
+
+static int MakeDisplayListFromGlyph(
+ DWORD listName,
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static BOOL LoadGLUTesselator(void);
+static BOOL UnloadGLUTesselator(void);
+
+static int MakeLinesFromArc(
+ FLOAT x0,
+ FLOAT y0,
+ FLOAT x1,
+ FLOAT y1,
+ FLOAT x2,
+ FLOAT y2,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviationSquared);
+
+static int MakeLinesFromGlyph( UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTLine( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount);
+
+static int MakeLinesFromTTPolycurve( UCHAR** pp,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTPolygon( UCHAR** pp,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTQSpline( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount,
+ FLOAT chordalDeviation);
+
+static void CALLBACK TessCombine( double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData);
+
+static void CALLBACK TessError( GLenum error);
+
+static void CALLBACK TessVertexOutData( FLOAT p[3],
+ GLfloat z);
+
+// ***********************************************************************
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLWGL.C vars for multi-threaded support")
+extern CRITICAL_SECTION CriticalSection;
+extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
+#endif
+int curPFD = 0; // Current PFD (static)
+
+// ***********************************************************************
+
+int dglGetPixelFormat(void)
+{
+#ifdef GLD_THREADS
+ int iPixelFormat;
+ // get thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iPixelFormat = curPFD;
+ }
+ }
+ // get global static var
+ else {
+ iPixelFormat = curPFD;
+ }
+ return iPixelFormat;
+#else
+ return curPFD;
+#endif
+}
+
+// ***********************************************************************
+
+void dglSetPixelFormat(int iPixelFormat)
+{
+#ifdef GLD_THREADS
+ // set thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ curPFD = iPixelFormat;
+ }
+ }
+ // set global static var
+ else {
+ curPFD = iPixelFormat;
+ }
+#else
+ curPFD = iPixelFormat;
+#endif
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
+ HDC a,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ DGL_pixelFormat *lpPF = glb.lpPF;
+
+ PIXELFORMATDESCRIPTOR ppfdBest;
+ int i;
+ int bestIndex = -1;
+ int numPixelFormats;
+ DWORD dwFlags;
+
+ char buf[128];
+ char cat[8];
+
+ DWORD dwAllFlags =
+ PFD_DRAW_TO_WINDOW |
+ PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI |
+ PFD_SUPPORT_OPENGL |
+ PFD_GENERIC_FORMAT |
+ PFD_NEED_PALETTE |
+ PFD_NEED_SYSTEM_PALETTE |
+ PFD_DOUBLEBUFFER |
+ PFD_STEREO |
+ /*PFD_SWAP_LAYER_BUFFERS |*/
+ PFD_DOUBLEBUFFER_DONTCARE |
+ PFD_STEREO_DONTCARE |
+ PFD_SWAP_COPY |
+ PFD_SWAP_EXCHANGE |
+ PFD_GENERIC_ACCELERATED |
+ 0;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // List may not be built until dglValidate() is called! KeithH
+ lpPF = glb.lpPF;
+
+ //
+ // Lets print the input pixel format to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ //
+ ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ sprintf(buf, " . ");
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+ if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+ //
+ // Examine the flags for correctness
+ //
+ dwFlags = ppfd->dwFlags;
+ if (dwFlags != (dwFlags & dwAllFlags))
+ {
+ /* error: bad dwFlags */
+ ddlogPrintf(DDLOG_WARN,
+ "ChoosePixelFormat: bad flags (0x%x)",
+ dwFlags & (~dwAllFlags));
+ // Mask illegal flags and continue
+ dwFlags = dwFlags & dwAllFlags;
+ }
+
+ switch (ppfd->iPixelType) {
+ case PFD_TYPE_RGBA:
+ case PFD_TYPE_COLORINDEX:
+ break;
+ default:
+ /* error: bad iPixelType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
+ return 0;
+ }
+
+ switch (ppfd->iLayerType) {
+ case PFD_MAIN_PLANE:
+ case PFD_OVERLAY_PLANE:
+ case PFD_UNDERLAY_PLANE:
+ break;
+ default:
+ /* error: bad iLayerType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
+ return 0;
+ }
+
+ numPixelFormats = glb.nPixelFormatCount;
+
+ /* loop through candidate pixel format descriptors */
+ for (i=0; i<numPixelFormats; ++i) {
+ PIXELFORMATDESCRIPTOR ppfdCandidate;
+
+ memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
+
+ /*
+ ** Check attributes which must match
+ */
+ if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
+ continue;
+ }
+
+ if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
+ continue;
+ }
+
+ if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
+ (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
+ if ((dwFlags & PFD_DOUBLEBUFFER) !=
+ (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
+ {
+ continue;
+ }
+ }
+
+// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
+ if ((dwFlags & PFD_STEREO) !=
+ (ppfdCandidate.dwFlags & PFD_STEREO))
+ {
+ continue;
+ }
+// }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
+ continue;
+ }
+
+ if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
+ continue;
+ }
+
+ if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
+ continue;
+ }
+
+ /*
+ ** See if candidate is better than the previous best choice
+ */
+ if (bestIndex == -1) {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cColorBits > ppfdBest.cColorBits &&
+ ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
+ (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
+ ppfdCandidate.cColorBits < ppfdBest.cColorBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits
+ && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits
+ && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
+ ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
+ (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
+ ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cStencilBits &&
+ ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers &&
+ ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+ }
+
+ if (bestIndex != -1) {
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
+ return bestIndex + 1;
+ }
+
+ // Return the pixelformat that has the most capabilities.
+ // ** NOTE: This is only possible due to the way the list
+ // of pixelformats is built. **
+ // Now picks best pixelformat. KeithH
+ bestIndex = numPixelFormats; // most capable double buffer format
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
+ return (bestIndex);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
+ HGLRC a,
+ HGLRC b,
+ UINT c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+ UNSUPPORTED("wglCopyContext")
+ return FALSE; // Failed
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
+ HDC a)
+{
+ int ipf;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // Check that the current PFD is valid
+ ipf = dglGetPixelFormat();
+ if (!IsValidPFD(ipf))
+ return (HGLRC)0;
+
+ return dglCreateContext(a, &glb.lpPF[ipf-1]);
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
+ HDC a,
+ int b)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("wglCreateLayerContext")
+ return NULL; // Failed
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
+ HGLRC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglDeleteContext(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
+ HDC hDC,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_DescribeLayerPlane")
+
+// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
+ HDC a,
+ int b,
+ UINT c,
+ LPPIXELFORMATDESCRIPTOR d)
+{
+ UINT nSize;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ if (d == NULL) // Calling app requires max number of PF's
+ return glb.nPixelFormatCount;
+
+ // The supplied buffer may be larger than the info that we
+ // will be copying.
+ if (c > sizeof(PIXELFORMATDESCRIPTOR))
+ nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ else
+ nSize = c;
+
+ // Setup an empty PFD before doing validation check
+ memset(d, 0, nSize);
+ d->nSize = nSize;
+ d->nVersion = 1;
+
+ if (!IsValidPFD(b))
+ return 0; // Bail if PFD index is invalid
+
+ memcpy(d, &glb.lpPF[b-1].pfd, nSize);
+
+ return glb.nPixelFormatCount;
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentContext();
+}
+
+// ***********************************************************************
+
+HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentDC();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
+ LPCSTR a)
+{
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ UNSUPPORTED("DGL_GetDefaultProcAddress")
+ return NULL;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_GetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetPixelFormat();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
+ LPCSTR a)
+{
+ PROC dglGetProcAddressD3D(LPCSTR a);
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+#ifdef _USE_GLD3_WGL
+ return _gldDriver.wglGetProcAddress(a);
+#else
+ return dglGetProcAddressD3D(a);
+#endif
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
+ HDC a,
+ HGLRC b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglMakeCurrent(a, b);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
+ HDC a,
+ int b,
+ BOOL c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_RealizeLayerPalette")
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ CONST COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_SetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
+ HDC a,
+ int b,
+ CONST PIXELFORMATDESCRIPTOR *c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if (IsValidPFD(b)) {
+ ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
+ dglSetPixelFormat(b);
+ return TRUE;
+ } else {
+ ddlogPrintf(DDLOG_ERROR,
+ "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
+ return FALSE;
+ }
+}
+
+// ***********************************************************************
+/*
+ * Share lists between two gl_context structures.
+ * This was added for WIN32 WGL function support, since wglShareLists()
+ * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
+ */
+//
+// Copied from GLD2.x. KeithH
+//
+static GLboolean _gldShareLists(
+ GLcontext *ctx1,
+ GLcontext *ctx2)
+{
+ /* Sanity check context pointers */
+ if (ctx1 == NULL || ctx2 == NULL)
+ return GL_FALSE;
+ /* Sanity check shared list pointers */
+ if (ctx1->Shared == NULL || ctx2->Shared == NULL)
+ return GL_FALSE;
+ /* Decrement reference count on sharee to release previous list */
+ ctx2->Shared->RefCount--;
+#if 0 /* 3DStudio exits on this memory release */
+ if (ctx2->Shared->RefCount == 0)
+ free_shared_state(ctx2, ctx2->Shared);
+#endif
+ /* Re-assign list from sharer to sharee and increment reference count */
+ ctx2->Shared = ctx1->Shared;
+ ctx1->Shared->RefCount++;
+ return GL_TRUE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
+ HGLRC a,
+ HGLRC b)
+{
+ DGL_ctx *dgl1, *dgl2;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Mesa supports shared lists, but you need to supply the shared
+ // GL context info when calling gl_create_context(). An auxiliary
+ // function gl_share_lists() has been added to update the shared
+ // list info after the GL contexts have been created. (DaveM)
+ dgl1 = dglGetContextAddress(a);
+ dgl2 = dglGetContextAddress(b);
+ if (dgl1->bAllocated && dgl2->bAllocated) {
+#ifdef _USE_GLD3_WGL
+ return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
+#else
+ return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
+#endif
+ }
+ return FALSE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
+ HDC a,
+ UINT b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+// ***********************************************************************
+// Note: This ResizeBuffers() function may be called from
+// either MESA glViewport() or GLD wglMakeCurrent().
+
+BOOL dglWglResizeBuffers(
+ GLcontext *ctx,
+ BOOL bDefaultDriver)
+{
+ DGL_ctx *dgl = NULL;
+ RECT rcScreenRect;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ IDirectDrawClipper *lpddClipper = NULL;
+ DWORD dwFlags;
+ HRESULT hResult;
+
+ DWORD dwMemoryType;
+
+ int i;
+ struct gl_texture_object *tObj;
+ struct gl_texture_image *image;
+
+ BOOL bWasFullscreen;
+ BOOL bSaveDesktop;
+ BOOL bFullScrnWin = FALSE;
+ DDSURFACEDESC2 ddsd2DisplayMode;
+
+ DDBLTFX ddbltfx;
+ POINT pt;
+ RECT rcDst;
+#ifdef _USE_GLD3_WGL
+ GLD_displayMode glddm;
+#endif
+
+#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Sanity checks
+ if (ctx == NULL)
+ return FALSE;
+ dgl = ctx->DriverCtx;
+ if (dgl == NULL)
+ return FALSE;
+
+ // Get the window size and calculate its dimensions
+ if (dgl->hWnd == NULL) {
+ // Check for non-window DC = memory DC ?
+ if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ }
+ else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ dwWidth = rcScreenRect.right - rcScreenRect.left;
+ dwHeight = rcScreenRect.bottom - rcScreenRect.top;
+ CopyRect(&dgl->rcScreenRect, &rcScreenRect);
+
+ // This will occur on Alt-Tab
+ if ((dwWidth == 0) && (dwHeight == 0)) {
+ //dgl->bCanRender = FALSE;
+ return TRUE; // No resize possible!
+ }
+
+ // Some apps zero only 1 dimension for non-visible window... (DaveM)
+ if ((dwWidth == 0) || (dwHeight == 0)) {
+ dwWidth = 8;
+ dwHeight = 8;
+ }
+
+ // Test to see if a resize is required.
+ // Note that the dimensions will be the same if a prior resize attempt failed.
+ if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
+ return TRUE; // No resize required
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
+#ifndef _USE_GLD3_WGL
+ // Work out where we want our surfaces created
+ dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
+#endif // _USE_GLD3_WGL
+
+ // Note previous fullscreen vs window display status
+ bWasFullscreen = dgl->bFullscreen;
+
+#ifdef _USE_GLD3_WGL
+ if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
+ if ( (dwWidth == glddm.Width) &&
+ (dwHeight == glddm.Height) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = glddm.Width;
+ dgl->dwModeHeight = glddm.Height;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > glddm.Width)
+ dgl->dwWidth = glddm.Width;
+ if (dgl->dwHeight > glddm.Height)
+ dgl->dwHeight = glddm.Height;
+#else // _USE_GLD3_WGL
+ // Window resize may have changed to fullscreen
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ dgl->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
+ dgl->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
+ dgl->dwHeight = ddsd2DisplayMode.dwHeight;
+#endif // _USE_GLD3_WGL
+
+ // Note if fullscreen vs window display has changed?
+ bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
+ // Save the desktop primary surface from being destroyed
+ // whenever remaining in windowed mode, since the stereo mode
+ // switches are expensive...
+
+#ifndef _USE_GLD3_WGL
+ // Don't need to re-allocate persistant buffers. (DaveM)
+ // Though we should clear the back buffers to hide artifacts.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+ return TRUE;
+ }
+
+ // Ensure all rendering is complete
+ if (ctx->Driver.Finish)
+ (*ctx->Driver.Finish)(ctx);
+ if (dgl->bSceneStarted == TRUE) {
+ IDirect3DDevice3_EndScene(dgl->lpDev3);
+ dgl->bSceneStarted = FALSE;
+ }
+#endif // _USE_GLD3_WGL
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw and DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifndef _USE_GLD3_WGL
+ // Release existing surfaces
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+#endif // _USE_GLD3_WGL
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+
+ // Set defaults
+ dgl->dwModeWidth = dgl->dwWidth;
+ dgl->dwModeHeight = dgl->dwHeight;
+
+#ifdef _USE_GLD3_WGL
+ if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
+ goto cleanup_and_return_with_error;
+#else // _USE_GLD3_WGL
+
+ if (dgl->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release the persistant DirectDraw primary surface
+ // if switching to fullscreen mode. So if application wants
+ // persistant display in fullscreen mode, a fullscreen-size
+ // window should be used instead via fullscreen-blit option.
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
+ dgl->dwModeWidth,
+ dgl->dwModeHeight,
+ dgl->dwBPP,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (dgl->bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ dgl->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ // Ditto if persistant DirectDraw primary
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ goto DoClipperOnly;
+
+ // WINDOWED
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
+ dgl->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Cache the primary surface for persistant DirectDraw state
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = dgl->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+DoClipperOnly:
+ // Update the window for the original clipper
+ if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
+ IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ RELEASE(lpddClipper);
+ }
+
+ if (dgl->bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ } else {
+ dgl->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Zbuffer
+ //
+ if (dgl->bDepthBuffer) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[dgl->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Create a z-buffer
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ dgl->lpDepth4),
+ "dglResize: Attach Zbuffer");
+
+ }
+
+ // Clear the newly resized back buffers for the window client area.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+
+ //
+ // Now that we have a zbuffer we can create the 3D device
+ //
+ hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
+ bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ &dgl->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(dgl);
+
+ //
+ // Viewport
+ //
+ hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Initialise the viewport
+ dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
+ dgl->d3dViewport.dwX = 0;
+ dgl->d3dViewport.dwY = 0;
+ dgl->d3dViewport.dwWidth = dgl->dwWidth;
+ dgl->d3dViewport.dwHeight = dgl->dwHeight;
+ dgl->d3dViewport.dvClipX = 0;
+ dgl->d3dViewport.dvClipY = 0;
+ dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
+ dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
+// dgl->d3dViewport.dvMinZ = 0.0f;
+// dgl->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
+ "dglResize: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // (Re)Initialise all the Direct3D renderstates
+ dglInitStateD3D(ctx);
+
+ // Now we have to recreate all of our textures (+ mipmaps).
+ // Walk over all textures in hash table
+ // XXX what about the default texture objects (id=0)?
+ {
+ struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
+ GLuint id;
+ for (id = _mesa_HashFirstEntry(textures);
+ id;
+ id = _mesa_HashNextEntry(textures, id)) {
+ tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
+ if (tObj->DriverData) {
+ // We could call our TexImage function directly, but it's
+ // safer to use the driver pointer.
+ for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+ image = tObj->Image[i];
+ if (image) {
+ switch (tObj->Dimensions){
+ case 1:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
+ break;
+ case 2:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Re-Bind each texture Unit
+ for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
+ tObj = ctx->Texture.Unit[i].Current;
+ if (tObj) {
+ DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
+ hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
+ }
+ }
+ }
+#endif // _USE_GLD3_WGL
+
+ dgl->bCanRender = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // SUCCESS.
+ return TRUE;
+
+cleanup_and_return_with_error:
+ // Relase all interfaces before returning.
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyDrawable(dgl);
+#else // _USE_GLD3_WGL
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+
+#undef DDLOG_CRITICAL_OR_WARN
+#endif // _USE_GLD3_WGL
+
+ // Mark context as not being able to render
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for bitmap fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+/*****************************************************************************
+**
+** InvertGlyphBitmap.
+**
+** Invert the bitmap so that it suits OpenGL's representation.
+** Each row starts on a double word boundary.
+**
+*****************************************************************************/
+
+static void InvertGlyphBitmap(
+ int w,
+ int h,
+ DWORD *fptr,
+ DWORD *tptr)
+{
+ int dWordsInRow = (w+31)/32;
+ int i, j;
+ DWORD *tmp = tptr;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ tptr += ((h-1)*dWordsInRow);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < dWordsInRow; j++) {
+ *(tptr + j) = *(fptr + j);
+ }
+ tptr -= dWordsInRow;
+ fptr += dWordsInRow;
+ }
+}
+
+// ***********************************************************************
+
+/*****************************************************************************
+ * wglUseFontBitmaps
+ *
+ * Converts a subrange of the glyphs in a GDI font to OpenGL display
+ * lists.
+ *
+ * Extended to support any GDI font, not just TrueType fonts. (DaveM)
+ *
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
+ HDC hDC,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ int i, ox, oy, ix, iy;
+ int w, h;
+ int iBufSize, iCurBufSize = 0;
+ DWORD *bitmapBuffer = NULL;
+ DWORD *invertedBitmapBuffer = NULL;
+ BOOL bSuccessOrFail = TRUE;
+ BOOL bTrueType = FALSE;
+ TEXTMETRIC tm;
+ GLYPHMETRICS gm;
+ RASTERIZER_STATUS rs;
+ MAT2 mat;
+ SIZE size;
+ RECT rect;
+ HDC hDCMem;
+ HBITMAP hBitmap;
+ BITMAPINFO bmi;
+ HFONT hFont;
+
+ // Validate SciTech DirectGL license
+ if (!dglValidate())
+ return FALSE;
+
+ // Set up a unity matrix.
+ ZeroMemory(&mat, sizeof(mat));
+ mat.eM11.value = 1;
+ mat.eM22.value = 1;
+
+ // Test to see if selected font is TrueType or not
+ ZeroMemory(&tm, sizeof(tm));
+ if (!GetTextMetrics(hDC, &tm)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
+ return (FALSE);
+ }
+ bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
+
+ // Test to see if TRUE-TYPE capabilities are installed
+ // (only necessary if TrueType font selected)
+ ZeroMemory(&rs, sizeof(rs));
+ if (bTrueType) {
+ if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
+ return (FALSE);
+ }
+ if (!(rs.wFlags & TT_ENABLED)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
+ return (FALSE);
+ }
+ }
+
+ // Trick to get the current font handle
+ hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+ SelectObject(hDC, hFont);
+
+ // Have memory device context available for holding bitmaps of font glyphs
+ hDCMem = CreateCompatibleDC(hDC);
+ SelectObject(hDCMem, hFont);
+ SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
+ SetBkColor(hDCMem, 0);
+
+ for (i = first; (DWORD) i < (first + count); i++) {
+ // Find out how much space is needed for the bitmap so we can
+ // Set the buffer size correctly.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap size of glyph
+ iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ 0, NULL, &mat);
+ if (iBufSize == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+ else {
+ // Use generic GDI support to compute bitmap size of glyph
+ w = tm.tmMaxCharWidth;
+ h = tm.tmHeight;
+ if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
+ w = size.cx;
+ h = size.cy;
+ }
+ iBufSize = w * h;
+ // Use DWORD multiple for compatibility
+ iBufSize += 3;
+ iBufSize /= 4;
+ iBufSize *= 4;
+ }
+
+ // If we need to allocate Larger Buffers, then do so - but allocate
+ // An extra 50 % so that we don't do too many mallocs !
+ if (iBufSize > iCurBufSize) {
+ if (bitmapBuffer) {
+ __wglFree(bitmapBuffer);
+ }
+ if (invertedBitmapBuffer) {
+ __wglFree(invertedBitmapBuffer);
+ }
+
+ iCurBufSize = iBufSize * 2;
+ bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+ invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+
+ if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+
+ // If we fail to get the Glyph data, delete the display lists
+ // Created so far and return FALSE.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap of glyph
+ if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ w = gm.gmBlackBoxX;
+ h = gm.gmBlackBoxY;
+ ox = gm.gmptGlyphOrigin.x;
+ oy = gm.gmptGlyphOrigin.y;
+ ix = gm.gmCellIncX;
+ iy = gm.gmCellIncY;
+ }
+ else {
+ // Use generic GDI support to create bitmap of glyph
+ ZeroMemory(bitmapBuffer, iBufSize);
+
+ if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
+ // Only create bitmaps for actual font glyphs
+ hBitmap = CreateBitmap(w, h, 1, 1, NULL);
+ SelectObject(hDCMem, hBitmap);
+ // Make bitmap of current font glyph
+ SetRect(&rect, 0, 0, w, h);
+ DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
+ // Make copy of bitmap in our local buffer
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = -h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
+ DeleteObject(hBitmap);
+ }
+ else {
+ // Otherwise use empty display list for non-existing glyph
+ iBufSize = 0;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ ox = 0;
+ oy = tm.tmDescent;
+ ix = w;
+ iy = 0;
+ }
+
+ // Create an OpenGL display list.
+ _GLD_glNewList((listBase + i), GL_COMPILE);
+
+ // Some fonts have no data for the space character, yet advertise
+ // a non-zero size.
+ if (0 == iBufSize) {
+ _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
+ } else {
+ // Invert the Glyph data.
+ InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
+
+ // Render an OpenGL bitmap and invert the origin.
+ _GLD_glBitmap(w, h,
+ (GLfloat) ox, (GLfloat) (h-oy),
+ (GLfloat) ix, (GLfloat) iy,
+ (GLubyte *) invertedBitmapBuffer);
+ }
+
+ // Close this display list.
+ _GLD_glEndList();
+ }
+
+ if (bSuccessOrFail == FALSE) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
+ _GLD_glDeleteLists((i+listBase), (i-first));
+ }
+
+ // Release resources used
+ DeleteObject(hFont);
+ DeleteDC(hDCMem);
+
+ if (bitmapBuffer)
+ __wglFree(bitmapBuffer);
+ if (invertedBitmapBuffer)
+ __wglFree(invertedBitmapBuffer);
+
+ return(bSuccessOrFail);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
+ HDC a,
+ DWORD b,
+ DWORD c,
+ DWORD d)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for outline TrueType fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+void * __wglRealloc(
+ void *oldPtr,
+ size_t newSize)
+{
+ void *newPtr = NULL;
+
+ if (newSize != 0) {
+ newPtr = (void *) GlobalAlloc(GPTR, newSize);
+ if (oldPtr && newPtr) {
+ DWORD oldSize = GlobalSize(oldPtr);
+
+ memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
+ GlobalFree(oldPtr);
+ }
+ } else if (oldPtr) {
+ GlobalFree(oldPtr);
+ }
+ if (newPtr == NULL) {
+ return NULL; /* XXX out of memory error */
+ }
+ return newPtr;
+}
+
+// ***********************************************************************
+
+
+/*****************************************************************************
+ * wglUseFontOutlinesW
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
+ chordalDeviation, extrusion, format, lpgmf);
+}
+
+/*****************************************************************************
+ * wglUseFontOutlinesA
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
+ {
+ DWORD glyphIndex;
+ UCHAR* glyphBuf;
+ DWORD glyphBufSize;
+
+
+ /*
+ * Flush any previous OpenGL errors. This allows us to check for
+ * new errors so they can be reported via the function return value.
+ */
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+
+ /*
+ * Make sure that the current font can be sampled accurately.
+ */
+ hNewFont = CreateHighResolutionFont(hDC);
+ if (!hNewFont)
+ return FALSE;
+
+ hOldFont = SelectObject(hDC, hNewFont);
+ if (!hOldFont)
+ return FALSE;
+
+ /*
+ * Preallocate a buffer for the outline data, and track its size:
+ */
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+
+ /*
+ * Process each glyph in the given range:
+ */
+ for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+ {
+ GLYPHMETRICS glyphMetrics;
+ DWORD glyphSize;
+ static MAT2 matrix =
+ {
+ {0, 1}, {0, 0},
+ {0, 0}, {0, 1}
+ };
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat =
+ &glyphMetricsFloatArray[glyphIndex - first];
+
+
+ /*
+ * Determine how much space is needed to store the glyph's
+ * outlines. If our glyph buffer isn't large enough,
+ * resize it.
+ */
+ glyphSize = GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ 0,
+ NULL,
+ &matrix
+ );
+ if (glyphSize < 0)
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ if (glyphSize > glyphBufSize)
+ {
+ __wglFree(glyphBuf);
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+ }
+
+
+ /*
+ * Get the glyph's outlines.
+ */
+ if (GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ glyphBufSize,
+ glyphBuf,
+ &matrix
+ ) < 0)
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+
+ glyphMetricsFloat->gmfBlackBoxX =
+ (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
+ glyphMetricsFloat->gmfBlackBoxY =
+ (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.x =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.y =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncX =
+ (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncY =
+ (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
+
+ /*
+ * Turn the glyph into a display list:
+ */
+ if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
+ glyphBuf,
+ glyphSize,
+ glyphMetricsFloat,
+ chordalDeviation + ScaleFactor,
+ extrusion,
+ format))
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+ /*
+ * Clean up temporary storage and return. If an error occurred,
+ * clear all OpenGL error flags and return FAILURE status;
+ * otherwise just return SUCCESS.
+ */
+ __wglFree(glyphBuf);
+
+ SelectObject(hDC, hOldFont);
+
+ if (_GLD_glGetError() == GL_NO_ERROR)
+ return TRUE; /*WGL_STATUS_SUCCESS*/
+ else
+ {
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+
+/*****************************************************************************
+ * CreateHighResolutionFont
+ *
+ * Gets metrics for the current font and creates an equivalent font
+ * scaled to the design units of the font.
+ *
+ *****************************************************************************/
+
+static HFONT
+CreateHighResolutionFont(HDC hDC)
+ {
+ UINT otmSize;
+ OUTLINETEXTMETRIC *otm;
+ LONG fontHeight, fontWidth, fontUnits;
+ LOGFONT logFont;
+
+ otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
+ if (otmSize == 0)
+ return NULL;
+
+ otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
+ if (otm == NULL)
+ return NULL;
+
+ otm->otmSize = otmSize;
+ if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
+ return NULL;
+
+ fontHeight = otm->otmTextMetrics.tmHeight -
+ otm->otmTextMetrics.tmInternalLeading;
+ fontWidth = otm->otmTextMetrics.tmAveCharWidth;
+ fontUnits = (LONG) otm->otmEMSquare;
+
+ ScaleFactor = 1.0F / (FLOAT) fontUnits;
+
+ logFont.lfHeight = - ((LONG) fontUnits);
+ logFont.lfWidth = (LONG)
+ ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfWeight = otm->otmTextMetrics.tmWeight;
+ logFont.lfItalic = otm->otmTextMetrics.tmItalic;
+ logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
+ logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
+ logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
+ logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logFont.lfQuality = DEFAULT_QUALITY;
+ logFont.lfPitchAndFamily =
+ otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
+ strcpy(logFont.lfFaceName,
+ (char *)otm + (int)otm->otmpFaceName);
+
+ hNewFont = CreateFontIndirect(&logFont);
+ if (hNewFont == NULL)
+ return NULL;
+
+ __wglFree(otm);
+
+ return hNewFont;
+ }
+
+
+
+/*****************************************************************************
+ * MakeDisplayListFromGlyph
+ *
+ * Converts the outline of a glyph to an OpenGL display list.
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+MakeDisplayListFromGlyph( IN DWORD listName,
+ IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ int status;
+
+ _GLD_glNewList(listName, GL_COMPILE);
+ status = DrawGlyph( glyphBuf,
+ glyphSize,
+ chordalDeviation,
+ extrusion,
+ format);
+
+ _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
+ glyphMetricsFloat->gmfCellIncY,
+ 0.0F);
+ _GLD_glEndList();
+
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * DrawGlyph
+ *
+ * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
+ * as needed, and then draws the glyph. Tessellation of the quadratic splines
+ * in the outline is controlled by "chordalDeviation", and the drawing
+ * primitives (lines or polygons) are selected by "format".
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+DrawGlyph( IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ INT status = 0;
+ FLOAT* p;
+ DWORD loop;
+ DWORD point;
+ GLUtesselator* tess = NULL;
+
+
+ /*
+ * Initialize the global buffer into which we place the outlines:
+ */
+ if (!InitLineBuf())
+ goto exit;
+
+
+ /*
+ * Convert the glyph outlines to a set of polyline loops.
+ * (See MakeLinesFromGlyph() for the format of the loop data
+ * structure.)
+ */
+ if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
+ goto exit;
+ p = LineBuf;
+
+
+ /*
+ * Now draw the loops in the appropriate format:
+ */
+ if (format == WGL_FONT_LINES)
+ {
+ /*
+ * This is the easy case. Just draw the outlines.
+ */
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ _GLD_glBegin(GL_LINE_LOOP);
+ for (point = (DWORD) *p++; point; --point)
+ {
+ _GLD_glVertex2fv(p);
+ p += 2;
+ }
+ _GLD_glEnd();
+ }
+ status = 1;
+ }
+
+ else if (format == WGL_FONT_POLYGONS)
+ {
+ double v[3];
+ FLOAT *save_p = p;
+ GLfloat z_value;
+
+ /*
+ * This is the hard case. We have to set up a tessellator
+ * to convert the outlines into a set of polygonal
+ * primitives, which the tessellator passes to some
+ * auxiliary routines for drawing.
+ */
+ if (!LoadGLUTesselator())
+ goto exit;
+ if (!InitVertBuf())
+ goto exit;
+ if (!(tess = gluNewTessProc()))
+ goto exit;
+ gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
+ gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
+ (void(CALLBACK *)()) TessVertexOutData);
+ gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
+ gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
+ gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
+ gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
+
+ TessErrorOccurred = 0;
+ _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
+ v[2] = 0.0;
+ z_value = 0.0f;
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ gluTessBeginContourProc(tess);
+
+ for (point = (DWORD) *p++; point; --point)
+ {
+ v[0] = p[0];
+ v[1] = p[1];
+ gluTessVertexProc(tess, v, p);
+ p += 2;
+ }
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+
+ status = !TessErrorOccurred;
+
+ /* Extrusion code */
+ if (extrusion) {
+ DWORD loops;
+ GLfloat thickness = (GLfloat) -extrusion;
+ FLOAT *vert, *vert2;
+ DWORD count;
+
+ p = save_p;
+ loops = (DWORD) *p++;
+
+ for (loop = 0; loop < loops; loop++) {
+ GLfloat dx, dy, len;
+ DWORD last;
+
+ count = (DWORD) *p++;
+ _GLD_glBegin(GL_QUAD_STRIP);
+
+ /* Check if the first and last vertex are identical
+ * so we don't draw the same quad twice.
+ */
+ vert = p + (count-1)*2;
+ last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
+
+ for (point = 0; point <= last; point++) {
+ vert = p + 2 * (point % last);
+ vert2 = p + 2 * ((point+1) % last);
+
+ dx = vert[0] - vert2[0];
+ dy = vert[1] - vert2[1];
+ len = (GLfloat)sqrt(dx * dx + dy * dy);
+
+ _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], thickness);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], 0.0f);
+ }
+
+ _GLD_glEnd();
+ p += count*2;
+ }
+
+ /* Draw the back face */
+ p = save_p;
+ v[2] = thickness;
+ _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
+ gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
+
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ count = (DWORD) *p++;
+
+ gluTessBeginContourProc(tess);
+
+ for (point = 0; point < count; point++)
+ {
+ vert = p + ((count-point-1)<<1);
+ v[0] = vert[0];
+ v[1] = vert[1];
+ gluTessVertexProc(tess, v, vert);
+ }
+ p += count*2;
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+ }
+
+#if DEBUG
+ if (TessErrorOccurred)
+ printf("Tessellation error %s\n",
+ gluErrorString(TessErrorOccurred));
+#endif
+ }
+
+
+exit:
+ FreeLineBuf();
+ if (tess)
+ gluDeleteTessProc(tess);
+ // UnloadGLUTesselator();
+ FreeVertBuf();
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * LoadGLUTesselator
+ *
+ * Maps the glu32.dll module and gets function pointers for the
+ * tesselator functions.
+ *****************************************************************************/
+
+static BOOL
+LoadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ return TRUE;
+
+ {
+ extern HINSTANCE hInstanceOpenGL;
+ char *gluName = "GLU32.DLL";
+// char name[256];
+// char *ptr;
+// int len;
+
+/*
+ len = GetModuleFileName(hInstanceOpenGL, name, 255);
+ if (len != 0)
+ {
+ ptr = name+len-1;
+ while (ptr > name && *ptr != '\\')
+ ptr--;
+ if (*ptr == '\\')
+ ptr++;
+ if (!stricmp(ptr, "cosmogl.dll"))
+ {
+ gluName = "COSMOGLU.DLL";
+ }
+ else if (!stricmp(ptr, "opengl32.dll"))
+ {
+ gluName = "GLU32.DLL";
+ }
+ }
+*/
+ if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
+ return FALSE;
+ }
+
+ if ((gluNewTessProc = (gluNewTessProto)
+ GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
+ return FALSE;
+
+ if ((gluDeleteTessProc = (gluDeleteTessProto)
+ GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginContourProc = (gluTessBeginContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessVertexProc = (gluTessVertexProto)
+ GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndContourProc = (gluTessEndContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessPropertyProc = (gluTessPropertyProto)
+ GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
+ return FALSE;
+
+ if ((gluTessNormalProc = (gluTessNormalProto)
+ GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
+ return FALSE;
+
+ if ((gluTessCallbackProc = (gluTessCallbackProto)
+ GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+
+/*****************************************************************************
+ * UnloadGLUTesselator
+ *
+ * Unmaps the glu32.dll module.
+ *****************************************************************************/
+
+static BOOL
+UnloadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ if (FreeLibrary(gluModuleHandle) == FALSE)
+ return FALSE;
+ gluModuleHandle = NULL;
+ }
+
+
+
+/*****************************************************************************
+ * TessVertexOut
+ *
+ * Used by tessellator to handle output vertexes.
+ *****************************************************************************/
+
+static void CALLBACK
+TessVertexOut(FLOAT p[3])
+ {
+ GLfloat v[2];
+
+ v[0] = p[0] * ScaleFactor;
+ v[1] = p[1] * ScaleFactor;
+ _GLD_glVertex2fv(v);
+ }
+
+static void CALLBACK
+TessVertexOutData(FLOAT p[3], GLfloat z)
+{
+ GLfloat v[3];
+
+ v[0] = (GLfloat) p[0];
+ v[1] = (GLfloat) p[1];
+ v[2] = z;
+ _GLD_glVertex3fv(v);
+}
+
+
+/*****************************************************************************
+ * TessCombine
+ *
+ * Used by tessellator to handle self-intersecting contours and degenerate
+ * geometry.
+ *****************************************************************************/
+
+static void CALLBACK
+TessCombine(double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData)
+ {
+ if (!AppendToVertBuf((FLOAT) coords[0])
+ || !AppendToVertBuf((FLOAT) coords[1])
+ || !AppendToVertBuf((FLOAT) coords[2]))
+ TessErrorOccurred = GL_OUT_OF_MEMORY;
+ *outData = VertBuf + (VertBufIndex - 3);
+ }
+
+
+
+/*****************************************************************************
+ * TessError
+ *
+ * Saves the last tessellator error code in the global TessErrorOccurred.
+ *****************************************************************************/
+
+static void CALLBACK
+TessError(GLenum error)
+ {
+ TessErrorOccurred = error;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromGlyph
+ *
+ * Converts the outline of a glyph from the TTPOLYGON format to a simple
+ * array of floating-point values containing one or more loops.
+ *
+ * The first element of the output array is a count of the number of loops.
+ * The loop data follows this count. Each loop consists of a count of the
+ * number of vertices it contains, followed by the vertices. Each vertex
+ * is an X and Y coordinate. For example, a single triangle might be
+ * described by this array:
+ *
+ * 1., 3., 0., 0., 1., 0., 0., 1.
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * #loops #verts x1 y1 x2 y2 x3 y3
+ *
+ * A two-loop glyph would look like this:
+ *
+ * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
+ *
+ * Line segments from the TTPOLYGON are transferred to the output array in
+ * the obvious way. Quadratic splines in the TTPOLYGON are converted to
+ * collections of line segments
+ *****************************************************************************/
+
+static int
+MakeLinesFromGlyph(IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation)
+ {
+ UCHAR* p;
+ int status = 0;
+
+
+ /*
+ * Pick up all the polygons (aka loops) that make up the glyph:
+ */
+ if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
+ goto exit;
+
+ p = glyphBuf;
+ while (p < glyphBuf + glyphSize)
+ {
+ if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
+ goto exit;
+ LineBuf[0] += 1.0F; /* increment loop count */
+ }
+
+ status = 1;
+
+exit:
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolygon
+ *
+ * Converts a TTPOLYGONHEADER and its associated curve structures into a
+ * single polyline loop in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
+ IN FLOAT chordalDeviation)
+ {
+ DWORD polySize;
+ UCHAR* polyStart;
+ DWORD vertexCountIndex;
+
+ /*
+ * Record where the polygon data begins, and where the loop's
+ * vertex count resides:
+ */
+ polyStart = *pp;
+ vertexCountIndex = LineBufIndex;
+ if (!AppendToLineBuf(0.0F))
+ return 0;
+
+ /*
+ * Extract relevant data from the TTPOLYGONHEADER:
+ */
+ polySize = GetDWord(pp);
+ if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
+ return 0;
+ LineBuf[vertexCountIndex] += 1.0F;
+
+ /*
+ * Process each of the TTPOLYCURVE structures in the polygon:
+ */
+ while (*pp < polyStart + polySize)
+ if (!MakeLinesFromTTPolycurve( pp,
+ vertexCountIndex,
+ chordalDeviation))
+ return 0;
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolyCurve
+ *
+ * Converts the lines and splines in a single TTPOLYCURVE structure to points
+ * in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviation)
+ {
+ WORD type;
+ WORD pointCount;
+
+
+ /*
+ * Pick up the relevant fields of the TTPOLYCURVE structure:
+ */
+ type = (WORD) GetWord(pp);
+ pointCount = (WORD) GetWord(pp);
+
+ /*
+ * Convert the "curve" to line segments:
+ */
+ if (type == TT_PRIM_LINE)
+ return MakeLinesFromTTLine( pp,
+ vertexCountIndex,
+ pointCount);
+ else if (type == TT_PRIM_QSPLINE)
+ return MakeLinesFromTTQSpline( pp,
+ vertexCountIndex,
+ pointCount,
+ chordalDeviation);
+ else
+ return 0;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTLine
+ *
+ * Converts points from the polyline in a TT_PRIM_LINE structure to
+ * equivalent points in the global LineBuf.
+ *****************************************************************************/
+static int
+MakeLinesFromTTLine( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount)
+ {
+ /*
+ * Just copy the line segments into the line buffer (converting
+ * type as we go):
+ */
+ LineBuf[vertexCountIndex] += pointCount;
+ while (pointCount--)
+ {
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
+ || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTQSpline
+ *
+ * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
+ * structure to polyline points in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount,
+ IN FLOAT chordalDeviation)
+ {
+ FLOAT x0, y0, x1, y1, x2, y2;
+ WORD point;
+
+ /*
+ * Process each of the non-interpolated points in the outline.
+ * To do this, we need to generate two interpolated points (the
+ * start and end of the arc) for each non-interpolated point.
+ * The first interpolated point is always the one most recently
+ * stored in LineBuf, so we just extract it from there. The
+ * second interpolated point is either the average of the next
+ * two points in the QSpline, or the last point in the QSpline
+ * if only one remains.
+ */
+ for (point = 0; point < pointCount - 1; ++point)
+ {
+ x0 = LineBuf[LineBufIndex - 2];
+ y0 = LineBuf[LineBufIndex - 1];
+
+ x1 = (FLOAT) GetFixed(pp);
+ y1 = (FLOAT) GetFixed(pp);
+
+ if (point == pointCount - 2)
+ {
+ /*
+ * This is the last arc in the QSpline. The final
+ * point is the end of the arc.
+ */
+ x2 = (FLOAT) GetFixed(pp);
+ y2 = (FLOAT) GetFixed(pp);
+ }
+ else
+ {
+ /*
+ * Peek at the next point in the input to compute
+ * the end of the arc:
+ */
+ x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
+ y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
+ /*
+ * Push the point back onto the input so it will
+ * be reused as the next off-curve point:
+ */
+ *pp -= 8;
+ }
+
+ if (!MakeLinesFromArc( x0, y0,
+ x1, y1,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviation * chordalDeviation))
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromArc
+ *
+ * Subdivides one arc of a quadratic spline until the chordal deviation
+ * tolerance requirement is met, then places the resulting set of line
+ * segments in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromArc( IN FLOAT x0,
+ IN FLOAT y0,
+ IN FLOAT x1,
+ IN FLOAT y1,
+ IN FLOAT x2,
+ IN FLOAT y2,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviationSquared)
+ {
+ FLOAT x01;
+ FLOAT y01;
+ FLOAT x12;
+ FLOAT y12;
+ FLOAT midPointX;
+ FLOAT midPointY;
+ FLOAT deltaX;
+ FLOAT deltaY;
+
+ /*
+ * Calculate midpoint of the curve by de Casteljau:
+ */
+ x01 = 0.5F * (x0 + x1);
+ y01 = 0.5F * (y0 + y1);
+ x12 = 0.5F * (x1 + x2);
+ y12 = 0.5F * (y1 + y2);
+ midPointX = 0.5F * (x01 + x12);
+ midPointY = 0.5F * (y01 + y12);
+
+
+ /*
+ * Estimate chordal deviation by the distance from the midpoint
+ * of the curve to its non-interpolated control point. If this
+ * distance is greater than the specified chordal deviation
+ * constraint, then subdivide. Otherwise, generate polylines
+ * from the three control points.
+ */
+ deltaX = midPointX - x1;
+ deltaY = midPointY - y1;
+ if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
+ {
+ MakeLinesFromArc( x0, y0,
+ x01, y01,
+ midPointX, midPointY,
+ vertexCountIndex,
+ chordalDeviationSquared);
+
+ MakeLinesFromArc( midPointX, midPointY,
+ x12, y12,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviationSquared);
+ }
+ else
+ {
+ /*
+ * The "pen" is already at (x0, y0), so we don't need to
+ * add that point to the LineBuf.
+ */
+ if (!AppendToLineBuf(x1)
+ || !AppendToLineBuf(y1)
+ || !AppendToLineBuf(x2)
+ || !AppendToLineBuf(y2))
+ return 0;
+ LineBuf[vertexCountIndex] += 2.0F;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitLineBuf
+ *
+ * Initializes the global LineBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitLineBuf(void)
+ {
+ if (!(LineBuf = (FLOAT*)
+ __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ LineBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitVertBuf
+ *
+ * Initializes the global VertBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitVertBuf(void)
+ {
+ if (!(VertBuf = (FLOAT*)
+ __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ VertBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToLineBuf
+ *
+ * Appends one floating-point value to the global LineBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *****************************************************************************/
+
+static int
+AppendToLineBuf(FLOAT value)
+ {
+ if (LineBufIndex >= LineBufSize)
+ {
+ FLOAT* f;
+
+ f = (FLOAT*) __wglRealloc(LineBuf,
+ (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
+ if (!f)
+ return 0;
+ LineBuf = f;
+ }
+ LineBuf[LineBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToVertBuf
+ *
+ * Appends one floating-point value to the global VertBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *
+ * Note that we can't realloc this one, because the tessellator is using
+ * pointers into it.
+ *****************************************************************************/
+
+static int
+AppendToVertBuf(FLOAT value)
+ {
+ if (VertBufIndex >= VertBufSize)
+ return 0;
+ VertBuf[VertBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * FreeLineBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeLineBuf(void)
+ {
+ if (LineBuf)
+ {
+ __wglFree(LineBuf);
+ LineBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * FreeVertBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeVertBuf(void)
+ {
+ if (VertBuf)
+ {
+ __wglFree(VertBuf);
+ VertBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * GetWord
+ *
+ * Fetch the next 16-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[1] << 8) + (*p)[0];
+ *p += 2;
+ return value;
+ }
+
+
+
+/*****************************************************************************
+ * GetDWord
+ *
+ * Fetch the next 32-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetDWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
+ *p += 4;
+ return value;
+ }
+
+
+
+
+/*****************************************************************************
+ * GetFixed
+ *
+ * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
+ * convert it to floating-point, and increment the stream pointer to the next
+ * unscanned byte.
+ *****************************************************************************/
+
+static double GetFixed(
+ UCHAR** p)
+{
+ long hiBits, loBits;
+ double value;
+
+ loBits = GetWord(p);
+ hiBits = GetWord(p);
+ value = (double) ((hiBits << 16) | loBits) / 65536.0;
+
+ return value * ScaleFactor;
+}
+
+// ***********************************************************************
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h
new file mode 100644
index 000000000..aac041033
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dglwgl.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#ifndef __DGLWGL_H
+#define __DGLWGL_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <GL\gl.h>
+
+#include "dglcontext.h"
+#include "dglglobals.h"
+#include "dglmacros.h"
+#include "ddlog.h"
+#include "dglpf.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PROC proc;
+ char *name;
+} DGL_extension;
+
+#ifndef __MINGW32__
+/* XXX why is this here?
+ * It should probaby be somewhere in src/mesa/drivers/windows/
+ */
+#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_WINGDI_H) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP) && !defined(BUILD_FOR_SNAP)
+# define WGL_FONT_LINES 0
+# define WGL_FONT_POLYGONS 1
+#ifndef _GNU_H_WINDOWS32_FUNCTIONS
+# ifdef UNICODE
+# define wglUseFontBitmaps wglUseFontBitmapsW
+# define wglUseFontOutlines wglUseFontOutlinesW
+# else
+# define wglUseFontBitmaps wglUseFontBitmapsA
+# define wglUseFontOutlines wglUseFontOutlinesA
+# endif /* !UNICODE */
+#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
+typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
+typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
+typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
+#if !defined(GLX_USE_MESA)
+#include <GL/mesa_wgl.h>
+#endif
+#endif
+#endif /* !__MINGW32__ */
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _USE_GLD3_WGL
+int APIENTRY DGL_ChoosePixelFormat(HDC a, CONST PIXELFORMATDESCRIPTOR *ppfd);
+BOOL APIENTRY DGL_CopyContext(HGLRC a, HGLRC b, UINT c);
+HGLRC APIENTRY DGL_CreateContext(HDC a);
+HGLRC APIENTRY DGL_CreateLayerContext(HDC a, int b);
+BOOL APIENTRY DGL_DeleteContext(HGLRC a);
+BOOL APIENTRY DGL_DescribeLayerPlane(HDC a, int b, int c, UINT d, LPLAYERPLANEDESCRIPTOR e);
+int APIENTRY DGL_DescribePixelFormat(HDC a, int b, UINT c, LPPIXELFORMATDESCRIPTOR d);
+HGLRC APIENTRY DGL_GetCurrentContext(void);
+HDC APIENTRY DGL_GetCurrentDC(void);
+PROC APIENTRY DGL_GetDefaultProcAddress(LPCSTR a);
+int APIENTRY DGL_GetLayerPaletteEntries(HDC a, int b, int c, int d, COLORREF *e);
+int APIENTRY DGL_GetPixelFormat(HDC a);
+PROC APIENTRY DGL_GetProcAddress(LPCSTR a);
+BOOL APIENTRY DGL_MakeCurrent(HDC a, HGLRC b);
+BOOL APIENTRY DGL_RealizeLayerPalette(HDC a, int b, BOOL c);
+int APIENTRY DGL_SetLayerPaletteEntries(HDC a, int b, int c, int d, CONST COLORREF *e);
+BOOL APIENTRY DGL_SetPixelFormat(HDC a, int b, CONST PIXELFORMATDESCRIPTOR *c);
+BOOL APIENTRY DGL_ShareLists(HGLRC a, HGLRC b);
+BOOL APIENTRY DGL_SwapBuffers(HDC a);
+BOOL APIENTRY DGL_SwapLayerBuffers(HDC a, UINT b);
+BOOL APIENTRY DGL_UseFontBitmapsA(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontBitmapsW(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontOutlinesA(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+BOOL APIENTRY DGL_UseFontOutlinesW(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+#endif //_USE_GLD3_WGL
+
+BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dll_main.c b/mesalib/src/mesa/drivers/windows/gldirect/dll_main.c
new file mode 100644
index 000000000..1d7ac64f4
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dll_main.c
@@ -0,0 +1,817 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+// INITGUID must only be defined once.
+// Don't put it in a shared header file!
+// GLD3 uses dxguid.lib, so INITGUID must *not* be used!
+#ifndef _USE_GLD3_WGL
+#define INITGUID
+#endif // _USE_GLD3_WGL
+
+#include "dllmain.h"
+
+//#include "snap/graphics.h"
+//#include "drvlib/os/os.h"
+
+#ifdef _USE_GLD3_WGL
+typedef void (APIENTRY *LPDGLSPLASHSCREEN)(int, int, char*);
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+BOOL bInitialized = FALSE; // callback driver initialized?
+BOOL bExited = FALSE; // callback driver exited this instance?
+HINSTANCE hInstanceDll = NULL; // DLL instance handle
+
+static BOOL bDriverValidated = FALSE; // prior validation status
+static BOOL bSplashScreen = TRUE; // Splash Screen ?
+static BOOL bValidINIFound = FALSE; // Have we found a valid INI file?
+
+HHOOK hKeyHook = NULL; // global keyboard handler hook
+
+// Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+int _gld_bMultiThreaded = FALSE;
+
+// ***********************************************************************
+
+DWORD dwLogging = 0; // Logging flag
+DWORD dwDebugLevel = 0; // Log debug level
+
+char szLogPath[_MAX_PATH] = {"\0"}; // Log file path
+char szSNAPPath[_MAX_PATH] = {"\0"}; // SNAP driver path
+
+#ifndef _USE_GLD3_WGL
+DGL_wglFuncs wglFuncs = {
+ sizeof(DGL_wglFuncs),
+ DGL_ChoosePixelFormat,
+ DGL_CopyContext,
+ DGL_CreateContext,
+ DGL_CreateLayerContext,
+ DGL_DeleteContext,
+ DGL_DescribeLayerPlane,
+ DGL_DescribePixelFormat,
+ DGL_GetCurrentContext,
+ DGL_GetCurrentDC,
+ DGL_GetDefaultProcAddress,
+ DGL_GetLayerPaletteEntries,
+ DGL_GetPixelFormat,
+ DGL_GetProcAddress,
+ DGL_MakeCurrent,
+ DGL_RealizeLayerPalette,
+ DGL_SetLayerPaletteEntries,
+ DGL_SetPixelFormat,
+ DGL_ShareLists,
+ DGL_SwapBuffers,
+ DGL_SwapLayerBuffers,
+ DGL_UseFontBitmapsA,
+ DGL_UseFontBitmapsW,
+ DGL_UseFontOutlinesA,
+ DGL_UseFontOutlinesW,
+};
+
+DGL_mesaFuncs mesaFuncs = {
+ sizeof(DGL_mesaFuncs),
+};
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+typedef struct {
+ DWORD dwDriver; // 0=SciTech SW, 1=Direct3D SW, 2=Direct3D HW
+ BOOL bMipmapping; // 0=off, 1=on
+ BOOL bMultitexture; // 0=off, 1=on
+ BOOL bWaitForRetrace; // 0=off, 1=on
+ BOOL bFullscreenBlit; // 0=off, 1=on
+ BOOL bFastFPU; // 0=off, 1=on
+ BOOL bDirectDrawPersistant;// 0=off, 1=on
+ BOOL bPersistantBuffers; // 0=off, 1=on
+ DWORD dwLogging; // 0=off, 1=normal, 2=crash-proof
+ DWORD dwLoggingSeverity; // 0=all, 1=warnings+errors, 2=errors only
+ BOOL bMessageBoxWarnings;// 0=off, 1=on
+ BOOL bMultiThreaded; // 0=off, 1=on
+ BOOL bAppCustomizations; // 0=off, 1=on
+ BOOL bHotKeySupport; // 0=off, 1=on
+ BOOL bSplashScreen; // 0=off, 1=on
+
+#ifdef _USE_GLD3_WGL
+ //
+ // New for GLDirect 3.0
+ //
+ DWORD dwAdapter; // DX8 adpater ordinal
+ DWORD dwTnL; // Transform & Lighting type
+ DWORD dwMultisample; // DX8 multisample type
+#endif // _USE_GLD3_WGL
+} INI_settings;
+
+static INI_settings ini;
+
+// ***********************************************************************
+
+BOOL APIENTRY DGL_initDriver(
+#ifdef _USE_GLD3_WGL
+ void)
+{
+#else
+ DGL_wglFuncs *lpWglFuncs,
+ DGL_mesaFuncs *lpMesaFuncs)
+{
+ // Check for valid pointers
+ if ((lpWglFuncs == NULL) || (lpMesaFuncs == NULL))
+ return FALSE;
+
+ // Check for valid structs
+ if (lpWglFuncs->dwSize != sizeof(DGL_wglFuncs)) {
+ return FALSE;
+ }
+
+ // Check for valid structs
+ if (lpMesaFuncs->dwSize != sizeof(DGL_mesaFuncs)) {
+ return FALSE;
+ }
+
+ // Copy the Mesa functions
+ memcpy(&mesaFuncs, lpMesaFuncs, sizeof(DGL_mesaFuncs));
+
+ // Pass back the wgl functions
+ memcpy(lpWglFuncs, &wglFuncs, sizeof(DGL_wglFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Finally initialize the callback driver
+ if (!dglInitDriver())
+ return FALSE;
+
+ return TRUE;
+};
+
+// ***********************************************************************
+
+BOOL ReadINIFile(
+ HINSTANCE hInstance)
+{
+ char szModuleFilename[MAX_PATH];
+ char szSystemDirectory[MAX_PATH];
+ const char szSectionName[] = "Config";
+ char szINIFile[MAX_PATH];
+ int pos;
+
+ // Now using the DLL module handle. KeithH, 24/May/2000.
+ // Addendum: GetModuleFileName(NULL, ... returns process filename,
+ // GetModuleFileName(hModule, ... returns DLL filename,
+
+ // Get the dll path and filename.
+ GetModuleFileName(hInstance, &szModuleFilename[0], MAX_PATH); // NULL for current process
+ // Get the System directory.
+ GetSystemDirectory(&szSystemDirectory[0], MAX_PATH);
+
+ // Test to see if DLL is in system directory.
+ if (strnicmp(szModuleFilename, szSystemDirectory, strlen(szSystemDirectory))==0) {
+ // DLL *is* in system directory.
+ // Return FALSE to indicate that registry keys should be read.
+ return FALSE;
+ }
+
+ // Compose filename of INI file
+ strcpy(szINIFile, szModuleFilename);
+ pos = strlen(szINIFile);
+ while (szINIFile[pos] != '\\') {
+ pos--;
+ }
+ szINIFile[pos+1] = '\0';
+ // Use run-time DLL path for log file too
+ strcpy(szLogPath, szINIFile);
+ szLogPath[pos] = '\0';
+ // Complete full INI file path
+ strcat(szINIFile, "gldirect.ini");
+
+ // Read settings from private INI file.
+ // Note that defaults are contained in the calls.
+ ini.dwDriver = GetPrivateProfileInt(szSectionName, "dwDriver", 2, szINIFile);
+ ini.bMipmapping = GetPrivateProfileInt(szSectionName, "bMipmapping", 1, szINIFile);
+ ini.bMultitexture = GetPrivateProfileInt(szSectionName, "bMultitexture", 1, szINIFile);
+ ini.bWaitForRetrace = GetPrivateProfileInt(szSectionName, "bWaitForRetrace", 0, szINIFile);
+ ini.bFullscreenBlit = GetPrivateProfileInt(szSectionName, "bFullscreenBlit", 0, szINIFile);
+ ini.bFastFPU = GetPrivateProfileInt(szSectionName, "bFastFPU", 1, szINIFile);
+ ini.bDirectDrawPersistant = GetPrivateProfileInt(szSectionName, "bPersistantDisplay", 0, szINIFile);
+ ini.bPersistantBuffers = GetPrivateProfileInt(szSectionName, "bPersistantResources", 0, szINIFile);
+ ini.dwLogging = GetPrivateProfileInt(szSectionName, "dwLogging", 0, szINIFile);
+ ini.dwLoggingSeverity = GetPrivateProfileInt(szSectionName, "dwLoggingSeverity", 0, szINIFile);
+ ini.bMessageBoxWarnings = GetPrivateProfileInt(szSectionName, "bMessageBoxWarnings", 0, szINIFile);
+ ini.bMultiThreaded = GetPrivateProfileInt(szSectionName, "bMultiThreaded", 0, szINIFile);
+ ini.bAppCustomizations = GetPrivateProfileInt(szSectionName, "bAppCustomizations", 1, szINIFile);
+ ini.bHotKeySupport = GetPrivateProfileInt(szSectionName, "bHotKeySupport", 0, szINIFile);
+ ini.bSplashScreen = GetPrivateProfileInt(szSectionName, "bSplashScreen", 1, szINIFile);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ ini.dwAdapter = GetPrivateProfileInt(szSectionName, "dwAdapter", 0, szINIFile);
+ // dwTnL now defaults to zero (chooses TnL at runtime). KeithH
+ ini.dwTnL = GetPrivateProfileInt(szSectionName, "dwTnL", 0, szINIFile);
+ ini.dwMultisample = GetPrivateProfileInt(szSectionName, "dwMultisample", 0, szINIFile);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dllReadRegistry(
+ HINSTANCE hInstance)
+{
+ // Read settings from INI file, if available
+ bValidINIFound = FALSE;
+ if (ReadINIFile(hInstance)) {
+ const char *szRendering[3] = {
+ "SciTech Software Renderer",
+ "Direct3D MMX Software Renderer",
+ "Direct3D Hardware Renderer"
+ };
+ // Set globals
+ glb.bPrimary = 1;
+ glb.bHardware = (ini.dwDriver == 2) ? 1 : 0;
+#ifndef _USE_GLD3_WGL
+ memset(&glb.ddGuid, 0, sizeof(glb.ddGuid));
+ glb.d3dGuid = (ini.dwDriver == 2) ? IID_IDirect3DHALDevice : IID_IDirect3DRGBDevice;
+#endif // _USE_GLD3_WGL
+ strcpy(glb.szDDName, "Primary");
+ strcpy(glb.szD3DName, szRendering[ini.dwDriver]);
+ glb.dwRendering = ini.dwDriver;
+ glb.bUseMipmaps = ini.bMipmapping;
+ glb.bMultitexture = ini.bMultitexture;
+ glb.bWaitForRetrace = ini.bWaitForRetrace;
+ glb.bFullscreenBlit = ini.bFullscreenBlit;
+ glb.bFastFPU = ini.bFastFPU;
+ glb.bDirectDrawPersistant = ini.bDirectDrawPersistant;
+ glb.bPersistantBuffers = ini.bPersistantBuffers;
+ dwLogging = ini.dwLogging;
+ dwDebugLevel = ini.dwLoggingSeverity;
+ glb.bMessageBoxWarnings = ini.bMessageBoxWarnings;
+ glb.bMultiThreaded = ini.bMultiThreaded;
+ glb.bAppCustomizations = ini.bAppCustomizations;
+ glb.bHotKeySupport = ini.bHotKeySupport;
+ bSplashScreen = ini.bSplashScreen;
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwAdapter = ini.dwAdapter;
+ glb.dwDriver = ini.dwDriver;
+ glb.dwTnL = ini.dwTnL;
+ glb.dwMultisample = ini.dwMultisample;
+#endif
+ bValidINIFound = TRUE;
+ return TRUE;
+ }
+ // Read settings from registry
+ else {
+ HKEY hReg;
+ DWORD cbValSize;
+ DWORD dwType = REG_SZ; // Registry data type for strings
+ BOOL bRegistryError;
+ BOOL bSuccess;
+
+#define REG_READ_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegQueryValueEx( hReg, (a), \
+ NULL, NULL, (LPBYTE)&(b), &cbValSize )) \
+ bRegistryError = TRUE;
+
+#define REG_READ_DEVICEID(a, b) \
+ cbValSize = MAX_DDDEVICEID_STRING; \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+#define REG_READ_STRING(a, b) \
+ cbValSize = sizeof((b)); \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+ // Read settings from the registry.
+
+ // Open the registry key for the current user if it exists.
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ // Otherwise open the registry key for the local machine.
+ if (!bSuccess)
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(DIRECTGL_REG_KEY_ROOT,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (!bSuccess)
+ return FALSE;
+
+ bRegistryError = FALSE;
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PRIMARY, glb.bPrimary);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_HW, glb.bHardware);
+#ifndef _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DD_GUID, glb.ddGuid);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_GUID, glb.d3dGuid);
+#endif // _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_LOGGING, dwLogging);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DEBUGLEVEL, dwDebugLevel);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_RENDERING, glb.dwRendering);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITEXTURE, glb.bMultitexture);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_WAITFORRETRACE, glb.bWaitForRetrace);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FULLSCREENBLIT, glb.bFullscreenBlit);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_USEMIPMAPS, glb.bUseMipmaps);
+
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_DD_NAME, glb.szDDName);
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_D3D_NAME, glb.szD3DName);
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MSGBOXWARNINGS, glb.bMessageBoxWarnings);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTDISPLAY, glb.bDirectDrawPersistant);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTBUFFERS, glb.bPersistantBuffers);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FASTFPU, glb.bFastFPU);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_HOTKEYS, glb.bHotKeySupport);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITHREAD, glb.bMultiThreaded);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_APPCUSTOM, glb.bAppCustomizations);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_SPLASHSCREEN, bSplashScreen);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwDriver = glb.dwRendering;
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_ADAPTER, glb.dwAdapter);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_TNL, glb.dwTnL);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTISAMPLE, glb.dwMultisample);
+#endif
+
+ RegCloseKey(hReg);
+
+ // Open the global registry key for GLDirect
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (bSuccess) {
+ // Read the installation path for GLDirect
+ REG_READ_STRING("InstallLocation",szLogPath);
+ RegCloseKey(hReg);
+ }
+
+ if (bRegistryError || !bSuccess)
+ return FALSE;
+ else
+
+ return TRUE;
+
+#undef REG_READ_DWORD
+#undef REG_READ_DEVICEID
+#undef REG_READ_STRING
+ }
+}
+
+// ***********************************************************************
+
+BOOL dllWriteRegistry(
+ void )
+{
+ HKEY hReg;
+ DWORD dwCreateDisposition, cbValSize;
+ BOOL bRegistryError = FALSE;
+
+#define REG_WRITE_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegSetValueEx( hReg, (a), \
+ 0, REG_DWORD, (LPBYTE)&(b), cbValSize )) \
+ bRegistryError = TRUE;
+
+ if (ERROR_SUCCESS == RegCreateKeyEx( DIRECTGL_REG_KEY_ROOT, DIRECTGL_REG_SETTINGS_KEY,
+ 0, NULL, 0, KEY_WRITE, NULL, &hReg,
+ &dwCreateDisposition )) {
+ RegFlushKey(hReg); // Make sure keys are written to disk
+ RegCloseKey(hReg);
+ hReg = NULL;
+ }
+
+ if (bRegistryError)
+ return FALSE;
+ else
+ return TRUE;
+
+#undef REG_WRITE_DWORD
+}
+
+// ***********************************************************************
+
+void dglInitHotKeys(HINSTANCE hInstance)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Install global keyboard interceptor
+ hKeyHook = SetWindowsHookEx(WH_KEYBOARD, dglKeyProc, hInstance, 0);
+}
+
+// ***********************************************************************
+
+void dglExitHotKeys(void)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Remove global keyboard interceptor
+ if (hKeyHook)
+ UnhookWindowsHookEx(hKeyHook);
+ hKeyHook = NULL;
+}
+
+// ***********************************************************************
+
+// Note: This app-customization step must be performed in both the main
+// OpenGL32 driver and the callback driver DLLs for multithreading option.
+void dglSetAppCustomizations(void)
+{
+ char szModuleFileName[MAX_PATH];
+ int iSize = MAX_PATH;
+
+ // Get the currently loaded EXE filename.
+ GetModuleFileName(NULL, &szModuleFileName[0], MAX_PATH); // NULL for current process
+ strupr(szModuleFileName);
+ iSize = strlen(szModuleFileName);
+
+ // Check for specific EXEs and adjust global settings accordingly
+
+ // NOTE: In GLD3.x "bDirectDrawPersistant" corresponds to IDirect3D8 and
+ // "bPersistantBuffers" corresponds to IDirect3DDevice8. KeithH
+
+ // Case 1: 3DStudio must be multi-threaded
+ // Added: Discreet GMAX (3DStudio MAX 4 for gamers. KeithH)
+ if (strstr(szModuleFileName, "3DSMAX.EXE")
+ || strstr(szModuleFileName, "3DSVIZ.EXE")
+ || strstr(szModuleFileName, "GMAX.EXE")) {
+ glb.bMultiThreaded = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 2: Solid Edge must use pre-allocated resources for all GLRCs
+ if (strstr(szModuleFileName, "PART.EXE")
+ || strstr(szModuleFileName, "ASSEMBL.EXE")
+ || strstr(szModuleFileName, "DRAFT.EXE")
+ || strstr(szModuleFileName, "SMARTVW.EXE")
+ || strstr(szModuleFileName, "SMETAL.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 3: Sudden Depth creates and destroys GLRCs on paint commands
+ if (strstr(szModuleFileName, "SUDDEPTH.EXE")
+ || strstr(szModuleFileName, "SUDDEMO.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ glb.bFullscreenBlit = TRUE;
+ return;
+ }
+
+ // Case 4: StereoGraphics test apps create and destroy GLRCs on paint commands
+ if (strstr(szModuleFileName, "REDBLUE.EXE")
+ || strstr(szModuleFileName, "DIAGNOSE.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 5: Pipes screen savers share multiple GLRCs for same window
+ if (strstr(szModuleFileName, "PIPES.SCR")
+ || (strstr(szModuleFileName, "PIPES") && strstr(szModuleFileName, ".SCR"))) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 6: AutoVue uses sub-viewport ops which are temporarily broken in stereo window
+ if (strstr(szModuleFileName, "AVWIN.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+ // Case 7: Quake3 is waiting for DDraw objects to be released at exit
+ if (strstr(szModuleFileName, "QUAKE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ glb.bFullscreenBlit = FALSE;
+ return;
+ }
+ // Case 8: Reflection GLX server is unable to switch contexts at run-time
+ if (strstr(szModuleFileName, "RX.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bMessageBoxWarnings = FALSE;
+ return;
+ }
+ // Case 9: Original AutoCAD 2000 must share DDraw objects across GLRCs
+ if (strstr(szModuleFileName, "ACAD.EXE")) {
+ glb.bFastFPU = FALSE;
+ if (GetModuleHandle("wopengl6.hdi") != NULL) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ }
+ return;
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglInitDriver(void)
+{
+ UCHAR szExeName[MAX_PATH];
+ const char *szRendering[] = {
+ "Mesa Software",
+ "Direct3D RGB SW",
+ "Direct3D HW",
+ };
+ static BOOL bWarnOnce = FALSE;
+
+ // Already initialized?
+ if (bInitialized)
+ return TRUE;
+
+ // Moved from DllMain DLL_PROCESS_ATTACH:
+
+ // (Re-)Init defaults
+ dglInitGlobals();
+
+ // Read registry or INI file settings
+ if (!dllReadRegistry(hInstanceDll)) {
+ if (!bWarnOnce)
+ MessageBox( NULL, "GLDirect has not been configured.\n\n"
+ "Please run the configuration program\n"
+ "before using GLDirect with applications.\n",
+ "GLDirect", MB_OK | MB_ICONWARNING);
+ bWarnOnce = TRUE;
+ return FALSE;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Must do this as early as possible.
+ // Need to read regkeys/ini-file first though.
+ gldInitDriverPointers(glb.dwDriver);
+
+ // Create private driver globals
+ _gldDriver.CreatePrivateGlobals();
+#endif
+ // Overide settings with application customizations
+ if (glb.bAppCustomizations)
+ dglSetAppCustomizations();
+
+//#ifndef _USE_GLD3_WGL
+ // Set the global memory type to either sysmem or vidmem
+ glb.dwMemoryType = glb.bHardware ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY;
+//#endif
+
+ // Multi-threaded support overides persistant display support
+ if (glb.bMultiThreaded)
+ glb.bDirectDrawPersistant = glb.bPersistantBuffers = FALSE;
+
+ // Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+ _gld_bMultiThreaded = glb.bMultiThreaded;
+
+ // Start logging
+ ddlogPathOption(szLogPath);
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+ ddlogOpen((DDLOG_loggingMethodType)dwLogging,
+ (DDLOG_severityType)dwDebugLevel);
+
+ // Obtain the name of the calling app
+ ddlogMessage(DDLOG_SYSTEM, "Driver : SciTech GLDirect 4.0\n");
+ GetModuleFileName(NULL, szExeName, sizeof(szExeName));
+ ddlogPrintf(DDLOG_SYSTEM, "Executable : %s", szExeName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "DirectDraw device: %s", glb.szDDName);
+ ddlogPrintf(DDLOG_SYSTEM, "Direct3D driver : %s", glb.szD3DName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Rendering type : %s", szRendering[glb.dwRendering]);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Multithreaded : %s", glb.bMultiThreaded ? "Enabled" : "Disabled");
+ ddlogPrintf(DDLOG_SYSTEM, "Display resources: %s", glb.bDirectDrawPersistant ? "Persistant" : "Instanced");
+ ddlogPrintf(DDLOG_SYSTEM, "Buffer resources : %s", glb.bPersistantBuffers ? "Persistant" : "Instanced");
+
+ dglInitContextState();
+ dglBuildPixelFormatList();
+ //dglBuildTextureFormatList();
+
+ // D3D callback driver is now successfully initialized
+ bInitialized = TRUE;
+ // D3D callback driver is now ready to be exited
+ bExited = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void dglExitDriver(void)
+{
+
+ // Only need to clean up once per instance:
+ // May be called implicitly from DLL_PROCESS_DETACH,
+ // or explicitly from DGL_exitDriver().
+ if (bExited)
+ return;
+ bExited = TRUE;
+
+ // DDraw objects may be invalid when DLL unloads.
+__try {
+
+ // Clean-up sequence (moved from DLL_PROCESS_DETACH)
+#ifndef _USE_GLD3_WGL
+ dglReleaseTextureFormatList();
+#endif
+ dglReleasePixelFormatList();
+ dglDeleteContextState();
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyPrivateGlobals();
+#endif
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglExitDriver.");
+}
+
+ // Close the log file
+ ddlogClose();
+}
+
+// ***********************************************************************
+
+int WINAPI DllMain(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ // Cache DLL instance handle
+ hInstanceDll = hInstance;
+
+ // Flag that callback driver has yet to be initialized
+ bInitialized = bExited = FALSE;
+
+#ifndef _USE_GLD3_WGL
+ // Init internal Mesa function pointers
+ memset(&mesaFuncs, 0, sizeof(DGL_mesaFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Init defaults
+ dglInitGlobals();
+
+ // Defer rest of DLL initialization to 1st WGL function call
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Call exit clean-up sequence
+ dglExitDriver();
+ break;
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_exitDriver(void)
+{
+ // Call exit clean-up sequence
+ dglExitDriver();
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_reinitDriver(void)
+{
+ // Force init sequence again
+ bInitialized = bExited = FALSE;
+ dglInitDriver();
+}
+
+// ***********************************************************************
+
+int WINAPI DllInitialize(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ // Some Watcom compiled executables require this.
+ return DllMain(hInstance, fdwReason, pvReserved);
+}
+
+// ***********************************************************************
+
+void DGL_LoadSplashScreen(int piReg, char* pszUser)
+{
+ HINSTANCE hSplashDll = NULL;
+ LPDGLSPLASHSCREEN dglSplashScreen = NULL;
+ static BOOL bOnce = FALSE;
+ static int iReg = 0;
+ static char szUser[255] = {"\0"};
+
+ // Display splash screen at all?
+ if (!bSplashScreen)
+ return;
+
+ // Only display splash screen once
+ if (bOnce)
+ return;
+ bOnce = TRUE;
+
+ // Make local copy of string for passing to DLL
+ if (pszUser)
+ strcpy(szUser, pszUser);
+ iReg = piReg;
+
+ // Load Splash Screen DLL
+ // (If it fails to load for any reason, we don't care...)
+ hSplashDll = LoadLibrary("gldsplash.dll");
+ if (hSplashDll) {
+ // Execute the Splash Screen function
+ dglSplashScreen = (LPDGLSPLASHSCREEN)GetProcAddress(hSplashDll, "GLDSplashScreen");
+ if (dglSplashScreen)
+ (*dglSplashScreen)(1, iReg, szUser);
+ // Don't unload the DLL since splash screen dialog is modeless now
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglValidate()
+{
+ char *szCaption = "SciTech GLDirect Driver";
+ UINT uType = MB_OK | MB_ICONEXCLAMATION;
+
+#ifdef _USE_GLD3_WGL
+ // (Re)build pixelformat list
+ if (glb.bPixelformatsDirty)
+ _gldDriver.BuildPixelformatList();
+#endif
+
+ // Check to see if we have already validated
+ if (bDriverValidated && bInitialized)
+ return TRUE;
+
+ // Since all (most) the WGL functions must be validated at this point,
+ // this also insure that the callback driver is completely initialized.
+ if (!bInitialized)
+ if (!dglInitDriver()) {
+ MessageBox(NULL,
+ "The GLDirect driver could not initialize.\n\n"
+ "Please run the configuration program to\n"
+ "properly configure the driver, or else\n"
+ "re-run the installation program.", szCaption, uType);
+ _exit(1); // Bail
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dllmain.h b/mesalib/src/mesa/drivers/windows/gldirect/dllmain.h
new file mode 100644
index 000000000..03343ef7a
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/dllmain.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+#ifndef __DLLMAIN_H
+#define __DLLMAIN_H
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#ifndef _USE_GLD3_WGL
+#include "DirectGL.h"
+#endif // _USE_GLD3_WGL
+
+//#include "gldirect/regkeys.h"
+#include "dglglobals.h"
+#include "ddlog.h"
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif // _USE_GLD3_WGL
+
+#include "dglwgl.h"
+
+extern BOOL bInitialized;
+
+BOOL dglInitDriver(void);
+void dglExitDriver(void);
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_clip.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
new file mode 100644
index 000000000..044d2e66f
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
@@ -0,0 +1,39 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_clip.c HACK")
+
+void _math_test_all_cliptest_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_norm.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
new file mode 100644
index 000000000..c20362bb2
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
@@ -0,0 +1,39 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_norm.c HACK")
+
+void _math_test_all_normal_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_xform.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
new file mode 100644
index 000000000..73439dc3b
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
@@ -0,0 +1,41 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Updated for P6 architecture by Gareth Hughes.
+ */
+
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_xform.c HACK")
+
+void _math_test_all_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_dispatch.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_dispatch.c
new file mode 100644
index 000000000..e05d767e3
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_dispatch.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Thread-aware dispatch table.
+*
+****************************************************************************/
+
+#include "glheader.h"
+#include "glapi.h"
+#include "glapitable.h"
+#include "mtypes.h"
+#include "context.h"
+
+#define KEYWORD1
+#define KEYWORD2 GLAPIENTRY
+#if defined(USE_MGL_NAMESPACE)
+ #define NAME(func) mgl##func
+#else
+ #define NAME(func) gl##func
+#endif
+
+#if 0
+// Altered these to get the dispatch table from
+// the current context of the calling thread.
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (gc->CurrentDispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (gc->CurrentDispatch->FUNC) ARGS
+#else // #if 0
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (_glapi_Dispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (_glapi_Dispatch->FUNC) ARGS
+#endif // #if 0
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#include "glapitemp.h"
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c
new file mode 100644
index 000000000..f7c575614
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.c
@@ -0,0 +1,279 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "gld_driver.h"
+#include "ddlog.h"
+#include "glheader.h"
+
+// For glGetString().
+#include "common_x86_asm.h"
+
+//---------------------------------------------------------------------------
+
+static char *szDriverError = "Driver used before initialisation!";
+
+// This holds our dynamically created OpenGL renderer string.
+// 256 chars should be plenty - remember that some apps display this.
+static char _gldRendererString[256];
+
+static char *szVendor = "SciTech Software, Inc.";
+
+//---------------------------------------------------------------------------
+
+extern BOOL gldGetDXErrorString_DX(HRESULT hr, char *buf, int nBufSize);
+
+extern BOOL gldCreateDrawable_MesaSW(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_MesaSW(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_MesaSW(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_MesaSW(void);
+extern BOOL gldDestroyPrivateGlobals_MesaSW(void);
+extern BOOL gldBuildPixelformatList_MesaSW(void);
+extern BOOL gldInitialiseMesa_MesaSW(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_MesaSW(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_MesaSW(LPCSTR a);
+extern BOOL gldGetDisplayMode_MesaSW(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+extern BOOL gldCreateDrawable_DX(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_DX(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_DX(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_DX(void);
+extern BOOL gldDestroyPrivateGlobals_DX(void);
+extern BOOL gldBuildPixelformatList_DX(void);
+extern BOOL gldInitialiseMesa_DX(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_DX(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_DX(LPCSTR a);
+extern BOOL gldGetDisplayMode_DX(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+//---------------------------------------------------------------------------
+// NOP functions. Called if proper driver functions are not set.
+//---------------------------------------------------------------------------
+
+static BOOL _gldDriverError(void)
+{
+ ddlogMessage(DDLOG_CRITICAL, szDriverError);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDXErrorString_ERROR(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreateDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _ResizeDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyDrawable_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreatePrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyPrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _BuildPixelformatList_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+
+static BOOL _InitialiseMesa_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _SwapBuffers_ERROR(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static PROC _GetProcAddress_ERROR(
+ LPCSTR a)
+{
+ _gldDriverError();
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDisplayMode_ERROR(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+// Functions useful to all drivers
+//---------------------------------------------------------------------------
+
+const GLubyte* _gldGetStringGeneric(
+ GLcontext *ctx,
+ GLenum name)
+{
+ if (!ctx)
+ return NULL;
+
+ switch (name) {
+ case GL_RENDERER:
+ sprintf(_gldRendererString, "GLDirect 4.0 %s%s%s%s (%s %s)",
+ _mesa_x86_cpu_features ? "/x86" : "",
+ cpu_has_mmx ? "/MMX" : "",
+ cpu_has_3dnow ? "/3DNow!" : "",
+ cpu_has_xmm ? "/SSE" : "",
+ __DATE__, __TIME__);
+ return (const GLubyte *) _gldRendererString;
+ case GL_VENDOR:
+ return (const GLubyte *) szVendor;
+ default:
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Global driver function pointers, initially set to functions that
+// will report an error when called.
+//---------------------------------------------------------------------------
+
+GLD_driver _gldDriver = {
+ _GetDXErrorString_ERROR,
+ _CreateDrawable_ERROR,
+ _ResizeDrawable_ERROR,
+ _DestroyDrawable_ERROR,
+ _CreatePrivateGlobals_ERROR,
+ _DestroyPrivateGlobals_ERROR,
+ _BuildPixelformatList_ERROR,
+ _InitialiseMesa_ERROR,
+ _SwapBuffers_ERROR,
+ _GetProcAddress_ERROR,
+ _GetDisplayMode_ERROR
+};
+
+//---------------------------------------------------------------------------
+// Init function. Should be called as soon as regkeys/ini-settings are read.
+//---------------------------------------------------------------------------
+
+BOOL gldInitDriverPointers(
+ DWORD dwDriver)
+{
+ _gldDriver.GetDXErrorString = gldGetDXErrorString_DX;
+
+ if (dwDriver == GLDS_DRIVER_MESA_SW) {
+ // Mesa Software driver
+ _gldDriver.CreateDrawable = gldCreateDrawable_MesaSW;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_MesaSW;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_MesaSW;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_MesaSW;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_MesaSW;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_MesaSW;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_MesaSW;
+ _gldDriver.SwapBuffers = gldSwapBuffers_MesaSW;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_MesaSW;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_MesaSW;
+ return TRUE;
+ }
+
+ if ((dwDriver == GLDS_DRIVER_REF) || (dwDriver == GLDS_DRIVER_HAL)) {
+ // Direct3D driver, either HW or SW
+ _gldDriver.CreateDrawable = gldCreateDrawable_DX;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_DX;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_DX;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_DX;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_DX;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_DX;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_DX;
+ _gldDriver.SwapBuffers = gldSwapBuffers_DX;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_DX;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_DX;
+ return TRUE;
+ };
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h
new file mode 100644
index 000000000..01a46a832
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gld_driver.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#ifndef _GLD_DRIVER_H
+#define _GLD_DRIVER_H
+
+// This file is only useful is we're using the new GLD3 WGL code.
+#ifdef _USE_GLD3_WGL
+
+#include "dglcontext.h"
+
+// Same as DX8 D3DDISPLAYMODE
+typedef struct {
+ DWORD Width;
+ DWORD Height;
+ DWORD Refresh;
+ DWORD BPP;
+} GLD_displayMode;
+
+typedef struct {
+ // Returns a string for a given HRESULT error code.
+ BOOL (*GetDXErrorString)(HRESULT hr, char *buf, int nBufSize);
+
+ // Driver functions for managing drawables.
+ // Functions must respect persistant buffers / persistant interface.
+ // NOTE: Persistant interface is: DirectDraw, pre-DX8; Direct3D, DX8 and above.
+ BOOL (*CreateDrawable)(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*ResizeDrawable)(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*DestroyDrawable)(DGL_ctx *ctx);
+
+ // Create/Destroy private globals belonging to driver
+ BOOL (*CreatePrivateGlobals)(void);
+ BOOL (*DestroyPrivateGlobals)(void);
+
+ // Build pixelformat list
+ BOOL (*BuildPixelformatList)(void);
+
+ // Initialise Mesa's driver pointers
+ BOOL (*InitialiseMesa)(DGL_ctx *ctx);
+
+ // Swap buffers
+ BOOL (*SwapBuffers)(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+
+ // wglGetProcAddress()
+ PROC (*wglGetProcAddress)(LPCSTR a);
+
+ BOOL (*GetDisplayMode)(DGL_ctx *ctx, GLD_displayMode *glddm);
+} GLD_driver;
+
+extern GLD_driver _gldDriver;
+
+BOOL gldInitDriverPointers(DWORD dwDriver);
+const GLubyte* _gldGetStringGeneric(GLcontext *ctx, GLenum name);
+
+#endif // _USE_GLD3_WGL
+
+#endif // _GLD_DRIVER_H
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/gldlame8.c b/mesalib/src/mesa/drivers/windows/gldirect/gldlame8.c
new file mode 100644
index 000000000..5ac519c17
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/gldlame8.c
@@ -0,0 +1,181 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: GLDirect utility for determining lame boards/drivers.
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <d3d8.h>
+
+/*
+Ack. Broken out from gldlame.c because of broken D3D headers. KeithH
+*/
+
+/****************************************************************************
+REMARKS:
+Scans list of DirectDraw devices for specific device IDs.
+****************************************************************************/
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+static __inline BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3D8 device for "lameness" with respect to GLDirect.
+This is done on per-chipset basis, as in GLD CAD driver (DGLCONTEXT.C).
+If bTestForWHQL is set then the device is tested to see if it is
+certified, and bIsWHQL is set to indicate TRUE or FALSE. Otherwise bIsWHQL
+is not set. [WHQL = Windows Hardware Quality Labs]
+
+NOTE: There is a one- or two-second time penalty incurred in determining
+ the WHQL certification date.
+****************************************************************************/
+BOOL IsThisD3D8Lame(
+ IDirect3D8 *pD3D,
+ DWORD dwAdapter,
+ BOOL bTestForWHQL,
+ BOOL *bIsWHQL)
+{
+ DWORD dwFlags = bTestForWHQL ? 0 : D3DENUM_NO_WHQL_LEVEL;
+ D3DADAPTER_IDENTIFIER8 d3dai;
+ HRESULT hr;
+
+ hr = IDirect3D8_GetAdapterIdentifier(pD3D, dwAdapter, dwFlags, &d3dai);
+ if (FAILED(hr))
+ return TRUE; // Definitely lame if adapter details can't be obtained!
+
+ if (bTestForWHQL) {
+ *bIsWHQL = d3dai.WHQLLevel ? TRUE : FALSE;
+ }
+
+ // Vendor 1: ATI
+ if (d3dai.VendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, d3dai.DeviceId, sizeof(devATIRagePro)))
+ return TRUE; // bad mipmapping
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, d3dai.DeviceId, sizeof(devATIRageIIplus)))
+ return TRUE; // bad HW alpha testing
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3DDevice8 device for "lameness" with respect to GLDirect.
+This is done by querying for particular caps, as in GLD CPL (CPLMAIN.CPP).
+****************************************************************************/
+BOOL IsThisD3D8DeviceLame(
+ IDirect3DDevice8 *pDev)
+{
+ D3DCAPS8 d3dCaps;
+ HRESULT hr;
+
+ hr = IDirect3DDevice8_GetDeviceCaps(pDev, &d3dCaps);
+ if (FAILED(hr))
+ return TRUE;
+
+ // Test 1: Perspective-correct textures
+ // Any card that cannot do perspective-textures is *exceptionally* lame.
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 2: Bilinear filtering
+ if (!(d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 3: Mipmapping
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 4: Depth-test modes (?)
+
+ // Test 5: Blend Modes -- Based on DX7 D3DIM MTEXTURE.CPP caps test
+
+ // Accept devices that can do multipass, alpha blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_INVSRCALPHA) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_SRCALPHA)) )
+ return TRUE;
+
+ // Accept devices that can do multipass, color blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_SRCCOLOR) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_ZERO)) )
+ return TRUE;
+
+ // Accept devices that really support multiple textures.
+ if( !((d3dCaps.MaxTextureBlendStages > 1 ) &&
+ (d3dCaps.MaxSimultaneousTextures > 1 ) &&
+ (d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATE )) )
+ return TRUE;
+
+ return FALSE; // Not lame
+}
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/opengl32.def b/mesalib/src/mesa/drivers/windows/gldirect/opengl32.def
new file mode 100644
index 000000000..b213b6e04
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/opengl32.def
@@ -0,0 +1,488 @@
+;****************************************************************************
+;*
+;* Mesa 3-D graphics library
+;* Direct3D Driver Interface
+;*
+;* ========================================================================
+;*
+;* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+;*
+;* Permission is hereby granted, free of charge, to any person obtaining a
+;* copy of this software and associated documentation files (the "Software"),
+;* to deal in the Software without restriction, including without limitation
+;* the rights to use, copy, modify, merge, publish, distribute, 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
+;* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+;* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+;* SOFTWARE.
+;*
+;* ======================================================================
+;*
+;* Language: ANSI C
+;* Environment: Windows 9x/2000/XP/XBox (Win32)
+;*
+;* Description: DLL Module definition file
+;*
+;****************************************************************************/
+
+DESCRIPTION 'GLDirect'
+
+VERSION 3.0
+
+EXPORTS
+ glAccum=glAccum @1
+ glAlphaFunc=glAlphaFunc @2
+ glAreTexturesResident=glAreTexturesResident @3
+ glArrayElement=glArrayElement @4
+ glBegin=glBegin @5
+ glBindTexture=glBindTexture @6
+ glBitmap=glBitmap @7
+ glBlendFunc=glBlendFunc @8
+ glCallList=glCallList @9
+ glCallLists=glCallLists @10
+ glClear=glClear @11
+ glClearAccum=glClearAccum @12
+ glClearIndex=glClearIndex @13
+ glClearColor=glClearColor @14
+ glClearDepth=glClearDepth @15
+ glClearStencil=glClearStencil @16
+ glClipPlane=glClipPlane @17
+ glColor3b=glColor3b @18
+ glColor3d=glColor3d @19
+ glColor3f=glColor3f @20
+ glColor3i=glColor3i @21
+ glColor3s=glColor3s @22
+ glColor3ub=glColor3ub @23
+ glColor3ui=glColor3ui @24
+ glColor3us=glColor3us @25
+ glColor4b=glColor4b @26
+ glColor4d=glColor4d @27
+ glColor4f=glColor4f @28
+ glColor4i=glColor4i @29
+ glColor4s=glColor4s @30
+ glColor4ub=glColor4ub @31
+ glColor4ui=glColor4ui @32
+ glColor4us=glColor4us @33
+ glColor3bv=glColor3bv @34
+ glColor3dv=glColor3dv @35
+ glColor3fv=glColor3fv @36
+ glColor3iv=glColor3iv @37
+ glColor3sv=glColor3sv @38
+ glColor3ubv=glColor3ubv @39
+ glColor3uiv=glColor3uiv @40
+ glColor3usv=glColor3usv @41
+ glColor4bv=glColor4bv @42
+ glColor4dv=glColor4dv @43
+ glColor4fv=glColor4fv @44
+ glColor4iv=glColor4iv @45
+ glColor4sv=glColor4sv @46
+ glColor4ubv=glColor4ubv @47
+ glColor4uiv=glColor4uiv @48
+ glColor4usv=glColor4usv @49
+ glColorMask=glColorMask @50
+ glColorMaterial=glColorMaterial @51
+ glColorPointer=glColorPointer @52
+ glColorTableEXT=glColorTableEXT @53
+ glColorSubTableEXT=glColorSubTableEXT @54
+ glCopyPixels=glCopyPixels @55
+ glCopyTexImage1D=glCopyTexImage1D @56
+ glCopyTexImage2D=glCopyTexImage2D @57
+ glCopyTexSubImage1D=glCopyTexSubImage1D @58
+ glCopyTexSubImage2D=glCopyTexSubImage2D @59
+ glCullFace=glCullFace @60
+ glDepthFunc=glDepthFunc @61
+ glDepthMask=glDepthMask @62
+ glDepthRange=glDepthRange @63
+ glDeleteLists=glDeleteLists @64
+ glDeleteTextures=glDeleteTextures @65
+ glDisable=glDisable @66
+ glDisableClientState=glDisableClientState @67
+ glDrawArrays=glDrawArrays @68
+ glDrawBuffer=glDrawBuffer @69
+ glDrawElements=glDrawElements @70
+ glDrawPixels=glDrawPixels @71
+ glEnable=glEnable @72
+ glEnableClientState=glEnableClientState @73
+ glEnd=glEnd @74
+ glEndList=glEndList @75
+ glEvalCoord1d=glEvalCoord1d @76
+ glEvalCoord1f=glEvalCoord1f @77
+ glEvalCoord1dv=glEvalCoord1dv @78
+ glEvalCoord1fv=glEvalCoord1fv @79
+ glEvalCoord2d=glEvalCoord2d @80
+ glEvalCoord2f=glEvalCoord2f @81
+ glEvalCoord2dv=glEvalCoord2dv @82
+ glEvalCoord2fv=glEvalCoord2fv @83
+ glEvalPoint1=glEvalPoint1 @84
+ glEvalPoint2=glEvalPoint2 @85
+ glEvalMesh1=glEvalMesh1 @86
+ glEdgeFlag=glEdgeFlag @87
+ glEdgeFlagv=glEdgeFlagv @88
+ glEdgeFlagPointer=glEdgeFlagPointer @89
+ glEvalMesh2=glEvalMesh2 @90
+ glFeedbackBuffer=glFeedbackBuffer @91
+ glFinish=glFinish @92
+ glFlush=glFlush @93
+ glFogf=glFogf @94
+ glFogi=glFogi @95
+ glFogfv=glFogfv @96
+ glFogiv=glFogiv @97
+ glFrontFace=glFrontFace @98
+ glFrustum=glFrustum @99
+ glGenLists=glGenLists @100
+ glGenTextures=glGenTextures @101
+ glGetBooleanv=glGetBooleanv @102
+ glGetClipPlane=glGetClipPlane @103
+ glGetColorTableEXT=glGetColorTableEXT @104
+ glGetColorTableParameterivEXT=glGetColorTableParameterivEXT @105
+ glGetColorTableParameterfvEXT=glGetColorTableParameterfvEXT @106
+ glGetDoublev=glGetDoublev @107
+ glGetError=glGetError @108
+ glGetFloatv=glGetFloatv @109
+ glGetIntegerv=glGetIntegerv @110
+ glGetLightfv=glGetLightfv @111
+ glGetLightiv=glGetLightiv @112
+ glGetMapdv=glGetMapdv @113
+ glGetMapfv=glGetMapfv @114
+ glGetMapiv=glGetMapiv @115
+ glGetMaterialfv=glGetMaterialfv @116
+ glGetMaterialiv=glGetMaterialiv @117
+ glGetPixelMapfv=glGetPixelMapfv @118
+ glGetPixelMapuiv=glGetPixelMapuiv @119
+ glGetPixelMapusv=glGetPixelMapusv @120
+ glGetPointerv=glGetPointerv @121
+ glGetPolygonStipple=glGetPolygonStipple @122
+ glGetString=glGetString @123
+ glGetTexEnvfv=glGetTexEnvfv @124
+ glGetTexEnviv=glGetTexEnviv @125
+ glGetTexGeniv=glGetTexGeniv @126
+ glGetTexGendv=glGetTexGendv @127
+ glGetTexGenfv=glGetTexGenfv @128
+ glGetTexImage=glGetTexImage @129
+ glGetTexLevelParameterfv=glGetTexLevelParameterfv @130
+ glGetTexLevelParameteriv=glGetTexLevelParameteriv @131
+ glGetTexParameterfv=glGetTexParameterfv @132
+ glGetTexParameteriv=glGetTexParameteriv @133
+ glHint=glHint @134
+ glIndexd=glIndexd @135
+ glIndexf=glIndexf @136
+ glIndexi=glIndexi @137
+ glIndexs=glIndexs @138
+ glIndexub=glIndexub @139
+ glIndexdv=glIndexdv @140
+ glIndexfv=glIndexfv @141
+ glIndexiv=glIndexiv @142
+ glIndexsv=glIndexsv @143
+ glIndexubv=glIndexubv @144
+ glIndexMask=glIndexMask @145
+ glIndexPointer=glIndexPointer @146
+ glInterleavedArrays=glInterleavedArrays @147
+ glInitNames=glInitNames @148
+ glIsList=glIsList @149
+ glIsTexture=glIsTexture @150
+ glLightf=glLightf @151
+ glLighti=glLighti @152
+ glLightfv=glLightfv @153
+ glLightiv=glLightiv @154
+ glLightModelf=glLightModelf @155
+ glLightModeli=glLightModeli @156
+ glLightModelfv=glLightModelfv @157
+ glLightModeliv=glLightModeliv @158
+ glLineWidth=glLineWidth @159
+ glLineStipple=glLineStipple @160
+ glListBase=glListBase @161
+ glLoadIdentity=glLoadIdentity @162
+ glLoadMatrixd=glLoadMatrixd @163
+ glLoadMatrixf=glLoadMatrixf @164
+ glLoadName=glLoadName @165
+ glLogicOp=glLogicOp @166
+ glMap1d=glMap1d @167
+ glMap1f=glMap1f @168
+ glMap2d=glMap2d @169
+ glMap2f=glMap2f @170
+ glMapGrid1d=glMapGrid1d @171
+ glMapGrid1f=glMapGrid1f @172
+ glMapGrid2d=glMapGrid2d @173
+ glMapGrid2f=glMapGrid2f @174
+ glMaterialf=glMaterialf @175
+ glMateriali=glMateriali @176
+ glMaterialfv=glMaterialfv @177
+ glMaterialiv=glMaterialiv @178
+ glMatrixMode=glMatrixMode @179
+ glMultMatrixd=glMultMatrixd @180
+ glMultMatrixf=glMultMatrixf @181
+ glNewList=glNewList @182
+ glNormal3b=glNormal3b @183
+ glNormal3d=glNormal3d @184
+ glNormal3f=glNormal3f @185
+ glNormal3i=glNormal3i @186
+ glNormal3s=glNormal3s @187
+ glNormal3bv=glNormal3bv @188
+ glNormal3dv=glNormal3dv @189
+ glNormal3fv=glNormal3fv @190
+ glNormal3iv=glNormal3iv @191
+ glNormal3sv=glNormal3sv @192
+ glNormalPointer=glNormalPointer @193
+ glOrtho=glOrtho @194
+ glPassThrough=glPassThrough @195
+ glPixelMapfv=glPixelMapfv @196
+ glPixelMapuiv=glPixelMapuiv @197
+ glPixelMapusv=glPixelMapusv @198
+ glPixelStoref=glPixelStoref @199
+ glPixelStorei=glPixelStorei @200
+ glPixelTransferf=glPixelTransferf @201
+ glPixelTransferi=glPixelTransferi @202
+ glPixelZoom=glPixelZoom @203
+ glPointSize=glPointSize @204
+ glPolygonMode=glPolygonMode @205
+ glPolygonOffset=glPolygonOffset @206
+ glPolygonOffsetEXT=glPolygonOffsetEXT @207
+ glPolygonStipple=glPolygonStipple @208
+ glPopAttrib=glPopAttrib @209
+ glPopClientAttrib=glPopClientAttrib @210
+ glPopMatrix=glPopMatrix @211
+ glPopName=glPopName @212
+ glPrioritizeTextures=glPrioritizeTextures @213
+ glPushMatrix=glPushMatrix @214
+ glRasterPos2d=glRasterPos2d @215
+ glRasterPos2f=glRasterPos2f @216
+ glRasterPos2i=glRasterPos2i @217
+ glRasterPos2s=glRasterPos2s @218
+ glRasterPos3d=glRasterPos3d @219
+ glRasterPos3f=glRasterPos3f @220
+ glRasterPos3i=glRasterPos3i @221
+ glRasterPos3s=glRasterPos3s @222
+ glRasterPos4d=glRasterPos4d @223
+ glRasterPos4f=glRasterPos4f @224
+ glRasterPos4i=glRasterPos4i @225
+ glRasterPos4s=glRasterPos4s @226
+ glRasterPos2dv=glRasterPos2dv @227
+ glRasterPos2fv=glRasterPos2fv @228
+ glRasterPos2iv=glRasterPos2iv @229
+ glRasterPos2sv=glRasterPos2sv @230
+ glRasterPos3dv=glRasterPos3dv @231
+ glRasterPos3fv=glRasterPos3fv @232
+ glRasterPos3iv=glRasterPos3iv @233
+ glRasterPos3sv=glRasterPos3sv @234
+ glRasterPos4dv=glRasterPos4dv @235
+ glRasterPos4fv=glRasterPos4fv @236
+ glRasterPos4iv=glRasterPos4iv @237
+ glRasterPos4sv=glRasterPos4sv @238
+ glReadBuffer=glReadBuffer @239
+ glReadPixels=glReadPixels @240
+ glRectd=glRectd @241
+ glRectf=glRectf @242
+ glRecti=glRecti @243
+ glRects=glRects @244
+ glRectdv=glRectdv @245
+ glRectfv=glRectfv @246
+ glRectiv=glRectiv @247
+ glRectsv=glRectsv @248
+ glScissor=glScissor @249
+ glIsEnabled=glIsEnabled @250
+ glPushAttrib=glPushAttrib @251
+ glPushClientAttrib=glPushClientAttrib @252
+ glPushName=glPushName @253
+ glRenderMode=glRenderMode @254
+ glRotated=glRotated @255
+ glRotatef=glRotatef @256
+ glSelectBuffer=glSelectBuffer @257
+ glScaled=glScaled @258
+ glScalef=glScalef @259
+ glShadeModel=glShadeModel @260
+ glStencilFunc=glStencilFunc @261
+ glStencilMask=glStencilMask @262
+ glStencilOp=glStencilOp @263
+ glTexCoord1d=glTexCoord1d @264
+ glTexCoord1f=glTexCoord1f @265
+ glTexCoord1i=glTexCoord1i @266
+ glTexCoord1s=glTexCoord1s @267
+ glTexCoord2d=glTexCoord2d @268
+ glTexCoord2f=glTexCoord2f @269
+ glTexCoord2i=glTexCoord2i @270
+ glTexCoord2s=glTexCoord2s @271
+ glTexCoord3d=glTexCoord3d @272
+ glTexCoord3f=glTexCoord3f @273
+ glTexCoord3i=glTexCoord3i @274
+ glTexCoord3s=glTexCoord3s @275
+ glTexCoord4d=glTexCoord4d @276
+ glTexCoord4f=glTexCoord4f @277
+ glTexCoord4i=glTexCoord4i @278
+ glTexCoord4s=glTexCoord4s @279
+ glTexCoord1dv=glTexCoord1dv @280
+ glTexCoord1fv=glTexCoord1fv @281
+ glTexCoord1iv=glTexCoord1iv @282
+ glTexCoord1sv=glTexCoord1sv @283
+ glTexCoord2dv=glTexCoord2dv @284
+ glTexCoord2fv=glTexCoord2fv @285
+ glTexCoord2iv=glTexCoord2iv @286
+ glTexCoord2sv=glTexCoord2sv @287
+ glTexCoord3dv=glTexCoord3dv @288
+ glTexCoord3fv=glTexCoord3fv @289
+ glTexCoord3iv=glTexCoord3iv @290
+ glTexCoord3sv=glTexCoord3sv @291
+ glTexCoord4dv=glTexCoord4dv @292
+ glTexCoord4fv=glTexCoord4fv @293
+ glTexCoord4iv=glTexCoord4iv @294
+ glTexCoord4sv=glTexCoord4sv @295
+ glTexCoordPointer=glTexCoordPointer @296
+ glTexGend=glTexGend @297
+ glTexGenf=glTexGenf @298
+ glTexGeni=glTexGeni @299
+ glTexGendv=glTexGendv @300
+ glTexGeniv=glTexGeniv @301
+ glTexGenfv=glTexGenfv @302
+ glTexEnvf=glTexEnvf @303
+ glTexEnvi=glTexEnvi @304
+ glTexEnvfv=glTexEnvfv @305
+ glTexEnviv=glTexEnviv @306
+ glTexImage1D=glTexImage1D @307
+ glTexImage2D=glTexImage2D @308
+ glTexParameterf=glTexParameterf @309
+ glTexParameteri=glTexParameteri @310
+ glTexParameterfv=glTexParameterfv @311
+ glTexParameteriv=glTexParameteriv @312
+ glTexSubImage1D=glTexSubImage1D @313
+ glTexSubImage2D=glTexSubImage2D @314
+ glTranslated=glTranslated @315
+ glTranslatef=glTranslatef @316
+ glVertex2d=glVertex2d @317
+ glVertex2f=glVertex2f @318
+ glVertex2i=glVertex2i @319
+ glVertex2s=glVertex2s @320
+ glVertex3d=glVertex3d @321
+ glVertex3f=glVertex3f @322
+ glVertex3i=glVertex3i @323
+ glVertex3s=glVertex3s @324
+ glVertex4d=glVertex4d @325
+ glVertex4f=glVertex4f @326
+ glVertex4i=glVertex4i @327
+ glVertex4s=glVertex4s @328
+ glVertex2dv=glVertex2dv @329
+ glVertex2fv=glVertex2fv @330
+ glVertex2iv=glVertex2iv @331
+ glVertex2sv=glVertex2sv @332
+ glVertex3dv=glVertex3dv @333
+ glVertex3fv=glVertex3fv @334
+ glVertex3iv=glVertex3iv @335
+ glVertex3sv=glVertex3sv @336
+ glVertex4dv=glVertex4dv @337
+ glVertex4fv=glVertex4fv @338
+ glVertex4iv=glVertex4iv @339
+ glVertex4sv=glVertex4sv @340
+ glVertexPointer=glVertexPointer @341
+ glViewport=glViewport @342
+ glBlendEquationEXT=glBlendEquationEXT @343
+ glBlendColorEXT=glBlendColorEXT @344
+ glVertexPointerEXT=glVertexPointerEXT @345
+ glNormalPointerEXT=glNormalPointerEXT @346
+ glColorPointerEXT=glColorPointerEXT @347
+ glIndexPointerEXT=glIndexPointerEXT @348
+ glTexCoordPointerEXT=glTexCoordPointerEXT @349
+ glEdgeFlagPointerEXT=glEdgeFlagPointerEXT @350
+ glGetPointervEXT=glGetPointervEXT @351
+ glArrayElementEXT=glArrayElementEXT @352
+ glDrawArraysEXT=glDrawArraysEXT @353
+ glBindTextureEXT=glBindTextureEXT @354
+ glDeleteTexturesEXT=glDeleteTexturesEXT @355
+ glGenTexturesEXT=glGenTexturesEXT @356
+ glPrioritizeTexturesEXT=glPrioritizeTexturesEXT @357
+ glCopyTexSubImage3DEXT=glCopyTexSubImage3DEXT @358
+ glTexImage3DEXT=glTexImage3DEXT @359
+ glTexSubImage3DEXT=glTexSubImage3DEXT @360
+ glWindowPos4fMESA=glWindowPos4fMESA @361
+ glWindowPos2iMESA=glWindowPos2iMESA @362
+ glWindowPos2sMESA=glWindowPos2sMESA @363
+ glWindowPos2fMESA=glWindowPos2fMESA @364
+ glWindowPos2dMESA=glWindowPos2dMESA @365
+ glWindowPos2ivMESA=glWindowPos2ivMESA @366
+ glWindowPos2svMESA=glWindowPos2svMESA @367
+ glWindowPos2fvMESA=glWindowPos2fvMESA @368
+ glWindowPos2dvMESA=glWindowPos2dvMESA @369
+ glWindowPos3iMESA=glWindowPos3iMESA @370
+ glWindowPos3sMESA=glWindowPos3sMESA @371
+ glWindowPos3fMESA=glWindowPos3fMESA @372
+ glWindowPos3dMESA=glWindowPos3dMESA @373
+ glWindowPos3ivMESA=glWindowPos3ivMESA @374
+ glWindowPos3svMESA=glWindowPos3svMESA @375
+ glWindowPos3fvMESA=glWindowPos3fvMESA @376
+ glWindowPos3dvMESA=glWindowPos3dvMESA @377
+ glWindowPos4iMESA=glWindowPos4iMESA @378
+ glWindowPos4sMESA=glWindowPos4sMESA @379
+ glWindowPos4dMESA=glWindowPos4dMESA @380
+ glWindowPos4ivMESA=glWindowPos4ivMESA @381
+ glWindowPos4svMESA=glWindowPos4svMESA @382
+ glWindowPos4fvMESA=glWindowPos4fvMESA @383
+ glWindowPos4dvMESA=glWindowPos4dvMESA @384
+ glResizeBuffersMESA=glResizeBuffersMESA @385
+ wglCopyContext=wglCopyContext @386
+ wglCreateContext=wglCreateContext @387
+ wglCreateLayerContext=wglCreateLayerContext @388
+ wglDeleteContext=wglDeleteContext @389
+ wglDescribeLayerPlane=wglDescribeLayerPlane @390
+ wglGetCurrentContext=wglGetCurrentContext @391
+ wglGetCurrentDC=wglGetCurrentDC @392
+ wglGetLayerPaletteEntries=wglGetLayerPaletteEntries @393
+ wglGetProcAddress=wglGetProcAddress @394
+ wglMakeCurrent=wglMakeCurrent @395
+ wglRealizeLayerPalette=wglRealizeLayerPalette @396
+ wglSetLayerPaletteEntries=wglSetLayerPaletteEntries @397
+ wglShareLists=wglShareLists @398
+ wglSwapLayerBuffers=wglSwapLayerBuffers @399
+ wglUseFontBitmapsA=wglUseFontBitmapsA @400
+ wglUseFontBitmapsW=wglUseFontBitmapsW @401
+ wglUseFontOutlinesA=wglUseFontOutlinesA @402
+ wglUseFontOutlinesW=wglUseFontOutlinesW @403
+ ChoosePixelFormat=ChoosePixelFormat @404
+ DescribePixelFormat=DescribePixelFormat @405
+ GetPixelFormat=GetPixelFormat @406
+ SetPixelFormat=SetPixelFormat @407
+ SwapBuffers=SwapBuffers @408
+ wglChoosePixelFormat=wglChoosePixelFormat @409
+ wglDescribePixelFormat=wglDescribePixelFormat @410
+ wglGetPixelFormat=wglGetPixelFormat @411
+ wglSetPixelFormat=wglSetPixelFormat @412
+ wglSwapBuffers=wglSwapBuffers @413
+ glActiveTextureARB=glActiveTextureARB @414
+ glClientActiveTextureARB=glClientActiveTextureARB @415
+ glMultiTexCoord1dARB=glMultiTexCoord1dARB @416
+ glMultiTexCoord1dvARB=glMultiTexCoord1dvARB @417
+ glMultiTexCoord1fARB=glMultiTexCoord1fARB @418
+ glMultiTexCoord1fvARB=glMultiTexCoord1fvARB @419
+ glMultiTexCoord1iARB=glMultiTexCoord1iARB @420
+ glMultiTexCoord1ivARB=glMultiTexCoord1ivARB @421
+ glMultiTexCoord1sARB=glMultiTexCoord1sARB @422
+ glMultiTexCoord1svARB=glMultiTexCoord1svARB @423
+ glMultiTexCoord2dARB=glMultiTexCoord2dARB @424
+ glMultiTexCoord2dvARB=glMultiTexCoord2dvARB @425
+ glMultiTexCoord2fARB=glMultiTexCoord2fARB @426
+ glMultiTexCoord2fvARB=glMultiTexCoord2fvARB @427
+ glMultiTexCoord2iARB=glMultiTexCoord2iARB @428
+ glMultiTexCoord2ivARB=glMultiTexCoord2ivARB @429
+ glMultiTexCoord2sARB=glMultiTexCoord2sARB @430
+ glMultiTexCoord2svARB=glMultiTexCoord2svARB @431
+ glMultiTexCoord3dARB=glMultiTexCoord3dARB @432
+ glMultiTexCoord3dvARB=glMultiTexCoord3dvARB @433
+ glMultiTexCoord3fARB=glMultiTexCoord3fARB @434
+ glMultiTexCoord3fvARB=glMultiTexCoord3fvARB @435
+ glMultiTexCoord3iARB=glMultiTexCoord3iARB @436
+ glMultiTexCoord3ivARB=glMultiTexCoord3ivARB @437
+ glMultiTexCoord3sARB=glMultiTexCoord3sARB @438
+ glMultiTexCoord3svARB=glMultiTexCoord3svARB @439
+ glMultiTexCoord4dARB=glMultiTexCoord4dARB @440
+ glMultiTexCoord4dvARB=glMultiTexCoord4dvARB @441
+ glMultiTexCoord4fARB=glMultiTexCoord4fARB @442
+ glMultiTexCoord4fvARB=glMultiTexCoord4fvARB @443
+ glMultiTexCoord4iARB=glMultiTexCoord4iARB @444
+ glMultiTexCoord4ivARB=glMultiTexCoord4ivARB @445
+ glMultiTexCoord4sARB=glMultiTexCoord4sARB @446
+ glMultiTexCoord4svARB=glMultiTexCoord4svARB @447
diff --git a/mesalib/src/mesa/drivers/windows/gldirect/pixpack.h b/mesalib/src/mesa/drivers/windows/gldirect/pixpack.h
new file mode 100644
index 000000000..ec848d455
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/gldirect/pixpack.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, 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
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel packing functions.
+*
+****************************************************************************/
+
+#ifndef __PIXPACK_H
+#define __PIXPACK_H
+
+#include <GL\gl.h>
+#include <ddraw.h>
+
+#include "ddlog.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#define PXAPI
+
+// Typedef that can be used for pixel packing function pointers.
+#define PX_PACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packFunc)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel unpacking function pointers.
+#define PX_UNPACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_unpackFunc)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel span packing function pointers.
+#define PX_PACK_SPAN_FUNC(a) void PXAPI (a)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packSpanFunc)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Function that examines a pixel format and returns the relevent
+// pixel-packing function
+void PXAPI pxClassifyPixelFormat(const LPDDPIXELFORMAT lpddpf, PX_packFunc *lpPackFn ,PX_unpackFunc *lpUnpackFn, PX_packSpanFunc *lpPackSpanFn);
+
+// Packing functions
+PX_PACK_FUNC(pxPackGeneric);
+PX_PACK_FUNC(pxPackRGB555);
+PX_PACK_FUNC(pxPackARGB4444);
+PX_PACK_FUNC(pxPackARGB1555);
+PX_PACK_FUNC(pxPackRGB565);
+PX_PACK_FUNC(pxPackRGB332);
+PX_PACK_FUNC(pxPackRGB888);
+PX_PACK_FUNC(pxPackARGB8888);
+PX_PACK_FUNC(pxPackPAL8);
+
+// Unpacking functions
+PX_UNPACK_FUNC(pxUnpackGeneric);
+PX_UNPACK_FUNC(pxUnpackRGB555);
+PX_UNPACK_FUNC(pxUnpackARGB4444);
+PX_UNPACK_FUNC(pxUnpackARGB1555);
+PX_UNPACK_FUNC(pxUnpackRGB565);
+PX_UNPACK_FUNC(pxUnpackRGB332);
+PX_UNPACK_FUNC(pxUnpackRGB888);
+PX_UNPACK_FUNC(pxUnpackARGB8888);
+PX_UNPACK_FUNC(pxUnpackPAL8);
+
+// Span Packing functions
+PX_PACK_SPAN_FUNC(pxPackSpanGeneric);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB555);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB4444);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB1555);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB565);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB332);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB888);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB8888);
+PX_PACK_SPAN_FUNC(pxPackSpanPAL8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/drivers/windows/icd/icd.c b/mesalib/src/mesa/drivers/windows/icd/icd.c
new file mode 100644
index 000000000..4bc6176b1
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/icd/icd.c
@@ -0,0 +1,347 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/*
+ * File name: icd.c
+ * Author: Gregor Anich
+ *
+ * ICD (Installable Client Driver) interface.
+ * Based on the windows GDI/WGL driver.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <stdio.h>
+#include <tchar.h>
+#include "GL/wmesa.h"
+#include "mtypes.h"
+#include "glapi.h"
+
+#define MAX_MESA_ATTRS 20
+
+typedef struct wmesa_context *PWMC;
+
+typedef struct _icdTable {
+ DWORD size;
+ PROC table[336];
+} ICDTABLE, *PICDTABLE;
+
+#ifdef USE_MGL_NAMESPACE
+# define GL_FUNC(func) mgl##func
+#else
+# define GL_FUNC(func) gl##func
+#endif
+
+static ICDTABLE icdTable = { 336, {
+#define ICD_ENTRY(func) (PROC)GL_FUNC(func),
+#include "icdlist.h"
+#undef ICD_ENTRY
+} };
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLboolean doubleBuffered;
+};
+
+struct __pixelformat__ pix[] =
+{
+ /* Double Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|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
+ },
+ /* Single Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL, /* | PFD_SUPPORT_GDI ? */
+ 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
+ },
+ /* Double Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ /* Single Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL, /* | PFD_SUPPORT_GDI ? */
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 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 int ctx_current = -1;
+static unsigned curPFD = 0;
+
+WGLAPI BOOL GLAPIENTRY DrvCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ (void) hglrcSrc; (void) hglrcDst; (void) mask;
+ return(FALSE);
+}
+
+WGLAPI HGLRC GLAPIENTRY DrvCreateContext(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,
+ pix[curPFD-1].pfd.cAlphaBits ? GL_TRUE : GL_FALSE);
+ if (wgl_ctx[i].ctx == NULL)
+ break;
+ wgl_ctx[i].hdc = hdc;
+ ctx_count++;
+ return ((HGLRC)wgl_ctx[i].ctx);
+ }
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvDeleteContext(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);
+}
+
+WGLAPI HGLRC GLAPIENTRY DrvCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ if (iLayerPlane == 0)
+ return DrvCreateContext(hdc);
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI PICDTABLE GLAPIENTRY DrvSetContext(HDC hdc,HGLRC hglrc,void *callback)
+{
+ int i;
+ (void) callback;
+
+ /* new code suggested by Andy Sy */
+ if (!hdc || !hglrc) {
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+ return NULL;
+ }
+
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ wgl_ctx[i].hdc = hdc;
+ WMesaMakeCurrent( (PWMC) hglrc );
+ ctx_current = i;
+ return &icdTable;
+ }
+ }
+ return NULL;
+}
+
+WGLAPI void GLAPIENTRY DrvReleaseContext(HGLRC hglrc)
+{
+ (void) hglrc;
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+}
+
+WGLAPI BOOL GLAPIENTRY DrvShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ (void) hglrc1; (void) hglrc2;
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvDescribeLayerPlane(HDC hdc,int iPixelFormat,
+ int iLayerPlane,UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ (void) hdc; (void) iPixelFormat; (void) iLayerPlane; (void) nBytes; (void) plpd;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY DrvSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ CONST COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI int GLAPIENTRY DrvGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
+{
+ (void) hdc; (void) iLayerPlane; (void) bRealize;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ (void) fuPlanes;
+ if( !hdc )
+ {
+ WMesaSwapBuffers();
+ return(TRUE);
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY DrvDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(ppfd == NULL)
+ return(qt_valid_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
+*/
+WGLAPI PROC GLAPIENTRY DrvGetProcAddress(LPCSTR lpszProc)
+{
+ PROC p = (PROC) (int) _glapi_get_proc_address((const char *) lpszProc);
+ if (p)
+ return p;
+
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSetPixelFormat(HDC hdc,int iPixelFormat)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix)
+ {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSwapBuffers(HDC hdc)
+{
+ (void) hdc;
+ if (ctx_current < 0)
+ return FALSE;
+
+ if(wgl_ctx[ctx_current].ctx == NULL) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ WMesaSwapBuffers();
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvValidateVersion(DWORD version)
+{
+ (void) version;
+ return TRUE;
+}
diff --git a/mesalib/src/mesa/drivers/windows/icd/icdlist.h b/mesalib/src/mesa/drivers/windows/icd/icdlist.h
new file mode 100644
index 000000000..1318804cf
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/icd/icdlist.h
@@ -0,0 +1,336 @@
+ICD_ENTRY(NewList) /* 0 */
+ICD_ENTRY(EndList) /* 1 */
+ICD_ENTRY(CallList) /* 2 */
+ICD_ENTRY(CallLists) /* 3 */
+ICD_ENTRY(DeleteLists) /* 4 */
+ICD_ENTRY(GenLists) /* 5 */
+ICD_ENTRY(ListBase) /* 6 */
+ICD_ENTRY(Begin) /* 7 */
+ICD_ENTRY(Bitmap) /* 8 */
+ICD_ENTRY(Color3b) /* 9 */
+ICD_ENTRY(Color3bv) /* 10 */
+ICD_ENTRY(Color3d) /* 11 */
+ICD_ENTRY(Color3dv) /* 12 */
+ICD_ENTRY(Color3f) /* 13 */
+ICD_ENTRY(Color3fv) /* 14 */
+ICD_ENTRY(Color3i) /* 15 */
+ICD_ENTRY(Color3iv) /* 16 */
+ICD_ENTRY(Color3s) /* 17 */
+ICD_ENTRY(Color3sv) /* 18 */
+ICD_ENTRY(Color3ub) /* 19 */
+ICD_ENTRY(Color3ubv) /* 20 */
+ICD_ENTRY(Color3ui) /* 21 */
+ICD_ENTRY(Color3uiv) /* 22 */
+ICD_ENTRY(Color3us) /* 23 */
+ICD_ENTRY(Color3usv) /* 24 */
+ICD_ENTRY(Color4b) /* 25 */
+ICD_ENTRY(Color4bv) /* 26 */
+ICD_ENTRY(Color4d) /* 27 */
+ICD_ENTRY(Color4dv) /* 28 */
+ICD_ENTRY(Color4f) /* 29 */
+ICD_ENTRY(Color4fv) /* 30 */
+ICD_ENTRY(Color4i) /* 31 */
+ICD_ENTRY(Color4iv) /* 32 */
+ICD_ENTRY(Color4s) /* 33 */
+ICD_ENTRY(Color4sv) /* 34 */
+ICD_ENTRY(Color4ub) /* 35 */
+ICD_ENTRY(Color4ubv) /* 36 */
+ICD_ENTRY(Color4ui) /* 37 */
+ICD_ENTRY(Color4uiv) /* 38 */
+ICD_ENTRY(Color4us) /* 39 */
+ICD_ENTRY(Color4usv) /* 40 */
+ICD_ENTRY(EdgeFlag) /* 41 */
+ICD_ENTRY(EdgeFlagv) /* 42 */
+ICD_ENTRY(End) /* 43 */
+ICD_ENTRY(Indexd) /* 44 */
+ICD_ENTRY(Indexdv) /* 45 */
+ICD_ENTRY(Indexf) /* 46 */
+ICD_ENTRY(Indexfv) /* 47 */
+ICD_ENTRY(Indexi) /* 48 */
+ICD_ENTRY(Indexiv) /* 49 */
+ICD_ENTRY(Indexs) /* 50 */
+ICD_ENTRY(Indexsv) /* 51 */
+ICD_ENTRY(Normal3b) /* 52 */
+ICD_ENTRY(Normal3bv) /* 53 */
+ICD_ENTRY(Normal3d) /* 54 */
+ICD_ENTRY(Normal3dv) /* 55 */
+ICD_ENTRY(Normal3f) /* 56 */
+ICD_ENTRY(Normal3fv) /* 57 */
+ICD_ENTRY(Normal3i) /* 58 */
+ICD_ENTRY(Normal3iv) /* 59 */
+ICD_ENTRY(Normal3s) /* 60 */
+ICD_ENTRY(Normal3sv) /* 61 */
+ICD_ENTRY(RasterPos2d) /* 62 */
+ICD_ENTRY(RasterPos2dv) /* 63 */
+ICD_ENTRY(RasterPos2f) /* 64 */
+ICD_ENTRY(RasterPos2fv) /* 65 */
+ICD_ENTRY(RasterPos2i) /* 66 */
+ICD_ENTRY(RasterPos2iv) /* 67 */
+ICD_ENTRY(RasterPos2s) /* 68 */
+ICD_ENTRY(RasterPos2sv) /* 69 */
+ICD_ENTRY(RasterPos3d) /* 70 */
+ICD_ENTRY(RasterPos3dv) /* 71 */
+ICD_ENTRY(RasterPos3f) /* 72 */
+ICD_ENTRY(RasterPos3fv) /* 73 */
+ICD_ENTRY(RasterPos3i) /* 74 */
+ICD_ENTRY(RasterPos3iv) /* 75 */
+ICD_ENTRY(RasterPos3s) /* 76 */
+ICD_ENTRY(RasterPos3sv) /* 77 */
+ICD_ENTRY(RasterPos4d) /* 78 */
+ICD_ENTRY(RasterPos4dv) /* 79 */
+ICD_ENTRY(RasterPos4f) /* 80 */
+ICD_ENTRY(RasterPos4fv) /* 81 */
+ICD_ENTRY(RasterPos4i) /* 82 */
+ICD_ENTRY(RasterPos4iv) /* 83 */
+ICD_ENTRY(RasterPos4s) /* 84 */
+ICD_ENTRY(RasterPos4sv) /* 85 */
+ICD_ENTRY(Rectd) /* 86 */
+ICD_ENTRY(Rectdv) /* 87 */
+ICD_ENTRY(Rectf) /* 88 */
+ICD_ENTRY(Rectfv) /* 89 */
+ICD_ENTRY(Recti) /* 90 */
+ICD_ENTRY(Rectiv) /* 91 */
+ICD_ENTRY(Rects) /* 92 */
+ICD_ENTRY(Rectsv) /* 93 */
+ICD_ENTRY(TexCoord1d) /* 94 */
+ICD_ENTRY(TexCoord1dv) /* 95 */
+ICD_ENTRY(TexCoord1f) /* 96 */
+ICD_ENTRY(TexCoord1fv) /* 97 */
+ICD_ENTRY(TexCoord1i) /* 98 */
+ICD_ENTRY(TexCoord1iv) /* 99 */
+ICD_ENTRY(TexCoord1s) /* 100 */
+ICD_ENTRY(TexCoord1sv) /* 101 */
+ICD_ENTRY(TexCoord2d) /* 102 */
+ICD_ENTRY(TexCoord2dv) /* 103 */
+ICD_ENTRY(TexCoord2f) /* 104 */
+ICD_ENTRY(TexCoord2fv) /* 105 */
+ICD_ENTRY(TexCoord2i) /* 106 */
+ICD_ENTRY(TexCoord2iv) /* 107 */
+ICD_ENTRY(TexCoord2s) /* 108 */
+ICD_ENTRY(TexCoord2sv) /* 109 */
+ICD_ENTRY(TexCoord3d) /* 110 */
+ICD_ENTRY(TexCoord3dv) /* 111 */
+ICD_ENTRY(TexCoord3f) /* 112 */
+ICD_ENTRY(TexCoord3fv) /* 113 */
+ICD_ENTRY(TexCoord3i) /* 114 */
+ICD_ENTRY(TexCoord3iv) /* 115 */
+ICD_ENTRY(TexCoord3s) /* 116 */
+ICD_ENTRY(TexCoord3sv) /* 117 */
+ICD_ENTRY(TexCoord4d) /* 118 */
+ICD_ENTRY(TexCoord4dv) /* 119 */
+ICD_ENTRY(TexCoord4f) /* 120 */
+ICD_ENTRY(TexCoord4fv) /* 121 */
+ICD_ENTRY(TexCoord4i) /* 122 */
+ICD_ENTRY(TexCoord4iv) /* 123 */
+ICD_ENTRY(TexCoord4s) /* 124 */
+ICD_ENTRY(TexCoord4sv) /* 125 */
+ICD_ENTRY(Vertex2d) /* 126 */
+ICD_ENTRY(Vertex2dv) /* 127 */
+ICD_ENTRY(Vertex2f) /* 128 */
+ICD_ENTRY(Vertex2fv) /* 129 */
+ICD_ENTRY(Vertex2i) /* 130 */
+ICD_ENTRY(Vertex2iv) /* 131 */
+ICD_ENTRY(Vertex2s) /* 132 */
+ICD_ENTRY(Vertex2sv) /* 133 */
+ICD_ENTRY(Vertex3d) /* 134 */
+ICD_ENTRY(Vertex3dv) /* 135 */
+ICD_ENTRY(Vertex3f) /* 136 */
+ICD_ENTRY(Vertex3fv) /* 137 */
+ICD_ENTRY(Vertex3i) /* 138 */
+ICD_ENTRY(Vertex3iv) /* 139 */
+ICD_ENTRY(Vertex3s) /* 140 */
+ICD_ENTRY(Vertex3sv) /* 141 */
+ICD_ENTRY(Vertex4d) /* 142 */
+ICD_ENTRY(Vertex4dv) /* 143 */
+ICD_ENTRY(Vertex4f) /* 144 */
+ICD_ENTRY(Vertex4fv) /* 145 */
+ICD_ENTRY(Vertex4i) /* 146 */
+ICD_ENTRY(Vertex4iv) /* 147 */
+ICD_ENTRY(Vertex4s) /* 148 */
+ICD_ENTRY(Vertex4sv) /* 149 */
+ICD_ENTRY(ClipPlane) /* 150 */
+ICD_ENTRY(ColorMaterial) /* 151 */
+ICD_ENTRY(CullFace) /* 152 */
+ICD_ENTRY(Fogf) /* 153 */
+ICD_ENTRY(Fogfv) /* 154 */
+ICD_ENTRY(Fogi) /* 155 */
+ICD_ENTRY(Fogiv) /* 156 */
+ICD_ENTRY(FrontFace) /* 157 */
+ICD_ENTRY(Hint) /* 158 */
+ICD_ENTRY(Lightf) /* 159 */
+ICD_ENTRY(Lightfv) /* 160 */
+ICD_ENTRY(Lighti) /* 161 */
+ICD_ENTRY(Lightiv) /* 162 */
+ICD_ENTRY(LightModelf) /* 163 */
+ICD_ENTRY(LightModelfv) /* 164 */
+ICD_ENTRY(LightModeli) /* 165 */
+ICD_ENTRY(LightModeliv) /* 166 */
+ICD_ENTRY(LineStipple) /* 167 */
+ICD_ENTRY(LineWidth) /* 168 */
+ICD_ENTRY(Materialf) /* 169 */
+ICD_ENTRY(Materialfv) /* 170 */
+ICD_ENTRY(Materiali) /* 171 */
+ICD_ENTRY(Materialiv) /* 172 */
+ICD_ENTRY(PointSize) /* 173 */
+ICD_ENTRY(PolygonMode) /* 174 */
+ICD_ENTRY(PolygonStipple) /* 175 */
+ICD_ENTRY(Scissor) /* 176 */
+ICD_ENTRY(ShadeModel) /* 177 */
+ICD_ENTRY(TexParameterf) /* 178 */
+ICD_ENTRY(TexParameterfv) /* 179 */
+ICD_ENTRY(TexParameteri) /* 180 */
+ICD_ENTRY(TexParameteriv) /* 181 */
+ICD_ENTRY(TexImage1D) /* 182 */
+ICD_ENTRY(TexImage2D) /* 183 */
+ICD_ENTRY(TexEnvf) /* 184 */
+ICD_ENTRY(TexEnvfv) /* 185 */
+ICD_ENTRY(TexEnvi) /* 186 */
+ICD_ENTRY(TexEnviv) /* 187 */
+ICD_ENTRY(TexGend) /* 188 */
+ICD_ENTRY(TexGendv) /* 189 */
+ICD_ENTRY(TexGenf) /* 190 */
+ICD_ENTRY(TexGenfv) /* 191 */
+ICD_ENTRY(TexGeni) /* 192 */
+ICD_ENTRY(TexGeniv) /* 193 */
+ICD_ENTRY(FeedbackBuffer) /* 194 */
+ICD_ENTRY(SelectBuffer) /* 195 */
+ICD_ENTRY(RenderMode) /* 196 */
+ICD_ENTRY(InitNames) /* 197 */
+ICD_ENTRY(LoadName) /* 198 */
+ICD_ENTRY(PassThrough) /* 199 */
+ICD_ENTRY(PopName) /* 200 */
+ICD_ENTRY(PushName) /* 201 */
+ICD_ENTRY(DrawBuffer) /* 202 */
+ICD_ENTRY(Clear) /* 203 */
+ICD_ENTRY(ClearAccum) /* 204 */
+ICD_ENTRY(ClearIndex) /* 205 */
+ICD_ENTRY(ClearColor) /* 206 */
+ICD_ENTRY(ClearStencil) /* 207 */
+ICD_ENTRY(ClearDepth) /* 208 */
+ICD_ENTRY(StencilMask) /* 209 */
+ICD_ENTRY(ColorMask) /* 210 */
+ICD_ENTRY(DepthMask) /* 211 */
+ICD_ENTRY(IndexMask) /* 212 */
+ICD_ENTRY(Accum) /* 213 */
+ICD_ENTRY(Disable) /* 214 */
+ICD_ENTRY(Enable) /* 215 */
+ICD_ENTRY(Finish) /* 216 */
+ICD_ENTRY(Flush) /* 217 */
+ICD_ENTRY(PopAttrib) /* 218 */
+ICD_ENTRY(PushAttrib) /* 219 */
+ICD_ENTRY(Map1d) /* 220 */
+ICD_ENTRY(Map1f) /* 221 */
+ICD_ENTRY(Map2d) /* 222 */
+ICD_ENTRY(Map2f) /* 223 */
+ICD_ENTRY(MapGrid1d) /* 224 */
+ICD_ENTRY(MapGrid1f) /* 225 */
+ICD_ENTRY(MapGrid2d) /* 226 */
+ICD_ENTRY(MapGrid2f) /* 227 */
+ICD_ENTRY(EvalCoord1d) /* 228 */
+ICD_ENTRY(EvalCoord1dv) /* 229 */
+ICD_ENTRY(EvalCoord1f) /* 230 */
+ICD_ENTRY(EvalCoord1fv) /* 231 */
+ICD_ENTRY(EvalCoord2d) /* 232 */
+ICD_ENTRY(EvalCoord2dv) /* 233 */
+ICD_ENTRY(EvalCoord2f) /* 234 */
+ICD_ENTRY(EvalCoord2fv) /* 235 */
+ICD_ENTRY(EvalMesh1) /* 236 */
+ICD_ENTRY(EvalPoint1) /* 237 */
+ICD_ENTRY(EvalMesh2) /* 238 */
+ICD_ENTRY(EvalPoint2) /* 239 */
+ICD_ENTRY(AlphaFunc) /* 240 */
+ICD_ENTRY(BlendFunc) /* 241 */
+ICD_ENTRY(LogicOp) /* 242 */
+ICD_ENTRY(StencilFunc) /* 243 */
+ICD_ENTRY(StencilOp) /* 244 */
+ICD_ENTRY(DepthFunc) /* 245 */
+ICD_ENTRY(PixelZoom) /* 246 */
+ICD_ENTRY(PixelTransferf) /* 247 */
+ICD_ENTRY(PixelTransferi) /* 248 */
+ICD_ENTRY(PixelStoref) /* 249 */
+ICD_ENTRY(PixelStorei) /* 250 */
+ICD_ENTRY(PixelMapfv) /* 251 */
+ICD_ENTRY(PixelMapuiv) /* 252 */
+ICD_ENTRY(PixelMapusv) /* 253 */
+ICD_ENTRY(ReadBuffer) /* 254 */
+ICD_ENTRY(CopyPixels) /* 255 */
+ICD_ENTRY(ReadPixels) /* 256 */
+ICD_ENTRY(DrawPixels) /* 257 */
+ICD_ENTRY(GetBooleanv) /* 258 */
+ICD_ENTRY(GetClipPlane) /* 259 */
+ICD_ENTRY(GetDoublev) /* 260 */
+ICD_ENTRY(GetError) /* 261 */
+ICD_ENTRY(GetFloatv) /* 262 */
+ICD_ENTRY(GetIntegerv) /* 263 */
+ICD_ENTRY(GetLightfv) /* 264 */
+ICD_ENTRY(GetLightiv) /* 265 */
+ICD_ENTRY(GetMapdv) /* 266 */
+ICD_ENTRY(GetMapfv) /* 267 */
+ICD_ENTRY(GetMapiv) /* 268 */
+ICD_ENTRY(GetMaterialfv) /* 269 */
+ICD_ENTRY(GetMaterialiv) /* 270 */
+ICD_ENTRY(GetPixelMapfv) /* 271 */
+ICD_ENTRY(GetPixelMapuiv) /* 272 */
+ICD_ENTRY(GetPixelMapusv) /* 273 */
+ICD_ENTRY(GetPolygonStipple) /* 274 */
+ICD_ENTRY(GetString) /* 275 */
+ICD_ENTRY(GetTexEnvfv) /* 276 */
+ICD_ENTRY(GetTexEnviv) /* 277 */
+ICD_ENTRY(GetTexGendv) /* 278 */
+ICD_ENTRY(GetTexGenfv) /* 279 */
+ICD_ENTRY(GetTexGeniv) /* 280 */
+ICD_ENTRY(GetTexImage) /* 281 */
+ICD_ENTRY(GetTexParameterfv) /* 282 */
+ICD_ENTRY(GetTexParameteriv) /* 283 */
+ICD_ENTRY(GetTexLevelParameterfv) /* 284 */
+ICD_ENTRY(GetTexLevelParameteriv) /* 285 */
+ICD_ENTRY(IsEnabled) /* 286 */
+ICD_ENTRY(IsList) /* 287 */
+ICD_ENTRY(DepthRange) /* 288 */
+ICD_ENTRY(Frustum) /* 289 */
+ICD_ENTRY(LoadIdentity) /* 290 */
+ICD_ENTRY(LoadMatrixf) /* 291 */
+ICD_ENTRY(LoadMatrixd) /* 292 */
+ICD_ENTRY(MatrixMode) /* 293 */
+ICD_ENTRY(MultMatrixf) /* 294 */
+ICD_ENTRY(MultMatrixd) /* 295 */
+ICD_ENTRY(Ortho) /* 296 */
+ICD_ENTRY(PopMatrix) /* 297 */
+ICD_ENTRY(PushMatrix) /* 298 */
+ICD_ENTRY(Rotated) /* 299 */
+ICD_ENTRY(Rotatef) /* 300 */
+ICD_ENTRY(Scaled) /* 301 */
+ICD_ENTRY(Scalef) /* 302 */
+ICD_ENTRY(Translated) /* 303 */
+ICD_ENTRY(Translatef) /* 304 */
+ICD_ENTRY(Viewport) /* 305 */
+ICD_ENTRY(ArrayElement) /* 306 */
+ICD_ENTRY(BindTexture) /* 307 */
+ICD_ENTRY(ColorPointer) /* 308 */
+ICD_ENTRY(DisableClientState) /* 309 */
+ICD_ENTRY(DrawArrays) /* 310 */
+ICD_ENTRY(DrawElements) /* 311 */
+ICD_ENTRY(EdgeFlagPointer) /* 312 */
+ICD_ENTRY(EnableClientState) /* 313 */
+ICD_ENTRY(IndexPointer) /* 314 */
+ICD_ENTRY(Indexub) /* 315 */
+ICD_ENTRY(Indexubv) /* 316 */
+ICD_ENTRY(InterleavedArrays) /* 317 */
+ICD_ENTRY(NormalPointer) /* 318 */
+ICD_ENTRY(PolygonOffset) /* 319 */
+ICD_ENTRY(TexCoordPointer) /* 320 */
+ICD_ENTRY(VertexPointer) /* 321 */
+ICD_ENTRY(AreTexturesResident) /* 322 */
+ICD_ENTRY(CopyTexImage1D) /* 323 */
+ICD_ENTRY(CopyTexImage2D) /* 324 */
+ICD_ENTRY(CopyTexSubImage1D) /* 325 */
+ICD_ENTRY(CopyTexSubImage2D) /* 326 */
+ICD_ENTRY(DeleteTextures) /* 327 */
+ICD_ENTRY(GenTextures) /* 328 */
+ICD_ENTRY(GetPointerv) /* 329 */
+ICD_ENTRY(IsTexture) /* 330 */
+ICD_ENTRY(PrioritizeTextures) /* 331 */
+ICD_ENTRY(TexSubImage1D) /* 332 */
+ICD_ENTRY(TexSubImage2D) /* 333 */
+ICD_ENTRY(PopClientAttrib) /* 334 */
+ICD_ENTRY(PushClientAttrib) /* 335 */
diff --git a/mesalib/src/mesa/drivers/windows/icd/mesa.def b/mesalib/src/mesa/drivers/windows/icd/mesa.def
new file mode 100644
index 000000000..465b380a0
--- /dev/null
+++ b/mesalib/src/mesa/drivers/windows/icd/mesa.def
@@ -0,0 +1,108 @@
+DESCRIPTION 'Mesa (OpenGL driver) for Win32'
+VERSION 6.1
+
+EXPORTS
+;
+; ICD API
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvReleaseContext
+ DrvRealizeLayerPalette
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
+
+;
+; Mesa internals - mostly for OSMESA
+ _vbo_CreateContext
+ _vbo_DestroyContext
+ _vbo_InvalidateState
+ _glapi_get_context
+ _glapi_get_proc_address
+ _mesa_buffer_data
+ _mesa_buffer_map
+ _mesa_buffer_subdata
+ _mesa_bzero
+ _mesa_calloc
+ _mesa_choose_tex_format
+ _mesa_compressed_texture_size
+ _mesa_create_framebuffer
+ _mesa_create_visual
+ _mesa_delete_buffer_object
+ _mesa_delete_texture_object
+ _mesa_destroy_framebuffer
+ _mesa_destroy_visual
+ _mesa_enable_1_3_extensions
+ _mesa_enable_1_4_extensions
+ _mesa_enable_1_5_extensions
+ _mesa_enable_sw_extensions
+ _mesa_error
+ _mesa_free
+ _mesa_free_context_data
+ _mesa_get_current_context
+ _mesa_init_default_imports
+ _mesa_init_driver_functions
+ _mesa_initialize_context
+ _mesa_make_current
+ _mesa_memcpy
+ _mesa_memset
+ _mesa_new_buffer_object
+ _mesa_new_texture_object
+ _mesa_problem
+ _mesa_ResizeBuffersMESA
+ _mesa_store_compressed_teximage1d
+ _mesa_store_compressed_teximage2d
+ _mesa_store_compressed_teximage3d
+ _mesa_store_compressed_texsubimage1d
+ _mesa_store_compressed_texsubimage2d
+ _mesa_store_compressed_texsubimage3d
+ _mesa_store_teximage1d
+ _mesa_store_teximage2d
+ _mesa_store_teximage3d
+ _mesa_store_texsubimage1d
+ _mesa_store_texsubimage2d
+ _mesa_store_texsubimage3d
+ _mesa_strcmp
+ _mesa_test_proxy_teximage
+ _mesa_Viewport
+ _swrast_Accum
+ _swrast_Bitmap
+ _swrast_CopyPixels
+ _swrast_DrawBuffer
+ _swrast_DrawPixels
+ _swrast_GetDeviceDriverReference
+ _swrast_Clear
+ _swrast_choose_line
+ _swrast_choose_triangle
+ _swrast_CopyColorSubTable
+ _swrast_CopyColorTable
+ _swrast_CopyConvolutionFilter1D
+ _swrast_CopyConvolutionFilter2D
+ _swrast_copy_teximage1d
+ _swrast_copy_teximage2d
+ _swrast_copy_texsubimage1d
+ _swrast_copy_texsubimage2d
+ _swrast_copy_texsubimage3d
+ _swrast_CreateContext
+ _swrast_DestroyContext
+ _swrast_InvalidateState
+ _swrast_ReadPixels
+ _swsetup_Wakeup
+ _swsetup_CreateContext
+ _swsetup_DestroyContext
+ _swsetup_InvalidateState
+ _tnl_CreateContext
+ _tnl_DestroyContext
+ _tnl_InvalidateState
+ _tnl_MakeCurrent
+ _tnl_run_pipeline
diff --git a/mesalib/src/mesa/gl.pc.in b/mesalib/src/mesa/gl.pc.in
new file mode 100644
index 000000000..97b86596f
--- /dev/null
+++ b/mesalib/src/mesa/gl.pc.in
@@ -0,0 +1,12 @@
+prefix=@INSTALL_DIR@
+exec_prefix=${prefix}
+libdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+
+Name: gl
+Description: Mesa OpenGL library
+Requires.private: @GL_PC_REQ_PRIV@
+Version: @VERSION@
+Libs: -L${libdir} -l@GL_LIB@
+Libs.private: @GL_PC_LIB_PRIV@
+Cflags: -I${includedir} @GL_PC_CFLAGS@
diff --git a/mesalib/src/mesa/glapi/dispatch.h b/mesalib/src/mesa/glapi/dispatch.h
new file mode 100644
index 000000000..0d3204591
--- /dev/null
+++ b/mesalib/src/mesa/glapi/dispatch.h
@@ -0,0 +1,3985 @@
+/* DO NOT EDIT - This file generated automatically by gl_table.py (from Mesa) script */
+
+/*
+ * (C) Copyright IBM Corporation 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined( _DISPATCH_H_ )
+# define _DISPATCH_H_
+
+
+#include "glapitable.h"
+/**
+ * \file dispatch.h
+ * Macros for handling GL dispatch tables.
+ *
+ * For each known GL function, there are 3 macros in this file. The first
+ * macro is named CALL_FuncName and is used to call that GL function using
+ * the specified dispatch table. The other 2 macros, called GET_FuncName
+ * can SET_FuncName, are used to get and set the dispatch pointer for the
+ * named function in the specified dispatch table.
+ */
+
+#define CALL_by_offset(disp, cast, offset, parameters) \
+ (*(cast (GET_by_offset(disp, offset)))) parameters
+#define GET_by_offset(disp, offset) \
+ (offset >= 0) ? (((_glapi_proc *)(disp))[offset]) : NULL
+#define SET_by_offset(disp, offset, fn) \
+ do { \
+ if ( (offset) < 0 ) { \
+ /* fprintf( stderr, "[%s:%u] SET_by_offset(%p, %d, %s)!\n", */ \
+ /* __func__, __LINE__, disp, offset, # fn); */ \
+ /* abort(); */ \
+ } \
+ else { \
+ ( (_glapi_proc *) (disp) )[offset] = (_glapi_proc) fn; \
+ } \
+ } while(0)
+
+#define CALL_NewList(disp, parameters) (*((disp)->NewList)) parameters
+#define GET_NewList(disp) ((disp)->NewList)
+#define SET_NewList(disp, fn) ((disp)->NewList = fn)
+#define CALL_EndList(disp, parameters) (*((disp)->EndList)) parameters
+#define GET_EndList(disp) ((disp)->EndList)
+#define SET_EndList(disp, fn) ((disp)->EndList = fn)
+#define CALL_CallList(disp, parameters) (*((disp)->CallList)) parameters
+#define GET_CallList(disp) ((disp)->CallList)
+#define SET_CallList(disp, fn) ((disp)->CallList = fn)
+#define CALL_CallLists(disp, parameters) (*((disp)->CallLists)) parameters
+#define GET_CallLists(disp) ((disp)->CallLists)
+#define SET_CallLists(disp, fn) ((disp)->CallLists = fn)
+#define CALL_DeleteLists(disp, parameters) (*((disp)->DeleteLists)) parameters
+#define GET_DeleteLists(disp) ((disp)->DeleteLists)
+#define SET_DeleteLists(disp, fn) ((disp)->DeleteLists = fn)
+#define CALL_GenLists(disp, parameters) (*((disp)->GenLists)) parameters
+#define GET_GenLists(disp) ((disp)->GenLists)
+#define SET_GenLists(disp, fn) ((disp)->GenLists = fn)
+#define CALL_ListBase(disp, parameters) (*((disp)->ListBase)) parameters
+#define GET_ListBase(disp) ((disp)->ListBase)
+#define SET_ListBase(disp, fn) ((disp)->ListBase = fn)
+#define CALL_Begin(disp, parameters) (*((disp)->Begin)) parameters
+#define GET_Begin(disp) ((disp)->Begin)
+#define SET_Begin(disp, fn) ((disp)->Begin = fn)
+#define CALL_Bitmap(disp, parameters) (*((disp)->Bitmap)) parameters
+#define GET_Bitmap(disp) ((disp)->Bitmap)
+#define SET_Bitmap(disp, fn) ((disp)->Bitmap = fn)
+#define CALL_Color3b(disp, parameters) (*((disp)->Color3b)) parameters
+#define GET_Color3b(disp) ((disp)->Color3b)
+#define SET_Color3b(disp, fn) ((disp)->Color3b = fn)
+#define CALL_Color3bv(disp, parameters) (*((disp)->Color3bv)) parameters
+#define GET_Color3bv(disp) ((disp)->Color3bv)
+#define SET_Color3bv(disp, fn) ((disp)->Color3bv = fn)
+#define CALL_Color3d(disp, parameters) (*((disp)->Color3d)) parameters
+#define GET_Color3d(disp) ((disp)->Color3d)
+#define SET_Color3d(disp, fn) ((disp)->Color3d = fn)
+#define CALL_Color3dv(disp, parameters) (*((disp)->Color3dv)) parameters
+#define GET_Color3dv(disp) ((disp)->Color3dv)
+#define SET_Color3dv(disp, fn) ((disp)->Color3dv = fn)
+#define CALL_Color3f(disp, parameters) (*((disp)->Color3f)) parameters
+#define GET_Color3f(disp) ((disp)->Color3f)
+#define SET_Color3f(disp, fn) ((disp)->Color3f = fn)
+#define CALL_Color3fv(disp, parameters) (*((disp)->Color3fv)) parameters
+#define GET_Color3fv(disp) ((disp)->Color3fv)
+#define SET_Color3fv(disp, fn) ((disp)->Color3fv = fn)
+#define CALL_Color3i(disp, parameters) (*((disp)->Color3i)) parameters
+#define GET_Color3i(disp) ((disp)->Color3i)
+#define SET_Color3i(disp, fn) ((disp)->Color3i = fn)
+#define CALL_Color3iv(disp, parameters) (*((disp)->Color3iv)) parameters
+#define GET_Color3iv(disp) ((disp)->Color3iv)
+#define SET_Color3iv(disp, fn) ((disp)->Color3iv = fn)
+#define CALL_Color3s(disp, parameters) (*((disp)->Color3s)) parameters
+#define GET_Color3s(disp) ((disp)->Color3s)
+#define SET_Color3s(disp, fn) ((disp)->Color3s = fn)
+#define CALL_Color3sv(disp, parameters) (*((disp)->Color3sv)) parameters
+#define GET_Color3sv(disp) ((disp)->Color3sv)
+#define SET_Color3sv(disp, fn) ((disp)->Color3sv = fn)
+#define CALL_Color3ub(disp, parameters) (*((disp)->Color3ub)) parameters
+#define GET_Color3ub(disp) ((disp)->Color3ub)
+#define SET_Color3ub(disp, fn) ((disp)->Color3ub = fn)
+#define CALL_Color3ubv(disp, parameters) (*((disp)->Color3ubv)) parameters
+#define GET_Color3ubv(disp) ((disp)->Color3ubv)
+#define SET_Color3ubv(disp, fn) ((disp)->Color3ubv = fn)
+#define CALL_Color3ui(disp, parameters) (*((disp)->Color3ui)) parameters
+#define GET_Color3ui(disp) ((disp)->Color3ui)
+#define SET_Color3ui(disp, fn) ((disp)->Color3ui = fn)
+#define CALL_Color3uiv(disp, parameters) (*((disp)->Color3uiv)) parameters
+#define GET_Color3uiv(disp) ((disp)->Color3uiv)
+#define SET_Color3uiv(disp, fn) ((disp)->Color3uiv = fn)
+#define CALL_Color3us(disp, parameters) (*((disp)->Color3us)) parameters
+#define GET_Color3us(disp) ((disp)->Color3us)
+#define SET_Color3us(disp, fn) ((disp)->Color3us = fn)
+#define CALL_Color3usv(disp, parameters) (*((disp)->Color3usv)) parameters
+#define GET_Color3usv(disp) ((disp)->Color3usv)
+#define SET_Color3usv(disp, fn) ((disp)->Color3usv = fn)
+#define CALL_Color4b(disp, parameters) (*((disp)->Color4b)) parameters
+#define GET_Color4b(disp) ((disp)->Color4b)
+#define SET_Color4b(disp, fn) ((disp)->Color4b = fn)
+#define CALL_Color4bv(disp, parameters) (*((disp)->Color4bv)) parameters
+#define GET_Color4bv(disp) ((disp)->Color4bv)
+#define SET_Color4bv(disp, fn) ((disp)->Color4bv = fn)
+#define CALL_Color4d(disp, parameters) (*((disp)->Color4d)) parameters
+#define GET_Color4d(disp) ((disp)->Color4d)
+#define SET_Color4d(disp, fn) ((disp)->Color4d = fn)
+#define CALL_Color4dv(disp, parameters) (*((disp)->Color4dv)) parameters
+#define GET_Color4dv(disp) ((disp)->Color4dv)
+#define SET_Color4dv(disp, fn) ((disp)->Color4dv = fn)
+#define CALL_Color4f(disp, parameters) (*((disp)->Color4f)) parameters
+#define GET_Color4f(disp) ((disp)->Color4f)
+#define SET_Color4f(disp, fn) ((disp)->Color4f = fn)
+#define CALL_Color4fv(disp, parameters) (*((disp)->Color4fv)) parameters
+#define GET_Color4fv(disp) ((disp)->Color4fv)
+#define SET_Color4fv(disp, fn) ((disp)->Color4fv = fn)
+#define CALL_Color4i(disp, parameters) (*((disp)->Color4i)) parameters
+#define GET_Color4i(disp) ((disp)->Color4i)
+#define SET_Color4i(disp, fn) ((disp)->Color4i = fn)
+#define CALL_Color4iv(disp, parameters) (*((disp)->Color4iv)) parameters
+#define GET_Color4iv(disp) ((disp)->Color4iv)
+#define SET_Color4iv(disp, fn) ((disp)->Color4iv = fn)
+#define CALL_Color4s(disp, parameters) (*((disp)->Color4s)) parameters
+#define GET_Color4s(disp) ((disp)->Color4s)
+#define SET_Color4s(disp, fn) ((disp)->Color4s = fn)
+#define CALL_Color4sv(disp, parameters) (*((disp)->Color4sv)) parameters
+#define GET_Color4sv(disp) ((disp)->Color4sv)
+#define SET_Color4sv(disp, fn) ((disp)->Color4sv = fn)
+#define CALL_Color4ub(disp, parameters) (*((disp)->Color4ub)) parameters
+#define GET_Color4ub(disp) ((disp)->Color4ub)
+#define SET_Color4ub(disp, fn) ((disp)->Color4ub = fn)
+#define CALL_Color4ubv(disp, parameters) (*((disp)->Color4ubv)) parameters
+#define GET_Color4ubv(disp) ((disp)->Color4ubv)
+#define SET_Color4ubv(disp, fn) ((disp)->Color4ubv = fn)
+#define CALL_Color4ui(disp, parameters) (*((disp)->Color4ui)) parameters
+#define GET_Color4ui(disp) ((disp)->Color4ui)
+#define SET_Color4ui(disp, fn) ((disp)->Color4ui = fn)
+#define CALL_Color4uiv(disp, parameters) (*((disp)->Color4uiv)) parameters
+#define GET_Color4uiv(disp) ((disp)->Color4uiv)
+#define SET_Color4uiv(disp, fn) ((disp)->Color4uiv = fn)
+#define CALL_Color4us(disp, parameters) (*((disp)->Color4us)) parameters
+#define GET_Color4us(disp) ((disp)->Color4us)
+#define SET_Color4us(disp, fn) ((disp)->Color4us = fn)
+#define CALL_Color4usv(disp, parameters) (*((disp)->Color4usv)) parameters
+#define GET_Color4usv(disp) ((disp)->Color4usv)
+#define SET_Color4usv(disp, fn) ((disp)->Color4usv = fn)
+#define CALL_EdgeFlag(disp, parameters) (*((disp)->EdgeFlag)) parameters
+#define GET_EdgeFlag(disp) ((disp)->EdgeFlag)
+#define SET_EdgeFlag(disp, fn) ((disp)->EdgeFlag = fn)
+#define CALL_EdgeFlagv(disp, parameters) (*((disp)->EdgeFlagv)) parameters
+#define GET_EdgeFlagv(disp) ((disp)->EdgeFlagv)
+#define SET_EdgeFlagv(disp, fn) ((disp)->EdgeFlagv = fn)
+#define CALL_End(disp, parameters) (*((disp)->End)) parameters
+#define GET_End(disp) ((disp)->End)
+#define SET_End(disp, fn) ((disp)->End = fn)
+#define CALL_Indexd(disp, parameters) (*((disp)->Indexd)) parameters
+#define GET_Indexd(disp) ((disp)->Indexd)
+#define SET_Indexd(disp, fn) ((disp)->Indexd = fn)
+#define CALL_Indexdv(disp, parameters) (*((disp)->Indexdv)) parameters
+#define GET_Indexdv(disp) ((disp)->Indexdv)
+#define SET_Indexdv(disp, fn) ((disp)->Indexdv = fn)
+#define CALL_Indexf(disp, parameters) (*((disp)->Indexf)) parameters
+#define GET_Indexf(disp) ((disp)->Indexf)
+#define SET_Indexf(disp, fn) ((disp)->Indexf = fn)
+#define CALL_Indexfv(disp, parameters) (*((disp)->Indexfv)) parameters
+#define GET_Indexfv(disp) ((disp)->Indexfv)
+#define SET_Indexfv(disp, fn) ((disp)->Indexfv = fn)
+#define CALL_Indexi(disp, parameters) (*((disp)->Indexi)) parameters
+#define GET_Indexi(disp) ((disp)->Indexi)
+#define SET_Indexi(disp, fn) ((disp)->Indexi = fn)
+#define CALL_Indexiv(disp, parameters) (*((disp)->Indexiv)) parameters
+#define GET_Indexiv(disp) ((disp)->Indexiv)
+#define SET_Indexiv(disp, fn) ((disp)->Indexiv = fn)
+#define CALL_Indexs(disp, parameters) (*((disp)->Indexs)) parameters
+#define GET_Indexs(disp) ((disp)->Indexs)
+#define SET_Indexs(disp, fn) ((disp)->Indexs = fn)
+#define CALL_Indexsv(disp, parameters) (*((disp)->Indexsv)) parameters
+#define GET_Indexsv(disp) ((disp)->Indexsv)
+#define SET_Indexsv(disp, fn) ((disp)->Indexsv = fn)
+#define CALL_Normal3b(disp, parameters) (*((disp)->Normal3b)) parameters
+#define GET_Normal3b(disp) ((disp)->Normal3b)
+#define SET_Normal3b(disp, fn) ((disp)->Normal3b = fn)
+#define CALL_Normal3bv(disp, parameters) (*((disp)->Normal3bv)) parameters
+#define GET_Normal3bv(disp) ((disp)->Normal3bv)
+#define SET_Normal3bv(disp, fn) ((disp)->Normal3bv = fn)
+#define CALL_Normal3d(disp, parameters) (*((disp)->Normal3d)) parameters
+#define GET_Normal3d(disp) ((disp)->Normal3d)
+#define SET_Normal3d(disp, fn) ((disp)->Normal3d = fn)
+#define CALL_Normal3dv(disp, parameters) (*((disp)->Normal3dv)) parameters
+#define GET_Normal3dv(disp) ((disp)->Normal3dv)
+#define SET_Normal3dv(disp, fn) ((disp)->Normal3dv = fn)
+#define CALL_Normal3f(disp, parameters) (*((disp)->Normal3f)) parameters
+#define GET_Normal3f(disp) ((disp)->Normal3f)
+#define SET_Normal3f(disp, fn) ((disp)->Normal3f = fn)
+#define CALL_Normal3fv(disp, parameters) (*((disp)->Normal3fv)) parameters
+#define GET_Normal3fv(disp) ((disp)->Normal3fv)
+#define SET_Normal3fv(disp, fn) ((disp)->Normal3fv = fn)
+#define CALL_Normal3i(disp, parameters) (*((disp)->Normal3i)) parameters
+#define GET_Normal3i(disp) ((disp)->Normal3i)
+#define SET_Normal3i(disp, fn) ((disp)->Normal3i = fn)
+#define CALL_Normal3iv(disp, parameters) (*((disp)->Normal3iv)) parameters
+#define GET_Normal3iv(disp) ((disp)->Normal3iv)
+#define SET_Normal3iv(disp, fn) ((disp)->Normal3iv = fn)
+#define CALL_Normal3s(disp, parameters) (*((disp)->Normal3s)) parameters
+#define GET_Normal3s(disp) ((disp)->Normal3s)
+#define SET_Normal3s(disp, fn) ((disp)->Normal3s = fn)
+#define CALL_Normal3sv(disp, parameters) (*((disp)->Normal3sv)) parameters
+#define GET_Normal3sv(disp) ((disp)->Normal3sv)
+#define SET_Normal3sv(disp, fn) ((disp)->Normal3sv = fn)
+#define CALL_RasterPos2d(disp, parameters) (*((disp)->RasterPos2d)) parameters
+#define GET_RasterPos2d(disp) ((disp)->RasterPos2d)
+#define SET_RasterPos2d(disp, fn) ((disp)->RasterPos2d = fn)
+#define CALL_RasterPos2dv(disp, parameters) (*((disp)->RasterPos2dv)) parameters
+#define GET_RasterPos2dv(disp) ((disp)->RasterPos2dv)
+#define SET_RasterPos2dv(disp, fn) ((disp)->RasterPos2dv = fn)
+#define CALL_RasterPos2f(disp, parameters) (*((disp)->RasterPos2f)) parameters
+#define GET_RasterPos2f(disp) ((disp)->RasterPos2f)
+#define SET_RasterPos2f(disp, fn) ((disp)->RasterPos2f = fn)
+#define CALL_RasterPos2fv(disp, parameters) (*((disp)->RasterPos2fv)) parameters
+#define GET_RasterPos2fv(disp) ((disp)->RasterPos2fv)
+#define SET_RasterPos2fv(disp, fn) ((disp)->RasterPos2fv = fn)
+#define CALL_RasterPos2i(disp, parameters) (*((disp)->RasterPos2i)) parameters
+#define GET_RasterPos2i(disp) ((disp)->RasterPos2i)
+#define SET_RasterPos2i(disp, fn) ((disp)->RasterPos2i = fn)
+#define CALL_RasterPos2iv(disp, parameters) (*((disp)->RasterPos2iv)) parameters
+#define GET_RasterPos2iv(disp) ((disp)->RasterPos2iv)
+#define SET_RasterPos2iv(disp, fn) ((disp)->RasterPos2iv = fn)
+#define CALL_RasterPos2s(disp, parameters) (*((disp)->RasterPos2s)) parameters
+#define GET_RasterPos2s(disp) ((disp)->RasterPos2s)
+#define SET_RasterPos2s(disp, fn) ((disp)->RasterPos2s = fn)
+#define CALL_RasterPos2sv(disp, parameters) (*((disp)->RasterPos2sv)) parameters
+#define GET_RasterPos2sv(disp) ((disp)->RasterPos2sv)
+#define SET_RasterPos2sv(disp, fn) ((disp)->RasterPos2sv = fn)
+#define CALL_RasterPos3d(disp, parameters) (*((disp)->RasterPos3d)) parameters
+#define GET_RasterPos3d(disp) ((disp)->RasterPos3d)
+#define SET_RasterPos3d(disp, fn) ((disp)->RasterPos3d = fn)
+#define CALL_RasterPos3dv(disp, parameters) (*((disp)->RasterPos3dv)) parameters
+#define GET_RasterPos3dv(disp) ((disp)->RasterPos3dv)
+#define SET_RasterPos3dv(disp, fn) ((disp)->RasterPos3dv = fn)
+#define CALL_RasterPos3f(disp, parameters) (*((disp)->RasterPos3f)) parameters
+#define GET_RasterPos3f(disp) ((disp)->RasterPos3f)
+#define SET_RasterPos3f(disp, fn) ((disp)->RasterPos3f = fn)
+#define CALL_RasterPos3fv(disp, parameters) (*((disp)->RasterPos3fv)) parameters
+#define GET_RasterPos3fv(disp) ((disp)->RasterPos3fv)
+#define SET_RasterPos3fv(disp, fn) ((disp)->RasterPos3fv = fn)
+#define CALL_RasterPos3i(disp, parameters) (*((disp)->RasterPos3i)) parameters
+#define GET_RasterPos3i(disp) ((disp)->RasterPos3i)
+#define SET_RasterPos3i(disp, fn) ((disp)->RasterPos3i = fn)
+#define CALL_RasterPos3iv(disp, parameters) (*((disp)->RasterPos3iv)) parameters
+#define GET_RasterPos3iv(disp) ((disp)->RasterPos3iv)
+#define SET_RasterPos3iv(disp, fn) ((disp)->RasterPos3iv = fn)
+#define CALL_RasterPos3s(disp, parameters) (*((disp)->RasterPos3s)) parameters
+#define GET_RasterPos3s(disp) ((disp)->RasterPos3s)
+#define SET_RasterPos3s(disp, fn) ((disp)->RasterPos3s = fn)
+#define CALL_RasterPos3sv(disp, parameters) (*((disp)->RasterPos3sv)) parameters
+#define GET_RasterPos3sv(disp) ((disp)->RasterPos3sv)
+#define SET_RasterPos3sv(disp, fn) ((disp)->RasterPos3sv = fn)
+#define CALL_RasterPos4d(disp, parameters) (*((disp)->RasterPos4d)) parameters
+#define GET_RasterPos4d(disp) ((disp)->RasterPos4d)
+#define SET_RasterPos4d(disp, fn) ((disp)->RasterPos4d = fn)
+#define CALL_RasterPos4dv(disp, parameters) (*((disp)->RasterPos4dv)) parameters
+#define GET_RasterPos4dv(disp) ((disp)->RasterPos4dv)
+#define SET_RasterPos4dv(disp, fn) ((disp)->RasterPos4dv = fn)
+#define CALL_RasterPos4f(disp, parameters) (*((disp)->RasterPos4f)) parameters
+#define GET_RasterPos4f(disp) ((disp)->RasterPos4f)
+#define SET_RasterPos4f(disp, fn) ((disp)->RasterPos4f = fn)
+#define CALL_RasterPos4fv(disp, parameters) (*((disp)->RasterPos4fv)) parameters
+#define GET_RasterPos4fv(disp) ((disp)->RasterPos4fv)
+#define SET_RasterPos4fv(disp, fn) ((disp)->RasterPos4fv = fn)
+#define CALL_RasterPos4i(disp, parameters) (*((disp)->RasterPos4i)) parameters
+#define GET_RasterPos4i(disp) ((disp)->RasterPos4i)
+#define SET_RasterPos4i(disp, fn) ((disp)->RasterPos4i = fn)
+#define CALL_RasterPos4iv(disp, parameters) (*((disp)->RasterPos4iv)) parameters
+#define GET_RasterPos4iv(disp) ((disp)->RasterPos4iv)
+#define SET_RasterPos4iv(disp, fn) ((disp)->RasterPos4iv = fn)
+#define CALL_RasterPos4s(disp, parameters) (*((disp)->RasterPos4s)) parameters
+#define GET_RasterPos4s(disp) ((disp)->RasterPos4s)
+#define SET_RasterPos4s(disp, fn) ((disp)->RasterPos4s = fn)
+#define CALL_RasterPos4sv(disp, parameters) (*((disp)->RasterPos4sv)) parameters
+#define GET_RasterPos4sv(disp) ((disp)->RasterPos4sv)
+#define SET_RasterPos4sv(disp, fn) ((disp)->RasterPos4sv = fn)
+#define CALL_Rectd(disp, parameters) (*((disp)->Rectd)) parameters
+#define GET_Rectd(disp) ((disp)->Rectd)
+#define SET_Rectd(disp, fn) ((disp)->Rectd = fn)
+#define CALL_Rectdv(disp, parameters) (*((disp)->Rectdv)) parameters
+#define GET_Rectdv(disp) ((disp)->Rectdv)
+#define SET_Rectdv(disp, fn) ((disp)->Rectdv = fn)
+#define CALL_Rectf(disp, parameters) (*((disp)->Rectf)) parameters
+#define GET_Rectf(disp) ((disp)->Rectf)
+#define SET_Rectf(disp, fn) ((disp)->Rectf = fn)
+#define CALL_Rectfv(disp, parameters) (*((disp)->Rectfv)) parameters
+#define GET_Rectfv(disp) ((disp)->Rectfv)
+#define SET_Rectfv(disp, fn) ((disp)->Rectfv = fn)
+#define CALL_Recti(disp, parameters) (*((disp)->Recti)) parameters
+#define GET_Recti(disp) ((disp)->Recti)
+#define SET_Recti(disp, fn) ((disp)->Recti = fn)
+#define CALL_Rectiv(disp, parameters) (*((disp)->Rectiv)) parameters
+#define GET_Rectiv(disp) ((disp)->Rectiv)
+#define SET_Rectiv(disp, fn) ((disp)->Rectiv = fn)
+#define CALL_Rects(disp, parameters) (*((disp)->Rects)) parameters
+#define GET_Rects(disp) ((disp)->Rects)
+#define SET_Rects(disp, fn) ((disp)->Rects = fn)
+#define CALL_Rectsv(disp, parameters) (*((disp)->Rectsv)) parameters
+#define GET_Rectsv(disp) ((disp)->Rectsv)
+#define SET_Rectsv(disp, fn) ((disp)->Rectsv = fn)
+#define CALL_TexCoord1d(disp, parameters) (*((disp)->TexCoord1d)) parameters
+#define GET_TexCoord1d(disp) ((disp)->TexCoord1d)
+#define SET_TexCoord1d(disp, fn) ((disp)->TexCoord1d = fn)
+#define CALL_TexCoord1dv(disp, parameters) (*((disp)->TexCoord1dv)) parameters
+#define GET_TexCoord1dv(disp) ((disp)->TexCoord1dv)
+#define SET_TexCoord1dv(disp, fn) ((disp)->TexCoord1dv = fn)
+#define CALL_TexCoord1f(disp, parameters) (*((disp)->TexCoord1f)) parameters
+#define GET_TexCoord1f(disp) ((disp)->TexCoord1f)
+#define SET_TexCoord1f(disp, fn) ((disp)->TexCoord1f = fn)
+#define CALL_TexCoord1fv(disp, parameters) (*((disp)->TexCoord1fv)) parameters
+#define GET_TexCoord1fv(disp) ((disp)->TexCoord1fv)
+#define SET_TexCoord1fv(disp, fn) ((disp)->TexCoord1fv = fn)
+#define CALL_TexCoord1i(disp, parameters) (*((disp)->TexCoord1i)) parameters
+#define GET_TexCoord1i(disp) ((disp)->TexCoord1i)
+#define SET_TexCoord1i(disp, fn) ((disp)->TexCoord1i = fn)
+#define CALL_TexCoord1iv(disp, parameters) (*((disp)->TexCoord1iv)) parameters
+#define GET_TexCoord1iv(disp) ((disp)->TexCoord1iv)
+#define SET_TexCoord1iv(disp, fn) ((disp)->TexCoord1iv = fn)
+#define CALL_TexCoord1s(disp, parameters) (*((disp)->TexCoord1s)) parameters
+#define GET_TexCoord1s(disp) ((disp)->TexCoord1s)
+#define SET_TexCoord1s(disp, fn) ((disp)->TexCoord1s = fn)
+#define CALL_TexCoord1sv(disp, parameters) (*((disp)->TexCoord1sv)) parameters
+#define GET_TexCoord1sv(disp) ((disp)->TexCoord1sv)
+#define SET_TexCoord1sv(disp, fn) ((disp)->TexCoord1sv = fn)
+#define CALL_TexCoord2d(disp, parameters) (*((disp)->TexCoord2d)) parameters
+#define GET_TexCoord2d(disp) ((disp)->TexCoord2d)
+#define SET_TexCoord2d(disp, fn) ((disp)->TexCoord2d = fn)
+#define CALL_TexCoord2dv(disp, parameters) (*((disp)->TexCoord2dv)) parameters
+#define GET_TexCoord2dv(disp) ((disp)->TexCoord2dv)
+#define SET_TexCoord2dv(disp, fn) ((disp)->TexCoord2dv = fn)
+#define CALL_TexCoord2f(disp, parameters) (*((disp)->TexCoord2f)) parameters
+#define GET_TexCoord2f(disp) ((disp)->TexCoord2f)
+#define SET_TexCoord2f(disp, fn) ((disp)->TexCoord2f = fn)
+#define CALL_TexCoord2fv(disp, parameters) (*((disp)->TexCoord2fv)) parameters
+#define GET_TexCoord2fv(disp) ((disp)->TexCoord2fv)
+#define SET_TexCoord2fv(disp, fn) ((disp)->TexCoord2fv = fn)
+#define CALL_TexCoord2i(disp, parameters) (*((disp)->TexCoord2i)) parameters
+#define GET_TexCoord2i(disp) ((disp)->TexCoord2i)
+#define SET_TexCoord2i(disp, fn) ((disp)->TexCoord2i = fn)
+#define CALL_TexCoord2iv(disp, parameters) (*((disp)->TexCoord2iv)) parameters
+#define GET_TexCoord2iv(disp) ((disp)->TexCoord2iv)
+#define SET_TexCoord2iv(disp, fn) ((disp)->TexCoord2iv = fn)
+#define CALL_TexCoord2s(disp, parameters) (*((disp)->TexCoord2s)) parameters
+#define GET_TexCoord2s(disp) ((disp)->TexCoord2s)
+#define SET_TexCoord2s(disp, fn) ((disp)->TexCoord2s = fn)
+#define CALL_TexCoord2sv(disp, parameters) (*((disp)->TexCoord2sv)) parameters
+#define GET_TexCoord2sv(disp) ((disp)->TexCoord2sv)
+#define SET_TexCoord2sv(disp, fn) ((disp)->TexCoord2sv = fn)
+#define CALL_TexCoord3d(disp, parameters) (*((disp)->TexCoord3d)) parameters
+#define GET_TexCoord3d(disp) ((disp)->TexCoord3d)
+#define SET_TexCoord3d(disp, fn) ((disp)->TexCoord3d = fn)
+#define CALL_TexCoord3dv(disp, parameters) (*((disp)->TexCoord3dv)) parameters
+#define GET_TexCoord3dv(disp) ((disp)->TexCoord3dv)
+#define SET_TexCoord3dv(disp, fn) ((disp)->TexCoord3dv = fn)
+#define CALL_TexCoord3f(disp, parameters) (*((disp)->TexCoord3f)) parameters
+#define GET_TexCoord3f(disp) ((disp)->TexCoord3f)
+#define SET_TexCoord3f(disp, fn) ((disp)->TexCoord3f = fn)
+#define CALL_TexCoord3fv(disp, parameters) (*((disp)->TexCoord3fv)) parameters
+#define GET_TexCoord3fv(disp) ((disp)->TexCoord3fv)
+#define SET_TexCoord3fv(disp, fn) ((disp)->TexCoord3fv = fn)
+#define CALL_TexCoord3i(disp, parameters) (*((disp)->TexCoord3i)) parameters
+#define GET_TexCoord3i(disp) ((disp)->TexCoord3i)
+#define SET_TexCoord3i(disp, fn) ((disp)->TexCoord3i = fn)
+#define CALL_TexCoord3iv(disp, parameters) (*((disp)->TexCoord3iv)) parameters
+#define GET_TexCoord3iv(disp) ((disp)->TexCoord3iv)
+#define SET_TexCoord3iv(disp, fn) ((disp)->TexCoord3iv = fn)
+#define CALL_TexCoord3s(disp, parameters) (*((disp)->TexCoord3s)) parameters
+#define GET_TexCoord3s(disp) ((disp)->TexCoord3s)
+#define SET_TexCoord3s(disp, fn) ((disp)->TexCoord3s = fn)
+#define CALL_TexCoord3sv(disp, parameters) (*((disp)->TexCoord3sv)) parameters
+#define GET_TexCoord3sv(disp) ((disp)->TexCoord3sv)
+#define SET_TexCoord3sv(disp, fn) ((disp)->TexCoord3sv = fn)
+#define CALL_TexCoord4d(disp, parameters) (*((disp)->TexCoord4d)) parameters
+#define GET_TexCoord4d(disp) ((disp)->TexCoord4d)
+#define SET_TexCoord4d(disp, fn) ((disp)->TexCoord4d = fn)
+#define CALL_TexCoord4dv(disp, parameters) (*((disp)->TexCoord4dv)) parameters
+#define GET_TexCoord4dv(disp) ((disp)->TexCoord4dv)
+#define SET_TexCoord4dv(disp, fn) ((disp)->TexCoord4dv = fn)
+#define CALL_TexCoord4f(disp, parameters) (*((disp)->TexCoord4f)) parameters
+#define GET_TexCoord4f(disp) ((disp)->TexCoord4f)
+#define SET_TexCoord4f(disp, fn) ((disp)->TexCoord4f = fn)
+#define CALL_TexCoord4fv(disp, parameters) (*((disp)->TexCoord4fv)) parameters
+#define GET_TexCoord4fv(disp) ((disp)->TexCoord4fv)
+#define SET_TexCoord4fv(disp, fn) ((disp)->TexCoord4fv = fn)
+#define CALL_TexCoord4i(disp, parameters) (*((disp)->TexCoord4i)) parameters
+#define GET_TexCoord4i(disp) ((disp)->TexCoord4i)
+#define SET_TexCoord4i(disp, fn) ((disp)->TexCoord4i = fn)
+#define CALL_TexCoord4iv(disp, parameters) (*((disp)->TexCoord4iv)) parameters
+#define GET_TexCoord4iv(disp) ((disp)->TexCoord4iv)
+#define SET_TexCoord4iv(disp, fn) ((disp)->TexCoord4iv = fn)
+#define CALL_TexCoord4s(disp, parameters) (*((disp)->TexCoord4s)) parameters
+#define GET_TexCoord4s(disp) ((disp)->TexCoord4s)
+#define SET_TexCoord4s(disp, fn) ((disp)->TexCoord4s = fn)
+#define CALL_TexCoord4sv(disp, parameters) (*((disp)->TexCoord4sv)) parameters
+#define GET_TexCoord4sv(disp) ((disp)->TexCoord4sv)
+#define SET_TexCoord4sv(disp, fn) ((disp)->TexCoord4sv = fn)
+#define CALL_Vertex2d(disp, parameters) (*((disp)->Vertex2d)) parameters
+#define GET_Vertex2d(disp) ((disp)->Vertex2d)
+#define SET_Vertex2d(disp, fn) ((disp)->Vertex2d = fn)
+#define CALL_Vertex2dv(disp, parameters) (*((disp)->Vertex2dv)) parameters
+#define GET_Vertex2dv(disp) ((disp)->Vertex2dv)
+#define SET_Vertex2dv(disp, fn) ((disp)->Vertex2dv = fn)
+#define CALL_Vertex2f(disp, parameters) (*((disp)->Vertex2f)) parameters
+#define GET_Vertex2f(disp) ((disp)->Vertex2f)
+#define SET_Vertex2f(disp, fn) ((disp)->Vertex2f = fn)
+#define CALL_Vertex2fv(disp, parameters) (*((disp)->Vertex2fv)) parameters
+#define GET_Vertex2fv(disp) ((disp)->Vertex2fv)
+#define SET_Vertex2fv(disp, fn) ((disp)->Vertex2fv = fn)
+#define CALL_Vertex2i(disp, parameters) (*((disp)->Vertex2i)) parameters
+#define GET_Vertex2i(disp) ((disp)->Vertex2i)
+#define SET_Vertex2i(disp, fn) ((disp)->Vertex2i = fn)
+#define CALL_Vertex2iv(disp, parameters) (*((disp)->Vertex2iv)) parameters
+#define GET_Vertex2iv(disp) ((disp)->Vertex2iv)
+#define SET_Vertex2iv(disp, fn) ((disp)->Vertex2iv = fn)
+#define CALL_Vertex2s(disp, parameters) (*((disp)->Vertex2s)) parameters
+#define GET_Vertex2s(disp) ((disp)->Vertex2s)
+#define SET_Vertex2s(disp, fn) ((disp)->Vertex2s = fn)
+#define CALL_Vertex2sv(disp, parameters) (*((disp)->Vertex2sv)) parameters
+#define GET_Vertex2sv(disp) ((disp)->Vertex2sv)
+#define SET_Vertex2sv(disp, fn) ((disp)->Vertex2sv = fn)
+#define CALL_Vertex3d(disp, parameters) (*((disp)->Vertex3d)) parameters
+#define GET_Vertex3d(disp) ((disp)->Vertex3d)
+#define SET_Vertex3d(disp, fn) ((disp)->Vertex3d = fn)
+#define CALL_Vertex3dv(disp, parameters) (*((disp)->Vertex3dv)) parameters
+#define GET_Vertex3dv(disp) ((disp)->Vertex3dv)
+#define SET_Vertex3dv(disp, fn) ((disp)->Vertex3dv = fn)
+#define CALL_Vertex3f(disp, parameters) (*((disp)->Vertex3f)) parameters
+#define GET_Vertex3f(disp) ((disp)->Vertex3f)
+#define SET_Vertex3f(disp, fn) ((disp)->Vertex3f = fn)
+#define CALL_Vertex3fv(disp, parameters) (*((disp)->Vertex3fv)) parameters
+#define GET_Vertex3fv(disp) ((disp)->Vertex3fv)
+#define SET_Vertex3fv(disp, fn) ((disp)->Vertex3fv = fn)
+#define CALL_Vertex3i(disp, parameters) (*((disp)->Vertex3i)) parameters
+#define GET_Vertex3i(disp) ((disp)->Vertex3i)
+#define SET_Vertex3i(disp, fn) ((disp)->Vertex3i = fn)
+#define CALL_Vertex3iv(disp, parameters) (*((disp)->Vertex3iv)) parameters
+#define GET_Vertex3iv(disp) ((disp)->Vertex3iv)
+#define SET_Vertex3iv(disp, fn) ((disp)->Vertex3iv = fn)
+#define CALL_Vertex3s(disp, parameters) (*((disp)->Vertex3s)) parameters
+#define GET_Vertex3s(disp) ((disp)->Vertex3s)
+#define SET_Vertex3s(disp, fn) ((disp)->Vertex3s = fn)
+#define CALL_Vertex3sv(disp, parameters) (*((disp)->Vertex3sv)) parameters
+#define GET_Vertex3sv(disp) ((disp)->Vertex3sv)
+#define SET_Vertex3sv(disp, fn) ((disp)->Vertex3sv = fn)
+#define CALL_Vertex4d(disp, parameters) (*((disp)->Vertex4d)) parameters
+#define GET_Vertex4d(disp) ((disp)->Vertex4d)
+#define SET_Vertex4d(disp, fn) ((disp)->Vertex4d = fn)
+#define CALL_Vertex4dv(disp, parameters) (*((disp)->Vertex4dv)) parameters
+#define GET_Vertex4dv(disp) ((disp)->Vertex4dv)
+#define SET_Vertex4dv(disp, fn) ((disp)->Vertex4dv = fn)
+#define CALL_Vertex4f(disp, parameters) (*((disp)->Vertex4f)) parameters
+#define GET_Vertex4f(disp) ((disp)->Vertex4f)
+#define SET_Vertex4f(disp, fn) ((disp)->Vertex4f = fn)
+#define CALL_Vertex4fv(disp, parameters) (*((disp)->Vertex4fv)) parameters
+#define GET_Vertex4fv(disp) ((disp)->Vertex4fv)
+#define SET_Vertex4fv(disp, fn) ((disp)->Vertex4fv = fn)
+#define CALL_Vertex4i(disp, parameters) (*((disp)->Vertex4i)) parameters
+#define GET_Vertex4i(disp) ((disp)->Vertex4i)
+#define SET_Vertex4i(disp, fn) ((disp)->Vertex4i = fn)
+#define CALL_Vertex4iv(disp, parameters) (*((disp)->Vertex4iv)) parameters
+#define GET_Vertex4iv(disp) ((disp)->Vertex4iv)
+#define SET_Vertex4iv(disp, fn) ((disp)->Vertex4iv = fn)
+#define CALL_Vertex4s(disp, parameters) (*((disp)->Vertex4s)) parameters
+#define GET_Vertex4s(disp) ((disp)->Vertex4s)
+#define SET_Vertex4s(disp, fn) ((disp)->Vertex4s = fn)
+#define CALL_Vertex4sv(disp, parameters) (*((disp)->Vertex4sv)) parameters
+#define GET_Vertex4sv(disp) ((disp)->Vertex4sv)
+#define SET_Vertex4sv(disp, fn) ((disp)->Vertex4sv = fn)
+#define CALL_ClipPlane(disp, parameters) (*((disp)->ClipPlane)) parameters
+#define GET_ClipPlane(disp) ((disp)->ClipPlane)
+#define SET_ClipPlane(disp, fn) ((disp)->ClipPlane = fn)
+#define CALL_ColorMaterial(disp, parameters) (*((disp)->ColorMaterial)) parameters
+#define GET_ColorMaterial(disp) ((disp)->ColorMaterial)
+#define SET_ColorMaterial(disp, fn) ((disp)->ColorMaterial = fn)
+#define CALL_CullFace(disp, parameters) (*((disp)->CullFace)) parameters
+#define GET_CullFace(disp) ((disp)->CullFace)
+#define SET_CullFace(disp, fn) ((disp)->CullFace = fn)
+#define CALL_Fogf(disp, parameters) (*((disp)->Fogf)) parameters
+#define GET_Fogf(disp) ((disp)->Fogf)
+#define SET_Fogf(disp, fn) ((disp)->Fogf = fn)
+#define CALL_Fogfv(disp, parameters) (*((disp)->Fogfv)) parameters
+#define GET_Fogfv(disp) ((disp)->Fogfv)
+#define SET_Fogfv(disp, fn) ((disp)->Fogfv = fn)
+#define CALL_Fogi(disp, parameters) (*((disp)->Fogi)) parameters
+#define GET_Fogi(disp) ((disp)->Fogi)
+#define SET_Fogi(disp, fn) ((disp)->Fogi = fn)
+#define CALL_Fogiv(disp, parameters) (*((disp)->Fogiv)) parameters
+#define GET_Fogiv(disp) ((disp)->Fogiv)
+#define SET_Fogiv(disp, fn) ((disp)->Fogiv = fn)
+#define CALL_FrontFace(disp, parameters) (*((disp)->FrontFace)) parameters
+#define GET_FrontFace(disp) ((disp)->FrontFace)
+#define SET_FrontFace(disp, fn) ((disp)->FrontFace = fn)
+#define CALL_Hint(disp, parameters) (*((disp)->Hint)) parameters
+#define GET_Hint(disp) ((disp)->Hint)
+#define SET_Hint(disp, fn) ((disp)->Hint = fn)
+#define CALL_Lightf(disp, parameters) (*((disp)->Lightf)) parameters
+#define GET_Lightf(disp) ((disp)->Lightf)
+#define SET_Lightf(disp, fn) ((disp)->Lightf = fn)
+#define CALL_Lightfv(disp, parameters) (*((disp)->Lightfv)) parameters
+#define GET_Lightfv(disp) ((disp)->Lightfv)
+#define SET_Lightfv(disp, fn) ((disp)->Lightfv = fn)
+#define CALL_Lighti(disp, parameters) (*((disp)->Lighti)) parameters
+#define GET_Lighti(disp) ((disp)->Lighti)
+#define SET_Lighti(disp, fn) ((disp)->Lighti = fn)
+#define CALL_Lightiv(disp, parameters) (*((disp)->Lightiv)) parameters
+#define GET_Lightiv(disp) ((disp)->Lightiv)
+#define SET_Lightiv(disp, fn) ((disp)->Lightiv = fn)
+#define CALL_LightModelf(disp, parameters) (*((disp)->LightModelf)) parameters
+#define GET_LightModelf(disp) ((disp)->LightModelf)
+#define SET_LightModelf(disp, fn) ((disp)->LightModelf = fn)
+#define CALL_LightModelfv(disp, parameters) (*((disp)->LightModelfv)) parameters
+#define GET_LightModelfv(disp) ((disp)->LightModelfv)
+#define SET_LightModelfv(disp, fn) ((disp)->LightModelfv = fn)
+#define CALL_LightModeli(disp, parameters) (*((disp)->LightModeli)) parameters
+#define GET_LightModeli(disp) ((disp)->LightModeli)
+#define SET_LightModeli(disp, fn) ((disp)->LightModeli = fn)
+#define CALL_LightModeliv(disp, parameters) (*((disp)->LightModeliv)) parameters
+#define GET_LightModeliv(disp) ((disp)->LightModeliv)
+#define SET_LightModeliv(disp, fn) ((disp)->LightModeliv = fn)
+#define CALL_LineStipple(disp, parameters) (*((disp)->LineStipple)) parameters
+#define GET_LineStipple(disp) ((disp)->LineStipple)
+#define SET_LineStipple(disp, fn) ((disp)->LineStipple = fn)
+#define CALL_LineWidth(disp, parameters) (*((disp)->LineWidth)) parameters
+#define GET_LineWidth(disp) ((disp)->LineWidth)
+#define SET_LineWidth(disp, fn) ((disp)->LineWidth = fn)
+#define CALL_Materialf(disp, parameters) (*((disp)->Materialf)) parameters
+#define GET_Materialf(disp) ((disp)->Materialf)
+#define SET_Materialf(disp, fn) ((disp)->Materialf = fn)
+#define CALL_Materialfv(disp, parameters) (*((disp)->Materialfv)) parameters
+#define GET_Materialfv(disp) ((disp)->Materialfv)
+#define SET_Materialfv(disp, fn) ((disp)->Materialfv = fn)
+#define CALL_Materiali(disp, parameters) (*((disp)->Materiali)) parameters
+#define GET_Materiali(disp) ((disp)->Materiali)
+#define SET_Materiali(disp, fn) ((disp)->Materiali = fn)
+#define CALL_Materialiv(disp, parameters) (*((disp)->Materialiv)) parameters
+#define GET_Materialiv(disp) ((disp)->Materialiv)
+#define SET_Materialiv(disp, fn) ((disp)->Materialiv = fn)
+#define CALL_PointSize(disp, parameters) (*((disp)->PointSize)) parameters
+#define GET_PointSize(disp) ((disp)->PointSize)
+#define SET_PointSize(disp, fn) ((disp)->PointSize = fn)
+#define CALL_PolygonMode(disp, parameters) (*((disp)->PolygonMode)) parameters
+#define GET_PolygonMode(disp) ((disp)->PolygonMode)
+#define SET_PolygonMode(disp, fn) ((disp)->PolygonMode = fn)
+#define CALL_PolygonStipple(disp, parameters) (*((disp)->PolygonStipple)) parameters
+#define GET_PolygonStipple(disp) ((disp)->PolygonStipple)
+#define SET_PolygonStipple(disp, fn) ((disp)->PolygonStipple = fn)
+#define CALL_Scissor(disp, parameters) (*((disp)->Scissor)) parameters
+#define GET_Scissor(disp) ((disp)->Scissor)
+#define SET_Scissor(disp, fn) ((disp)->Scissor = fn)
+#define CALL_ShadeModel(disp, parameters) (*((disp)->ShadeModel)) parameters
+#define GET_ShadeModel(disp) ((disp)->ShadeModel)
+#define SET_ShadeModel(disp, fn) ((disp)->ShadeModel = fn)
+#define CALL_TexParameterf(disp, parameters) (*((disp)->TexParameterf)) parameters
+#define GET_TexParameterf(disp) ((disp)->TexParameterf)
+#define SET_TexParameterf(disp, fn) ((disp)->TexParameterf = fn)
+#define CALL_TexParameterfv(disp, parameters) (*((disp)->TexParameterfv)) parameters
+#define GET_TexParameterfv(disp) ((disp)->TexParameterfv)
+#define SET_TexParameterfv(disp, fn) ((disp)->TexParameterfv = fn)
+#define CALL_TexParameteri(disp, parameters) (*((disp)->TexParameteri)) parameters
+#define GET_TexParameteri(disp) ((disp)->TexParameteri)
+#define SET_TexParameteri(disp, fn) ((disp)->TexParameteri = fn)
+#define CALL_TexParameteriv(disp, parameters) (*((disp)->TexParameteriv)) parameters
+#define GET_TexParameteriv(disp) ((disp)->TexParameteriv)
+#define SET_TexParameteriv(disp, fn) ((disp)->TexParameteriv = fn)
+#define CALL_TexImage1D(disp, parameters) (*((disp)->TexImage1D)) parameters
+#define GET_TexImage1D(disp) ((disp)->TexImage1D)
+#define SET_TexImage1D(disp, fn) ((disp)->TexImage1D = fn)
+#define CALL_TexImage2D(disp, parameters) (*((disp)->TexImage2D)) parameters
+#define GET_TexImage2D(disp) ((disp)->TexImage2D)
+#define SET_TexImage2D(disp, fn) ((disp)->TexImage2D = fn)
+#define CALL_TexEnvf(disp, parameters) (*((disp)->TexEnvf)) parameters
+#define GET_TexEnvf(disp) ((disp)->TexEnvf)
+#define SET_TexEnvf(disp, fn) ((disp)->TexEnvf = fn)
+#define CALL_TexEnvfv(disp, parameters) (*((disp)->TexEnvfv)) parameters
+#define GET_TexEnvfv(disp) ((disp)->TexEnvfv)
+#define SET_TexEnvfv(disp, fn) ((disp)->TexEnvfv = fn)
+#define CALL_TexEnvi(disp, parameters) (*((disp)->TexEnvi)) parameters
+#define GET_TexEnvi(disp) ((disp)->TexEnvi)
+#define SET_TexEnvi(disp, fn) ((disp)->TexEnvi = fn)
+#define CALL_TexEnviv(disp, parameters) (*((disp)->TexEnviv)) parameters
+#define GET_TexEnviv(disp) ((disp)->TexEnviv)
+#define SET_TexEnviv(disp, fn) ((disp)->TexEnviv = fn)
+#define CALL_TexGend(disp, parameters) (*((disp)->TexGend)) parameters
+#define GET_TexGend(disp) ((disp)->TexGend)
+#define SET_TexGend(disp, fn) ((disp)->TexGend = fn)
+#define CALL_TexGendv(disp, parameters) (*((disp)->TexGendv)) parameters
+#define GET_TexGendv(disp) ((disp)->TexGendv)
+#define SET_TexGendv(disp, fn) ((disp)->TexGendv = fn)
+#define CALL_TexGenf(disp, parameters) (*((disp)->TexGenf)) parameters
+#define GET_TexGenf(disp) ((disp)->TexGenf)
+#define SET_TexGenf(disp, fn) ((disp)->TexGenf = fn)
+#define CALL_TexGenfv(disp, parameters) (*((disp)->TexGenfv)) parameters
+#define GET_TexGenfv(disp) ((disp)->TexGenfv)
+#define SET_TexGenfv(disp, fn) ((disp)->TexGenfv = fn)
+#define CALL_TexGeni(disp, parameters) (*((disp)->TexGeni)) parameters
+#define GET_TexGeni(disp) ((disp)->TexGeni)
+#define SET_TexGeni(disp, fn) ((disp)->TexGeni = fn)
+#define CALL_TexGeniv(disp, parameters) (*((disp)->TexGeniv)) parameters
+#define GET_TexGeniv(disp) ((disp)->TexGeniv)
+#define SET_TexGeniv(disp, fn) ((disp)->TexGeniv = fn)
+#define CALL_FeedbackBuffer(disp, parameters) (*((disp)->FeedbackBuffer)) parameters
+#define GET_FeedbackBuffer(disp) ((disp)->FeedbackBuffer)
+#define SET_FeedbackBuffer(disp, fn) ((disp)->FeedbackBuffer = fn)
+#define CALL_SelectBuffer(disp, parameters) (*((disp)->SelectBuffer)) parameters
+#define GET_SelectBuffer(disp) ((disp)->SelectBuffer)
+#define SET_SelectBuffer(disp, fn) ((disp)->SelectBuffer = fn)
+#define CALL_RenderMode(disp, parameters) (*((disp)->RenderMode)) parameters
+#define GET_RenderMode(disp) ((disp)->RenderMode)
+#define SET_RenderMode(disp, fn) ((disp)->RenderMode = fn)
+#define CALL_InitNames(disp, parameters) (*((disp)->InitNames)) parameters
+#define GET_InitNames(disp) ((disp)->InitNames)
+#define SET_InitNames(disp, fn) ((disp)->InitNames = fn)
+#define CALL_LoadName(disp, parameters) (*((disp)->LoadName)) parameters
+#define GET_LoadName(disp) ((disp)->LoadName)
+#define SET_LoadName(disp, fn) ((disp)->LoadName = fn)
+#define CALL_PassThrough(disp, parameters) (*((disp)->PassThrough)) parameters
+#define GET_PassThrough(disp) ((disp)->PassThrough)
+#define SET_PassThrough(disp, fn) ((disp)->PassThrough = fn)
+#define CALL_PopName(disp, parameters) (*((disp)->PopName)) parameters
+#define GET_PopName(disp) ((disp)->PopName)
+#define SET_PopName(disp, fn) ((disp)->PopName = fn)
+#define CALL_PushName(disp, parameters) (*((disp)->PushName)) parameters
+#define GET_PushName(disp) ((disp)->PushName)
+#define SET_PushName(disp, fn) ((disp)->PushName = fn)
+#define CALL_DrawBuffer(disp, parameters) (*((disp)->DrawBuffer)) parameters
+#define GET_DrawBuffer(disp) ((disp)->DrawBuffer)
+#define SET_DrawBuffer(disp, fn) ((disp)->DrawBuffer = fn)
+#define CALL_Clear(disp, parameters) (*((disp)->Clear)) parameters
+#define GET_Clear(disp) ((disp)->Clear)
+#define SET_Clear(disp, fn) ((disp)->Clear = fn)
+#define CALL_ClearAccum(disp, parameters) (*((disp)->ClearAccum)) parameters
+#define GET_ClearAccum(disp) ((disp)->ClearAccum)
+#define SET_ClearAccum(disp, fn) ((disp)->ClearAccum = fn)
+#define CALL_ClearIndex(disp, parameters) (*((disp)->ClearIndex)) parameters
+#define GET_ClearIndex(disp) ((disp)->ClearIndex)
+#define SET_ClearIndex(disp, fn) ((disp)->ClearIndex = fn)
+#define CALL_ClearColor(disp, parameters) (*((disp)->ClearColor)) parameters
+#define GET_ClearColor(disp) ((disp)->ClearColor)
+#define SET_ClearColor(disp, fn) ((disp)->ClearColor = fn)
+#define CALL_ClearStencil(disp, parameters) (*((disp)->ClearStencil)) parameters
+#define GET_ClearStencil(disp) ((disp)->ClearStencil)
+#define SET_ClearStencil(disp, fn) ((disp)->ClearStencil = fn)
+#define CALL_ClearDepth(disp, parameters) (*((disp)->ClearDepth)) parameters
+#define GET_ClearDepth(disp) ((disp)->ClearDepth)
+#define SET_ClearDepth(disp, fn) ((disp)->ClearDepth = fn)
+#define CALL_StencilMask(disp, parameters) (*((disp)->StencilMask)) parameters
+#define GET_StencilMask(disp) ((disp)->StencilMask)
+#define SET_StencilMask(disp, fn) ((disp)->StencilMask = fn)
+#define CALL_ColorMask(disp, parameters) (*((disp)->ColorMask)) parameters
+#define GET_ColorMask(disp) ((disp)->ColorMask)
+#define SET_ColorMask(disp, fn) ((disp)->ColorMask = fn)
+#define CALL_DepthMask(disp, parameters) (*((disp)->DepthMask)) parameters
+#define GET_DepthMask(disp) ((disp)->DepthMask)
+#define SET_DepthMask(disp, fn) ((disp)->DepthMask = fn)
+#define CALL_IndexMask(disp, parameters) (*((disp)->IndexMask)) parameters
+#define GET_IndexMask(disp) ((disp)->IndexMask)
+#define SET_IndexMask(disp, fn) ((disp)->IndexMask = fn)
+#define CALL_Accum(disp, parameters) (*((disp)->Accum)) parameters
+#define GET_Accum(disp) ((disp)->Accum)
+#define SET_Accum(disp, fn) ((disp)->Accum = fn)
+#define CALL_Disable(disp, parameters) (*((disp)->Disable)) parameters
+#define GET_Disable(disp) ((disp)->Disable)
+#define SET_Disable(disp, fn) ((disp)->Disable = fn)
+#define CALL_Enable(disp, parameters) (*((disp)->Enable)) parameters
+#define GET_Enable(disp) ((disp)->Enable)
+#define SET_Enable(disp, fn) ((disp)->Enable = fn)
+#define CALL_Finish(disp, parameters) (*((disp)->Finish)) parameters
+#define GET_Finish(disp) ((disp)->Finish)
+#define SET_Finish(disp, fn) ((disp)->Finish = fn)
+#define CALL_Flush(disp, parameters) (*((disp)->Flush)) parameters
+#define GET_Flush(disp) ((disp)->Flush)
+#define SET_Flush(disp, fn) ((disp)->Flush = fn)
+#define CALL_PopAttrib(disp, parameters) (*((disp)->PopAttrib)) parameters
+#define GET_PopAttrib(disp) ((disp)->PopAttrib)
+#define SET_PopAttrib(disp, fn) ((disp)->PopAttrib = fn)
+#define CALL_PushAttrib(disp, parameters) (*((disp)->PushAttrib)) parameters
+#define GET_PushAttrib(disp) ((disp)->PushAttrib)
+#define SET_PushAttrib(disp, fn) ((disp)->PushAttrib = fn)
+#define CALL_Map1d(disp, parameters) (*((disp)->Map1d)) parameters
+#define GET_Map1d(disp) ((disp)->Map1d)
+#define SET_Map1d(disp, fn) ((disp)->Map1d = fn)
+#define CALL_Map1f(disp, parameters) (*((disp)->Map1f)) parameters
+#define GET_Map1f(disp) ((disp)->Map1f)
+#define SET_Map1f(disp, fn) ((disp)->Map1f = fn)
+#define CALL_Map2d(disp, parameters) (*((disp)->Map2d)) parameters
+#define GET_Map2d(disp) ((disp)->Map2d)
+#define SET_Map2d(disp, fn) ((disp)->Map2d = fn)
+#define CALL_Map2f(disp, parameters) (*((disp)->Map2f)) parameters
+#define GET_Map2f(disp) ((disp)->Map2f)
+#define SET_Map2f(disp, fn) ((disp)->Map2f = fn)
+#define CALL_MapGrid1d(disp, parameters) (*((disp)->MapGrid1d)) parameters
+#define GET_MapGrid1d(disp) ((disp)->MapGrid1d)
+#define SET_MapGrid1d(disp, fn) ((disp)->MapGrid1d = fn)
+#define CALL_MapGrid1f(disp, parameters) (*((disp)->MapGrid1f)) parameters
+#define GET_MapGrid1f(disp) ((disp)->MapGrid1f)
+#define SET_MapGrid1f(disp, fn) ((disp)->MapGrid1f = fn)
+#define CALL_MapGrid2d(disp, parameters) (*((disp)->MapGrid2d)) parameters
+#define GET_MapGrid2d(disp) ((disp)->MapGrid2d)
+#define SET_MapGrid2d(disp, fn) ((disp)->MapGrid2d = fn)
+#define CALL_MapGrid2f(disp, parameters) (*((disp)->MapGrid2f)) parameters
+#define GET_MapGrid2f(disp) ((disp)->MapGrid2f)
+#define SET_MapGrid2f(disp, fn) ((disp)->MapGrid2f = fn)
+#define CALL_EvalCoord1d(disp, parameters) (*((disp)->EvalCoord1d)) parameters
+#define GET_EvalCoord1d(disp) ((disp)->EvalCoord1d)
+#define SET_EvalCoord1d(disp, fn) ((disp)->EvalCoord1d = fn)
+#define CALL_EvalCoord1dv(disp, parameters) (*((disp)->EvalCoord1dv)) parameters
+#define GET_EvalCoord1dv(disp) ((disp)->EvalCoord1dv)
+#define SET_EvalCoord1dv(disp, fn) ((disp)->EvalCoord1dv = fn)
+#define CALL_EvalCoord1f(disp, parameters) (*((disp)->EvalCoord1f)) parameters
+#define GET_EvalCoord1f(disp) ((disp)->EvalCoord1f)
+#define SET_EvalCoord1f(disp, fn) ((disp)->EvalCoord1f = fn)
+#define CALL_EvalCoord1fv(disp, parameters) (*((disp)->EvalCoord1fv)) parameters
+#define GET_EvalCoord1fv(disp) ((disp)->EvalCoord1fv)
+#define SET_EvalCoord1fv(disp, fn) ((disp)->EvalCoord1fv = fn)
+#define CALL_EvalCoord2d(disp, parameters) (*((disp)->EvalCoord2d)) parameters
+#define GET_EvalCoord2d(disp) ((disp)->EvalCoord2d)
+#define SET_EvalCoord2d(disp, fn) ((disp)->EvalCoord2d = fn)
+#define CALL_EvalCoord2dv(disp, parameters) (*((disp)->EvalCoord2dv)) parameters
+#define GET_EvalCoord2dv(disp) ((disp)->EvalCoord2dv)
+#define SET_EvalCoord2dv(disp, fn) ((disp)->EvalCoord2dv = fn)
+#define CALL_EvalCoord2f(disp, parameters) (*((disp)->EvalCoord2f)) parameters
+#define GET_EvalCoord2f(disp) ((disp)->EvalCoord2f)
+#define SET_EvalCoord2f(disp, fn) ((disp)->EvalCoord2f = fn)
+#define CALL_EvalCoord2fv(disp, parameters) (*((disp)->EvalCoord2fv)) parameters
+#define GET_EvalCoord2fv(disp) ((disp)->EvalCoord2fv)
+#define SET_EvalCoord2fv(disp, fn) ((disp)->EvalCoord2fv = fn)
+#define CALL_EvalMesh1(disp, parameters) (*((disp)->EvalMesh1)) parameters
+#define GET_EvalMesh1(disp) ((disp)->EvalMesh1)
+#define SET_EvalMesh1(disp, fn) ((disp)->EvalMesh1 = fn)
+#define CALL_EvalPoint1(disp, parameters) (*((disp)->EvalPoint1)) parameters
+#define GET_EvalPoint1(disp) ((disp)->EvalPoint1)
+#define SET_EvalPoint1(disp, fn) ((disp)->EvalPoint1 = fn)
+#define CALL_EvalMesh2(disp, parameters) (*((disp)->EvalMesh2)) parameters
+#define GET_EvalMesh2(disp) ((disp)->EvalMesh2)
+#define SET_EvalMesh2(disp, fn) ((disp)->EvalMesh2 = fn)
+#define CALL_EvalPoint2(disp, parameters) (*((disp)->EvalPoint2)) parameters
+#define GET_EvalPoint2(disp) ((disp)->EvalPoint2)
+#define SET_EvalPoint2(disp, fn) ((disp)->EvalPoint2 = fn)
+#define CALL_AlphaFunc(disp, parameters) (*((disp)->AlphaFunc)) parameters
+#define GET_AlphaFunc(disp) ((disp)->AlphaFunc)
+#define SET_AlphaFunc(disp, fn) ((disp)->AlphaFunc = fn)
+#define CALL_BlendFunc(disp, parameters) (*((disp)->BlendFunc)) parameters
+#define GET_BlendFunc(disp) ((disp)->BlendFunc)
+#define SET_BlendFunc(disp, fn) ((disp)->BlendFunc = fn)
+#define CALL_LogicOp(disp, parameters) (*((disp)->LogicOp)) parameters
+#define GET_LogicOp(disp) ((disp)->LogicOp)
+#define SET_LogicOp(disp, fn) ((disp)->LogicOp = fn)
+#define CALL_StencilFunc(disp, parameters) (*((disp)->StencilFunc)) parameters
+#define GET_StencilFunc(disp) ((disp)->StencilFunc)
+#define SET_StencilFunc(disp, fn) ((disp)->StencilFunc = fn)
+#define CALL_StencilOp(disp, parameters) (*((disp)->StencilOp)) parameters
+#define GET_StencilOp(disp) ((disp)->StencilOp)
+#define SET_StencilOp(disp, fn) ((disp)->StencilOp = fn)
+#define CALL_DepthFunc(disp, parameters) (*((disp)->DepthFunc)) parameters
+#define GET_DepthFunc(disp) ((disp)->DepthFunc)
+#define SET_DepthFunc(disp, fn) ((disp)->DepthFunc = fn)
+#define CALL_PixelZoom(disp, parameters) (*((disp)->PixelZoom)) parameters
+#define GET_PixelZoom(disp) ((disp)->PixelZoom)
+#define SET_PixelZoom(disp, fn) ((disp)->PixelZoom = fn)
+#define CALL_PixelTransferf(disp, parameters) (*((disp)->PixelTransferf)) parameters
+#define GET_PixelTransferf(disp) ((disp)->PixelTransferf)
+#define SET_PixelTransferf(disp, fn) ((disp)->PixelTransferf = fn)
+#define CALL_PixelTransferi(disp, parameters) (*((disp)->PixelTransferi)) parameters
+#define GET_PixelTransferi(disp) ((disp)->PixelTransferi)
+#define SET_PixelTransferi(disp, fn) ((disp)->PixelTransferi = fn)
+#define CALL_PixelStoref(disp, parameters) (*((disp)->PixelStoref)) parameters
+#define GET_PixelStoref(disp) ((disp)->PixelStoref)
+#define SET_PixelStoref(disp, fn) ((disp)->PixelStoref = fn)
+#define CALL_PixelStorei(disp, parameters) (*((disp)->PixelStorei)) parameters
+#define GET_PixelStorei(disp) ((disp)->PixelStorei)
+#define SET_PixelStorei(disp, fn) ((disp)->PixelStorei = fn)
+#define CALL_PixelMapfv(disp, parameters) (*((disp)->PixelMapfv)) parameters
+#define GET_PixelMapfv(disp) ((disp)->PixelMapfv)
+#define SET_PixelMapfv(disp, fn) ((disp)->PixelMapfv = fn)
+#define CALL_PixelMapuiv(disp, parameters) (*((disp)->PixelMapuiv)) parameters
+#define GET_PixelMapuiv(disp) ((disp)->PixelMapuiv)
+#define SET_PixelMapuiv(disp, fn) ((disp)->PixelMapuiv = fn)
+#define CALL_PixelMapusv(disp, parameters) (*((disp)->PixelMapusv)) parameters
+#define GET_PixelMapusv(disp) ((disp)->PixelMapusv)
+#define SET_PixelMapusv(disp, fn) ((disp)->PixelMapusv = fn)
+#define CALL_ReadBuffer(disp, parameters) (*((disp)->ReadBuffer)) parameters
+#define GET_ReadBuffer(disp) ((disp)->ReadBuffer)
+#define SET_ReadBuffer(disp, fn) ((disp)->ReadBuffer = fn)
+#define CALL_CopyPixels(disp, parameters) (*((disp)->CopyPixels)) parameters
+#define GET_CopyPixels(disp) ((disp)->CopyPixels)
+#define SET_CopyPixels(disp, fn) ((disp)->CopyPixels = fn)
+#define CALL_ReadPixels(disp, parameters) (*((disp)->ReadPixels)) parameters
+#define GET_ReadPixels(disp) ((disp)->ReadPixels)
+#define SET_ReadPixels(disp, fn) ((disp)->ReadPixels = fn)
+#define CALL_DrawPixels(disp, parameters) (*((disp)->DrawPixels)) parameters
+#define GET_DrawPixels(disp) ((disp)->DrawPixels)
+#define SET_DrawPixels(disp, fn) ((disp)->DrawPixels = fn)
+#define CALL_GetBooleanv(disp, parameters) (*((disp)->GetBooleanv)) parameters
+#define GET_GetBooleanv(disp) ((disp)->GetBooleanv)
+#define SET_GetBooleanv(disp, fn) ((disp)->GetBooleanv = fn)
+#define CALL_GetClipPlane(disp, parameters) (*((disp)->GetClipPlane)) parameters
+#define GET_GetClipPlane(disp) ((disp)->GetClipPlane)
+#define SET_GetClipPlane(disp, fn) ((disp)->GetClipPlane = fn)
+#define CALL_GetDoublev(disp, parameters) (*((disp)->GetDoublev)) parameters
+#define GET_GetDoublev(disp) ((disp)->GetDoublev)
+#define SET_GetDoublev(disp, fn) ((disp)->GetDoublev = fn)
+#define CALL_GetError(disp, parameters) (*((disp)->GetError)) parameters
+#define GET_GetError(disp) ((disp)->GetError)
+#define SET_GetError(disp, fn) ((disp)->GetError = fn)
+#define CALL_GetFloatv(disp, parameters) (*((disp)->GetFloatv)) parameters
+#define GET_GetFloatv(disp) ((disp)->GetFloatv)
+#define SET_GetFloatv(disp, fn) ((disp)->GetFloatv = fn)
+#define CALL_GetIntegerv(disp, parameters) (*((disp)->GetIntegerv)) parameters
+#define GET_GetIntegerv(disp) ((disp)->GetIntegerv)
+#define SET_GetIntegerv(disp, fn) ((disp)->GetIntegerv = fn)
+#define CALL_GetLightfv(disp, parameters) (*((disp)->GetLightfv)) parameters
+#define GET_GetLightfv(disp) ((disp)->GetLightfv)
+#define SET_GetLightfv(disp, fn) ((disp)->GetLightfv = fn)
+#define CALL_GetLightiv(disp, parameters) (*((disp)->GetLightiv)) parameters
+#define GET_GetLightiv(disp) ((disp)->GetLightiv)
+#define SET_GetLightiv(disp, fn) ((disp)->GetLightiv = fn)
+#define CALL_GetMapdv(disp, parameters) (*((disp)->GetMapdv)) parameters
+#define GET_GetMapdv(disp) ((disp)->GetMapdv)
+#define SET_GetMapdv(disp, fn) ((disp)->GetMapdv = fn)
+#define CALL_GetMapfv(disp, parameters) (*((disp)->GetMapfv)) parameters
+#define GET_GetMapfv(disp) ((disp)->GetMapfv)
+#define SET_GetMapfv(disp, fn) ((disp)->GetMapfv = fn)
+#define CALL_GetMapiv(disp, parameters) (*((disp)->GetMapiv)) parameters
+#define GET_GetMapiv(disp) ((disp)->GetMapiv)
+#define SET_GetMapiv(disp, fn) ((disp)->GetMapiv = fn)
+#define CALL_GetMaterialfv(disp, parameters) (*((disp)->GetMaterialfv)) parameters
+#define GET_GetMaterialfv(disp) ((disp)->GetMaterialfv)
+#define SET_GetMaterialfv(disp, fn) ((disp)->GetMaterialfv = fn)
+#define CALL_GetMaterialiv(disp, parameters) (*((disp)->GetMaterialiv)) parameters
+#define GET_GetMaterialiv(disp) ((disp)->GetMaterialiv)
+#define SET_GetMaterialiv(disp, fn) ((disp)->GetMaterialiv = fn)
+#define CALL_GetPixelMapfv(disp, parameters) (*((disp)->GetPixelMapfv)) parameters
+#define GET_GetPixelMapfv(disp) ((disp)->GetPixelMapfv)
+#define SET_GetPixelMapfv(disp, fn) ((disp)->GetPixelMapfv = fn)
+#define CALL_GetPixelMapuiv(disp, parameters) (*((disp)->GetPixelMapuiv)) parameters
+#define GET_GetPixelMapuiv(disp) ((disp)->GetPixelMapuiv)
+#define SET_GetPixelMapuiv(disp, fn) ((disp)->GetPixelMapuiv = fn)
+#define CALL_GetPixelMapusv(disp, parameters) (*((disp)->GetPixelMapusv)) parameters
+#define GET_GetPixelMapusv(disp) ((disp)->GetPixelMapusv)
+#define SET_GetPixelMapusv(disp, fn) ((disp)->GetPixelMapusv = fn)
+#define CALL_GetPolygonStipple(disp, parameters) (*((disp)->GetPolygonStipple)) parameters
+#define GET_GetPolygonStipple(disp) ((disp)->GetPolygonStipple)
+#define SET_GetPolygonStipple(disp, fn) ((disp)->GetPolygonStipple = fn)
+#define CALL_GetString(disp, parameters) (*((disp)->GetString)) parameters
+#define GET_GetString(disp) ((disp)->GetString)
+#define SET_GetString(disp, fn) ((disp)->GetString = fn)
+#define CALL_GetTexEnvfv(disp, parameters) (*((disp)->GetTexEnvfv)) parameters
+#define GET_GetTexEnvfv(disp) ((disp)->GetTexEnvfv)
+#define SET_GetTexEnvfv(disp, fn) ((disp)->GetTexEnvfv = fn)
+#define CALL_GetTexEnviv(disp, parameters) (*((disp)->GetTexEnviv)) parameters
+#define GET_GetTexEnviv(disp) ((disp)->GetTexEnviv)
+#define SET_GetTexEnviv(disp, fn) ((disp)->GetTexEnviv = fn)
+#define CALL_GetTexGendv(disp, parameters) (*((disp)->GetTexGendv)) parameters
+#define GET_GetTexGendv(disp) ((disp)->GetTexGendv)
+#define SET_GetTexGendv(disp, fn) ((disp)->GetTexGendv = fn)
+#define CALL_GetTexGenfv(disp, parameters) (*((disp)->GetTexGenfv)) parameters
+#define GET_GetTexGenfv(disp) ((disp)->GetTexGenfv)
+#define SET_GetTexGenfv(disp, fn) ((disp)->GetTexGenfv = fn)
+#define CALL_GetTexGeniv(disp, parameters) (*((disp)->GetTexGeniv)) parameters
+#define GET_GetTexGeniv(disp) ((disp)->GetTexGeniv)
+#define SET_GetTexGeniv(disp, fn) ((disp)->GetTexGeniv = fn)
+#define CALL_GetTexImage(disp, parameters) (*((disp)->GetTexImage)) parameters
+#define GET_GetTexImage(disp) ((disp)->GetTexImage)
+#define SET_GetTexImage(disp, fn) ((disp)->GetTexImage = fn)
+#define CALL_GetTexParameterfv(disp, parameters) (*((disp)->GetTexParameterfv)) parameters
+#define GET_GetTexParameterfv(disp) ((disp)->GetTexParameterfv)
+#define SET_GetTexParameterfv(disp, fn) ((disp)->GetTexParameterfv = fn)
+#define CALL_GetTexParameteriv(disp, parameters) (*((disp)->GetTexParameteriv)) parameters
+#define GET_GetTexParameteriv(disp) ((disp)->GetTexParameteriv)
+#define SET_GetTexParameteriv(disp, fn) ((disp)->GetTexParameteriv = fn)
+#define CALL_GetTexLevelParameterfv(disp, parameters) (*((disp)->GetTexLevelParameterfv)) parameters
+#define GET_GetTexLevelParameterfv(disp) ((disp)->GetTexLevelParameterfv)
+#define SET_GetTexLevelParameterfv(disp, fn) ((disp)->GetTexLevelParameterfv = fn)
+#define CALL_GetTexLevelParameteriv(disp, parameters) (*((disp)->GetTexLevelParameteriv)) parameters
+#define GET_GetTexLevelParameteriv(disp) ((disp)->GetTexLevelParameteriv)
+#define SET_GetTexLevelParameteriv(disp, fn) ((disp)->GetTexLevelParameteriv = fn)
+#define CALL_IsEnabled(disp, parameters) (*((disp)->IsEnabled)) parameters
+#define GET_IsEnabled(disp) ((disp)->IsEnabled)
+#define SET_IsEnabled(disp, fn) ((disp)->IsEnabled = fn)
+#define CALL_IsList(disp, parameters) (*((disp)->IsList)) parameters
+#define GET_IsList(disp) ((disp)->IsList)
+#define SET_IsList(disp, fn) ((disp)->IsList = fn)
+#define CALL_DepthRange(disp, parameters) (*((disp)->DepthRange)) parameters
+#define GET_DepthRange(disp) ((disp)->DepthRange)
+#define SET_DepthRange(disp, fn) ((disp)->DepthRange = fn)
+#define CALL_Frustum(disp, parameters) (*((disp)->Frustum)) parameters
+#define GET_Frustum(disp) ((disp)->Frustum)
+#define SET_Frustum(disp, fn) ((disp)->Frustum = fn)
+#define CALL_LoadIdentity(disp, parameters) (*((disp)->LoadIdentity)) parameters
+#define GET_LoadIdentity(disp) ((disp)->LoadIdentity)
+#define SET_LoadIdentity(disp, fn) ((disp)->LoadIdentity = fn)
+#define CALL_LoadMatrixf(disp, parameters) (*((disp)->LoadMatrixf)) parameters
+#define GET_LoadMatrixf(disp) ((disp)->LoadMatrixf)
+#define SET_LoadMatrixf(disp, fn) ((disp)->LoadMatrixf = fn)
+#define CALL_LoadMatrixd(disp, parameters) (*((disp)->LoadMatrixd)) parameters
+#define GET_LoadMatrixd(disp) ((disp)->LoadMatrixd)
+#define SET_LoadMatrixd(disp, fn) ((disp)->LoadMatrixd = fn)
+#define CALL_MatrixMode(disp, parameters) (*((disp)->MatrixMode)) parameters
+#define GET_MatrixMode(disp) ((disp)->MatrixMode)
+#define SET_MatrixMode(disp, fn) ((disp)->MatrixMode = fn)
+#define CALL_MultMatrixf(disp, parameters) (*((disp)->MultMatrixf)) parameters
+#define GET_MultMatrixf(disp) ((disp)->MultMatrixf)
+#define SET_MultMatrixf(disp, fn) ((disp)->MultMatrixf = fn)
+#define CALL_MultMatrixd(disp, parameters) (*((disp)->MultMatrixd)) parameters
+#define GET_MultMatrixd(disp) ((disp)->MultMatrixd)
+#define SET_MultMatrixd(disp, fn) ((disp)->MultMatrixd = fn)
+#define CALL_Ortho(disp, parameters) (*((disp)->Ortho)) parameters
+#define GET_Ortho(disp) ((disp)->Ortho)
+#define SET_Ortho(disp, fn) ((disp)->Ortho = fn)
+#define CALL_PopMatrix(disp, parameters) (*((disp)->PopMatrix)) parameters
+#define GET_PopMatrix(disp) ((disp)->PopMatrix)
+#define SET_PopMatrix(disp, fn) ((disp)->PopMatrix = fn)
+#define CALL_PushMatrix(disp, parameters) (*((disp)->PushMatrix)) parameters
+#define GET_PushMatrix(disp) ((disp)->PushMatrix)
+#define SET_PushMatrix(disp, fn) ((disp)->PushMatrix = fn)
+#define CALL_Rotated(disp, parameters) (*((disp)->Rotated)) parameters
+#define GET_Rotated(disp) ((disp)->Rotated)
+#define SET_Rotated(disp, fn) ((disp)->Rotated = fn)
+#define CALL_Rotatef(disp, parameters) (*((disp)->Rotatef)) parameters
+#define GET_Rotatef(disp) ((disp)->Rotatef)
+#define SET_Rotatef(disp, fn) ((disp)->Rotatef = fn)
+#define CALL_Scaled(disp, parameters) (*((disp)->Scaled)) parameters
+#define GET_Scaled(disp) ((disp)->Scaled)
+#define SET_Scaled(disp, fn) ((disp)->Scaled = fn)
+#define CALL_Scalef(disp, parameters) (*((disp)->Scalef)) parameters
+#define GET_Scalef(disp) ((disp)->Scalef)
+#define SET_Scalef(disp, fn) ((disp)->Scalef = fn)
+#define CALL_Translated(disp, parameters) (*((disp)->Translated)) parameters
+#define GET_Translated(disp) ((disp)->Translated)
+#define SET_Translated(disp, fn) ((disp)->Translated = fn)
+#define CALL_Translatef(disp, parameters) (*((disp)->Translatef)) parameters
+#define GET_Translatef(disp) ((disp)->Translatef)
+#define SET_Translatef(disp, fn) ((disp)->Translatef = fn)
+#define CALL_Viewport(disp, parameters) (*((disp)->Viewport)) parameters
+#define GET_Viewport(disp) ((disp)->Viewport)
+#define SET_Viewport(disp, fn) ((disp)->Viewport = fn)
+#define CALL_ArrayElement(disp, parameters) (*((disp)->ArrayElement)) parameters
+#define GET_ArrayElement(disp) ((disp)->ArrayElement)
+#define SET_ArrayElement(disp, fn) ((disp)->ArrayElement = fn)
+#define CALL_BindTexture(disp, parameters) (*((disp)->BindTexture)) parameters
+#define GET_BindTexture(disp) ((disp)->BindTexture)
+#define SET_BindTexture(disp, fn) ((disp)->BindTexture = fn)
+#define CALL_ColorPointer(disp, parameters) (*((disp)->ColorPointer)) parameters
+#define GET_ColorPointer(disp) ((disp)->ColorPointer)
+#define SET_ColorPointer(disp, fn) ((disp)->ColorPointer = fn)
+#define CALL_DisableClientState(disp, parameters) (*((disp)->DisableClientState)) parameters
+#define GET_DisableClientState(disp) ((disp)->DisableClientState)
+#define SET_DisableClientState(disp, fn) ((disp)->DisableClientState = fn)
+#define CALL_DrawArrays(disp, parameters) (*((disp)->DrawArrays)) parameters
+#define GET_DrawArrays(disp) ((disp)->DrawArrays)
+#define SET_DrawArrays(disp, fn) ((disp)->DrawArrays = fn)
+#define CALL_DrawElements(disp, parameters) (*((disp)->DrawElements)) parameters
+#define GET_DrawElements(disp) ((disp)->DrawElements)
+#define SET_DrawElements(disp, fn) ((disp)->DrawElements = fn)
+#define CALL_EdgeFlagPointer(disp, parameters) (*((disp)->EdgeFlagPointer)) parameters
+#define GET_EdgeFlagPointer(disp) ((disp)->EdgeFlagPointer)
+#define SET_EdgeFlagPointer(disp, fn) ((disp)->EdgeFlagPointer = fn)
+#define CALL_EnableClientState(disp, parameters) (*((disp)->EnableClientState)) parameters
+#define GET_EnableClientState(disp) ((disp)->EnableClientState)
+#define SET_EnableClientState(disp, fn) ((disp)->EnableClientState = fn)
+#define CALL_IndexPointer(disp, parameters) (*((disp)->IndexPointer)) parameters
+#define GET_IndexPointer(disp) ((disp)->IndexPointer)
+#define SET_IndexPointer(disp, fn) ((disp)->IndexPointer = fn)
+#define CALL_Indexub(disp, parameters) (*((disp)->Indexub)) parameters
+#define GET_Indexub(disp) ((disp)->Indexub)
+#define SET_Indexub(disp, fn) ((disp)->Indexub = fn)
+#define CALL_Indexubv(disp, parameters) (*((disp)->Indexubv)) parameters
+#define GET_Indexubv(disp) ((disp)->Indexubv)
+#define SET_Indexubv(disp, fn) ((disp)->Indexubv = fn)
+#define CALL_InterleavedArrays(disp, parameters) (*((disp)->InterleavedArrays)) parameters
+#define GET_InterleavedArrays(disp) ((disp)->InterleavedArrays)
+#define SET_InterleavedArrays(disp, fn) ((disp)->InterleavedArrays = fn)
+#define CALL_NormalPointer(disp, parameters) (*((disp)->NormalPointer)) parameters
+#define GET_NormalPointer(disp) ((disp)->NormalPointer)
+#define SET_NormalPointer(disp, fn) ((disp)->NormalPointer = fn)
+#define CALL_PolygonOffset(disp, parameters) (*((disp)->PolygonOffset)) parameters
+#define GET_PolygonOffset(disp) ((disp)->PolygonOffset)
+#define SET_PolygonOffset(disp, fn) ((disp)->PolygonOffset = fn)
+#define CALL_TexCoordPointer(disp, parameters) (*((disp)->TexCoordPointer)) parameters
+#define GET_TexCoordPointer(disp) ((disp)->TexCoordPointer)
+#define SET_TexCoordPointer(disp, fn) ((disp)->TexCoordPointer = fn)
+#define CALL_VertexPointer(disp, parameters) (*((disp)->VertexPointer)) parameters
+#define GET_VertexPointer(disp) ((disp)->VertexPointer)
+#define SET_VertexPointer(disp, fn) ((disp)->VertexPointer = fn)
+#define CALL_AreTexturesResident(disp, parameters) (*((disp)->AreTexturesResident)) parameters
+#define GET_AreTexturesResident(disp) ((disp)->AreTexturesResident)
+#define SET_AreTexturesResident(disp, fn) ((disp)->AreTexturesResident = fn)
+#define CALL_CopyTexImage1D(disp, parameters) (*((disp)->CopyTexImage1D)) parameters
+#define GET_CopyTexImage1D(disp) ((disp)->CopyTexImage1D)
+#define SET_CopyTexImage1D(disp, fn) ((disp)->CopyTexImage1D = fn)
+#define CALL_CopyTexImage2D(disp, parameters) (*((disp)->CopyTexImage2D)) parameters
+#define GET_CopyTexImage2D(disp) ((disp)->CopyTexImage2D)
+#define SET_CopyTexImage2D(disp, fn) ((disp)->CopyTexImage2D = fn)
+#define CALL_CopyTexSubImage1D(disp, parameters) (*((disp)->CopyTexSubImage1D)) parameters
+#define GET_CopyTexSubImage1D(disp) ((disp)->CopyTexSubImage1D)
+#define SET_CopyTexSubImage1D(disp, fn) ((disp)->CopyTexSubImage1D = fn)
+#define CALL_CopyTexSubImage2D(disp, parameters) (*((disp)->CopyTexSubImage2D)) parameters
+#define GET_CopyTexSubImage2D(disp) ((disp)->CopyTexSubImage2D)
+#define SET_CopyTexSubImage2D(disp, fn) ((disp)->CopyTexSubImage2D = fn)
+#define CALL_DeleteTextures(disp, parameters) (*((disp)->DeleteTextures)) parameters
+#define GET_DeleteTextures(disp) ((disp)->DeleteTextures)
+#define SET_DeleteTextures(disp, fn) ((disp)->DeleteTextures = fn)
+#define CALL_GenTextures(disp, parameters) (*((disp)->GenTextures)) parameters
+#define GET_GenTextures(disp) ((disp)->GenTextures)
+#define SET_GenTextures(disp, fn) ((disp)->GenTextures = fn)
+#define CALL_GetPointerv(disp, parameters) (*((disp)->GetPointerv)) parameters
+#define GET_GetPointerv(disp) ((disp)->GetPointerv)
+#define SET_GetPointerv(disp, fn) ((disp)->GetPointerv = fn)
+#define CALL_IsTexture(disp, parameters) (*((disp)->IsTexture)) parameters
+#define GET_IsTexture(disp) ((disp)->IsTexture)
+#define SET_IsTexture(disp, fn) ((disp)->IsTexture = fn)
+#define CALL_PrioritizeTextures(disp, parameters) (*((disp)->PrioritizeTextures)) parameters
+#define GET_PrioritizeTextures(disp) ((disp)->PrioritizeTextures)
+#define SET_PrioritizeTextures(disp, fn) ((disp)->PrioritizeTextures = fn)
+#define CALL_TexSubImage1D(disp, parameters) (*((disp)->TexSubImage1D)) parameters
+#define GET_TexSubImage1D(disp) ((disp)->TexSubImage1D)
+#define SET_TexSubImage1D(disp, fn) ((disp)->TexSubImage1D = fn)
+#define CALL_TexSubImage2D(disp, parameters) (*((disp)->TexSubImage2D)) parameters
+#define GET_TexSubImage2D(disp) ((disp)->TexSubImage2D)
+#define SET_TexSubImage2D(disp, fn) ((disp)->TexSubImage2D = fn)
+#define CALL_PopClientAttrib(disp, parameters) (*((disp)->PopClientAttrib)) parameters
+#define GET_PopClientAttrib(disp) ((disp)->PopClientAttrib)
+#define SET_PopClientAttrib(disp, fn) ((disp)->PopClientAttrib = fn)
+#define CALL_PushClientAttrib(disp, parameters) (*((disp)->PushClientAttrib)) parameters
+#define GET_PushClientAttrib(disp) ((disp)->PushClientAttrib)
+#define SET_PushClientAttrib(disp, fn) ((disp)->PushClientAttrib = fn)
+#define CALL_BlendColor(disp, parameters) (*((disp)->BlendColor)) parameters
+#define GET_BlendColor(disp) ((disp)->BlendColor)
+#define SET_BlendColor(disp, fn) ((disp)->BlendColor = fn)
+#define CALL_BlendEquation(disp, parameters) (*((disp)->BlendEquation)) parameters
+#define GET_BlendEquation(disp) ((disp)->BlendEquation)
+#define SET_BlendEquation(disp, fn) ((disp)->BlendEquation = fn)
+#define CALL_DrawRangeElements(disp, parameters) (*((disp)->DrawRangeElements)) parameters
+#define GET_DrawRangeElements(disp) ((disp)->DrawRangeElements)
+#define SET_DrawRangeElements(disp, fn) ((disp)->DrawRangeElements = fn)
+#define CALL_ColorTable(disp, parameters) (*((disp)->ColorTable)) parameters
+#define GET_ColorTable(disp) ((disp)->ColorTable)
+#define SET_ColorTable(disp, fn) ((disp)->ColorTable = fn)
+#define CALL_ColorTableParameterfv(disp, parameters) (*((disp)->ColorTableParameterfv)) parameters
+#define GET_ColorTableParameterfv(disp) ((disp)->ColorTableParameterfv)
+#define SET_ColorTableParameterfv(disp, fn) ((disp)->ColorTableParameterfv = fn)
+#define CALL_ColorTableParameteriv(disp, parameters) (*((disp)->ColorTableParameteriv)) parameters
+#define GET_ColorTableParameteriv(disp) ((disp)->ColorTableParameteriv)
+#define SET_ColorTableParameteriv(disp, fn) ((disp)->ColorTableParameteriv = fn)
+#define CALL_CopyColorTable(disp, parameters) (*((disp)->CopyColorTable)) parameters
+#define GET_CopyColorTable(disp) ((disp)->CopyColorTable)
+#define SET_CopyColorTable(disp, fn) ((disp)->CopyColorTable = fn)
+#define CALL_GetColorTable(disp, parameters) (*((disp)->GetColorTable)) parameters
+#define GET_GetColorTable(disp) ((disp)->GetColorTable)
+#define SET_GetColorTable(disp, fn) ((disp)->GetColorTable = fn)
+#define CALL_GetColorTableParameterfv(disp, parameters) (*((disp)->GetColorTableParameterfv)) parameters
+#define GET_GetColorTableParameterfv(disp) ((disp)->GetColorTableParameterfv)
+#define SET_GetColorTableParameterfv(disp, fn) ((disp)->GetColorTableParameterfv = fn)
+#define CALL_GetColorTableParameteriv(disp, parameters) (*((disp)->GetColorTableParameteriv)) parameters
+#define GET_GetColorTableParameteriv(disp) ((disp)->GetColorTableParameteriv)
+#define SET_GetColorTableParameteriv(disp, fn) ((disp)->GetColorTableParameteriv = fn)
+#define CALL_ColorSubTable(disp, parameters) (*((disp)->ColorSubTable)) parameters
+#define GET_ColorSubTable(disp) ((disp)->ColorSubTable)
+#define SET_ColorSubTable(disp, fn) ((disp)->ColorSubTable = fn)
+#define CALL_CopyColorSubTable(disp, parameters) (*((disp)->CopyColorSubTable)) parameters
+#define GET_CopyColorSubTable(disp) ((disp)->CopyColorSubTable)
+#define SET_CopyColorSubTable(disp, fn) ((disp)->CopyColorSubTable = fn)
+#define CALL_ConvolutionFilter1D(disp, parameters) (*((disp)->ConvolutionFilter1D)) parameters
+#define GET_ConvolutionFilter1D(disp) ((disp)->ConvolutionFilter1D)
+#define SET_ConvolutionFilter1D(disp, fn) ((disp)->ConvolutionFilter1D = fn)
+#define CALL_ConvolutionFilter2D(disp, parameters) (*((disp)->ConvolutionFilter2D)) parameters
+#define GET_ConvolutionFilter2D(disp) ((disp)->ConvolutionFilter2D)
+#define SET_ConvolutionFilter2D(disp, fn) ((disp)->ConvolutionFilter2D = fn)
+#define CALL_ConvolutionParameterf(disp, parameters) (*((disp)->ConvolutionParameterf)) parameters
+#define GET_ConvolutionParameterf(disp) ((disp)->ConvolutionParameterf)
+#define SET_ConvolutionParameterf(disp, fn) ((disp)->ConvolutionParameterf = fn)
+#define CALL_ConvolutionParameterfv(disp, parameters) (*((disp)->ConvolutionParameterfv)) parameters
+#define GET_ConvolutionParameterfv(disp) ((disp)->ConvolutionParameterfv)
+#define SET_ConvolutionParameterfv(disp, fn) ((disp)->ConvolutionParameterfv = fn)
+#define CALL_ConvolutionParameteri(disp, parameters) (*((disp)->ConvolutionParameteri)) parameters
+#define GET_ConvolutionParameteri(disp) ((disp)->ConvolutionParameteri)
+#define SET_ConvolutionParameteri(disp, fn) ((disp)->ConvolutionParameteri = fn)
+#define CALL_ConvolutionParameteriv(disp, parameters) (*((disp)->ConvolutionParameteriv)) parameters
+#define GET_ConvolutionParameteriv(disp) ((disp)->ConvolutionParameteriv)
+#define SET_ConvolutionParameteriv(disp, fn) ((disp)->ConvolutionParameteriv = fn)
+#define CALL_CopyConvolutionFilter1D(disp, parameters) (*((disp)->CopyConvolutionFilter1D)) parameters
+#define GET_CopyConvolutionFilter1D(disp) ((disp)->CopyConvolutionFilter1D)
+#define SET_CopyConvolutionFilter1D(disp, fn) ((disp)->CopyConvolutionFilter1D = fn)
+#define CALL_CopyConvolutionFilter2D(disp, parameters) (*((disp)->CopyConvolutionFilter2D)) parameters
+#define GET_CopyConvolutionFilter2D(disp) ((disp)->CopyConvolutionFilter2D)
+#define SET_CopyConvolutionFilter2D(disp, fn) ((disp)->CopyConvolutionFilter2D = fn)
+#define CALL_GetConvolutionFilter(disp, parameters) (*((disp)->GetConvolutionFilter)) parameters
+#define GET_GetConvolutionFilter(disp) ((disp)->GetConvolutionFilter)
+#define SET_GetConvolutionFilter(disp, fn) ((disp)->GetConvolutionFilter = fn)
+#define CALL_GetConvolutionParameterfv(disp, parameters) (*((disp)->GetConvolutionParameterfv)) parameters
+#define GET_GetConvolutionParameterfv(disp) ((disp)->GetConvolutionParameterfv)
+#define SET_GetConvolutionParameterfv(disp, fn) ((disp)->GetConvolutionParameterfv = fn)
+#define CALL_GetConvolutionParameteriv(disp, parameters) (*((disp)->GetConvolutionParameteriv)) parameters
+#define GET_GetConvolutionParameteriv(disp) ((disp)->GetConvolutionParameteriv)
+#define SET_GetConvolutionParameteriv(disp, fn) ((disp)->GetConvolutionParameteriv = fn)
+#define CALL_GetSeparableFilter(disp, parameters) (*((disp)->GetSeparableFilter)) parameters
+#define GET_GetSeparableFilter(disp) ((disp)->GetSeparableFilter)
+#define SET_GetSeparableFilter(disp, fn) ((disp)->GetSeparableFilter = fn)
+#define CALL_SeparableFilter2D(disp, parameters) (*((disp)->SeparableFilter2D)) parameters
+#define GET_SeparableFilter2D(disp) ((disp)->SeparableFilter2D)
+#define SET_SeparableFilter2D(disp, fn) ((disp)->SeparableFilter2D = fn)
+#define CALL_GetHistogram(disp, parameters) (*((disp)->GetHistogram)) parameters
+#define GET_GetHistogram(disp) ((disp)->GetHistogram)
+#define SET_GetHistogram(disp, fn) ((disp)->GetHistogram = fn)
+#define CALL_GetHistogramParameterfv(disp, parameters) (*((disp)->GetHistogramParameterfv)) parameters
+#define GET_GetHistogramParameterfv(disp) ((disp)->GetHistogramParameterfv)
+#define SET_GetHistogramParameterfv(disp, fn) ((disp)->GetHistogramParameterfv = fn)
+#define CALL_GetHistogramParameteriv(disp, parameters) (*((disp)->GetHistogramParameteriv)) parameters
+#define GET_GetHistogramParameteriv(disp) ((disp)->GetHistogramParameteriv)
+#define SET_GetHistogramParameteriv(disp, fn) ((disp)->GetHistogramParameteriv = fn)
+#define CALL_GetMinmax(disp, parameters) (*((disp)->GetMinmax)) parameters
+#define GET_GetMinmax(disp) ((disp)->GetMinmax)
+#define SET_GetMinmax(disp, fn) ((disp)->GetMinmax = fn)
+#define CALL_GetMinmaxParameterfv(disp, parameters) (*((disp)->GetMinmaxParameterfv)) parameters
+#define GET_GetMinmaxParameterfv(disp) ((disp)->GetMinmaxParameterfv)
+#define SET_GetMinmaxParameterfv(disp, fn) ((disp)->GetMinmaxParameterfv = fn)
+#define CALL_GetMinmaxParameteriv(disp, parameters) (*((disp)->GetMinmaxParameteriv)) parameters
+#define GET_GetMinmaxParameteriv(disp) ((disp)->GetMinmaxParameteriv)
+#define SET_GetMinmaxParameteriv(disp, fn) ((disp)->GetMinmaxParameteriv = fn)
+#define CALL_Histogram(disp, parameters) (*((disp)->Histogram)) parameters
+#define GET_Histogram(disp) ((disp)->Histogram)
+#define SET_Histogram(disp, fn) ((disp)->Histogram = fn)
+#define CALL_Minmax(disp, parameters) (*((disp)->Minmax)) parameters
+#define GET_Minmax(disp) ((disp)->Minmax)
+#define SET_Minmax(disp, fn) ((disp)->Minmax = fn)
+#define CALL_ResetHistogram(disp, parameters) (*((disp)->ResetHistogram)) parameters
+#define GET_ResetHistogram(disp) ((disp)->ResetHistogram)
+#define SET_ResetHistogram(disp, fn) ((disp)->ResetHistogram = fn)
+#define CALL_ResetMinmax(disp, parameters) (*((disp)->ResetMinmax)) parameters
+#define GET_ResetMinmax(disp) ((disp)->ResetMinmax)
+#define SET_ResetMinmax(disp, fn) ((disp)->ResetMinmax = fn)
+#define CALL_TexImage3D(disp, parameters) (*((disp)->TexImage3D)) parameters
+#define GET_TexImage3D(disp) ((disp)->TexImage3D)
+#define SET_TexImage3D(disp, fn) ((disp)->TexImage3D = fn)
+#define CALL_TexSubImage3D(disp, parameters) (*((disp)->TexSubImage3D)) parameters
+#define GET_TexSubImage3D(disp) ((disp)->TexSubImage3D)
+#define SET_TexSubImage3D(disp, fn) ((disp)->TexSubImage3D = fn)
+#define CALL_CopyTexSubImage3D(disp, parameters) (*((disp)->CopyTexSubImage3D)) parameters
+#define GET_CopyTexSubImage3D(disp) ((disp)->CopyTexSubImage3D)
+#define SET_CopyTexSubImage3D(disp, fn) ((disp)->CopyTexSubImage3D = fn)
+#define CALL_ActiveTextureARB(disp, parameters) (*((disp)->ActiveTextureARB)) parameters
+#define GET_ActiveTextureARB(disp) ((disp)->ActiveTextureARB)
+#define SET_ActiveTextureARB(disp, fn) ((disp)->ActiveTextureARB = fn)
+#define CALL_ClientActiveTextureARB(disp, parameters) (*((disp)->ClientActiveTextureARB)) parameters
+#define GET_ClientActiveTextureARB(disp) ((disp)->ClientActiveTextureARB)
+#define SET_ClientActiveTextureARB(disp, fn) ((disp)->ClientActiveTextureARB = fn)
+#define CALL_MultiTexCoord1dARB(disp, parameters) (*((disp)->MultiTexCoord1dARB)) parameters
+#define GET_MultiTexCoord1dARB(disp) ((disp)->MultiTexCoord1dARB)
+#define SET_MultiTexCoord1dARB(disp, fn) ((disp)->MultiTexCoord1dARB = fn)
+#define CALL_MultiTexCoord1dvARB(disp, parameters) (*((disp)->MultiTexCoord1dvARB)) parameters
+#define GET_MultiTexCoord1dvARB(disp) ((disp)->MultiTexCoord1dvARB)
+#define SET_MultiTexCoord1dvARB(disp, fn) ((disp)->MultiTexCoord1dvARB = fn)
+#define CALL_MultiTexCoord1fARB(disp, parameters) (*((disp)->MultiTexCoord1fARB)) parameters
+#define GET_MultiTexCoord1fARB(disp) ((disp)->MultiTexCoord1fARB)
+#define SET_MultiTexCoord1fARB(disp, fn) ((disp)->MultiTexCoord1fARB = fn)
+#define CALL_MultiTexCoord1fvARB(disp, parameters) (*((disp)->MultiTexCoord1fvARB)) parameters
+#define GET_MultiTexCoord1fvARB(disp) ((disp)->MultiTexCoord1fvARB)
+#define SET_MultiTexCoord1fvARB(disp, fn) ((disp)->MultiTexCoord1fvARB = fn)
+#define CALL_MultiTexCoord1iARB(disp, parameters) (*((disp)->MultiTexCoord1iARB)) parameters
+#define GET_MultiTexCoord1iARB(disp) ((disp)->MultiTexCoord1iARB)
+#define SET_MultiTexCoord1iARB(disp, fn) ((disp)->MultiTexCoord1iARB = fn)
+#define CALL_MultiTexCoord1ivARB(disp, parameters) (*((disp)->MultiTexCoord1ivARB)) parameters
+#define GET_MultiTexCoord1ivARB(disp) ((disp)->MultiTexCoord1ivARB)
+#define SET_MultiTexCoord1ivARB(disp, fn) ((disp)->MultiTexCoord1ivARB = fn)
+#define CALL_MultiTexCoord1sARB(disp, parameters) (*((disp)->MultiTexCoord1sARB)) parameters
+#define GET_MultiTexCoord1sARB(disp) ((disp)->MultiTexCoord1sARB)
+#define SET_MultiTexCoord1sARB(disp, fn) ((disp)->MultiTexCoord1sARB = fn)
+#define CALL_MultiTexCoord1svARB(disp, parameters) (*((disp)->MultiTexCoord1svARB)) parameters
+#define GET_MultiTexCoord1svARB(disp) ((disp)->MultiTexCoord1svARB)
+#define SET_MultiTexCoord1svARB(disp, fn) ((disp)->MultiTexCoord1svARB = fn)
+#define CALL_MultiTexCoord2dARB(disp, parameters) (*((disp)->MultiTexCoord2dARB)) parameters
+#define GET_MultiTexCoord2dARB(disp) ((disp)->MultiTexCoord2dARB)
+#define SET_MultiTexCoord2dARB(disp, fn) ((disp)->MultiTexCoord2dARB = fn)
+#define CALL_MultiTexCoord2dvARB(disp, parameters) (*((disp)->MultiTexCoord2dvARB)) parameters
+#define GET_MultiTexCoord2dvARB(disp) ((disp)->MultiTexCoord2dvARB)
+#define SET_MultiTexCoord2dvARB(disp, fn) ((disp)->MultiTexCoord2dvARB = fn)
+#define CALL_MultiTexCoord2fARB(disp, parameters) (*((disp)->MultiTexCoord2fARB)) parameters
+#define GET_MultiTexCoord2fARB(disp) ((disp)->MultiTexCoord2fARB)
+#define SET_MultiTexCoord2fARB(disp, fn) ((disp)->MultiTexCoord2fARB = fn)
+#define CALL_MultiTexCoord2fvARB(disp, parameters) (*((disp)->MultiTexCoord2fvARB)) parameters
+#define GET_MultiTexCoord2fvARB(disp) ((disp)->MultiTexCoord2fvARB)
+#define SET_MultiTexCoord2fvARB(disp, fn) ((disp)->MultiTexCoord2fvARB = fn)
+#define CALL_MultiTexCoord2iARB(disp, parameters) (*((disp)->MultiTexCoord2iARB)) parameters
+#define GET_MultiTexCoord2iARB(disp) ((disp)->MultiTexCoord2iARB)
+#define SET_MultiTexCoord2iARB(disp, fn) ((disp)->MultiTexCoord2iARB = fn)
+#define CALL_MultiTexCoord2ivARB(disp, parameters) (*((disp)->MultiTexCoord2ivARB)) parameters
+#define GET_MultiTexCoord2ivARB(disp) ((disp)->MultiTexCoord2ivARB)
+#define SET_MultiTexCoord2ivARB(disp, fn) ((disp)->MultiTexCoord2ivARB = fn)
+#define CALL_MultiTexCoord2sARB(disp, parameters) (*((disp)->MultiTexCoord2sARB)) parameters
+#define GET_MultiTexCoord2sARB(disp) ((disp)->MultiTexCoord2sARB)
+#define SET_MultiTexCoord2sARB(disp, fn) ((disp)->MultiTexCoord2sARB = fn)
+#define CALL_MultiTexCoord2svARB(disp, parameters) (*((disp)->MultiTexCoord2svARB)) parameters
+#define GET_MultiTexCoord2svARB(disp) ((disp)->MultiTexCoord2svARB)
+#define SET_MultiTexCoord2svARB(disp, fn) ((disp)->MultiTexCoord2svARB = fn)
+#define CALL_MultiTexCoord3dARB(disp, parameters) (*((disp)->MultiTexCoord3dARB)) parameters
+#define GET_MultiTexCoord3dARB(disp) ((disp)->MultiTexCoord3dARB)
+#define SET_MultiTexCoord3dARB(disp, fn) ((disp)->MultiTexCoord3dARB = fn)
+#define CALL_MultiTexCoord3dvARB(disp, parameters) (*((disp)->MultiTexCoord3dvARB)) parameters
+#define GET_MultiTexCoord3dvARB(disp) ((disp)->MultiTexCoord3dvARB)
+#define SET_MultiTexCoord3dvARB(disp, fn) ((disp)->MultiTexCoord3dvARB = fn)
+#define CALL_MultiTexCoord3fARB(disp, parameters) (*((disp)->MultiTexCoord3fARB)) parameters
+#define GET_MultiTexCoord3fARB(disp) ((disp)->MultiTexCoord3fARB)
+#define SET_MultiTexCoord3fARB(disp, fn) ((disp)->MultiTexCoord3fARB = fn)
+#define CALL_MultiTexCoord3fvARB(disp, parameters) (*((disp)->MultiTexCoord3fvARB)) parameters
+#define GET_MultiTexCoord3fvARB(disp) ((disp)->MultiTexCoord3fvARB)
+#define SET_MultiTexCoord3fvARB(disp, fn) ((disp)->MultiTexCoord3fvARB = fn)
+#define CALL_MultiTexCoord3iARB(disp, parameters) (*((disp)->MultiTexCoord3iARB)) parameters
+#define GET_MultiTexCoord3iARB(disp) ((disp)->MultiTexCoord3iARB)
+#define SET_MultiTexCoord3iARB(disp, fn) ((disp)->MultiTexCoord3iARB = fn)
+#define CALL_MultiTexCoord3ivARB(disp, parameters) (*((disp)->MultiTexCoord3ivARB)) parameters
+#define GET_MultiTexCoord3ivARB(disp) ((disp)->MultiTexCoord3ivARB)
+#define SET_MultiTexCoord3ivARB(disp, fn) ((disp)->MultiTexCoord3ivARB = fn)
+#define CALL_MultiTexCoord3sARB(disp, parameters) (*((disp)->MultiTexCoord3sARB)) parameters
+#define GET_MultiTexCoord3sARB(disp) ((disp)->MultiTexCoord3sARB)
+#define SET_MultiTexCoord3sARB(disp, fn) ((disp)->MultiTexCoord3sARB = fn)
+#define CALL_MultiTexCoord3svARB(disp, parameters) (*((disp)->MultiTexCoord3svARB)) parameters
+#define GET_MultiTexCoord3svARB(disp) ((disp)->MultiTexCoord3svARB)
+#define SET_MultiTexCoord3svARB(disp, fn) ((disp)->MultiTexCoord3svARB = fn)
+#define CALL_MultiTexCoord4dARB(disp, parameters) (*((disp)->MultiTexCoord4dARB)) parameters
+#define GET_MultiTexCoord4dARB(disp) ((disp)->MultiTexCoord4dARB)
+#define SET_MultiTexCoord4dARB(disp, fn) ((disp)->MultiTexCoord4dARB = fn)
+#define CALL_MultiTexCoord4dvARB(disp, parameters) (*((disp)->MultiTexCoord4dvARB)) parameters
+#define GET_MultiTexCoord4dvARB(disp) ((disp)->MultiTexCoord4dvARB)
+#define SET_MultiTexCoord4dvARB(disp, fn) ((disp)->MultiTexCoord4dvARB = fn)
+#define CALL_MultiTexCoord4fARB(disp, parameters) (*((disp)->MultiTexCoord4fARB)) parameters
+#define GET_MultiTexCoord4fARB(disp) ((disp)->MultiTexCoord4fARB)
+#define SET_MultiTexCoord4fARB(disp, fn) ((disp)->MultiTexCoord4fARB = fn)
+#define CALL_MultiTexCoord4fvARB(disp, parameters) (*((disp)->MultiTexCoord4fvARB)) parameters
+#define GET_MultiTexCoord4fvARB(disp) ((disp)->MultiTexCoord4fvARB)
+#define SET_MultiTexCoord4fvARB(disp, fn) ((disp)->MultiTexCoord4fvARB = fn)
+#define CALL_MultiTexCoord4iARB(disp, parameters) (*((disp)->MultiTexCoord4iARB)) parameters
+#define GET_MultiTexCoord4iARB(disp) ((disp)->MultiTexCoord4iARB)
+#define SET_MultiTexCoord4iARB(disp, fn) ((disp)->MultiTexCoord4iARB = fn)
+#define CALL_MultiTexCoord4ivARB(disp, parameters) (*((disp)->MultiTexCoord4ivARB)) parameters
+#define GET_MultiTexCoord4ivARB(disp) ((disp)->MultiTexCoord4ivARB)
+#define SET_MultiTexCoord4ivARB(disp, fn) ((disp)->MultiTexCoord4ivARB = fn)
+#define CALL_MultiTexCoord4sARB(disp, parameters) (*((disp)->MultiTexCoord4sARB)) parameters
+#define GET_MultiTexCoord4sARB(disp) ((disp)->MultiTexCoord4sARB)
+#define SET_MultiTexCoord4sARB(disp, fn) ((disp)->MultiTexCoord4sARB = fn)
+#define CALL_MultiTexCoord4svARB(disp, parameters) (*((disp)->MultiTexCoord4svARB)) parameters
+#define GET_MultiTexCoord4svARB(disp) ((disp)->MultiTexCoord4svARB)
+#define SET_MultiTexCoord4svARB(disp, fn) ((disp)->MultiTexCoord4svARB = fn)
+
+#if !defined(IN_DRI_DRIVER)
+
+#define CALL_AttachShader(disp, parameters) (*((disp)->AttachShader)) parameters
+#define GET_AttachShader(disp) ((disp)->AttachShader)
+#define SET_AttachShader(disp, fn) ((disp)->AttachShader = fn)
+#define CALL_CreateProgram(disp, parameters) (*((disp)->CreateProgram)) parameters
+#define GET_CreateProgram(disp) ((disp)->CreateProgram)
+#define SET_CreateProgram(disp, fn) ((disp)->CreateProgram = fn)
+#define CALL_CreateShader(disp, parameters) (*((disp)->CreateShader)) parameters
+#define GET_CreateShader(disp) ((disp)->CreateShader)
+#define SET_CreateShader(disp, fn) ((disp)->CreateShader = fn)
+#define CALL_DeleteProgram(disp, parameters) (*((disp)->DeleteProgram)) parameters
+#define GET_DeleteProgram(disp) ((disp)->DeleteProgram)
+#define SET_DeleteProgram(disp, fn) ((disp)->DeleteProgram = fn)
+#define CALL_DeleteShader(disp, parameters) (*((disp)->DeleteShader)) parameters
+#define GET_DeleteShader(disp) ((disp)->DeleteShader)
+#define SET_DeleteShader(disp, fn) ((disp)->DeleteShader = fn)
+#define CALL_DetachShader(disp, parameters) (*((disp)->DetachShader)) parameters
+#define GET_DetachShader(disp) ((disp)->DetachShader)
+#define SET_DetachShader(disp, fn) ((disp)->DetachShader = fn)
+#define CALL_GetAttachedShaders(disp, parameters) (*((disp)->GetAttachedShaders)) parameters
+#define GET_GetAttachedShaders(disp) ((disp)->GetAttachedShaders)
+#define SET_GetAttachedShaders(disp, fn) ((disp)->GetAttachedShaders = fn)
+#define CALL_GetProgramInfoLog(disp, parameters) (*((disp)->GetProgramInfoLog)) parameters
+#define GET_GetProgramInfoLog(disp) ((disp)->GetProgramInfoLog)
+#define SET_GetProgramInfoLog(disp, fn) ((disp)->GetProgramInfoLog = fn)
+#define CALL_GetProgramiv(disp, parameters) (*((disp)->GetProgramiv)) parameters
+#define GET_GetProgramiv(disp) ((disp)->GetProgramiv)
+#define SET_GetProgramiv(disp, fn) ((disp)->GetProgramiv = fn)
+#define CALL_GetShaderInfoLog(disp, parameters) (*((disp)->GetShaderInfoLog)) parameters
+#define GET_GetShaderInfoLog(disp) ((disp)->GetShaderInfoLog)
+#define SET_GetShaderInfoLog(disp, fn) ((disp)->GetShaderInfoLog = fn)
+#define CALL_GetShaderiv(disp, parameters) (*((disp)->GetShaderiv)) parameters
+#define GET_GetShaderiv(disp) ((disp)->GetShaderiv)
+#define SET_GetShaderiv(disp, fn) ((disp)->GetShaderiv = fn)
+#define CALL_IsProgram(disp, parameters) (*((disp)->IsProgram)) parameters
+#define GET_IsProgram(disp) ((disp)->IsProgram)
+#define SET_IsProgram(disp, fn) ((disp)->IsProgram = fn)
+#define CALL_IsShader(disp, parameters) (*((disp)->IsShader)) parameters
+#define GET_IsShader(disp) ((disp)->IsShader)
+#define SET_IsShader(disp, fn) ((disp)->IsShader = fn)
+#define CALL_StencilFuncSeparate(disp, parameters) (*((disp)->StencilFuncSeparate)) parameters
+#define GET_StencilFuncSeparate(disp) ((disp)->StencilFuncSeparate)
+#define SET_StencilFuncSeparate(disp, fn) ((disp)->StencilFuncSeparate = fn)
+#define CALL_StencilMaskSeparate(disp, parameters) (*((disp)->StencilMaskSeparate)) parameters
+#define GET_StencilMaskSeparate(disp) ((disp)->StencilMaskSeparate)
+#define SET_StencilMaskSeparate(disp, fn) ((disp)->StencilMaskSeparate = fn)
+#define CALL_StencilOpSeparate(disp, parameters) (*((disp)->StencilOpSeparate)) parameters
+#define GET_StencilOpSeparate(disp) ((disp)->StencilOpSeparate)
+#define SET_StencilOpSeparate(disp, fn) ((disp)->StencilOpSeparate = fn)
+#define CALL_UniformMatrix2x3fv(disp, parameters) (*((disp)->UniformMatrix2x3fv)) parameters
+#define GET_UniformMatrix2x3fv(disp) ((disp)->UniformMatrix2x3fv)
+#define SET_UniformMatrix2x3fv(disp, fn) ((disp)->UniformMatrix2x3fv = fn)
+#define CALL_UniformMatrix2x4fv(disp, parameters) (*((disp)->UniformMatrix2x4fv)) parameters
+#define GET_UniformMatrix2x4fv(disp) ((disp)->UniformMatrix2x4fv)
+#define SET_UniformMatrix2x4fv(disp, fn) ((disp)->UniformMatrix2x4fv = fn)
+#define CALL_UniformMatrix3x2fv(disp, parameters) (*((disp)->UniformMatrix3x2fv)) parameters
+#define GET_UniformMatrix3x2fv(disp) ((disp)->UniformMatrix3x2fv)
+#define SET_UniformMatrix3x2fv(disp, fn) ((disp)->UniformMatrix3x2fv = fn)
+#define CALL_UniformMatrix3x4fv(disp, parameters) (*((disp)->UniformMatrix3x4fv)) parameters
+#define GET_UniformMatrix3x4fv(disp) ((disp)->UniformMatrix3x4fv)
+#define SET_UniformMatrix3x4fv(disp, fn) ((disp)->UniformMatrix3x4fv = fn)
+#define CALL_UniformMatrix4x2fv(disp, parameters) (*((disp)->UniformMatrix4x2fv)) parameters
+#define GET_UniformMatrix4x2fv(disp) ((disp)->UniformMatrix4x2fv)
+#define SET_UniformMatrix4x2fv(disp, fn) ((disp)->UniformMatrix4x2fv = fn)
+#define CALL_UniformMatrix4x3fv(disp, parameters) (*((disp)->UniformMatrix4x3fv)) parameters
+#define GET_UniformMatrix4x3fv(disp) ((disp)->UniformMatrix4x3fv)
+#define SET_UniformMatrix4x3fv(disp, fn) ((disp)->UniformMatrix4x3fv = fn)
+#define CALL_LoadTransposeMatrixdARB(disp, parameters) (*((disp)->LoadTransposeMatrixdARB)) parameters
+#define GET_LoadTransposeMatrixdARB(disp) ((disp)->LoadTransposeMatrixdARB)
+#define SET_LoadTransposeMatrixdARB(disp, fn) ((disp)->LoadTransposeMatrixdARB = fn)
+#define CALL_LoadTransposeMatrixfARB(disp, parameters) (*((disp)->LoadTransposeMatrixfARB)) parameters
+#define GET_LoadTransposeMatrixfARB(disp) ((disp)->LoadTransposeMatrixfARB)
+#define SET_LoadTransposeMatrixfARB(disp, fn) ((disp)->LoadTransposeMatrixfARB = fn)
+#define CALL_MultTransposeMatrixdARB(disp, parameters) (*((disp)->MultTransposeMatrixdARB)) parameters
+#define GET_MultTransposeMatrixdARB(disp) ((disp)->MultTransposeMatrixdARB)
+#define SET_MultTransposeMatrixdARB(disp, fn) ((disp)->MultTransposeMatrixdARB = fn)
+#define CALL_MultTransposeMatrixfARB(disp, parameters) (*((disp)->MultTransposeMatrixfARB)) parameters
+#define GET_MultTransposeMatrixfARB(disp) ((disp)->MultTransposeMatrixfARB)
+#define SET_MultTransposeMatrixfARB(disp, fn) ((disp)->MultTransposeMatrixfARB = fn)
+#define CALL_SampleCoverageARB(disp, parameters) (*((disp)->SampleCoverageARB)) parameters
+#define GET_SampleCoverageARB(disp) ((disp)->SampleCoverageARB)
+#define SET_SampleCoverageARB(disp, fn) ((disp)->SampleCoverageARB = fn)
+#define CALL_CompressedTexImage1DARB(disp, parameters) (*((disp)->CompressedTexImage1DARB)) parameters
+#define GET_CompressedTexImage1DARB(disp) ((disp)->CompressedTexImage1DARB)
+#define SET_CompressedTexImage1DARB(disp, fn) ((disp)->CompressedTexImage1DARB = fn)
+#define CALL_CompressedTexImage2DARB(disp, parameters) (*((disp)->CompressedTexImage2DARB)) parameters
+#define GET_CompressedTexImage2DARB(disp) ((disp)->CompressedTexImage2DARB)
+#define SET_CompressedTexImage2DARB(disp, fn) ((disp)->CompressedTexImage2DARB = fn)
+#define CALL_CompressedTexImage3DARB(disp, parameters) (*((disp)->CompressedTexImage3DARB)) parameters
+#define GET_CompressedTexImage3DARB(disp) ((disp)->CompressedTexImage3DARB)
+#define SET_CompressedTexImage3DARB(disp, fn) ((disp)->CompressedTexImage3DARB = fn)
+#define CALL_CompressedTexSubImage1DARB(disp, parameters) (*((disp)->CompressedTexSubImage1DARB)) parameters
+#define GET_CompressedTexSubImage1DARB(disp) ((disp)->CompressedTexSubImage1DARB)
+#define SET_CompressedTexSubImage1DARB(disp, fn) ((disp)->CompressedTexSubImage1DARB = fn)
+#define CALL_CompressedTexSubImage2DARB(disp, parameters) (*((disp)->CompressedTexSubImage2DARB)) parameters
+#define GET_CompressedTexSubImage2DARB(disp) ((disp)->CompressedTexSubImage2DARB)
+#define SET_CompressedTexSubImage2DARB(disp, fn) ((disp)->CompressedTexSubImage2DARB = fn)
+#define CALL_CompressedTexSubImage3DARB(disp, parameters) (*((disp)->CompressedTexSubImage3DARB)) parameters
+#define GET_CompressedTexSubImage3DARB(disp) ((disp)->CompressedTexSubImage3DARB)
+#define SET_CompressedTexSubImage3DARB(disp, fn) ((disp)->CompressedTexSubImage3DARB = fn)
+#define CALL_GetCompressedTexImageARB(disp, parameters) (*((disp)->GetCompressedTexImageARB)) parameters
+#define GET_GetCompressedTexImageARB(disp) ((disp)->GetCompressedTexImageARB)
+#define SET_GetCompressedTexImageARB(disp, fn) ((disp)->GetCompressedTexImageARB = fn)
+#define CALL_DisableVertexAttribArrayARB(disp, parameters) (*((disp)->DisableVertexAttribArrayARB)) parameters
+#define GET_DisableVertexAttribArrayARB(disp) ((disp)->DisableVertexAttribArrayARB)
+#define SET_DisableVertexAttribArrayARB(disp, fn) ((disp)->DisableVertexAttribArrayARB = fn)
+#define CALL_EnableVertexAttribArrayARB(disp, parameters) (*((disp)->EnableVertexAttribArrayARB)) parameters
+#define GET_EnableVertexAttribArrayARB(disp) ((disp)->EnableVertexAttribArrayARB)
+#define SET_EnableVertexAttribArrayARB(disp, fn) ((disp)->EnableVertexAttribArrayARB = fn)
+#define CALL_GetProgramEnvParameterdvARB(disp, parameters) (*((disp)->GetProgramEnvParameterdvARB)) parameters
+#define GET_GetProgramEnvParameterdvARB(disp) ((disp)->GetProgramEnvParameterdvARB)
+#define SET_GetProgramEnvParameterdvARB(disp, fn) ((disp)->GetProgramEnvParameterdvARB = fn)
+#define CALL_GetProgramEnvParameterfvARB(disp, parameters) (*((disp)->GetProgramEnvParameterfvARB)) parameters
+#define GET_GetProgramEnvParameterfvARB(disp) ((disp)->GetProgramEnvParameterfvARB)
+#define SET_GetProgramEnvParameterfvARB(disp, fn) ((disp)->GetProgramEnvParameterfvARB = fn)
+#define CALL_GetProgramLocalParameterdvARB(disp, parameters) (*((disp)->GetProgramLocalParameterdvARB)) parameters
+#define GET_GetProgramLocalParameterdvARB(disp) ((disp)->GetProgramLocalParameterdvARB)
+#define SET_GetProgramLocalParameterdvARB(disp, fn) ((disp)->GetProgramLocalParameterdvARB = fn)
+#define CALL_GetProgramLocalParameterfvARB(disp, parameters) (*((disp)->GetProgramLocalParameterfvARB)) parameters
+#define GET_GetProgramLocalParameterfvARB(disp) ((disp)->GetProgramLocalParameterfvARB)
+#define SET_GetProgramLocalParameterfvARB(disp, fn) ((disp)->GetProgramLocalParameterfvARB = fn)
+#define CALL_GetProgramStringARB(disp, parameters) (*((disp)->GetProgramStringARB)) parameters
+#define GET_GetProgramStringARB(disp) ((disp)->GetProgramStringARB)
+#define SET_GetProgramStringARB(disp, fn) ((disp)->GetProgramStringARB = fn)
+#define CALL_GetProgramivARB(disp, parameters) (*((disp)->GetProgramivARB)) parameters
+#define GET_GetProgramivARB(disp) ((disp)->GetProgramivARB)
+#define SET_GetProgramivARB(disp, fn) ((disp)->GetProgramivARB = fn)
+#define CALL_GetVertexAttribdvARB(disp, parameters) (*((disp)->GetVertexAttribdvARB)) parameters
+#define GET_GetVertexAttribdvARB(disp) ((disp)->GetVertexAttribdvARB)
+#define SET_GetVertexAttribdvARB(disp, fn) ((disp)->GetVertexAttribdvARB = fn)
+#define CALL_GetVertexAttribfvARB(disp, parameters) (*((disp)->GetVertexAttribfvARB)) parameters
+#define GET_GetVertexAttribfvARB(disp) ((disp)->GetVertexAttribfvARB)
+#define SET_GetVertexAttribfvARB(disp, fn) ((disp)->GetVertexAttribfvARB = fn)
+#define CALL_GetVertexAttribivARB(disp, parameters) (*((disp)->GetVertexAttribivARB)) parameters
+#define GET_GetVertexAttribivARB(disp) ((disp)->GetVertexAttribivARB)
+#define SET_GetVertexAttribivARB(disp, fn) ((disp)->GetVertexAttribivARB = fn)
+#define CALL_ProgramEnvParameter4dARB(disp, parameters) (*((disp)->ProgramEnvParameter4dARB)) parameters
+#define GET_ProgramEnvParameter4dARB(disp) ((disp)->ProgramEnvParameter4dARB)
+#define SET_ProgramEnvParameter4dARB(disp, fn) ((disp)->ProgramEnvParameter4dARB = fn)
+#define CALL_ProgramEnvParameter4dvARB(disp, parameters) (*((disp)->ProgramEnvParameter4dvARB)) parameters
+#define GET_ProgramEnvParameter4dvARB(disp) ((disp)->ProgramEnvParameter4dvARB)
+#define SET_ProgramEnvParameter4dvARB(disp, fn) ((disp)->ProgramEnvParameter4dvARB = fn)
+#define CALL_ProgramEnvParameter4fARB(disp, parameters) (*((disp)->ProgramEnvParameter4fARB)) parameters
+#define GET_ProgramEnvParameter4fARB(disp) ((disp)->ProgramEnvParameter4fARB)
+#define SET_ProgramEnvParameter4fARB(disp, fn) ((disp)->ProgramEnvParameter4fARB = fn)
+#define CALL_ProgramEnvParameter4fvARB(disp, parameters) (*((disp)->ProgramEnvParameter4fvARB)) parameters
+#define GET_ProgramEnvParameter4fvARB(disp) ((disp)->ProgramEnvParameter4fvARB)
+#define SET_ProgramEnvParameter4fvARB(disp, fn) ((disp)->ProgramEnvParameter4fvARB = fn)
+#define CALL_ProgramLocalParameter4dARB(disp, parameters) (*((disp)->ProgramLocalParameter4dARB)) parameters
+#define GET_ProgramLocalParameter4dARB(disp) ((disp)->ProgramLocalParameter4dARB)
+#define SET_ProgramLocalParameter4dARB(disp, fn) ((disp)->ProgramLocalParameter4dARB = fn)
+#define CALL_ProgramLocalParameter4dvARB(disp, parameters) (*((disp)->ProgramLocalParameter4dvARB)) parameters
+#define GET_ProgramLocalParameter4dvARB(disp) ((disp)->ProgramLocalParameter4dvARB)
+#define SET_ProgramLocalParameter4dvARB(disp, fn) ((disp)->ProgramLocalParameter4dvARB = fn)
+#define CALL_ProgramLocalParameter4fARB(disp, parameters) (*((disp)->ProgramLocalParameter4fARB)) parameters
+#define GET_ProgramLocalParameter4fARB(disp) ((disp)->ProgramLocalParameter4fARB)
+#define SET_ProgramLocalParameter4fARB(disp, fn) ((disp)->ProgramLocalParameter4fARB = fn)
+#define CALL_ProgramLocalParameter4fvARB(disp, parameters) (*((disp)->ProgramLocalParameter4fvARB)) parameters
+#define GET_ProgramLocalParameter4fvARB(disp) ((disp)->ProgramLocalParameter4fvARB)
+#define SET_ProgramLocalParameter4fvARB(disp, fn) ((disp)->ProgramLocalParameter4fvARB = fn)
+#define CALL_ProgramStringARB(disp, parameters) (*((disp)->ProgramStringARB)) parameters
+#define GET_ProgramStringARB(disp) ((disp)->ProgramStringARB)
+#define SET_ProgramStringARB(disp, fn) ((disp)->ProgramStringARB = fn)
+#define CALL_VertexAttrib1dARB(disp, parameters) (*((disp)->VertexAttrib1dARB)) parameters
+#define GET_VertexAttrib1dARB(disp) ((disp)->VertexAttrib1dARB)
+#define SET_VertexAttrib1dARB(disp, fn) ((disp)->VertexAttrib1dARB = fn)
+#define CALL_VertexAttrib1dvARB(disp, parameters) (*((disp)->VertexAttrib1dvARB)) parameters
+#define GET_VertexAttrib1dvARB(disp) ((disp)->VertexAttrib1dvARB)
+#define SET_VertexAttrib1dvARB(disp, fn) ((disp)->VertexAttrib1dvARB = fn)
+#define CALL_VertexAttrib1fARB(disp, parameters) (*((disp)->VertexAttrib1fARB)) parameters
+#define GET_VertexAttrib1fARB(disp) ((disp)->VertexAttrib1fARB)
+#define SET_VertexAttrib1fARB(disp, fn) ((disp)->VertexAttrib1fARB = fn)
+#define CALL_VertexAttrib1fvARB(disp, parameters) (*((disp)->VertexAttrib1fvARB)) parameters
+#define GET_VertexAttrib1fvARB(disp) ((disp)->VertexAttrib1fvARB)
+#define SET_VertexAttrib1fvARB(disp, fn) ((disp)->VertexAttrib1fvARB = fn)
+#define CALL_VertexAttrib1sARB(disp, parameters) (*((disp)->VertexAttrib1sARB)) parameters
+#define GET_VertexAttrib1sARB(disp) ((disp)->VertexAttrib1sARB)
+#define SET_VertexAttrib1sARB(disp, fn) ((disp)->VertexAttrib1sARB = fn)
+#define CALL_VertexAttrib1svARB(disp, parameters) (*((disp)->VertexAttrib1svARB)) parameters
+#define GET_VertexAttrib1svARB(disp) ((disp)->VertexAttrib1svARB)
+#define SET_VertexAttrib1svARB(disp, fn) ((disp)->VertexAttrib1svARB = fn)
+#define CALL_VertexAttrib2dARB(disp, parameters) (*((disp)->VertexAttrib2dARB)) parameters
+#define GET_VertexAttrib2dARB(disp) ((disp)->VertexAttrib2dARB)
+#define SET_VertexAttrib2dARB(disp, fn) ((disp)->VertexAttrib2dARB = fn)
+#define CALL_VertexAttrib2dvARB(disp, parameters) (*((disp)->VertexAttrib2dvARB)) parameters
+#define GET_VertexAttrib2dvARB(disp) ((disp)->VertexAttrib2dvARB)
+#define SET_VertexAttrib2dvARB(disp, fn) ((disp)->VertexAttrib2dvARB = fn)
+#define CALL_VertexAttrib2fARB(disp, parameters) (*((disp)->VertexAttrib2fARB)) parameters
+#define GET_VertexAttrib2fARB(disp) ((disp)->VertexAttrib2fARB)
+#define SET_VertexAttrib2fARB(disp, fn) ((disp)->VertexAttrib2fARB = fn)
+#define CALL_VertexAttrib2fvARB(disp, parameters) (*((disp)->VertexAttrib2fvARB)) parameters
+#define GET_VertexAttrib2fvARB(disp) ((disp)->VertexAttrib2fvARB)
+#define SET_VertexAttrib2fvARB(disp, fn) ((disp)->VertexAttrib2fvARB = fn)
+#define CALL_VertexAttrib2sARB(disp, parameters) (*((disp)->VertexAttrib2sARB)) parameters
+#define GET_VertexAttrib2sARB(disp) ((disp)->VertexAttrib2sARB)
+#define SET_VertexAttrib2sARB(disp, fn) ((disp)->VertexAttrib2sARB = fn)
+#define CALL_VertexAttrib2svARB(disp, parameters) (*((disp)->VertexAttrib2svARB)) parameters
+#define GET_VertexAttrib2svARB(disp) ((disp)->VertexAttrib2svARB)
+#define SET_VertexAttrib2svARB(disp, fn) ((disp)->VertexAttrib2svARB = fn)
+#define CALL_VertexAttrib3dARB(disp, parameters) (*((disp)->VertexAttrib3dARB)) parameters
+#define GET_VertexAttrib3dARB(disp) ((disp)->VertexAttrib3dARB)
+#define SET_VertexAttrib3dARB(disp, fn) ((disp)->VertexAttrib3dARB = fn)
+#define CALL_VertexAttrib3dvARB(disp, parameters) (*((disp)->VertexAttrib3dvARB)) parameters
+#define GET_VertexAttrib3dvARB(disp) ((disp)->VertexAttrib3dvARB)
+#define SET_VertexAttrib3dvARB(disp, fn) ((disp)->VertexAttrib3dvARB = fn)
+#define CALL_VertexAttrib3fARB(disp, parameters) (*((disp)->VertexAttrib3fARB)) parameters
+#define GET_VertexAttrib3fARB(disp) ((disp)->VertexAttrib3fARB)
+#define SET_VertexAttrib3fARB(disp, fn) ((disp)->VertexAttrib3fARB = fn)
+#define CALL_VertexAttrib3fvARB(disp, parameters) (*((disp)->VertexAttrib3fvARB)) parameters
+#define GET_VertexAttrib3fvARB(disp) ((disp)->VertexAttrib3fvARB)
+#define SET_VertexAttrib3fvARB(disp, fn) ((disp)->VertexAttrib3fvARB = fn)
+#define CALL_VertexAttrib3sARB(disp, parameters) (*((disp)->VertexAttrib3sARB)) parameters
+#define GET_VertexAttrib3sARB(disp) ((disp)->VertexAttrib3sARB)
+#define SET_VertexAttrib3sARB(disp, fn) ((disp)->VertexAttrib3sARB = fn)
+#define CALL_VertexAttrib3svARB(disp, parameters) (*((disp)->VertexAttrib3svARB)) parameters
+#define GET_VertexAttrib3svARB(disp) ((disp)->VertexAttrib3svARB)
+#define SET_VertexAttrib3svARB(disp, fn) ((disp)->VertexAttrib3svARB = fn)
+#define CALL_VertexAttrib4NbvARB(disp, parameters) (*((disp)->VertexAttrib4NbvARB)) parameters
+#define GET_VertexAttrib4NbvARB(disp) ((disp)->VertexAttrib4NbvARB)
+#define SET_VertexAttrib4NbvARB(disp, fn) ((disp)->VertexAttrib4NbvARB = fn)
+#define CALL_VertexAttrib4NivARB(disp, parameters) (*((disp)->VertexAttrib4NivARB)) parameters
+#define GET_VertexAttrib4NivARB(disp) ((disp)->VertexAttrib4NivARB)
+#define SET_VertexAttrib4NivARB(disp, fn) ((disp)->VertexAttrib4NivARB = fn)
+#define CALL_VertexAttrib4NsvARB(disp, parameters) (*((disp)->VertexAttrib4NsvARB)) parameters
+#define GET_VertexAttrib4NsvARB(disp) ((disp)->VertexAttrib4NsvARB)
+#define SET_VertexAttrib4NsvARB(disp, fn) ((disp)->VertexAttrib4NsvARB = fn)
+#define CALL_VertexAttrib4NubARB(disp, parameters) (*((disp)->VertexAttrib4NubARB)) parameters
+#define GET_VertexAttrib4NubARB(disp) ((disp)->VertexAttrib4NubARB)
+#define SET_VertexAttrib4NubARB(disp, fn) ((disp)->VertexAttrib4NubARB = fn)
+#define CALL_VertexAttrib4NubvARB(disp, parameters) (*((disp)->VertexAttrib4NubvARB)) parameters
+#define GET_VertexAttrib4NubvARB(disp) ((disp)->VertexAttrib4NubvARB)
+#define SET_VertexAttrib4NubvARB(disp, fn) ((disp)->VertexAttrib4NubvARB = fn)
+#define CALL_VertexAttrib4NuivARB(disp, parameters) (*((disp)->VertexAttrib4NuivARB)) parameters
+#define GET_VertexAttrib4NuivARB(disp) ((disp)->VertexAttrib4NuivARB)
+#define SET_VertexAttrib4NuivARB(disp, fn) ((disp)->VertexAttrib4NuivARB = fn)
+#define CALL_VertexAttrib4NusvARB(disp, parameters) (*((disp)->VertexAttrib4NusvARB)) parameters
+#define GET_VertexAttrib4NusvARB(disp) ((disp)->VertexAttrib4NusvARB)
+#define SET_VertexAttrib4NusvARB(disp, fn) ((disp)->VertexAttrib4NusvARB = fn)
+#define CALL_VertexAttrib4bvARB(disp, parameters) (*((disp)->VertexAttrib4bvARB)) parameters
+#define GET_VertexAttrib4bvARB(disp) ((disp)->VertexAttrib4bvARB)
+#define SET_VertexAttrib4bvARB(disp, fn) ((disp)->VertexAttrib4bvARB = fn)
+#define CALL_VertexAttrib4dARB(disp, parameters) (*((disp)->VertexAttrib4dARB)) parameters
+#define GET_VertexAttrib4dARB(disp) ((disp)->VertexAttrib4dARB)
+#define SET_VertexAttrib4dARB(disp, fn) ((disp)->VertexAttrib4dARB = fn)
+#define CALL_VertexAttrib4dvARB(disp, parameters) (*((disp)->VertexAttrib4dvARB)) parameters
+#define GET_VertexAttrib4dvARB(disp) ((disp)->VertexAttrib4dvARB)
+#define SET_VertexAttrib4dvARB(disp, fn) ((disp)->VertexAttrib4dvARB = fn)
+#define CALL_VertexAttrib4fARB(disp, parameters) (*((disp)->VertexAttrib4fARB)) parameters
+#define GET_VertexAttrib4fARB(disp) ((disp)->VertexAttrib4fARB)
+#define SET_VertexAttrib4fARB(disp, fn) ((disp)->VertexAttrib4fARB = fn)
+#define CALL_VertexAttrib4fvARB(disp, parameters) (*((disp)->VertexAttrib4fvARB)) parameters
+#define GET_VertexAttrib4fvARB(disp) ((disp)->VertexAttrib4fvARB)
+#define SET_VertexAttrib4fvARB(disp, fn) ((disp)->VertexAttrib4fvARB = fn)
+#define CALL_VertexAttrib4ivARB(disp, parameters) (*((disp)->VertexAttrib4ivARB)) parameters
+#define GET_VertexAttrib4ivARB(disp) ((disp)->VertexAttrib4ivARB)
+#define SET_VertexAttrib4ivARB(disp, fn) ((disp)->VertexAttrib4ivARB = fn)
+#define CALL_VertexAttrib4sARB(disp, parameters) (*((disp)->VertexAttrib4sARB)) parameters
+#define GET_VertexAttrib4sARB(disp) ((disp)->VertexAttrib4sARB)
+#define SET_VertexAttrib4sARB(disp, fn) ((disp)->VertexAttrib4sARB = fn)
+#define CALL_VertexAttrib4svARB(disp, parameters) (*((disp)->VertexAttrib4svARB)) parameters
+#define GET_VertexAttrib4svARB(disp) ((disp)->VertexAttrib4svARB)
+#define SET_VertexAttrib4svARB(disp, fn) ((disp)->VertexAttrib4svARB = fn)
+#define CALL_VertexAttrib4ubvARB(disp, parameters) (*((disp)->VertexAttrib4ubvARB)) parameters
+#define GET_VertexAttrib4ubvARB(disp) ((disp)->VertexAttrib4ubvARB)
+#define SET_VertexAttrib4ubvARB(disp, fn) ((disp)->VertexAttrib4ubvARB = fn)
+#define CALL_VertexAttrib4uivARB(disp, parameters) (*((disp)->VertexAttrib4uivARB)) parameters
+#define GET_VertexAttrib4uivARB(disp) ((disp)->VertexAttrib4uivARB)
+#define SET_VertexAttrib4uivARB(disp, fn) ((disp)->VertexAttrib4uivARB = fn)
+#define CALL_VertexAttrib4usvARB(disp, parameters) (*((disp)->VertexAttrib4usvARB)) parameters
+#define GET_VertexAttrib4usvARB(disp) ((disp)->VertexAttrib4usvARB)
+#define SET_VertexAttrib4usvARB(disp, fn) ((disp)->VertexAttrib4usvARB = fn)
+#define CALL_VertexAttribPointerARB(disp, parameters) (*((disp)->VertexAttribPointerARB)) parameters
+#define GET_VertexAttribPointerARB(disp) ((disp)->VertexAttribPointerARB)
+#define SET_VertexAttribPointerARB(disp, fn) ((disp)->VertexAttribPointerARB = fn)
+#define CALL_BindBufferARB(disp, parameters) (*((disp)->BindBufferARB)) parameters
+#define GET_BindBufferARB(disp) ((disp)->BindBufferARB)
+#define SET_BindBufferARB(disp, fn) ((disp)->BindBufferARB = fn)
+#define CALL_BufferDataARB(disp, parameters) (*((disp)->BufferDataARB)) parameters
+#define GET_BufferDataARB(disp) ((disp)->BufferDataARB)
+#define SET_BufferDataARB(disp, fn) ((disp)->BufferDataARB = fn)
+#define CALL_BufferSubDataARB(disp, parameters) (*((disp)->BufferSubDataARB)) parameters
+#define GET_BufferSubDataARB(disp) ((disp)->BufferSubDataARB)
+#define SET_BufferSubDataARB(disp, fn) ((disp)->BufferSubDataARB = fn)
+#define CALL_DeleteBuffersARB(disp, parameters) (*((disp)->DeleteBuffersARB)) parameters
+#define GET_DeleteBuffersARB(disp) ((disp)->DeleteBuffersARB)
+#define SET_DeleteBuffersARB(disp, fn) ((disp)->DeleteBuffersARB = fn)
+#define CALL_GenBuffersARB(disp, parameters) (*((disp)->GenBuffersARB)) parameters
+#define GET_GenBuffersARB(disp) ((disp)->GenBuffersARB)
+#define SET_GenBuffersARB(disp, fn) ((disp)->GenBuffersARB = fn)
+#define CALL_GetBufferParameterivARB(disp, parameters) (*((disp)->GetBufferParameterivARB)) parameters
+#define GET_GetBufferParameterivARB(disp) ((disp)->GetBufferParameterivARB)
+#define SET_GetBufferParameterivARB(disp, fn) ((disp)->GetBufferParameterivARB = fn)
+#define CALL_GetBufferPointervARB(disp, parameters) (*((disp)->GetBufferPointervARB)) parameters
+#define GET_GetBufferPointervARB(disp) ((disp)->GetBufferPointervARB)
+#define SET_GetBufferPointervARB(disp, fn) ((disp)->GetBufferPointervARB = fn)
+#define CALL_GetBufferSubDataARB(disp, parameters) (*((disp)->GetBufferSubDataARB)) parameters
+#define GET_GetBufferSubDataARB(disp) ((disp)->GetBufferSubDataARB)
+#define SET_GetBufferSubDataARB(disp, fn) ((disp)->GetBufferSubDataARB = fn)
+#define CALL_IsBufferARB(disp, parameters) (*((disp)->IsBufferARB)) parameters
+#define GET_IsBufferARB(disp) ((disp)->IsBufferARB)
+#define SET_IsBufferARB(disp, fn) ((disp)->IsBufferARB = fn)
+#define CALL_MapBufferARB(disp, parameters) (*((disp)->MapBufferARB)) parameters
+#define GET_MapBufferARB(disp) ((disp)->MapBufferARB)
+#define SET_MapBufferARB(disp, fn) ((disp)->MapBufferARB = fn)
+#define CALL_UnmapBufferARB(disp, parameters) (*((disp)->UnmapBufferARB)) parameters
+#define GET_UnmapBufferARB(disp) ((disp)->UnmapBufferARB)
+#define SET_UnmapBufferARB(disp, fn) ((disp)->UnmapBufferARB = fn)
+#define CALL_BeginQueryARB(disp, parameters) (*((disp)->BeginQueryARB)) parameters
+#define GET_BeginQueryARB(disp) ((disp)->BeginQueryARB)
+#define SET_BeginQueryARB(disp, fn) ((disp)->BeginQueryARB = fn)
+#define CALL_DeleteQueriesARB(disp, parameters) (*((disp)->DeleteQueriesARB)) parameters
+#define GET_DeleteQueriesARB(disp) ((disp)->DeleteQueriesARB)
+#define SET_DeleteQueriesARB(disp, fn) ((disp)->DeleteQueriesARB = fn)
+#define CALL_EndQueryARB(disp, parameters) (*((disp)->EndQueryARB)) parameters
+#define GET_EndQueryARB(disp) ((disp)->EndQueryARB)
+#define SET_EndQueryARB(disp, fn) ((disp)->EndQueryARB = fn)
+#define CALL_GenQueriesARB(disp, parameters) (*((disp)->GenQueriesARB)) parameters
+#define GET_GenQueriesARB(disp) ((disp)->GenQueriesARB)
+#define SET_GenQueriesARB(disp, fn) ((disp)->GenQueriesARB = fn)
+#define CALL_GetQueryObjectivARB(disp, parameters) (*((disp)->GetQueryObjectivARB)) parameters
+#define GET_GetQueryObjectivARB(disp) ((disp)->GetQueryObjectivARB)
+#define SET_GetQueryObjectivARB(disp, fn) ((disp)->GetQueryObjectivARB = fn)
+#define CALL_GetQueryObjectuivARB(disp, parameters) (*((disp)->GetQueryObjectuivARB)) parameters
+#define GET_GetQueryObjectuivARB(disp) ((disp)->GetQueryObjectuivARB)
+#define SET_GetQueryObjectuivARB(disp, fn) ((disp)->GetQueryObjectuivARB = fn)
+#define CALL_GetQueryivARB(disp, parameters) (*((disp)->GetQueryivARB)) parameters
+#define GET_GetQueryivARB(disp) ((disp)->GetQueryivARB)
+#define SET_GetQueryivARB(disp, fn) ((disp)->GetQueryivARB = fn)
+#define CALL_IsQueryARB(disp, parameters) (*((disp)->IsQueryARB)) parameters
+#define GET_IsQueryARB(disp) ((disp)->IsQueryARB)
+#define SET_IsQueryARB(disp, fn) ((disp)->IsQueryARB = fn)
+#define CALL_AttachObjectARB(disp, parameters) (*((disp)->AttachObjectARB)) parameters
+#define GET_AttachObjectARB(disp) ((disp)->AttachObjectARB)
+#define SET_AttachObjectARB(disp, fn) ((disp)->AttachObjectARB = fn)
+#define CALL_CompileShaderARB(disp, parameters) (*((disp)->CompileShaderARB)) parameters
+#define GET_CompileShaderARB(disp) ((disp)->CompileShaderARB)
+#define SET_CompileShaderARB(disp, fn) ((disp)->CompileShaderARB = fn)
+#define CALL_CreateProgramObjectARB(disp, parameters) (*((disp)->CreateProgramObjectARB)) parameters
+#define GET_CreateProgramObjectARB(disp) ((disp)->CreateProgramObjectARB)
+#define SET_CreateProgramObjectARB(disp, fn) ((disp)->CreateProgramObjectARB = fn)
+#define CALL_CreateShaderObjectARB(disp, parameters) (*((disp)->CreateShaderObjectARB)) parameters
+#define GET_CreateShaderObjectARB(disp) ((disp)->CreateShaderObjectARB)
+#define SET_CreateShaderObjectARB(disp, fn) ((disp)->CreateShaderObjectARB = fn)
+#define CALL_DeleteObjectARB(disp, parameters) (*((disp)->DeleteObjectARB)) parameters
+#define GET_DeleteObjectARB(disp) ((disp)->DeleteObjectARB)
+#define SET_DeleteObjectARB(disp, fn) ((disp)->DeleteObjectARB = fn)
+#define CALL_DetachObjectARB(disp, parameters) (*((disp)->DetachObjectARB)) parameters
+#define GET_DetachObjectARB(disp) ((disp)->DetachObjectARB)
+#define SET_DetachObjectARB(disp, fn) ((disp)->DetachObjectARB = fn)
+#define CALL_GetActiveUniformARB(disp, parameters) (*((disp)->GetActiveUniformARB)) parameters
+#define GET_GetActiveUniformARB(disp) ((disp)->GetActiveUniformARB)
+#define SET_GetActiveUniformARB(disp, fn) ((disp)->GetActiveUniformARB = fn)
+#define CALL_GetAttachedObjectsARB(disp, parameters) (*((disp)->GetAttachedObjectsARB)) parameters
+#define GET_GetAttachedObjectsARB(disp) ((disp)->GetAttachedObjectsARB)
+#define SET_GetAttachedObjectsARB(disp, fn) ((disp)->GetAttachedObjectsARB = fn)
+#define CALL_GetHandleARB(disp, parameters) (*((disp)->GetHandleARB)) parameters
+#define GET_GetHandleARB(disp) ((disp)->GetHandleARB)
+#define SET_GetHandleARB(disp, fn) ((disp)->GetHandleARB = fn)
+#define CALL_GetInfoLogARB(disp, parameters) (*((disp)->GetInfoLogARB)) parameters
+#define GET_GetInfoLogARB(disp) ((disp)->GetInfoLogARB)
+#define SET_GetInfoLogARB(disp, fn) ((disp)->GetInfoLogARB = fn)
+#define CALL_GetObjectParameterfvARB(disp, parameters) (*((disp)->GetObjectParameterfvARB)) parameters
+#define GET_GetObjectParameterfvARB(disp) ((disp)->GetObjectParameterfvARB)
+#define SET_GetObjectParameterfvARB(disp, fn) ((disp)->GetObjectParameterfvARB = fn)
+#define CALL_GetObjectParameterivARB(disp, parameters) (*((disp)->GetObjectParameterivARB)) parameters
+#define GET_GetObjectParameterivARB(disp) ((disp)->GetObjectParameterivARB)
+#define SET_GetObjectParameterivARB(disp, fn) ((disp)->GetObjectParameterivARB = fn)
+#define CALL_GetShaderSourceARB(disp, parameters) (*((disp)->GetShaderSourceARB)) parameters
+#define GET_GetShaderSourceARB(disp) ((disp)->GetShaderSourceARB)
+#define SET_GetShaderSourceARB(disp, fn) ((disp)->GetShaderSourceARB = fn)
+#define CALL_GetUniformLocationARB(disp, parameters) (*((disp)->GetUniformLocationARB)) parameters
+#define GET_GetUniformLocationARB(disp) ((disp)->GetUniformLocationARB)
+#define SET_GetUniformLocationARB(disp, fn) ((disp)->GetUniformLocationARB = fn)
+#define CALL_GetUniformfvARB(disp, parameters) (*((disp)->GetUniformfvARB)) parameters
+#define GET_GetUniformfvARB(disp) ((disp)->GetUniformfvARB)
+#define SET_GetUniformfvARB(disp, fn) ((disp)->GetUniformfvARB = fn)
+#define CALL_GetUniformivARB(disp, parameters) (*((disp)->GetUniformivARB)) parameters
+#define GET_GetUniformivARB(disp) ((disp)->GetUniformivARB)
+#define SET_GetUniformivARB(disp, fn) ((disp)->GetUniformivARB = fn)
+#define CALL_LinkProgramARB(disp, parameters) (*((disp)->LinkProgramARB)) parameters
+#define GET_LinkProgramARB(disp) ((disp)->LinkProgramARB)
+#define SET_LinkProgramARB(disp, fn) ((disp)->LinkProgramARB = fn)
+#define CALL_ShaderSourceARB(disp, parameters) (*((disp)->ShaderSourceARB)) parameters
+#define GET_ShaderSourceARB(disp) ((disp)->ShaderSourceARB)
+#define SET_ShaderSourceARB(disp, fn) ((disp)->ShaderSourceARB = fn)
+#define CALL_Uniform1fARB(disp, parameters) (*((disp)->Uniform1fARB)) parameters
+#define GET_Uniform1fARB(disp) ((disp)->Uniform1fARB)
+#define SET_Uniform1fARB(disp, fn) ((disp)->Uniform1fARB = fn)
+#define CALL_Uniform1fvARB(disp, parameters) (*((disp)->Uniform1fvARB)) parameters
+#define GET_Uniform1fvARB(disp) ((disp)->Uniform1fvARB)
+#define SET_Uniform1fvARB(disp, fn) ((disp)->Uniform1fvARB = fn)
+#define CALL_Uniform1iARB(disp, parameters) (*((disp)->Uniform1iARB)) parameters
+#define GET_Uniform1iARB(disp) ((disp)->Uniform1iARB)
+#define SET_Uniform1iARB(disp, fn) ((disp)->Uniform1iARB = fn)
+#define CALL_Uniform1ivARB(disp, parameters) (*((disp)->Uniform1ivARB)) parameters
+#define GET_Uniform1ivARB(disp) ((disp)->Uniform1ivARB)
+#define SET_Uniform1ivARB(disp, fn) ((disp)->Uniform1ivARB = fn)
+#define CALL_Uniform2fARB(disp, parameters) (*((disp)->Uniform2fARB)) parameters
+#define GET_Uniform2fARB(disp) ((disp)->Uniform2fARB)
+#define SET_Uniform2fARB(disp, fn) ((disp)->Uniform2fARB = fn)
+#define CALL_Uniform2fvARB(disp, parameters) (*((disp)->Uniform2fvARB)) parameters
+#define GET_Uniform2fvARB(disp) ((disp)->Uniform2fvARB)
+#define SET_Uniform2fvARB(disp, fn) ((disp)->Uniform2fvARB = fn)
+#define CALL_Uniform2iARB(disp, parameters) (*((disp)->Uniform2iARB)) parameters
+#define GET_Uniform2iARB(disp) ((disp)->Uniform2iARB)
+#define SET_Uniform2iARB(disp, fn) ((disp)->Uniform2iARB = fn)
+#define CALL_Uniform2ivARB(disp, parameters) (*((disp)->Uniform2ivARB)) parameters
+#define GET_Uniform2ivARB(disp) ((disp)->Uniform2ivARB)
+#define SET_Uniform2ivARB(disp, fn) ((disp)->Uniform2ivARB = fn)
+#define CALL_Uniform3fARB(disp, parameters) (*((disp)->Uniform3fARB)) parameters
+#define GET_Uniform3fARB(disp) ((disp)->Uniform3fARB)
+#define SET_Uniform3fARB(disp, fn) ((disp)->Uniform3fARB = fn)
+#define CALL_Uniform3fvARB(disp, parameters) (*((disp)->Uniform3fvARB)) parameters
+#define GET_Uniform3fvARB(disp) ((disp)->Uniform3fvARB)
+#define SET_Uniform3fvARB(disp, fn) ((disp)->Uniform3fvARB = fn)
+#define CALL_Uniform3iARB(disp, parameters) (*((disp)->Uniform3iARB)) parameters
+#define GET_Uniform3iARB(disp) ((disp)->Uniform3iARB)
+#define SET_Uniform3iARB(disp, fn) ((disp)->Uniform3iARB = fn)
+#define CALL_Uniform3ivARB(disp, parameters) (*((disp)->Uniform3ivARB)) parameters
+#define GET_Uniform3ivARB(disp) ((disp)->Uniform3ivARB)
+#define SET_Uniform3ivARB(disp, fn) ((disp)->Uniform3ivARB = fn)
+#define CALL_Uniform4fARB(disp, parameters) (*((disp)->Uniform4fARB)) parameters
+#define GET_Uniform4fARB(disp) ((disp)->Uniform4fARB)
+#define SET_Uniform4fARB(disp, fn) ((disp)->Uniform4fARB = fn)
+#define CALL_Uniform4fvARB(disp, parameters) (*((disp)->Uniform4fvARB)) parameters
+#define GET_Uniform4fvARB(disp) ((disp)->Uniform4fvARB)
+#define SET_Uniform4fvARB(disp, fn) ((disp)->Uniform4fvARB = fn)
+#define CALL_Uniform4iARB(disp, parameters) (*((disp)->Uniform4iARB)) parameters
+#define GET_Uniform4iARB(disp) ((disp)->Uniform4iARB)
+#define SET_Uniform4iARB(disp, fn) ((disp)->Uniform4iARB = fn)
+#define CALL_Uniform4ivARB(disp, parameters) (*((disp)->Uniform4ivARB)) parameters
+#define GET_Uniform4ivARB(disp) ((disp)->Uniform4ivARB)
+#define SET_Uniform4ivARB(disp, fn) ((disp)->Uniform4ivARB = fn)
+#define CALL_UniformMatrix2fvARB(disp, parameters) (*((disp)->UniformMatrix2fvARB)) parameters
+#define GET_UniformMatrix2fvARB(disp) ((disp)->UniformMatrix2fvARB)
+#define SET_UniformMatrix2fvARB(disp, fn) ((disp)->UniformMatrix2fvARB = fn)
+#define CALL_UniformMatrix3fvARB(disp, parameters) (*((disp)->UniformMatrix3fvARB)) parameters
+#define GET_UniformMatrix3fvARB(disp) ((disp)->UniformMatrix3fvARB)
+#define SET_UniformMatrix3fvARB(disp, fn) ((disp)->UniformMatrix3fvARB = fn)
+#define CALL_UniformMatrix4fvARB(disp, parameters) (*((disp)->UniformMatrix4fvARB)) parameters
+#define GET_UniformMatrix4fvARB(disp) ((disp)->UniformMatrix4fvARB)
+#define SET_UniformMatrix4fvARB(disp, fn) ((disp)->UniformMatrix4fvARB = fn)
+#define CALL_UseProgramObjectARB(disp, parameters) (*((disp)->UseProgramObjectARB)) parameters
+#define GET_UseProgramObjectARB(disp) ((disp)->UseProgramObjectARB)
+#define SET_UseProgramObjectARB(disp, fn) ((disp)->UseProgramObjectARB = fn)
+#define CALL_ValidateProgramARB(disp, parameters) (*((disp)->ValidateProgramARB)) parameters
+#define GET_ValidateProgramARB(disp) ((disp)->ValidateProgramARB)
+#define SET_ValidateProgramARB(disp, fn) ((disp)->ValidateProgramARB = fn)
+#define CALL_BindAttribLocationARB(disp, parameters) (*((disp)->BindAttribLocationARB)) parameters
+#define GET_BindAttribLocationARB(disp) ((disp)->BindAttribLocationARB)
+#define SET_BindAttribLocationARB(disp, fn) ((disp)->BindAttribLocationARB = fn)
+#define CALL_GetActiveAttribARB(disp, parameters) (*((disp)->GetActiveAttribARB)) parameters
+#define GET_GetActiveAttribARB(disp) ((disp)->GetActiveAttribARB)
+#define SET_GetActiveAttribARB(disp, fn) ((disp)->GetActiveAttribARB = fn)
+#define CALL_GetAttribLocationARB(disp, parameters) (*((disp)->GetAttribLocationARB)) parameters
+#define GET_GetAttribLocationARB(disp) ((disp)->GetAttribLocationARB)
+#define SET_GetAttribLocationARB(disp, fn) ((disp)->GetAttribLocationARB = fn)
+#define CALL_DrawBuffersARB(disp, parameters) (*((disp)->DrawBuffersARB)) parameters
+#define GET_DrawBuffersARB(disp) ((disp)->DrawBuffersARB)
+#define SET_DrawBuffersARB(disp, fn) ((disp)->DrawBuffersARB = fn)
+#define CALL_RenderbufferStorageMultisample(disp, parameters) (*((disp)->RenderbufferStorageMultisample)) parameters
+#define GET_RenderbufferStorageMultisample(disp) ((disp)->RenderbufferStorageMultisample)
+#define SET_RenderbufferStorageMultisample(disp, fn) ((disp)->RenderbufferStorageMultisample = fn)
+#define CALL_FlushMappedBufferRange(disp, parameters) (*((disp)->FlushMappedBufferRange)) parameters
+#define GET_FlushMappedBufferRange(disp) ((disp)->FlushMappedBufferRange)
+#define SET_FlushMappedBufferRange(disp, fn) ((disp)->FlushMappedBufferRange = fn)
+#define CALL_MapBufferRange(disp, parameters) (*((disp)->MapBufferRange)) parameters
+#define GET_MapBufferRange(disp) ((disp)->MapBufferRange)
+#define SET_MapBufferRange(disp, fn) ((disp)->MapBufferRange = fn)
+#define CALL_BindVertexArray(disp, parameters) (*((disp)->BindVertexArray)) parameters
+#define GET_BindVertexArray(disp) ((disp)->BindVertexArray)
+#define SET_BindVertexArray(disp, fn) ((disp)->BindVertexArray = fn)
+#define CALL_GenVertexArrays(disp, parameters) (*((disp)->GenVertexArrays)) parameters
+#define GET_GenVertexArrays(disp) ((disp)->GenVertexArrays)
+#define SET_GenVertexArrays(disp, fn) ((disp)->GenVertexArrays = fn)
+#define CALL_CopyBufferSubData(disp, parameters) (*((disp)->CopyBufferSubData)) parameters
+#define GET_CopyBufferSubData(disp) ((disp)->CopyBufferSubData)
+#define SET_CopyBufferSubData(disp, fn) ((disp)->CopyBufferSubData = fn)
+#define CALL_ClientWaitSync(disp, parameters) (*((disp)->ClientWaitSync)) parameters
+#define GET_ClientWaitSync(disp) ((disp)->ClientWaitSync)
+#define SET_ClientWaitSync(disp, fn) ((disp)->ClientWaitSync = fn)
+#define CALL_DeleteSync(disp, parameters) (*((disp)->DeleteSync)) parameters
+#define GET_DeleteSync(disp) ((disp)->DeleteSync)
+#define SET_DeleteSync(disp, fn) ((disp)->DeleteSync = fn)
+#define CALL_FenceSync(disp, parameters) (*((disp)->FenceSync)) parameters
+#define GET_FenceSync(disp) ((disp)->FenceSync)
+#define SET_FenceSync(disp, fn) ((disp)->FenceSync = fn)
+#define CALL_GetInteger64v(disp, parameters) (*((disp)->GetInteger64v)) parameters
+#define GET_GetInteger64v(disp) ((disp)->GetInteger64v)
+#define SET_GetInteger64v(disp, fn) ((disp)->GetInteger64v = fn)
+#define CALL_GetSynciv(disp, parameters) (*((disp)->GetSynciv)) parameters
+#define GET_GetSynciv(disp) ((disp)->GetSynciv)
+#define SET_GetSynciv(disp, fn) ((disp)->GetSynciv = fn)
+#define CALL_IsSync(disp, parameters) (*((disp)->IsSync)) parameters
+#define GET_IsSync(disp) ((disp)->IsSync)
+#define SET_IsSync(disp, fn) ((disp)->IsSync = fn)
+#define CALL_WaitSync(disp, parameters) (*((disp)->WaitSync)) parameters
+#define GET_WaitSync(disp) ((disp)->WaitSync)
+#define SET_WaitSync(disp, fn) ((disp)->WaitSync = fn)
+#define CALL_PolygonOffsetEXT(disp, parameters) (*((disp)->PolygonOffsetEXT)) parameters
+#define GET_PolygonOffsetEXT(disp) ((disp)->PolygonOffsetEXT)
+#define SET_PolygonOffsetEXT(disp, fn) ((disp)->PolygonOffsetEXT = fn)
+#define CALL_GetPixelTexGenParameterfvSGIS(disp, parameters) (*((disp)->GetPixelTexGenParameterfvSGIS)) parameters
+#define GET_GetPixelTexGenParameterfvSGIS(disp) ((disp)->GetPixelTexGenParameterfvSGIS)
+#define SET_GetPixelTexGenParameterfvSGIS(disp, fn) ((disp)->GetPixelTexGenParameterfvSGIS = fn)
+#define CALL_GetPixelTexGenParameterivSGIS(disp, parameters) (*((disp)->GetPixelTexGenParameterivSGIS)) parameters
+#define GET_GetPixelTexGenParameterivSGIS(disp) ((disp)->GetPixelTexGenParameterivSGIS)
+#define SET_GetPixelTexGenParameterivSGIS(disp, fn) ((disp)->GetPixelTexGenParameterivSGIS = fn)
+#define CALL_PixelTexGenParameterfSGIS(disp, parameters) (*((disp)->PixelTexGenParameterfSGIS)) parameters
+#define GET_PixelTexGenParameterfSGIS(disp) ((disp)->PixelTexGenParameterfSGIS)
+#define SET_PixelTexGenParameterfSGIS(disp, fn) ((disp)->PixelTexGenParameterfSGIS = fn)
+#define CALL_PixelTexGenParameterfvSGIS(disp, parameters) (*((disp)->PixelTexGenParameterfvSGIS)) parameters
+#define GET_PixelTexGenParameterfvSGIS(disp) ((disp)->PixelTexGenParameterfvSGIS)
+#define SET_PixelTexGenParameterfvSGIS(disp, fn) ((disp)->PixelTexGenParameterfvSGIS = fn)
+#define CALL_PixelTexGenParameteriSGIS(disp, parameters) (*((disp)->PixelTexGenParameteriSGIS)) parameters
+#define GET_PixelTexGenParameteriSGIS(disp) ((disp)->PixelTexGenParameteriSGIS)
+#define SET_PixelTexGenParameteriSGIS(disp, fn) ((disp)->PixelTexGenParameteriSGIS = fn)
+#define CALL_PixelTexGenParameterivSGIS(disp, parameters) (*((disp)->PixelTexGenParameterivSGIS)) parameters
+#define GET_PixelTexGenParameterivSGIS(disp) ((disp)->PixelTexGenParameterivSGIS)
+#define SET_PixelTexGenParameterivSGIS(disp, fn) ((disp)->PixelTexGenParameterivSGIS = fn)
+#define CALL_SampleMaskSGIS(disp, parameters) (*((disp)->SampleMaskSGIS)) parameters
+#define GET_SampleMaskSGIS(disp) ((disp)->SampleMaskSGIS)
+#define SET_SampleMaskSGIS(disp, fn) ((disp)->SampleMaskSGIS = fn)
+#define CALL_SamplePatternSGIS(disp, parameters) (*((disp)->SamplePatternSGIS)) parameters
+#define GET_SamplePatternSGIS(disp) ((disp)->SamplePatternSGIS)
+#define SET_SamplePatternSGIS(disp, fn) ((disp)->SamplePatternSGIS = fn)
+#define CALL_ColorPointerEXT(disp, parameters) (*((disp)->ColorPointerEXT)) parameters
+#define GET_ColorPointerEXT(disp) ((disp)->ColorPointerEXT)
+#define SET_ColorPointerEXT(disp, fn) ((disp)->ColorPointerEXT = fn)
+#define CALL_EdgeFlagPointerEXT(disp, parameters) (*((disp)->EdgeFlagPointerEXT)) parameters
+#define GET_EdgeFlagPointerEXT(disp) ((disp)->EdgeFlagPointerEXT)
+#define SET_EdgeFlagPointerEXT(disp, fn) ((disp)->EdgeFlagPointerEXT = fn)
+#define CALL_IndexPointerEXT(disp, parameters) (*((disp)->IndexPointerEXT)) parameters
+#define GET_IndexPointerEXT(disp) ((disp)->IndexPointerEXT)
+#define SET_IndexPointerEXT(disp, fn) ((disp)->IndexPointerEXT = fn)
+#define CALL_NormalPointerEXT(disp, parameters) (*((disp)->NormalPointerEXT)) parameters
+#define GET_NormalPointerEXT(disp) ((disp)->NormalPointerEXT)
+#define SET_NormalPointerEXT(disp, fn) ((disp)->NormalPointerEXT = fn)
+#define CALL_TexCoordPointerEXT(disp, parameters) (*((disp)->TexCoordPointerEXT)) parameters
+#define GET_TexCoordPointerEXT(disp) ((disp)->TexCoordPointerEXT)
+#define SET_TexCoordPointerEXT(disp, fn) ((disp)->TexCoordPointerEXT = fn)
+#define CALL_VertexPointerEXT(disp, parameters) (*((disp)->VertexPointerEXT)) parameters
+#define GET_VertexPointerEXT(disp) ((disp)->VertexPointerEXT)
+#define SET_VertexPointerEXT(disp, fn) ((disp)->VertexPointerEXT = fn)
+#define CALL_PointParameterfEXT(disp, parameters) (*((disp)->PointParameterfEXT)) parameters
+#define GET_PointParameterfEXT(disp) ((disp)->PointParameterfEXT)
+#define SET_PointParameterfEXT(disp, fn) ((disp)->PointParameterfEXT = fn)
+#define CALL_PointParameterfvEXT(disp, parameters) (*((disp)->PointParameterfvEXT)) parameters
+#define GET_PointParameterfvEXT(disp) ((disp)->PointParameterfvEXT)
+#define SET_PointParameterfvEXT(disp, fn) ((disp)->PointParameterfvEXT = fn)
+#define CALL_LockArraysEXT(disp, parameters) (*((disp)->LockArraysEXT)) parameters
+#define GET_LockArraysEXT(disp) ((disp)->LockArraysEXT)
+#define SET_LockArraysEXT(disp, fn) ((disp)->LockArraysEXT = fn)
+#define CALL_UnlockArraysEXT(disp, parameters) (*((disp)->UnlockArraysEXT)) parameters
+#define GET_UnlockArraysEXT(disp) ((disp)->UnlockArraysEXT)
+#define SET_UnlockArraysEXT(disp, fn) ((disp)->UnlockArraysEXT = fn)
+#define CALL_CullParameterdvEXT(disp, parameters) (*((disp)->CullParameterdvEXT)) parameters
+#define GET_CullParameterdvEXT(disp) ((disp)->CullParameterdvEXT)
+#define SET_CullParameterdvEXT(disp, fn) ((disp)->CullParameterdvEXT = fn)
+#define CALL_CullParameterfvEXT(disp, parameters) (*((disp)->CullParameterfvEXT)) parameters
+#define GET_CullParameterfvEXT(disp) ((disp)->CullParameterfvEXT)
+#define SET_CullParameterfvEXT(disp, fn) ((disp)->CullParameterfvEXT = fn)
+#define CALL_SecondaryColor3bEXT(disp, parameters) (*((disp)->SecondaryColor3bEXT)) parameters
+#define GET_SecondaryColor3bEXT(disp) ((disp)->SecondaryColor3bEXT)
+#define SET_SecondaryColor3bEXT(disp, fn) ((disp)->SecondaryColor3bEXT = fn)
+#define CALL_SecondaryColor3bvEXT(disp, parameters) (*((disp)->SecondaryColor3bvEXT)) parameters
+#define GET_SecondaryColor3bvEXT(disp) ((disp)->SecondaryColor3bvEXT)
+#define SET_SecondaryColor3bvEXT(disp, fn) ((disp)->SecondaryColor3bvEXT = fn)
+#define CALL_SecondaryColor3dEXT(disp, parameters) (*((disp)->SecondaryColor3dEXT)) parameters
+#define GET_SecondaryColor3dEXT(disp) ((disp)->SecondaryColor3dEXT)
+#define SET_SecondaryColor3dEXT(disp, fn) ((disp)->SecondaryColor3dEXT = fn)
+#define CALL_SecondaryColor3dvEXT(disp, parameters) (*((disp)->SecondaryColor3dvEXT)) parameters
+#define GET_SecondaryColor3dvEXT(disp) ((disp)->SecondaryColor3dvEXT)
+#define SET_SecondaryColor3dvEXT(disp, fn) ((disp)->SecondaryColor3dvEXT = fn)
+#define CALL_SecondaryColor3fEXT(disp, parameters) (*((disp)->SecondaryColor3fEXT)) parameters
+#define GET_SecondaryColor3fEXT(disp) ((disp)->SecondaryColor3fEXT)
+#define SET_SecondaryColor3fEXT(disp, fn) ((disp)->SecondaryColor3fEXT = fn)
+#define CALL_SecondaryColor3fvEXT(disp, parameters) (*((disp)->SecondaryColor3fvEXT)) parameters
+#define GET_SecondaryColor3fvEXT(disp) ((disp)->SecondaryColor3fvEXT)
+#define SET_SecondaryColor3fvEXT(disp, fn) ((disp)->SecondaryColor3fvEXT = fn)
+#define CALL_SecondaryColor3iEXT(disp, parameters) (*((disp)->SecondaryColor3iEXT)) parameters
+#define GET_SecondaryColor3iEXT(disp) ((disp)->SecondaryColor3iEXT)
+#define SET_SecondaryColor3iEXT(disp, fn) ((disp)->SecondaryColor3iEXT = fn)
+#define CALL_SecondaryColor3ivEXT(disp, parameters) (*((disp)->SecondaryColor3ivEXT)) parameters
+#define GET_SecondaryColor3ivEXT(disp) ((disp)->SecondaryColor3ivEXT)
+#define SET_SecondaryColor3ivEXT(disp, fn) ((disp)->SecondaryColor3ivEXT = fn)
+#define CALL_SecondaryColor3sEXT(disp, parameters) (*((disp)->SecondaryColor3sEXT)) parameters
+#define GET_SecondaryColor3sEXT(disp) ((disp)->SecondaryColor3sEXT)
+#define SET_SecondaryColor3sEXT(disp, fn) ((disp)->SecondaryColor3sEXT = fn)
+#define CALL_SecondaryColor3svEXT(disp, parameters) (*((disp)->SecondaryColor3svEXT)) parameters
+#define GET_SecondaryColor3svEXT(disp) ((disp)->SecondaryColor3svEXT)
+#define SET_SecondaryColor3svEXT(disp, fn) ((disp)->SecondaryColor3svEXT = fn)
+#define CALL_SecondaryColor3ubEXT(disp, parameters) (*((disp)->SecondaryColor3ubEXT)) parameters
+#define GET_SecondaryColor3ubEXT(disp) ((disp)->SecondaryColor3ubEXT)
+#define SET_SecondaryColor3ubEXT(disp, fn) ((disp)->SecondaryColor3ubEXT = fn)
+#define CALL_SecondaryColor3ubvEXT(disp, parameters) (*((disp)->SecondaryColor3ubvEXT)) parameters
+#define GET_SecondaryColor3ubvEXT(disp) ((disp)->SecondaryColor3ubvEXT)
+#define SET_SecondaryColor3ubvEXT(disp, fn) ((disp)->SecondaryColor3ubvEXT = fn)
+#define CALL_SecondaryColor3uiEXT(disp, parameters) (*((disp)->SecondaryColor3uiEXT)) parameters
+#define GET_SecondaryColor3uiEXT(disp) ((disp)->SecondaryColor3uiEXT)
+#define SET_SecondaryColor3uiEXT(disp, fn) ((disp)->SecondaryColor3uiEXT = fn)
+#define CALL_SecondaryColor3uivEXT(disp, parameters) (*((disp)->SecondaryColor3uivEXT)) parameters
+#define GET_SecondaryColor3uivEXT(disp) ((disp)->SecondaryColor3uivEXT)
+#define SET_SecondaryColor3uivEXT(disp, fn) ((disp)->SecondaryColor3uivEXT = fn)
+#define CALL_SecondaryColor3usEXT(disp, parameters) (*((disp)->SecondaryColor3usEXT)) parameters
+#define GET_SecondaryColor3usEXT(disp) ((disp)->SecondaryColor3usEXT)
+#define SET_SecondaryColor3usEXT(disp, fn) ((disp)->SecondaryColor3usEXT = fn)
+#define CALL_SecondaryColor3usvEXT(disp, parameters) (*((disp)->SecondaryColor3usvEXT)) parameters
+#define GET_SecondaryColor3usvEXT(disp) ((disp)->SecondaryColor3usvEXT)
+#define SET_SecondaryColor3usvEXT(disp, fn) ((disp)->SecondaryColor3usvEXT = fn)
+#define CALL_SecondaryColorPointerEXT(disp, parameters) (*((disp)->SecondaryColorPointerEXT)) parameters
+#define GET_SecondaryColorPointerEXT(disp) ((disp)->SecondaryColorPointerEXT)
+#define SET_SecondaryColorPointerEXT(disp, fn) ((disp)->SecondaryColorPointerEXT = fn)
+#define CALL_MultiDrawArraysEXT(disp, parameters) (*((disp)->MultiDrawArraysEXT)) parameters
+#define GET_MultiDrawArraysEXT(disp) ((disp)->MultiDrawArraysEXT)
+#define SET_MultiDrawArraysEXT(disp, fn) ((disp)->MultiDrawArraysEXT = fn)
+#define CALL_MultiDrawElementsEXT(disp, parameters) (*((disp)->MultiDrawElementsEXT)) parameters
+#define GET_MultiDrawElementsEXT(disp) ((disp)->MultiDrawElementsEXT)
+#define SET_MultiDrawElementsEXT(disp, fn) ((disp)->MultiDrawElementsEXT = fn)
+#define CALL_FogCoordPointerEXT(disp, parameters) (*((disp)->FogCoordPointerEXT)) parameters
+#define GET_FogCoordPointerEXT(disp) ((disp)->FogCoordPointerEXT)
+#define SET_FogCoordPointerEXT(disp, fn) ((disp)->FogCoordPointerEXT = fn)
+#define CALL_FogCoorddEXT(disp, parameters) (*((disp)->FogCoorddEXT)) parameters
+#define GET_FogCoorddEXT(disp) ((disp)->FogCoorddEXT)
+#define SET_FogCoorddEXT(disp, fn) ((disp)->FogCoorddEXT = fn)
+#define CALL_FogCoorddvEXT(disp, parameters) (*((disp)->FogCoorddvEXT)) parameters
+#define GET_FogCoorddvEXT(disp) ((disp)->FogCoorddvEXT)
+#define SET_FogCoorddvEXT(disp, fn) ((disp)->FogCoorddvEXT = fn)
+#define CALL_FogCoordfEXT(disp, parameters) (*((disp)->FogCoordfEXT)) parameters
+#define GET_FogCoordfEXT(disp) ((disp)->FogCoordfEXT)
+#define SET_FogCoordfEXT(disp, fn) ((disp)->FogCoordfEXT = fn)
+#define CALL_FogCoordfvEXT(disp, parameters) (*((disp)->FogCoordfvEXT)) parameters
+#define GET_FogCoordfvEXT(disp) ((disp)->FogCoordfvEXT)
+#define SET_FogCoordfvEXT(disp, fn) ((disp)->FogCoordfvEXT = fn)
+#define CALL_PixelTexGenSGIX(disp, parameters) (*((disp)->PixelTexGenSGIX)) parameters
+#define GET_PixelTexGenSGIX(disp) ((disp)->PixelTexGenSGIX)
+#define SET_PixelTexGenSGIX(disp, fn) ((disp)->PixelTexGenSGIX = fn)
+#define CALL_BlendFuncSeparateEXT(disp, parameters) (*((disp)->BlendFuncSeparateEXT)) parameters
+#define GET_BlendFuncSeparateEXT(disp) ((disp)->BlendFuncSeparateEXT)
+#define SET_BlendFuncSeparateEXT(disp, fn) ((disp)->BlendFuncSeparateEXT = fn)
+#define CALL_FlushVertexArrayRangeNV(disp, parameters) (*((disp)->FlushVertexArrayRangeNV)) parameters
+#define GET_FlushVertexArrayRangeNV(disp) ((disp)->FlushVertexArrayRangeNV)
+#define SET_FlushVertexArrayRangeNV(disp, fn) ((disp)->FlushVertexArrayRangeNV = fn)
+#define CALL_VertexArrayRangeNV(disp, parameters) (*((disp)->VertexArrayRangeNV)) parameters
+#define GET_VertexArrayRangeNV(disp) ((disp)->VertexArrayRangeNV)
+#define SET_VertexArrayRangeNV(disp, fn) ((disp)->VertexArrayRangeNV = fn)
+#define CALL_CombinerInputNV(disp, parameters) (*((disp)->CombinerInputNV)) parameters
+#define GET_CombinerInputNV(disp) ((disp)->CombinerInputNV)
+#define SET_CombinerInputNV(disp, fn) ((disp)->CombinerInputNV = fn)
+#define CALL_CombinerOutputNV(disp, parameters) (*((disp)->CombinerOutputNV)) parameters
+#define GET_CombinerOutputNV(disp) ((disp)->CombinerOutputNV)
+#define SET_CombinerOutputNV(disp, fn) ((disp)->CombinerOutputNV = fn)
+#define CALL_CombinerParameterfNV(disp, parameters) (*((disp)->CombinerParameterfNV)) parameters
+#define GET_CombinerParameterfNV(disp) ((disp)->CombinerParameterfNV)
+#define SET_CombinerParameterfNV(disp, fn) ((disp)->CombinerParameterfNV = fn)
+#define CALL_CombinerParameterfvNV(disp, parameters) (*((disp)->CombinerParameterfvNV)) parameters
+#define GET_CombinerParameterfvNV(disp) ((disp)->CombinerParameterfvNV)
+#define SET_CombinerParameterfvNV(disp, fn) ((disp)->CombinerParameterfvNV = fn)
+#define CALL_CombinerParameteriNV(disp, parameters) (*((disp)->CombinerParameteriNV)) parameters
+#define GET_CombinerParameteriNV(disp) ((disp)->CombinerParameteriNV)
+#define SET_CombinerParameteriNV(disp, fn) ((disp)->CombinerParameteriNV = fn)
+#define CALL_CombinerParameterivNV(disp, parameters) (*((disp)->CombinerParameterivNV)) parameters
+#define GET_CombinerParameterivNV(disp) ((disp)->CombinerParameterivNV)
+#define SET_CombinerParameterivNV(disp, fn) ((disp)->CombinerParameterivNV = fn)
+#define CALL_FinalCombinerInputNV(disp, parameters) (*((disp)->FinalCombinerInputNV)) parameters
+#define GET_FinalCombinerInputNV(disp) ((disp)->FinalCombinerInputNV)
+#define SET_FinalCombinerInputNV(disp, fn) ((disp)->FinalCombinerInputNV = fn)
+#define CALL_GetCombinerInputParameterfvNV(disp, parameters) (*((disp)->GetCombinerInputParameterfvNV)) parameters
+#define GET_GetCombinerInputParameterfvNV(disp) ((disp)->GetCombinerInputParameterfvNV)
+#define SET_GetCombinerInputParameterfvNV(disp, fn) ((disp)->GetCombinerInputParameterfvNV = fn)
+#define CALL_GetCombinerInputParameterivNV(disp, parameters) (*((disp)->GetCombinerInputParameterivNV)) parameters
+#define GET_GetCombinerInputParameterivNV(disp) ((disp)->GetCombinerInputParameterivNV)
+#define SET_GetCombinerInputParameterivNV(disp, fn) ((disp)->GetCombinerInputParameterivNV = fn)
+#define CALL_GetCombinerOutputParameterfvNV(disp, parameters) (*((disp)->GetCombinerOutputParameterfvNV)) parameters
+#define GET_GetCombinerOutputParameterfvNV(disp) ((disp)->GetCombinerOutputParameterfvNV)
+#define SET_GetCombinerOutputParameterfvNV(disp, fn) ((disp)->GetCombinerOutputParameterfvNV = fn)
+#define CALL_GetCombinerOutputParameterivNV(disp, parameters) (*((disp)->GetCombinerOutputParameterivNV)) parameters
+#define GET_GetCombinerOutputParameterivNV(disp) ((disp)->GetCombinerOutputParameterivNV)
+#define SET_GetCombinerOutputParameterivNV(disp, fn) ((disp)->GetCombinerOutputParameterivNV = fn)
+#define CALL_GetFinalCombinerInputParameterfvNV(disp, parameters) (*((disp)->GetFinalCombinerInputParameterfvNV)) parameters
+#define GET_GetFinalCombinerInputParameterfvNV(disp) ((disp)->GetFinalCombinerInputParameterfvNV)
+#define SET_GetFinalCombinerInputParameterfvNV(disp, fn) ((disp)->GetFinalCombinerInputParameterfvNV = fn)
+#define CALL_GetFinalCombinerInputParameterivNV(disp, parameters) (*((disp)->GetFinalCombinerInputParameterivNV)) parameters
+#define GET_GetFinalCombinerInputParameterivNV(disp) ((disp)->GetFinalCombinerInputParameterivNV)
+#define SET_GetFinalCombinerInputParameterivNV(disp, fn) ((disp)->GetFinalCombinerInputParameterivNV = fn)
+#define CALL_ResizeBuffersMESA(disp, parameters) (*((disp)->ResizeBuffersMESA)) parameters
+#define GET_ResizeBuffersMESA(disp) ((disp)->ResizeBuffersMESA)
+#define SET_ResizeBuffersMESA(disp, fn) ((disp)->ResizeBuffersMESA = fn)
+#define CALL_WindowPos2dMESA(disp, parameters) (*((disp)->WindowPos2dMESA)) parameters
+#define GET_WindowPos2dMESA(disp) ((disp)->WindowPos2dMESA)
+#define SET_WindowPos2dMESA(disp, fn) ((disp)->WindowPos2dMESA = fn)
+#define CALL_WindowPos2dvMESA(disp, parameters) (*((disp)->WindowPos2dvMESA)) parameters
+#define GET_WindowPos2dvMESA(disp) ((disp)->WindowPos2dvMESA)
+#define SET_WindowPos2dvMESA(disp, fn) ((disp)->WindowPos2dvMESA = fn)
+#define CALL_WindowPos2fMESA(disp, parameters) (*((disp)->WindowPos2fMESA)) parameters
+#define GET_WindowPos2fMESA(disp) ((disp)->WindowPos2fMESA)
+#define SET_WindowPos2fMESA(disp, fn) ((disp)->WindowPos2fMESA = fn)
+#define CALL_WindowPos2fvMESA(disp, parameters) (*((disp)->WindowPos2fvMESA)) parameters
+#define GET_WindowPos2fvMESA(disp) ((disp)->WindowPos2fvMESA)
+#define SET_WindowPos2fvMESA(disp, fn) ((disp)->WindowPos2fvMESA = fn)
+#define CALL_WindowPos2iMESA(disp, parameters) (*((disp)->WindowPos2iMESA)) parameters
+#define GET_WindowPos2iMESA(disp) ((disp)->WindowPos2iMESA)
+#define SET_WindowPos2iMESA(disp, fn) ((disp)->WindowPos2iMESA = fn)
+#define CALL_WindowPos2ivMESA(disp, parameters) (*((disp)->WindowPos2ivMESA)) parameters
+#define GET_WindowPos2ivMESA(disp) ((disp)->WindowPos2ivMESA)
+#define SET_WindowPos2ivMESA(disp, fn) ((disp)->WindowPos2ivMESA = fn)
+#define CALL_WindowPos2sMESA(disp, parameters) (*((disp)->WindowPos2sMESA)) parameters
+#define GET_WindowPos2sMESA(disp) ((disp)->WindowPos2sMESA)
+#define SET_WindowPos2sMESA(disp, fn) ((disp)->WindowPos2sMESA = fn)
+#define CALL_WindowPos2svMESA(disp, parameters) (*((disp)->WindowPos2svMESA)) parameters
+#define GET_WindowPos2svMESA(disp) ((disp)->WindowPos2svMESA)
+#define SET_WindowPos2svMESA(disp, fn) ((disp)->WindowPos2svMESA = fn)
+#define CALL_WindowPos3dMESA(disp, parameters) (*((disp)->WindowPos3dMESA)) parameters
+#define GET_WindowPos3dMESA(disp) ((disp)->WindowPos3dMESA)
+#define SET_WindowPos3dMESA(disp, fn) ((disp)->WindowPos3dMESA = fn)
+#define CALL_WindowPos3dvMESA(disp, parameters) (*((disp)->WindowPos3dvMESA)) parameters
+#define GET_WindowPos3dvMESA(disp) ((disp)->WindowPos3dvMESA)
+#define SET_WindowPos3dvMESA(disp, fn) ((disp)->WindowPos3dvMESA = fn)
+#define CALL_WindowPos3fMESA(disp, parameters) (*((disp)->WindowPos3fMESA)) parameters
+#define GET_WindowPos3fMESA(disp) ((disp)->WindowPos3fMESA)
+#define SET_WindowPos3fMESA(disp, fn) ((disp)->WindowPos3fMESA = fn)
+#define CALL_WindowPos3fvMESA(disp, parameters) (*((disp)->WindowPos3fvMESA)) parameters
+#define GET_WindowPos3fvMESA(disp) ((disp)->WindowPos3fvMESA)
+#define SET_WindowPos3fvMESA(disp, fn) ((disp)->WindowPos3fvMESA = fn)
+#define CALL_WindowPos3iMESA(disp, parameters) (*((disp)->WindowPos3iMESA)) parameters
+#define GET_WindowPos3iMESA(disp) ((disp)->WindowPos3iMESA)
+#define SET_WindowPos3iMESA(disp, fn) ((disp)->WindowPos3iMESA = fn)
+#define CALL_WindowPos3ivMESA(disp, parameters) (*((disp)->WindowPos3ivMESA)) parameters
+#define GET_WindowPos3ivMESA(disp) ((disp)->WindowPos3ivMESA)
+#define SET_WindowPos3ivMESA(disp, fn) ((disp)->WindowPos3ivMESA = fn)
+#define CALL_WindowPos3sMESA(disp, parameters) (*((disp)->WindowPos3sMESA)) parameters
+#define GET_WindowPos3sMESA(disp) ((disp)->WindowPos3sMESA)
+#define SET_WindowPos3sMESA(disp, fn) ((disp)->WindowPos3sMESA = fn)
+#define CALL_WindowPos3svMESA(disp, parameters) (*((disp)->WindowPos3svMESA)) parameters
+#define GET_WindowPos3svMESA(disp) ((disp)->WindowPos3svMESA)
+#define SET_WindowPos3svMESA(disp, fn) ((disp)->WindowPos3svMESA = fn)
+#define CALL_WindowPos4dMESA(disp, parameters) (*((disp)->WindowPos4dMESA)) parameters
+#define GET_WindowPos4dMESA(disp) ((disp)->WindowPos4dMESA)
+#define SET_WindowPos4dMESA(disp, fn) ((disp)->WindowPos4dMESA = fn)
+#define CALL_WindowPos4dvMESA(disp, parameters) (*((disp)->WindowPos4dvMESA)) parameters
+#define GET_WindowPos4dvMESA(disp) ((disp)->WindowPos4dvMESA)
+#define SET_WindowPos4dvMESA(disp, fn) ((disp)->WindowPos4dvMESA = fn)
+#define CALL_WindowPos4fMESA(disp, parameters) (*((disp)->WindowPos4fMESA)) parameters
+#define GET_WindowPos4fMESA(disp) ((disp)->WindowPos4fMESA)
+#define SET_WindowPos4fMESA(disp, fn) ((disp)->WindowPos4fMESA = fn)
+#define CALL_WindowPos4fvMESA(disp, parameters) (*((disp)->WindowPos4fvMESA)) parameters
+#define GET_WindowPos4fvMESA(disp) ((disp)->WindowPos4fvMESA)
+#define SET_WindowPos4fvMESA(disp, fn) ((disp)->WindowPos4fvMESA = fn)
+#define CALL_WindowPos4iMESA(disp, parameters) (*((disp)->WindowPos4iMESA)) parameters
+#define GET_WindowPos4iMESA(disp) ((disp)->WindowPos4iMESA)
+#define SET_WindowPos4iMESA(disp, fn) ((disp)->WindowPos4iMESA = fn)
+#define CALL_WindowPos4ivMESA(disp, parameters) (*((disp)->WindowPos4ivMESA)) parameters
+#define GET_WindowPos4ivMESA(disp) ((disp)->WindowPos4ivMESA)
+#define SET_WindowPos4ivMESA(disp, fn) ((disp)->WindowPos4ivMESA = fn)
+#define CALL_WindowPos4sMESA(disp, parameters) (*((disp)->WindowPos4sMESA)) parameters
+#define GET_WindowPos4sMESA(disp) ((disp)->WindowPos4sMESA)
+#define SET_WindowPos4sMESA(disp, fn) ((disp)->WindowPos4sMESA = fn)
+#define CALL_WindowPos4svMESA(disp, parameters) (*((disp)->WindowPos4svMESA)) parameters
+#define GET_WindowPos4svMESA(disp) ((disp)->WindowPos4svMESA)
+#define SET_WindowPos4svMESA(disp, fn) ((disp)->WindowPos4svMESA = fn)
+#define CALL_MultiModeDrawArraysIBM(disp, parameters) (*((disp)->MultiModeDrawArraysIBM)) parameters
+#define GET_MultiModeDrawArraysIBM(disp) ((disp)->MultiModeDrawArraysIBM)
+#define SET_MultiModeDrawArraysIBM(disp, fn) ((disp)->MultiModeDrawArraysIBM = fn)
+#define CALL_MultiModeDrawElementsIBM(disp, parameters) (*((disp)->MultiModeDrawElementsIBM)) parameters
+#define GET_MultiModeDrawElementsIBM(disp) ((disp)->MultiModeDrawElementsIBM)
+#define SET_MultiModeDrawElementsIBM(disp, fn) ((disp)->MultiModeDrawElementsIBM = fn)
+#define CALL_DeleteFencesNV(disp, parameters) (*((disp)->DeleteFencesNV)) parameters
+#define GET_DeleteFencesNV(disp) ((disp)->DeleteFencesNV)
+#define SET_DeleteFencesNV(disp, fn) ((disp)->DeleteFencesNV = fn)
+#define CALL_FinishFenceNV(disp, parameters) (*((disp)->FinishFenceNV)) parameters
+#define GET_FinishFenceNV(disp) ((disp)->FinishFenceNV)
+#define SET_FinishFenceNV(disp, fn) ((disp)->FinishFenceNV = fn)
+#define CALL_GenFencesNV(disp, parameters) (*((disp)->GenFencesNV)) parameters
+#define GET_GenFencesNV(disp) ((disp)->GenFencesNV)
+#define SET_GenFencesNV(disp, fn) ((disp)->GenFencesNV = fn)
+#define CALL_GetFenceivNV(disp, parameters) (*((disp)->GetFenceivNV)) parameters
+#define GET_GetFenceivNV(disp) ((disp)->GetFenceivNV)
+#define SET_GetFenceivNV(disp, fn) ((disp)->GetFenceivNV = fn)
+#define CALL_IsFenceNV(disp, parameters) (*((disp)->IsFenceNV)) parameters
+#define GET_IsFenceNV(disp) ((disp)->IsFenceNV)
+#define SET_IsFenceNV(disp, fn) ((disp)->IsFenceNV = fn)
+#define CALL_SetFenceNV(disp, parameters) (*((disp)->SetFenceNV)) parameters
+#define GET_SetFenceNV(disp) ((disp)->SetFenceNV)
+#define SET_SetFenceNV(disp, fn) ((disp)->SetFenceNV = fn)
+#define CALL_TestFenceNV(disp, parameters) (*((disp)->TestFenceNV)) parameters
+#define GET_TestFenceNV(disp) ((disp)->TestFenceNV)
+#define SET_TestFenceNV(disp, fn) ((disp)->TestFenceNV = fn)
+#define CALL_AreProgramsResidentNV(disp, parameters) (*((disp)->AreProgramsResidentNV)) parameters
+#define GET_AreProgramsResidentNV(disp) ((disp)->AreProgramsResidentNV)
+#define SET_AreProgramsResidentNV(disp, fn) ((disp)->AreProgramsResidentNV = fn)
+#define CALL_BindProgramNV(disp, parameters) (*((disp)->BindProgramNV)) parameters
+#define GET_BindProgramNV(disp) ((disp)->BindProgramNV)
+#define SET_BindProgramNV(disp, fn) ((disp)->BindProgramNV = fn)
+#define CALL_DeleteProgramsNV(disp, parameters) (*((disp)->DeleteProgramsNV)) parameters
+#define GET_DeleteProgramsNV(disp) ((disp)->DeleteProgramsNV)
+#define SET_DeleteProgramsNV(disp, fn) ((disp)->DeleteProgramsNV = fn)
+#define CALL_ExecuteProgramNV(disp, parameters) (*((disp)->ExecuteProgramNV)) parameters
+#define GET_ExecuteProgramNV(disp) ((disp)->ExecuteProgramNV)
+#define SET_ExecuteProgramNV(disp, fn) ((disp)->ExecuteProgramNV = fn)
+#define CALL_GenProgramsNV(disp, parameters) (*((disp)->GenProgramsNV)) parameters
+#define GET_GenProgramsNV(disp) ((disp)->GenProgramsNV)
+#define SET_GenProgramsNV(disp, fn) ((disp)->GenProgramsNV = fn)
+#define CALL_GetProgramParameterdvNV(disp, parameters) (*((disp)->GetProgramParameterdvNV)) parameters
+#define GET_GetProgramParameterdvNV(disp) ((disp)->GetProgramParameterdvNV)
+#define SET_GetProgramParameterdvNV(disp, fn) ((disp)->GetProgramParameterdvNV = fn)
+#define CALL_GetProgramParameterfvNV(disp, parameters) (*((disp)->GetProgramParameterfvNV)) parameters
+#define GET_GetProgramParameterfvNV(disp) ((disp)->GetProgramParameterfvNV)
+#define SET_GetProgramParameterfvNV(disp, fn) ((disp)->GetProgramParameterfvNV = fn)
+#define CALL_GetProgramStringNV(disp, parameters) (*((disp)->GetProgramStringNV)) parameters
+#define GET_GetProgramStringNV(disp) ((disp)->GetProgramStringNV)
+#define SET_GetProgramStringNV(disp, fn) ((disp)->GetProgramStringNV = fn)
+#define CALL_GetProgramivNV(disp, parameters) (*((disp)->GetProgramivNV)) parameters
+#define GET_GetProgramivNV(disp) ((disp)->GetProgramivNV)
+#define SET_GetProgramivNV(disp, fn) ((disp)->GetProgramivNV = fn)
+#define CALL_GetTrackMatrixivNV(disp, parameters) (*((disp)->GetTrackMatrixivNV)) parameters
+#define GET_GetTrackMatrixivNV(disp) ((disp)->GetTrackMatrixivNV)
+#define SET_GetTrackMatrixivNV(disp, fn) ((disp)->GetTrackMatrixivNV = fn)
+#define CALL_GetVertexAttribPointervNV(disp, parameters) (*((disp)->GetVertexAttribPointervNV)) parameters
+#define GET_GetVertexAttribPointervNV(disp) ((disp)->GetVertexAttribPointervNV)
+#define SET_GetVertexAttribPointervNV(disp, fn) ((disp)->GetVertexAttribPointervNV = fn)
+#define CALL_GetVertexAttribdvNV(disp, parameters) (*((disp)->GetVertexAttribdvNV)) parameters
+#define GET_GetVertexAttribdvNV(disp) ((disp)->GetVertexAttribdvNV)
+#define SET_GetVertexAttribdvNV(disp, fn) ((disp)->GetVertexAttribdvNV = fn)
+#define CALL_GetVertexAttribfvNV(disp, parameters) (*((disp)->GetVertexAttribfvNV)) parameters
+#define GET_GetVertexAttribfvNV(disp) ((disp)->GetVertexAttribfvNV)
+#define SET_GetVertexAttribfvNV(disp, fn) ((disp)->GetVertexAttribfvNV = fn)
+#define CALL_GetVertexAttribivNV(disp, parameters) (*((disp)->GetVertexAttribivNV)) parameters
+#define GET_GetVertexAttribivNV(disp) ((disp)->GetVertexAttribivNV)
+#define SET_GetVertexAttribivNV(disp, fn) ((disp)->GetVertexAttribivNV = fn)
+#define CALL_IsProgramNV(disp, parameters) (*((disp)->IsProgramNV)) parameters
+#define GET_IsProgramNV(disp) ((disp)->IsProgramNV)
+#define SET_IsProgramNV(disp, fn) ((disp)->IsProgramNV = fn)
+#define CALL_LoadProgramNV(disp, parameters) (*((disp)->LoadProgramNV)) parameters
+#define GET_LoadProgramNV(disp) ((disp)->LoadProgramNV)
+#define SET_LoadProgramNV(disp, fn) ((disp)->LoadProgramNV = fn)
+#define CALL_ProgramParameters4dvNV(disp, parameters) (*((disp)->ProgramParameters4dvNV)) parameters
+#define GET_ProgramParameters4dvNV(disp) ((disp)->ProgramParameters4dvNV)
+#define SET_ProgramParameters4dvNV(disp, fn) ((disp)->ProgramParameters4dvNV = fn)
+#define CALL_ProgramParameters4fvNV(disp, parameters) (*((disp)->ProgramParameters4fvNV)) parameters
+#define GET_ProgramParameters4fvNV(disp) ((disp)->ProgramParameters4fvNV)
+#define SET_ProgramParameters4fvNV(disp, fn) ((disp)->ProgramParameters4fvNV = fn)
+#define CALL_RequestResidentProgramsNV(disp, parameters) (*((disp)->RequestResidentProgramsNV)) parameters
+#define GET_RequestResidentProgramsNV(disp) ((disp)->RequestResidentProgramsNV)
+#define SET_RequestResidentProgramsNV(disp, fn) ((disp)->RequestResidentProgramsNV = fn)
+#define CALL_TrackMatrixNV(disp, parameters) (*((disp)->TrackMatrixNV)) parameters
+#define GET_TrackMatrixNV(disp) ((disp)->TrackMatrixNV)
+#define SET_TrackMatrixNV(disp, fn) ((disp)->TrackMatrixNV = fn)
+#define CALL_VertexAttrib1dNV(disp, parameters) (*((disp)->VertexAttrib1dNV)) parameters
+#define GET_VertexAttrib1dNV(disp) ((disp)->VertexAttrib1dNV)
+#define SET_VertexAttrib1dNV(disp, fn) ((disp)->VertexAttrib1dNV = fn)
+#define CALL_VertexAttrib1dvNV(disp, parameters) (*((disp)->VertexAttrib1dvNV)) parameters
+#define GET_VertexAttrib1dvNV(disp) ((disp)->VertexAttrib1dvNV)
+#define SET_VertexAttrib1dvNV(disp, fn) ((disp)->VertexAttrib1dvNV = fn)
+#define CALL_VertexAttrib1fNV(disp, parameters) (*((disp)->VertexAttrib1fNV)) parameters
+#define GET_VertexAttrib1fNV(disp) ((disp)->VertexAttrib1fNV)
+#define SET_VertexAttrib1fNV(disp, fn) ((disp)->VertexAttrib1fNV = fn)
+#define CALL_VertexAttrib1fvNV(disp, parameters) (*((disp)->VertexAttrib1fvNV)) parameters
+#define GET_VertexAttrib1fvNV(disp) ((disp)->VertexAttrib1fvNV)
+#define SET_VertexAttrib1fvNV(disp, fn) ((disp)->VertexAttrib1fvNV = fn)
+#define CALL_VertexAttrib1sNV(disp, parameters) (*((disp)->VertexAttrib1sNV)) parameters
+#define GET_VertexAttrib1sNV(disp) ((disp)->VertexAttrib1sNV)
+#define SET_VertexAttrib1sNV(disp, fn) ((disp)->VertexAttrib1sNV = fn)
+#define CALL_VertexAttrib1svNV(disp, parameters) (*((disp)->VertexAttrib1svNV)) parameters
+#define GET_VertexAttrib1svNV(disp) ((disp)->VertexAttrib1svNV)
+#define SET_VertexAttrib1svNV(disp, fn) ((disp)->VertexAttrib1svNV = fn)
+#define CALL_VertexAttrib2dNV(disp, parameters) (*((disp)->VertexAttrib2dNV)) parameters
+#define GET_VertexAttrib2dNV(disp) ((disp)->VertexAttrib2dNV)
+#define SET_VertexAttrib2dNV(disp, fn) ((disp)->VertexAttrib2dNV = fn)
+#define CALL_VertexAttrib2dvNV(disp, parameters) (*((disp)->VertexAttrib2dvNV)) parameters
+#define GET_VertexAttrib2dvNV(disp) ((disp)->VertexAttrib2dvNV)
+#define SET_VertexAttrib2dvNV(disp, fn) ((disp)->VertexAttrib2dvNV = fn)
+#define CALL_VertexAttrib2fNV(disp, parameters) (*((disp)->VertexAttrib2fNV)) parameters
+#define GET_VertexAttrib2fNV(disp) ((disp)->VertexAttrib2fNV)
+#define SET_VertexAttrib2fNV(disp, fn) ((disp)->VertexAttrib2fNV = fn)
+#define CALL_VertexAttrib2fvNV(disp, parameters) (*((disp)->VertexAttrib2fvNV)) parameters
+#define GET_VertexAttrib2fvNV(disp) ((disp)->VertexAttrib2fvNV)
+#define SET_VertexAttrib2fvNV(disp, fn) ((disp)->VertexAttrib2fvNV = fn)
+#define CALL_VertexAttrib2sNV(disp, parameters) (*((disp)->VertexAttrib2sNV)) parameters
+#define GET_VertexAttrib2sNV(disp) ((disp)->VertexAttrib2sNV)
+#define SET_VertexAttrib2sNV(disp, fn) ((disp)->VertexAttrib2sNV = fn)
+#define CALL_VertexAttrib2svNV(disp, parameters) (*((disp)->VertexAttrib2svNV)) parameters
+#define GET_VertexAttrib2svNV(disp) ((disp)->VertexAttrib2svNV)
+#define SET_VertexAttrib2svNV(disp, fn) ((disp)->VertexAttrib2svNV = fn)
+#define CALL_VertexAttrib3dNV(disp, parameters) (*((disp)->VertexAttrib3dNV)) parameters
+#define GET_VertexAttrib3dNV(disp) ((disp)->VertexAttrib3dNV)
+#define SET_VertexAttrib3dNV(disp, fn) ((disp)->VertexAttrib3dNV = fn)
+#define CALL_VertexAttrib3dvNV(disp, parameters) (*((disp)->VertexAttrib3dvNV)) parameters
+#define GET_VertexAttrib3dvNV(disp) ((disp)->VertexAttrib3dvNV)
+#define SET_VertexAttrib3dvNV(disp, fn) ((disp)->VertexAttrib3dvNV = fn)
+#define CALL_VertexAttrib3fNV(disp, parameters) (*((disp)->VertexAttrib3fNV)) parameters
+#define GET_VertexAttrib3fNV(disp) ((disp)->VertexAttrib3fNV)
+#define SET_VertexAttrib3fNV(disp, fn) ((disp)->VertexAttrib3fNV = fn)
+#define CALL_VertexAttrib3fvNV(disp, parameters) (*((disp)->VertexAttrib3fvNV)) parameters
+#define GET_VertexAttrib3fvNV(disp) ((disp)->VertexAttrib3fvNV)
+#define SET_VertexAttrib3fvNV(disp, fn) ((disp)->VertexAttrib3fvNV = fn)
+#define CALL_VertexAttrib3sNV(disp, parameters) (*((disp)->VertexAttrib3sNV)) parameters
+#define GET_VertexAttrib3sNV(disp) ((disp)->VertexAttrib3sNV)
+#define SET_VertexAttrib3sNV(disp, fn) ((disp)->VertexAttrib3sNV = fn)
+#define CALL_VertexAttrib3svNV(disp, parameters) (*((disp)->VertexAttrib3svNV)) parameters
+#define GET_VertexAttrib3svNV(disp) ((disp)->VertexAttrib3svNV)
+#define SET_VertexAttrib3svNV(disp, fn) ((disp)->VertexAttrib3svNV = fn)
+#define CALL_VertexAttrib4dNV(disp, parameters) (*((disp)->VertexAttrib4dNV)) parameters
+#define GET_VertexAttrib4dNV(disp) ((disp)->VertexAttrib4dNV)
+#define SET_VertexAttrib4dNV(disp, fn) ((disp)->VertexAttrib4dNV = fn)
+#define CALL_VertexAttrib4dvNV(disp, parameters) (*((disp)->VertexAttrib4dvNV)) parameters
+#define GET_VertexAttrib4dvNV(disp) ((disp)->VertexAttrib4dvNV)
+#define SET_VertexAttrib4dvNV(disp, fn) ((disp)->VertexAttrib4dvNV = fn)
+#define CALL_VertexAttrib4fNV(disp, parameters) (*((disp)->VertexAttrib4fNV)) parameters
+#define GET_VertexAttrib4fNV(disp) ((disp)->VertexAttrib4fNV)
+#define SET_VertexAttrib4fNV(disp, fn) ((disp)->VertexAttrib4fNV = fn)
+#define CALL_VertexAttrib4fvNV(disp, parameters) (*((disp)->VertexAttrib4fvNV)) parameters
+#define GET_VertexAttrib4fvNV(disp) ((disp)->VertexAttrib4fvNV)
+#define SET_VertexAttrib4fvNV(disp, fn) ((disp)->VertexAttrib4fvNV = fn)
+#define CALL_VertexAttrib4sNV(disp, parameters) (*((disp)->VertexAttrib4sNV)) parameters
+#define GET_VertexAttrib4sNV(disp) ((disp)->VertexAttrib4sNV)
+#define SET_VertexAttrib4sNV(disp, fn) ((disp)->VertexAttrib4sNV = fn)
+#define CALL_VertexAttrib4svNV(disp, parameters) (*((disp)->VertexAttrib4svNV)) parameters
+#define GET_VertexAttrib4svNV(disp) ((disp)->VertexAttrib4svNV)
+#define SET_VertexAttrib4svNV(disp, fn) ((disp)->VertexAttrib4svNV = fn)
+#define CALL_VertexAttrib4ubNV(disp, parameters) (*((disp)->VertexAttrib4ubNV)) parameters
+#define GET_VertexAttrib4ubNV(disp) ((disp)->VertexAttrib4ubNV)
+#define SET_VertexAttrib4ubNV(disp, fn) ((disp)->VertexAttrib4ubNV = fn)
+#define CALL_VertexAttrib4ubvNV(disp, parameters) (*((disp)->VertexAttrib4ubvNV)) parameters
+#define GET_VertexAttrib4ubvNV(disp) ((disp)->VertexAttrib4ubvNV)
+#define SET_VertexAttrib4ubvNV(disp, fn) ((disp)->VertexAttrib4ubvNV = fn)
+#define CALL_VertexAttribPointerNV(disp, parameters) (*((disp)->VertexAttribPointerNV)) parameters
+#define GET_VertexAttribPointerNV(disp) ((disp)->VertexAttribPointerNV)
+#define SET_VertexAttribPointerNV(disp, fn) ((disp)->VertexAttribPointerNV = fn)
+#define CALL_VertexAttribs1dvNV(disp, parameters) (*((disp)->VertexAttribs1dvNV)) parameters
+#define GET_VertexAttribs1dvNV(disp) ((disp)->VertexAttribs1dvNV)
+#define SET_VertexAttribs1dvNV(disp, fn) ((disp)->VertexAttribs1dvNV = fn)
+#define CALL_VertexAttribs1fvNV(disp, parameters) (*((disp)->VertexAttribs1fvNV)) parameters
+#define GET_VertexAttribs1fvNV(disp) ((disp)->VertexAttribs1fvNV)
+#define SET_VertexAttribs1fvNV(disp, fn) ((disp)->VertexAttribs1fvNV = fn)
+#define CALL_VertexAttribs1svNV(disp, parameters) (*((disp)->VertexAttribs1svNV)) parameters
+#define GET_VertexAttribs1svNV(disp) ((disp)->VertexAttribs1svNV)
+#define SET_VertexAttribs1svNV(disp, fn) ((disp)->VertexAttribs1svNV = fn)
+#define CALL_VertexAttribs2dvNV(disp, parameters) (*((disp)->VertexAttribs2dvNV)) parameters
+#define GET_VertexAttribs2dvNV(disp) ((disp)->VertexAttribs2dvNV)
+#define SET_VertexAttribs2dvNV(disp, fn) ((disp)->VertexAttribs2dvNV = fn)
+#define CALL_VertexAttribs2fvNV(disp, parameters) (*((disp)->VertexAttribs2fvNV)) parameters
+#define GET_VertexAttribs2fvNV(disp) ((disp)->VertexAttribs2fvNV)
+#define SET_VertexAttribs2fvNV(disp, fn) ((disp)->VertexAttribs2fvNV = fn)
+#define CALL_VertexAttribs2svNV(disp, parameters) (*((disp)->VertexAttribs2svNV)) parameters
+#define GET_VertexAttribs2svNV(disp) ((disp)->VertexAttribs2svNV)
+#define SET_VertexAttribs2svNV(disp, fn) ((disp)->VertexAttribs2svNV = fn)
+#define CALL_VertexAttribs3dvNV(disp, parameters) (*((disp)->VertexAttribs3dvNV)) parameters
+#define GET_VertexAttribs3dvNV(disp) ((disp)->VertexAttribs3dvNV)
+#define SET_VertexAttribs3dvNV(disp, fn) ((disp)->VertexAttribs3dvNV = fn)
+#define CALL_VertexAttribs3fvNV(disp, parameters) (*((disp)->VertexAttribs3fvNV)) parameters
+#define GET_VertexAttribs3fvNV(disp) ((disp)->VertexAttribs3fvNV)
+#define SET_VertexAttribs3fvNV(disp, fn) ((disp)->VertexAttribs3fvNV = fn)
+#define CALL_VertexAttribs3svNV(disp, parameters) (*((disp)->VertexAttribs3svNV)) parameters
+#define GET_VertexAttribs3svNV(disp) ((disp)->VertexAttribs3svNV)
+#define SET_VertexAttribs3svNV(disp, fn) ((disp)->VertexAttribs3svNV = fn)
+#define CALL_VertexAttribs4dvNV(disp, parameters) (*((disp)->VertexAttribs4dvNV)) parameters
+#define GET_VertexAttribs4dvNV(disp) ((disp)->VertexAttribs4dvNV)
+#define SET_VertexAttribs4dvNV(disp, fn) ((disp)->VertexAttribs4dvNV = fn)
+#define CALL_VertexAttribs4fvNV(disp, parameters) (*((disp)->VertexAttribs4fvNV)) parameters
+#define GET_VertexAttribs4fvNV(disp) ((disp)->VertexAttribs4fvNV)
+#define SET_VertexAttribs4fvNV(disp, fn) ((disp)->VertexAttribs4fvNV = fn)
+#define CALL_VertexAttribs4svNV(disp, parameters) (*((disp)->VertexAttribs4svNV)) parameters
+#define GET_VertexAttribs4svNV(disp) ((disp)->VertexAttribs4svNV)
+#define SET_VertexAttribs4svNV(disp, fn) ((disp)->VertexAttribs4svNV = fn)
+#define CALL_VertexAttribs4ubvNV(disp, parameters) (*((disp)->VertexAttribs4ubvNV)) parameters
+#define GET_VertexAttribs4ubvNV(disp) ((disp)->VertexAttribs4ubvNV)
+#define SET_VertexAttribs4ubvNV(disp, fn) ((disp)->VertexAttribs4ubvNV = fn)
+#define CALL_GetTexBumpParameterfvATI(disp, parameters) (*((disp)->GetTexBumpParameterfvATI)) parameters
+#define GET_GetTexBumpParameterfvATI(disp) ((disp)->GetTexBumpParameterfvATI)
+#define SET_GetTexBumpParameterfvATI(disp, fn) ((disp)->GetTexBumpParameterfvATI = fn)
+#define CALL_GetTexBumpParameterivATI(disp, parameters) (*((disp)->GetTexBumpParameterivATI)) parameters
+#define GET_GetTexBumpParameterivATI(disp) ((disp)->GetTexBumpParameterivATI)
+#define SET_GetTexBumpParameterivATI(disp, fn) ((disp)->GetTexBumpParameterivATI = fn)
+#define CALL_TexBumpParameterfvATI(disp, parameters) (*((disp)->TexBumpParameterfvATI)) parameters
+#define GET_TexBumpParameterfvATI(disp) ((disp)->TexBumpParameterfvATI)
+#define SET_TexBumpParameterfvATI(disp, fn) ((disp)->TexBumpParameterfvATI = fn)
+#define CALL_TexBumpParameterivATI(disp, parameters) (*((disp)->TexBumpParameterivATI)) parameters
+#define GET_TexBumpParameterivATI(disp) ((disp)->TexBumpParameterivATI)
+#define SET_TexBumpParameterivATI(disp, fn) ((disp)->TexBumpParameterivATI = fn)
+#define CALL_AlphaFragmentOp1ATI(disp, parameters) (*((disp)->AlphaFragmentOp1ATI)) parameters
+#define GET_AlphaFragmentOp1ATI(disp) ((disp)->AlphaFragmentOp1ATI)
+#define SET_AlphaFragmentOp1ATI(disp, fn) ((disp)->AlphaFragmentOp1ATI = fn)
+#define CALL_AlphaFragmentOp2ATI(disp, parameters) (*((disp)->AlphaFragmentOp2ATI)) parameters
+#define GET_AlphaFragmentOp2ATI(disp) ((disp)->AlphaFragmentOp2ATI)
+#define SET_AlphaFragmentOp2ATI(disp, fn) ((disp)->AlphaFragmentOp2ATI = fn)
+#define CALL_AlphaFragmentOp3ATI(disp, parameters) (*((disp)->AlphaFragmentOp3ATI)) parameters
+#define GET_AlphaFragmentOp3ATI(disp) ((disp)->AlphaFragmentOp3ATI)
+#define SET_AlphaFragmentOp3ATI(disp, fn) ((disp)->AlphaFragmentOp3ATI = fn)
+#define CALL_BeginFragmentShaderATI(disp, parameters) (*((disp)->BeginFragmentShaderATI)) parameters
+#define GET_BeginFragmentShaderATI(disp) ((disp)->BeginFragmentShaderATI)
+#define SET_BeginFragmentShaderATI(disp, fn) ((disp)->BeginFragmentShaderATI = fn)
+#define CALL_BindFragmentShaderATI(disp, parameters) (*((disp)->BindFragmentShaderATI)) parameters
+#define GET_BindFragmentShaderATI(disp) ((disp)->BindFragmentShaderATI)
+#define SET_BindFragmentShaderATI(disp, fn) ((disp)->BindFragmentShaderATI = fn)
+#define CALL_ColorFragmentOp1ATI(disp, parameters) (*((disp)->ColorFragmentOp1ATI)) parameters
+#define GET_ColorFragmentOp1ATI(disp) ((disp)->ColorFragmentOp1ATI)
+#define SET_ColorFragmentOp1ATI(disp, fn) ((disp)->ColorFragmentOp1ATI = fn)
+#define CALL_ColorFragmentOp2ATI(disp, parameters) (*((disp)->ColorFragmentOp2ATI)) parameters
+#define GET_ColorFragmentOp2ATI(disp) ((disp)->ColorFragmentOp2ATI)
+#define SET_ColorFragmentOp2ATI(disp, fn) ((disp)->ColorFragmentOp2ATI = fn)
+#define CALL_ColorFragmentOp3ATI(disp, parameters) (*((disp)->ColorFragmentOp3ATI)) parameters
+#define GET_ColorFragmentOp3ATI(disp) ((disp)->ColorFragmentOp3ATI)
+#define SET_ColorFragmentOp3ATI(disp, fn) ((disp)->ColorFragmentOp3ATI = fn)
+#define CALL_DeleteFragmentShaderATI(disp, parameters) (*((disp)->DeleteFragmentShaderATI)) parameters
+#define GET_DeleteFragmentShaderATI(disp) ((disp)->DeleteFragmentShaderATI)
+#define SET_DeleteFragmentShaderATI(disp, fn) ((disp)->DeleteFragmentShaderATI = fn)
+#define CALL_EndFragmentShaderATI(disp, parameters) (*((disp)->EndFragmentShaderATI)) parameters
+#define GET_EndFragmentShaderATI(disp) ((disp)->EndFragmentShaderATI)
+#define SET_EndFragmentShaderATI(disp, fn) ((disp)->EndFragmentShaderATI = fn)
+#define CALL_GenFragmentShadersATI(disp, parameters) (*((disp)->GenFragmentShadersATI)) parameters
+#define GET_GenFragmentShadersATI(disp) ((disp)->GenFragmentShadersATI)
+#define SET_GenFragmentShadersATI(disp, fn) ((disp)->GenFragmentShadersATI = fn)
+#define CALL_PassTexCoordATI(disp, parameters) (*((disp)->PassTexCoordATI)) parameters
+#define GET_PassTexCoordATI(disp) ((disp)->PassTexCoordATI)
+#define SET_PassTexCoordATI(disp, fn) ((disp)->PassTexCoordATI = fn)
+#define CALL_SampleMapATI(disp, parameters) (*((disp)->SampleMapATI)) parameters
+#define GET_SampleMapATI(disp) ((disp)->SampleMapATI)
+#define SET_SampleMapATI(disp, fn) ((disp)->SampleMapATI = fn)
+#define CALL_SetFragmentShaderConstantATI(disp, parameters) (*((disp)->SetFragmentShaderConstantATI)) parameters
+#define GET_SetFragmentShaderConstantATI(disp) ((disp)->SetFragmentShaderConstantATI)
+#define SET_SetFragmentShaderConstantATI(disp, fn) ((disp)->SetFragmentShaderConstantATI = fn)
+#define CALL_PointParameteriNV(disp, parameters) (*((disp)->PointParameteriNV)) parameters
+#define GET_PointParameteriNV(disp) ((disp)->PointParameteriNV)
+#define SET_PointParameteriNV(disp, fn) ((disp)->PointParameteriNV = fn)
+#define CALL_PointParameterivNV(disp, parameters) (*((disp)->PointParameterivNV)) parameters
+#define GET_PointParameterivNV(disp) ((disp)->PointParameterivNV)
+#define SET_PointParameterivNV(disp, fn) ((disp)->PointParameterivNV = fn)
+#define CALL_ActiveStencilFaceEXT(disp, parameters) (*((disp)->ActiveStencilFaceEXT)) parameters
+#define GET_ActiveStencilFaceEXT(disp) ((disp)->ActiveStencilFaceEXT)
+#define SET_ActiveStencilFaceEXT(disp, fn) ((disp)->ActiveStencilFaceEXT = fn)
+#define CALL_BindVertexArrayAPPLE(disp, parameters) (*((disp)->BindVertexArrayAPPLE)) parameters
+#define GET_BindVertexArrayAPPLE(disp) ((disp)->BindVertexArrayAPPLE)
+#define SET_BindVertexArrayAPPLE(disp, fn) ((disp)->BindVertexArrayAPPLE = fn)
+#define CALL_DeleteVertexArraysAPPLE(disp, parameters) (*((disp)->DeleteVertexArraysAPPLE)) parameters
+#define GET_DeleteVertexArraysAPPLE(disp) ((disp)->DeleteVertexArraysAPPLE)
+#define SET_DeleteVertexArraysAPPLE(disp, fn) ((disp)->DeleteVertexArraysAPPLE = fn)
+#define CALL_GenVertexArraysAPPLE(disp, parameters) (*((disp)->GenVertexArraysAPPLE)) parameters
+#define GET_GenVertexArraysAPPLE(disp) ((disp)->GenVertexArraysAPPLE)
+#define SET_GenVertexArraysAPPLE(disp, fn) ((disp)->GenVertexArraysAPPLE = fn)
+#define CALL_IsVertexArrayAPPLE(disp, parameters) (*((disp)->IsVertexArrayAPPLE)) parameters
+#define GET_IsVertexArrayAPPLE(disp) ((disp)->IsVertexArrayAPPLE)
+#define SET_IsVertexArrayAPPLE(disp, fn) ((disp)->IsVertexArrayAPPLE = fn)
+#define CALL_GetProgramNamedParameterdvNV(disp, parameters) (*((disp)->GetProgramNamedParameterdvNV)) parameters
+#define GET_GetProgramNamedParameterdvNV(disp) ((disp)->GetProgramNamedParameterdvNV)
+#define SET_GetProgramNamedParameterdvNV(disp, fn) ((disp)->GetProgramNamedParameterdvNV = fn)
+#define CALL_GetProgramNamedParameterfvNV(disp, parameters) (*((disp)->GetProgramNamedParameterfvNV)) parameters
+#define GET_GetProgramNamedParameterfvNV(disp) ((disp)->GetProgramNamedParameterfvNV)
+#define SET_GetProgramNamedParameterfvNV(disp, fn) ((disp)->GetProgramNamedParameterfvNV = fn)
+#define CALL_ProgramNamedParameter4dNV(disp, parameters) (*((disp)->ProgramNamedParameter4dNV)) parameters
+#define GET_ProgramNamedParameter4dNV(disp) ((disp)->ProgramNamedParameter4dNV)
+#define SET_ProgramNamedParameter4dNV(disp, fn) ((disp)->ProgramNamedParameter4dNV = fn)
+#define CALL_ProgramNamedParameter4dvNV(disp, parameters) (*((disp)->ProgramNamedParameter4dvNV)) parameters
+#define GET_ProgramNamedParameter4dvNV(disp) ((disp)->ProgramNamedParameter4dvNV)
+#define SET_ProgramNamedParameter4dvNV(disp, fn) ((disp)->ProgramNamedParameter4dvNV = fn)
+#define CALL_ProgramNamedParameter4fNV(disp, parameters) (*((disp)->ProgramNamedParameter4fNV)) parameters
+#define GET_ProgramNamedParameter4fNV(disp) ((disp)->ProgramNamedParameter4fNV)
+#define SET_ProgramNamedParameter4fNV(disp, fn) ((disp)->ProgramNamedParameter4fNV = fn)
+#define CALL_ProgramNamedParameter4fvNV(disp, parameters) (*((disp)->ProgramNamedParameter4fvNV)) parameters
+#define GET_ProgramNamedParameter4fvNV(disp) ((disp)->ProgramNamedParameter4fvNV)
+#define SET_ProgramNamedParameter4fvNV(disp, fn) ((disp)->ProgramNamedParameter4fvNV = fn)
+#define CALL_DepthBoundsEXT(disp, parameters) (*((disp)->DepthBoundsEXT)) parameters
+#define GET_DepthBoundsEXT(disp) ((disp)->DepthBoundsEXT)
+#define SET_DepthBoundsEXT(disp, fn) ((disp)->DepthBoundsEXT = fn)
+#define CALL_BlendEquationSeparateEXT(disp, parameters) (*((disp)->BlendEquationSeparateEXT)) parameters
+#define GET_BlendEquationSeparateEXT(disp) ((disp)->BlendEquationSeparateEXT)
+#define SET_BlendEquationSeparateEXT(disp, fn) ((disp)->BlendEquationSeparateEXT = fn)
+#define CALL_BindFramebufferEXT(disp, parameters) (*((disp)->BindFramebufferEXT)) parameters
+#define GET_BindFramebufferEXT(disp) ((disp)->BindFramebufferEXT)
+#define SET_BindFramebufferEXT(disp, fn) ((disp)->BindFramebufferEXT = fn)
+#define CALL_BindRenderbufferEXT(disp, parameters) (*((disp)->BindRenderbufferEXT)) parameters
+#define GET_BindRenderbufferEXT(disp) ((disp)->BindRenderbufferEXT)
+#define SET_BindRenderbufferEXT(disp, fn) ((disp)->BindRenderbufferEXT = fn)
+#define CALL_CheckFramebufferStatusEXT(disp, parameters) (*((disp)->CheckFramebufferStatusEXT)) parameters
+#define GET_CheckFramebufferStatusEXT(disp) ((disp)->CheckFramebufferStatusEXT)
+#define SET_CheckFramebufferStatusEXT(disp, fn) ((disp)->CheckFramebufferStatusEXT = fn)
+#define CALL_DeleteFramebuffersEXT(disp, parameters) (*((disp)->DeleteFramebuffersEXT)) parameters
+#define GET_DeleteFramebuffersEXT(disp) ((disp)->DeleteFramebuffersEXT)
+#define SET_DeleteFramebuffersEXT(disp, fn) ((disp)->DeleteFramebuffersEXT = fn)
+#define CALL_DeleteRenderbuffersEXT(disp, parameters) (*((disp)->DeleteRenderbuffersEXT)) parameters
+#define GET_DeleteRenderbuffersEXT(disp) ((disp)->DeleteRenderbuffersEXT)
+#define SET_DeleteRenderbuffersEXT(disp, fn) ((disp)->DeleteRenderbuffersEXT = fn)
+#define CALL_FramebufferRenderbufferEXT(disp, parameters) (*((disp)->FramebufferRenderbufferEXT)) parameters
+#define GET_FramebufferRenderbufferEXT(disp) ((disp)->FramebufferRenderbufferEXT)
+#define SET_FramebufferRenderbufferEXT(disp, fn) ((disp)->FramebufferRenderbufferEXT = fn)
+#define CALL_FramebufferTexture1DEXT(disp, parameters) (*((disp)->FramebufferTexture1DEXT)) parameters
+#define GET_FramebufferTexture1DEXT(disp) ((disp)->FramebufferTexture1DEXT)
+#define SET_FramebufferTexture1DEXT(disp, fn) ((disp)->FramebufferTexture1DEXT = fn)
+#define CALL_FramebufferTexture2DEXT(disp, parameters) (*((disp)->FramebufferTexture2DEXT)) parameters
+#define GET_FramebufferTexture2DEXT(disp) ((disp)->FramebufferTexture2DEXT)
+#define SET_FramebufferTexture2DEXT(disp, fn) ((disp)->FramebufferTexture2DEXT = fn)
+#define CALL_FramebufferTexture3DEXT(disp, parameters) (*((disp)->FramebufferTexture3DEXT)) parameters
+#define GET_FramebufferTexture3DEXT(disp) ((disp)->FramebufferTexture3DEXT)
+#define SET_FramebufferTexture3DEXT(disp, fn) ((disp)->FramebufferTexture3DEXT = fn)
+#define CALL_GenFramebuffersEXT(disp, parameters) (*((disp)->GenFramebuffersEXT)) parameters
+#define GET_GenFramebuffersEXT(disp) ((disp)->GenFramebuffersEXT)
+#define SET_GenFramebuffersEXT(disp, fn) ((disp)->GenFramebuffersEXT = fn)
+#define CALL_GenRenderbuffersEXT(disp, parameters) (*((disp)->GenRenderbuffersEXT)) parameters
+#define GET_GenRenderbuffersEXT(disp) ((disp)->GenRenderbuffersEXT)
+#define SET_GenRenderbuffersEXT(disp, fn) ((disp)->GenRenderbuffersEXT = fn)
+#define CALL_GenerateMipmapEXT(disp, parameters) (*((disp)->GenerateMipmapEXT)) parameters
+#define GET_GenerateMipmapEXT(disp) ((disp)->GenerateMipmapEXT)
+#define SET_GenerateMipmapEXT(disp, fn) ((disp)->GenerateMipmapEXT = fn)
+#define CALL_GetFramebufferAttachmentParameterivEXT(disp, parameters) (*((disp)->GetFramebufferAttachmentParameterivEXT)) parameters
+#define GET_GetFramebufferAttachmentParameterivEXT(disp) ((disp)->GetFramebufferAttachmentParameterivEXT)
+#define SET_GetFramebufferAttachmentParameterivEXT(disp, fn) ((disp)->GetFramebufferAttachmentParameterivEXT = fn)
+#define CALL_GetRenderbufferParameterivEXT(disp, parameters) (*((disp)->GetRenderbufferParameterivEXT)) parameters
+#define GET_GetRenderbufferParameterivEXT(disp) ((disp)->GetRenderbufferParameterivEXT)
+#define SET_GetRenderbufferParameterivEXT(disp, fn) ((disp)->GetRenderbufferParameterivEXT = fn)
+#define CALL_IsFramebufferEXT(disp, parameters) (*((disp)->IsFramebufferEXT)) parameters
+#define GET_IsFramebufferEXT(disp) ((disp)->IsFramebufferEXT)
+#define SET_IsFramebufferEXT(disp, fn) ((disp)->IsFramebufferEXT = fn)
+#define CALL_IsRenderbufferEXT(disp, parameters) (*((disp)->IsRenderbufferEXT)) parameters
+#define GET_IsRenderbufferEXT(disp) ((disp)->IsRenderbufferEXT)
+#define SET_IsRenderbufferEXT(disp, fn) ((disp)->IsRenderbufferEXT = fn)
+#define CALL_RenderbufferStorageEXT(disp, parameters) (*((disp)->RenderbufferStorageEXT)) parameters
+#define GET_RenderbufferStorageEXT(disp) ((disp)->RenderbufferStorageEXT)
+#define SET_RenderbufferStorageEXT(disp, fn) ((disp)->RenderbufferStorageEXT = fn)
+#define CALL_BlitFramebufferEXT(disp, parameters) (*((disp)->BlitFramebufferEXT)) parameters
+#define GET_BlitFramebufferEXT(disp) ((disp)->BlitFramebufferEXT)
+#define SET_BlitFramebufferEXT(disp, fn) ((disp)->BlitFramebufferEXT = fn)
+#define CALL_BufferParameteriAPPLE(disp, parameters) (*((disp)->BufferParameteriAPPLE)) parameters
+#define GET_BufferParameteriAPPLE(disp) ((disp)->BufferParameteriAPPLE)
+#define SET_BufferParameteriAPPLE(disp, fn) ((disp)->BufferParameteriAPPLE = fn)
+#define CALL_FlushMappedBufferRangeAPPLE(disp, parameters) (*((disp)->FlushMappedBufferRangeAPPLE)) parameters
+#define GET_FlushMappedBufferRangeAPPLE(disp) ((disp)->FlushMappedBufferRangeAPPLE)
+#define SET_FlushMappedBufferRangeAPPLE(disp, fn) ((disp)->FlushMappedBufferRangeAPPLE = fn)
+#define CALL_FramebufferTextureLayerEXT(disp, parameters) (*((disp)->FramebufferTextureLayerEXT)) parameters
+#define GET_FramebufferTextureLayerEXT(disp) ((disp)->FramebufferTextureLayerEXT)
+#define SET_FramebufferTextureLayerEXT(disp, fn) ((disp)->FramebufferTextureLayerEXT = fn)
+#define CALL_ProvokingVertexEXT(disp, parameters) (*((disp)->ProvokingVertexEXT)) parameters
+#define GET_ProvokingVertexEXT(disp) ((disp)->ProvokingVertexEXT)
+#define SET_ProvokingVertexEXT(disp, fn) ((disp)->ProvokingVertexEXT = fn)
+#define CALL_GetTexParameterPointervAPPLE(disp, parameters) (*((disp)->GetTexParameterPointervAPPLE)) parameters
+#define GET_GetTexParameterPointervAPPLE(disp) ((disp)->GetTexParameterPointervAPPLE)
+#define SET_GetTexParameterPointervAPPLE(disp, fn) ((disp)->GetTexParameterPointervAPPLE = fn)
+#define CALL_TextureRangeAPPLE(disp, parameters) (*((disp)->TextureRangeAPPLE)) parameters
+#define GET_TextureRangeAPPLE(disp) ((disp)->TextureRangeAPPLE)
+#define SET_TextureRangeAPPLE(disp, fn) ((disp)->TextureRangeAPPLE = fn)
+#define CALL_StencilFuncSeparateATI(disp, parameters) (*((disp)->StencilFuncSeparateATI)) parameters
+#define GET_StencilFuncSeparateATI(disp) ((disp)->StencilFuncSeparateATI)
+#define SET_StencilFuncSeparateATI(disp, fn) ((disp)->StencilFuncSeparateATI = fn)
+#define CALL_ProgramEnvParameters4fvEXT(disp, parameters) (*((disp)->ProgramEnvParameters4fvEXT)) parameters
+#define GET_ProgramEnvParameters4fvEXT(disp) ((disp)->ProgramEnvParameters4fvEXT)
+#define SET_ProgramEnvParameters4fvEXT(disp, fn) ((disp)->ProgramEnvParameters4fvEXT = fn)
+#define CALL_ProgramLocalParameters4fvEXT(disp, parameters) (*((disp)->ProgramLocalParameters4fvEXT)) parameters
+#define GET_ProgramLocalParameters4fvEXT(disp) ((disp)->ProgramLocalParameters4fvEXT)
+#define SET_ProgramLocalParameters4fvEXT(disp, fn) ((disp)->ProgramLocalParameters4fvEXT = fn)
+#define CALL_GetQueryObjecti64vEXT(disp, parameters) (*((disp)->GetQueryObjecti64vEXT)) parameters
+#define GET_GetQueryObjecti64vEXT(disp) ((disp)->GetQueryObjecti64vEXT)
+#define SET_GetQueryObjecti64vEXT(disp, fn) ((disp)->GetQueryObjecti64vEXT = fn)
+#define CALL_GetQueryObjectui64vEXT(disp, parameters) (*((disp)->GetQueryObjectui64vEXT)) parameters
+#define GET_GetQueryObjectui64vEXT(disp) ((disp)->GetQueryObjectui64vEXT)
+#define SET_GetQueryObjectui64vEXT(disp, fn) ((disp)->GetQueryObjectui64vEXT = fn)
+
+#else
+
+#define driDispatchRemapTable_size 384
+extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
+
+#define AttachShader_remap_index 0
+#define CreateProgram_remap_index 1
+#define CreateShader_remap_index 2
+#define DeleteProgram_remap_index 3
+#define DeleteShader_remap_index 4
+#define DetachShader_remap_index 5
+#define GetAttachedShaders_remap_index 6
+#define GetProgramInfoLog_remap_index 7
+#define GetProgramiv_remap_index 8
+#define GetShaderInfoLog_remap_index 9
+#define GetShaderiv_remap_index 10
+#define IsProgram_remap_index 11
+#define IsShader_remap_index 12
+#define StencilFuncSeparate_remap_index 13
+#define StencilMaskSeparate_remap_index 14
+#define StencilOpSeparate_remap_index 15
+#define UniformMatrix2x3fv_remap_index 16
+#define UniformMatrix2x4fv_remap_index 17
+#define UniformMatrix3x2fv_remap_index 18
+#define UniformMatrix3x4fv_remap_index 19
+#define UniformMatrix4x2fv_remap_index 20
+#define UniformMatrix4x3fv_remap_index 21
+#define LoadTransposeMatrixdARB_remap_index 22
+#define LoadTransposeMatrixfARB_remap_index 23
+#define MultTransposeMatrixdARB_remap_index 24
+#define MultTransposeMatrixfARB_remap_index 25
+#define SampleCoverageARB_remap_index 26
+#define CompressedTexImage1DARB_remap_index 27
+#define CompressedTexImage2DARB_remap_index 28
+#define CompressedTexImage3DARB_remap_index 29
+#define CompressedTexSubImage1DARB_remap_index 30
+#define CompressedTexSubImage2DARB_remap_index 31
+#define CompressedTexSubImage3DARB_remap_index 32
+#define GetCompressedTexImageARB_remap_index 33
+#define DisableVertexAttribArrayARB_remap_index 34
+#define EnableVertexAttribArrayARB_remap_index 35
+#define GetProgramEnvParameterdvARB_remap_index 36
+#define GetProgramEnvParameterfvARB_remap_index 37
+#define GetProgramLocalParameterdvARB_remap_index 38
+#define GetProgramLocalParameterfvARB_remap_index 39
+#define GetProgramStringARB_remap_index 40
+#define GetProgramivARB_remap_index 41
+#define GetVertexAttribdvARB_remap_index 42
+#define GetVertexAttribfvARB_remap_index 43
+#define GetVertexAttribivARB_remap_index 44
+#define ProgramEnvParameter4dARB_remap_index 45
+#define ProgramEnvParameter4dvARB_remap_index 46
+#define ProgramEnvParameter4fARB_remap_index 47
+#define ProgramEnvParameter4fvARB_remap_index 48
+#define ProgramLocalParameter4dARB_remap_index 49
+#define ProgramLocalParameter4dvARB_remap_index 50
+#define ProgramLocalParameter4fARB_remap_index 51
+#define ProgramLocalParameter4fvARB_remap_index 52
+#define ProgramStringARB_remap_index 53
+#define VertexAttrib1dARB_remap_index 54
+#define VertexAttrib1dvARB_remap_index 55
+#define VertexAttrib1fARB_remap_index 56
+#define VertexAttrib1fvARB_remap_index 57
+#define VertexAttrib1sARB_remap_index 58
+#define VertexAttrib1svARB_remap_index 59
+#define VertexAttrib2dARB_remap_index 60
+#define VertexAttrib2dvARB_remap_index 61
+#define VertexAttrib2fARB_remap_index 62
+#define VertexAttrib2fvARB_remap_index 63
+#define VertexAttrib2sARB_remap_index 64
+#define VertexAttrib2svARB_remap_index 65
+#define VertexAttrib3dARB_remap_index 66
+#define VertexAttrib3dvARB_remap_index 67
+#define VertexAttrib3fARB_remap_index 68
+#define VertexAttrib3fvARB_remap_index 69
+#define VertexAttrib3sARB_remap_index 70
+#define VertexAttrib3svARB_remap_index 71
+#define VertexAttrib4NbvARB_remap_index 72
+#define VertexAttrib4NivARB_remap_index 73
+#define VertexAttrib4NsvARB_remap_index 74
+#define VertexAttrib4NubARB_remap_index 75
+#define VertexAttrib4NubvARB_remap_index 76
+#define VertexAttrib4NuivARB_remap_index 77
+#define VertexAttrib4NusvARB_remap_index 78
+#define VertexAttrib4bvARB_remap_index 79
+#define VertexAttrib4dARB_remap_index 80
+#define VertexAttrib4dvARB_remap_index 81
+#define VertexAttrib4fARB_remap_index 82
+#define VertexAttrib4fvARB_remap_index 83
+#define VertexAttrib4ivARB_remap_index 84
+#define VertexAttrib4sARB_remap_index 85
+#define VertexAttrib4svARB_remap_index 86
+#define VertexAttrib4ubvARB_remap_index 87
+#define VertexAttrib4uivARB_remap_index 88
+#define VertexAttrib4usvARB_remap_index 89
+#define VertexAttribPointerARB_remap_index 90
+#define BindBufferARB_remap_index 91
+#define BufferDataARB_remap_index 92
+#define BufferSubDataARB_remap_index 93
+#define DeleteBuffersARB_remap_index 94
+#define GenBuffersARB_remap_index 95
+#define GetBufferParameterivARB_remap_index 96
+#define GetBufferPointervARB_remap_index 97
+#define GetBufferSubDataARB_remap_index 98
+#define IsBufferARB_remap_index 99
+#define MapBufferARB_remap_index 100
+#define UnmapBufferARB_remap_index 101
+#define BeginQueryARB_remap_index 102
+#define DeleteQueriesARB_remap_index 103
+#define EndQueryARB_remap_index 104
+#define GenQueriesARB_remap_index 105
+#define GetQueryObjectivARB_remap_index 106
+#define GetQueryObjectuivARB_remap_index 107
+#define GetQueryivARB_remap_index 108
+#define IsQueryARB_remap_index 109
+#define AttachObjectARB_remap_index 110
+#define CompileShaderARB_remap_index 111
+#define CreateProgramObjectARB_remap_index 112
+#define CreateShaderObjectARB_remap_index 113
+#define DeleteObjectARB_remap_index 114
+#define DetachObjectARB_remap_index 115
+#define GetActiveUniformARB_remap_index 116
+#define GetAttachedObjectsARB_remap_index 117
+#define GetHandleARB_remap_index 118
+#define GetInfoLogARB_remap_index 119
+#define GetObjectParameterfvARB_remap_index 120
+#define GetObjectParameterivARB_remap_index 121
+#define GetShaderSourceARB_remap_index 122
+#define GetUniformLocationARB_remap_index 123
+#define GetUniformfvARB_remap_index 124
+#define GetUniformivARB_remap_index 125
+#define LinkProgramARB_remap_index 126
+#define ShaderSourceARB_remap_index 127
+#define Uniform1fARB_remap_index 128
+#define Uniform1fvARB_remap_index 129
+#define Uniform1iARB_remap_index 130
+#define Uniform1ivARB_remap_index 131
+#define Uniform2fARB_remap_index 132
+#define Uniform2fvARB_remap_index 133
+#define Uniform2iARB_remap_index 134
+#define Uniform2ivARB_remap_index 135
+#define Uniform3fARB_remap_index 136
+#define Uniform3fvARB_remap_index 137
+#define Uniform3iARB_remap_index 138
+#define Uniform3ivARB_remap_index 139
+#define Uniform4fARB_remap_index 140
+#define Uniform4fvARB_remap_index 141
+#define Uniform4iARB_remap_index 142
+#define Uniform4ivARB_remap_index 143
+#define UniformMatrix2fvARB_remap_index 144
+#define UniformMatrix3fvARB_remap_index 145
+#define UniformMatrix4fvARB_remap_index 146
+#define UseProgramObjectARB_remap_index 147
+#define ValidateProgramARB_remap_index 148
+#define BindAttribLocationARB_remap_index 149
+#define GetActiveAttribARB_remap_index 150
+#define GetAttribLocationARB_remap_index 151
+#define DrawBuffersARB_remap_index 152
+#define RenderbufferStorageMultisample_remap_index 153
+#define FlushMappedBufferRange_remap_index 154
+#define MapBufferRange_remap_index 155
+#define BindVertexArray_remap_index 156
+#define GenVertexArrays_remap_index 157
+#define CopyBufferSubData_remap_index 158
+#define ClientWaitSync_remap_index 159
+#define DeleteSync_remap_index 160
+#define FenceSync_remap_index 161
+#define GetInteger64v_remap_index 162
+#define GetSynciv_remap_index 163
+#define IsSync_remap_index 164
+#define WaitSync_remap_index 165
+#define PolygonOffsetEXT_remap_index 166
+#define GetPixelTexGenParameterfvSGIS_remap_index 167
+#define GetPixelTexGenParameterivSGIS_remap_index 168
+#define PixelTexGenParameterfSGIS_remap_index 169
+#define PixelTexGenParameterfvSGIS_remap_index 170
+#define PixelTexGenParameteriSGIS_remap_index 171
+#define PixelTexGenParameterivSGIS_remap_index 172
+#define SampleMaskSGIS_remap_index 173
+#define SamplePatternSGIS_remap_index 174
+#define ColorPointerEXT_remap_index 175
+#define EdgeFlagPointerEXT_remap_index 176
+#define IndexPointerEXT_remap_index 177
+#define NormalPointerEXT_remap_index 178
+#define TexCoordPointerEXT_remap_index 179
+#define VertexPointerEXT_remap_index 180
+#define PointParameterfEXT_remap_index 181
+#define PointParameterfvEXT_remap_index 182
+#define LockArraysEXT_remap_index 183
+#define UnlockArraysEXT_remap_index 184
+#define CullParameterdvEXT_remap_index 185
+#define CullParameterfvEXT_remap_index 186
+#define SecondaryColor3bEXT_remap_index 187
+#define SecondaryColor3bvEXT_remap_index 188
+#define SecondaryColor3dEXT_remap_index 189
+#define SecondaryColor3dvEXT_remap_index 190
+#define SecondaryColor3fEXT_remap_index 191
+#define SecondaryColor3fvEXT_remap_index 192
+#define SecondaryColor3iEXT_remap_index 193
+#define SecondaryColor3ivEXT_remap_index 194
+#define SecondaryColor3sEXT_remap_index 195
+#define SecondaryColor3svEXT_remap_index 196
+#define SecondaryColor3ubEXT_remap_index 197
+#define SecondaryColor3ubvEXT_remap_index 198
+#define SecondaryColor3uiEXT_remap_index 199
+#define SecondaryColor3uivEXT_remap_index 200
+#define SecondaryColor3usEXT_remap_index 201
+#define SecondaryColor3usvEXT_remap_index 202
+#define SecondaryColorPointerEXT_remap_index 203
+#define MultiDrawArraysEXT_remap_index 204
+#define MultiDrawElementsEXT_remap_index 205
+#define FogCoordPointerEXT_remap_index 206
+#define FogCoorddEXT_remap_index 207
+#define FogCoorddvEXT_remap_index 208
+#define FogCoordfEXT_remap_index 209
+#define FogCoordfvEXT_remap_index 210
+#define PixelTexGenSGIX_remap_index 211
+#define BlendFuncSeparateEXT_remap_index 212
+#define FlushVertexArrayRangeNV_remap_index 213
+#define VertexArrayRangeNV_remap_index 214
+#define CombinerInputNV_remap_index 215
+#define CombinerOutputNV_remap_index 216
+#define CombinerParameterfNV_remap_index 217
+#define CombinerParameterfvNV_remap_index 218
+#define CombinerParameteriNV_remap_index 219
+#define CombinerParameterivNV_remap_index 220
+#define FinalCombinerInputNV_remap_index 221
+#define GetCombinerInputParameterfvNV_remap_index 222
+#define GetCombinerInputParameterivNV_remap_index 223
+#define GetCombinerOutputParameterfvNV_remap_index 224
+#define GetCombinerOutputParameterivNV_remap_index 225
+#define GetFinalCombinerInputParameterfvNV_remap_index 226
+#define GetFinalCombinerInputParameterivNV_remap_index 227
+#define ResizeBuffersMESA_remap_index 228
+#define WindowPos2dMESA_remap_index 229
+#define WindowPos2dvMESA_remap_index 230
+#define WindowPos2fMESA_remap_index 231
+#define WindowPos2fvMESA_remap_index 232
+#define WindowPos2iMESA_remap_index 233
+#define WindowPos2ivMESA_remap_index 234
+#define WindowPos2sMESA_remap_index 235
+#define WindowPos2svMESA_remap_index 236
+#define WindowPos3dMESA_remap_index 237
+#define WindowPos3dvMESA_remap_index 238
+#define WindowPos3fMESA_remap_index 239
+#define WindowPos3fvMESA_remap_index 240
+#define WindowPos3iMESA_remap_index 241
+#define WindowPos3ivMESA_remap_index 242
+#define WindowPos3sMESA_remap_index 243
+#define WindowPos3svMESA_remap_index 244
+#define WindowPos4dMESA_remap_index 245
+#define WindowPos4dvMESA_remap_index 246
+#define WindowPos4fMESA_remap_index 247
+#define WindowPos4fvMESA_remap_index 248
+#define WindowPos4iMESA_remap_index 249
+#define WindowPos4ivMESA_remap_index 250
+#define WindowPos4sMESA_remap_index 251
+#define WindowPos4svMESA_remap_index 252
+#define MultiModeDrawArraysIBM_remap_index 253
+#define MultiModeDrawElementsIBM_remap_index 254
+#define DeleteFencesNV_remap_index 255
+#define FinishFenceNV_remap_index 256
+#define GenFencesNV_remap_index 257
+#define GetFenceivNV_remap_index 258
+#define IsFenceNV_remap_index 259
+#define SetFenceNV_remap_index 260
+#define TestFenceNV_remap_index 261
+#define AreProgramsResidentNV_remap_index 262
+#define BindProgramNV_remap_index 263
+#define DeleteProgramsNV_remap_index 264
+#define ExecuteProgramNV_remap_index 265
+#define GenProgramsNV_remap_index 266
+#define GetProgramParameterdvNV_remap_index 267
+#define GetProgramParameterfvNV_remap_index 268
+#define GetProgramStringNV_remap_index 269
+#define GetProgramivNV_remap_index 270
+#define GetTrackMatrixivNV_remap_index 271
+#define GetVertexAttribPointervNV_remap_index 272
+#define GetVertexAttribdvNV_remap_index 273
+#define GetVertexAttribfvNV_remap_index 274
+#define GetVertexAttribivNV_remap_index 275
+#define IsProgramNV_remap_index 276
+#define LoadProgramNV_remap_index 277
+#define ProgramParameters4dvNV_remap_index 278
+#define ProgramParameters4fvNV_remap_index 279
+#define RequestResidentProgramsNV_remap_index 280
+#define TrackMatrixNV_remap_index 281
+#define VertexAttrib1dNV_remap_index 282
+#define VertexAttrib1dvNV_remap_index 283
+#define VertexAttrib1fNV_remap_index 284
+#define VertexAttrib1fvNV_remap_index 285
+#define VertexAttrib1sNV_remap_index 286
+#define VertexAttrib1svNV_remap_index 287
+#define VertexAttrib2dNV_remap_index 288
+#define VertexAttrib2dvNV_remap_index 289
+#define VertexAttrib2fNV_remap_index 290
+#define VertexAttrib2fvNV_remap_index 291
+#define VertexAttrib2sNV_remap_index 292
+#define VertexAttrib2svNV_remap_index 293
+#define VertexAttrib3dNV_remap_index 294
+#define VertexAttrib3dvNV_remap_index 295
+#define VertexAttrib3fNV_remap_index 296
+#define VertexAttrib3fvNV_remap_index 297
+#define VertexAttrib3sNV_remap_index 298
+#define VertexAttrib3svNV_remap_index 299
+#define VertexAttrib4dNV_remap_index 300
+#define VertexAttrib4dvNV_remap_index 301
+#define VertexAttrib4fNV_remap_index 302
+#define VertexAttrib4fvNV_remap_index 303
+#define VertexAttrib4sNV_remap_index 304
+#define VertexAttrib4svNV_remap_index 305
+#define VertexAttrib4ubNV_remap_index 306
+#define VertexAttrib4ubvNV_remap_index 307
+#define VertexAttribPointerNV_remap_index 308
+#define VertexAttribs1dvNV_remap_index 309
+#define VertexAttribs1fvNV_remap_index 310
+#define VertexAttribs1svNV_remap_index 311
+#define VertexAttribs2dvNV_remap_index 312
+#define VertexAttribs2fvNV_remap_index 313
+#define VertexAttribs2svNV_remap_index 314
+#define VertexAttribs3dvNV_remap_index 315
+#define VertexAttribs3fvNV_remap_index 316
+#define VertexAttribs3svNV_remap_index 317
+#define VertexAttribs4dvNV_remap_index 318
+#define VertexAttribs4fvNV_remap_index 319
+#define VertexAttribs4svNV_remap_index 320
+#define VertexAttribs4ubvNV_remap_index 321
+#define GetTexBumpParameterfvATI_remap_index 322
+#define GetTexBumpParameterivATI_remap_index 323
+#define TexBumpParameterfvATI_remap_index 324
+#define TexBumpParameterivATI_remap_index 325
+#define AlphaFragmentOp1ATI_remap_index 326
+#define AlphaFragmentOp2ATI_remap_index 327
+#define AlphaFragmentOp3ATI_remap_index 328
+#define BeginFragmentShaderATI_remap_index 329
+#define BindFragmentShaderATI_remap_index 330
+#define ColorFragmentOp1ATI_remap_index 331
+#define ColorFragmentOp2ATI_remap_index 332
+#define ColorFragmentOp3ATI_remap_index 333
+#define DeleteFragmentShaderATI_remap_index 334
+#define EndFragmentShaderATI_remap_index 335
+#define GenFragmentShadersATI_remap_index 336
+#define PassTexCoordATI_remap_index 337
+#define SampleMapATI_remap_index 338
+#define SetFragmentShaderConstantATI_remap_index 339
+#define PointParameteriNV_remap_index 340
+#define PointParameterivNV_remap_index 341
+#define ActiveStencilFaceEXT_remap_index 342
+#define BindVertexArrayAPPLE_remap_index 343
+#define DeleteVertexArraysAPPLE_remap_index 344
+#define GenVertexArraysAPPLE_remap_index 345
+#define IsVertexArrayAPPLE_remap_index 346
+#define GetProgramNamedParameterdvNV_remap_index 347
+#define GetProgramNamedParameterfvNV_remap_index 348
+#define ProgramNamedParameter4dNV_remap_index 349
+#define ProgramNamedParameter4dvNV_remap_index 350
+#define ProgramNamedParameter4fNV_remap_index 351
+#define ProgramNamedParameter4fvNV_remap_index 352
+#define DepthBoundsEXT_remap_index 353
+#define BlendEquationSeparateEXT_remap_index 354
+#define BindFramebufferEXT_remap_index 355
+#define BindRenderbufferEXT_remap_index 356
+#define CheckFramebufferStatusEXT_remap_index 357
+#define DeleteFramebuffersEXT_remap_index 358
+#define DeleteRenderbuffersEXT_remap_index 359
+#define FramebufferRenderbufferEXT_remap_index 360
+#define FramebufferTexture1DEXT_remap_index 361
+#define FramebufferTexture2DEXT_remap_index 362
+#define FramebufferTexture3DEXT_remap_index 363
+#define GenFramebuffersEXT_remap_index 364
+#define GenRenderbuffersEXT_remap_index 365
+#define GenerateMipmapEXT_remap_index 366
+#define GetFramebufferAttachmentParameterivEXT_remap_index 367
+#define GetRenderbufferParameterivEXT_remap_index 368
+#define IsFramebufferEXT_remap_index 369
+#define IsRenderbufferEXT_remap_index 370
+#define RenderbufferStorageEXT_remap_index 371
+#define BlitFramebufferEXT_remap_index 372
+#define BufferParameteriAPPLE_remap_index 373
+#define FlushMappedBufferRangeAPPLE_remap_index 374
+#define FramebufferTextureLayerEXT_remap_index 375
+#define ProvokingVertexEXT_remap_index 376
+#define GetTexParameterPointervAPPLE_remap_index 377
+#define TextureRangeAPPLE_remap_index 378
+#define StencilFuncSeparateATI_remap_index 379
+#define ProgramEnvParameters4fvEXT_remap_index 380
+#define ProgramLocalParameters4fvEXT_remap_index 381
+#define GetQueryObjecti64vEXT_remap_index 382
+#define GetQueryObjectui64vEXT_remap_index 383
+
+#define CALL_AttachShader(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint)), driDispatchRemapTable[AttachShader_remap_index], parameters)
+#define GET_AttachShader(disp) GET_by_offset(disp, driDispatchRemapTable[AttachShader_remap_index])
+#define SET_AttachShader(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AttachShader_remap_index], fn)
+#define CALL_CreateProgram(disp, parameters) CALL_by_offset(disp, (GLuint (GLAPIENTRYP)(void)), driDispatchRemapTable[CreateProgram_remap_index], parameters)
+#define GET_CreateProgram(disp) GET_by_offset(disp, driDispatchRemapTable[CreateProgram_remap_index])
+#define SET_CreateProgram(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CreateProgram_remap_index], fn)
+#define CALL_CreateShader(disp, parameters) CALL_by_offset(disp, (GLuint (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[CreateShader_remap_index], parameters)
+#define GET_CreateShader(disp) GET_by_offset(disp, driDispatchRemapTable[CreateShader_remap_index])
+#define SET_CreateShader(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CreateShader_remap_index], fn)
+#define CALL_DeleteProgram(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[DeleteProgram_remap_index], parameters)
+#define GET_DeleteProgram(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteProgram_remap_index])
+#define SET_DeleteProgram(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteProgram_remap_index], fn)
+#define CALL_DeleteShader(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[DeleteShader_remap_index], parameters)
+#define GET_DeleteShader(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteShader_remap_index])
+#define SET_DeleteShader(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteShader_remap_index], fn)
+#define CALL_DetachShader(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint)), driDispatchRemapTable[DetachShader_remap_index], parameters)
+#define GET_DetachShader(disp) GET_by_offset(disp, driDispatchRemapTable[DetachShader_remap_index])
+#define SET_DetachShader(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DetachShader_remap_index], fn)
+#define CALL_GetAttachedShaders(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, GLsizei *, GLuint *)), driDispatchRemapTable[GetAttachedShaders_remap_index], parameters)
+#define GET_GetAttachedShaders(disp) GET_by_offset(disp, driDispatchRemapTable[GetAttachedShaders_remap_index])
+#define SET_GetAttachedShaders(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetAttachedShaders_remap_index], fn)
+#define CALL_GetProgramInfoLog(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, GLsizei *, GLchar *)), driDispatchRemapTable[GetProgramInfoLog_remap_index], parameters)
+#define GET_GetProgramInfoLog(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramInfoLog_remap_index])
+#define SET_GetProgramInfoLog(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramInfoLog_remap_index], fn)
+#define CALL_GetProgramiv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetProgramiv_remap_index], parameters)
+#define GET_GetProgramiv(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramiv_remap_index])
+#define SET_GetProgramiv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramiv_remap_index], fn)
+#define CALL_GetShaderInfoLog(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, GLsizei *, GLchar *)), driDispatchRemapTable[GetShaderInfoLog_remap_index], parameters)
+#define GET_GetShaderInfoLog(disp) GET_by_offset(disp, driDispatchRemapTable[GetShaderInfoLog_remap_index])
+#define SET_GetShaderInfoLog(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetShaderInfoLog_remap_index], fn)
+#define CALL_GetShaderiv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetShaderiv_remap_index], parameters)
+#define GET_GetShaderiv(disp) GET_by_offset(disp, driDispatchRemapTable[GetShaderiv_remap_index])
+#define SET_GetShaderiv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetShaderiv_remap_index], fn)
+#define CALL_IsProgram(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsProgram_remap_index], parameters)
+#define GET_IsProgram(disp) GET_by_offset(disp, driDispatchRemapTable[IsProgram_remap_index])
+#define SET_IsProgram(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsProgram_remap_index], fn)
+#define CALL_IsShader(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsShader_remap_index], parameters)
+#define GET_IsShader(disp) GET_by_offset(disp, driDispatchRemapTable[IsShader_remap_index])
+#define SET_IsShader(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsShader_remap_index], fn)
+#define CALL_StencilFuncSeparate(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint, GLuint)), driDispatchRemapTable[StencilFuncSeparate_remap_index], parameters)
+#define GET_StencilFuncSeparate(disp) GET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparate_remap_index])
+#define SET_StencilFuncSeparate(disp, fn) SET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparate_remap_index], fn)
+#define CALL_StencilMaskSeparate(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[StencilMaskSeparate_remap_index], parameters)
+#define GET_StencilMaskSeparate(disp) GET_by_offset(disp, driDispatchRemapTable[StencilMaskSeparate_remap_index])
+#define SET_StencilMaskSeparate(disp, fn) SET_by_offset(disp, driDispatchRemapTable[StencilMaskSeparate_remap_index], fn)
+#define CALL_StencilOpSeparate(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum)), driDispatchRemapTable[StencilOpSeparate_remap_index], parameters)
+#define GET_StencilOpSeparate(disp) GET_by_offset(disp, driDispatchRemapTable[StencilOpSeparate_remap_index])
+#define SET_StencilOpSeparate(disp, fn) SET_by_offset(disp, driDispatchRemapTable[StencilOpSeparate_remap_index], fn)
+#define CALL_UniformMatrix2x3fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix2x3fv_remap_index], parameters)
+#define GET_UniformMatrix2x3fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix2x3fv_remap_index])
+#define SET_UniformMatrix2x3fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix2x3fv_remap_index], fn)
+#define CALL_UniformMatrix2x4fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix2x4fv_remap_index], parameters)
+#define GET_UniformMatrix2x4fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix2x4fv_remap_index])
+#define SET_UniformMatrix2x4fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix2x4fv_remap_index], fn)
+#define CALL_UniformMatrix3x2fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix3x2fv_remap_index], parameters)
+#define GET_UniformMatrix3x2fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix3x2fv_remap_index])
+#define SET_UniformMatrix3x2fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix3x2fv_remap_index], fn)
+#define CALL_UniformMatrix3x4fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix3x4fv_remap_index], parameters)
+#define GET_UniformMatrix3x4fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix3x4fv_remap_index])
+#define SET_UniformMatrix3x4fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix3x4fv_remap_index], fn)
+#define CALL_UniformMatrix4x2fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix4x2fv_remap_index], parameters)
+#define GET_UniformMatrix4x2fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix4x2fv_remap_index])
+#define SET_UniformMatrix4x2fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix4x2fv_remap_index], fn)
+#define CALL_UniformMatrix4x3fv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix4x3fv_remap_index], parameters)
+#define GET_UniformMatrix4x3fv(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix4x3fv_remap_index])
+#define SET_UniformMatrix4x3fv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix4x3fv_remap_index], fn)
+#define CALL_LoadTransposeMatrixdARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[LoadTransposeMatrixdARB_remap_index], parameters)
+#define GET_LoadTransposeMatrixdARB(disp) GET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixdARB_remap_index])
+#define SET_LoadTransposeMatrixdARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixdARB_remap_index], fn)
+#define CALL_LoadTransposeMatrixfARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index], parameters)
+#define GET_LoadTransposeMatrixfARB(disp) GET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index])
+#define SET_LoadTransposeMatrixfARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index], fn)
+#define CALL_MultTransposeMatrixdARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[MultTransposeMatrixdARB_remap_index], parameters)
+#define GET_MultTransposeMatrixdARB(disp) GET_by_offset(disp, driDispatchRemapTable[MultTransposeMatrixdARB_remap_index])
+#define SET_MultTransposeMatrixdARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultTransposeMatrixdARB_remap_index], fn)
+#define CALL_MultTransposeMatrixfARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[MultTransposeMatrixfARB_remap_index], parameters)
+#define GET_MultTransposeMatrixfARB(disp) GET_by_offset(disp, driDispatchRemapTable[MultTransposeMatrixfARB_remap_index])
+#define SET_MultTransposeMatrixfARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultTransposeMatrixfARB_remap_index], fn)
+#define CALL_SampleCoverageARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLclampf, GLboolean)), driDispatchRemapTable[SampleCoverageARB_remap_index], parameters)
+#define GET_SampleCoverageARB(disp) GET_by_offset(disp, driDispatchRemapTable[SampleCoverageARB_remap_index])
+#define SET_SampleCoverageARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SampleCoverageARB_remap_index], fn)
+#define CALL_CompressedTexImage1DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexImage1DARB_remap_index], parameters)
+#define GET_CompressedTexImage1DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexImage1DARB_remap_index])
+#define SET_CompressedTexImage1DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexImage1DARB_remap_index], fn)
+#define CALL_CompressedTexImage2DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexImage2DARB_remap_index], parameters)
+#define GET_CompressedTexImage2DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexImage2DARB_remap_index])
+#define SET_CompressedTexImage2DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexImage2DARB_remap_index], fn)
+#define CALL_CompressedTexImage3DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexImage3DARB_remap_index], parameters)
+#define GET_CompressedTexImage3DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexImage3DARB_remap_index])
+#define SET_CompressedTexImage3DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexImage3DARB_remap_index], fn)
+#define CALL_CompressedTexSubImage1DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexSubImage1DARB_remap_index], parameters)
+#define GET_CompressedTexSubImage1DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage1DARB_remap_index])
+#define SET_CompressedTexSubImage1DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage1DARB_remap_index], fn)
+#define CALL_CompressedTexSubImage2DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexSubImage2DARB_remap_index], parameters)
+#define GET_CompressedTexSubImage2DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage2DARB_remap_index])
+#define SET_CompressedTexSubImage2DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage2DARB_remap_index], fn)
+#define CALL_CompressedTexSubImage3DARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[CompressedTexSubImage3DARB_remap_index], parameters)
+#define GET_CompressedTexSubImage3DARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage3DARB_remap_index])
+#define SET_CompressedTexSubImage3DARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompressedTexSubImage3DARB_remap_index], fn)
+#define CALL_GetCompressedTexImageARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint, GLvoid *)), driDispatchRemapTable[GetCompressedTexImageARB_remap_index], parameters)
+#define GET_GetCompressedTexImageARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetCompressedTexImageARB_remap_index])
+#define SET_GetCompressedTexImageARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetCompressedTexImageARB_remap_index], fn)
+#define CALL_DisableVertexAttribArrayARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[DisableVertexAttribArrayARB_remap_index], parameters)
+#define GET_DisableVertexAttribArrayARB(disp) GET_by_offset(disp, driDispatchRemapTable[DisableVertexAttribArrayARB_remap_index])
+#define SET_DisableVertexAttribArrayARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DisableVertexAttribArrayARB_remap_index], fn)
+#define CALL_EnableVertexAttribArrayARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[EnableVertexAttribArrayARB_remap_index], parameters)
+#define GET_EnableVertexAttribArrayARB(disp) GET_by_offset(disp, driDispatchRemapTable[EnableVertexAttribArrayARB_remap_index])
+#define SET_EnableVertexAttribArrayARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[EnableVertexAttribArrayARB_remap_index], fn)
+#define CALL_GetProgramEnvParameterdvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLdouble *)), driDispatchRemapTable[GetProgramEnvParameterdvARB_remap_index], parameters)
+#define GET_GetProgramEnvParameterdvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramEnvParameterdvARB_remap_index])
+#define SET_GetProgramEnvParameterdvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramEnvParameterdvARB_remap_index], fn)
+#define CALL_GetProgramEnvParameterfvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLfloat *)), driDispatchRemapTable[GetProgramEnvParameterfvARB_remap_index], parameters)
+#define GET_GetProgramEnvParameterfvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramEnvParameterfvARB_remap_index])
+#define SET_GetProgramEnvParameterfvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramEnvParameterfvARB_remap_index], fn)
+#define CALL_GetProgramLocalParameterdvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLdouble *)), driDispatchRemapTable[GetProgramLocalParameterdvARB_remap_index], parameters)
+#define GET_GetProgramLocalParameterdvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramLocalParameterdvARB_remap_index])
+#define SET_GetProgramLocalParameterdvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramLocalParameterdvARB_remap_index], fn)
+#define CALL_GetProgramLocalParameterfvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLfloat *)), driDispatchRemapTable[GetProgramLocalParameterfvARB_remap_index], parameters)
+#define GET_GetProgramLocalParameterfvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramLocalParameterfvARB_remap_index])
+#define SET_GetProgramLocalParameterfvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramLocalParameterfvARB_remap_index], fn)
+#define CALL_GetProgramStringARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLvoid *)), driDispatchRemapTable[GetProgramStringARB_remap_index], parameters)
+#define GET_GetProgramStringARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramStringARB_remap_index])
+#define SET_GetProgramStringARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramStringARB_remap_index], fn)
+#define CALL_GetProgramivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint *)), driDispatchRemapTable[GetProgramivARB_remap_index], parameters)
+#define GET_GetProgramivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramivARB_remap_index])
+#define SET_GetProgramivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramivARB_remap_index], fn)
+#define CALL_GetVertexAttribdvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLdouble *)), driDispatchRemapTable[GetVertexAttribdvARB_remap_index], parameters)
+#define GET_GetVertexAttribdvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribdvARB_remap_index])
+#define SET_GetVertexAttribdvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribdvARB_remap_index], fn)
+#define CALL_GetVertexAttribfvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLfloat *)), driDispatchRemapTable[GetVertexAttribfvARB_remap_index], parameters)
+#define GET_GetVertexAttribfvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribfvARB_remap_index])
+#define SET_GetVertexAttribfvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribfvARB_remap_index], fn)
+#define CALL_GetVertexAttribivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetVertexAttribivARB_remap_index], parameters)
+#define GET_GetVertexAttribivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribivARB_remap_index])
+#define SET_GetVertexAttribivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribivARB_remap_index], fn)
+#define CALL_ProgramEnvParameter4dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[ProgramEnvParameter4dARB_remap_index], parameters)
+#define GET_ProgramEnvParameter4dARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4dARB_remap_index])
+#define SET_ProgramEnvParameter4dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4dARB_remap_index], fn)
+#define CALL_ProgramEnvParameter4dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, const GLdouble *)), driDispatchRemapTable[ProgramEnvParameter4dvARB_remap_index], parameters)
+#define GET_ProgramEnvParameter4dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4dvARB_remap_index])
+#define SET_ProgramEnvParameter4dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4dvARB_remap_index], fn)
+#define CALL_ProgramEnvParameter4fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[ProgramEnvParameter4fARB_remap_index], parameters)
+#define GET_ProgramEnvParameter4fARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4fARB_remap_index])
+#define SET_ProgramEnvParameter4fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4fARB_remap_index], fn)
+#define CALL_ProgramEnvParameter4fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, const GLfloat *)), driDispatchRemapTable[ProgramEnvParameter4fvARB_remap_index], parameters)
+#define GET_ProgramEnvParameter4fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4fvARB_remap_index])
+#define SET_ProgramEnvParameter4fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameter4fvARB_remap_index], fn)
+#define CALL_ProgramLocalParameter4dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[ProgramLocalParameter4dARB_remap_index], parameters)
+#define GET_ProgramLocalParameter4dARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4dARB_remap_index])
+#define SET_ProgramLocalParameter4dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4dARB_remap_index], fn)
+#define CALL_ProgramLocalParameter4dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, const GLdouble *)), driDispatchRemapTable[ProgramLocalParameter4dvARB_remap_index], parameters)
+#define GET_ProgramLocalParameter4dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4dvARB_remap_index])
+#define SET_ProgramLocalParameter4dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4dvARB_remap_index], fn)
+#define CALL_ProgramLocalParameter4fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[ProgramLocalParameter4fARB_remap_index], parameters)
+#define GET_ProgramLocalParameter4fARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4fARB_remap_index])
+#define SET_ProgramLocalParameter4fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4fARB_remap_index], fn)
+#define CALL_ProgramLocalParameter4fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, const GLfloat *)), driDispatchRemapTable[ProgramLocalParameter4fvARB_remap_index], parameters)
+#define GET_ProgramLocalParameter4fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4fvARB_remap_index])
+#define SET_ProgramLocalParameter4fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameter4fvARB_remap_index], fn)
+#define CALL_ProgramStringARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[ProgramStringARB_remap_index], parameters)
+#define GET_ProgramStringARB(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramStringARB_remap_index])
+#define SET_ProgramStringARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramStringARB_remap_index], fn)
+#define CALL_VertexAttrib1dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble)), driDispatchRemapTable[VertexAttrib1dARB_remap_index], parameters)
+#define GET_VertexAttrib1dARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dARB_remap_index])
+#define SET_VertexAttrib1dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dARB_remap_index], fn)
+#define CALL_VertexAttrib1dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib1dvARB_remap_index], parameters)
+#define GET_VertexAttrib1dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dvARB_remap_index])
+#define SET_VertexAttrib1dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dvARB_remap_index], fn)
+#define CALL_VertexAttrib1fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat)), driDispatchRemapTable[VertexAttrib1fARB_remap_index], parameters)
+#define GET_VertexAttrib1fARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fARB_remap_index])
+#define SET_VertexAttrib1fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fARB_remap_index], fn)
+#define CALL_VertexAttrib1fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib1fvARB_remap_index], parameters)
+#define GET_VertexAttrib1fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fvARB_remap_index])
+#define SET_VertexAttrib1fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fvARB_remap_index], fn)
+#define CALL_VertexAttrib1sARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort)), driDispatchRemapTable[VertexAttrib1sARB_remap_index], parameters)
+#define GET_VertexAttrib1sARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1sARB_remap_index])
+#define SET_VertexAttrib1sARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1sARB_remap_index], fn)
+#define CALL_VertexAttrib1svARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib1svARB_remap_index], parameters)
+#define GET_VertexAttrib1svARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1svARB_remap_index])
+#define SET_VertexAttrib1svARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1svARB_remap_index], fn)
+#define CALL_VertexAttrib2dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib2dARB_remap_index], parameters)
+#define GET_VertexAttrib2dARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dARB_remap_index])
+#define SET_VertexAttrib2dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dARB_remap_index], fn)
+#define CALL_VertexAttrib2dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib2dvARB_remap_index], parameters)
+#define GET_VertexAttrib2dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dvARB_remap_index])
+#define SET_VertexAttrib2dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dvARB_remap_index], fn)
+#define CALL_VertexAttrib2fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib2fARB_remap_index], parameters)
+#define GET_VertexAttrib2fARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fARB_remap_index])
+#define SET_VertexAttrib2fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fARB_remap_index], fn)
+#define CALL_VertexAttrib2fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib2fvARB_remap_index], parameters)
+#define GET_VertexAttrib2fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fvARB_remap_index])
+#define SET_VertexAttrib2fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fvARB_remap_index], fn)
+#define CALL_VertexAttrib2sARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib2sARB_remap_index], parameters)
+#define GET_VertexAttrib2sARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2sARB_remap_index])
+#define SET_VertexAttrib2sARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2sARB_remap_index], fn)
+#define CALL_VertexAttrib2svARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib2svARB_remap_index], parameters)
+#define GET_VertexAttrib2svARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2svARB_remap_index])
+#define SET_VertexAttrib2svARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2svARB_remap_index], fn)
+#define CALL_VertexAttrib3dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib3dARB_remap_index], parameters)
+#define GET_VertexAttrib3dARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dARB_remap_index])
+#define SET_VertexAttrib3dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dARB_remap_index], fn)
+#define CALL_VertexAttrib3dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib3dvARB_remap_index], parameters)
+#define GET_VertexAttrib3dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dvARB_remap_index])
+#define SET_VertexAttrib3dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dvARB_remap_index], fn)
+#define CALL_VertexAttrib3fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib3fARB_remap_index], parameters)
+#define GET_VertexAttrib3fARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fARB_remap_index])
+#define SET_VertexAttrib3fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fARB_remap_index], fn)
+#define CALL_VertexAttrib3fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib3fvARB_remap_index], parameters)
+#define GET_VertexAttrib3fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fvARB_remap_index])
+#define SET_VertexAttrib3fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fvARB_remap_index], fn)
+#define CALL_VertexAttrib3sARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib3sARB_remap_index], parameters)
+#define GET_VertexAttrib3sARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3sARB_remap_index])
+#define SET_VertexAttrib3sARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3sARB_remap_index], fn)
+#define CALL_VertexAttrib3svARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib3svARB_remap_index], parameters)
+#define GET_VertexAttrib3svARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3svARB_remap_index])
+#define SET_VertexAttrib3svARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3svARB_remap_index], fn)
+#define CALL_VertexAttrib4NbvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLbyte *)), driDispatchRemapTable[VertexAttrib4NbvARB_remap_index], parameters)
+#define GET_VertexAttrib4NbvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NbvARB_remap_index])
+#define SET_VertexAttrib4NbvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NbvARB_remap_index], fn)
+#define CALL_VertexAttrib4NivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLint *)), driDispatchRemapTable[VertexAttrib4NivARB_remap_index], parameters)
+#define GET_VertexAttrib4NivARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NivARB_remap_index])
+#define SET_VertexAttrib4NivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NivARB_remap_index], fn)
+#define CALL_VertexAttrib4NsvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib4NsvARB_remap_index], parameters)
+#define GET_VertexAttrib4NsvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NsvARB_remap_index])
+#define SET_VertexAttrib4NsvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NsvARB_remap_index], fn)
+#define CALL_VertexAttrib4NubARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte)), driDispatchRemapTable[VertexAttrib4NubARB_remap_index], parameters)
+#define GET_VertexAttrib4NubARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NubARB_remap_index])
+#define SET_VertexAttrib4NubARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NubARB_remap_index], fn)
+#define CALL_VertexAttrib4NubvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLubyte *)), driDispatchRemapTable[VertexAttrib4NubvARB_remap_index], parameters)
+#define GET_VertexAttrib4NubvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NubvARB_remap_index])
+#define SET_VertexAttrib4NubvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NubvARB_remap_index], fn)
+#define CALL_VertexAttrib4NuivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLuint *)), driDispatchRemapTable[VertexAttrib4NuivARB_remap_index], parameters)
+#define GET_VertexAttrib4NuivARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NuivARB_remap_index])
+#define SET_VertexAttrib4NuivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NuivARB_remap_index], fn)
+#define CALL_VertexAttrib4NusvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLushort *)), driDispatchRemapTable[VertexAttrib4NusvARB_remap_index], parameters)
+#define GET_VertexAttrib4NusvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NusvARB_remap_index])
+#define SET_VertexAttrib4NusvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4NusvARB_remap_index], fn)
+#define CALL_VertexAttrib4bvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLbyte *)), driDispatchRemapTable[VertexAttrib4bvARB_remap_index], parameters)
+#define GET_VertexAttrib4bvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4bvARB_remap_index])
+#define SET_VertexAttrib4bvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4bvARB_remap_index], fn)
+#define CALL_VertexAttrib4dARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib4dARB_remap_index], parameters)
+#define GET_VertexAttrib4dARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dARB_remap_index])
+#define SET_VertexAttrib4dARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dARB_remap_index], fn)
+#define CALL_VertexAttrib4dvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib4dvARB_remap_index], parameters)
+#define GET_VertexAttrib4dvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dvARB_remap_index])
+#define SET_VertexAttrib4dvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dvARB_remap_index], fn)
+#define CALL_VertexAttrib4fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib4fARB_remap_index], parameters)
+#define GET_VertexAttrib4fARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fARB_remap_index])
+#define SET_VertexAttrib4fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fARB_remap_index], fn)
+#define CALL_VertexAttrib4fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib4fvARB_remap_index], parameters)
+#define GET_VertexAttrib4fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fvARB_remap_index])
+#define SET_VertexAttrib4fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fvARB_remap_index], fn)
+#define CALL_VertexAttrib4ivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLint *)), driDispatchRemapTable[VertexAttrib4ivARB_remap_index], parameters)
+#define GET_VertexAttrib4ivARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ivARB_remap_index])
+#define SET_VertexAttrib4ivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ivARB_remap_index], fn)
+#define CALL_VertexAttrib4sARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib4sARB_remap_index], parameters)
+#define GET_VertexAttrib4sARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4sARB_remap_index])
+#define SET_VertexAttrib4sARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4sARB_remap_index], fn)
+#define CALL_VertexAttrib4svARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib4svARB_remap_index], parameters)
+#define GET_VertexAttrib4svARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4svARB_remap_index])
+#define SET_VertexAttrib4svARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4svARB_remap_index], fn)
+#define CALL_VertexAttrib4ubvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLubyte *)), driDispatchRemapTable[VertexAttrib4ubvARB_remap_index], parameters)
+#define GET_VertexAttrib4ubvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubvARB_remap_index])
+#define SET_VertexAttrib4ubvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubvARB_remap_index], fn)
+#define CALL_VertexAttrib4uivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLuint *)), driDispatchRemapTable[VertexAttrib4uivARB_remap_index], parameters)
+#define GET_VertexAttrib4uivARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4uivARB_remap_index])
+#define SET_VertexAttrib4uivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4uivARB_remap_index], fn)
+#define CALL_VertexAttrib4usvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLushort *)), driDispatchRemapTable[VertexAttrib4usvARB_remap_index], parameters)
+#define GET_VertexAttrib4usvARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4usvARB_remap_index])
+#define SET_VertexAttrib4usvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4usvARB_remap_index], fn)
+#define CALL_VertexAttribPointerARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *)), driDispatchRemapTable[VertexAttribPointerARB_remap_index], parameters)
+#define GET_VertexAttribPointerARB(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribPointerARB_remap_index])
+#define SET_VertexAttribPointerARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribPointerARB_remap_index], fn)
+#define CALL_BindBufferARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[BindBufferARB_remap_index], parameters)
+#define GET_BindBufferARB(disp) GET_by_offset(disp, driDispatchRemapTable[BindBufferARB_remap_index])
+#define SET_BindBufferARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindBufferARB_remap_index], fn)
+#define CALL_BufferDataARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizeiptrARB, const GLvoid *, GLenum)), driDispatchRemapTable[BufferDataARB_remap_index], parameters)
+#define GET_BufferDataARB(disp) GET_by_offset(disp, driDispatchRemapTable[BufferDataARB_remap_index])
+#define SET_BufferDataARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BufferDataARB_remap_index], fn)
+#define CALL_BufferSubDataARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *)), driDispatchRemapTable[BufferSubDataARB_remap_index], parameters)
+#define GET_BufferSubDataARB(disp) GET_by_offset(disp, driDispatchRemapTable[BufferSubDataARB_remap_index])
+#define SET_BufferSubDataARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BufferSubDataARB_remap_index], fn)
+#define CALL_DeleteBuffersARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteBuffersARB_remap_index], parameters)
+#define GET_DeleteBuffersARB(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteBuffersARB_remap_index])
+#define SET_DeleteBuffersARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteBuffersARB_remap_index], fn)
+#define CALL_GenBuffersARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenBuffersARB_remap_index], parameters)
+#define GET_GenBuffersARB(disp) GET_by_offset(disp, driDispatchRemapTable[GenBuffersARB_remap_index])
+#define SET_GenBuffersARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenBuffersARB_remap_index], fn)
+#define CALL_GetBufferParameterivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint *)), driDispatchRemapTable[GetBufferParameterivARB_remap_index], parameters)
+#define GET_GetBufferParameterivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetBufferParameterivARB_remap_index])
+#define SET_GetBufferParameterivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetBufferParameterivARB_remap_index], fn)
+#define CALL_GetBufferPointervARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLvoid **)), driDispatchRemapTable[GetBufferPointervARB_remap_index], parameters)
+#define GET_GetBufferPointervARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetBufferPointervARB_remap_index])
+#define SET_GetBufferPointervARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetBufferPointervARB_remap_index], fn)
+#define CALL_GetBufferSubDataARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *)), driDispatchRemapTable[GetBufferSubDataARB_remap_index], parameters)
+#define GET_GetBufferSubDataARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetBufferSubDataARB_remap_index])
+#define SET_GetBufferSubDataARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetBufferSubDataARB_remap_index], fn)
+#define CALL_IsBufferARB(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsBufferARB_remap_index], parameters)
+#define GET_IsBufferARB(disp) GET_by_offset(disp, driDispatchRemapTable[IsBufferARB_remap_index])
+#define SET_IsBufferARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsBufferARB_remap_index], fn)
+#define CALL_MapBufferARB(disp, parameters) CALL_by_offset(disp, (GLvoid * (GLAPIENTRYP)(GLenum, GLenum)), driDispatchRemapTable[MapBufferARB_remap_index], parameters)
+#define GET_MapBufferARB(disp) GET_by_offset(disp, driDispatchRemapTable[MapBufferARB_remap_index])
+#define SET_MapBufferARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MapBufferARB_remap_index], fn)
+#define CALL_UnmapBufferARB(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[UnmapBufferARB_remap_index], parameters)
+#define GET_UnmapBufferARB(disp) GET_by_offset(disp, driDispatchRemapTable[UnmapBufferARB_remap_index])
+#define SET_UnmapBufferARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UnmapBufferARB_remap_index], fn)
+#define CALL_BeginQueryARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[BeginQueryARB_remap_index], parameters)
+#define GET_BeginQueryARB(disp) GET_by_offset(disp, driDispatchRemapTable[BeginQueryARB_remap_index])
+#define SET_BeginQueryARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BeginQueryARB_remap_index], fn)
+#define CALL_DeleteQueriesARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteQueriesARB_remap_index], parameters)
+#define GET_DeleteQueriesARB(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteQueriesARB_remap_index])
+#define SET_DeleteQueriesARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteQueriesARB_remap_index], fn)
+#define CALL_EndQueryARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[EndQueryARB_remap_index], parameters)
+#define GET_EndQueryARB(disp) GET_by_offset(disp, driDispatchRemapTable[EndQueryARB_remap_index])
+#define SET_EndQueryARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[EndQueryARB_remap_index], fn)
+#define CALL_GenQueriesARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenQueriesARB_remap_index], parameters)
+#define GET_GenQueriesARB(disp) GET_by_offset(disp, driDispatchRemapTable[GenQueriesARB_remap_index])
+#define SET_GenQueriesARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenQueriesARB_remap_index], fn)
+#define CALL_GetQueryObjectivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetQueryObjectivARB_remap_index], parameters)
+#define GET_GetQueryObjectivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectivARB_remap_index])
+#define SET_GetQueryObjectivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectivARB_remap_index], fn)
+#define CALL_GetQueryObjectuivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLuint *)), driDispatchRemapTable[GetQueryObjectuivARB_remap_index], parameters)
+#define GET_GetQueryObjectuivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectuivARB_remap_index])
+#define SET_GetQueryObjectuivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectuivARB_remap_index], fn)
+#define CALL_GetQueryivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint *)), driDispatchRemapTable[GetQueryivARB_remap_index], parameters)
+#define GET_GetQueryivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryivARB_remap_index])
+#define SET_GetQueryivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryivARB_remap_index], fn)
+#define CALL_IsQueryARB(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsQueryARB_remap_index], parameters)
+#define GET_IsQueryARB(disp) GET_by_offset(disp, driDispatchRemapTable[IsQueryARB_remap_index])
+#define SET_IsQueryARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsQueryARB_remap_index], fn)
+#define CALL_AttachObjectARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLhandleARB)), driDispatchRemapTable[AttachObjectARB_remap_index], parameters)
+#define GET_AttachObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[AttachObjectARB_remap_index])
+#define SET_AttachObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AttachObjectARB_remap_index], fn)
+#define CALL_CompileShaderARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB)), driDispatchRemapTable[CompileShaderARB_remap_index], parameters)
+#define GET_CompileShaderARB(disp) GET_by_offset(disp, driDispatchRemapTable[CompileShaderARB_remap_index])
+#define SET_CompileShaderARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CompileShaderARB_remap_index], fn)
+#define CALL_CreateProgramObjectARB(disp, parameters) CALL_by_offset(disp, (GLhandleARB (GLAPIENTRYP)(void)), driDispatchRemapTable[CreateProgramObjectARB_remap_index], parameters)
+#define GET_CreateProgramObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[CreateProgramObjectARB_remap_index])
+#define SET_CreateProgramObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CreateProgramObjectARB_remap_index], fn)
+#define CALL_CreateShaderObjectARB(disp, parameters) CALL_by_offset(disp, (GLhandleARB (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[CreateShaderObjectARB_remap_index], parameters)
+#define GET_CreateShaderObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[CreateShaderObjectARB_remap_index])
+#define SET_CreateShaderObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CreateShaderObjectARB_remap_index], fn)
+#define CALL_DeleteObjectARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB)), driDispatchRemapTable[DeleteObjectARB_remap_index], parameters)
+#define GET_DeleteObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteObjectARB_remap_index])
+#define SET_DeleteObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteObjectARB_remap_index], fn)
+#define CALL_DetachObjectARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLhandleARB)), driDispatchRemapTable[DetachObjectARB_remap_index], parameters)
+#define GET_DetachObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[DetachObjectARB_remap_index])
+#define SET_DetachObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DetachObjectARB_remap_index], fn)
+#define CALL_GetActiveUniformARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *)), driDispatchRemapTable[GetActiveUniformARB_remap_index], parameters)
+#define GET_GetActiveUniformARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetActiveUniformARB_remap_index])
+#define SET_GetActiveUniformARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetActiveUniformARB_remap_index], fn)
+#define CALL_GetAttachedObjectsARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLsizei, GLsizei *, GLhandleARB *)), driDispatchRemapTable[GetAttachedObjectsARB_remap_index], parameters)
+#define GET_GetAttachedObjectsARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetAttachedObjectsARB_remap_index])
+#define SET_GetAttachedObjectsARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetAttachedObjectsARB_remap_index], fn)
+#define CALL_GetHandleARB(disp, parameters) CALL_by_offset(disp, (GLhandleARB (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[GetHandleARB_remap_index], parameters)
+#define GET_GetHandleARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetHandleARB_remap_index])
+#define SET_GetHandleARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetHandleARB_remap_index], fn)
+#define CALL_GetInfoLogARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *)), driDispatchRemapTable[GetInfoLogARB_remap_index], parameters)
+#define GET_GetInfoLogARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetInfoLogARB_remap_index])
+#define SET_GetInfoLogARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetInfoLogARB_remap_index], fn)
+#define CALL_GetObjectParameterfvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLenum, GLfloat *)), driDispatchRemapTable[GetObjectParameterfvARB_remap_index], parameters)
+#define GET_GetObjectParameterfvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetObjectParameterfvARB_remap_index])
+#define SET_GetObjectParameterfvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetObjectParameterfvARB_remap_index], fn)
+#define CALL_GetObjectParameterivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLenum, GLint *)), driDispatchRemapTable[GetObjectParameterivARB_remap_index], parameters)
+#define GET_GetObjectParameterivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetObjectParameterivARB_remap_index])
+#define SET_GetObjectParameterivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetObjectParameterivARB_remap_index], fn)
+#define CALL_GetShaderSourceARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *)), driDispatchRemapTable[GetShaderSourceARB_remap_index], parameters)
+#define GET_GetShaderSourceARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetShaderSourceARB_remap_index])
+#define SET_GetShaderSourceARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetShaderSourceARB_remap_index], fn)
+#define CALL_GetUniformLocationARB(disp, parameters) CALL_by_offset(disp, (GLint (GLAPIENTRYP)(GLhandleARB, const GLcharARB *)), driDispatchRemapTable[GetUniformLocationARB_remap_index], parameters)
+#define GET_GetUniformLocationARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetUniformLocationARB_remap_index])
+#define SET_GetUniformLocationARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetUniformLocationARB_remap_index], fn)
+#define CALL_GetUniformfvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLint, GLfloat *)), driDispatchRemapTable[GetUniformfvARB_remap_index], parameters)
+#define GET_GetUniformfvARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetUniformfvARB_remap_index])
+#define SET_GetUniformfvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetUniformfvARB_remap_index], fn)
+#define CALL_GetUniformivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLint, GLint *)), driDispatchRemapTable[GetUniformivARB_remap_index], parameters)
+#define GET_GetUniformivARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetUniformivARB_remap_index])
+#define SET_GetUniformivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetUniformivARB_remap_index], fn)
+#define CALL_LinkProgramARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB)), driDispatchRemapTable[LinkProgramARB_remap_index], parameters)
+#define GET_LinkProgramARB(disp) GET_by_offset(disp, driDispatchRemapTable[LinkProgramARB_remap_index])
+#define SET_LinkProgramARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[LinkProgramARB_remap_index], fn)
+#define CALL_ShaderSourceARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLsizei, const GLcharARB **, const GLint *)), driDispatchRemapTable[ShaderSourceARB_remap_index], parameters)
+#define GET_ShaderSourceARB(disp) GET_by_offset(disp, driDispatchRemapTable[ShaderSourceARB_remap_index])
+#define SET_ShaderSourceARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ShaderSourceARB_remap_index], fn)
+#define CALL_Uniform1fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLfloat)), driDispatchRemapTable[Uniform1fARB_remap_index], parameters)
+#define GET_Uniform1fARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform1fARB_remap_index])
+#define SET_Uniform1fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform1fARB_remap_index], fn)
+#define CALL_Uniform1fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLfloat *)), driDispatchRemapTable[Uniform1fvARB_remap_index], parameters)
+#define GET_Uniform1fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform1fvARB_remap_index])
+#define SET_Uniform1fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform1fvARB_remap_index], fn)
+#define CALL_Uniform1iARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint)), driDispatchRemapTable[Uniform1iARB_remap_index], parameters)
+#define GET_Uniform1iARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform1iARB_remap_index])
+#define SET_Uniform1iARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform1iARB_remap_index], fn)
+#define CALL_Uniform1ivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLint *)), driDispatchRemapTable[Uniform1ivARB_remap_index], parameters)
+#define GET_Uniform1ivARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform1ivARB_remap_index])
+#define SET_Uniform1ivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform1ivARB_remap_index], fn)
+#define CALL_Uniform2fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLfloat, GLfloat)), driDispatchRemapTable[Uniform2fARB_remap_index], parameters)
+#define GET_Uniform2fARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform2fARB_remap_index])
+#define SET_Uniform2fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform2fARB_remap_index], fn)
+#define CALL_Uniform2fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLfloat *)), driDispatchRemapTable[Uniform2fvARB_remap_index], parameters)
+#define GET_Uniform2fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform2fvARB_remap_index])
+#define SET_Uniform2fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform2fvARB_remap_index], fn)
+#define CALL_Uniform2iARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint)), driDispatchRemapTable[Uniform2iARB_remap_index], parameters)
+#define GET_Uniform2iARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform2iARB_remap_index])
+#define SET_Uniform2iARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform2iARB_remap_index], fn)
+#define CALL_Uniform2ivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLint *)), driDispatchRemapTable[Uniform2ivARB_remap_index], parameters)
+#define GET_Uniform2ivARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform2ivARB_remap_index])
+#define SET_Uniform2ivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform2ivARB_remap_index], fn)
+#define CALL_Uniform3fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[Uniform3fARB_remap_index], parameters)
+#define GET_Uniform3fARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform3fARB_remap_index])
+#define SET_Uniform3fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform3fARB_remap_index], fn)
+#define CALL_Uniform3fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLfloat *)), driDispatchRemapTable[Uniform3fvARB_remap_index], parameters)
+#define GET_Uniform3fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform3fvARB_remap_index])
+#define SET_Uniform3fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform3fvARB_remap_index], fn)
+#define CALL_Uniform3iARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint)), driDispatchRemapTable[Uniform3iARB_remap_index], parameters)
+#define GET_Uniform3iARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform3iARB_remap_index])
+#define SET_Uniform3iARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform3iARB_remap_index], fn)
+#define CALL_Uniform3ivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLint *)), driDispatchRemapTable[Uniform3ivARB_remap_index], parameters)
+#define GET_Uniform3ivARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform3ivARB_remap_index])
+#define SET_Uniform3ivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform3ivARB_remap_index], fn)
+#define CALL_Uniform4fARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[Uniform4fARB_remap_index], parameters)
+#define GET_Uniform4fARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform4fARB_remap_index])
+#define SET_Uniform4fARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform4fARB_remap_index], fn)
+#define CALL_Uniform4fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLfloat *)), driDispatchRemapTable[Uniform4fvARB_remap_index], parameters)
+#define GET_Uniform4fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform4fvARB_remap_index])
+#define SET_Uniform4fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform4fvARB_remap_index], fn)
+#define CALL_Uniform4iARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint)), driDispatchRemapTable[Uniform4iARB_remap_index], parameters)
+#define GET_Uniform4iARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform4iARB_remap_index])
+#define SET_Uniform4iARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform4iARB_remap_index], fn)
+#define CALL_Uniform4ivARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, const GLint *)), driDispatchRemapTable[Uniform4ivARB_remap_index], parameters)
+#define GET_Uniform4ivARB(disp) GET_by_offset(disp, driDispatchRemapTable[Uniform4ivARB_remap_index])
+#define SET_Uniform4ivARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[Uniform4ivARB_remap_index], fn)
+#define CALL_UniformMatrix2fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix2fvARB_remap_index], parameters)
+#define GET_UniformMatrix2fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix2fvARB_remap_index])
+#define SET_UniformMatrix2fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix2fvARB_remap_index], fn)
+#define CALL_UniformMatrix3fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix3fvARB_remap_index], parameters)
+#define GET_UniformMatrix3fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix3fvARB_remap_index])
+#define SET_UniformMatrix3fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix3fvARB_remap_index], fn)
+#define CALL_UniformMatrix4fvARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei, GLboolean, const GLfloat *)), driDispatchRemapTable[UniformMatrix4fvARB_remap_index], parameters)
+#define GET_UniformMatrix4fvARB(disp) GET_by_offset(disp, driDispatchRemapTable[UniformMatrix4fvARB_remap_index])
+#define SET_UniformMatrix4fvARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UniformMatrix4fvARB_remap_index], fn)
+#define CALL_UseProgramObjectARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB)), driDispatchRemapTable[UseProgramObjectARB_remap_index], parameters)
+#define GET_UseProgramObjectARB(disp) GET_by_offset(disp, driDispatchRemapTable[UseProgramObjectARB_remap_index])
+#define SET_UseProgramObjectARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UseProgramObjectARB_remap_index], fn)
+#define CALL_ValidateProgramARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB)), driDispatchRemapTable[ValidateProgramARB_remap_index], parameters)
+#define GET_ValidateProgramARB(disp) GET_by_offset(disp, driDispatchRemapTable[ValidateProgramARB_remap_index])
+#define SET_ValidateProgramARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ValidateProgramARB_remap_index], fn)
+#define CALL_BindAttribLocationARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLuint, const GLcharARB *)), driDispatchRemapTable[BindAttribLocationARB_remap_index], parameters)
+#define GET_BindAttribLocationARB(disp) GET_by_offset(disp, driDispatchRemapTable[BindAttribLocationARB_remap_index])
+#define SET_BindAttribLocationARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindAttribLocationARB_remap_index], fn)
+#define CALL_GetActiveAttribARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *)), driDispatchRemapTable[GetActiveAttribARB_remap_index], parameters)
+#define GET_GetActiveAttribARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetActiveAttribARB_remap_index])
+#define SET_GetActiveAttribARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetActiveAttribARB_remap_index], fn)
+#define CALL_GetAttribLocationARB(disp, parameters) CALL_by_offset(disp, (GLint (GLAPIENTRYP)(GLhandleARB, const GLcharARB *)), driDispatchRemapTable[GetAttribLocationARB_remap_index], parameters)
+#define GET_GetAttribLocationARB(disp) GET_by_offset(disp, driDispatchRemapTable[GetAttribLocationARB_remap_index])
+#define SET_GetAttribLocationARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetAttribLocationARB_remap_index], fn)
+#define CALL_DrawBuffersARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLenum *)), driDispatchRemapTable[DrawBuffersARB_remap_index], parameters)
+#define GET_DrawBuffersARB(disp) GET_by_offset(disp, driDispatchRemapTable[DrawBuffersARB_remap_index])
+#define SET_DrawBuffersARB(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DrawBuffersARB_remap_index], fn)
+#define CALL_RenderbufferStorageMultisample(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)), driDispatchRemapTable[RenderbufferStorageMultisample_remap_index], parameters)
+#define GET_RenderbufferStorageMultisample(disp) GET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageMultisample_remap_index])
+#define SET_RenderbufferStorageMultisample(disp, fn) SET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageMultisample_remap_index], fn)
+#define CALL_FlushMappedBufferRange(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr)), driDispatchRemapTable[FlushMappedBufferRange_remap_index], parameters)
+#define GET_FlushMappedBufferRange(disp) GET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRange_remap_index])
+#define SET_FlushMappedBufferRange(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRange_remap_index], fn)
+#define CALL_MapBufferRange(disp, parameters) CALL_by_offset(disp, (GLvoid * (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr, GLbitfield)), driDispatchRemapTable[MapBufferRange_remap_index], parameters)
+#define GET_MapBufferRange(disp) GET_by_offset(disp, driDispatchRemapTable[MapBufferRange_remap_index])
+#define SET_MapBufferRange(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MapBufferRange_remap_index], fn)
+#define CALL_BindVertexArray(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[BindVertexArray_remap_index], parameters)
+#define GET_BindVertexArray(disp) GET_by_offset(disp, driDispatchRemapTable[BindVertexArray_remap_index])
+#define SET_BindVertexArray(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindVertexArray_remap_index], fn)
+#define CALL_GenVertexArrays(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenVertexArrays_remap_index], parameters)
+#define GET_GenVertexArrays(disp) GET_by_offset(disp, driDispatchRemapTable[GenVertexArrays_remap_index])
+#define SET_GenVertexArrays(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenVertexArrays_remap_index], fn)
+#define CALL_CopyBufferSubData(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr)), driDispatchRemapTable[CopyBufferSubData_remap_index], parameters)
+#define GET_CopyBufferSubData(disp) GET_by_offset(disp, driDispatchRemapTable[CopyBufferSubData_remap_index])
+#define SET_CopyBufferSubData(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CopyBufferSubData_remap_index], fn)
+#define CALL_ClientWaitSync(disp, parameters) CALL_by_offset(disp, (GLenum (GLAPIENTRYP)(GLsync, GLbitfield, GLuint64)), driDispatchRemapTable[ClientWaitSync_remap_index], parameters)
+#define GET_ClientWaitSync(disp) GET_by_offset(disp, driDispatchRemapTable[ClientWaitSync_remap_index])
+#define SET_ClientWaitSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ClientWaitSync_remap_index], fn)
+#define CALL_DeleteSync(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync)), driDispatchRemapTable[DeleteSync_remap_index], parameters)
+#define GET_DeleteSync(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteSync_remap_index])
+#define SET_DeleteSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteSync_remap_index], fn)
+#define CALL_FenceSync(disp, parameters) CALL_by_offset(disp, (GLsync (GLAPIENTRYP)(GLenum, GLbitfield)), driDispatchRemapTable[FenceSync_remap_index], parameters)
+#define GET_FenceSync(disp) GET_by_offset(disp, driDispatchRemapTable[FenceSync_remap_index])
+#define SET_FenceSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FenceSync_remap_index], fn)
+#define CALL_GetInteger64v(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint64 *)), driDispatchRemapTable[GetInteger64v_remap_index], parameters)
+#define GET_GetInteger64v(disp) GET_by_offset(disp, driDispatchRemapTable[GetInteger64v_remap_index])
+#define SET_GetInteger64v(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetInteger64v_remap_index], fn)
+#define CALL_GetSynciv(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync, GLenum, GLsizei, GLsizei *, GLint *)), driDispatchRemapTable[GetSynciv_remap_index], parameters)
+#define GET_GetSynciv(disp) GET_by_offset(disp, driDispatchRemapTable[GetSynciv_remap_index])
+#define SET_GetSynciv(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetSynciv_remap_index], fn)
+#define CALL_IsSync(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLsync)), driDispatchRemapTable[IsSync_remap_index], parameters)
+#define GET_IsSync(disp) GET_by_offset(disp, driDispatchRemapTable[IsSync_remap_index])
+#define SET_IsSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsSync_remap_index], fn)
+#define CALL_WaitSync(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsync, GLbitfield, GLuint64)), driDispatchRemapTable[WaitSync_remap_index], parameters)
+#define GET_WaitSync(disp) GET_by_offset(disp, driDispatchRemapTable[WaitSync_remap_index])
+#define SET_WaitSync(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WaitSync_remap_index], fn)
+#define CALL_PolygonOffsetEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat)), driDispatchRemapTable[PolygonOffsetEXT_remap_index], parameters)
+#define GET_PolygonOffsetEXT(disp) GET_by_offset(disp, driDispatchRemapTable[PolygonOffsetEXT_remap_index])
+#define SET_PolygonOffsetEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PolygonOffsetEXT_remap_index], fn)
+#define CALL_GetPixelTexGenParameterfvSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat *)), driDispatchRemapTable[GetPixelTexGenParameterfvSGIS_remap_index], parameters)
+#define GET_GetPixelTexGenParameterfvSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[GetPixelTexGenParameterfvSGIS_remap_index])
+#define SET_GetPixelTexGenParameterfvSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetPixelTexGenParameterfvSGIS_remap_index], fn)
+#define CALL_GetPixelTexGenParameterivSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint *)), driDispatchRemapTable[GetPixelTexGenParameterivSGIS_remap_index], parameters)
+#define GET_GetPixelTexGenParameterivSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[GetPixelTexGenParameterivSGIS_remap_index])
+#define SET_GetPixelTexGenParameterivSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetPixelTexGenParameterivSGIS_remap_index], fn)
+#define CALL_PixelTexGenParameterfSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat)), driDispatchRemapTable[PixelTexGenParameterfSGIS_remap_index], parameters)
+#define GET_PixelTexGenParameterfSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterfSGIS_remap_index])
+#define SET_PixelTexGenParameterfSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterfSGIS_remap_index], fn)
+#define CALL_PixelTexGenParameterfvSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLfloat *)), driDispatchRemapTable[PixelTexGenParameterfvSGIS_remap_index], parameters)
+#define GET_PixelTexGenParameterfvSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterfvSGIS_remap_index])
+#define SET_PixelTexGenParameterfvSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterfvSGIS_remap_index], fn)
+#define CALL_PixelTexGenParameteriSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint)), driDispatchRemapTable[PixelTexGenParameteriSGIS_remap_index], parameters)
+#define GET_PixelTexGenParameteriSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameteriSGIS_remap_index])
+#define SET_PixelTexGenParameteriSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameteriSGIS_remap_index], fn)
+#define CALL_PixelTexGenParameterivSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLint *)), driDispatchRemapTable[PixelTexGenParameterivSGIS_remap_index], parameters)
+#define GET_PixelTexGenParameterivSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterivSGIS_remap_index])
+#define SET_PixelTexGenParameterivSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PixelTexGenParameterivSGIS_remap_index], fn)
+#define CALL_SampleMaskSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLclampf, GLboolean)), driDispatchRemapTable[SampleMaskSGIS_remap_index], parameters)
+#define GET_SampleMaskSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[SampleMaskSGIS_remap_index])
+#define SET_SampleMaskSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SampleMaskSGIS_remap_index], fn)
+#define CALL_SamplePatternSGIS(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[SamplePatternSGIS_remap_index], parameters)
+#define GET_SamplePatternSGIS(disp) GET_by_offset(disp, driDispatchRemapTable[SamplePatternSGIS_remap_index])
+#define SET_SamplePatternSGIS(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SamplePatternSGIS_remap_index], fn)
+#define CALL_ColorPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLenum, GLsizei, GLsizei, const GLvoid *)), driDispatchRemapTable[ColorPointerEXT_remap_index], parameters)
+#define GET_ColorPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ColorPointerEXT_remap_index])
+#define SET_ColorPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ColorPointerEXT_remap_index], fn)
+#define CALL_EdgeFlagPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLsizei, const GLboolean *)), driDispatchRemapTable[EdgeFlagPointerEXT_remap_index], parameters)
+#define GET_EdgeFlagPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[EdgeFlagPointerEXT_remap_index])
+#define SET_EdgeFlagPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[EdgeFlagPointerEXT_remap_index], fn)
+#define CALL_IndexPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLsizei, const GLvoid *)), driDispatchRemapTable[IndexPointerEXT_remap_index], parameters)
+#define GET_IndexPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[IndexPointerEXT_remap_index])
+#define SET_IndexPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IndexPointerEXT_remap_index], fn)
+#define CALL_NormalPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLsizei, const GLvoid *)), driDispatchRemapTable[NormalPointerEXT_remap_index], parameters)
+#define GET_NormalPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[NormalPointerEXT_remap_index])
+#define SET_NormalPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[NormalPointerEXT_remap_index], fn)
+#define CALL_TexCoordPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLenum, GLsizei, GLsizei, const GLvoid *)), driDispatchRemapTable[TexCoordPointerEXT_remap_index], parameters)
+#define GET_TexCoordPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[TexCoordPointerEXT_remap_index])
+#define SET_TexCoordPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TexCoordPointerEXT_remap_index], fn)
+#define CALL_VertexPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLenum, GLsizei, GLsizei, const GLvoid *)), driDispatchRemapTable[VertexPointerEXT_remap_index], parameters)
+#define GET_VertexPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[VertexPointerEXT_remap_index])
+#define SET_VertexPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexPointerEXT_remap_index], fn)
+#define CALL_PointParameterfEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat)), driDispatchRemapTable[PointParameterfEXT_remap_index], parameters)
+#define GET_PointParameterfEXT(disp) GET_by_offset(disp, driDispatchRemapTable[PointParameterfEXT_remap_index])
+#define SET_PointParameterfEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PointParameterfEXT_remap_index], fn)
+#define CALL_PointParameterfvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLfloat *)), driDispatchRemapTable[PointParameterfvEXT_remap_index], parameters)
+#define GET_PointParameterfvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[PointParameterfvEXT_remap_index])
+#define SET_PointParameterfvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PointParameterfvEXT_remap_index], fn)
+#define CALL_LockArraysEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLsizei)), driDispatchRemapTable[LockArraysEXT_remap_index], parameters)
+#define GET_LockArraysEXT(disp) GET_by_offset(disp, driDispatchRemapTable[LockArraysEXT_remap_index])
+#define SET_LockArraysEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[LockArraysEXT_remap_index], fn)
+#define CALL_UnlockArraysEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(void)), driDispatchRemapTable[UnlockArraysEXT_remap_index], parameters)
+#define GET_UnlockArraysEXT(disp) GET_by_offset(disp, driDispatchRemapTable[UnlockArraysEXT_remap_index])
+#define SET_UnlockArraysEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[UnlockArraysEXT_remap_index], fn)
+#define CALL_CullParameterdvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLdouble *)), driDispatchRemapTable[CullParameterdvEXT_remap_index], parameters)
+#define GET_CullParameterdvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[CullParameterdvEXT_remap_index])
+#define SET_CullParameterdvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CullParameterdvEXT_remap_index], fn)
+#define CALL_CullParameterfvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat *)), driDispatchRemapTable[CullParameterfvEXT_remap_index], parameters)
+#define GET_CullParameterfvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[CullParameterfvEXT_remap_index])
+#define SET_CullParameterfvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CullParameterfvEXT_remap_index], fn)
+#define CALL_SecondaryColor3bEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLbyte, GLbyte, GLbyte)), driDispatchRemapTable[SecondaryColor3bEXT_remap_index], parameters)
+#define GET_SecondaryColor3bEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3bEXT_remap_index])
+#define SET_SecondaryColor3bEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3bEXT_remap_index], fn)
+#define CALL_SecondaryColor3bvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLbyte *)), driDispatchRemapTable[SecondaryColor3bvEXT_remap_index], parameters)
+#define GET_SecondaryColor3bvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3bvEXT_remap_index])
+#define SET_SecondaryColor3bvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3bvEXT_remap_index], fn)
+#define CALL_SecondaryColor3dEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[SecondaryColor3dEXT_remap_index], parameters)
+#define GET_SecondaryColor3dEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3dEXT_remap_index])
+#define SET_SecondaryColor3dEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3dEXT_remap_index], fn)
+#define CALL_SecondaryColor3dvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[SecondaryColor3dvEXT_remap_index], parameters)
+#define GET_SecondaryColor3dvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3dvEXT_remap_index])
+#define SET_SecondaryColor3dvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3dvEXT_remap_index], fn)
+#define CALL_SecondaryColor3fEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[SecondaryColor3fEXT_remap_index], parameters)
+#define GET_SecondaryColor3fEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3fEXT_remap_index])
+#define SET_SecondaryColor3fEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3fEXT_remap_index], fn)
+#define CALL_SecondaryColor3fvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[SecondaryColor3fvEXT_remap_index], parameters)
+#define GET_SecondaryColor3fvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3fvEXT_remap_index])
+#define SET_SecondaryColor3fvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3fvEXT_remap_index], fn)
+#define CALL_SecondaryColor3iEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint)), driDispatchRemapTable[SecondaryColor3iEXT_remap_index], parameters)
+#define GET_SecondaryColor3iEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3iEXT_remap_index])
+#define SET_SecondaryColor3iEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3iEXT_remap_index], fn)
+#define CALL_SecondaryColor3ivEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLint *)), driDispatchRemapTable[SecondaryColor3ivEXT_remap_index], parameters)
+#define GET_SecondaryColor3ivEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ivEXT_remap_index])
+#define SET_SecondaryColor3ivEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ivEXT_remap_index], fn)
+#define CALL_SecondaryColor3sEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLshort, GLshort, GLshort)), driDispatchRemapTable[SecondaryColor3sEXT_remap_index], parameters)
+#define GET_SecondaryColor3sEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3sEXT_remap_index])
+#define SET_SecondaryColor3sEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3sEXT_remap_index], fn)
+#define CALL_SecondaryColor3svEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLshort *)), driDispatchRemapTable[SecondaryColor3svEXT_remap_index], parameters)
+#define GET_SecondaryColor3svEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3svEXT_remap_index])
+#define SET_SecondaryColor3svEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3svEXT_remap_index], fn)
+#define CALL_SecondaryColor3ubEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLubyte, GLubyte, GLubyte)), driDispatchRemapTable[SecondaryColor3ubEXT_remap_index], parameters)
+#define GET_SecondaryColor3ubEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ubEXT_remap_index])
+#define SET_SecondaryColor3ubEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ubEXT_remap_index], fn)
+#define CALL_SecondaryColor3ubvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLubyte *)), driDispatchRemapTable[SecondaryColor3ubvEXT_remap_index], parameters)
+#define GET_SecondaryColor3ubvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ubvEXT_remap_index])
+#define SET_SecondaryColor3ubvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3ubvEXT_remap_index], fn)
+#define CALL_SecondaryColor3uiEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint, GLuint)), driDispatchRemapTable[SecondaryColor3uiEXT_remap_index], parameters)
+#define GET_SecondaryColor3uiEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3uiEXT_remap_index])
+#define SET_SecondaryColor3uiEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3uiEXT_remap_index], fn)
+#define CALL_SecondaryColor3uivEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLuint *)), driDispatchRemapTable[SecondaryColor3uivEXT_remap_index], parameters)
+#define GET_SecondaryColor3uivEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3uivEXT_remap_index])
+#define SET_SecondaryColor3uivEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3uivEXT_remap_index], fn)
+#define CALL_SecondaryColor3usEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLushort, GLushort, GLushort)), driDispatchRemapTable[SecondaryColor3usEXT_remap_index], parameters)
+#define GET_SecondaryColor3usEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3usEXT_remap_index])
+#define SET_SecondaryColor3usEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3usEXT_remap_index], fn)
+#define CALL_SecondaryColor3usvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLushort *)), driDispatchRemapTable[SecondaryColor3usvEXT_remap_index], parameters)
+#define GET_SecondaryColor3usvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColor3usvEXT_remap_index])
+#define SET_SecondaryColor3usvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColor3usvEXT_remap_index], fn)
+#define CALL_SecondaryColorPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[SecondaryColorPointerEXT_remap_index], parameters)
+#define GET_SecondaryColorPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[SecondaryColorPointerEXT_remap_index])
+#define SET_SecondaryColorPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SecondaryColorPointerEXT_remap_index], fn)
+#define CALL_MultiDrawArraysEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint *, GLsizei *, GLsizei)), driDispatchRemapTable[MultiDrawArraysEXT_remap_index], parameters)
+#define GET_MultiDrawArraysEXT(disp) GET_by_offset(disp, driDispatchRemapTable[MultiDrawArraysEXT_remap_index])
+#define SET_MultiDrawArraysEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultiDrawArraysEXT_remap_index], fn)
+#define CALL_MultiDrawElementsEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei)), driDispatchRemapTable[MultiDrawElementsEXT_remap_index], parameters)
+#define GET_MultiDrawElementsEXT(disp) GET_by_offset(disp, driDispatchRemapTable[MultiDrawElementsEXT_remap_index])
+#define SET_MultiDrawElementsEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultiDrawElementsEXT_remap_index], fn)
+#define CALL_FogCoordPointerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[FogCoordPointerEXT_remap_index], parameters)
+#define GET_FogCoordPointerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FogCoordPointerEXT_remap_index])
+#define SET_FogCoordPointerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FogCoordPointerEXT_remap_index], fn)
+#define CALL_FogCoorddEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLdouble)), driDispatchRemapTable[FogCoorddEXT_remap_index], parameters)
+#define GET_FogCoorddEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FogCoorddEXT_remap_index])
+#define SET_FogCoorddEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FogCoorddEXT_remap_index], fn)
+#define CALL_FogCoorddvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[FogCoorddvEXT_remap_index], parameters)
+#define GET_FogCoorddvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FogCoorddvEXT_remap_index])
+#define SET_FogCoorddvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FogCoorddvEXT_remap_index], fn)
+#define CALL_FogCoordfEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat)), driDispatchRemapTable[FogCoordfEXT_remap_index], parameters)
+#define GET_FogCoordfEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FogCoordfEXT_remap_index])
+#define SET_FogCoordfEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FogCoordfEXT_remap_index], fn)
+#define CALL_FogCoordfvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[FogCoordfvEXT_remap_index], parameters)
+#define GET_FogCoordfvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FogCoordfvEXT_remap_index])
+#define SET_FogCoordfvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FogCoordfvEXT_remap_index], fn)
+#define CALL_PixelTexGenSGIX(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[PixelTexGenSGIX_remap_index], parameters)
+#define GET_PixelTexGenSGIX(disp) GET_by_offset(disp, driDispatchRemapTable[PixelTexGenSGIX_remap_index])
+#define SET_PixelTexGenSGIX(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PixelTexGenSGIX_remap_index], fn)
+#define CALL_BlendFuncSeparateEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum)), driDispatchRemapTable[BlendFuncSeparateEXT_remap_index], parameters)
+#define GET_BlendFuncSeparateEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlendFuncSeparateEXT_remap_index])
+#define SET_BlendFuncSeparateEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlendFuncSeparateEXT_remap_index], fn)
+#define CALL_FlushVertexArrayRangeNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(void)), driDispatchRemapTable[FlushVertexArrayRangeNV_remap_index], parameters)
+#define GET_FlushVertexArrayRangeNV(disp) GET_by_offset(disp, driDispatchRemapTable[FlushVertexArrayRangeNV_remap_index])
+#define SET_FlushVertexArrayRangeNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FlushVertexArrayRangeNV_remap_index], fn)
+#define CALL_VertexArrayRangeNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLvoid *)), driDispatchRemapTable[VertexArrayRangeNV_remap_index], parameters)
+#define GET_VertexArrayRangeNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexArrayRangeNV_remap_index])
+#define SET_VertexArrayRangeNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexArrayRangeNV_remap_index], fn)
+#define CALL_CombinerInputNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum)), driDispatchRemapTable[CombinerInputNV_remap_index], parameters)
+#define GET_CombinerInputNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerInputNV_remap_index])
+#define SET_CombinerInputNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerInputNV_remap_index], fn)
+#define CALL_CombinerOutputNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean)), driDispatchRemapTable[CombinerOutputNV_remap_index], parameters)
+#define GET_CombinerOutputNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerOutputNV_remap_index])
+#define SET_CombinerOutputNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerOutputNV_remap_index], fn)
+#define CALL_CombinerParameterfNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat)), driDispatchRemapTable[CombinerParameterfNV_remap_index], parameters)
+#define GET_CombinerParameterfNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerParameterfNV_remap_index])
+#define SET_CombinerParameterfNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerParameterfNV_remap_index], fn)
+#define CALL_CombinerParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLfloat *)), driDispatchRemapTable[CombinerParameterfvNV_remap_index], parameters)
+#define GET_CombinerParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerParameterfvNV_remap_index])
+#define SET_CombinerParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerParameterfvNV_remap_index], fn)
+#define CALL_CombinerParameteriNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint)), driDispatchRemapTable[CombinerParameteriNV_remap_index], parameters)
+#define GET_CombinerParameteriNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerParameteriNV_remap_index])
+#define SET_CombinerParameteriNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerParameteriNV_remap_index], fn)
+#define CALL_CombinerParameterivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLint *)), driDispatchRemapTable[CombinerParameterivNV_remap_index], parameters)
+#define GET_CombinerParameterivNV(disp) GET_by_offset(disp, driDispatchRemapTable[CombinerParameterivNV_remap_index])
+#define SET_CombinerParameterivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CombinerParameterivNV_remap_index], fn)
+#define CALL_FinalCombinerInputNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum)), driDispatchRemapTable[FinalCombinerInputNV_remap_index], parameters)
+#define GET_FinalCombinerInputNV(disp) GET_by_offset(disp, driDispatchRemapTable[FinalCombinerInputNV_remap_index])
+#define SET_FinalCombinerInputNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FinalCombinerInputNV_remap_index], fn)
+#define CALL_GetCombinerInputParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum, GLfloat *)), driDispatchRemapTable[GetCombinerInputParameterfvNV_remap_index], parameters)
+#define GET_GetCombinerInputParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetCombinerInputParameterfvNV_remap_index])
+#define SET_GetCombinerInputParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetCombinerInputParameterfvNV_remap_index], fn)
+#define CALL_GetCombinerInputParameterivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLenum, GLint *)), driDispatchRemapTable[GetCombinerInputParameterivNV_remap_index], parameters)
+#define GET_GetCombinerInputParameterivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetCombinerInputParameterivNV_remap_index])
+#define SET_GetCombinerInputParameterivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetCombinerInputParameterivNV_remap_index], fn)
+#define CALL_GetCombinerOutputParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLfloat *)), driDispatchRemapTable[GetCombinerOutputParameterfvNV_remap_index], parameters)
+#define GET_GetCombinerOutputParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetCombinerOutputParameterfvNV_remap_index])
+#define SET_GetCombinerOutputParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetCombinerOutputParameterfvNV_remap_index], fn)
+#define CALL_GetCombinerOutputParameterivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLint *)), driDispatchRemapTable[GetCombinerOutputParameterivNV_remap_index], parameters)
+#define GET_GetCombinerOutputParameterivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetCombinerOutputParameterivNV_remap_index])
+#define SET_GetCombinerOutputParameterivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetCombinerOutputParameterivNV_remap_index], fn)
+#define CALL_GetFinalCombinerInputParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLfloat *)), driDispatchRemapTable[GetFinalCombinerInputParameterfvNV_remap_index], parameters)
+#define GET_GetFinalCombinerInputParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetFinalCombinerInputParameterfvNV_remap_index])
+#define SET_GetFinalCombinerInputParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetFinalCombinerInputParameterfvNV_remap_index], fn)
+#define CALL_GetFinalCombinerInputParameterivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint *)), driDispatchRemapTable[GetFinalCombinerInputParameterivNV_remap_index], parameters)
+#define GET_GetFinalCombinerInputParameterivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetFinalCombinerInputParameterivNV_remap_index])
+#define SET_GetFinalCombinerInputParameterivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetFinalCombinerInputParameterivNV_remap_index], fn)
+#define CALL_ResizeBuffersMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(void)), driDispatchRemapTable[ResizeBuffersMESA_remap_index], parameters)
+#define GET_ResizeBuffersMESA(disp) GET_by_offset(disp, driDispatchRemapTable[ResizeBuffersMESA_remap_index])
+#define SET_ResizeBuffersMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ResizeBuffersMESA_remap_index], fn)
+#define CALL_WindowPos2dMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLdouble, GLdouble)), driDispatchRemapTable[WindowPos2dMESA_remap_index], parameters)
+#define GET_WindowPos2dMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2dMESA_remap_index])
+#define SET_WindowPos2dMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2dMESA_remap_index], fn)
+#define CALL_WindowPos2dvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[WindowPos2dvMESA_remap_index], parameters)
+#define GET_WindowPos2dvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2dvMESA_remap_index])
+#define SET_WindowPos2dvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2dvMESA_remap_index], fn)
+#define CALL_WindowPos2fMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat)), driDispatchRemapTable[WindowPos2fMESA_remap_index], parameters)
+#define GET_WindowPos2fMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2fMESA_remap_index])
+#define SET_WindowPos2fMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2fMESA_remap_index], fn)
+#define CALL_WindowPos2fvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[WindowPos2fvMESA_remap_index], parameters)
+#define GET_WindowPos2fvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2fvMESA_remap_index])
+#define SET_WindowPos2fvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2fvMESA_remap_index], fn)
+#define CALL_WindowPos2iMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint)), driDispatchRemapTable[WindowPos2iMESA_remap_index], parameters)
+#define GET_WindowPos2iMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2iMESA_remap_index])
+#define SET_WindowPos2iMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2iMESA_remap_index], fn)
+#define CALL_WindowPos2ivMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLint *)), driDispatchRemapTable[WindowPos2ivMESA_remap_index], parameters)
+#define GET_WindowPos2ivMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2ivMESA_remap_index])
+#define SET_WindowPos2ivMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2ivMESA_remap_index], fn)
+#define CALL_WindowPos2sMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLshort, GLshort)), driDispatchRemapTable[WindowPos2sMESA_remap_index], parameters)
+#define GET_WindowPos2sMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2sMESA_remap_index])
+#define SET_WindowPos2sMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2sMESA_remap_index], fn)
+#define CALL_WindowPos2svMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLshort *)), driDispatchRemapTable[WindowPos2svMESA_remap_index], parameters)
+#define GET_WindowPos2svMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos2svMESA_remap_index])
+#define SET_WindowPos2svMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos2svMESA_remap_index], fn)
+#define CALL_WindowPos3dMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[WindowPos3dMESA_remap_index], parameters)
+#define GET_WindowPos3dMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3dMESA_remap_index])
+#define SET_WindowPos3dMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3dMESA_remap_index], fn)
+#define CALL_WindowPos3dvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[WindowPos3dvMESA_remap_index], parameters)
+#define GET_WindowPos3dvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3dvMESA_remap_index])
+#define SET_WindowPos3dvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3dvMESA_remap_index], fn)
+#define CALL_WindowPos3fMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[WindowPos3fMESA_remap_index], parameters)
+#define GET_WindowPos3fMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3fMESA_remap_index])
+#define SET_WindowPos3fMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3fMESA_remap_index], fn)
+#define CALL_WindowPos3fvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[WindowPos3fvMESA_remap_index], parameters)
+#define GET_WindowPos3fvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3fvMESA_remap_index])
+#define SET_WindowPos3fvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3fvMESA_remap_index], fn)
+#define CALL_WindowPos3iMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint)), driDispatchRemapTable[WindowPos3iMESA_remap_index], parameters)
+#define GET_WindowPos3iMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3iMESA_remap_index])
+#define SET_WindowPos3iMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3iMESA_remap_index], fn)
+#define CALL_WindowPos3ivMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLint *)), driDispatchRemapTable[WindowPos3ivMESA_remap_index], parameters)
+#define GET_WindowPos3ivMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3ivMESA_remap_index])
+#define SET_WindowPos3ivMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3ivMESA_remap_index], fn)
+#define CALL_WindowPos3sMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLshort, GLshort, GLshort)), driDispatchRemapTable[WindowPos3sMESA_remap_index], parameters)
+#define GET_WindowPos3sMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3sMESA_remap_index])
+#define SET_WindowPos3sMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3sMESA_remap_index], fn)
+#define CALL_WindowPos3svMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLshort *)), driDispatchRemapTable[WindowPos3svMESA_remap_index], parameters)
+#define GET_WindowPos3svMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos3svMESA_remap_index])
+#define SET_WindowPos3svMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos3svMESA_remap_index], fn)
+#define CALL_WindowPos4dMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[WindowPos4dMESA_remap_index], parameters)
+#define GET_WindowPos4dMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4dMESA_remap_index])
+#define SET_WindowPos4dMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4dMESA_remap_index], fn)
+#define CALL_WindowPos4dvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLdouble *)), driDispatchRemapTable[WindowPos4dvMESA_remap_index], parameters)
+#define GET_WindowPos4dvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4dvMESA_remap_index])
+#define SET_WindowPos4dvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4dvMESA_remap_index], fn)
+#define CALL_WindowPos4fMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[WindowPos4fMESA_remap_index], parameters)
+#define GET_WindowPos4fMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4fMESA_remap_index])
+#define SET_WindowPos4fMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4fMESA_remap_index], fn)
+#define CALL_WindowPos4fvMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[WindowPos4fvMESA_remap_index], parameters)
+#define GET_WindowPos4fvMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4fvMESA_remap_index])
+#define SET_WindowPos4fvMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4fvMESA_remap_index], fn)
+#define CALL_WindowPos4iMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint)), driDispatchRemapTable[WindowPos4iMESA_remap_index], parameters)
+#define GET_WindowPos4iMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4iMESA_remap_index])
+#define SET_WindowPos4iMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4iMESA_remap_index], fn)
+#define CALL_WindowPos4ivMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLint *)), driDispatchRemapTable[WindowPos4ivMESA_remap_index], parameters)
+#define GET_WindowPos4ivMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4ivMESA_remap_index])
+#define SET_WindowPos4ivMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4ivMESA_remap_index], fn)
+#define CALL_WindowPos4sMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLshort, GLshort, GLshort, GLshort)), driDispatchRemapTable[WindowPos4sMESA_remap_index], parameters)
+#define GET_WindowPos4sMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4sMESA_remap_index])
+#define SET_WindowPos4sMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4sMESA_remap_index], fn)
+#define CALL_WindowPos4svMESA(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLshort *)), driDispatchRemapTable[WindowPos4svMESA_remap_index], parameters)
+#define GET_WindowPos4svMESA(disp) GET_by_offset(disp, driDispatchRemapTable[WindowPos4svMESA_remap_index])
+#define SET_WindowPos4svMESA(disp, fn) SET_by_offset(disp, driDispatchRemapTable[WindowPos4svMESA_remap_index], fn)
+#define CALL_MultiModeDrawArraysIBM(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint)), driDispatchRemapTable[MultiModeDrawArraysIBM_remap_index], parameters)
+#define GET_MultiModeDrawArraysIBM(disp) GET_by_offset(disp, driDispatchRemapTable[MultiModeDrawArraysIBM_remap_index])
+#define SET_MultiModeDrawArraysIBM(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultiModeDrawArraysIBM_remap_index], fn)
+#define CALL_MultiModeDrawElementsIBM(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLenum *, const GLsizei *, GLenum, const GLvoid * const *, GLsizei, GLint)), driDispatchRemapTable[MultiModeDrawElementsIBM_remap_index], parameters)
+#define GET_MultiModeDrawElementsIBM(disp) GET_by_offset(disp, driDispatchRemapTable[MultiModeDrawElementsIBM_remap_index])
+#define SET_MultiModeDrawElementsIBM(disp, fn) SET_by_offset(disp, driDispatchRemapTable[MultiModeDrawElementsIBM_remap_index], fn)
+#define CALL_DeleteFencesNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteFencesNV_remap_index], parameters)
+#define GET_DeleteFencesNV(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteFencesNV_remap_index])
+#define SET_DeleteFencesNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteFencesNV_remap_index], fn)
+#define CALL_FinishFenceNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[FinishFenceNV_remap_index], parameters)
+#define GET_FinishFenceNV(disp) GET_by_offset(disp, driDispatchRemapTable[FinishFenceNV_remap_index])
+#define SET_FinishFenceNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FinishFenceNV_remap_index], fn)
+#define CALL_GenFencesNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenFencesNV_remap_index], parameters)
+#define GET_GenFencesNV(disp) GET_by_offset(disp, driDispatchRemapTable[GenFencesNV_remap_index])
+#define SET_GenFencesNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenFencesNV_remap_index], fn)
+#define CALL_GetFenceivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetFenceivNV_remap_index], parameters)
+#define GET_GetFenceivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetFenceivNV_remap_index])
+#define SET_GetFenceivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetFenceivNV_remap_index], fn)
+#define CALL_IsFenceNV(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsFenceNV_remap_index], parameters)
+#define GET_IsFenceNV(disp) GET_by_offset(disp, driDispatchRemapTable[IsFenceNV_remap_index])
+#define SET_IsFenceNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsFenceNV_remap_index], fn)
+#define CALL_SetFenceNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum)), driDispatchRemapTable[SetFenceNV_remap_index], parameters)
+#define GET_SetFenceNV(disp) GET_by_offset(disp, driDispatchRemapTable[SetFenceNV_remap_index])
+#define SET_SetFenceNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SetFenceNV_remap_index], fn)
+#define CALL_TestFenceNV(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[TestFenceNV_remap_index], parameters)
+#define GET_TestFenceNV(disp) GET_by_offset(disp, driDispatchRemapTable[TestFenceNV_remap_index])
+#define SET_TestFenceNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TestFenceNV_remap_index], fn)
+#define CALL_AreProgramsResidentNV(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLsizei, const GLuint *, GLboolean *)), driDispatchRemapTable[AreProgramsResidentNV_remap_index], parameters)
+#define GET_AreProgramsResidentNV(disp) GET_by_offset(disp, driDispatchRemapTable[AreProgramsResidentNV_remap_index])
+#define SET_AreProgramsResidentNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AreProgramsResidentNV_remap_index], fn)
+#define CALL_BindProgramNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[BindProgramNV_remap_index], parameters)
+#define GET_BindProgramNV(disp) GET_by_offset(disp, driDispatchRemapTable[BindProgramNV_remap_index])
+#define SET_BindProgramNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindProgramNV_remap_index], fn)
+#define CALL_DeleteProgramsNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteProgramsNV_remap_index], parameters)
+#define GET_DeleteProgramsNV(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteProgramsNV_remap_index])
+#define SET_DeleteProgramsNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteProgramsNV_remap_index], fn)
+#define CALL_ExecuteProgramNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, const GLfloat *)), driDispatchRemapTable[ExecuteProgramNV_remap_index], parameters)
+#define GET_ExecuteProgramNV(disp) GET_by_offset(disp, driDispatchRemapTable[ExecuteProgramNV_remap_index])
+#define SET_ExecuteProgramNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ExecuteProgramNV_remap_index], fn)
+#define CALL_GenProgramsNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenProgramsNV_remap_index], parameters)
+#define GET_GenProgramsNV(disp) GET_by_offset(disp, driDispatchRemapTable[GenProgramsNV_remap_index])
+#define SET_GenProgramsNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenProgramsNV_remap_index], fn)
+#define CALL_GetProgramParameterdvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLenum, GLdouble *)), driDispatchRemapTable[GetProgramParameterdvNV_remap_index], parameters)
+#define GET_GetProgramParameterdvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramParameterdvNV_remap_index])
+#define SET_GetProgramParameterdvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramParameterdvNV_remap_index], fn)
+#define CALL_GetProgramParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLenum, GLfloat *)), driDispatchRemapTable[GetProgramParameterfvNV_remap_index], parameters)
+#define GET_GetProgramParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramParameterfvNV_remap_index])
+#define SET_GetProgramParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramParameterfvNV_remap_index], fn)
+#define CALL_GetProgramStringNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLubyte *)), driDispatchRemapTable[GetProgramStringNV_remap_index], parameters)
+#define GET_GetProgramStringNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramStringNV_remap_index])
+#define SET_GetProgramStringNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramStringNV_remap_index], fn)
+#define CALL_GetProgramivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetProgramivNV_remap_index], parameters)
+#define GET_GetProgramivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramivNV_remap_index])
+#define SET_GetProgramivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramivNV_remap_index], fn)
+#define CALL_GetTrackMatrixivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLenum, GLint *)), driDispatchRemapTable[GetTrackMatrixivNV_remap_index], parameters)
+#define GET_GetTrackMatrixivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetTrackMatrixivNV_remap_index])
+#define SET_GetTrackMatrixivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTrackMatrixivNV_remap_index], fn)
+#define CALL_GetVertexAttribPointervNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLvoid **)), driDispatchRemapTable[GetVertexAttribPointervNV_remap_index], parameters)
+#define GET_GetVertexAttribPointervNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribPointervNV_remap_index])
+#define SET_GetVertexAttribPointervNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribPointervNV_remap_index], fn)
+#define CALL_GetVertexAttribdvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLdouble *)), driDispatchRemapTable[GetVertexAttribdvNV_remap_index], parameters)
+#define GET_GetVertexAttribdvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribdvNV_remap_index])
+#define SET_GetVertexAttribdvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribdvNV_remap_index], fn)
+#define CALL_GetVertexAttribfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLfloat *)), driDispatchRemapTable[GetVertexAttribfvNV_remap_index], parameters)
+#define GET_GetVertexAttribfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribfvNV_remap_index])
+#define SET_GetVertexAttribfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribfvNV_remap_index], fn)
+#define CALL_GetVertexAttribivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint *)), driDispatchRemapTable[GetVertexAttribivNV_remap_index], parameters)
+#define GET_GetVertexAttribivNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetVertexAttribivNV_remap_index])
+#define SET_GetVertexAttribivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetVertexAttribivNV_remap_index], fn)
+#define CALL_IsProgramNV(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsProgramNV_remap_index], parameters)
+#define GET_IsProgramNV(disp) GET_by_offset(disp, driDispatchRemapTable[IsProgramNV_remap_index])
+#define SET_IsProgramNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsProgramNV_remap_index], fn)
+#define CALL_LoadProgramNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLsizei, const GLubyte *)), driDispatchRemapTable[LoadProgramNV_remap_index], parameters)
+#define GET_LoadProgramNV(disp) GET_by_offset(disp, driDispatchRemapTable[LoadProgramNV_remap_index])
+#define SET_LoadProgramNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[LoadProgramNV_remap_index], fn)
+#define CALL_ProgramParameters4dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, const GLdouble *)), driDispatchRemapTable[ProgramParameters4dvNV_remap_index], parameters)
+#define GET_ProgramParameters4dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramParameters4dvNV_remap_index])
+#define SET_ProgramParameters4dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramParameters4dvNV_remap_index], fn)
+#define CALL_ProgramParameters4fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, const GLfloat *)), driDispatchRemapTable[ProgramParameters4fvNV_remap_index], parameters)
+#define GET_ProgramParameters4fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramParameters4fvNV_remap_index])
+#define SET_ProgramParameters4fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramParameters4fvNV_remap_index], fn)
+#define CALL_RequestResidentProgramsNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[RequestResidentProgramsNV_remap_index], parameters)
+#define GET_RequestResidentProgramsNV(disp) GET_by_offset(disp, driDispatchRemapTable[RequestResidentProgramsNV_remap_index])
+#define SET_RequestResidentProgramsNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[RequestResidentProgramsNV_remap_index], fn)
+#define CALL_TrackMatrixNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLenum, GLenum)), driDispatchRemapTable[TrackMatrixNV_remap_index], parameters)
+#define GET_TrackMatrixNV(disp) GET_by_offset(disp, driDispatchRemapTable[TrackMatrixNV_remap_index])
+#define SET_TrackMatrixNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TrackMatrixNV_remap_index], fn)
+#define CALL_VertexAttrib1dNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble)), driDispatchRemapTable[VertexAttrib1dNV_remap_index], parameters)
+#define GET_VertexAttrib1dNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dNV_remap_index])
+#define SET_VertexAttrib1dNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dNV_remap_index], fn)
+#define CALL_VertexAttrib1dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib1dvNV_remap_index], parameters)
+#define GET_VertexAttrib1dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dvNV_remap_index])
+#define SET_VertexAttrib1dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1dvNV_remap_index], fn)
+#define CALL_VertexAttrib1fNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat)), driDispatchRemapTable[VertexAttrib1fNV_remap_index], parameters)
+#define GET_VertexAttrib1fNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fNV_remap_index])
+#define SET_VertexAttrib1fNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fNV_remap_index], fn)
+#define CALL_VertexAttrib1fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib1fvNV_remap_index], parameters)
+#define GET_VertexAttrib1fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fvNV_remap_index])
+#define SET_VertexAttrib1fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1fvNV_remap_index], fn)
+#define CALL_VertexAttrib1sNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort)), driDispatchRemapTable[VertexAttrib1sNV_remap_index], parameters)
+#define GET_VertexAttrib1sNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1sNV_remap_index])
+#define SET_VertexAttrib1sNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1sNV_remap_index], fn)
+#define CALL_VertexAttrib1svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib1svNV_remap_index], parameters)
+#define GET_VertexAttrib1svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib1svNV_remap_index])
+#define SET_VertexAttrib1svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib1svNV_remap_index], fn)
+#define CALL_VertexAttrib2dNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib2dNV_remap_index], parameters)
+#define GET_VertexAttrib2dNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dNV_remap_index])
+#define SET_VertexAttrib2dNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dNV_remap_index], fn)
+#define CALL_VertexAttrib2dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib2dvNV_remap_index], parameters)
+#define GET_VertexAttrib2dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dvNV_remap_index])
+#define SET_VertexAttrib2dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2dvNV_remap_index], fn)
+#define CALL_VertexAttrib2fNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib2fNV_remap_index], parameters)
+#define GET_VertexAttrib2fNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fNV_remap_index])
+#define SET_VertexAttrib2fNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fNV_remap_index], fn)
+#define CALL_VertexAttrib2fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib2fvNV_remap_index], parameters)
+#define GET_VertexAttrib2fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fvNV_remap_index])
+#define SET_VertexAttrib2fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2fvNV_remap_index], fn)
+#define CALL_VertexAttrib2sNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib2sNV_remap_index], parameters)
+#define GET_VertexAttrib2sNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2sNV_remap_index])
+#define SET_VertexAttrib2sNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2sNV_remap_index], fn)
+#define CALL_VertexAttrib2svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib2svNV_remap_index], parameters)
+#define GET_VertexAttrib2svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib2svNV_remap_index])
+#define SET_VertexAttrib2svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib2svNV_remap_index], fn)
+#define CALL_VertexAttrib3dNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib3dNV_remap_index], parameters)
+#define GET_VertexAttrib3dNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dNV_remap_index])
+#define SET_VertexAttrib3dNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dNV_remap_index], fn)
+#define CALL_VertexAttrib3dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib3dvNV_remap_index], parameters)
+#define GET_VertexAttrib3dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dvNV_remap_index])
+#define SET_VertexAttrib3dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3dvNV_remap_index], fn)
+#define CALL_VertexAttrib3fNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib3fNV_remap_index], parameters)
+#define GET_VertexAttrib3fNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fNV_remap_index])
+#define SET_VertexAttrib3fNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fNV_remap_index], fn)
+#define CALL_VertexAttrib3fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib3fvNV_remap_index], parameters)
+#define GET_VertexAttrib3fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fvNV_remap_index])
+#define SET_VertexAttrib3fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3fvNV_remap_index], fn)
+#define CALL_VertexAttrib3sNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib3sNV_remap_index], parameters)
+#define GET_VertexAttrib3sNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3sNV_remap_index])
+#define SET_VertexAttrib3sNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3sNV_remap_index], fn)
+#define CALL_VertexAttrib3svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib3svNV_remap_index], parameters)
+#define GET_VertexAttrib3svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib3svNV_remap_index])
+#define SET_VertexAttrib3svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib3svNV_remap_index], fn)
+#define CALL_VertexAttrib4dNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[VertexAttrib4dNV_remap_index], parameters)
+#define GET_VertexAttrib4dNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dNV_remap_index])
+#define SET_VertexAttrib4dNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dNV_remap_index], fn)
+#define CALL_VertexAttrib4dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLdouble *)), driDispatchRemapTable[VertexAttrib4dvNV_remap_index], parameters)
+#define GET_VertexAttrib4dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dvNV_remap_index])
+#define SET_VertexAttrib4dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4dvNV_remap_index], fn)
+#define CALL_VertexAttrib4fNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[VertexAttrib4fNV_remap_index], parameters)
+#define GET_VertexAttrib4fNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fNV_remap_index])
+#define SET_VertexAttrib4fNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fNV_remap_index], fn)
+#define CALL_VertexAttrib4fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[VertexAttrib4fvNV_remap_index], parameters)
+#define GET_VertexAttrib4fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fvNV_remap_index])
+#define SET_VertexAttrib4fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4fvNV_remap_index], fn)
+#define CALL_VertexAttrib4sNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLshort, GLshort, GLshort, GLshort)), driDispatchRemapTable[VertexAttrib4sNV_remap_index], parameters)
+#define GET_VertexAttrib4sNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4sNV_remap_index])
+#define SET_VertexAttrib4sNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4sNV_remap_index], fn)
+#define CALL_VertexAttrib4svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLshort *)), driDispatchRemapTable[VertexAttrib4svNV_remap_index], parameters)
+#define GET_VertexAttrib4svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4svNV_remap_index])
+#define SET_VertexAttrib4svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4svNV_remap_index], fn)
+#define CALL_VertexAttrib4ubNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte)), driDispatchRemapTable[VertexAttrib4ubNV_remap_index], parameters)
+#define GET_VertexAttrib4ubNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubNV_remap_index])
+#define SET_VertexAttrib4ubNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubNV_remap_index], fn)
+#define CALL_VertexAttrib4ubvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLubyte *)), driDispatchRemapTable[VertexAttrib4ubvNV_remap_index], parameters)
+#define GET_VertexAttrib4ubvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubvNV_remap_index])
+#define SET_VertexAttrib4ubvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttrib4ubvNV_remap_index], fn)
+#define CALL_VertexAttribPointerNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLint, GLenum, GLsizei, const GLvoid *)), driDispatchRemapTable[VertexAttribPointerNV_remap_index], parameters)
+#define GET_VertexAttribPointerNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribPointerNV_remap_index])
+#define SET_VertexAttribPointerNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribPointerNV_remap_index], fn)
+#define CALL_VertexAttribs1dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLdouble *)), driDispatchRemapTable[VertexAttribs1dvNV_remap_index], parameters)
+#define GET_VertexAttribs1dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs1dvNV_remap_index])
+#define SET_VertexAttribs1dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs1dvNV_remap_index], fn)
+#define CALL_VertexAttribs1fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[VertexAttribs1fvNV_remap_index], parameters)
+#define GET_VertexAttribs1fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs1fvNV_remap_index])
+#define SET_VertexAttribs1fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs1fvNV_remap_index], fn)
+#define CALL_VertexAttribs1svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLshort *)), driDispatchRemapTable[VertexAttribs1svNV_remap_index], parameters)
+#define GET_VertexAttribs1svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs1svNV_remap_index])
+#define SET_VertexAttribs1svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs1svNV_remap_index], fn)
+#define CALL_VertexAttribs2dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLdouble *)), driDispatchRemapTable[VertexAttribs2dvNV_remap_index], parameters)
+#define GET_VertexAttribs2dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs2dvNV_remap_index])
+#define SET_VertexAttribs2dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs2dvNV_remap_index], fn)
+#define CALL_VertexAttribs2fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[VertexAttribs2fvNV_remap_index], parameters)
+#define GET_VertexAttribs2fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs2fvNV_remap_index])
+#define SET_VertexAttribs2fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs2fvNV_remap_index], fn)
+#define CALL_VertexAttribs2svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLshort *)), driDispatchRemapTable[VertexAttribs2svNV_remap_index], parameters)
+#define GET_VertexAttribs2svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs2svNV_remap_index])
+#define SET_VertexAttribs2svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs2svNV_remap_index], fn)
+#define CALL_VertexAttribs3dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLdouble *)), driDispatchRemapTable[VertexAttribs3dvNV_remap_index], parameters)
+#define GET_VertexAttribs3dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs3dvNV_remap_index])
+#define SET_VertexAttribs3dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs3dvNV_remap_index], fn)
+#define CALL_VertexAttribs3fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[VertexAttribs3fvNV_remap_index], parameters)
+#define GET_VertexAttribs3fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs3fvNV_remap_index])
+#define SET_VertexAttribs3fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs3fvNV_remap_index], fn)
+#define CALL_VertexAttribs3svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLshort *)), driDispatchRemapTable[VertexAttribs3svNV_remap_index], parameters)
+#define GET_VertexAttribs3svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs3svNV_remap_index])
+#define SET_VertexAttribs3svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs3svNV_remap_index], fn)
+#define CALL_VertexAttribs4dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLdouble *)), driDispatchRemapTable[VertexAttribs4dvNV_remap_index], parameters)
+#define GET_VertexAttribs4dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs4dvNV_remap_index])
+#define SET_VertexAttribs4dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs4dvNV_remap_index], fn)
+#define CALL_VertexAttribs4fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[VertexAttribs4fvNV_remap_index], parameters)
+#define GET_VertexAttribs4fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs4fvNV_remap_index])
+#define SET_VertexAttribs4fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs4fvNV_remap_index], fn)
+#define CALL_VertexAttribs4svNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLshort *)), driDispatchRemapTable[VertexAttribs4svNV_remap_index], parameters)
+#define GET_VertexAttribs4svNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs4svNV_remap_index])
+#define SET_VertexAttribs4svNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs4svNV_remap_index], fn)
+#define CALL_VertexAttribs4ubvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *)), driDispatchRemapTable[VertexAttribs4ubvNV_remap_index], parameters)
+#define GET_VertexAttribs4ubvNV(disp) GET_by_offset(disp, driDispatchRemapTable[VertexAttribs4ubvNV_remap_index])
+#define SET_VertexAttribs4ubvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[VertexAttribs4ubvNV_remap_index], fn)
+#define CALL_GetTexBumpParameterfvATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLfloat *)), driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index], parameters)
+#define GET_GetTexBumpParameterfvATI(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index])
+#define SET_GetTexBumpParameterfvATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index], fn)
+#define CALL_GetTexBumpParameterivATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint *)), driDispatchRemapTable[GetTexBumpParameterivATI_remap_index], parameters)
+#define GET_GetTexBumpParameterivATI(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterivATI_remap_index])
+#define SET_GetTexBumpParameterivATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexBumpParameterivATI_remap_index], fn)
+#define CALL_TexBumpParameterfvATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLfloat *)), driDispatchRemapTable[TexBumpParameterfvATI_remap_index], parameters)
+#define GET_TexBumpParameterfvATI(disp) GET_by_offset(disp, driDispatchRemapTable[TexBumpParameterfvATI_remap_index])
+#define SET_TexBumpParameterfvATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TexBumpParameterfvATI_remap_index], fn)
+#define CALL_TexBumpParameterivATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLint *)), driDispatchRemapTable[TexBumpParameterivATI_remap_index], parameters)
+#define GET_TexBumpParameterivATI(disp) GET_by_offset(disp, driDispatchRemapTable[TexBumpParameterivATI_remap_index])
+#define SET_TexBumpParameterivATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TexBumpParameterivATI_remap_index], fn)
+#define CALL_AlphaFragmentOp1ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index], parameters)
+#define GET_AlphaFragmentOp1ATI(disp) GET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index])
+#define SET_AlphaFragmentOp1ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index], fn)
+#define CALL_AlphaFragmentOp2ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[AlphaFragmentOp2ATI_remap_index], parameters)
+#define GET_AlphaFragmentOp2ATI(disp) GET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp2ATI_remap_index])
+#define SET_AlphaFragmentOp2ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp2ATI_remap_index], fn)
+#define CALL_AlphaFragmentOp3ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[AlphaFragmentOp3ATI_remap_index], parameters)
+#define GET_AlphaFragmentOp3ATI(disp) GET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp3ATI_remap_index])
+#define SET_AlphaFragmentOp3ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[AlphaFragmentOp3ATI_remap_index], fn)
+#define CALL_BeginFragmentShaderATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(void)), driDispatchRemapTable[BeginFragmentShaderATI_remap_index], parameters)
+#define GET_BeginFragmentShaderATI(disp) GET_by_offset(disp, driDispatchRemapTable[BeginFragmentShaderATI_remap_index])
+#define SET_BeginFragmentShaderATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BeginFragmentShaderATI_remap_index], fn)
+#define CALL_BindFragmentShaderATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[BindFragmentShaderATI_remap_index], parameters)
+#define GET_BindFragmentShaderATI(disp) GET_by_offset(disp, driDispatchRemapTable[BindFragmentShaderATI_remap_index])
+#define SET_BindFragmentShaderATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindFragmentShaderATI_remap_index], fn)
+#define CALL_ColorFragmentOp1ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[ColorFragmentOp1ATI_remap_index], parameters)
+#define GET_ColorFragmentOp1ATI(disp) GET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp1ATI_remap_index])
+#define SET_ColorFragmentOp1ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp1ATI_remap_index], fn)
+#define CALL_ColorFragmentOp2ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[ColorFragmentOp2ATI_remap_index], parameters)
+#define GET_ColorFragmentOp2ATI(disp) GET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp2ATI_remap_index])
+#define SET_ColorFragmentOp2ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp2ATI_remap_index], fn)
+#define CALL_ColorFragmentOp3ATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)), driDispatchRemapTable[ColorFragmentOp3ATI_remap_index], parameters)
+#define GET_ColorFragmentOp3ATI(disp) GET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp3ATI_remap_index])
+#define SET_ColorFragmentOp3ATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ColorFragmentOp3ATI_remap_index], fn)
+#define CALL_DeleteFragmentShaderATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[DeleteFragmentShaderATI_remap_index], parameters)
+#define GET_DeleteFragmentShaderATI(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteFragmentShaderATI_remap_index])
+#define SET_DeleteFragmentShaderATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteFragmentShaderATI_remap_index], fn)
+#define CALL_EndFragmentShaderATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(void)), driDispatchRemapTable[EndFragmentShaderATI_remap_index], parameters)
+#define GET_EndFragmentShaderATI(disp) GET_by_offset(disp, driDispatchRemapTable[EndFragmentShaderATI_remap_index])
+#define SET_EndFragmentShaderATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[EndFragmentShaderATI_remap_index], fn)
+#define CALL_GenFragmentShadersATI(disp, parameters) CALL_by_offset(disp, (GLuint (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[GenFragmentShadersATI_remap_index], parameters)
+#define GET_GenFragmentShadersATI(disp) GET_by_offset(disp, driDispatchRemapTable[GenFragmentShadersATI_remap_index])
+#define SET_GenFragmentShadersATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenFragmentShadersATI_remap_index], fn)
+#define CALL_PassTexCoordATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint, GLenum)), driDispatchRemapTable[PassTexCoordATI_remap_index], parameters)
+#define GET_PassTexCoordATI(disp) GET_by_offset(disp, driDispatchRemapTable[PassTexCoordATI_remap_index])
+#define SET_PassTexCoordATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PassTexCoordATI_remap_index], fn)
+#define CALL_SampleMapATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLuint, GLenum)), driDispatchRemapTable[SampleMapATI_remap_index], parameters)
+#define GET_SampleMapATI(disp) GET_by_offset(disp, driDispatchRemapTable[SampleMapATI_remap_index])
+#define SET_SampleMapATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SampleMapATI_remap_index], fn)
+#define CALL_SetFragmentShaderConstantATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, const GLfloat *)), driDispatchRemapTable[SetFragmentShaderConstantATI_remap_index], parameters)
+#define GET_SetFragmentShaderConstantATI(disp) GET_by_offset(disp, driDispatchRemapTable[SetFragmentShaderConstantATI_remap_index])
+#define SET_SetFragmentShaderConstantATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[SetFragmentShaderConstantATI_remap_index], fn)
+#define CALL_PointParameteriNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLint)), driDispatchRemapTable[PointParameteriNV_remap_index], parameters)
+#define GET_PointParameteriNV(disp) GET_by_offset(disp, driDispatchRemapTable[PointParameteriNV_remap_index])
+#define SET_PointParameteriNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PointParameteriNV_remap_index], fn)
+#define CALL_PointParameterivNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, const GLint *)), driDispatchRemapTable[PointParameterivNV_remap_index], parameters)
+#define GET_PointParameterivNV(disp) GET_by_offset(disp, driDispatchRemapTable[PointParameterivNV_remap_index])
+#define SET_PointParameterivNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[PointParameterivNV_remap_index], fn)
+#define CALL_ActiveStencilFaceEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[ActiveStencilFaceEXT_remap_index], parameters)
+#define GET_ActiveStencilFaceEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ActiveStencilFaceEXT_remap_index])
+#define SET_ActiveStencilFaceEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ActiveStencilFaceEXT_remap_index], fn)
+#define CALL_BindVertexArrayAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[BindVertexArrayAPPLE_remap_index], parameters)
+#define GET_BindVertexArrayAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[BindVertexArrayAPPLE_remap_index])
+#define SET_BindVertexArrayAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindVertexArrayAPPLE_remap_index], fn)
+#define CALL_DeleteVertexArraysAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteVertexArraysAPPLE_remap_index], parameters)
+#define GET_DeleteVertexArraysAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteVertexArraysAPPLE_remap_index])
+#define SET_DeleteVertexArraysAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteVertexArraysAPPLE_remap_index], fn)
+#define CALL_GenVertexArraysAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenVertexArraysAPPLE_remap_index], parameters)
+#define GET_GenVertexArraysAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[GenVertexArraysAPPLE_remap_index])
+#define SET_GenVertexArraysAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenVertexArraysAPPLE_remap_index], fn)
+#define CALL_IsVertexArrayAPPLE(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsVertexArrayAPPLE_remap_index], parameters)
+#define GET_IsVertexArrayAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[IsVertexArrayAPPLE_remap_index])
+#define SET_IsVertexArrayAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsVertexArrayAPPLE_remap_index], fn)
+#define CALL_GetProgramNamedParameterdvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, GLdouble *)), driDispatchRemapTable[GetProgramNamedParameterdvNV_remap_index], parameters)
+#define GET_GetProgramNamedParameterdvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramNamedParameterdvNV_remap_index])
+#define SET_GetProgramNamedParameterdvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramNamedParameterdvNV_remap_index], fn)
+#define CALL_GetProgramNamedParameterfvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, GLfloat *)), driDispatchRemapTable[GetProgramNamedParameterfvNV_remap_index], parameters)
+#define GET_GetProgramNamedParameterfvNV(disp) GET_by_offset(disp, driDispatchRemapTable[GetProgramNamedParameterfvNV_remap_index])
+#define SET_GetProgramNamedParameterfvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetProgramNamedParameterfvNV_remap_index], fn)
+#define CALL_ProgramNamedParameter4dNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble)), driDispatchRemapTable[ProgramNamedParameter4dNV_remap_index], parameters)
+#define GET_ProgramNamedParameter4dNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4dNV_remap_index])
+#define SET_ProgramNamedParameter4dNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4dNV_remap_index], fn)
+#define CALL_ProgramNamedParameter4dvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, const GLdouble *)), driDispatchRemapTable[ProgramNamedParameter4dvNV_remap_index], parameters)
+#define GET_ProgramNamedParameter4dvNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4dvNV_remap_index])
+#define SET_ProgramNamedParameter4dvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4dvNV_remap_index], fn)
+#define CALL_ProgramNamedParameter4fNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat)), driDispatchRemapTable[ProgramNamedParameter4fNV_remap_index], parameters)
+#define GET_ProgramNamedParameter4fNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4fNV_remap_index])
+#define SET_ProgramNamedParameter4fNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4fNV_remap_index], fn)
+#define CALL_ProgramNamedParameter4fvNV(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLsizei, const GLubyte *, const GLfloat *)), driDispatchRemapTable[ProgramNamedParameter4fvNV_remap_index], parameters)
+#define GET_ProgramNamedParameter4fvNV(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4fvNV_remap_index])
+#define SET_ProgramNamedParameter4fvNV(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramNamedParameter4fvNV_remap_index], fn)
+#define CALL_DepthBoundsEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLclampd, GLclampd)), driDispatchRemapTable[DepthBoundsEXT_remap_index], parameters)
+#define GET_DepthBoundsEXT(disp) GET_by_offset(disp, driDispatchRemapTable[DepthBoundsEXT_remap_index])
+#define SET_DepthBoundsEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DepthBoundsEXT_remap_index], fn)
+#define CALL_BlendEquationSeparateEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum)), driDispatchRemapTable[BlendEquationSeparateEXT_remap_index], parameters)
+#define GET_BlendEquationSeparateEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlendEquationSeparateEXT_remap_index])
+#define SET_BlendEquationSeparateEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlendEquationSeparateEXT_remap_index], fn)
+#define CALL_BindFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[BindFramebufferEXT_remap_index], parameters)
+#define GET_BindFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BindFramebufferEXT_remap_index])
+#define SET_BindFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindFramebufferEXT_remap_index], fn)
+#define CALL_BindRenderbufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint)), driDispatchRemapTable[BindRenderbufferEXT_remap_index], parameters)
+#define GET_BindRenderbufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BindRenderbufferEXT_remap_index])
+#define SET_BindRenderbufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BindRenderbufferEXT_remap_index], fn)
+#define CALL_CheckFramebufferStatusEXT(disp, parameters) CALL_by_offset(disp, (GLenum (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[CheckFramebufferStatusEXT_remap_index], parameters)
+#define GET_CheckFramebufferStatusEXT(disp) GET_by_offset(disp, driDispatchRemapTable[CheckFramebufferStatusEXT_remap_index])
+#define SET_CheckFramebufferStatusEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[CheckFramebufferStatusEXT_remap_index], fn)
+#define CALL_DeleteFramebuffersEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteFramebuffersEXT_remap_index], parameters)
+#define GET_DeleteFramebuffersEXT(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteFramebuffersEXT_remap_index])
+#define SET_DeleteFramebuffersEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteFramebuffersEXT_remap_index], fn)
+#define CALL_DeleteRenderbuffersEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, const GLuint *)), driDispatchRemapTable[DeleteRenderbuffersEXT_remap_index], parameters)
+#define GET_DeleteRenderbuffersEXT(disp) GET_by_offset(disp, driDispatchRemapTable[DeleteRenderbuffersEXT_remap_index])
+#define SET_DeleteRenderbuffersEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[DeleteRenderbuffersEXT_remap_index], fn)
+#define CALL_FramebufferRenderbufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLuint)), driDispatchRemapTable[FramebufferRenderbufferEXT_remap_index], parameters)
+#define GET_FramebufferRenderbufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferRenderbufferEXT_remap_index])
+#define SET_FramebufferRenderbufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferRenderbufferEXT_remap_index], fn)
+#define CALL_FramebufferTexture1DEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint)), driDispatchRemapTable[FramebufferTexture1DEXT_remap_index], parameters)
+#define GET_FramebufferTexture1DEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferTexture1DEXT_remap_index])
+#define SET_FramebufferTexture1DEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferTexture1DEXT_remap_index], fn)
+#define CALL_FramebufferTexture2DEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint)), driDispatchRemapTable[FramebufferTexture2DEXT_remap_index], parameters)
+#define GET_FramebufferTexture2DEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferTexture2DEXT_remap_index])
+#define SET_FramebufferTexture2DEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferTexture2DEXT_remap_index], fn)
+#define CALL_FramebufferTexture3DEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLint)), driDispatchRemapTable[FramebufferTexture3DEXT_remap_index], parameters)
+#define GET_FramebufferTexture3DEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferTexture3DEXT_remap_index])
+#define SET_FramebufferTexture3DEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferTexture3DEXT_remap_index], fn)
+#define CALL_GenFramebuffersEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenFramebuffersEXT_remap_index], parameters)
+#define GET_GenFramebuffersEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GenFramebuffersEXT_remap_index])
+#define SET_GenFramebuffersEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenFramebuffersEXT_remap_index], fn)
+#define CALL_GenRenderbuffersEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLsizei, GLuint *)), driDispatchRemapTable[GenRenderbuffersEXT_remap_index], parameters)
+#define GET_GenRenderbuffersEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GenRenderbuffersEXT_remap_index])
+#define SET_GenRenderbuffersEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenRenderbuffersEXT_remap_index], fn)
+#define CALL_GenerateMipmapEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[GenerateMipmapEXT_remap_index], parameters)
+#define GET_GenerateMipmapEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GenerateMipmapEXT_remap_index])
+#define SET_GenerateMipmapEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GenerateMipmapEXT_remap_index], fn)
+#define CALL_GetFramebufferAttachmentParameterivEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLenum, GLint *)), driDispatchRemapTable[GetFramebufferAttachmentParameterivEXT_remap_index], parameters)
+#define GET_GetFramebufferAttachmentParameterivEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetFramebufferAttachmentParameterivEXT_remap_index])
+#define SET_GetFramebufferAttachmentParameterivEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetFramebufferAttachmentParameterivEXT_remap_index], fn)
+#define CALL_GetRenderbufferParameterivEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint *)), driDispatchRemapTable[GetRenderbufferParameterivEXT_remap_index], parameters)
+#define GET_GetRenderbufferParameterivEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetRenderbufferParameterivEXT_remap_index])
+#define SET_GetRenderbufferParameterivEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetRenderbufferParameterivEXT_remap_index], fn)
+#define CALL_IsFramebufferEXT(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsFramebufferEXT_remap_index], parameters)
+#define GET_IsFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[IsFramebufferEXT_remap_index])
+#define SET_IsFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsFramebufferEXT_remap_index], fn)
+#define CALL_IsRenderbufferEXT(disp, parameters) CALL_by_offset(disp, (GLboolean (GLAPIENTRYP)(GLuint)), driDispatchRemapTable[IsRenderbufferEXT_remap_index], parameters)
+#define GET_IsRenderbufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[IsRenderbufferEXT_remap_index])
+#define SET_IsRenderbufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[IsRenderbufferEXT_remap_index], fn)
+#define CALL_RenderbufferStorageEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLsizei, GLsizei)), driDispatchRemapTable[RenderbufferStorageEXT_remap_index], parameters)
+#define GET_RenderbufferStorageEXT(disp) GET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageEXT_remap_index])
+#define SET_RenderbufferStorageEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[RenderbufferStorageEXT_remap_index], fn)
+#define CALL_BlitFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)), driDispatchRemapTable[BlitFramebufferEXT_remap_index], parameters)
+#define GET_BlitFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index])
+#define SET_BlitFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index], fn)
+#define CALL_BufferParameteriAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint)), driDispatchRemapTable[BufferParameteriAPPLE_remap_index], parameters)
+#define GET_BufferParameteriAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[BufferParameteriAPPLE_remap_index])
+#define SET_BufferParameteriAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BufferParameteriAPPLE_remap_index], fn)
+#define CALL_FlushMappedBufferRangeAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLintptr, GLsizeiptr)), driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index], parameters)
+#define GET_FlushMappedBufferRangeAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index])
+#define SET_FlushMappedBufferRangeAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index], fn)
+#define CALL_FramebufferTextureLayerEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint)), driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index], parameters)
+#define GET_FramebufferTextureLayerEXT(disp) GET_by_offset(disp, driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index])
+#define SET_FramebufferTextureLayerEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index], fn)
+#define CALL_ProvokingVertexEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum)), driDispatchRemapTable[ProvokingVertexEXT_remap_index], parameters)
+#define GET_ProvokingVertexEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ProvokingVertexEXT_remap_index])
+#define SET_ProvokingVertexEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProvokingVertexEXT_remap_index], fn)
+#define CALL_GetTexParameterPointervAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLvoid **)), driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index], parameters)
+#define GET_GetTexParameterPointervAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index])
+#define SET_GetTexParameterPointervAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index], fn)
+#define CALL_TextureRangeAPPLE(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLsizei, GLvoid *)), driDispatchRemapTable[TextureRangeAPPLE_remap_index], parameters)
+#define GET_TextureRangeAPPLE(disp) GET_by_offset(disp, driDispatchRemapTable[TextureRangeAPPLE_remap_index])
+#define SET_TextureRangeAPPLE(disp, fn) SET_by_offset(disp, driDispatchRemapTable[TextureRangeAPPLE_remap_index], fn)
+#define CALL_StencilFuncSeparateATI(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLenum, GLint, GLuint)), driDispatchRemapTable[StencilFuncSeparateATI_remap_index], parameters)
+#define GET_StencilFuncSeparateATI(disp) GET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparateATI_remap_index])
+#define SET_StencilFuncSeparateATI(disp, fn) SET_by_offset(disp, driDispatchRemapTable[StencilFuncSeparateATI_remap_index], fn)
+#define CALL_ProgramEnvParameters4fvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[ProgramEnvParameters4fvEXT_remap_index], parameters)
+#define GET_ProgramEnvParameters4fvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameters4fvEXT_remap_index])
+#define SET_ProgramEnvParameters4fvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramEnvParameters4fvEXT_remap_index], fn)
+#define CALL_ProgramLocalParameters4fvEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLenum, GLuint, GLsizei, const GLfloat *)), driDispatchRemapTable[ProgramLocalParameters4fvEXT_remap_index], parameters)
+#define GET_ProgramLocalParameters4fvEXT(disp) GET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameters4fvEXT_remap_index])
+#define SET_ProgramLocalParameters4fvEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[ProgramLocalParameters4fvEXT_remap_index], fn)
+#define CALL_GetQueryObjecti64vEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLint64EXT *)), driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index], parameters)
+#define GET_GetQueryObjecti64vEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index])
+#define SET_GetQueryObjecti64vEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index], fn)
+#define CALL_GetQueryObjectui64vEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLuint64EXT *)), driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], parameters)
+#define GET_GetQueryObjectui64vEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index])
+#define SET_GetQueryObjectui64vEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], fn)
+
+#endif /* !defined(IN_DRI_DRIVER) */
+
+#endif /* !defined( _DISPATCH_H_ ) */
diff --git a/mesalib/src/mesa/glapi/glapi.c b/mesalib/src/mesa/glapi/glapi.c
new file mode 100644
index 000000000..e36fccb35
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapi.c
@@ -0,0 +1,650 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/*
+ * This file manages the OpenGL API dispatch layer.
+ * The dispatch table (struct _glapi_table) is basically just a list
+ * of function pointers.
+ * There are functions to set/get the current dispatch table for the
+ * current thread and to manage registration/dispatch of dynamically
+ * added extension functions.
+ *
+ * It's intended that this file and the other glapi*.[ch] files are
+ * flexible enough to be reused in several places: XFree86, DRI-
+ * based libGL.so, and perhaps the SGI SI.
+ *
+ * NOTE: There are no dependencies on Mesa in this code.
+ *
+ * Versions (API changes):
+ * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0
+ * 2001/01/16 - added dispatch override feature for Mesa 3.5
+ * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1.
+ * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints
+ * itself (using offset ~0). _glapi_add_entrypoint() can be
+ * called afterward and it'll fill in the correct dispatch
+ * offset. This allows DRI libGL to avoid probing for DRI
+ * drivers! No changes to the public glapi interface.
+ */
+
+
+
+#ifdef HAVE_DIX_CONFIG_H
+
+#include <dix-config.h>
+#define PUBLIC
+
+#else
+
+#include "main/glheader.h"
+
+#endif
+
+#include "main/compiler.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include "glapi.h"
+#include "glapioffsets.h"
+#include "glapitable.h"
+
+
+/***** BEGIN NO-OP DISPATCH *****/
+
+static GLboolean WarnFlag = GL_FALSE;
+static _glapi_warning_func warning_func;
+
+/*
+ * Enable/disable printing of warning messages.
+ */
+PUBLIC void
+_glapi_noop_enable_warnings(GLboolean enable)
+{
+ WarnFlag = enable;
+}
+
+/*
+ * Register a callback function for reporting errors.
+ */
+PUBLIC void
+_glapi_set_warning_func( _glapi_warning_func func )
+{
+ warning_func = func;
+}
+
+static GLboolean
+warn(void)
+{
+#if !defined(_WIN32_WCE)
+ if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
+ && warning_func) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+#else
+ return GL_FALSE;
+#endif
+}
+
+
+#define KEYWORD1 static
+#define KEYWORD1_ALT static
+#define KEYWORD2 GLAPIENTRY
+#define NAME(func) NoOp##func
+
+#define F NULL
+
+#define DISPATCH(func, args, msg) \
+ if (warn()) { \
+ warning_func(NULL, "GL User Error: called without context: %s", #func); \
+ }
+
+#define RETURN_DISPATCH(func, args, msg) \
+ if (warn()) { \
+ warning_func(NULL, "GL User Error: called without context: %s", #func); \
+ } \
+ return 0
+
+#define DISPATCH_TABLE_NAME __glapi_noop_table
+#define UNUSED_TABLE_NAME __unused_noop_functions
+
+#define TABLE_ENTRY(name) (_glapi_proc) NoOp##name
+
+static GLint NoOpUnused(void)
+{
+ if (warn()) {
+ warning_func(NULL, "GL User Error: calling extension function without a current context\n");
+ }
+ return 0;
+}
+
+#include "glapitemp.h"
+
+/***** END NO-OP DISPATCH *****/
+
+
+
+/**
+ * \name Current dispatch and current context control variables
+ *
+ * Depending on whether or not multithreading is support, and the type of
+ * support available, several variables are used to store the current context
+ * pointer and the current dispatch table pointer. In the non-threaded case,
+ * the variables \c _glapi_Dispatch and \c _glapi_Context are used for this
+ * purpose.
+ *
+ * In the "normal" threaded case, the variables \c _glapi_Dispatch and
+ * \c _glapi_Context will be \c NULL if an application is detected as being
+ * multithreaded. Single-threaded applications will use \c _glapi_Dispatch
+ * and \c _glapi_Context just like the case without any threading support.
+ * When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state
+ * data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the
+ * static dispatch functions access these variables via \c _glapi_get_dispatch
+ * and \c _glapi_get_context.
+ *
+ * There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is
+ * possible for the original thread to be setting it at the same instant a new
+ * thread, perhaps running on a different processor, is clearing it. Because
+ * of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is
+ * used to determine whether or not the application is multithreaded.
+ *
+ * In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are
+ * hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and
+ * \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and
+ * \c _glapi_Context be hardcoded to \c NULL maintains binary compatability
+ * between TLS enabled loaders and non-TLS DRI drivers.
+ */
+/*@{*/
+#if defined(GLX_USE_TLS)
+
+PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch
+ __attribute__((tls_model("initial-exec")))
+ = (struct _glapi_table *) __glapi_noop_table;
+
+PUBLIC __thread void * _glapi_tls_Context
+ __attribute__((tls_model("initial-exec")));
+
+PUBLIC const struct _glapi_table *_glapi_Dispatch = NULL;
+PUBLIC const void *_glapi_Context = NULL;
+
+#else
+
+#if defined(THREADS)
+
+#ifdef WIN32_THREADS
+/* _glthread_DECLARE_STATIC_MUTEX is broken on windows. There will be race! */
+#define CHECK_MULTITHREAD_LOCK()
+#define CHECK_MULTITHREAD_UNLOCK()
+#else
+_glthread_DECLARE_STATIC_MUTEX(ThreadCheckMutex);
+#define CHECK_MULTITHREAD_LOCK() _glthread_LOCK_MUTEX(ThreadCheckMutex)
+#define CHECK_MULTITHREAD_UNLOCK() _glthread_UNLOCK_MUTEX(ThreadCheckMutex)
+#endif
+
+static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
+_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
+static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
+
+#if defined(WIN32_THREADS)
+void FreeTSD(_glthread_TSD *p);
+void FreeAllTSD(void)
+{
+ FreeTSD(&_gl_DispatchTSD);
+ FreeTSD(&ContextTSD);
+}
+#endif /* defined(WIN32_THREADS) */
+
+#endif /* defined(THREADS) */
+
+PUBLIC struct _glapi_table *_glapi_Dispatch =
+ (struct _glapi_table *) __glapi_noop_table;
+PUBLIC void *_glapi_Context = NULL;
+
+#endif /* defined(GLX_USE_TLS) */
+/*@}*/
+
+
+
+
+/**
+ * We should call this periodically from a function such as glXMakeCurrent
+ * in order to test if multiple threads are being used.
+ */
+void
+_glapi_check_multithread(void)
+{
+#if defined(THREADS) && !defined(GLX_USE_TLS)
+ static unsigned long knownID;
+ static GLboolean firstCall = GL_TRUE;
+
+ if (ThreadSafe)
+ return;
+
+ CHECK_MULTITHREAD_LOCK();
+ if (firstCall) {
+ /* initialize TSDs */
+ (void) _glthread_GetTSD(&ContextTSD);
+ (void) _glthread_GetTSD(&_gl_DispatchTSD);
+
+ knownID = _glthread_GetID();
+ firstCall = GL_FALSE;
+ }
+ else if (knownID != _glthread_GetID()) {
+ ThreadSafe = GL_TRUE;
+ _glapi_set_dispatch(NULL);
+ _glapi_set_context(NULL);
+ }
+ CHECK_MULTITHREAD_UNLOCK();
+#endif
+}
+
+
+
+/**
+ * Set the current context pointer for this thread.
+ * The context pointer is an opaque type which should be cast to
+ * void from the real context pointer type.
+ */
+PUBLIC void
+_glapi_set_context(void *context)
+{
+ (void) __unused_noop_functions; /* silence a warning */
+#if defined(GLX_USE_TLS)
+ _glapi_tls_Context = context;
+#elif defined(THREADS)
+ _glthread_SetTSD(&ContextTSD, context);
+ _glapi_Context = (ThreadSafe) ? NULL : context;
+#else
+ _glapi_Context = context;
+#endif
+}
+
+
+
+/**
+ * Get the current context pointer for this thread.
+ * The context pointer is an opaque type which should be cast from
+ * void to the real context pointer type.
+ */
+PUBLIC void *
+_glapi_get_context(void)
+{
+#if defined(GLX_USE_TLS)
+ return _glapi_tls_Context;
+#elif defined(THREADS)
+ if (ThreadSafe) {
+ return _glthread_GetTSD(&ContextTSD);
+ }
+ else {
+ return _glapi_Context;
+ }
+#else
+ return _glapi_Context;
+#endif
+}
+
+#ifdef USE_X86_ASM
+
+#if defined( GLX_USE_TLS )
+extern GLubyte gl_dispatch_functions_start[];
+extern GLubyte gl_dispatch_functions_end[];
+#else
+extern const GLubyte gl_dispatch_functions_start[];
+#endif
+
+#endif /* USE_X86_ASM */
+
+
+#if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 16
+#elif defined(USE_X86_ASM)
+# if defined(THREADS) && !defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 32
+# else
+# define DISPATCH_FUNCTION_SIZE 16
+# endif
+#endif
+
+#ifdef USE_SPARC_ASM
+#ifdef GLX_USE_TLS
+extern unsigned int __glapi_sparc_tls_stub;
+#else
+extern unsigned int __glapi_sparc_pthread_stub;
+#endif
+#endif
+
+#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer)
+# define NEED_FUNCTION_POINTER
+#endif
+
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+/**
+ * Perform platform-specific GL API entry-point fixups.
+ */
+static void
+init_glapi_relocs( void )
+{
+#if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
+ extern unsigned long _x86_get_dispatch(void);
+ char run_time_patch[] = {
+ 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */
+ };
+ GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */
+ const GLubyte * const get_disp = (const GLubyte *) run_time_patch;
+ GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start;
+
+ *offset = _x86_get_dispatch();
+ while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) {
+ (void) memcpy( curr_func, get_disp, sizeof(run_time_patch));
+ curr_func += DISPATCH_FUNCTION_SIZE;
+ }
+#endif
+#ifdef USE_SPARC_ASM
+ extern void __glapi_sparc_icache_flush(unsigned int *);
+ static const unsigned int template[] = {
+#ifdef GLX_USE_TLS
+ 0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */
+ 0x8730e00a, /* srl %g3, 10, %g3 */
+ 0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */
+#ifdef __arch64__
+ 0xc259c002, /* ldx [%g7 + %g2], %g1 */
+ 0xc2584003, /* ldx [%g1 + %g3], %g1 */
+#else
+ 0xc201c002, /* ld [%g7 + %g2], %g1 */
+ 0xc2004003, /* ld [%g1 + %g3], %g1 */
+#endif
+ 0x81c04000, /* jmp %g1 */
+ 0x01000000, /* nop */
+#else
+#ifdef __arch64__
+ 0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */
+ 0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */
+ 0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */
+ 0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */
+ 0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */
+ 0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */
+ 0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#else
+ 0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */
+ 0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */
+ 0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
+#endif
+ 0x80a06000, /* --> cmp %g1, 0 */
+ 0x02800005, /* --> be +4*5 */
+ 0x01000000, /* --> nop */
+#ifdef __arch64__
+ 0xc2584003, /* 64-bit --> ldx [%g1 + %g3], %g1 */
+#else
+ 0xc2004003, /* 32-bit --> ld [%g1 + %g3], %g1 */
+#endif
+ 0x81c04000, /* --> jmp %g1 */
+ 0x01000000, /* --> nop */
+#ifdef __arch64__
+ 0x9de3bf80, /* 64-bit --> save %sp, -128, %sp */
+#else
+ 0x9de3bfc0, /* 32-bit --> save %sp, -64, %sp */
+#endif
+ 0xa0100003, /* --> mov %g3, %l0 */
+ 0x40000000, /* --> call _glapi_get_dispatch */
+ 0x01000000, /* --> nop */
+ 0x82100008, /* --> mov %o0, %g1 */
+ 0x86100010, /* --> mov %l0, %g3 */
+ 0x10bffff7, /* --> ba -4*9 */
+ 0x81e80000, /* --> restore */
+#endif
+ };
+#ifdef GLX_USE_TLS
+ extern unsigned long __glapi_sparc_get_dispatch(void);
+ unsigned int *code = &__glapi_sparc_tls_stub;
+ unsigned long dispatch = __glapi_sparc_get_dispatch();
+#else
+ unsigned int *code = &__glapi_sparc_pthread_stub;
+ unsigned long dispatch = (unsigned long) &_glapi_Dispatch;
+ unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch;
+ int idx;
+#endif
+
+#if defined(GLX_USE_TLS)
+ code[0] = template[0] | (dispatch >> 10);
+ code[1] = template[1];
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | (dispatch & 0x3ff);
+ code[3] = template[3];
+ __glapi_sparc_icache_flush(&code[2]);
+ code[4] = template[4];
+ code[5] = template[5];
+ __glapi_sparc_icache_flush(&code[4]);
+ code[6] = template[6];
+ __glapi_sparc_icache_flush(&code[6]);
+#else
+#if defined(__arch64__)
+ code[0] = template[0] | (dispatch >> (32 + 10));
+ code[1] = template[1] | ((dispatch & 0xffffffff) >> 10);
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | ((dispatch >> 32) & 0x3ff);
+ code[3] = template[3];
+ __glapi_sparc_icache_flush(&code[2]);
+ code[4] = template[4];
+ code[5] = template[5];
+ __glapi_sparc_icache_flush(&code[4]);
+ code[6] = template[6] | (dispatch & 0x3ff);
+ idx = 7;
+#else
+ code[0] = template[0] | (dispatch >> 10);
+ code[1] = template[1];
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] | (dispatch & 0x3ff);
+ idx = 3;
+#endif
+ code[idx + 0] = template[idx + 0];
+ __glapi_sparc_icache_flush(&code[idx - 1]);
+ code[idx + 1] = template[idx + 1];
+ code[idx + 2] = template[idx + 2];
+ __glapi_sparc_icache_flush(&code[idx + 1]);
+ code[idx + 3] = template[idx + 3];
+ code[idx + 4] = template[idx + 4];
+ __glapi_sparc_icache_flush(&code[idx + 3]);
+ code[idx + 5] = template[idx + 5];
+ code[idx + 6] = template[idx + 6];
+ __glapi_sparc_icache_flush(&code[idx + 5]);
+ code[idx + 7] = template[idx + 7];
+ code[idx + 8] = template[idx + 8] |
+ (((call_dest - ((unsigned long) &code[idx + 8]))
+ >> 2) & 0x3fffffff);
+ __glapi_sparc_icache_flush(&code[idx + 7]);
+ code[idx + 9] = template[idx + 9];
+ code[idx + 10] = template[idx + 10];
+ __glapi_sparc_icache_flush(&code[idx + 9]);
+ code[idx + 11] = template[idx + 11];
+ code[idx + 12] = template[idx + 12];
+ __glapi_sparc_icache_flush(&code[idx + 11]);
+ code[idx + 13] = template[idx + 13];
+ __glapi_sparc_icache_flush(&code[idx + 13]);
+#endif
+#endif
+}
+#endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */
+
+
+/**
+ * Set the global or per-thread dispatch table pointer.
+ * If the dispatch parameter is NULL we'll plug in the no-op dispatch
+ * table (__glapi_noop_table).
+ */
+PUBLIC void
+_glapi_set_dispatch(struct _glapi_table *dispatch)
+{
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+ pthread_once( & once_control, init_glapi_relocs );
+#endif
+
+ if (!dispatch) {
+ /* use the no-op functions */
+ dispatch = (struct _glapi_table *) __glapi_noop_table;
+ }
+#ifdef DEBUG
+ else {
+ _glapi_check_table(dispatch);
+ }
+#endif
+
+#if defined(GLX_USE_TLS)
+ _glapi_tls_Dispatch = dispatch;
+#elif defined(THREADS)
+ _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
+ _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch;
+#else /*THREADS*/
+ _glapi_Dispatch = dispatch;
+#endif /*THREADS*/
+}
+
+
+
+/**
+ * Return pointer to current dispatch table for calling thread.
+ */
+PUBLIC struct _glapi_table *
+_glapi_get_dispatch(void)
+{
+ struct _glapi_table * api;
+#if defined(GLX_USE_TLS)
+ api = _glapi_tls_Dispatch;
+#elif defined(THREADS)
+ api = (ThreadSafe)
+ ? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD)
+ : _glapi_Dispatch;
+#else
+ api = _glapi_Dispatch;
+#endif
+ return api;
+}
+
+
+
+
+/*
+ * The dispatch table size (number of entries) is the size of the
+ * _glapi_table struct plus the number of dynamic entries we can add.
+ * The extra slots can be filled in by DRI drivers that register new extension
+ * functions.
+ */
+#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
+
+
+/**
+ * Return size of dispatch table struct as number of functions (or
+ * slots).
+ */
+PUBLIC GLuint
+_glapi_get_dispatch_table_size(void)
+{
+ return DISPATCH_TABLE_SIZE;
+}
+
+
+/**
+ * Make sure there are no NULL pointers in the given dispatch table.
+ * Intended for debugging purposes.
+ */
+void
+_glapi_check_table(const struct _glapi_table *table)
+{
+#ifdef EXTRA_DEBUG
+ const GLuint entries = _glapi_get_dispatch_table_size();
+ const void **tab = (const void **) table;
+ GLuint i;
+ for (i = 1; i < entries; i++) {
+ assert(tab[i]);
+ }
+
+ /* Do some spot checks to be sure that the dispatch table
+ * slots are assigned correctly.
+ */
+ {
+ GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
+ char *BeginFunc = (char*) &table->Begin;
+ GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
+ assert(BeginOffset == _gloffset_Begin);
+ assert(BeginOffset == offset);
+ }
+ {
+ GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
+ char *viewportFunc = (char*) &table->Viewport;
+ GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
+ assert(viewportOffset == _gloffset_Viewport);
+ assert(viewportOffset == offset);
+ }
+ {
+ GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
+ char *VertexPointerFunc = (char*) &table->VertexPointer;
+ GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
+ assert(VertexPointerOffset == _gloffset_VertexPointer);
+ assert(VertexPointerOffset == offset);
+ }
+ {
+ GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
+ char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
+ GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
+ assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
+ assert(ResetMinMaxOffset == offset);
+ }
+ {
+ GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
+ char *blendColorFunc = (char*) &table->BlendColor;
+ GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
+ assert(blendColorOffset == _gloffset_BlendColor);
+ assert(blendColorOffset == offset);
+ }
+ {
+ GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
+ char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
+ GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
+ assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
+ assert(secondaryColor3fOffset == offset);
+ }
+ {
+ GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
+ char *pointParameterivFunc = (char*) &table->PointParameterivNV;
+ GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
+ assert(pointParameterivOffset == _gloffset_PointParameterivNV);
+ assert(pointParameterivOffset == offset);
+ }
+ {
+ GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
+ char *setFenceFunc = (char*) &table->SetFenceNV;
+ GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
+ assert(setFenceOffset == _gloffset_SetFenceNV);
+ assert(setFenceOffset == offset);
+ }
+#else
+ (void) table;
+#endif
+}
diff --git a/mesalib/src/mesa/glapi/glapi.h b/mesalib/src/mesa/glapi/glapi.h
new file mode 100644
index 000000000..5fb540122
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapi.h
@@ -0,0 +1,171 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \mainpage Mesa GL API Module
+ *
+ * \section GLAPIIntroduction Introduction
+ *
+ * The Mesa GL API module is responsible for dispatching all the
+ * gl*() functions. All GL functions are dispatched by jumping through
+ * the current dispatch table (basically a struct full of function
+ * pointers.)
+ *
+ * A per-thread current dispatch table and per-thread current context
+ * pointer are managed by this module too.
+ *
+ * This module is intended to be non-Mesa-specific so it can be used
+ * with the X/DRI libGL also.
+ */
+
+
+#ifndef _GLAPI_H
+#define _GLAPI_H
+
+#define GL_GLEXT_PROTOTYPES
+
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "glthread.h"
+
+
+struct _glapi_table;
+
+typedef void (*_glapi_proc)(void); /* generic function pointer */
+
+typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...);
+
+
+#if defined(USE_MGL_NAMESPACE)
+#define _glapi_set_dispatch _mglapi_set_dispatch
+#define _glapi_get_dispatch _mglapi_get_dispatch
+#define _glapi_set_context _mglapi_set_context
+#define _glapi_get_context _mglapi_get_context
+#define _glapi_Context _mglapi_Context
+#define _glapi_Dispatch _mglapi_Dispatch
+#endif
+
+
+/*
+ * Number of extension functions which we can dynamically add at runtime.
+ */
+#define MAX_EXTENSION_FUNCS 300
+
+
+/**
+ ** Define the GET_CURRENT_CONTEXT() macro.
+ ** \param C local variable which will hold the current context.
+ **/
+#if defined (GLX_USE_TLS)
+
+extern const void *_glapi_Context;
+extern const struct _glapi_table *_glapi_Dispatch;
+
+extern __thread void * _glapi_tls_Context
+ __attribute__((tls_model("initial-exec")));
+
+# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) _glapi_tls_Context
+
+#else
+
+extern void *_glapi_Context;
+extern struct _glapi_table *_glapi_Dispatch;
+
+# ifdef THREADS
+# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())
+# else
+# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) _glapi_Context
+# endif
+
+#endif /* defined (GLX_USE_TLS) */
+
+
+/**
+ ** GL API public functions
+ **/
+
+extern void
+_glapi_noop_enable_warnings(GLboolean enable);
+
+extern void
+_glapi_set_warning_func(_glapi_warning_func func);
+
+extern void
+_glapi_check_multithread(void);
+
+
+extern void
+_glapi_set_context(void *context);
+
+
+extern void *
+_glapi_get_context(void);
+
+
+extern void
+_glapi_set_dispatch(struct _glapi_table *dispatch);
+
+
+extern struct _glapi_table *
+_glapi_get_dispatch(void);
+
+
+extern int
+_glapi_begin_dispatch_override(struct _glapi_table *override);
+
+
+extern void
+_glapi_end_dispatch_override(int layer);
+
+
+struct _glapi_table *
+_glapi_get_override_dispatch(int layer);
+
+
+extern GLuint
+_glapi_get_dispatch_table_size(void);
+
+
+extern void
+_glapi_check_table(const struct _glapi_table *table);
+
+
+extern int
+_glapi_add_dispatch( const char * const * function_names,
+ const char * parameter_signature );
+
+extern GLint
+_glapi_get_proc_offset(const char *funcName);
+
+
+extern _glapi_proc
+_glapi_get_proc_address(const char *funcName);
+
+
+extern const char *
+_glapi_get_proc_name(GLuint offset);
+
+
+#endif
diff --git a/mesalib/src/mesa/glapi/glapi_getproc.c b/mesalib/src/mesa/glapi/glapi_getproc.c
new file mode 100644
index 000000000..ed443c12c
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapi_getproc.c
@@ -0,0 +1,592 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file glapi_getproc.c
+ *
+ * Code for implementing glXGetProcAddress(), etc.
+ * This was originally in glapi.c but refactored out.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "main/glheader.h"
+#include "main/compiler.h"
+#include "glapi.h"
+#include "glapioffsets.h"
+#include "glapitable.h"
+
+
+static void
+fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
+
+
+/**
+ * strdup() is actually not a standard ANSI C or POSIX routine.
+ * Irix will not define it if ANSI mode is in effect.
+ */
+static char *
+str_dup(const char *str)
+{
+ char *copy;
+ copy = (char*) malloc(strlen(str) + 1);
+ if (!copy)
+ return NULL;
+ strcpy(copy, str);
+ return copy;
+}
+
+
+
+#if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 16
+#elif defined(USE_X86_ASM)
+# if defined(THREADS) && !defined(GLX_USE_TLS)
+# define DISPATCH_FUNCTION_SIZE 32
+# else
+# define DISPATCH_FUNCTION_SIZE 16
+# endif
+#endif
+
+#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer)
+# define NEED_FUNCTION_POINTER
+#endif
+
+/* The code in this file is auto-generated with Python */
+#include "glprocs.h"
+
+
+/**
+ * Search the table of static entrypoint functions for the named function
+ * and return the corresponding glprocs_table_t entry.
+ */
+static const glprocs_table_t *
+find_entry( const char * n )
+{
+ GLuint i;
+ for (i = 0; static_functions[i].Name_offset >= 0; i++) {
+ const char *testName = gl_string_table + static_functions[i].Name_offset;
+#ifdef MANGLE
+ /* skip the "m" prefix on the name */
+ if (strcmp(testName, n + 1) == 0)
+#else
+ if (strcmp(testName, n) == 0)
+#endif
+ {
+ return &static_functions[i];
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Return dispatch table offset of the named static (built-in) function.
+ * Return -1 if function not found.
+ */
+static GLint
+get_static_proc_offset(const char *funcName)
+{
+ const glprocs_table_t * const f = find_entry( funcName );
+ if (f) {
+ return f->Offset;
+ }
+ return -1;
+}
+
+
+#if !defined(XFree86Server) && !defined(XGLServer)
+#ifdef USE_X86_ASM
+
+#if defined( GLX_USE_TLS )
+extern GLubyte gl_dispatch_functions_start[];
+extern GLubyte gl_dispatch_functions_end[];
+#else
+extern const GLubyte gl_dispatch_functions_start[];
+#endif
+
+#endif /* USE_X86_ASM */
+
+
+/**
+ * Return dispatch function address for the named static (built-in) function.
+ * Return NULL if function not found.
+ */
+static _glapi_proc
+get_static_proc_address(const char *funcName)
+{
+ const glprocs_table_t * const f = find_entry( funcName );
+ if (f) {
+#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
+ return (f->Address == NULL)
+ ? (_glapi_proc) (gl_dispatch_functions_start
+ + (DISPATCH_FUNCTION_SIZE * f->Offset))
+ : f->Address;
+#elif defined(DISPATCH_FUNCTION_SIZE)
+ return (_glapi_proc) (gl_dispatch_functions_start
+ + (DISPATCH_FUNCTION_SIZE * f->Offset));
+#else
+ return f->Address;
+#endif
+ }
+ else {
+ return NULL;
+ }
+}
+
+#endif /* !defined(XFree86Server) && !defined(XGLServer) */
+
+
+
+/**
+ * Return the name of the function at the given offset in the dispatch
+ * table. For debugging only.
+ */
+static const char *
+get_static_proc_name( GLuint offset )
+{
+ GLuint i;
+ for (i = 0; static_functions[i].Name_offset >= 0; i++) {
+ if (static_functions[i].Offset == offset) {
+ return gl_string_table + static_functions[i].Name_offset;
+ }
+ }
+ return NULL;
+}
+
+
+
+/**********************************************************************
+ * Extension function management.
+ */
+
+
+/**
+ * Track information about a function added to the GL API.
+ */
+struct _glapi_function {
+ /**
+ * Name of the function.
+ */
+ const char * name;
+
+
+ /**
+ * Text string that describes the types of the parameters passed to the
+ * named function. Parameter types are converted to characters using the
+ * following rules:
+ * - 'i' for \c GLint, \c GLuint, and \c GLenum
+ * - 'p' for any pointer type
+ * - 'f' for \c GLfloat and \c GLclampf
+ * - 'd' for \c GLdouble and \c GLclampd
+ */
+ const char * parameter_signature;
+
+
+ /**
+ * Offset in the dispatch table where the pointer to the real function is
+ * located. If the driver has not requested that the named function be
+ * added to the dispatch table, this will have the value ~0.
+ */
+ unsigned dispatch_offset;
+
+
+ /**
+ * Pointer to the dispatch stub for the named function.
+ *
+ * \todo
+ * The semantic of this field should be changed slightly. Currently, it
+ * is always expected to be non-\c NULL. However, it would be better to
+ * only allocate the entry-point stub when the application requests the
+ * function via \c glXGetProcAddress. This would save memory for all the
+ * functions that the driver exports but that the application never wants
+ * to call.
+ */
+ _glapi_proc dispatch_stub;
+};
+
+
+static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
+static GLuint NumExtEntryPoints = 0;
+
+#ifdef USE_SPARC_ASM
+extern void __glapi_sparc_icache_flush(unsigned int *);
+#endif
+
+/**
+ * Generate a dispatch function (entrypoint) which jumps through
+ * the given slot number (offset) in the current dispatch table.
+ * We need assembly language in order to accomplish this.
+ */
+static _glapi_proc
+generate_entrypoint(GLuint functionOffset)
+{
+#if defined(USE_X86_ASM)
+ /* 32 is chosen as something of a magic offset. For x86, the dispatch
+ * at offset 32 is the first one where the offset in the
+ * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
+ */
+ const GLubyte * const template_func = gl_dispatch_functions_start
+ + (DISPATCH_FUNCTION_SIZE * 32);
+ GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
+
+
+ if ( code != NULL ) {
+ (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
+ fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
+ }
+
+ return (_glapi_proc) code;
+#elif defined(USE_SPARC_ASM) && (defined(PTHREADS) || defined(GLX_USE_TLS))
+ static const unsigned int template[] = {
+ 0x07000000, /* sethi %hi(0), %g3 */
+ 0x8210000f, /* mov %o7, %g1 */
+ 0x40000000, /* call */
+ 0x9e100001, /* mov %g1, %o7 */
+ };
+#ifdef GLX_USE_TLS
+ extern unsigned int __glapi_sparc_tls_stub;
+ unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub;
+#else
+ extern unsigned int __glapi_sparc_pthread_stub;
+ unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub;
+#endif
+ unsigned int *code = (unsigned int *) malloc(sizeof(template));
+ if (code) {
+ code[0] = template[0] | (functionOffset & 0x3fffff);
+ code[1] = template[1];
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] = template[2] |
+ (((call_dest - ((unsigned long) &code[2]))
+ >> 2) & 0x3fffffff);
+ code[3] = template[3];
+ __glapi_sparc_icache_flush(&code[2]);
+ }
+ return (_glapi_proc) code;
+#else
+ (void) functionOffset;
+ return NULL;
+#endif /* USE_*_ASM */
+}
+
+
+/**
+ * This function inserts a new dispatch offset into the assembly language
+ * stub that was generated with the preceeding function.
+ */
+static void
+fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
+{
+#if defined(USE_X86_ASM)
+ GLubyte * const code = (GLubyte *) entrypoint;
+
+#if DISPATCH_FUNCTION_SIZE == 32
+ *((unsigned int *)(code + 11)) = 4 * offset;
+ *((unsigned int *)(code + 22)) = 4 * offset;
+#elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
+ *((unsigned int *)(code + 8)) = 4 * offset;
+#elif DISPATCH_FUNCTION_SIZE == 16
+ *((unsigned int *)(code + 7)) = 4 * offset;
+#else
+# error Invalid DISPATCH_FUNCTION_SIZE!
+#endif
+
+#elif defined(USE_SPARC_ASM)
+ unsigned int *code = (unsigned int *) entrypoint;
+ code[0] &= ~0x3fffff;
+ code[0] |= (offset * sizeof(void *)) & 0x3fffff;
+ __glapi_sparc_icache_flush(&code[0]);
+#else
+
+ /* an unimplemented architecture */
+ (void) entrypoint;
+ (void) offset;
+
+#endif /* USE_*_ASM */
+}
+
+
+/**
+ * Generate new entrypoint
+ *
+ * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver
+ * calls \c _glapi_add_dispatch we'll put in the proper offset. If that
+ * never happens, and the user calls this function, he'll segfault. That's
+ * what you get when you try calling a GL function that doesn't really exist.
+ *
+ * \param funcName Name of the function to create an entry-point for.
+ *
+ * \sa _glapi_add_entrypoint
+ */
+
+static struct _glapi_function *
+add_function_name( const char * funcName )
+{
+ struct _glapi_function * entry = NULL;
+
+ if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
+ _glapi_proc entrypoint = generate_entrypoint(~0);
+ if (entrypoint != NULL) {
+ entry = & ExtEntryTable[NumExtEntryPoints];
+
+ ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName);
+ ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL;
+ ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0;
+ ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint;
+ NumExtEntryPoints++;
+ }
+ }
+
+ return entry;
+}
+
+
+/**
+ * Fill-in the dispatch stub for the named function.
+ *
+ * This function is intended to be called by a hardware driver. When called,
+ * a dispatch stub may be created created for the function. A pointer to this
+ * dispatch function will be returned by glXGetProcAddress.
+ *
+ * \param function_names Array of pointers to function names that should
+ * share a common dispatch offset.
+ * \param parameter_signature String representing the types of the parameters
+ * passed to the named function. Parameter types
+ * are converted to characters using the following
+ * rules:
+ * - 'i' for \c GLint, \c GLuint, and \c GLenum
+ * - 'p' for any pointer type
+ * - 'f' for \c GLfloat and \c GLclampf
+ * - 'd' for \c GLdouble and \c GLclampd
+ *
+ * \returns
+ * The offset in the dispatch table of the named function. A pointer to the
+ * driver's implementation of the named function should be stored at
+ * \c dispatch_table[\c offset]. Return -1 if error/problem.
+ *
+ * \sa glXGetProcAddress
+ *
+ * \warning
+ * This function can only handle up to 8 names at a time. As far as I know,
+ * the maximum number of names ever associated with an existing GL function is
+ * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
+ * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
+ * too painful of a limitation.
+ *
+ * \todo
+ * Determine whether or not \c parameter_signature should be allowed to be
+ * \c NULL. It doesn't seem like much of a hardship for drivers to have to
+ * pass in an empty string.
+ *
+ * \todo
+ * Determine if code should be added to reject function names that start with
+ * 'glX'.
+ *
+ * \bug
+ * Add code to compare \c parameter_signature with the parameter signature of
+ * a static function. In order to do that, we need to find a way to \b get
+ * the parameter signature of a static function.
+ */
+
+PUBLIC int
+_glapi_add_dispatch( const char * const * function_names,
+ const char * parameter_signature )
+{
+ static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
+ const char * const real_sig = (parameter_signature != NULL)
+ ? parameter_signature : "";
+ struct _glapi_function * entry[8];
+ GLboolean is_static[8];
+ unsigned i;
+ unsigned j;
+ int offset = ~0;
+ int new_offset;
+
+
+ (void) memset( is_static, 0, sizeof( is_static ) );
+ (void) memset( entry, 0, sizeof( entry ) );
+
+ for ( i = 0 ; function_names[i] != NULL ; i++ ) {
+ /* Do some trivial validation on the name of the function.
+ */
+
+ if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
+ return -1;
+
+ /* Determine if the named function already exists. If the function does
+ * exist, it must have the same parameter signature as the function
+ * being added.
+ */
+
+ new_offset = get_static_proc_offset(function_names[i]);
+ if (new_offset >= 0) {
+ /* FIXME: Make sure the parameter signatures match! How do we get
+ * FIXME: the parameter signature for static functions?
+ */
+
+ if ( (offset != ~0) && (new_offset != offset) ) {
+ return -1;
+ }
+
+ is_static[i] = GL_TRUE;
+ offset = new_offset;
+ }
+
+
+ for ( j = 0 ; j < NumExtEntryPoints ; j++ ) {
+ if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) {
+ /* The offset may be ~0 if the function name was added by
+ * glXGetProcAddress but never filled in by the driver.
+ */
+
+ if (ExtEntryTable[j].dispatch_offset != ~0) {
+ if (strcmp(real_sig, ExtEntryTable[j].parameter_signature)
+ != 0) {
+ return -1;
+ }
+
+ if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) {
+ return -1;
+ }
+
+ offset = ExtEntryTable[j].dispatch_offset;
+ }
+
+ entry[i] = & ExtEntryTable[j];
+ break;
+ }
+ }
+ }
+
+ if (offset == ~0) {
+ offset = next_dynamic_offset;
+ next_dynamic_offset++;
+ }
+
+ for ( i = 0 ; function_names[i] != NULL ; i++ ) {
+ if (! is_static[i] ) {
+ if (entry[i] == NULL) {
+ entry[i] = add_function_name( function_names[i] );
+ if (entry[i] == NULL) {
+ /* FIXME: Possible memory leak here.
+ */
+ return -1;
+ }
+ }
+
+ entry[i]->parameter_signature = str_dup(real_sig);
+ fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
+ entry[i]->dispatch_offset = offset;
+ }
+ }
+
+ return offset;
+}
+
+
+/**
+ * Return offset of entrypoint for named function within dispatch table.
+ */
+PUBLIC GLint
+_glapi_get_proc_offset(const char *funcName)
+{
+ /* search extension functions first */
+ GLuint i;
+ for (i = 0; i < NumExtEntryPoints; i++) {
+ if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
+ return ExtEntryTable[i].dispatch_offset;
+ }
+ }
+ /* search static functions */
+ return get_static_proc_offset(funcName);
+}
+
+
+
+/**
+ * Return pointer to the named function. If the function name isn't found
+ * in the name of static functions, try generating a new API entrypoint on
+ * the fly with assembly language.
+ */
+_glapi_proc
+_glapi_get_proc_address(const char *funcName)
+{
+ struct _glapi_function * entry;
+ GLuint i;
+
+#ifdef MANGLE
+ if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
+ return NULL;
+#else
+ if (funcName[0] != 'g' || funcName[1] != 'l')
+ return NULL;
+#endif
+
+ /* search extension functions first */
+ for (i = 0; i < NumExtEntryPoints; i++) {
+ if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
+ return ExtEntryTable[i].dispatch_stub;
+ }
+ }
+
+#if !defined( XFree86Server ) && !defined( XGLServer )
+ /* search static functions */
+ {
+ const _glapi_proc func = get_static_proc_address(funcName);
+ if (func)
+ return func;
+ }
+#endif /* !defined( XFree86Server ) */
+
+ entry = add_function_name(funcName);
+ return (entry == NULL) ? NULL : entry->dispatch_stub;
+}
+
+
+
+/**
+ * Return the name of the function at the given dispatch offset.
+ * This is only intended for debugging.
+ */
+const char *
+_glapi_get_proc_name(GLuint offset)
+{
+ GLuint i;
+ const char * n;
+
+ /* search built-in functions */
+ n = get_static_proc_name(offset);
+ if ( n != NULL ) {
+ return n;
+ }
+
+ /* search added extension functions */
+ for (i = 0; i < NumExtEntryPoints; i++) {
+ if (ExtEntryTable[i].dispatch_offset == offset) {
+ return ExtEntryTable[i].name;
+ }
+ }
+ return NULL;
+}
diff --git a/mesalib/src/mesa/glapi/glapioffsets.h b/mesalib/src/mesa/glapi/glapioffsets.h
new file mode 100644
index 000000000..6d4ab09b0
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapioffsets.h
@@ -0,0 +1,1218 @@
+/* DO NOT EDIT - This file generated automatically by gl_offsets.py (from Mesa) script */
+
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL, IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined( _GLAPI_OFFSETS_H_ )
+# define _GLAPI_OFFSETS_H_
+
+#define _gloffset_NewList 0
+#define _gloffset_EndList 1
+#define _gloffset_CallList 2
+#define _gloffset_CallLists 3
+#define _gloffset_DeleteLists 4
+#define _gloffset_GenLists 5
+#define _gloffset_ListBase 6
+#define _gloffset_Begin 7
+#define _gloffset_Bitmap 8
+#define _gloffset_Color3b 9
+#define _gloffset_Color3bv 10
+#define _gloffset_Color3d 11
+#define _gloffset_Color3dv 12
+#define _gloffset_Color3f 13
+#define _gloffset_Color3fv 14
+#define _gloffset_Color3i 15
+#define _gloffset_Color3iv 16
+#define _gloffset_Color3s 17
+#define _gloffset_Color3sv 18
+#define _gloffset_Color3ub 19
+#define _gloffset_Color3ubv 20
+#define _gloffset_Color3ui 21
+#define _gloffset_Color3uiv 22
+#define _gloffset_Color3us 23
+#define _gloffset_Color3usv 24
+#define _gloffset_Color4b 25
+#define _gloffset_Color4bv 26
+#define _gloffset_Color4d 27
+#define _gloffset_Color4dv 28
+#define _gloffset_Color4f 29
+#define _gloffset_Color4fv 30
+#define _gloffset_Color4i 31
+#define _gloffset_Color4iv 32
+#define _gloffset_Color4s 33
+#define _gloffset_Color4sv 34
+#define _gloffset_Color4ub 35
+#define _gloffset_Color4ubv 36
+#define _gloffset_Color4ui 37
+#define _gloffset_Color4uiv 38
+#define _gloffset_Color4us 39
+#define _gloffset_Color4usv 40
+#define _gloffset_EdgeFlag 41
+#define _gloffset_EdgeFlagv 42
+#define _gloffset_End 43
+#define _gloffset_Indexd 44
+#define _gloffset_Indexdv 45
+#define _gloffset_Indexf 46
+#define _gloffset_Indexfv 47
+#define _gloffset_Indexi 48
+#define _gloffset_Indexiv 49
+#define _gloffset_Indexs 50
+#define _gloffset_Indexsv 51
+#define _gloffset_Normal3b 52
+#define _gloffset_Normal3bv 53
+#define _gloffset_Normal3d 54
+#define _gloffset_Normal3dv 55
+#define _gloffset_Normal3f 56
+#define _gloffset_Normal3fv 57
+#define _gloffset_Normal3i 58
+#define _gloffset_Normal3iv 59
+#define _gloffset_Normal3s 60
+#define _gloffset_Normal3sv 61
+#define _gloffset_RasterPos2d 62
+#define _gloffset_RasterPos2dv 63
+#define _gloffset_RasterPos2f 64
+#define _gloffset_RasterPos2fv 65
+#define _gloffset_RasterPos2i 66
+#define _gloffset_RasterPos2iv 67
+#define _gloffset_RasterPos2s 68
+#define _gloffset_RasterPos2sv 69
+#define _gloffset_RasterPos3d 70
+#define _gloffset_RasterPos3dv 71
+#define _gloffset_RasterPos3f 72
+#define _gloffset_RasterPos3fv 73
+#define _gloffset_RasterPos3i 74
+#define _gloffset_RasterPos3iv 75
+#define _gloffset_RasterPos3s 76
+#define _gloffset_RasterPos3sv 77
+#define _gloffset_RasterPos4d 78
+#define _gloffset_RasterPos4dv 79
+#define _gloffset_RasterPos4f 80
+#define _gloffset_RasterPos4fv 81
+#define _gloffset_RasterPos4i 82
+#define _gloffset_RasterPos4iv 83
+#define _gloffset_RasterPos4s 84
+#define _gloffset_RasterPos4sv 85
+#define _gloffset_Rectd 86
+#define _gloffset_Rectdv 87
+#define _gloffset_Rectf 88
+#define _gloffset_Rectfv 89
+#define _gloffset_Recti 90
+#define _gloffset_Rectiv 91
+#define _gloffset_Rects 92
+#define _gloffset_Rectsv 93
+#define _gloffset_TexCoord1d 94
+#define _gloffset_TexCoord1dv 95
+#define _gloffset_TexCoord1f 96
+#define _gloffset_TexCoord1fv 97
+#define _gloffset_TexCoord1i 98
+#define _gloffset_TexCoord1iv 99
+#define _gloffset_TexCoord1s 100
+#define _gloffset_TexCoord1sv 101
+#define _gloffset_TexCoord2d 102
+#define _gloffset_TexCoord2dv 103
+#define _gloffset_TexCoord2f 104
+#define _gloffset_TexCoord2fv 105
+#define _gloffset_TexCoord2i 106
+#define _gloffset_TexCoord2iv 107
+#define _gloffset_TexCoord2s 108
+#define _gloffset_TexCoord2sv 109
+#define _gloffset_TexCoord3d 110
+#define _gloffset_TexCoord3dv 111
+#define _gloffset_TexCoord3f 112
+#define _gloffset_TexCoord3fv 113
+#define _gloffset_TexCoord3i 114
+#define _gloffset_TexCoord3iv 115
+#define _gloffset_TexCoord3s 116
+#define _gloffset_TexCoord3sv 117
+#define _gloffset_TexCoord4d 118
+#define _gloffset_TexCoord4dv 119
+#define _gloffset_TexCoord4f 120
+#define _gloffset_TexCoord4fv 121
+#define _gloffset_TexCoord4i 122
+#define _gloffset_TexCoord4iv 123
+#define _gloffset_TexCoord4s 124
+#define _gloffset_TexCoord4sv 125
+#define _gloffset_Vertex2d 126
+#define _gloffset_Vertex2dv 127
+#define _gloffset_Vertex2f 128
+#define _gloffset_Vertex2fv 129
+#define _gloffset_Vertex2i 130
+#define _gloffset_Vertex2iv 131
+#define _gloffset_Vertex2s 132
+#define _gloffset_Vertex2sv 133
+#define _gloffset_Vertex3d 134
+#define _gloffset_Vertex3dv 135
+#define _gloffset_Vertex3f 136
+#define _gloffset_Vertex3fv 137
+#define _gloffset_Vertex3i 138
+#define _gloffset_Vertex3iv 139
+#define _gloffset_Vertex3s 140
+#define _gloffset_Vertex3sv 141
+#define _gloffset_Vertex4d 142
+#define _gloffset_Vertex4dv 143
+#define _gloffset_Vertex4f 144
+#define _gloffset_Vertex4fv 145
+#define _gloffset_Vertex4i 146
+#define _gloffset_Vertex4iv 147
+#define _gloffset_Vertex4s 148
+#define _gloffset_Vertex4sv 149
+#define _gloffset_ClipPlane 150
+#define _gloffset_ColorMaterial 151
+#define _gloffset_CullFace 152
+#define _gloffset_Fogf 153
+#define _gloffset_Fogfv 154
+#define _gloffset_Fogi 155
+#define _gloffset_Fogiv 156
+#define _gloffset_FrontFace 157
+#define _gloffset_Hint 158
+#define _gloffset_Lightf 159
+#define _gloffset_Lightfv 160
+#define _gloffset_Lighti 161
+#define _gloffset_Lightiv 162
+#define _gloffset_LightModelf 163
+#define _gloffset_LightModelfv 164
+#define _gloffset_LightModeli 165
+#define _gloffset_LightModeliv 166
+#define _gloffset_LineStipple 167
+#define _gloffset_LineWidth 168
+#define _gloffset_Materialf 169
+#define _gloffset_Materialfv 170
+#define _gloffset_Materiali 171
+#define _gloffset_Materialiv 172
+#define _gloffset_PointSize 173
+#define _gloffset_PolygonMode 174
+#define _gloffset_PolygonStipple 175
+#define _gloffset_Scissor 176
+#define _gloffset_ShadeModel 177
+#define _gloffset_TexParameterf 178
+#define _gloffset_TexParameterfv 179
+#define _gloffset_TexParameteri 180
+#define _gloffset_TexParameteriv 181
+#define _gloffset_TexImage1D 182
+#define _gloffset_TexImage2D 183
+#define _gloffset_TexEnvf 184
+#define _gloffset_TexEnvfv 185
+#define _gloffset_TexEnvi 186
+#define _gloffset_TexEnviv 187
+#define _gloffset_TexGend 188
+#define _gloffset_TexGendv 189
+#define _gloffset_TexGenf 190
+#define _gloffset_TexGenfv 191
+#define _gloffset_TexGeni 192
+#define _gloffset_TexGeniv 193
+#define _gloffset_FeedbackBuffer 194
+#define _gloffset_SelectBuffer 195
+#define _gloffset_RenderMode 196
+#define _gloffset_InitNames 197
+#define _gloffset_LoadName 198
+#define _gloffset_PassThrough 199
+#define _gloffset_PopName 200
+#define _gloffset_PushName 201
+#define _gloffset_DrawBuffer 202
+#define _gloffset_Clear 203
+#define _gloffset_ClearAccum 204
+#define _gloffset_ClearIndex 205
+#define _gloffset_ClearColor 206
+#define _gloffset_ClearStencil 207
+#define _gloffset_ClearDepth 208
+#define _gloffset_StencilMask 209
+#define _gloffset_ColorMask 210
+#define _gloffset_DepthMask 211
+#define _gloffset_IndexMask 212
+#define _gloffset_Accum 213
+#define _gloffset_Disable 214
+#define _gloffset_Enable 215
+#define _gloffset_Finish 216
+#define _gloffset_Flush 217
+#define _gloffset_PopAttrib 218
+#define _gloffset_PushAttrib 219
+#define _gloffset_Map1d 220
+#define _gloffset_Map1f 221
+#define _gloffset_Map2d 222
+#define _gloffset_Map2f 223
+#define _gloffset_MapGrid1d 224
+#define _gloffset_MapGrid1f 225
+#define _gloffset_MapGrid2d 226
+#define _gloffset_MapGrid2f 227
+#define _gloffset_EvalCoord1d 228
+#define _gloffset_EvalCoord1dv 229
+#define _gloffset_EvalCoord1f 230
+#define _gloffset_EvalCoord1fv 231
+#define _gloffset_EvalCoord2d 232
+#define _gloffset_EvalCoord2dv 233
+#define _gloffset_EvalCoord2f 234
+#define _gloffset_EvalCoord2fv 235
+#define _gloffset_EvalMesh1 236
+#define _gloffset_EvalPoint1 237
+#define _gloffset_EvalMesh2 238
+#define _gloffset_EvalPoint2 239
+#define _gloffset_AlphaFunc 240
+#define _gloffset_BlendFunc 241
+#define _gloffset_LogicOp 242
+#define _gloffset_StencilFunc 243
+#define _gloffset_StencilOp 244
+#define _gloffset_DepthFunc 245
+#define _gloffset_PixelZoom 246
+#define _gloffset_PixelTransferf 247
+#define _gloffset_PixelTransferi 248
+#define _gloffset_PixelStoref 249
+#define _gloffset_PixelStorei 250
+#define _gloffset_PixelMapfv 251
+#define _gloffset_PixelMapuiv 252
+#define _gloffset_PixelMapusv 253
+#define _gloffset_ReadBuffer 254
+#define _gloffset_CopyPixels 255
+#define _gloffset_ReadPixels 256
+#define _gloffset_DrawPixels 257
+#define _gloffset_GetBooleanv 258
+#define _gloffset_GetClipPlane 259
+#define _gloffset_GetDoublev 260
+#define _gloffset_GetError 261
+#define _gloffset_GetFloatv 262
+#define _gloffset_GetIntegerv 263
+#define _gloffset_GetLightfv 264
+#define _gloffset_GetLightiv 265
+#define _gloffset_GetMapdv 266
+#define _gloffset_GetMapfv 267
+#define _gloffset_GetMapiv 268
+#define _gloffset_GetMaterialfv 269
+#define _gloffset_GetMaterialiv 270
+#define _gloffset_GetPixelMapfv 271
+#define _gloffset_GetPixelMapuiv 272
+#define _gloffset_GetPixelMapusv 273
+#define _gloffset_GetPolygonStipple 274
+#define _gloffset_GetString 275
+#define _gloffset_GetTexEnvfv 276
+#define _gloffset_GetTexEnviv 277
+#define _gloffset_GetTexGendv 278
+#define _gloffset_GetTexGenfv 279
+#define _gloffset_GetTexGeniv 280
+#define _gloffset_GetTexImage 281
+#define _gloffset_GetTexParameterfv 282
+#define _gloffset_GetTexParameteriv 283
+#define _gloffset_GetTexLevelParameterfv 284
+#define _gloffset_GetTexLevelParameteriv 285
+#define _gloffset_IsEnabled 286
+#define _gloffset_IsList 287
+#define _gloffset_DepthRange 288
+#define _gloffset_Frustum 289
+#define _gloffset_LoadIdentity 290
+#define _gloffset_LoadMatrixf 291
+#define _gloffset_LoadMatrixd 292
+#define _gloffset_MatrixMode 293
+#define _gloffset_MultMatrixf 294
+#define _gloffset_MultMatrixd 295
+#define _gloffset_Ortho 296
+#define _gloffset_PopMatrix 297
+#define _gloffset_PushMatrix 298
+#define _gloffset_Rotated 299
+#define _gloffset_Rotatef 300
+#define _gloffset_Scaled 301
+#define _gloffset_Scalef 302
+#define _gloffset_Translated 303
+#define _gloffset_Translatef 304
+#define _gloffset_Viewport 305
+#define _gloffset_ArrayElement 306
+#define _gloffset_BindTexture 307
+#define _gloffset_ColorPointer 308
+#define _gloffset_DisableClientState 309
+#define _gloffset_DrawArrays 310
+#define _gloffset_DrawElements 311
+#define _gloffset_EdgeFlagPointer 312
+#define _gloffset_EnableClientState 313
+#define _gloffset_IndexPointer 314
+#define _gloffset_Indexub 315
+#define _gloffset_Indexubv 316
+#define _gloffset_InterleavedArrays 317
+#define _gloffset_NormalPointer 318
+#define _gloffset_PolygonOffset 319
+#define _gloffset_TexCoordPointer 320
+#define _gloffset_VertexPointer 321
+#define _gloffset_AreTexturesResident 322
+#define _gloffset_CopyTexImage1D 323
+#define _gloffset_CopyTexImage2D 324
+#define _gloffset_CopyTexSubImage1D 325
+#define _gloffset_CopyTexSubImage2D 326
+#define _gloffset_DeleteTextures 327
+#define _gloffset_GenTextures 328
+#define _gloffset_GetPointerv 329
+#define _gloffset_IsTexture 330
+#define _gloffset_PrioritizeTextures 331
+#define _gloffset_TexSubImage1D 332
+#define _gloffset_TexSubImage2D 333
+#define _gloffset_PopClientAttrib 334
+#define _gloffset_PushClientAttrib 335
+#define _gloffset_BlendColor 336
+#define _gloffset_BlendEquation 337
+#define _gloffset_DrawRangeElements 338
+#define _gloffset_ColorTable 339
+#define _gloffset_ColorTableParameterfv 340
+#define _gloffset_ColorTableParameteriv 341
+#define _gloffset_CopyColorTable 342
+#define _gloffset_GetColorTable 343
+#define _gloffset_GetColorTableParameterfv 344
+#define _gloffset_GetColorTableParameteriv 345
+#define _gloffset_ColorSubTable 346
+#define _gloffset_CopyColorSubTable 347
+#define _gloffset_ConvolutionFilter1D 348
+#define _gloffset_ConvolutionFilter2D 349
+#define _gloffset_ConvolutionParameterf 350
+#define _gloffset_ConvolutionParameterfv 351
+#define _gloffset_ConvolutionParameteri 352
+#define _gloffset_ConvolutionParameteriv 353
+#define _gloffset_CopyConvolutionFilter1D 354
+#define _gloffset_CopyConvolutionFilter2D 355
+#define _gloffset_GetConvolutionFilter 356
+#define _gloffset_GetConvolutionParameterfv 357
+#define _gloffset_GetConvolutionParameteriv 358
+#define _gloffset_GetSeparableFilter 359
+#define _gloffset_SeparableFilter2D 360
+#define _gloffset_GetHistogram 361
+#define _gloffset_GetHistogramParameterfv 362
+#define _gloffset_GetHistogramParameteriv 363
+#define _gloffset_GetMinmax 364
+#define _gloffset_GetMinmaxParameterfv 365
+#define _gloffset_GetMinmaxParameteriv 366
+#define _gloffset_Histogram 367
+#define _gloffset_Minmax 368
+#define _gloffset_ResetHistogram 369
+#define _gloffset_ResetMinmax 370
+#define _gloffset_TexImage3D 371
+#define _gloffset_TexSubImage3D 372
+#define _gloffset_CopyTexSubImage3D 373
+#define _gloffset_ActiveTextureARB 374
+#define _gloffset_ClientActiveTextureARB 375
+#define _gloffset_MultiTexCoord1dARB 376
+#define _gloffset_MultiTexCoord1dvARB 377
+#define _gloffset_MultiTexCoord1fARB 378
+#define _gloffset_MultiTexCoord1fvARB 379
+#define _gloffset_MultiTexCoord1iARB 380
+#define _gloffset_MultiTexCoord1ivARB 381
+#define _gloffset_MultiTexCoord1sARB 382
+#define _gloffset_MultiTexCoord1svARB 383
+#define _gloffset_MultiTexCoord2dARB 384
+#define _gloffset_MultiTexCoord2dvARB 385
+#define _gloffset_MultiTexCoord2fARB 386
+#define _gloffset_MultiTexCoord2fvARB 387
+#define _gloffset_MultiTexCoord2iARB 388
+#define _gloffset_MultiTexCoord2ivARB 389
+#define _gloffset_MultiTexCoord2sARB 390
+#define _gloffset_MultiTexCoord2svARB 391
+#define _gloffset_MultiTexCoord3dARB 392
+#define _gloffset_MultiTexCoord3dvARB 393
+#define _gloffset_MultiTexCoord3fARB 394
+#define _gloffset_MultiTexCoord3fvARB 395
+#define _gloffset_MultiTexCoord3iARB 396
+#define _gloffset_MultiTexCoord3ivARB 397
+#define _gloffset_MultiTexCoord3sARB 398
+#define _gloffset_MultiTexCoord3svARB 399
+#define _gloffset_MultiTexCoord4dARB 400
+#define _gloffset_MultiTexCoord4dvARB 401
+#define _gloffset_MultiTexCoord4fARB 402
+#define _gloffset_MultiTexCoord4fvARB 403
+#define _gloffset_MultiTexCoord4iARB 404
+#define _gloffset_MultiTexCoord4ivARB 405
+#define _gloffset_MultiTexCoord4sARB 406
+#define _gloffset_MultiTexCoord4svARB 407
+
+#if !defined(IN_DRI_DRIVER)
+
+#define _gloffset_AttachShader 408
+#define _gloffset_CreateProgram 409
+#define _gloffset_CreateShader 410
+#define _gloffset_DeleteProgram 411
+#define _gloffset_DeleteShader 412
+#define _gloffset_DetachShader 413
+#define _gloffset_GetAttachedShaders 414
+#define _gloffset_GetProgramInfoLog 415
+#define _gloffset_GetProgramiv 416
+#define _gloffset_GetShaderInfoLog 417
+#define _gloffset_GetShaderiv 418
+#define _gloffset_IsProgram 419
+#define _gloffset_IsShader 420
+#define _gloffset_StencilFuncSeparate 421
+#define _gloffset_StencilMaskSeparate 422
+#define _gloffset_StencilOpSeparate 423
+#define _gloffset_UniformMatrix2x3fv 424
+#define _gloffset_UniformMatrix2x4fv 425
+#define _gloffset_UniformMatrix3x2fv 426
+#define _gloffset_UniformMatrix3x4fv 427
+#define _gloffset_UniformMatrix4x2fv 428
+#define _gloffset_UniformMatrix4x3fv 429
+#define _gloffset_LoadTransposeMatrixdARB 430
+#define _gloffset_LoadTransposeMatrixfARB 431
+#define _gloffset_MultTransposeMatrixdARB 432
+#define _gloffset_MultTransposeMatrixfARB 433
+#define _gloffset_SampleCoverageARB 434
+#define _gloffset_CompressedTexImage1DARB 435
+#define _gloffset_CompressedTexImage2DARB 436
+#define _gloffset_CompressedTexImage3DARB 437
+#define _gloffset_CompressedTexSubImage1DARB 438
+#define _gloffset_CompressedTexSubImage2DARB 439
+#define _gloffset_CompressedTexSubImage3DARB 440
+#define _gloffset_GetCompressedTexImageARB 441
+#define _gloffset_DisableVertexAttribArrayARB 442
+#define _gloffset_EnableVertexAttribArrayARB 443
+#define _gloffset_GetProgramEnvParameterdvARB 444
+#define _gloffset_GetProgramEnvParameterfvARB 445
+#define _gloffset_GetProgramLocalParameterdvARB 446
+#define _gloffset_GetProgramLocalParameterfvARB 447
+#define _gloffset_GetProgramStringARB 448
+#define _gloffset_GetProgramivARB 449
+#define _gloffset_GetVertexAttribdvARB 450
+#define _gloffset_GetVertexAttribfvARB 451
+#define _gloffset_GetVertexAttribivARB 452
+#define _gloffset_ProgramEnvParameter4dARB 453
+#define _gloffset_ProgramEnvParameter4dvARB 454
+#define _gloffset_ProgramEnvParameter4fARB 455
+#define _gloffset_ProgramEnvParameter4fvARB 456
+#define _gloffset_ProgramLocalParameter4dARB 457
+#define _gloffset_ProgramLocalParameter4dvARB 458
+#define _gloffset_ProgramLocalParameter4fARB 459
+#define _gloffset_ProgramLocalParameter4fvARB 460
+#define _gloffset_ProgramStringARB 461
+#define _gloffset_VertexAttrib1dARB 462
+#define _gloffset_VertexAttrib1dvARB 463
+#define _gloffset_VertexAttrib1fARB 464
+#define _gloffset_VertexAttrib1fvARB 465
+#define _gloffset_VertexAttrib1sARB 466
+#define _gloffset_VertexAttrib1svARB 467
+#define _gloffset_VertexAttrib2dARB 468
+#define _gloffset_VertexAttrib2dvARB 469
+#define _gloffset_VertexAttrib2fARB 470
+#define _gloffset_VertexAttrib2fvARB 471
+#define _gloffset_VertexAttrib2sARB 472
+#define _gloffset_VertexAttrib2svARB 473
+#define _gloffset_VertexAttrib3dARB 474
+#define _gloffset_VertexAttrib3dvARB 475
+#define _gloffset_VertexAttrib3fARB 476
+#define _gloffset_VertexAttrib3fvARB 477
+#define _gloffset_VertexAttrib3sARB 478
+#define _gloffset_VertexAttrib3svARB 479
+#define _gloffset_VertexAttrib4NbvARB 480
+#define _gloffset_VertexAttrib4NivARB 481
+#define _gloffset_VertexAttrib4NsvARB 482
+#define _gloffset_VertexAttrib4NubARB 483
+#define _gloffset_VertexAttrib4NubvARB 484
+#define _gloffset_VertexAttrib4NuivARB 485
+#define _gloffset_VertexAttrib4NusvARB 486
+#define _gloffset_VertexAttrib4bvARB 487
+#define _gloffset_VertexAttrib4dARB 488
+#define _gloffset_VertexAttrib4dvARB 489
+#define _gloffset_VertexAttrib4fARB 490
+#define _gloffset_VertexAttrib4fvARB 491
+#define _gloffset_VertexAttrib4ivARB 492
+#define _gloffset_VertexAttrib4sARB 493
+#define _gloffset_VertexAttrib4svARB 494
+#define _gloffset_VertexAttrib4ubvARB 495
+#define _gloffset_VertexAttrib4uivARB 496
+#define _gloffset_VertexAttrib4usvARB 497
+#define _gloffset_VertexAttribPointerARB 498
+#define _gloffset_BindBufferARB 499
+#define _gloffset_BufferDataARB 500
+#define _gloffset_BufferSubDataARB 501
+#define _gloffset_DeleteBuffersARB 502
+#define _gloffset_GenBuffersARB 503
+#define _gloffset_GetBufferParameterivARB 504
+#define _gloffset_GetBufferPointervARB 505
+#define _gloffset_GetBufferSubDataARB 506
+#define _gloffset_IsBufferARB 507
+#define _gloffset_MapBufferARB 508
+#define _gloffset_UnmapBufferARB 509
+#define _gloffset_BeginQueryARB 510
+#define _gloffset_DeleteQueriesARB 511
+#define _gloffset_EndQueryARB 512
+#define _gloffset_GenQueriesARB 513
+#define _gloffset_GetQueryObjectivARB 514
+#define _gloffset_GetQueryObjectuivARB 515
+#define _gloffset_GetQueryivARB 516
+#define _gloffset_IsQueryARB 517
+#define _gloffset_AttachObjectARB 518
+#define _gloffset_CompileShaderARB 519
+#define _gloffset_CreateProgramObjectARB 520
+#define _gloffset_CreateShaderObjectARB 521
+#define _gloffset_DeleteObjectARB 522
+#define _gloffset_DetachObjectARB 523
+#define _gloffset_GetActiveUniformARB 524
+#define _gloffset_GetAttachedObjectsARB 525
+#define _gloffset_GetHandleARB 526
+#define _gloffset_GetInfoLogARB 527
+#define _gloffset_GetObjectParameterfvARB 528
+#define _gloffset_GetObjectParameterivARB 529
+#define _gloffset_GetShaderSourceARB 530
+#define _gloffset_GetUniformLocationARB 531
+#define _gloffset_GetUniformfvARB 532
+#define _gloffset_GetUniformivARB 533
+#define _gloffset_LinkProgramARB 534
+#define _gloffset_ShaderSourceARB 535
+#define _gloffset_Uniform1fARB 536
+#define _gloffset_Uniform1fvARB 537
+#define _gloffset_Uniform1iARB 538
+#define _gloffset_Uniform1ivARB 539
+#define _gloffset_Uniform2fARB 540
+#define _gloffset_Uniform2fvARB 541
+#define _gloffset_Uniform2iARB 542
+#define _gloffset_Uniform2ivARB 543
+#define _gloffset_Uniform3fARB 544
+#define _gloffset_Uniform3fvARB 545
+#define _gloffset_Uniform3iARB 546
+#define _gloffset_Uniform3ivARB 547
+#define _gloffset_Uniform4fARB 548
+#define _gloffset_Uniform4fvARB 549
+#define _gloffset_Uniform4iARB 550
+#define _gloffset_Uniform4ivARB 551
+#define _gloffset_UniformMatrix2fvARB 552
+#define _gloffset_UniformMatrix3fvARB 553
+#define _gloffset_UniformMatrix4fvARB 554
+#define _gloffset_UseProgramObjectARB 555
+#define _gloffset_ValidateProgramARB 556
+#define _gloffset_BindAttribLocationARB 557
+#define _gloffset_GetActiveAttribARB 558
+#define _gloffset_GetAttribLocationARB 559
+#define _gloffset_DrawBuffersARB 560
+#define _gloffset_RenderbufferStorageMultisample 561
+#define _gloffset_FlushMappedBufferRange 562
+#define _gloffset_MapBufferRange 563
+#define _gloffset_BindVertexArray 564
+#define _gloffset_GenVertexArrays 565
+#define _gloffset_CopyBufferSubData 566
+#define _gloffset_ClientWaitSync 567
+#define _gloffset_DeleteSync 568
+#define _gloffset_FenceSync 569
+#define _gloffset_GetInteger64v 570
+#define _gloffset_GetSynciv 571
+#define _gloffset_IsSync 572
+#define _gloffset_WaitSync 573
+#define _gloffset_PolygonOffsetEXT 574
+#define _gloffset_GetPixelTexGenParameterfvSGIS 575
+#define _gloffset_GetPixelTexGenParameterivSGIS 576
+#define _gloffset_PixelTexGenParameterfSGIS 577
+#define _gloffset_PixelTexGenParameterfvSGIS 578
+#define _gloffset_PixelTexGenParameteriSGIS 579
+#define _gloffset_PixelTexGenParameterivSGIS 580
+#define _gloffset_SampleMaskSGIS 581
+#define _gloffset_SamplePatternSGIS 582
+#define _gloffset_ColorPointerEXT 583
+#define _gloffset_EdgeFlagPointerEXT 584
+#define _gloffset_IndexPointerEXT 585
+#define _gloffset_NormalPointerEXT 586
+#define _gloffset_TexCoordPointerEXT 587
+#define _gloffset_VertexPointerEXT 588
+#define _gloffset_PointParameterfEXT 589
+#define _gloffset_PointParameterfvEXT 590
+#define _gloffset_LockArraysEXT 591
+#define _gloffset_UnlockArraysEXT 592
+#define _gloffset_CullParameterdvEXT 593
+#define _gloffset_CullParameterfvEXT 594
+#define _gloffset_SecondaryColor3bEXT 595
+#define _gloffset_SecondaryColor3bvEXT 596
+#define _gloffset_SecondaryColor3dEXT 597
+#define _gloffset_SecondaryColor3dvEXT 598
+#define _gloffset_SecondaryColor3fEXT 599
+#define _gloffset_SecondaryColor3fvEXT 600
+#define _gloffset_SecondaryColor3iEXT 601
+#define _gloffset_SecondaryColor3ivEXT 602
+#define _gloffset_SecondaryColor3sEXT 603
+#define _gloffset_SecondaryColor3svEXT 604
+#define _gloffset_SecondaryColor3ubEXT 605
+#define _gloffset_SecondaryColor3ubvEXT 606
+#define _gloffset_SecondaryColor3uiEXT 607
+#define _gloffset_SecondaryColor3uivEXT 608
+#define _gloffset_SecondaryColor3usEXT 609
+#define _gloffset_SecondaryColor3usvEXT 610
+#define _gloffset_SecondaryColorPointerEXT 611
+#define _gloffset_MultiDrawArraysEXT 612
+#define _gloffset_MultiDrawElementsEXT 613
+#define _gloffset_FogCoordPointerEXT 614
+#define _gloffset_FogCoorddEXT 615
+#define _gloffset_FogCoorddvEXT 616
+#define _gloffset_FogCoordfEXT 617
+#define _gloffset_FogCoordfvEXT 618
+#define _gloffset_PixelTexGenSGIX 619
+#define _gloffset_BlendFuncSeparateEXT 620
+#define _gloffset_FlushVertexArrayRangeNV 621
+#define _gloffset_VertexArrayRangeNV 622
+#define _gloffset_CombinerInputNV 623
+#define _gloffset_CombinerOutputNV 624
+#define _gloffset_CombinerParameterfNV 625
+#define _gloffset_CombinerParameterfvNV 626
+#define _gloffset_CombinerParameteriNV 627
+#define _gloffset_CombinerParameterivNV 628
+#define _gloffset_FinalCombinerInputNV 629
+#define _gloffset_GetCombinerInputParameterfvNV 630
+#define _gloffset_GetCombinerInputParameterivNV 631
+#define _gloffset_GetCombinerOutputParameterfvNV 632
+#define _gloffset_GetCombinerOutputParameterivNV 633
+#define _gloffset_GetFinalCombinerInputParameterfvNV 634
+#define _gloffset_GetFinalCombinerInputParameterivNV 635
+#define _gloffset_ResizeBuffersMESA 636
+#define _gloffset_WindowPos2dMESA 637
+#define _gloffset_WindowPos2dvMESA 638
+#define _gloffset_WindowPos2fMESA 639
+#define _gloffset_WindowPos2fvMESA 640
+#define _gloffset_WindowPos2iMESA 641
+#define _gloffset_WindowPos2ivMESA 642
+#define _gloffset_WindowPos2sMESA 643
+#define _gloffset_WindowPos2svMESA 644
+#define _gloffset_WindowPos3dMESA 645
+#define _gloffset_WindowPos3dvMESA 646
+#define _gloffset_WindowPos3fMESA 647
+#define _gloffset_WindowPos3fvMESA 648
+#define _gloffset_WindowPos3iMESA 649
+#define _gloffset_WindowPos3ivMESA 650
+#define _gloffset_WindowPos3sMESA 651
+#define _gloffset_WindowPos3svMESA 652
+#define _gloffset_WindowPos4dMESA 653
+#define _gloffset_WindowPos4dvMESA 654
+#define _gloffset_WindowPos4fMESA 655
+#define _gloffset_WindowPos4fvMESA 656
+#define _gloffset_WindowPos4iMESA 657
+#define _gloffset_WindowPos4ivMESA 658
+#define _gloffset_WindowPos4sMESA 659
+#define _gloffset_WindowPos4svMESA 660
+#define _gloffset_MultiModeDrawArraysIBM 661
+#define _gloffset_MultiModeDrawElementsIBM 662
+#define _gloffset_DeleteFencesNV 663
+#define _gloffset_FinishFenceNV 664
+#define _gloffset_GenFencesNV 665
+#define _gloffset_GetFenceivNV 666
+#define _gloffset_IsFenceNV 667
+#define _gloffset_SetFenceNV 668
+#define _gloffset_TestFenceNV 669
+#define _gloffset_AreProgramsResidentNV 670
+#define _gloffset_BindProgramNV 671
+#define _gloffset_DeleteProgramsNV 672
+#define _gloffset_ExecuteProgramNV 673
+#define _gloffset_GenProgramsNV 674
+#define _gloffset_GetProgramParameterdvNV 675
+#define _gloffset_GetProgramParameterfvNV 676
+#define _gloffset_GetProgramStringNV 677
+#define _gloffset_GetProgramivNV 678
+#define _gloffset_GetTrackMatrixivNV 679
+#define _gloffset_GetVertexAttribPointervNV 680
+#define _gloffset_GetVertexAttribdvNV 681
+#define _gloffset_GetVertexAttribfvNV 682
+#define _gloffset_GetVertexAttribivNV 683
+#define _gloffset_IsProgramNV 684
+#define _gloffset_LoadProgramNV 685
+#define _gloffset_ProgramParameters4dvNV 686
+#define _gloffset_ProgramParameters4fvNV 687
+#define _gloffset_RequestResidentProgramsNV 688
+#define _gloffset_TrackMatrixNV 689
+#define _gloffset_VertexAttrib1dNV 690
+#define _gloffset_VertexAttrib1dvNV 691
+#define _gloffset_VertexAttrib1fNV 692
+#define _gloffset_VertexAttrib1fvNV 693
+#define _gloffset_VertexAttrib1sNV 694
+#define _gloffset_VertexAttrib1svNV 695
+#define _gloffset_VertexAttrib2dNV 696
+#define _gloffset_VertexAttrib2dvNV 697
+#define _gloffset_VertexAttrib2fNV 698
+#define _gloffset_VertexAttrib2fvNV 699
+#define _gloffset_VertexAttrib2sNV 700
+#define _gloffset_VertexAttrib2svNV 701
+#define _gloffset_VertexAttrib3dNV 702
+#define _gloffset_VertexAttrib3dvNV 703
+#define _gloffset_VertexAttrib3fNV 704
+#define _gloffset_VertexAttrib3fvNV 705
+#define _gloffset_VertexAttrib3sNV 706
+#define _gloffset_VertexAttrib3svNV 707
+#define _gloffset_VertexAttrib4dNV 708
+#define _gloffset_VertexAttrib4dvNV 709
+#define _gloffset_VertexAttrib4fNV 710
+#define _gloffset_VertexAttrib4fvNV 711
+#define _gloffset_VertexAttrib4sNV 712
+#define _gloffset_VertexAttrib4svNV 713
+#define _gloffset_VertexAttrib4ubNV 714
+#define _gloffset_VertexAttrib4ubvNV 715
+#define _gloffset_VertexAttribPointerNV 716
+#define _gloffset_VertexAttribs1dvNV 717
+#define _gloffset_VertexAttribs1fvNV 718
+#define _gloffset_VertexAttribs1svNV 719
+#define _gloffset_VertexAttribs2dvNV 720
+#define _gloffset_VertexAttribs2fvNV 721
+#define _gloffset_VertexAttribs2svNV 722
+#define _gloffset_VertexAttribs3dvNV 723
+#define _gloffset_VertexAttribs3fvNV 724
+#define _gloffset_VertexAttribs3svNV 725
+#define _gloffset_VertexAttribs4dvNV 726
+#define _gloffset_VertexAttribs4fvNV 727
+#define _gloffset_VertexAttribs4svNV 728
+#define _gloffset_VertexAttribs4ubvNV 729
+#define _gloffset_GetTexBumpParameterfvATI 730
+#define _gloffset_GetTexBumpParameterivATI 731
+#define _gloffset_TexBumpParameterfvATI 732
+#define _gloffset_TexBumpParameterivATI 733
+#define _gloffset_AlphaFragmentOp1ATI 734
+#define _gloffset_AlphaFragmentOp2ATI 735
+#define _gloffset_AlphaFragmentOp3ATI 736
+#define _gloffset_BeginFragmentShaderATI 737
+#define _gloffset_BindFragmentShaderATI 738
+#define _gloffset_ColorFragmentOp1ATI 739
+#define _gloffset_ColorFragmentOp2ATI 740
+#define _gloffset_ColorFragmentOp3ATI 741
+#define _gloffset_DeleteFragmentShaderATI 742
+#define _gloffset_EndFragmentShaderATI 743
+#define _gloffset_GenFragmentShadersATI 744
+#define _gloffset_PassTexCoordATI 745
+#define _gloffset_SampleMapATI 746
+#define _gloffset_SetFragmentShaderConstantATI 747
+#define _gloffset_PointParameteriNV 748
+#define _gloffset_PointParameterivNV 749
+#define _gloffset_ActiveStencilFaceEXT 750
+#define _gloffset_BindVertexArrayAPPLE 751
+#define _gloffset_DeleteVertexArraysAPPLE 752
+#define _gloffset_GenVertexArraysAPPLE 753
+#define _gloffset_IsVertexArrayAPPLE 754
+#define _gloffset_GetProgramNamedParameterdvNV 755
+#define _gloffset_GetProgramNamedParameterfvNV 756
+#define _gloffset_ProgramNamedParameter4dNV 757
+#define _gloffset_ProgramNamedParameter4dvNV 758
+#define _gloffset_ProgramNamedParameter4fNV 759
+#define _gloffset_ProgramNamedParameter4fvNV 760
+#define _gloffset_DepthBoundsEXT 761
+#define _gloffset_BlendEquationSeparateEXT 762
+#define _gloffset_BindFramebufferEXT 763
+#define _gloffset_BindRenderbufferEXT 764
+#define _gloffset_CheckFramebufferStatusEXT 765
+#define _gloffset_DeleteFramebuffersEXT 766
+#define _gloffset_DeleteRenderbuffersEXT 767
+#define _gloffset_FramebufferRenderbufferEXT 768
+#define _gloffset_FramebufferTexture1DEXT 769
+#define _gloffset_FramebufferTexture2DEXT 770
+#define _gloffset_FramebufferTexture3DEXT 771
+#define _gloffset_GenFramebuffersEXT 772
+#define _gloffset_GenRenderbuffersEXT 773
+#define _gloffset_GenerateMipmapEXT 774
+#define _gloffset_GetFramebufferAttachmentParameterivEXT 775
+#define _gloffset_GetRenderbufferParameterivEXT 776
+#define _gloffset_IsFramebufferEXT 777
+#define _gloffset_IsRenderbufferEXT 778
+#define _gloffset_RenderbufferStorageEXT 779
+#define _gloffset_BlitFramebufferEXT 780
+#define _gloffset_BufferParameteriAPPLE 781
+#define _gloffset_FlushMappedBufferRangeAPPLE 782
+#define _gloffset_FramebufferTextureLayerEXT 783
+#define _gloffset_ProvokingVertexEXT 784
+#define _gloffset_GetTexParameterPointervAPPLE 785
+#define _gloffset_TextureRangeAPPLE 786
+#define _gloffset_StencilFuncSeparateATI 787
+#define _gloffset_ProgramEnvParameters4fvEXT 788
+#define _gloffset_ProgramLocalParameters4fvEXT 789
+#define _gloffset_GetQueryObjecti64vEXT 790
+#define _gloffset_GetQueryObjectui64vEXT 791
+#define _gloffset_FIRST_DYNAMIC 792
+
+#else
+
+#define _gloffset_AttachShader driDispatchRemapTable[AttachShader_remap_index]
+#define _gloffset_CreateProgram driDispatchRemapTable[CreateProgram_remap_index]
+#define _gloffset_CreateShader driDispatchRemapTable[CreateShader_remap_index]
+#define _gloffset_DeleteProgram driDispatchRemapTable[DeleteProgram_remap_index]
+#define _gloffset_DeleteShader driDispatchRemapTable[DeleteShader_remap_index]
+#define _gloffset_DetachShader driDispatchRemapTable[DetachShader_remap_index]
+#define _gloffset_GetAttachedShaders driDispatchRemapTable[GetAttachedShaders_remap_index]
+#define _gloffset_GetProgramInfoLog driDispatchRemapTable[GetProgramInfoLog_remap_index]
+#define _gloffset_GetProgramiv driDispatchRemapTable[GetProgramiv_remap_index]
+#define _gloffset_GetShaderInfoLog driDispatchRemapTable[GetShaderInfoLog_remap_index]
+#define _gloffset_GetShaderiv driDispatchRemapTable[GetShaderiv_remap_index]
+#define _gloffset_IsProgram driDispatchRemapTable[IsProgram_remap_index]
+#define _gloffset_IsShader driDispatchRemapTable[IsShader_remap_index]
+#define _gloffset_StencilFuncSeparate driDispatchRemapTable[StencilFuncSeparate_remap_index]
+#define _gloffset_StencilMaskSeparate driDispatchRemapTable[StencilMaskSeparate_remap_index]
+#define _gloffset_StencilOpSeparate driDispatchRemapTable[StencilOpSeparate_remap_index]
+#define _gloffset_UniformMatrix2x3fv driDispatchRemapTable[UniformMatrix2x3fv_remap_index]
+#define _gloffset_UniformMatrix2x4fv driDispatchRemapTable[UniformMatrix2x4fv_remap_index]
+#define _gloffset_UniformMatrix3x2fv driDispatchRemapTable[UniformMatrix3x2fv_remap_index]
+#define _gloffset_UniformMatrix3x4fv driDispatchRemapTable[UniformMatrix3x4fv_remap_index]
+#define _gloffset_UniformMatrix4x2fv driDispatchRemapTable[UniformMatrix4x2fv_remap_index]
+#define _gloffset_UniformMatrix4x3fv driDispatchRemapTable[UniformMatrix4x3fv_remap_index]
+#define _gloffset_LoadTransposeMatrixdARB driDispatchRemapTable[LoadTransposeMatrixdARB_remap_index]
+#define _gloffset_LoadTransposeMatrixfARB driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index]
+#define _gloffset_MultTransposeMatrixdARB driDispatchRemapTable[MultTransposeMatrixdARB_remap_index]
+#define _gloffset_MultTransposeMatrixfARB driDispatchRemapTable[MultTransposeMatrixfARB_remap_index]
+#define _gloffset_SampleCoverageARB driDispatchRemapTable[SampleCoverageARB_remap_index]
+#define _gloffset_CompressedTexImage1DARB driDispatchRemapTable[CompressedTexImage1DARB_remap_index]
+#define _gloffset_CompressedTexImage2DARB driDispatchRemapTable[CompressedTexImage2DARB_remap_index]
+#define _gloffset_CompressedTexImage3DARB driDispatchRemapTable[CompressedTexImage3DARB_remap_index]
+#define _gloffset_CompressedTexSubImage1DARB driDispatchRemapTable[CompressedTexSubImage1DARB_remap_index]
+#define _gloffset_CompressedTexSubImage2DARB driDispatchRemapTable[CompressedTexSubImage2DARB_remap_index]
+#define _gloffset_CompressedTexSubImage3DARB driDispatchRemapTable[CompressedTexSubImage3DARB_remap_index]
+#define _gloffset_GetCompressedTexImageARB driDispatchRemapTable[GetCompressedTexImageARB_remap_index]
+#define _gloffset_DisableVertexAttribArrayARB driDispatchRemapTable[DisableVertexAttribArrayARB_remap_index]
+#define _gloffset_EnableVertexAttribArrayARB driDispatchRemapTable[EnableVertexAttribArrayARB_remap_index]
+#define _gloffset_GetProgramEnvParameterdvARB driDispatchRemapTable[GetProgramEnvParameterdvARB_remap_index]
+#define _gloffset_GetProgramEnvParameterfvARB driDispatchRemapTable[GetProgramEnvParameterfvARB_remap_index]
+#define _gloffset_GetProgramLocalParameterdvARB driDispatchRemapTable[GetProgramLocalParameterdvARB_remap_index]
+#define _gloffset_GetProgramLocalParameterfvARB driDispatchRemapTable[GetProgramLocalParameterfvARB_remap_index]
+#define _gloffset_GetProgramStringARB driDispatchRemapTable[GetProgramStringARB_remap_index]
+#define _gloffset_GetProgramivARB driDispatchRemapTable[GetProgramivARB_remap_index]
+#define _gloffset_GetVertexAttribdvARB driDispatchRemapTable[GetVertexAttribdvARB_remap_index]
+#define _gloffset_GetVertexAttribfvARB driDispatchRemapTable[GetVertexAttribfvARB_remap_index]
+#define _gloffset_GetVertexAttribivARB driDispatchRemapTable[GetVertexAttribivARB_remap_index]
+#define _gloffset_ProgramEnvParameter4dARB driDispatchRemapTable[ProgramEnvParameter4dARB_remap_index]
+#define _gloffset_ProgramEnvParameter4dvARB driDispatchRemapTable[ProgramEnvParameter4dvARB_remap_index]
+#define _gloffset_ProgramEnvParameter4fARB driDispatchRemapTable[ProgramEnvParameter4fARB_remap_index]
+#define _gloffset_ProgramEnvParameter4fvARB driDispatchRemapTable[ProgramEnvParameter4fvARB_remap_index]
+#define _gloffset_ProgramLocalParameter4dARB driDispatchRemapTable[ProgramLocalParameter4dARB_remap_index]
+#define _gloffset_ProgramLocalParameter4dvARB driDispatchRemapTable[ProgramLocalParameter4dvARB_remap_index]
+#define _gloffset_ProgramLocalParameter4fARB driDispatchRemapTable[ProgramLocalParameter4fARB_remap_index]
+#define _gloffset_ProgramLocalParameter4fvARB driDispatchRemapTable[ProgramLocalParameter4fvARB_remap_index]
+#define _gloffset_ProgramStringARB driDispatchRemapTable[ProgramStringARB_remap_index]
+#define _gloffset_VertexAttrib1dARB driDispatchRemapTable[VertexAttrib1dARB_remap_index]
+#define _gloffset_VertexAttrib1dvARB driDispatchRemapTable[VertexAttrib1dvARB_remap_index]
+#define _gloffset_VertexAttrib1fARB driDispatchRemapTable[VertexAttrib1fARB_remap_index]
+#define _gloffset_VertexAttrib1fvARB driDispatchRemapTable[VertexAttrib1fvARB_remap_index]
+#define _gloffset_VertexAttrib1sARB driDispatchRemapTable[VertexAttrib1sARB_remap_index]
+#define _gloffset_VertexAttrib1svARB driDispatchRemapTable[VertexAttrib1svARB_remap_index]
+#define _gloffset_VertexAttrib2dARB driDispatchRemapTable[VertexAttrib2dARB_remap_index]
+#define _gloffset_VertexAttrib2dvARB driDispatchRemapTable[VertexAttrib2dvARB_remap_index]
+#define _gloffset_VertexAttrib2fARB driDispatchRemapTable[VertexAttrib2fARB_remap_index]
+#define _gloffset_VertexAttrib2fvARB driDispatchRemapTable[VertexAttrib2fvARB_remap_index]
+#define _gloffset_VertexAttrib2sARB driDispatchRemapTable[VertexAttrib2sARB_remap_index]
+#define _gloffset_VertexAttrib2svARB driDispatchRemapTable[VertexAttrib2svARB_remap_index]
+#define _gloffset_VertexAttrib3dARB driDispatchRemapTable[VertexAttrib3dARB_remap_index]
+#define _gloffset_VertexAttrib3dvARB driDispatchRemapTable[VertexAttrib3dvARB_remap_index]
+#define _gloffset_VertexAttrib3fARB driDispatchRemapTable[VertexAttrib3fARB_remap_index]
+#define _gloffset_VertexAttrib3fvARB driDispatchRemapTable[VertexAttrib3fvARB_remap_index]
+#define _gloffset_VertexAttrib3sARB driDispatchRemapTable[VertexAttrib3sARB_remap_index]
+#define _gloffset_VertexAttrib3svARB driDispatchRemapTable[VertexAttrib3svARB_remap_index]
+#define _gloffset_VertexAttrib4NbvARB driDispatchRemapTable[VertexAttrib4NbvARB_remap_index]
+#define _gloffset_VertexAttrib4NivARB driDispatchRemapTable[VertexAttrib4NivARB_remap_index]
+#define _gloffset_VertexAttrib4NsvARB driDispatchRemapTable[VertexAttrib4NsvARB_remap_index]
+#define _gloffset_VertexAttrib4NubARB driDispatchRemapTable[VertexAttrib4NubARB_remap_index]
+#define _gloffset_VertexAttrib4NubvARB driDispatchRemapTable[VertexAttrib4NubvARB_remap_index]
+#define _gloffset_VertexAttrib4NuivARB driDispatchRemapTable[VertexAttrib4NuivARB_remap_index]
+#define _gloffset_VertexAttrib4NusvARB driDispatchRemapTable[VertexAttrib4NusvARB_remap_index]
+#define _gloffset_VertexAttrib4bvARB driDispatchRemapTable[VertexAttrib4bvARB_remap_index]
+#define _gloffset_VertexAttrib4dARB driDispatchRemapTable[VertexAttrib4dARB_remap_index]
+#define _gloffset_VertexAttrib4dvARB driDispatchRemapTable[VertexAttrib4dvARB_remap_index]
+#define _gloffset_VertexAttrib4fARB driDispatchRemapTable[VertexAttrib4fARB_remap_index]
+#define _gloffset_VertexAttrib4fvARB driDispatchRemapTable[VertexAttrib4fvARB_remap_index]
+#define _gloffset_VertexAttrib4ivARB driDispatchRemapTable[VertexAttrib4ivARB_remap_index]
+#define _gloffset_VertexAttrib4sARB driDispatchRemapTable[VertexAttrib4sARB_remap_index]
+#define _gloffset_VertexAttrib4svARB driDispatchRemapTable[VertexAttrib4svARB_remap_index]
+#define _gloffset_VertexAttrib4ubvARB driDispatchRemapTable[VertexAttrib4ubvARB_remap_index]
+#define _gloffset_VertexAttrib4uivARB driDispatchRemapTable[VertexAttrib4uivARB_remap_index]
+#define _gloffset_VertexAttrib4usvARB driDispatchRemapTable[VertexAttrib4usvARB_remap_index]
+#define _gloffset_VertexAttribPointerARB driDispatchRemapTable[VertexAttribPointerARB_remap_index]
+#define _gloffset_BindBufferARB driDispatchRemapTable[BindBufferARB_remap_index]
+#define _gloffset_BufferDataARB driDispatchRemapTable[BufferDataARB_remap_index]
+#define _gloffset_BufferSubDataARB driDispatchRemapTable[BufferSubDataARB_remap_index]
+#define _gloffset_DeleteBuffersARB driDispatchRemapTable[DeleteBuffersARB_remap_index]
+#define _gloffset_GenBuffersARB driDispatchRemapTable[GenBuffersARB_remap_index]
+#define _gloffset_GetBufferParameterivARB driDispatchRemapTable[GetBufferParameterivARB_remap_index]
+#define _gloffset_GetBufferPointervARB driDispatchRemapTable[GetBufferPointervARB_remap_index]
+#define _gloffset_GetBufferSubDataARB driDispatchRemapTable[GetBufferSubDataARB_remap_index]
+#define _gloffset_IsBufferARB driDispatchRemapTable[IsBufferARB_remap_index]
+#define _gloffset_MapBufferARB driDispatchRemapTable[MapBufferARB_remap_index]
+#define _gloffset_UnmapBufferARB driDispatchRemapTable[UnmapBufferARB_remap_index]
+#define _gloffset_BeginQueryARB driDispatchRemapTable[BeginQueryARB_remap_index]
+#define _gloffset_DeleteQueriesARB driDispatchRemapTable[DeleteQueriesARB_remap_index]
+#define _gloffset_EndQueryARB driDispatchRemapTable[EndQueryARB_remap_index]
+#define _gloffset_GenQueriesARB driDispatchRemapTable[GenQueriesARB_remap_index]
+#define _gloffset_GetQueryObjectivARB driDispatchRemapTable[GetQueryObjectivARB_remap_index]
+#define _gloffset_GetQueryObjectuivARB driDispatchRemapTable[GetQueryObjectuivARB_remap_index]
+#define _gloffset_GetQueryivARB driDispatchRemapTable[GetQueryivARB_remap_index]
+#define _gloffset_IsQueryARB driDispatchRemapTable[IsQueryARB_remap_index]
+#define _gloffset_AttachObjectARB driDispatchRemapTable[AttachObjectARB_remap_index]
+#define _gloffset_CompileShaderARB driDispatchRemapTable[CompileShaderARB_remap_index]
+#define _gloffset_CreateProgramObjectARB driDispatchRemapTable[CreateProgramObjectARB_remap_index]
+#define _gloffset_CreateShaderObjectARB driDispatchRemapTable[CreateShaderObjectARB_remap_index]
+#define _gloffset_DeleteObjectARB driDispatchRemapTable[DeleteObjectARB_remap_index]
+#define _gloffset_DetachObjectARB driDispatchRemapTable[DetachObjectARB_remap_index]
+#define _gloffset_GetActiveUniformARB driDispatchRemapTable[GetActiveUniformARB_remap_index]
+#define _gloffset_GetAttachedObjectsARB driDispatchRemapTable[GetAttachedObjectsARB_remap_index]
+#define _gloffset_GetHandleARB driDispatchRemapTable[GetHandleARB_remap_index]
+#define _gloffset_GetInfoLogARB driDispatchRemapTable[GetInfoLogARB_remap_index]
+#define _gloffset_GetObjectParameterfvARB driDispatchRemapTable[GetObjectParameterfvARB_remap_index]
+#define _gloffset_GetObjectParameterivARB driDispatchRemapTable[GetObjectParameterivARB_remap_index]
+#define _gloffset_GetShaderSourceARB driDispatchRemapTable[GetShaderSourceARB_remap_index]
+#define _gloffset_GetUniformLocationARB driDispatchRemapTable[GetUniformLocationARB_remap_index]
+#define _gloffset_GetUniformfvARB driDispatchRemapTable[GetUniformfvARB_remap_index]
+#define _gloffset_GetUniformivARB driDispatchRemapTable[GetUniformivARB_remap_index]
+#define _gloffset_LinkProgramARB driDispatchRemapTable[LinkProgramARB_remap_index]
+#define _gloffset_ShaderSourceARB driDispatchRemapTable[ShaderSourceARB_remap_index]
+#define _gloffset_Uniform1fARB driDispatchRemapTable[Uniform1fARB_remap_index]
+#define _gloffset_Uniform1fvARB driDispatchRemapTable[Uniform1fvARB_remap_index]
+#define _gloffset_Uniform1iARB driDispatchRemapTable[Uniform1iARB_remap_index]
+#define _gloffset_Uniform1ivARB driDispatchRemapTable[Uniform1ivARB_remap_index]
+#define _gloffset_Uniform2fARB driDispatchRemapTable[Uniform2fARB_remap_index]
+#define _gloffset_Uniform2fvARB driDispatchRemapTable[Uniform2fvARB_remap_index]
+#define _gloffset_Uniform2iARB driDispatchRemapTable[Uniform2iARB_remap_index]
+#define _gloffset_Uniform2ivARB driDispatchRemapTable[Uniform2ivARB_remap_index]
+#define _gloffset_Uniform3fARB driDispatchRemapTable[Uniform3fARB_remap_index]
+#define _gloffset_Uniform3fvARB driDispatchRemapTable[Uniform3fvARB_remap_index]
+#define _gloffset_Uniform3iARB driDispatchRemapTable[Uniform3iARB_remap_index]
+#define _gloffset_Uniform3ivARB driDispatchRemapTable[Uniform3ivARB_remap_index]
+#define _gloffset_Uniform4fARB driDispatchRemapTable[Uniform4fARB_remap_index]
+#define _gloffset_Uniform4fvARB driDispatchRemapTable[Uniform4fvARB_remap_index]
+#define _gloffset_Uniform4iARB driDispatchRemapTable[Uniform4iARB_remap_index]
+#define _gloffset_Uniform4ivARB driDispatchRemapTable[Uniform4ivARB_remap_index]
+#define _gloffset_UniformMatrix2fvARB driDispatchRemapTable[UniformMatrix2fvARB_remap_index]
+#define _gloffset_UniformMatrix3fvARB driDispatchRemapTable[UniformMatrix3fvARB_remap_index]
+#define _gloffset_UniformMatrix4fvARB driDispatchRemapTable[UniformMatrix4fvARB_remap_index]
+#define _gloffset_UseProgramObjectARB driDispatchRemapTable[UseProgramObjectARB_remap_index]
+#define _gloffset_ValidateProgramARB driDispatchRemapTable[ValidateProgramARB_remap_index]
+#define _gloffset_BindAttribLocationARB driDispatchRemapTable[BindAttribLocationARB_remap_index]
+#define _gloffset_GetActiveAttribARB driDispatchRemapTable[GetActiveAttribARB_remap_index]
+#define _gloffset_GetAttribLocationARB driDispatchRemapTable[GetAttribLocationARB_remap_index]
+#define _gloffset_DrawBuffersARB driDispatchRemapTable[DrawBuffersARB_remap_index]
+#define _gloffset_RenderbufferStorageMultisample driDispatchRemapTable[RenderbufferStorageMultisample_remap_index]
+#define _gloffset_FlushMappedBufferRange driDispatchRemapTable[FlushMappedBufferRange_remap_index]
+#define _gloffset_MapBufferRange driDispatchRemapTable[MapBufferRange_remap_index]
+#define _gloffset_BindVertexArray driDispatchRemapTable[BindVertexArray_remap_index]
+#define _gloffset_GenVertexArrays driDispatchRemapTable[GenVertexArrays_remap_index]
+#define _gloffset_CopyBufferSubData driDispatchRemapTable[CopyBufferSubData_remap_index]
+#define _gloffset_ClientWaitSync driDispatchRemapTable[ClientWaitSync_remap_index]
+#define _gloffset_DeleteSync driDispatchRemapTable[DeleteSync_remap_index]
+#define _gloffset_FenceSync driDispatchRemapTable[FenceSync_remap_index]
+#define _gloffset_GetInteger64v driDispatchRemapTable[GetInteger64v_remap_index]
+#define _gloffset_GetSynciv driDispatchRemapTable[GetSynciv_remap_index]
+#define _gloffset_IsSync driDispatchRemapTable[IsSync_remap_index]
+#define _gloffset_WaitSync driDispatchRemapTable[WaitSync_remap_index]
+#define _gloffset_PolygonOffsetEXT driDispatchRemapTable[PolygonOffsetEXT_remap_index]
+#define _gloffset_GetPixelTexGenParameterfvSGIS driDispatchRemapTable[GetPixelTexGenParameterfvSGIS_remap_index]
+#define _gloffset_GetPixelTexGenParameterivSGIS driDispatchRemapTable[GetPixelTexGenParameterivSGIS_remap_index]
+#define _gloffset_PixelTexGenParameterfSGIS driDispatchRemapTable[PixelTexGenParameterfSGIS_remap_index]
+#define _gloffset_PixelTexGenParameterfvSGIS driDispatchRemapTable[PixelTexGenParameterfvSGIS_remap_index]
+#define _gloffset_PixelTexGenParameteriSGIS driDispatchRemapTable[PixelTexGenParameteriSGIS_remap_index]
+#define _gloffset_PixelTexGenParameterivSGIS driDispatchRemapTable[PixelTexGenParameterivSGIS_remap_index]
+#define _gloffset_SampleMaskSGIS driDispatchRemapTable[SampleMaskSGIS_remap_index]
+#define _gloffset_SamplePatternSGIS driDispatchRemapTable[SamplePatternSGIS_remap_index]
+#define _gloffset_ColorPointerEXT driDispatchRemapTable[ColorPointerEXT_remap_index]
+#define _gloffset_EdgeFlagPointerEXT driDispatchRemapTable[EdgeFlagPointerEXT_remap_index]
+#define _gloffset_IndexPointerEXT driDispatchRemapTable[IndexPointerEXT_remap_index]
+#define _gloffset_NormalPointerEXT driDispatchRemapTable[NormalPointerEXT_remap_index]
+#define _gloffset_TexCoordPointerEXT driDispatchRemapTable[TexCoordPointerEXT_remap_index]
+#define _gloffset_VertexPointerEXT driDispatchRemapTable[VertexPointerEXT_remap_index]
+#define _gloffset_PointParameterfEXT driDispatchRemapTable[PointParameterfEXT_remap_index]
+#define _gloffset_PointParameterfvEXT driDispatchRemapTable[PointParameterfvEXT_remap_index]
+#define _gloffset_LockArraysEXT driDispatchRemapTable[LockArraysEXT_remap_index]
+#define _gloffset_UnlockArraysEXT driDispatchRemapTable[UnlockArraysEXT_remap_index]
+#define _gloffset_CullParameterdvEXT driDispatchRemapTable[CullParameterdvEXT_remap_index]
+#define _gloffset_CullParameterfvEXT driDispatchRemapTable[CullParameterfvEXT_remap_index]
+#define _gloffset_SecondaryColor3bEXT driDispatchRemapTable[SecondaryColor3bEXT_remap_index]
+#define _gloffset_SecondaryColor3bvEXT driDispatchRemapTable[SecondaryColor3bvEXT_remap_index]
+#define _gloffset_SecondaryColor3dEXT driDispatchRemapTable[SecondaryColor3dEXT_remap_index]
+#define _gloffset_SecondaryColor3dvEXT driDispatchRemapTable[SecondaryColor3dvEXT_remap_index]
+#define _gloffset_SecondaryColor3fEXT driDispatchRemapTable[SecondaryColor3fEXT_remap_index]
+#define _gloffset_SecondaryColor3fvEXT driDispatchRemapTable[SecondaryColor3fvEXT_remap_index]
+#define _gloffset_SecondaryColor3iEXT driDispatchRemapTable[SecondaryColor3iEXT_remap_index]
+#define _gloffset_SecondaryColor3ivEXT driDispatchRemapTable[SecondaryColor3ivEXT_remap_index]
+#define _gloffset_SecondaryColor3sEXT driDispatchRemapTable[SecondaryColor3sEXT_remap_index]
+#define _gloffset_SecondaryColor3svEXT driDispatchRemapTable[SecondaryColor3svEXT_remap_index]
+#define _gloffset_SecondaryColor3ubEXT driDispatchRemapTable[SecondaryColor3ubEXT_remap_index]
+#define _gloffset_SecondaryColor3ubvEXT driDispatchRemapTable[SecondaryColor3ubvEXT_remap_index]
+#define _gloffset_SecondaryColor3uiEXT driDispatchRemapTable[SecondaryColor3uiEXT_remap_index]
+#define _gloffset_SecondaryColor3uivEXT driDispatchRemapTable[SecondaryColor3uivEXT_remap_index]
+#define _gloffset_SecondaryColor3usEXT driDispatchRemapTable[SecondaryColor3usEXT_remap_index]
+#define _gloffset_SecondaryColor3usvEXT driDispatchRemapTable[SecondaryColor3usvEXT_remap_index]
+#define _gloffset_SecondaryColorPointerEXT driDispatchRemapTable[SecondaryColorPointerEXT_remap_index]
+#define _gloffset_MultiDrawArraysEXT driDispatchRemapTable[MultiDrawArraysEXT_remap_index]
+#define _gloffset_MultiDrawElementsEXT driDispatchRemapTable[MultiDrawElementsEXT_remap_index]
+#define _gloffset_FogCoordPointerEXT driDispatchRemapTable[FogCoordPointerEXT_remap_index]
+#define _gloffset_FogCoorddEXT driDispatchRemapTable[FogCoorddEXT_remap_index]
+#define _gloffset_FogCoorddvEXT driDispatchRemapTable[FogCoorddvEXT_remap_index]
+#define _gloffset_FogCoordfEXT driDispatchRemapTable[FogCoordfEXT_remap_index]
+#define _gloffset_FogCoordfvEXT driDispatchRemapTable[FogCoordfvEXT_remap_index]
+#define _gloffset_PixelTexGenSGIX driDispatchRemapTable[PixelTexGenSGIX_remap_index]
+#define _gloffset_BlendFuncSeparateEXT driDispatchRemapTable[BlendFuncSeparateEXT_remap_index]
+#define _gloffset_FlushVertexArrayRangeNV driDispatchRemapTable[FlushVertexArrayRangeNV_remap_index]
+#define _gloffset_VertexArrayRangeNV driDispatchRemapTable[VertexArrayRangeNV_remap_index]
+#define _gloffset_CombinerInputNV driDispatchRemapTable[CombinerInputNV_remap_index]
+#define _gloffset_CombinerOutputNV driDispatchRemapTable[CombinerOutputNV_remap_index]
+#define _gloffset_CombinerParameterfNV driDispatchRemapTable[CombinerParameterfNV_remap_index]
+#define _gloffset_CombinerParameterfvNV driDispatchRemapTable[CombinerParameterfvNV_remap_index]
+#define _gloffset_CombinerParameteriNV driDispatchRemapTable[CombinerParameteriNV_remap_index]
+#define _gloffset_CombinerParameterivNV driDispatchRemapTable[CombinerParameterivNV_remap_index]
+#define _gloffset_FinalCombinerInputNV driDispatchRemapTable[FinalCombinerInputNV_remap_index]
+#define _gloffset_GetCombinerInputParameterfvNV driDispatchRemapTable[GetCombinerInputParameterfvNV_remap_index]
+#define _gloffset_GetCombinerInputParameterivNV driDispatchRemapTable[GetCombinerInputParameterivNV_remap_index]
+#define _gloffset_GetCombinerOutputParameterfvNV driDispatchRemapTable[GetCombinerOutputParameterfvNV_remap_index]
+#define _gloffset_GetCombinerOutputParameterivNV driDispatchRemapTable[GetCombinerOutputParameterivNV_remap_index]
+#define _gloffset_GetFinalCombinerInputParameterfvNV driDispatchRemapTable[GetFinalCombinerInputParameterfvNV_remap_index]
+#define _gloffset_GetFinalCombinerInputParameterivNV driDispatchRemapTable[GetFinalCombinerInputParameterivNV_remap_index]
+#define _gloffset_ResizeBuffersMESA driDispatchRemapTable[ResizeBuffersMESA_remap_index]
+#define _gloffset_WindowPos2dMESA driDispatchRemapTable[WindowPos2dMESA_remap_index]
+#define _gloffset_WindowPos2dvMESA driDispatchRemapTable[WindowPos2dvMESA_remap_index]
+#define _gloffset_WindowPos2fMESA driDispatchRemapTable[WindowPos2fMESA_remap_index]
+#define _gloffset_WindowPos2fvMESA driDispatchRemapTable[WindowPos2fvMESA_remap_index]
+#define _gloffset_WindowPos2iMESA driDispatchRemapTable[WindowPos2iMESA_remap_index]
+#define _gloffset_WindowPos2ivMESA driDispatchRemapTable[WindowPos2ivMESA_remap_index]
+#define _gloffset_WindowPos2sMESA driDispatchRemapTable[WindowPos2sMESA_remap_index]
+#define _gloffset_WindowPos2svMESA driDispatchRemapTable[WindowPos2svMESA_remap_index]
+#define _gloffset_WindowPos3dMESA driDispatchRemapTable[WindowPos3dMESA_remap_index]
+#define _gloffset_WindowPos3dvMESA driDispatchRemapTable[WindowPos3dvMESA_remap_index]
+#define _gloffset_WindowPos3fMESA driDispatchRemapTable[WindowPos3fMESA_remap_index]
+#define _gloffset_WindowPos3fvMESA driDispatchRemapTable[WindowPos3fvMESA_remap_index]
+#define _gloffset_WindowPos3iMESA driDispatchRemapTable[WindowPos3iMESA_remap_index]
+#define _gloffset_WindowPos3ivMESA driDispatchRemapTable[WindowPos3ivMESA_remap_index]
+#define _gloffset_WindowPos3sMESA driDispatchRemapTable[WindowPos3sMESA_remap_index]
+#define _gloffset_WindowPos3svMESA driDispatchRemapTable[WindowPos3svMESA_remap_index]
+#define _gloffset_WindowPos4dMESA driDispatchRemapTable[WindowPos4dMESA_remap_index]
+#define _gloffset_WindowPos4dvMESA driDispatchRemapTable[WindowPos4dvMESA_remap_index]
+#define _gloffset_WindowPos4fMESA driDispatchRemapTable[WindowPos4fMESA_remap_index]
+#define _gloffset_WindowPos4fvMESA driDispatchRemapTable[WindowPos4fvMESA_remap_index]
+#define _gloffset_WindowPos4iMESA driDispatchRemapTable[WindowPos4iMESA_remap_index]
+#define _gloffset_WindowPos4ivMESA driDispatchRemapTable[WindowPos4ivMESA_remap_index]
+#define _gloffset_WindowPos4sMESA driDispatchRemapTable[WindowPos4sMESA_remap_index]
+#define _gloffset_WindowPos4svMESA driDispatchRemapTable[WindowPos4svMESA_remap_index]
+#define _gloffset_MultiModeDrawArraysIBM driDispatchRemapTable[MultiModeDrawArraysIBM_remap_index]
+#define _gloffset_MultiModeDrawElementsIBM driDispatchRemapTable[MultiModeDrawElementsIBM_remap_index]
+#define _gloffset_DeleteFencesNV driDispatchRemapTable[DeleteFencesNV_remap_index]
+#define _gloffset_FinishFenceNV driDispatchRemapTable[FinishFenceNV_remap_index]
+#define _gloffset_GenFencesNV driDispatchRemapTable[GenFencesNV_remap_index]
+#define _gloffset_GetFenceivNV driDispatchRemapTable[GetFenceivNV_remap_index]
+#define _gloffset_IsFenceNV driDispatchRemapTable[IsFenceNV_remap_index]
+#define _gloffset_SetFenceNV driDispatchRemapTable[SetFenceNV_remap_index]
+#define _gloffset_TestFenceNV driDispatchRemapTable[TestFenceNV_remap_index]
+#define _gloffset_AreProgramsResidentNV driDispatchRemapTable[AreProgramsResidentNV_remap_index]
+#define _gloffset_BindProgramNV driDispatchRemapTable[BindProgramNV_remap_index]
+#define _gloffset_DeleteProgramsNV driDispatchRemapTable[DeleteProgramsNV_remap_index]
+#define _gloffset_ExecuteProgramNV driDispatchRemapTable[ExecuteProgramNV_remap_index]
+#define _gloffset_GenProgramsNV driDispatchRemapTable[GenProgramsNV_remap_index]
+#define _gloffset_GetProgramParameterdvNV driDispatchRemapTable[GetProgramParameterdvNV_remap_index]
+#define _gloffset_GetProgramParameterfvNV driDispatchRemapTable[GetProgramParameterfvNV_remap_index]
+#define _gloffset_GetProgramStringNV driDispatchRemapTable[GetProgramStringNV_remap_index]
+#define _gloffset_GetProgramivNV driDispatchRemapTable[GetProgramivNV_remap_index]
+#define _gloffset_GetTrackMatrixivNV driDispatchRemapTable[GetTrackMatrixivNV_remap_index]
+#define _gloffset_GetVertexAttribPointervNV driDispatchRemapTable[GetVertexAttribPointervNV_remap_index]
+#define _gloffset_GetVertexAttribdvNV driDispatchRemapTable[GetVertexAttribdvNV_remap_index]
+#define _gloffset_GetVertexAttribfvNV driDispatchRemapTable[GetVertexAttribfvNV_remap_index]
+#define _gloffset_GetVertexAttribivNV driDispatchRemapTable[GetVertexAttribivNV_remap_index]
+#define _gloffset_IsProgramNV driDispatchRemapTable[IsProgramNV_remap_index]
+#define _gloffset_LoadProgramNV driDispatchRemapTable[LoadProgramNV_remap_index]
+#define _gloffset_ProgramParameters4dvNV driDispatchRemapTable[ProgramParameters4dvNV_remap_index]
+#define _gloffset_ProgramParameters4fvNV driDispatchRemapTable[ProgramParameters4fvNV_remap_index]
+#define _gloffset_RequestResidentProgramsNV driDispatchRemapTable[RequestResidentProgramsNV_remap_index]
+#define _gloffset_TrackMatrixNV driDispatchRemapTable[TrackMatrixNV_remap_index]
+#define _gloffset_VertexAttrib1dNV driDispatchRemapTable[VertexAttrib1dNV_remap_index]
+#define _gloffset_VertexAttrib1dvNV driDispatchRemapTable[VertexAttrib1dvNV_remap_index]
+#define _gloffset_VertexAttrib1fNV driDispatchRemapTable[VertexAttrib1fNV_remap_index]
+#define _gloffset_VertexAttrib1fvNV driDispatchRemapTable[VertexAttrib1fvNV_remap_index]
+#define _gloffset_VertexAttrib1sNV driDispatchRemapTable[VertexAttrib1sNV_remap_index]
+#define _gloffset_VertexAttrib1svNV driDispatchRemapTable[VertexAttrib1svNV_remap_index]
+#define _gloffset_VertexAttrib2dNV driDispatchRemapTable[VertexAttrib2dNV_remap_index]
+#define _gloffset_VertexAttrib2dvNV driDispatchRemapTable[VertexAttrib2dvNV_remap_index]
+#define _gloffset_VertexAttrib2fNV driDispatchRemapTable[VertexAttrib2fNV_remap_index]
+#define _gloffset_VertexAttrib2fvNV driDispatchRemapTable[VertexAttrib2fvNV_remap_index]
+#define _gloffset_VertexAttrib2sNV driDispatchRemapTable[VertexAttrib2sNV_remap_index]
+#define _gloffset_VertexAttrib2svNV driDispatchRemapTable[VertexAttrib2svNV_remap_index]
+#define _gloffset_VertexAttrib3dNV driDispatchRemapTable[VertexAttrib3dNV_remap_index]
+#define _gloffset_VertexAttrib3dvNV driDispatchRemapTable[VertexAttrib3dvNV_remap_index]
+#define _gloffset_VertexAttrib3fNV driDispatchRemapTable[VertexAttrib3fNV_remap_index]
+#define _gloffset_VertexAttrib3fvNV driDispatchRemapTable[VertexAttrib3fvNV_remap_index]
+#define _gloffset_VertexAttrib3sNV driDispatchRemapTable[VertexAttrib3sNV_remap_index]
+#define _gloffset_VertexAttrib3svNV driDispatchRemapTable[VertexAttrib3svNV_remap_index]
+#define _gloffset_VertexAttrib4dNV driDispatchRemapTable[VertexAttrib4dNV_remap_index]
+#define _gloffset_VertexAttrib4dvNV driDispatchRemapTable[VertexAttrib4dvNV_remap_index]
+#define _gloffset_VertexAttrib4fNV driDispatchRemapTable[VertexAttrib4fNV_remap_index]
+#define _gloffset_VertexAttrib4fvNV driDispatchRemapTable[VertexAttrib4fvNV_remap_index]
+#define _gloffset_VertexAttrib4sNV driDispatchRemapTable[VertexAttrib4sNV_remap_index]
+#define _gloffset_VertexAttrib4svNV driDispatchRemapTable[VertexAttrib4svNV_remap_index]
+#define _gloffset_VertexAttrib4ubNV driDispatchRemapTable[VertexAttrib4ubNV_remap_index]
+#define _gloffset_VertexAttrib4ubvNV driDispatchRemapTable[VertexAttrib4ubvNV_remap_index]
+#define _gloffset_VertexAttribPointerNV driDispatchRemapTable[VertexAttribPointerNV_remap_index]
+#define _gloffset_VertexAttribs1dvNV driDispatchRemapTable[VertexAttribs1dvNV_remap_index]
+#define _gloffset_VertexAttribs1fvNV driDispatchRemapTable[VertexAttribs1fvNV_remap_index]
+#define _gloffset_VertexAttribs1svNV driDispatchRemapTable[VertexAttribs1svNV_remap_index]
+#define _gloffset_VertexAttribs2dvNV driDispatchRemapTable[VertexAttribs2dvNV_remap_index]
+#define _gloffset_VertexAttribs2fvNV driDispatchRemapTable[VertexAttribs2fvNV_remap_index]
+#define _gloffset_VertexAttribs2svNV driDispatchRemapTable[VertexAttribs2svNV_remap_index]
+#define _gloffset_VertexAttribs3dvNV driDispatchRemapTable[VertexAttribs3dvNV_remap_index]
+#define _gloffset_VertexAttribs3fvNV driDispatchRemapTable[VertexAttribs3fvNV_remap_index]
+#define _gloffset_VertexAttribs3svNV driDispatchRemapTable[VertexAttribs3svNV_remap_index]
+#define _gloffset_VertexAttribs4dvNV driDispatchRemapTable[VertexAttribs4dvNV_remap_index]
+#define _gloffset_VertexAttribs4fvNV driDispatchRemapTable[VertexAttribs4fvNV_remap_index]
+#define _gloffset_VertexAttribs4svNV driDispatchRemapTable[VertexAttribs4svNV_remap_index]
+#define _gloffset_VertexAttribs4ubvNV driDispatchRemapTable[VertexAttribs4ubvNV_remap_index]
+#define _gloffset_GetTexBumpParameterfvATI driDispatchRemapTable[GetTexBumpParameterfvATI_remap_index]
+#define _gloffset_GetTexBumpParameterivATI driDispatchRemapTable[GetTexBumpParameterivATI_remap_index]
+#define _gloffset_TexBumpParameterfvATI driDispatchRemapTable[TexBumpParameterfvATI_remap_index]
+#define _gloffset_TexBumpParameterivATI driDispatchRemapTable[TexBumpParameterivATI_remap_index]
+#define _gloffset_AlphaFragmentOp1ATI driDispatchRemapTable[AlphaFragmentOp1ATI_remap_index]
+#define _gloffset_AlphaFragmentOp2ATI driDispatchRemapTable[AlphaFragmentOp2ATI_remap_index]
+#define _gloffset_AlphaFragmentOp3ATI driDispatchRemapTable[AlphaFragmentOp3ATI_remap_index]
+#define _gloffset_BeginFragmentShaderATI driDispatchRemapTable[BeginFragmentShaderATI_remap_index]
+#define _gloffset_BindFragmentShaderATI driDispatchRemapTable[BindFragmentShaderATI_remap_index]
+#define _gloffset_ColorFragmentOp1ATI driDispatchRemapTable[ColorFragmentOp1ATI_remap_index]
+#define _gloffset_ColorFragmentOp2ATI driDispatchRemapTable[ColorFragmentOp2ATI_remap_index]
+#define _gloffset_ColorFragmentOp3ATI driDispatchRemapTable[ColorFragmentOp3ATI_remap_index]
+#define _gloffset_DeleteFragmentShaderATI driDispatchRemapTable[DeleteFragmentShaderATI_remap_index]
+#define _gloffset_EndFragmentShaderATI driDispatchRemapTable[EndFragmentShaderATI_remap_index]
+#define _gloffset_GenFragmentShadersATI driDispatchRemapTable[GenFragmentShadersATI_remap_index]
+#define _gloffset_PassTexCoordATI driDispatchRemapTable[PassTexCoordATI_remap_index]
+#define _gloffset_SampleMapATI driDispatchRemapTable[SampleMapATI_remap_index]
+#define _gloffset_SetFragmentShaderConstantATI driDispatchRemapTable[SetFragmentShaderConstantATI_remap_index]
+#define _gloffset_PointParameteriNV driDispatchRemapTable[PointParameteriNV_remap_index]
+#define _gloffset_PointParameterivNV driDispatchRemapTable[PointParameterivNV_remap_index]
+#define _gloffset_ActiveStencilFaceEXT driDispatchRemapTable[ActiveStencilFaceEXT_remap_index]
+#define _gloffset_BindVertexArrayAPPLE driDispatchRemapTable[BindVertexArrayAPPLE_remap_index]
+#define _gloffset_DeleteVertexArraysAPPLE driDispatchRemapTable[DeleteVertexArraysAPPLE_remap_index]
+#define _gloffset_GenVertexArraysAPPLE driDispatchRemapTable[GenVertexArraysAPPLE_remap_index]
+#define _gloffset_IsVertexArrayAPPLE driDispatchRemapTable[IsVertexArrayAPPLE_remap_index]
+#define _gloffset_GetProgramNamedParameterdvNV driDispatchRemapTable[GetProgramNamedParameterdvNV_remap_index]
+#define _gloffset_GetProgramNamedParameterfvNV driDispatchRemapTable[GetProgramNamedParameterfvNV_remap_index]
+#define _gloffset_ProgramNamedParameter4dNV driDispatchRemapTable[ProgramNamedParameter4dNV_remap_index]
+#define _gloffset_ProgramNamedParameter4dvNV driDispatchRemapTable[ProgramNamedParameter4dvNV_remap_index]
+#define _gloffset_ProgramNamedParameter4fNV driDispatchRemapTable[ProgramNamedParameter4fNV_remap_index]
+#define _gloffset_ProgramNamedParameter4fvNV driDispatchRemapTable[ProgramNamedParameter4fvNV_remap_index]
+#define _gloffset_DepthBoundsEXT driDispatchRemapTable[DepthBoundsEXT_remap_index]
+#define _gloffset_BlendEquationSeparateEXT driDispatchRemapTable[BlendEquationSeparateEXT_remap_index]
+#define _gloffset_BindFramebufferEXT driDispatchRemapTable[BindFramebufferEXT_remap_index]
+#define _gloffset_BindRenderbufferEXT driDispatchRemapTable[BindRenderbufferEXT_remap_index]
+#define _gloffset_CheckFramebufferStatusEXT driDispatchRemapTable[CheckFramebufferStatusEXT_remap_index]
+#define _gloffset_DeleteFramebuffersEXT driDispatchRemapTable[DeleteFramebuffersEXT_remap_index]
+#define _gloffset_DeleteRenderbuffersEXT driDispatchRemapTable[DeleteRenderbuffersEXT_remap_index]
+#define _gloffset_FramebufferRenderbufferEXT driDispatchRemapTable[FramebufferRenderbufferEXT_remap_index]
+#define _gloffset_FramebufferTexture1DEXT driDispatchRemapTable[FramebufferTexture1DEXT_remap_index]
+#define _gloffset_FramebufferTexture2DEXT driDispatchRemapTable[FramebufferTexture2DEXT_remap_index]
+#define _gloffset_FramebufferTexture3DEXT driDispatchRemapTable[FramebufferTexture3DEXT_remap_index]
+#define _gloffset_GenFramebuffersEXT driDispatchRemapTable[GenFramebuffersEXT_remap_index]
+#define _gloffset_GenRenderbuffersEXT driDispatchRemapTable[GenRenderbuffersEXT_remap_index]
+#define _gloffset_GenerateMipmapEXT driDispatchRemapTable[GenerateMipmapEXT_remap_index]
+#define _gloffset_GetFramebufferAttachmentParameterivEXT driDispatchRemapTable[GetFramebufferAttachmentParameterivEXT_remap_index]
+#define _gloffset_GetRenderbufferParameterivEXT driDispatchRemapTable[GetRenderbufferParameterivEXT_remap_index]
+#define _gloffset_IsFramebufferEXT driDispatchRemapTable[IsFramebufferEXT_remap_index]
+#define _gloffset_IsRenderbufferEXT driDispatchRemapTable[IsRenderbufferEXT_remap_index]
+#define _gloffset_RenderbufferStorageEXT driDispatchRemapTable[RenderbufferStorageEXT_remap_index]
+#define _gloffset_BlitFramebufferEXT driDispatchRemapTable[BlitFramebufferEXT_remap_index]
+#define _gloffset_BufferParameteriAPPLE driDispatchRemapTable[BufferParameteriAPPLE_remap_index]
+#define _gloffset_FlushMappedBufferRangeAPPLE driDispatchRemapTable[FlushMappedBufferRangeAPPLE_remap_index]
+#define _gloffset_FramebufferTextureLayerEXT driDispatchRemapTable[FramebufferTextureLayerEXT_remap_index]
+#define _gloffset_ProvokingVertexEXT driDispatchRemapTable[ProvokingVertexEXT_remap_index]
+#define _gloffset_GetTexParameterPointervAPPLE driDispatchRemapTable[GetTexParameterPointervAPPLE_remap_index]
+#define _gloffset_TextureRangeAPPLE driDispatchRemapTable[TextureRangeAPPLE_remap_index]
+#define _gloffset_StencilFuncSeparateATI driDispatchRemapTable[StencilFuncSeparateATI_remap_index]
+#define _gloffset_ProgramEnvParameters4fvEXT driDispatchRemapTable[ProgramEnvParameters4fvEXT_remap_index]
+#define _gloffset_ProgramLocalParameters4fvEXT driDispatchRemapTable[ProgramLocalParameters4fvEXT_remap_index]
+#define _gloffset_GetQueryObjecti64vEXT driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index]
+#define _gloffset_GetQueryObjectui64vEXT driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index]
+
+#endif /* !defined(IN_DRI_DRIVER) */
+
+#endif /* !defined( _GLAPI_OFFSETS_H_ ) */
diff --git a/mesalib/src/mesa/glapi/glapitable.h b/mesalib/src/mesa/glapi/glapitable.h
new file mode 100644
index 000000000..855fcaa7f
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapitable.h
@@ -0,0 +1,837 @@
+/* DO NOT EDIT - This file generated automatically by gl_table.py (from Mesa) script */
+
+/*
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL, IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined( _GLAPI_TABLE_H_ )
+# define _GLAPI_TABLE_H_
+
+#ifndef GLAPIENTRYP
+# ifndef GLAPIENTRY
+# define GLAPIENTRY
+# endif
+
+# define GLAPIENTRYP GLAPIENTRY *
+#endif
+
+
+struct _glapi_table
+{
+ void (GLAPIENTRYP NewList)(GLuint list, GLenum mode); /* 0 */
+ void (GLAPIENTRYP EndList)(void); /* 1 */
+ void (GLAPIENTRYP CallList)(GLuint list); /* 2 */
+ void (GLAPIENTRYP CallLists)(GLsizei n, GLenum type, const GLvoid * lists); /* 3 */
+ void (GLAPIENTRYP DeleteLists)(GLuint list, GLsizei range); /* 4 */
+ GLuint (GLAPIENTRYP GenLists)(GLsizei range); /* 5 */
+ void (GLAPIENTRYP ListBase)(GLuint base); /* 6 */
+ void (GLAPIENTRYP Begin)(GLenum mode); /* 7 */
+ void (GLAPIENTRYP Bitmap)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap); /* 8 */
+ void (GLAPIENTRYP Color3b)(GLbyte red, GLbyte green, GLbyte blue); /* 9 */
+ void (GLAPIENTRYP Color3bv)(const GLbyte * v); /* 10 */
+ void (GLAPIENTRYP Color3d)(GLdouble red, GLdouble green, GLdouble blue); /* 11 */
+ void (GLAPIENTRYP Color3dv)(const GLdouble * v); /* 12 */
+ void (GLAPIENTRYP Color3f)(GLfloat red, GLfloat green, GLfloat blue); /* 13 */
+ void (GLAPIENTRYP Color3fv)(const GLfloat * v); /* 14 */
+ void (GLAPIENTRYP Color3i)(GLint red, GLint green, GLint blue); /* 15 */
+ void (GLAPIENTRYP Color3iv)(const GLint * v); /* 16 */
+ void (GLAPIENTRYP Color3s)(GLshort red, GLshort green, GLshort blue); /* 17 */
+ void (GLAPIENTRYP Color3sv)(const GLshort * v); /* 18 */
+ void (GLAPIENTRYP Color3ub)(GLubyte red, GLubyte green, GLubyte blue); /* 19 */
+ void (GLAPIENTRYP Color3ubv)(const GLubyte * v); /* 20 */
+ void (GLAPIENTRYP Color3ui)(GLuint red, GLuint green, GLuint blue); /* 21 */
+ void (GLAPIENTRYP Color3uiv)(const GLuint * v); /* 22 */
+ void (GLAPIENTRYP Color3us)(GLushort red, GLushort green, GLushort blue); /* 23 */
+ void (GLAPIENTRYP Color3usv)(const GLushort * v); /* 24 */
+ void (GLAPIENTRYP Color4b)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); /* 25 */
+ void (GLAPIENTRYP Color4bv)(const GLbyte * v); /* 26 */
+ void (GLAPIENTRYP Color4d)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); /* 27 */
+ void (GLAPIENTRYP Color4dv)(const GLdouble * v); /* 28 */
+ void (GLAPIENTRYP Color4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); /* 29 */
+ void (GLAPIENTRYP Color4fv)(const GLfloat * v); /* 30 */
+ void (GLAPIENTRYP Color4i)(GLint red, GLint green, GLint blue, GLint alpha); /* 31 */
+ void (GLAPIENTRYP Color4iv)(const GLint * v); /* 32 */
+ void (GLAPIENTRYP Color4s)(GLshort red, GLshort green, GLshort blue, GLshort alpha); /* 33 */
+ void (GLAPIENTRYP Color4sv)(const GLshort * v); /* 34 */
+ void (GLAPIENTRYP Color4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); /* 35 */
+ void (GLAPIENTRYP Color4ubv)(const GLubyte * v); /* 36 */
+ void (GLAPIENTRYP Color4ui)(GLuint red, GLuint green, GLuint blue, GLuint alpha); /* 37 */
+ void (GLAPIENTRYP Color4uiv)(const GLuint * v); /* 38 */
+ void (GLAPIENTRYP Color4us)(GLushort red, GLushort green, GLushort blue, GLushort alpha); /* 39 */
+ void (GLAPIENTRYP Color4usv)(const GLushort * v); /* 40 */
+ void (GLAPIENTRYP EdgeFlag)(GLboolean flag); /* 41 */
+ void (GLAPIENTRYP EdgeFlagv)(const GLboolean * flag); /* 42 */
+ void (GLAPIENTRYP End)(void); /* 43 */
+ void (GLAPIENTRYP Indexd)(GLdouble c); /* 44 */
+ void (GLAPIENTRYP Indexdv)(const GLdouble * c); /* 45 */
+ void (GLAPIENTRYP Indexf)(GLfloat c); /* 46 */
+ void (GLAPIENTRYP Indexfv)(const GLfloat * c); /* 47 */
+ void (GLAPIENTRYP Indexi)(GLint c); /* 48 */
+ void (GLAPIENTRYP Indexiv)(const GLint * c); /* 49 */
+ void (GLAPIENTRYP Indexs)(GLshort c); /* 50 */
+ void (GLAPIENTRYP Indexsv)(const GLshort * c); /* 51 */
+ void (GLAPIENTRYP Normal3b)(GLbyte nx, GLbyte ny, GLbyte nz); /* 52 */
+ void (GLAPIENTRYP Normal3bv)(const GLbyte * v); /* 53 */
+ void (GLAPIENTRYP Normal3d)(GLdouble nx, GLdouble ny, GLdouble nz); /* 54 */
+ void (GLAPIENTRYP Normal3dv)(const GLdouble * v); /* 55 */
+ void (GLAPIENTRYP Normal3f)(GLfloat nx, GLfloat ny, GLfloat nz); /* 56 */
+ void (GLAPIENTRYP Normal3fv)(const GLfloat * v); /* 57 */
+ void (GLAPIENTRYP Normal3i)(GLint nx, GLint ny, GLint nz); /* 58 */
+ void (GLAPIENTRYP Normal3iv)(const GLint * v); /* 59 */
+ void (GLAPIENTRYP Normal3s)(GLshort nx, GLshort ny, GLshort nz); /* 60 */
+ void (GLAPIENTRYP Normal3sv)(const GLshort * v); /* 61 */
+ void (GLAPIENTRYP RasterPos2d)(GLdouble x, GLdouble y); /* 62 */
+ void (GLAPIENTRYP RasterPos2dv)(const GLdouble * v); /* 63 */
+ void (GLAPIENTRYP RasterPos2f)(GLfloat x, GLfloat y); /* 64 */
+ void (GLAPIENTRYP RasterPos2fv)(const GLfloat * v); /* 65 */
+ void (GLAPIENTRYP RasterPos2i)(GLint x, GLint y); /* 66 */
+ void (GLAPIENTRYP RasterPos2iv)(const GLint * v); /* 67 */
+ void (GLAPIENTRYP RasterPos2s)(GLshort x, GLshort y); /* 68 */
+ void (GLAPIENTRYP RasterPos2sv)(const GLshort * v); /* 69 */
+ void (GLAPIENTRYP RasterPos3d)(GLdouble x, GLdouble y, GLdouble z); /* 70 */
+ void (GLAPIENTRYP RasterPos3dv)(const GLdouble * v); /* 71 */
+ void (GLAPIENTRYP RasterPos3f)(GLfloat x, GLfloat y, GLfloat z); /* 72 */
+ void (GLAPIENTRYP RasterPos3fv)(const GLfloat * v); /* 73 */
+ void (GLAPIENTRYP RasterPos3i)(GLint x, GLint y, GLint z); /* 74 */
+ void (GLAPIENTRYP RasterPos3iv)(const GLint * v); /* 75 */
+ void (GLAPIENTRYP RasterPos3s)(GLshort x, GLshort y, GLshort z); /* 76 */
+ void (GLAPIENTRYP RasterPos3sv)(const GLshort * v); /* 77 */
+ void (GLAPIENTRYP RasterPos4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 78 */
+ void (GLAPIENTRYP RasterPos4dv)(const GLdouble * v); /* 79 */
+ void (GLAPIENTRYP RasterPos4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 80 */
+ void (GLAPIENTRYP RasterPos4fv)(const GLfloat * v); /* 81 */
+ void (GLAPIENTRYP RasterPos4i)(GLint x, GLint y, GLint z, GLint w); /* 82 */
+ void (GLAPIENTRYP RasterPos4iv)(const GLint * v); /* 83 */
+ void (GLAPIENTRYP RasterPos4s)(GLshort x, GLshort y, GLshort z, GLshort w); /* 84 */
+ void (GLAPIENTRYP RasterPos4sv)(const GLshort * v); /* 85 */
+ void (GLAPIENTRYP Rectd)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); /* 86 */
+ void (GLAPIENTRYP Rectdv)(const GLdouble * v1, const GLdouble * v2); /* 87 */
+ void (GLAPIENTRYP Rectf)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); /* 88 */
+ void (GLAPIENTRYP Rectfv)(const GLfloat * v1, const GLfloat * v2); /* 89 */
+ void (GLAPIENTRYP Recti)(GLint x1, GLint y1, GLint x2, GLint y2); /* 90 */
+ void (GLAPIENTRYP Rectiv)(const GLint * v1, const GLint * v2); /* 91 */
+ void (GLAPIENTRYP Rects)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); /* 92 */
+ void (GLAPIENTRYP Rectsv)(const GLshort * v1, const GLshort * v2); /* 93 */
+ void (GLAPIENTRYP TexCoord1d)(GLdouble s); /* 94 */
+ void (GLAPIENTRYP TexCoord1dv)(const GLdouble * v); /* 95 */
+ void (GLAPIENTRYP TexCoord1f)(GLfloat s); /* 96 */
+ void (GLAPIENTRYP TexCoord1fv)(const GLfloat * v); /* 97 */
+ void (GLAPIENTRYP TexCoord1i)(GLint s); /* 98 */
+ void (GLAPIENTRYP TexCoord1iv)(const GLint * v); /* 99 */
+ void (GLAPIENTRYP TexCoord1s)(GLshort s); /* 100 */
+ void (GLAPIENTRYP TexCoord1sv)(const GLshort * v); /* 101 */
+ void (GLAPIENTRYP TexCoord2d)(GLdouble s, GLdouble t); /* 102 */
+ void (GLAPIENTRYP TexCoord2dv)(const GLdouble * v); /* 103 */
+ void (GLAPIENTRYP TexCoord2f)(GLfloat s, GLfloat t); /* 104 */
+ void (GLAPIENTRYP TexCoord2fv)(const GLfloat * v); /* 105 */
+ void (GLAPIENTRYP TexCoord2i)(GLint s, GLint t); /* 106 */
+ void (GLAPIENTRYP TexCoord2iv)(const GLint * v); /* 107 */
+ void (GLAPIENTRYP TexCoord2s)(GLshort s, GLshort t); /* 108 */
+ void (GLAPIENTRYP TexCoord2sv)(const GLshort * v); /* 109 */
+ void (GLAPIENTRYP TexCoord3d)(GLdouble s, GLdouble t, GLdouble r); /* 110 */
+ void (GLAPIENTRYP TexCoord3dv)(const GLdouble * v); /* 111 */
+ void (GLAPIENTRYP TexCoord3f)(GLfloat s, GLfloat t, GLfloat r); /* 112 */
+ void (GLAPIENTRYP TexCoord3fv)(const GLfloat * v); /* 113 */
+ void (GLAPIENTRYP TexCoord3i)(GLint s, GLint t, GLint r); /* 114 */
+ void (GLAPIENTRYP TexCoord3iv)(const GLint * v); /* 115 */
+ void (GLAPIENTRYP TexCoord3s)(GLshort s, GLshort t, GLshort r); /* 116 */
+ void (GLAPIENTRYP TexCoord3sv)(const GLshort * v); /* 117 */
+ void (GLAPIENTRYP TexCoord4d)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); /* 118 */
+ void (GLAPIENTRYP TexCoord4dv)(const GLdouble * v); /* 119 */
+ void (GLAPIENTRYP TexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); /* 120 */
+ void (GLAPIENTRYP TexCoord4fv)(const GLfloat * v); /* 121 */
+ void (GLAPIENTRYP TexCoord4i)(GLint s, GLint t, GLint r, GLint q); /* 122 */
+ void (GLAPIENTRYP TexCoord4iv)(const GLint * v); /* 123 */
+ void (GLAPIENTRYP TexCoord4s)(GLshort s, GLshort t, GLshort r, GLshort q); /* 124 */
+ void (GLAPIENTRYP TexCoord4sv)(const GLshort * v); /* 125 */
+ void (GLAPIENTRYP Vertex2d)(GLdouble x, GLdouble y); /* 126 */
+ void (GLAPIENTRYP Vertex2dv)(const GLdouble * v); /* 127 */
+ void (GLAPIENTRYP Vertex2f)(GLfloat x, GLfloat y); /* 128 */
+ void (GLAPIENTRYP Vertex2fv)(const GLfloat * v); /* 129 */
+ void (GLAPIENTRYP Vertex2i)(GLint x, GLint y); /* 130 */
+ void (GLAPIENTRYP Vertex2iv)(const GLint * v); /* 131 */
+ void (GLAPIENTRYP Vertex2s)(GLshort x, GLshort y); /* 132 */
+ void (GLAPIENTRYP Vertex2sv)(const GLshort * v); /* 133 */
+ void (GLAPIENTRYP Vertex3d)(GLdouble x, GLdouble y, GLdouble z); /* 134 */
+ void (GLAPIENTRYP Vertex3dv)(const GLdouble * v); /* 135 */
+ void (GLAPIENTRYP Vertex3f)(GLfloat x, GLfloat y, GLfloat z); /* 136 */
+ void (GLAPIENTRYP Vertex3fv)(const GLfloat * v); /* 137 */
+ void (GLAPIENTRYP Vertex3i)(GLint x, GLint y, GLint z); /* 138 */
+ void (GLAPIENTRYP Vertex3iv)(const GLint * v); /* 139 */
+ void (GLAPIENTRYP Vertex3s)(GLshort x, GLshort y, GLshort z); /* 140 */
+ void (GLAPIENTRYP Vertex3sv)(const GLshort * v); /* 141 */
+ void (GLAPIENTRYP Vertex4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 142 */
+ void (GLAPIENTRYP Vertex4dv)(const GLdouble * v); /* 143 */
+ void (GLAPIENTRYP Vertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 144 */
+ void (GLAPIENTRYP Vertex4fv)(const GLfloat * v); /* 145 */
+ void (GLAPIENTRYP Vertex4i)(GLint x, GLint y, GLint z, GLint w); /* 146 */
+ void (GLAPIENTRYP Vertex4iv)(const GLint * v); /* 147 */
+ void (GLAPIENTRYP Vertex4s)(GLshort x, GLshort y, GLshort z, GLshort w); /* 148 */
+ void (GLAPIENTRYP Vertex4sv)(const GLshort * v); /* 149 */
+ void (GLAPIENTRYP ClipPlane)(GLenum plane, const GLdouble * equation); /* 150 */
+ void (GLAPIENTRYP ColorMaterial)(GLenum face, GLenum mode); /* 151 */
+ void (GLAPIENTRYP CullFace)(GLenum mode); /* 152 */
+ void (GLAPIENTRYP Fogf)(GLenum pname, GLfloat param); /* 153 */
+ void (GLAPIENTRYP Fogfv)(GLenum pname, const GLfloat * params); /* 154 */
+ void (GLAPIENTRYP Fogi)(GLenum pname, GLint param); /* 155 */
+ void (GLAPIENTRYP Fogiv)(GLenum pname, const GLint * params); /* 156 */
+ void (GLAPIENTRYP FrontFace)(GLenum mode); /* 157 */
+ void (GLAPIENTRYP Hint)(GLenum target, GLenum mode); /* 158 */
+ void (GLAPIENTRYP Lightf)(GLenum light, GLenum pname, GLfloat param); /* 159 */
+ void (GLAPIENTRYP Lightfv)(GLenum light, GLenum pname, const GLfloat * params); /* 160 */
+ void (GLAPIENTRYP Lighti)(GLenum light, GLenum pname, GLint param); /* 161 */
+ void (GLAPIENTRYP Lightiv)(GLenum light, GLenum pname, const GLint * params); /* 162 */
+ void (GLAPIENTRYP LightModelf)(GLenum pname, GLfloat param); /* 163 */
+ void (GLAPIENTRYP LightModelfv)(GLenum pname, const GLfloat * params); /* 164 */
+ void (GLAPIENTRYP LightModeli)(GLenum pname, GLint param); /* 165 */
+ void (GLAPIENTRYP LightModeliv)(GLenum pname, const GLint * params); /* 166 */
+ void (GLAPIENTRYP LineStipple)(GLint factor, GLushort pattern); /* 167 */
+ void (GLAPIENTRYP LineWidth)(GLfloat width); /* 168 */
+ void (GLAPIENTRYP Materialf)(GLenum face, GLenum pname, GLfloat param); /* 169 */
+ void (GLAPIENTRYP Materialfv)(GLenum face, GLenum pname, const GLfloat * params); /* 170 */
+ void (GLAPIENTRYP Materiali)(GLenum face, GLenum pname, GLint param); /* 171 */
+ void (GLAPIENTRYP Materialiv)(GLenum face, GLenum pname, const GLint * params); /* 172 */
+ void (GLAPIENTRYP PointSize)(GLfloat size); /* 173 */
+ void (GLAPIENTRYP PolygonMode)(GLenum face, GLenum mode); /* 174 */
+ void (GLAPIENTRYP PolygonStipple)(const GLubyte * mask); /* 175 */
+ void (GLAPIENTRYP Scissor)(GLint x, GLint y, GLsizei width, GLsizei height); /* 176 */
+ void (GLAPIENTRYP ShadeModel)(GLenum mode); /* 177 */
+ void (GLAPIENTRYP TexParameterf)(GLenum target, GLenum pname, GLfloat param); /* 178 */
+ void (GLAPIENTRYP TexParameterfv)(GLenum target, GLenum pname, const GLfloat * params); /* 179 */
+ void (GLAPIENTRYP TexParameteri)(GLenum target, GLenum pname, GLint param); /* 180 */
+ void (GLAPIENTRYP TexParameteriv)(GLenum target, GLenum pname, const GLint * params); /* 181 */
+ void (GLAPIENTRYP TexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels); /* 182 */
+ void (GLAPIENTRYP TexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels); /* 183 */
+ void (GLAPIENTRYP TexEnvf)(GLenum target, GLenum pname, GLfloat param); /* 184 */
+ void (GLAPIENTRYP TexEnvfv)(GLenum target, GLenum pname, const GLfloat * params); /* 185 */
+ void (GLAPIENTRYP TexEnvi)(GLenum target, GLenum pname, GLint param); /* 186 */
+ void (GLAPIENTRYP TexEnviv)(GLenum target, GLenum pname, const GLint * params); /* 187 */
+ void (GLAPIENTRYP TexGend)(GLenum coord, GLenum pname, GLdouble param); /* 188 */
+ void (GLAPIENTRYP TexGendv)(GLenum coord, GLenum pname, const GLdouble * params); /* 189 */
+ void (GLAPIENTRYP TexGenf)(GLenum coord, GLenum pname, GLfloat param); /* 190 */
+ void (GLAPIENTRYP TexGenfv)(GLenum coord, GLenum pname, const GLfloat * params); /* 191 */
+ void (GLAPIENTRYP TexGeni)(GLenum coord, GLenum pname, GLint param); /* 192 */
+ void (GLAPIENTRYP TexGeniv)(GLenum coord, GLenum pname, const GLint * params); /* 193 */
+ void (GLAPIENTRYP FeedbackBuffer)(GLsizei size, GLenum type, GLfloat * buffer); /* 194 */
+ void (GLAPIENTRYP SelectBuffer)(GLsizei size, GLuint * buffer); /* 195 */
+ GLint (GLAPIENTRYP RenderMode)(GLenum mode); /* 196 */
+ void (GLAPIENTRYP InitNames)(void); /* 197 */
+ void (GLAPIENTRYP LoadName)(GLuint name); /* 198 */
+ void (GLAPIENTRYP PassThrough)(GLfloat token); /* 199 */
+ void (GLAPIENTRYP PopName)(void); /* 200 */
+ void (GLAPIENTRYP PushName)(GLuint name); /* 201 */
+ void (GLAPIENTRYP DrawBuffer)(GLenum mode); /* 202 */
+ void (GLAPIENTRYP Clear)(GLbitfield mask); /* 203 */
+ void (GLAPIENTRYP ClearAccum)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); /* 204 */
+ void (GLAPIENTRYP ClearIndex)(GLfloat c); /* 205 */
+ void (GLAPIENTRYP ClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); /* 206 */
+ void (GLAPIENTRYP ClearStencil)(GLint s); /* 207 */
+ void (GLAPIENTRYP ClearDepth)(GLclampd depth); /* 208 */
+ void (GLAPIENTRYP StencilMask)(GLuint mask); /* 209 */
+ void (GLAPIENTRYP ColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); /* 210 */
+ void (GLAPIENTRYP DepthMask)(GLboolean flag); /* 211 */
+ void (GLAPIENTRYP IndexMask)(GLuint mask); /* 212 */
+ void (GLAPIENTRYP Accum)(GLenum op, GLfloat value); /* 213 */
+ void (GLAPIENTRYP Disable)(GLenum cap); /* 214 */
+ void (GLAPIENTRYP Enable)(GLenum cap); /* 215 */
+ void (GLAPIENTRYP Finish)(void); /* 216 */
+ void (GLAPIENTRYP Flush)(void); /* 217 */
+ void (GLAPIENTRYP PopAttrib)(void); /* 218 */
+ void (GLAPIENTRYP PushAttrib)(GLbitfield mask); /* 219 */
+ void (GLAPIENTRYP Map1d)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points); /* 220 */
+ void (GLAPIENTRYP Map1f)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points); /* 221 */
+ void (GLAPIENTRYP Map2d)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points); /* 222 */
+ void (GLAPIENTRYP Map2f)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points); /* 223 */
+ void (GLAPIENTRYP MapGrid1d)(GLint un, GLdouble u1, GLdouble u2); /* 224 */
+ void (GLAPIENTRYP MapGrid1f)(GLint un, GLfloat u1, GLfloat u2); /* 225 */
+ void (GLAPIENTRYP MapGrid2d)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); /* 226 */
+ void (GLAPIENTRYP MapGrid2f)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); /* 227 */
+ void (GLAPIENTRYP EvalCoord1d)(GLdouble u); /* 228 */
+ void (GLAPIENTRYP EvalCoord1dv)(const GLdouble * u); /* 229 */
+ void (GLAPIENTRYP EvalCoord1f)(GLfloat u); /* 230 */
+ void (GLAPIENTRYP EvalCoord1fv)(const GLfloat * u); /* 231 */
+ void (GLAPIENTRYP EvalCoord2d)(GLdouble u, GLdouble v); /* 232 */
+ void (GLAPIENTRYP EvalCoord2dv)(const GLdouble * u); /* 233 */
+ void (GLAPIENTRYP EvalCoord2f)(GLfloat u, GLfloat v); /* 234 */
+ void (GLAPIENTRYP EvalCoord2fv)(const GLfloat * u); /* 235 */
+ void (GLAPIENTRYP EvalMesh1)(GLenum mode, GLint i1, GLint i2); /* 236 */
+ void (GLAPIENTRYP EvalPoint1)(GLint i); /* 237 */
+ void (GLAPIENTRYP EvalMesh2)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); /* 238 */
+ void (GLAPIENTRYP EvalPoint2)(GLint i, GLint j); /* 239 */
+ void (GLAPIENTRYP AlphaFunc)(GLenum func, GLclampf ref); /* 240 */
+ void (GLAPIENTRYP BlendFunc)(GLenum sfactor, GLenum dfactor); /* 241 */
+ void (GLAPIENTRYP LogicOp)(GLenum opcode); /* 242 */
+ void (GLAPIENTRYP StencilFunc)(GLenum func, GLint ref, GLuint mask); /* 243 */
+ void (GLAPIENTRYP StencilOp)(GLenum fail, GLenum zfail, GLenum zpass); /* 244 */
+ void (GLAPIENTRYP DepthFunc)(GLenum func); /* 245 */
+ void (GLAPIENTRYP PixelZoom)(GLfloat xfactor, GLfloat yfactor); /* 246 */
+ void (GLAPIENTRYP PixelTransferf)(GLenum pname, GLfloat param); /* 247 */
+ void (GLAPIENTRYP PixelTransferi)(GLenum pname, GLint param); /* 248 */
+ void (GLAPIENTRYP PixelStoref)(GLenum pname, GLfloat param); /* 249 */
+ void (GLAPIENTRYP PixelStorei)(GLenum pname, GLint param); /* 250 */
+ void (GLAPIENTRYP PixelMapfv)(GLenum map, GLsizei mapsize, const GLfloat * values); /* 251 */
+ void (GLAPIENTRYP PixelMapuiv)(GLenum map, GLsizei mapsize, const GLuint * values); /* 252 */
+ void (GLAPIENTRYP PixelMapusv)(GLenum map, GLsizei mapsize, const GLushort * values); /* 253 */
+ void (GLAPIENTRYP ReadBuffer)(GLenum mode); /* 254 */
+ void (GLAPIENTRYP CopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); /* 255 */
+ void (GLAPIENTRYP ReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * pixels); /* 256 */
+ void (GLAPIENTRYP DrawPixels)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); /* 257 */
+ void (GLAPIENTRYP GetBooleanv)(GLenum pname, GLboolean * params); /* 258 */
+ void (GLAPIENTRYP GetClipPlane)(GLenum plane, GLdouble * equation); /* 259 */
+ void (GLAPIENTRYP GetDoublev)(GLenum pname, GLdouble * params); /* 260 */
+ GLenum (GLAPIENTRYP GetError)(void); /* 261 */
+ void (GLAPIENTRYP GetFloatv)(GLenum pname, GLfloat * params); /* 262 */
+ void (GLAPIENTRYP GetIntegerv)(GLenum pname, GLint * params); /* 263 */
+ void (GLAPIENTRYP GetLightfv)(GLenum light, GLenum pname, GLfloat * params); /* 264 */
+ void (GLAPIENTRYP GetLightiv)(GLenum light, GLenum pname, GLint * params); /* 265 */
+ void (GLAPIENTRYP GetMapdv)(GLenum target, GLenum query, GLdouble * v); /* 266 */
+ void (GLAPIENTRYP GetMapfv)(GLenum target, GLenum query, GLfloat * v); /* 267 */
+ void (GLAPIENTRYP GetMapiv)(GLenum target, GLenum query, GLint * v); /* 268 */
+ void (GLAPIENTRYP GetMaterialfv)(GLenum face, GLenum pname, GLfloat * params); /* 269 */
+ void (GLAPIENTRYP GetMaterialiv)(GLenum face, GLenum pname, GLint * params); /* 270 */
+ void (GLAPIENTRYP GetPixelMapfv)(GLenum map, GLfloat * values); /* 271 */
+ void (GLAPIENTRYP GetPixelMapuiv)(GLenum map, GLuint * values); /* 272 */
+ void (GLAPIENTRYP GetPixelMapusv)(GLenum map, GLushort * values); /* 273 */
+ void (GLAPIENTRYP GetPolygonStipple)(GLubyte * mask); /* 274 */
+ const GLubyte * (GLAPIENTRYP GetString)(GLenum name); /* 275 */
+ void (GLAPIENTRYP GetTexEnvfv)(GLenum target, GLenum pname, GLfloat * params); /* 276 */
+ void (GLAPIENTRYP GetTexEnviv)(GLenum target, GLenum pname, GLint * params); /* 277 */
+ void (GLAPIENTRYP GetTexGendv)(GLenum coord, GLenum pname, GLdouble * params); /* 278 */
+ void (GLAPIENTRYP GetTexGenfv)(GLenum coord, GLenum pname, GLfloat * params); /* 279 */
+ void (GLAPIENTRYP GetTexGeniv)(GLenum coord, GLenum pname, GLint * params); /* 280 */
+ void (GLAPIENTRYP GetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels); /* 281 */
+ void (GLAPIENTRYP GetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params); /* 282 */
+ void (GLAPIENTRYP GetTexParameteriv)(GLenum target, GLenum pname, GLint * params); /* 283 */
+ void (GLAPIENTRYP GetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params); /* 284 */
+ void (GLAPIENTRYP GetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params); /* 285 */
+ GLboolean (GLAPIENTRYP IsEnabled)(GLenum cap); /* 286 */
+ GLboolean (GLAPIENTRYP IsList)(GLuint list); /* 287 */
+ void (GLAPIENTRYP DepthRange)(GLclampd zNear, GLclampd zFar); /* 288 */
+ void (GLAPIENTRYP Frustum)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); /* 289 */
+ void (GLAPIENTRYP LoadIdentity)(void); /* 290 */
+ void (GLAPIENTRYP LoadMatrixf)(const GLfloat * m); /* 291 */
+ void (GLAPIENTRYP LoadMatrixd)(const GLdouble * m); /* 292 */
+ void (GLAPIENTRYP MatrixMode)(GLenum mode); /* 293 */
+ void (GLAPIENTRYP MultMatrixf)(const GLfloat * m); /* 294 */
+ void (GLAPIENTRYP MultMatrixd)(const GLdouble * m); /* 295 */
+ void (GLAPIENTRYP Ortho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); /* 296 */
+ void (GLAPIENTRYP PopMatrix)(void); /* 297 */
+ void (GLAPIENTRYP PushMatrix)(void); /* 298 */
+ void (GLAPIENTRYP Rotated)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); /* 299 */
+ void (GLAPIENTRYP Rotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); /* 300 */
+ void (GLAPIENTRYP Scaled)(GLdouble x, GLdouble y, GLdouble z); /* 301 */
+ void (GLAPIENTRYP Scalef)(GLfloat x, GLfloat y, GLfloat z); /* 302 */
+ void (GLAPIENTRYP Translated)(GLdouble x, GLdouble y, GLdouble z); /* 303 */
+ void (GLAPIENTRYP Translatef)(GLfloat x, GLfloat y, GLfloat z); /* 304 */
+ void (GLAPIENTRYP Viewport)(GLint x, GLint y, GLsizei width, GLsizei height); /* 305 */
+ void (GLAPIENTRYP ArrayElement)(GLint i); /* 306 */
+ void (GLAPIENTRYP BindTexture)(GLenum target, GLuint texture); /* 307 */
+ void (GLAPIENTRYP ColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 308 */
+ void (GLAPIENTRYP DisableClientState)(GLenum array); /* 309 */
+ void (GLAPIENTRYP DrawArrays)(GLenum mode, GLint first, GLsizei count); /* 310 */
+ void (GLAPIENTRYP DrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices); /* 311 */
+ void (GLAPIENTRYP EdgeFlagPointer)(GLsizei stride, const GLvoid * pointer); /* 312 */
+ void (GLAPIENTRYP EnableClientState)(GLenum array); /* 313 */
+ void (GLAPIENTRYP IndexPointer)(GLenum type, GLsizei stride, const GLvoid * pointer); /* 314 */
+ void (GLAPIENTRYP Indexub)(GLubyte c); /* 315 */
+ void (GLAPIENTRYP Indexubv)(const GLubyte * c); /* 316 */
+ void (GLAPIENTRYP InterleavedArrays)(GLenum format, GLsizei stride, const GLvoid * pointer); /* 317 */
+ void (GLAPIENTRYP NormalPointer)(GLenum type, GLsizei stride, const GLvoid * pointer); /* 318 */
+ void (GLAPIENTRYP PolygonOffset)(GLfloat factor, GLfloat units); /* 319 */
+ void (GLAPIENTRYP TexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 320 */
+ void (GLAPIENTRYP VertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 321 */
+ GLboolean (GLAPIENTRYP AreTexturesResident)(GLsizei n, const GLuint * textures, GLboolean * residences); /* 322 */
+ void (GLAPIENTRYP CopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); /* 323 */
+ void (GLAPIENTRYP CopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); /* 324 */
+ void (GLAPIENTRYP CopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); /* 325 */
+ void (GLAPIENTRYP CopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); /* 326 */
+ void (GLAPIENTRYP DeleteTextures)(GLsizei n, const GLuint * textures); /* 327 */
+ void (GLAPIENTRYP GenTextures)(GLsizei n, GLuint * textures); /* 328 */
+ void (GLAPIENTRYP GetPointerv)(GLenum pname, GLvoid ** params); /* 329 */
+ GLboolean (GLAPIENTRYP IsTexture)(GLuint texture); /* 330 */
+ void (GLAPIENTRYP PrioritizeTextures)(GLsizei n, const GLuint * textures, const GLclampf * priorities); /* 331 */
+ void (GLAPIENTRYP TexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels); /* 332 */
+ void (GLAPIENTRYP TexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels); /* 333 */
+ void (GLAPIENTRYP PopClientAttrib)(void); /* 334 */
+ void (GLAPIENTRYP PushClientAttrib)(GLbitfield mask); /* 335 */
+ void (GLAPIENTRYP BlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); /* 336 */
+ void (GLAPIENTRYP BlendEquation)(GLenum mode); /* 337 */
+ void (GLAPIENTRYP DrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices); /* 338 */
+ void (GLAPIENTRYP ColorTable)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table); /* 339 */
+ void (GLAPIENTRYP ColorTableParameterfv)(GLenum target, GLenum pname, const GLfloat * params); /* 340 */
+ void (GLAPIENTRYP ColorTableParameteriv)(GLenum target, GLenum pname, const GLint * params); /* 341 */
+ void (GLAPIENTRYP CopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); /* 342 */
+ void (GLAPIENTRYP GetColorTable)(GLenum target, GLenum format, GLenum type, GLvoid * table); /* 343 */
+ void (GLAPIENTRYP GetColorTableParameterfv)(GLenum target, GLenum pname, GLfloat * params); /* 344 */
+ void (GLAPIENTRYP GetColorTableParameteriv)(GLenum target, GLenum pname, GLint * params); /* 345 */
+ void (GLAPIENTRYP ColorSubTable)(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data); /* 346 */
+ void (GLAPIENTRYP CopyColorSubTable)(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); /* 347 */
+ void (GLAPIENTRYP ConvolutionFilter1D)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image); /* 348 */
+ void (GLAPIENTRYP ConvolutionFilter2D)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image); /* 349 */
+ void (GLAPIENTRYP ConvolutionParameterf)(GLenum target, GLenum pname, GLfloat params); /* 350 */
+ void (GLAPIENTRYP ConvolutionParameterfv)(GLenum target, GLenum pname, const GLfloat * params); /* 351 */
+ void (GLAPIENTRYP ConvolutionParameteri)(GLenum target, GLenum pname, GLint params); /* 352 */
+ void (GLAPIENTRYP ConvolutionParameteriv)(GLenum target, GLenum pname, const GLint * params); /* 353 */
+ void (GLAPIENTRYP CopyConvolutionFilter1D)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); /* 354 */
+ void (GLAPIENTRYP CopyConvolutionFilter2D)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); /* 355 */
+ void (GLAPIENTRYP GetConvolutionFilter)(GLenum target, GLenum format, GLenum type, GLvoid * image); /* 356 */
+ void (GLAPIENTRYP GetConvolutionParameterfv)(GLenum target, GLenum pname, GLfloat * params); /* 357 */
+ void (GLAPIENTRYP GetConvolutionParameteriv)(GLenum target, GLenum pname, GLint * params); /* 358 */
+ void (GLAPIENTRYP GetSeparableFilter)(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span); /* 359 */
+ void (GLAPIENTRYP SeparableFilter2D)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column); /* 360 */
+ void (GLAPIENTRYP GetHistogram)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); /* 361 */
+ void (GLAPIENTRYP GetHistogramParameterfv)(GLenum target, GLenum pname, GLfloat * params); /* 362 */
+ void (GLAPIENTRYP GetHistogramParameteriv)(GLenum target, GLenum pname, GLint * params); /* 363 */
+ void (GLAPIENTRYP GetMinmax)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values); /* 364 */
+ void (GLAPIENTRYP GetMinmaxParameterfv)(GLenum target, GLenum pname, GLfloat * params); /* 365 */
+ void (GLAPIENTRYP GetMinmaxParameteriv)(GLenum target, GLenum pname, GLint * params); /* 366 */
+ void (GLAPIENTRYP Histogram)(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); /* 367 */
+ void (GLAPIENTRYP Minmax)(GLenum target, GLenum internalformat, GLboolean sink); /* 368 */
+ void (GLAPIENTRYP ResetHistogram)(GLenum target); /* 369 */
+ void (GLAPIENTRYP ResetMinmax)(GLenum target); /* 370 */
+ void (GLAPIENTRYP TexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels); /* 371 */
+ void (GLAPIENTRYP TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels); /* 372 */
+ void (GLAPIENTRYP CopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); /* 373 */
+ void (GLAPIENTRYP ActiveTextureARB)(GLenum texture); /* 374 */
+ void (GLAPIENTRYP ClientActiveTextureARB)(GLenum texture); /* 375 */
+ void (GLAPIENTRYP MultiTexCoord1dARB)(GLenum target, GLdouble s); /* 376 */
+ void (GLAPIENTRYP MultiTexCoord1dvARB)(GLenum target, const GLdouble * v); /* 377 */
+ void (GLAPIENTRYP MultiTexCoord1fARB)(GLenum target, GLfloat s); /* 378 */
+ void (GLAPIENTRYP MultiTexCoord1fvARB)(GLenum target, const GLfloat * v); /* 379 */
+ void (GLAPIENTRYP MultiTexCoord1iARB)(GLenum target, GLint s); /* 380 */
+ void (GLAPIENTRYP MultiTexCoord1ivARB)(GLenum target, const GLint * v); /* 381 */
+ void (GLAPIENTRYP MultiTexCoord1sARB)(GLenum target, GLshort s); /* 382 */
+ void (GLAPIENTRYP MultiTexCoord1svARB)(GLenum target, const GLshort * v); /* 383 */
+ void (GLAPIENTRYP MultiTexCoord2dARB)(GLenum target, GLdouble s, GLdouble t); /* 384 */
+ void (GLAPIENTRYP MultiTexCoord2dvARB)(GLenum target, const GLdouble * v); /* 385 */
+ void (GLAPIENTRYP MultiTexCoord2fARB)(GLenum target, GLfloat s, GLfloat t); /* 386 */
+ void (GLAPIENTRYP MultiTexCoord2fvARB)(GLenum target, const GLfloat * v); /* 387 */
+ void (GLAPIENTRYP MultiTexCoord2iARB)(GLenum target, GLint s, GLint t); /* 388 */
+ void (GLAPIENTRYP MultiTexCoord2ivARB)(GLenum target, const GLint * v); /* 389 */
+ void (GLAPIENTRYP MultiTexCoord2sARB)(GLenum target, GLshort s, GLshort t); /* 390 */
+ void (GLAPIENTRYP MultiTexCoord2svARB)(GLenum target, const GLshort * v); /* 391 */
+ void (GLAPIENTRYP MultiTexCoord3dARB)(GLenum target, GLdouble s, GLdouble t, GLdouble r); /* 392 */
+ void (GLAPIENTRYP MultiTexCoord3dvARB)(GLenum target, const GLdouble * v); /* 393 */
+ void (GLAPIENTRYP MultiTexCoord3fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r); /* 394 */
+ void (GLAPIENTRYP MultiTexCoord3fvARB)(GLenum target, const GLfloat * v); /* 395 */
+ void (GLAPIENTRYP MultiTexCoord3iARB)(GLenum target, GLint s, GLint t, GLint r); /* 396 */
+ void (GLAPIENTRYP MultiTexCoord3ivARB)(GLenum target, const GLint * v); /* 397 */
+ void (GLAPIENTRYP MultiTexCoord3sARB)(GLenum target, GLshort s, GLshort t, GLshort r); /* 398 */
+ void (GLAPIENTRYP MultiTexCoord3svARB)(GLenum target, const GLshort * v); /* 399 */
+ void (GLAPIENTRYP MultiTexCoord4dARB)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); /* 400 */
+ void (GLAPIENTRYP MultiTexCoord4dvARB)(GLenum target, const GLdouble * v); /* 401 */
+ void (GLAPIENTRYP MultiTexCoord4fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); /* 402 */
+ void (GLAPIENTRYP MultiTexCoord4fvARB)(GLenum target, const GLfloat * v); /* 403 */
+ void (GLAPIENTRYP MultiTexCoord4iARB)(GLenum target, GLint s, GLint t, GLint r, GLint q); /* 404 */
+ void (GLAPIENTRYP MultiTexCoord4ivARB)(GLenum target, const GLint * v); /* 405 */
+ void (GLAPIENTRYP MultiTexCoord4sARB)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); /* 406 */
+ void (GLAPIENTRYP MultiTexCoord4svARB)(GLenum target, const GLshort * v); /* 407 */
+ void (GLAPIENTRYP AttachShader)(GLuint program, GLuint shader); /* 408 */
+ GLuint (GLAPIENTRYP CreateProgram)(void); /* 409 */
+ GLuint (GLAPIENTRYP CreateShader)(GLenum type); /* 410 */
+ void (GLAPIENTRYP DeleteProgram)(GLuint program); /* 411 */
+ void (GLAPIENTRYP DeleteShader)(GLuint program); /* 412 */
+ void (GLAPIENTRYP DetachShader)(GLuint program, GLuint shader); /* 413 */
+ void (GLAPIENTRYP GetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * obj); /* 414 */
+ void (GLAPIENTRYP GetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); /* 415 */
+ void (GLAPIENTRYP GetProgramiv)(GLuint program, GLenum pname, GLint * params); /* 416 */
+ void (GLAPIENTRYP GetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); /* 417 */
+ void (GLAPIENTRYP GetShaderiv)(GLuint shader, GLenum pname, GLint * params); /* 418 */
+ GLboolean (GLAPIENTRYP IsProgram)(GLuint program); /* 419 */
+ GLboolean (GLAPIENTRYP IsShader)(GLuint shader); /* 420 */
+ void (GLAPIENTRYP StencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); /* 421 */
+ void (GLAPIENTRYP StencilMaskSeparate)(GLenum face, GLuint mask); /* 422 */
+ void (GLAPIENTRYP StencilOpSeparate)(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass); /* 423 */
+ void (GLAPIENTRYP UniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 424 */
+ void (GLAPIENTRYP UniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 425 */
+ void (GLAPIENTRYP UniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 426 */
+ void (GLAPIENTRYP UniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 427 */
+ void (GLAPIENTRYP UniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 428 */
+ void (GLAPIENTRYP UniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 429 */
+ void (GLAPIENTRYP LoadTransposeMatrixdARB)(const GLdouble * m); /* 430 */
+ void (GLAPIENTRYP LoadTransposeMatrixfARB)(const GLfloat * m); /* 431 */
+ void (GLAPIENTRYP MultTransposeMatrixdARB)(const GLdouble * m); /* 432 */
+ void (GLAPIENTRYP MultTransposeMatrixfARB)(const GLfloat * m); /* 433 */
+ void (GLAPIENTRYP SampleCoverageARB)(GLclampf value, GLboolean invert); /* 434 */
+ void (GLAPIENTRYP CompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data); /* 435 */
+ void (GLAPIENTRYP CompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data); /* 436 */
+ void (GLAPIENTRYP CompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data); /* 437 */
+ void (GLAPIENTRYP CompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data); /* 438 */
+ void (GLAPIENTRYP CompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data); /* 439 */
+ void (GLAPIENTRYP CompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data); /* 440 */
+ void (GLAPIENTRYP GetCompressedTexImageARB)(GLenum target, GLint level, GLvoid * img); /* 441 */
+ void (GLAPIENTRYP DisableVertexAttribArrayARB)(GLuint index); /* 442 */
+ void (GLAPIENTRYP EnableVertexAttribArrayARB)(GLuint index); /* 443 */
+ void (GLAPIENTRYP GetProgramEnvParameterdvARB)(GLenum target, GLuint index, GLdouble * params); /* 444 */
+ void (GLAPIENTRYP GetProgramEnvParameterfvARB)(GLenum target, GLuint index, GLfloat * params); /* 445 */
+ void (GLAPIENTRYP GetProgramLocalParameterdvARB)(GLenum target, GLuint index, GLdouble * params); /* 446 */
+ void (GLAPIENTRYP GetProgramLocalParameterfvARB)(GLenum target, GLuint index, GLfloat * params); /* 447 */
+ void (GLAPIENTRYP GetProgramStringARB)(GLenum target, GLenum pname, GLvoid * string); /* 448 */
+ void (GLAPIENTRYP GetProgramivARB)(GLenum target, GLenum pname, GLint * params); /* 449 */
+ void (GLAPIENTRYP GetVertexAttribdvARB)(GLuint index, GLenum pname, GLdouble * params); /* 450 */
+ void (GLAPIENTRYP GetVertexAttribfvARB)(GLuint index, GLenum pname, GLfloat * params); /* 451 */
+ void (GLAPIENTRYP GetVertexAttribivARB)(GLuint index, GLenum pname, GLint * params); /* 452 */
+ void (GLAPIENTRYP ProgramEnvParameter4dARB)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 453 */
+ void (GLAPIENTRYP ProgramEnvParameter4dvARB)(GLenum target, GLuint index, const GLdouble * params); /* 454 */
+ void (GLAPIENTRYP ProgramEnvParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 455 */
+ void (GLAPIENTRYP ProgramEnvParameter4fvARB)(GLenum target, GLuint index, const GLfloat * params); /* 456 */
+ void (GLAPIENTRYP ProgramLocalParameter4dARB)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 457 */
+ void (GLAPIENTRYP ProgramLocalParameter4dvARB)(GLenum target, GLuint index, const GLdouble * params); /* 458 */
+ void (GLAPIENTRYP ProgramLocalParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 459 */
+ void (GLAPIENTRYP ProgramLocalParameter4fvARB)(GLenum target, GLuint index, const GLfloat * params); /* 460 */
+ void (GLAPIENTRYP ProgramStringARB)(GLenum target, GLenum format, GLsizei len, const GLvoid * string); /* 461 */
+ void (GLAPIENTRYP VertexAttrib1dARB)(GLuint index, GLdouble x); /* 462 */
+ void (GLAPIENTRYP VertexAttrib1dvARB)(GLuint index, const GLdouble * v); /* 463 */
+ void (GLAPIENTRYP VertexAttrib1fARB)(GLuint index, GLfloat x); /* 464 */
+ void (GLAPIENTRYP VertexAttrib1fvARB)(GLuint index, const GLfloat * v); /* 465 */
+ void (GLAPIENTRYP VertexAttrib1sARB)(GLuint index, GLshort x); /* 466 */
+ void (GLAPIENTRYP VertexAttrib1svARB)(GLuint index, const GLshort * v); /* 467 */
+ void (GLAPIENTRYP VertexAttrib2dARB)(GLuint index, GLdouble x, GLdouble y); /* 468 */
+ void (GLAPIENTRYP VertexAttrib2dvARB)(GLuint index, const GLdouble * v); /* 469 */
+ void (GLAPIENTRYP VertexAttrib2fARB)(GLuint index, GLfloat x, GLfloat y); /* 470 */
+ void (GLAPIENTRYP VertexAttrib2fvARB)(GLuint index, const GLfloat * v); /* 471 */
+ void (GLAPIENTRYP VertexAttrib2sARB)(GLuint index, GLshort x, GLshort y); /* 472 */
+ void (GLAPIENTRYP VertexAttrib2svARB)(GLuint index, const GLshort * v); /* 473 */
+ void (GLAPIENTRYP VertexAttrib3dARB)(GLuint index, GLdouble x, GLdouble y, GLdouble z); /* 474 */
+ void (GLAPIENTRYP VertexAttrib3dvARB)(GLuint index, const GLdouble * v); /* 475 */
+ void (GLAPIENTRYP VertexAttrib3fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z); /* 476 */
+ void (GLAPIENTRYP VertexAttrib3fvARB)(GLuint index, const GLfloat * v); /* 477 */
+ void (GLAPIENTRYP VertexAttrib3sARB)(GLuint index, GLshort x, GLshort y, GLshort z); /* 478 */
+ void (GLAPIENTRYP VertexAttrib3svARB)(GLuint index, const GLshort * v); /* 479 */
+ void (GLAPIENTRYP VertexAttrib4NbvARB)(GLuint index, const GLbyte * v); /* 480 */
+ void (GLAPIENTRYP VertexAttrib4NivARB)(GLuint index, const GLint * v); /* 481 */
+ void (GLAPIENTRYP VertexAttrib4NsvARB)(GLuint index, const GLshort * v); /* 482 */
+ void (GLAPIENTRYP VertexAttrib4NubARB)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); /* 483 */
+ void (GLAPIENTRYP VertexAttrib4NubvARB)(GLuint index, const GLubyte * v); /* 484 */
+ void (GLAPIENTRYP VertexAttrib4NuivARB)(GLuint index, const GLuint * v); /* 485 */
+ void (GLAPIENTRYP VertexAttrib4NusvARB)(GLuint index, const GLushort * v); /* 486 */
+ void (GLAPIENTRYP VertexAttrib4bvARB)(GLuint index, const GLbyte * v); /* 487 */
+ void (GLAPIENTRYP VertexAttrib4dARB)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 488 */
+ void (GLAPIENTRYP VertexAttrib4dvARB)(GLuint index, const GLdouble * v); /* 489 */
+ void (GLAPIENTRYP VertexAttrib4fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 490 */
+ void (GLAPIENTRYP VertexAttrib4fvARB)(GLuint index, const GLfloat * v); /* 491 */
+ void (GLAPIENTRYP VertexAttrib4ivARB)(GLuint index, const GLint * v); /* 492 */
+ void (GLAPIENTRYP VertexAttrib4sARB)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); /* 493 */
+ void (GLAPIENTRYP VertexAttrib4svARB)(GLuint index, const GLshort * v); /* 494 */
+ void (GLAPIENTRYP VertexAttrib4ubvARB)(GLuint index, const GLubyte * v); /* 495 */
+ void (GLAPIENTRYP VertexAttrib4uivARB)(GLuint index, const GLuint * v); /* 496 */
+ void (GLAPIENTRYP VertexAttrib4usvARB)(GLuint index, const GLushort * v); /* 497 */
+ void (GLAPIENTRYP VertexAttribPointerARB)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); /* 498 */
+ void (GLAPIENTRYP BindBufferARB)(GLenum target, GLuint buffer); /* 499 */
+ void (GLAPIENTRYP BufferDataARB)(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); /* 500 */
+ void (GLAPIENTRYP BufferSubDataARB)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); /* 501 */
+ void (GLAPIENTRYP DeleteBuffersARB)(GLsizei n, const GLuint * buffer); /* 502 */
+ void (GLAPIENTRYP GenBuffersARB)(GLsizei n, GLuint * buffer); /* 503 */
+ void (GLAPIENTRYP GetBufferParameterivARB)(GLenum target, GLenum pname, GLint * params); /* 504 */
+ void (GLAPIENTRYP GetBufferPointervARB)(GLenum target, GLenum pname, GLvoid ** params); /* 505 */
+ void (GLAPIENTRYP GetBufferSubDataARB)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data); /* 506 */
+ GLboolean (GLAPIENTRYP IsBufferARB)(GLuint buffer); /* 507 */
+ GLvoid * (GLAPIENTRYP MapBufferARB)(GLenum target, GLenum access); /* 508 */
+ GLboolean (GLAPIENTRYP UnmapBufferARB)(GLenum target); /* 509 */
+ void (GLAPIENTRYP BeginQueryARB)(GLenum target, GLuint id); /* 510 */
+ void (GLAPIENTRYP DeleteQueriesARB)(GLsizei n, const GLuint * ids); /* 511 */
+ void (GLAPIENTRYP EndQueryARB)(GLenum target); /* 512 */
+ void (GLAPIENTRYP GenQueriesARB)(GLsizei n, GLuint * ids); /* 513 */
+ void (GLAPIENTRYP GetQueryObjectivARB)(GLuint id, GLenum pname, GLint * params); /* 514 */
+ void (GLAPIENTRYP GetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint * params); /* 515 */
+ void (GLAPIENTRYP GetQueryivARB)(GLenum target, GLenum pname, GLint * params); /* 516 */
+ GLboolean (GLAPIENTRYP IsQueryARB)(GLuint id); /* 517 */
+ void (GLAPIENTRYP AttachObjectARB)(GLhandleARB containerObj, GLhandleARB obj); /* 518 */
+ void (GLAPIENTRYP CompileShaderARB)(GLhandleARB shader); /* 519 */
+ GLhandleARB (GLAPIENTRYP CreateProgramObjectARB)(void); /* 520 */
+ GLhandleARB (GLAPIENTRYP CreateShaderObjectARB)(GLenum shaderType); /* 521 */
+ void (GLAPIENTRYP DeleteObjectARB)(GLhandleARB obj); /* 522 */
+ void (GLAPIENTRYP DetachObjectARB)(GLhandleARB containerObj, GLhandleARB attachedObj); /* 523 */
+ void (GLAPIENTRYP GetActiveUniformARB)(GLhandleARB program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); /* 524 */
+ void (GLAPIENTRYP GetAttachedObjectsARB)(GLhandleARB containerObj, GLsizei maxLength, GLsizei * length, GLhandleARB * infoLog); /* 525 */
+ GLhandleARB (GLAPIENTRYP GetHandleARB)(GLenum pname); /* 526 */
+ void (GLAPIENTRYP GetInfoLogARB)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); /* 527 */
+ void (GLAPIENTRYP GetObjectParameterfvARB)(GLhandleARB obj, GLenum pname, GLfloat * params); /* 528 */
+ void (GLAPIENTRYP GetObjectParameterivARB)(GLhandleARB obj, GLenum pname, GLint * params); /* 529 */
+ void (GLAPIENTRYP GetShaderSourceARB)(GLhandleARB shader, GLsizei bufSize, GLsizei * length, GLcharARB * source); /* 530 */
+ GLint (GLAPIENTRYP GetUniformLocationARB)(GLhandleARB program, const GLcharARB * name); /* 531 */
+ void (GLAPIENTRYP GetUniformfvARB)(GLhandleARB program, GLint location, GLfloat * params); /* 532 */
+ void (GLAPIENTRYP GetUniformivARB)(GLhandleARB program, GLint location, GLint * params); /* 533 */
+ void (GLAPIENTRYP LinkProgramARB)(GLhandleARB program); /* 534 */
+ void (GLAPIENTRYP ShaderSourceARB)(GLhandleARB shader, GLsizei count, const GLcharARB ** string, const GLint * length); /* 535 */
+ void (GLAPIENTRYP Uniform1fARB)(GLint location, GLfloat v0); /* 536 */
+ void (GLAPIENTRYP Uniform1fvARB)(GLint location, GLsizei count, const GLfloat * value); /* 537 */
+ void (GLAPIENTRYP Uniform1iARB)(GLint location, GLint v0); /* 538 */
+ void (GLAPIENTRYP Uniform1ivARB)(GLint location, GLsizei count, const GLint * value); /* 539 */
+ void (GLAPIENTRYP Uniform2fARB)(GLint location, GLfloat v0, GLfloat v1); /* 540 */
+ void (GLAPIENTRYP Uniform2fvARB)(GLint location, GLsizei count, const GLfloat * value); /* 541 */
+ void (GLAPIENTRYP Uniform2iARB)(GLint location, GLint v0, GLint v1); /* 542 */
+ void (GLAPIENTRYP Uniform2ivARB)(GLint location, GLsizei count, const GLint * value); /* 543 */
+ void (GLAPIENTRYP Uniform3fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); /* 544 */
+ void (GLAPIENTRYP Uniform3fvARB)(GLint location, GLsizei count, const GLfloat * value); /* 545 */
+ void (GLAPIENTRYP Uniform3iARB)(GLint location, GLint v0, GLint v1, GLint v2); /* 546 */
+ void (GLAPIENTRYP Uniform3ivARB)(GLint location, GLsizei count, const GLint * value); /* 547 */
+ void (GLAPIENTRYP Uniform4fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); /* 548 */
+ void (GLAPIENTRYP Uniform4fvARB)(GLint location, GLsizei count, const GLfloat * value); /* 549 */
+ void (GLAPIENTRYP Uniform4iARB)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); /* 550 */
+ void (GLAPIENTRYP Uniform4ivARB)(GLint location, GLsizei count, const GLint * value); /* 551 */
+ void (GLAPIENTRYP UniformMatrix2fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 552 */
+ void (GLAPIENTRYP UniformMatrix3fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 553 */
+ void (GLAPIENTRYP UniformMatrix4fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); /* 554 */
+ void (GLAPIENTRYP UseProgramObjectARB)(GLhandleARB program); /* 555 */
+ void (GLAPIENTRYP ValidateProgramARB)(GLhandleARB program); /* 556 */
+ void (GLAPIENTRYP BindAttribLocationARB)(GLhandleARB program, GLuint index, const GLcharARB * name); /* 557 */
+ void (GLAPIENTRYP GetActiveAttribARB)(GLhandleARB program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); /* 558 */
+ GLint (GLAPIENTRYP GetAttribLocationARB)(GLhandleARB program, const GLcharARB * name); /* 559 */
+ void (GLAPIENTRYP DrawBuffersARB)(GLsizei n, const GLenum * bufs); /* 560 */
+ void (GLAPIENTRYP RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); /* 561 */
+ void (GLAPIENTRYP FlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length); /* 562 */
+ GLvoid * (GLAPIENTRYP MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); /* 563 */
+ void (GLAPIENTRYP BindVertexArray)(GLuint array); /* 564 */
+ void (GLAPIENTRYP GenVertexArrays)(GLsizei n, GLuint * arrays); /* 565 */
+ void (GLAPIENTRYP CopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); /* 566 */
+ GLenum (GLAPIENTRYP ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); /* 567 */
+ void (GLAPIENTRYP DeleteSync)(GLsync sync); /* 568 */
+ GLsync (GLAPIENTRYP FenceSync)(GLenum condition, GLbitfield flags); /* 569 */
+ void (GLAPIENTRYP GetInteger64v)(GLenum pname, GLint64 * params); /* 570 */
+ void (GLAPIENTRYP GetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values); /* 571 */
+ GLboolean (GLAPIENTRYP IsSync)(GLsync sync); /* 572 */
+ void (GLAPIENTRYP WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); /* 573 */
+ void (GLAPIENTRYP PolygonOffsetEXT)(GLfloat factor, GLfloat bias); /* 574 */
+ void (GLAPIENTRYP GetPixelTexGenParameterfvSGIS)(GLenum pname, GLfloat * params); /* 575 */
+ void (GLAPIENTRYP GetPixelTexGenParameterivSGIS)(GLenum pname, GLint * params); /* 576 */
+ void (GLAPIENTRYP PixelTexGenParameterfSGIS)(GLenum pname, GLfloat param); /* 577 */
+ void (GLAPIENTRYP PixelTexGenParameterfvSGIS)(GLenum pname, const GLfloat * params); /* 578 */
+ void (GLAPIENTRYP PixelTexGenParameteriSGIS)(GLenum pname, GLint param); /* 579 */
+ void (GLAPIENTRYP PixelTexGenParameterivSGIS)(GLenum pname, const GLint * params); /* 580 */
+ void (GLAPIENTRYP SampleMaskSGIS)(GLclampf value, GLboolean invert); /* 581 */
+ void (GLAPIENTRYP SamplePatternSGIS)(GLenum pattern); /* 582 */
+ void (GLAPIENTRYP ColorPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 583 */
+ void (GLAPIENTRYP EdgeFlagPointerEXT)(GLsizei stride, GLsizei count, const GLboolean * pointer); /* 584 */
+ void (GLAPIENTRYP IndexPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 585 */
+ void (GLAPIENTRYP NormalPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 586 */
+ void (GLAPIENTRYP TexCoordPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 587 */
+ void (GLAPIENTRYP VertexPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer); /* 588 */
+ void (GLAPIENTRYP PointParameterfEXT)(GLenum pname, GLfloat param); /* 589 */
+ void (GLAPIENTRYP PointParameterfvEXT)(GLenum pname, const GLfloat * params); /* 590 */
+ void (GLAPIENTRYP LockArraysEXT)(GLint first, GLsizei count); /* 591 */
+ void (GLAPIENTRYP UnlockArraysEXT)(void); /* 592 */
+ void (GLAPIENTRYP CullParameterdvEXT)(GLenum pname, GLdouble * params); /* 593 */
+ void (GLAPIENTRYP CullParameterfvEXT)(GLenum pname, GLfloat * params); /* 594 */
+ void (GLAPIENTRYP SecondaryColor3bEXT)(GLbyte red, GLbyte green, GLbyte blue); /* 595 */
+ void (GLAPIENTRYP SecondaryColor3bvEXT)(const GLbyte * v); /* 596 */
+ void (GLAPIENTRYP SecondaryColor3dEXT)(GLdouble red, GLdouble green, GLdouble blue); /* 597 */
+ void (GLAPIENTRYP SecondaryColor3dvEXT)(const GLdouble * v); /* 598 */
+ void (GLAPIENTRYP SecondaryColor3fEXT)(GLfloat red, GLfloat green, GLfloat blue); /* 599 */
+ void (GLAPIENTRYP SecondaryColor3fvEXT)(const GLfloat * v); /* 600 */
+ void (GLAPIENTRYP SecondaryColor3iEXT)(GLint red, GLint green, GLint blue); /* 601 */
+ void (GLAPIENTRYP SecondaryColor3ivEXT)(const GLint * v); /* 602 */
+ void (GLAPIENTRYP SecondaryColor3sEXT)(GLshort red, GLshort green, GLshort blue); /* 603 */
+ void (GLAPIENTRYP SecondaryColor3svEXT)(const GLshort * v); /* 604 */
+ void (GLAPIENTRYP SecondaryColor3ubEXT)(GLubyte red, GLubyte green, GLubyte blue); /* 605 */
+ void (GLAPIENTRYP SecondaryColor3ubvEXT)(const GLubyte * v); /* 606 */
+ void (GLAPIENTRYP SecondaryColor3uiEXT)(GLuint red, GLuint green, GLuint blue); /* 607 */
+ void (GLAPIENTRYP SecondaryColor3uivEXT)(const GLuint * v); /* 608 */
+ void (GLAPIENTRYP SecondaryColor3usEXT)(GLushort red, GLushort green, GLushort blue); /* 609 */
+ void (GLAPIENTRYP SecondaryColor3usvEXT)(const GLushort * v); /* 610 */
+ void (GLAPIENTRYP SecondaryColorPointerEXT)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 611 */
+ void (GLAPIENTRYP MultiDrawArraysEXT)(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount); /* 612 */
+ void (GLAPIENTRYP MultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount); /* 613 */
+ void (GLAPIENTRYP FogCoordPointerEXT)(GLenum type, GLsizei stride, const GLvoid * pointer); /* 614 */
+ void (GLAPIENTRYP FogCoorddEXT)(GLdouble coord); /* 615 */
+ void (GLAPIENTRYP FogCoorddvEXT)(const GLdouble * coord); /* 616 */
+ void (GLAPIENTRYP FogCoordfEXT)(GLfloat coord); /* 617 */
+ void (GLAPIENTRYP FogCoordfvEXT)(const GLfloat * coord); /* 618 */
+ void (GLAPIENTRYP PixelTexGenSGIX)(GLenum mode); /* 619 */
+ void (GLAPIENTRYP BlendFuncSeparateEXT)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); /* 620 */
+ void (GLAPIENTRYP FlushVertexArrayRangeNV)(void); /* 621 */
+ void (GLAPIENTRYP VertexArrayRangeNV)(GLsizei length, const GLvoid * pointer); /* 622 */
+ void (GLAPIENTRYP CombinerInputNV)(GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 623 */
+ void (GLAPIENTRYP CombinerOutputNV)(GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); /* 624 */
+ void (GLAPIENTRYP CombinerParameterfNV)(GLenum pname, GLfloat param); /* 625 */
+ void (GLAPIENTRYP CombinerParameterfvNV)(GLenum pname, const GLfloat * params); /* 626 */
+ void (GLAPIENTRYP CombinerParameteriNV)(GLenum pname, GLint param); /* 627 */
+ void (GLAPIENTRYP CombinerParameterivNV)(GLenum pname, const GLint * params); /* 628 */
+ void (GLAPIENTRYP FinalCombinerInputNV)(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); /* 629 */
+ void (GLAPIENTRYP GetCombinerInputParameterfvNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params); /* 630 */
+ void (GLAPIENTRYP GetCombinerInputParameterivNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params); /* 631 */
+ void (GLAPIENTRYP GetCombinerOutputParameterfvNV)(GLenum stage, GLenum portion, GLenum pname, GLfloat * params); /* 632 */
+ void (GLAPIENTRYP GetCombinerOutputParameterivNV)(GLenum stage, GLenum portion, GLenum pname, GLint * params); /* 633 */
+ void (GLAPIENTRYP GetFinalCombinerInputParameterfvNV)(GLenum variable, GLenum pname, GLfloat * params); /* 634 */
+ void (GLAPIENTRYP GetFinalCombinerInputParameterivNV)(GLenum variable, GLenum pname, GLint * params); /* 635 */
+ void (GLAPIENTRYP ResizeBuffersMESA)(void); /* 636 */
+ void (GLAPIENTRYP WindowPos2dMESA)(GLdouble x, GLdouble y); /* 637 */
+ void (GLAPIENTRYP WindowPos2dvMESA)(const GLdouble * v); /* 638 */
+ void (GLAPIENTRYP WindowPos2fMESA)(GLfloat x, GLfloat y); /* 639 */
+ void (GLAPIENTRYP WindowPos2fvMESA)(const GLfloat * v); /* 640 */
+ void (GLAPIENTRYP WindowPos2iMESA)(GLint x, GLint y); /* 641 */
+ void (GLAPIENTRYP WindowPos2ivMESA)(const GLint * v); /* 642 */
+ void (GLAPIENTRYP WindowPos2sMESA)(GLshort x, GLshort y); /* 643 */
+ void (GLAPIENTRYP WindowPos2svMESA)(const GLshort * v); /* 644 */
+ void (GLAPIENTRYP WindowPos3dMESA)(GLdouble x, GLdouble y, GLdouble z); /* 645 */
+ void (GLAPIENTRYP WindowPos3dvMESA)(const GLdouble * v); /* 646 */
+ void (GLAPIENTRYP WindowPos3fMESA)(GLfloat x, GLfloat y, GLfloat z); /* 647 */
+ void (GLAPIENTRYP WindowPos3fvMESA)(const GLfloat * v); /* 648 */
+ void (GLAPIENTRYP WindowPos3iMESA)(GLint x, GLint y, GLint z); /* 649 */
+ void (GLAPIENTRYP WindowPos3ivMESA)(const GLint * v); /* 650 */
+ void (GLAPIENTRYP WindowPos3sMESA)(GLshort x, GLshort y, GLshort z); /* 651 */
+ void (GLAPIENTRYP WindowPos3svMESA)(const GLshort * v); /* 652 */
+ void (GLAPIENTRYP WindowPos4dMESA)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 653 */
+ void (GLAPIENTRYP WindowPos4dvMESA)(const GLdouble * v); /* 654 */
+ void (GLAPIENTRYP WindowPos4fMESA)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 655 */
+ void (GLAPIENTRYP WindowPos4fvMESA)(const GLfloat * v); /* 656 */
+ void (GLAPIENTRYP WindowPos4iMESA)(GLint x, GLint y, GLint z, GLint w); /* 657 */
+ void (GLAPIENTRYP WindowPos4ivMESA)(const GLint * v); /* 658 */
+ void (GLAPIENTRYP WindowPos4sMESA)(GLshort x, GLshort y, GLshort z, GLshort w); /* 659 */
+ void (GLAPIENTRYP WindowPos4svMESA)(const GLshort * v); /* 660 */
+ void (GLAPIENTRYP MultiModeDrawArraysIBM)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride); /* 661 */
+ void (GLAPIENTRYP MultiModeDrawElementsIBM)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride); /* 662 */
+ void (GLAPIENTRYP DeleteFencesNV)(GLsizei n, const GLuint * fences); /* 663 */
+ void (GLAPIENTRYP FinishFenceNV)(GLuint fence); /* 664 */
+ void (GLAPIENTRYP GenFencesNV)(GLsizei n, GLuint * fences); /* 665 */
+ void (GLAPIENTRYP GetFenceivNV)(GLuint fence, GLenum pname, GLint * params); /* 666 */
+ GLboolean (GLAPIENTRYP IsFenceNV)(GLuint fence); /* 667 */
+ void (GLAPIENTRYP SetFenceNV)(GLuint fence, GLenum condition); /* 668 */
+ GLboolean (GLAPIENTRYP TestFenceNV)(GLuint fence); /* 669 */
+ GLboolean (GLAPIENTRYP AreProgramsResidentNV)(GLsizei n, const GLuint * ids, GLboolean * residences); /* 670 */
+ void (GLAPIENTRYP BindProgramNV)(GLenum target, GLuint program); /* 671 */
+ void (GLAPIENTRYP DeleteProgramsNV)(GLsizei n, const GLuint * programs); /* 672 */
+ void (GLAPIENTRYP ExecuteProgramNV)(GLenum target, GLuint id, const GLfloat * params); /* 673 */
+ void (GLAPIENTRYP GenProgramsNV)(GLsizei n, GLuint * programs); /* 674 */
+ void (GLAPIENTRYP GetProgramParameterdvNV)(GLenum target, GLuint index, GLenum pname, GLdouble * params); /* 675 */
+ void (GLAPIENTRYP GetProgramParameterfvNV)(GLenum target, GLuint index, GLenum pname, GLfloat * params); /* 676 */
+ void (GLAPIENTRYP GetProgramStringNV)(GLuint id, GLenum pname, GLubyte * program); /* 677 */
+ void (GLAPIENTRYP GetProgramivNV)(GLuint id, GLenum pname, GLint * params); /* 678 */
+ void (GLAPIENTRYP GetTrackMatrixivNV)(GLenum target, GLuint address, GLenum pname, GLint * params); /* 679 */
+ void (GLAPIENTRYP GetVertexAttribPointervNV)(GLuint index, GLenum pname, GLvoid ** pointer); /* 680 */
+ void (GLAPIENTRYP GetVertexAttribdvNV)(GLuint index, GLenum pname, GLdouble * params); /* 681 */
+ void (GLAPIENTRYP GetVertexAttribfvNV)(GLuint index, GLenum pname, GLfloat * params); /* 682 */
+ void (GLAPIENTRYP GetVertexAttribivNV)(GLuint index, GLenum pname, GLint * params); /* 683 */
+ GLboolean (GLAPIENTRYP IsProgramNV)(GLuint program); /* 684 */
+ void (GLAPIENTRYP LoadProgramNV)(GLenum target, GLuint id, GLsizei len, const GLubyte * program); /* 685 */
+ void (GLAPIENTRYP ProgramParameters4dvNV)(GLenum target, GLuint index, GLuint num, const GLdouble * params); /* 686 */
+ void (GLAPIENTRYP ProgramParameters4fvNV)(GLenum target, GLuint index, GLuint num, const GLfloat * params); /* 687 */
+ void (GLAPIENTRYP RequestResidentProgramsNV)(GLsizei n, const GLuint * ids); /* 688 */
+ void (GLAPIENTRYP TrackMatrixNV)(GLenum target, GLuint address, GLenum matrix, GLenum transform); /* 689 */
+ void (GLAPIENTRYP VertexAttrib1dNV)(GLuint index, GLdouble x); /* 690 */
+ void (GLAPIENTRYP VertexAttrib1dvNV)(GLuint index, const GLdouble * v); /* 691 */
+ void (GLAPIENTRYP VertexAttrib1fNV)(GLuint index, GLfloat x); /* 692 */
+ void (GLAPIENTRYP VertexAttrib1fvNV)(GLuint index, const GLfloat * v); /* 693 */
+ void (GLAPIENTRYP VertexAttrib1sNV)(GLuint index, GLshort x); /* 694 */
+ void (GLAPIENTRYP VertexAttrib1svNV)(GLuint index, const GLshort * v); /* 695 */
+ void (GLAPIENTRYP VertexAttrib2dNV)(GLuint index, GLdouble x, GLdouble y); /* 696 */
+ void (GLAPIENTRYP VertexAttrib2dvNV)(GLuint index, const GLdouble * v); /* 697 */
+ void (GLAPIENTRYP VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y); /* 698 */
+ void (GLAPIENTRYP VertexAttrib2fvNV)(GLuint index, const GLfloat * v); /* 699 */
+ void (GLAPIENTRYP VertexAttrib2sNV)(GLuint index, GLshort x, GLshort y); /* 700 */
+ void (GLAPIENTRYP VertexAttrib2svNV)(GLuint index, const GLshort * v); /* 701 */
+ void (GLAPIENTRYP VertexAttrib3dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z); /* 702 */
+ void (GLAPIENTRYP VertexAttrib3dvNV)(GLuint index, const GLdouble * v); /* 703 */
+ void (GLAPIENTRYP VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z); /* 704 */
+ void (GLAPIENTRYP VertexAttrib3fvNV)(GLuint index, const GLfloat * v); /* 705 */
+ void (GLAPIENTRYP VertexAttrib3sNV)(GLuint index, GLshort x, GLshort y, GLshort z); /* 706 */
+ void (GLAPIENTRYP VertexAttrib3svNV)(GLuint index, const GLshort * v); /* 707 */
+ void (GLAPIENTRYP VertexAttrib4dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 708 */
+ void (GLAPIENTRYP VertexAttrib4dvNV)(GLuint index, const GLdouble * v); /* 709 */
+ void (GLAPIENTRYP VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 710 */
+ void (GLAPIENTRYP VertexAttrib4fvNV)(GLuint index, const GLfloat * v); /* 711 */
+ void (GLAPIENTRYP VertexAttrib4sNV)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); /* 712 */
+ void (GLAPIENTRYP VertexAttrib4svNV)(GLuint index, const GLshort * v); /* 713 */
+ void (GLAPIENTRYP VertexAttrib4ubNV)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); /* 714 */
+ void (GLAPIENTRYP VertexAttrib4ubvNV)(GLuint index, const GLubyte * v); /* 715 */
+ void (GLAPIENTRYP VertexAttribPointerNV)(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer); /* 716 */
+ void (GLAPIENTRYP VertexAttribs1dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 717 */
+ void (GLAPIENTRYP VertexAttribs1fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 718 */
+ void (GLAPIENTRYP VertexAttribs1svNV)(GLuint index, GLsizei n, const GLshort * v); /* 719 */
+ void (GLAPIENTRYP VertexAttribs2dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 720 */
+ void (GLAPIENTRYP VertexAttribs2fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 721 */
+ void (GLAPIENTRYP VertexAttribs2svNV)(GLuint index, GLsizei n, const GLshort * v); /* 722 */
+ void (GLAPIENTRYP VertexAttribs3dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 723 */
+ void (GLAPIENTRYP VertexAttribs3fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 724 */
+ void (GLAPIENTRYP VertexAttribs3svNV)(GLuint index, GLsizei n, const GLshort * v); /* 725 */
+ void (GLAPIENTRYP VertexAttribs4dvNV)(GLuint index, GLsizei n, const GLdouble * v); /* 726 */
+ void (GLAPIENTRYP VertexAttribs4fvNV)(GLuint index, GLsizei n, const GLfloat * v); /* 727 */
+ void (GLAPIENTRYP VertexAttribs4svNV)(GLuint index, GLsizei n, const GLshort * v); /* 728 */
+ void (GLAPIENTRYP VertexAttribs4ubvNV)(GLuint index, GLsizei n, const GLubyte * v); /* 729 */
+ void (GLAPIENTRYP GetTexBumpParameterfvATI)(GLenum pname, GLfloat * param); /* 730 */
+ void (GLAPIENTRYP GetTexBumpParameterivATI)(GLenum pname, GLint * param); /* 731 */
+ void (GLAPIENTRYP TexBumpParameterfvATI)(GLenum pname, const GLfloat * param); /* 732 */
+ void (GLAPIENTRYP TexBumpParameterivATI)(GLenum pname, const GLint * param); /* 733 */
+ void (GLAPIENTRYP AlphaFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 734 */
+ void (GLAPIENTRYP AlphaFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 735 */
+ void (GLAPIENTRYP AlphaFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 736 */
+ void (GLAPIENTRYP BeginFragmentShaderATI)(void); /* 737 */
+ void (GLAPIENTRYP BindFragmentShaderATI)(GLuint id); /* 738 */
+ void (GLAPIENTRYP ColorFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); /* 739 */
+ void (GLAPIENTRYP ColorFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); /* 740 */
+ void (GLAPIENTRYP ColorFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); /* 741 */
+ void (GLAPIENTRYP DeleteFragmentShaderATI)(GLuint id); /* 742 */
+ void (GLAPIENTRYP EndFragmentShaderATI)(void); /* 743 */
+ GLuint (GLAPIENTRYP GenFragmentShadersATI)(GLuint range); /* 744 */
+ void (GLAPIENTRYP PassTexCoordATI)(GLuint dst, GLuint coord, GLenum swizzle); /* 745 */
+ void (GLAPIENTRYP SampleMapATI)(GLuint dst, GLuint interp, GLenum swizzle); /* 746 */
+ void (GLAPIENTRYP SetFragmentShaderConstantATI)(GLuint dst, const GLfloat * value); /* 747 */
+ void (GLAPIENTRYP PointParameteriNV)(GLenum pname, GLint param); /* 748 */
+ void (GLAPIENTRYP PointParameterivNV)(GLenum pname, const GLint * params); /* 749 */
+ void (GLAPIENTRYP ActiveStencilFaceEXT)(GLenum face); /* 750 */
+ void (GLAPIENTRYP BindVertexArrayAPPLE)(GLuint array); /* 751 */
+ void (GLAPIENTRYP DeleteVertexArraysAPPLE)(GLsizei n, const GLuint * arrays); /* 752 */
+ void (GLAPIENTRYP GenVertexArraysAPPLE)(GLsizei n, GLuint * arrays); /* 753 */
+ GLboolean (GLAPIENTRYP IsVertexArrayAPPLE)(GLuint array); /* 754 */
+ void (GLAPIENTRYP GetProgramNamedParameterdvNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble * params); /* 755 */
+ void (GLAPIENTRYP GetProgramNamedParameterfvNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat * params); /* 756 */
+ void (GLAPIENTRYP ProgramNamedParameter4dNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); /* 757 */
+ void (GLAPIENTRYP ProgramNamedParameter4dvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v); /* 758 */
+ void (GLAPIENTRYP ProgramNamedParameter4fNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); /* 759 */
+ void (GLAPIENTRYP ProgramNamedParameter4fvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v); /* 760 */
+ void (GLAPIENTRYP DepthBoundsEXT)(GLclampd zmin, GLclampd zmax); /* 761 */
+ void (GLAPIENTRYP BlendEquationSeparateEXT)(GLenum modeRGB, GLenum modeA); /* 762 */
+ void (GLAPIENTRYP BindFramebufferEXT)(GLenum target, GLuint framebuffer); /* 763 */
+ void (GLAPIENTRYP BindRenderbufferEXT)(GLenum target, GLuint renderbuffer); /* 764 */
+ GLenum (GLAPIENTRYP CheckFramebufferStatusEXT)(GLenum target); /* 765 */
+ void (GLAPIENTRYP DeleteFramebuffersEXT)(GLsizei n, const GLuint * framebuffers); /* 766 */
+ void (GLAPIENTRYP DeleteRenderbuffersEXT)(GLsizei n, const GLuint * renderbuffers); /* 767 */
+ void (GLAPIENTRYP FramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); /* 768 */
+ void (GLAPIENTRYP FramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 769 */
+ void (GLAPIENTRYP FramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); /* 770 */
+ void (GLAPIENTRYP FramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); /* 771 */
+ void (GLAPIENTRYP GenFramebuffersEXT)(GLsizei n, GLuint * framebuffers); /* 772 */
+ void (GLAPIENTRYP GenRenderbuffersEXT)(GLsizei n, GLuint * renderbuffers); /* 773 */
+ void (GLAPIENTRYP GenerateMipmapEXT)(GLenum target); /* 774 */
+ void (GLAPIENTRYP GetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint * params); /* 775 */
+ void (GLAPIENTRYP GetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint * params); /* 776 */
+ GLboolean (GLAPIENTRYP IsFramebufferEXT)(GLuint framebuffer); /* 777 */
+ GLboolean (GLAPIENTRYP IsRenderbufferEXT)(GLuint renderbuffer); /* 778 */
+ void (GLAPIENTRYP RenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); /* 779 */
+ void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 780 */
+ void (GLAPIENTRYP BufferParameteriAPPLE)(GLenum target, GLenum pname, GLint param); /* 781 */
+ void (GLAPIENTRYP FlushMappedBufferRangeAPPLE)(GLenum target, GLintptr offset, GLsizeiptr size); /* 782 */
+ void (GLAPIENTRYP FramebufferTextureLayerEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); /* 783 */
+ void (GLAPIENTRYP ProvokingVertexEXT)(GLenum mode); /* 784 */
+ void (GLAPIENTRYP GetTexParameterPointervAPPLE)(GLenum target, GLenum pname, GLvoid ** params); /* 785 */
+ void (GLAPIENTRYP TextureRangeAPPLE)(GLenum target, GLsizei length, GLvoid * pointer); /* 786 */
+ void (GLAPIENTRYP StencilFuncSeparateATI)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); /* 787 */
+ void (GLAPIENTRYP ProgramEnvParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 788 */
+ void (GLAPIENTRYP ProgramLocalParameters4fvEXT)(GLenum target, GLuint index, GLsizei count, const GLfloat * params); /* 789 */
+ void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 790 */
+ void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 791 */
+};
+
+#endif /* !defined( _GLAPI_TABLE_H_ ) */
diff --git a/mesalib/src/mesa/glapi/glapitemp.h b/mesalib/src/mesa/glapi/glapitemp.h
new file mode 100644
index 000000000..e08f9548f
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glapitemp.h
@@ -0,0 +1,6921 @@
+/* DO NOT EDIT - This file generated automatically by gl_apitemp.py (from Mesa) script */
+
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2004
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL, IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
+# define HIDDEN __attribute__((visibility("hidden")))
+# else
+# define HIDDEN
+# endif
+
+/*
+ * This file is a template which generates the OpenGL API entry point
+ * functions. It should be included by a .c file which first defines
+ * the following macros:
+ * KEYWORD1 - usually nothing, but might be __declspec(dllexport) on Win32
+ * KEYWORD2 - usually nothing, but might be __stdcall on Win32
+ * NAME(n) - builds the final function name (usually add "gl" prefix)
+ * DISPATCH(func, args, msg) - code to do dispatch of named function.
+ * msg is a printf-style debug message.
+ * RETURN_DISPATCH(func, args, msg) - code to do dispatch with a return value
+ *
+ * Here is an example which generates the usual OpenGL functions:
+ * #define KEYWORD1
+ * #define KEYWORD2
+ * #define NAME(func) gl##func
+ * #define DISPATCH(func, args, msg) \
+ * struct _glapi_table *dispatch = CurrentDispatch; \
+ * (*dispatch->func) args
+ * #define RETURN DISPATCH(func, args, msg) \
+ * struct _glapi_table *dispatch = CurrentDispatch; \
+ * return (*dispatch->func) args
+ *
+ */
+
+
+#if defined( NAME )
+#ifndef KEYWORD1
+#define KEYWORD1
+#endif
+
+#ifndef KEYWORD1_ALT
+#define KEYWORD1_ALT HIDDEN
+#endif
+
+#ifndef KEYWORD2
+#define KEYWORD2
+#endif
+
+#ifndef DISPATCH
+#error DISPATCH must be defined
+#endif
+
+#ifndef RETURN_DISPATCH
+#error RETURN_DISPATCH must be defined
+#endif
+
+
+KEYWORD1 void KEYWORD2 NAME(NewList)(GLuint list, GLenum mode)
+{
+ DISPATCH(NewList, (list, mode), (F, "glNewList(%d, 0x%x);\n", list, mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EndList)(void)
+{
+ DISPATCH(EndList, (), (F, "glEndList();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CallList)(GLuint list)
+{
+ DISPATCH(CallList, (list), (F, "glCallList(%d);\n", list));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CallLists)(GLsizei n, GLenum type, const GLvoid * lists)
+{
+ DISPATCH(CallLists, (n, type, lists), (F, "glCallLists(%d, 0x%x, %p);\n", n, type, (const void *) lists));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteLists)(GLuint list, GLsizei range)
+{
+ DISPATCH(DeleteLists, (list, range), (F, "glDeleteLists(%d, %d);\n", list, range));
+}
+
+KEYWORD1 GLuint KEYWORD2 NAME(GenLists)(GLsizei range)
+{
+ RETURN_DISPATCH(GenLists, (range), (F, "glGenLists(%d);\n", range));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ListBase)(GLuint base)
+{
+ DISPATCH(ListBase, (base), (F, "glListBase(%d);\n", base));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Begin)(GLenum mode)
+{
+ DISPATCH(Begin, (mode), (F, "glBegin(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Bitmap)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap)
+{
+ DISPATCH(Bitmap, (width, height, xorig, yorig, xmove, ymove, bitmap), (F, "glBitmap(%d, %d, %f, %f, %f, %f, %p);\n", width, height, xorig, yorig, xmove, ymove, (const void *) bitmap));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3b)(GLbyte red, GLbyte green, GLbyte blue)
+{
+ DISPATCH(Color3b, (red, green, blue), (F, "glColor3b(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3bv)(const GLbyte * v)
+{
+ DISPATCH(Color3bv, (v), (F, "glColor3bv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3d)(GLdouble red, GLdouble green, GLdouble blue)
+{
+ DISPATCH(Color3d, (red, green, blue), (F, "glColor3d(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3dv)(const GLdouble * v)
+{
+ DISPATCH(Color3dv, (v), (F, "glColor3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3f)(GLfloat red, GLfloat green, GLfloat blue)
+{
+ DISPATCH(Color3f, (red, green, blue), (F, "glColor3f(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3fv)(const GLfloat * v)
+{
+ DISPATCH(Color3fv, (v), (F, "glColor3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3i)(GLint red, GLint green, GLint blue)
+{
+ DISPATCH(Color3i, (red, green, blue), (F, "glColor3i(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3iv)(const GLint * v)
+{
+ DISPATCH(Color3iv, (v), (F, "glColor3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3s)(GLshort red, GLshort green, GLshort blue)
+{
+ DISPATCH(Color3s, (red, green, blue), (F, "glColor3s(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3sv)(const GLshort * v)
+{
+ DISPATCH(Color3sv, (v), (F, "glColor3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3ub)(GLubyte red, GLubyte green, GLubyte blue)
+{
+ DISPATCH(Color3ub, (red, green, blue), (F, "glColor3ub(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3ubv)(const GLubyte * v)
+{
+ DISPATCH(Color3ubv, (v), (F, "glColor3ubv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3ui)(GLuint red, GLuint green, GLuint blue)
+{
+ DISPATCH(Color3ui, (red, green, blue), (F, "glColor3ui(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3uiv)(const GLuint * v)
+{
+ DISPATCH(Color3uiv, (v), (F, "glColor3uiv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3us)(GLushort red, GLushort green, GLushort blue)
+{
+ DISPATCH(Color3us, (red, green, blue), (F, "glColor3us(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color3usv)(const GLushort * v)
+{
+ DISPATCH(Color3usv, (v), (F, "glColor3usv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4b)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha)
+{
+ DISPATCH(Color4b, (red, green, blue, alpha), (F, "glColor4b(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4bv)(const GLbyte * v)
+{
+ DISPATCH(Color4bv, (v), (F, "glColor4bv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4d)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha)
+{
+ DISPATCH(Color4d, (red, green, blue, alpha), (F, "glColor4d(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4dv)(const GLdouble * v)
+{
+ DISPATCH(Color4dv, (v), (F, "glColor4dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ DISPATCH(Color4f, (red, green, blue, alpha), (F, "glColor4f(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4fv)(const GLfloat * v)
+{
+ DISPATCH(Color4fv, (v), (F, "glColor4fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4i)(GLint red, GLint green, GLint blue, GLint alpha)
+{
+ DISPATCH(Color4i, (red, green, blue, alpha), (F, "glColor4i(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4iv)(const GLint * v)
+{
+ DISPATCH(Color4iv, (v), (F, "glColor4iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4s)(GLshort red, GLshort green, GLshort blue, GLshort alpha)
+{
+ DISPATCH(Color4s, (red, green, blue, alpha), (F, "glColor4s(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4sv)(const GLshort * v)
+{
+ DISPATCH(Color4sv, (v), (F, "glColor4sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+{
+ DISPATCH(Color4ub, (red, green, blue, alpha), (F, "glColor4ub(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4ubv)(const GLubyte * v)
+{
+ DISPATCH(Color4ubv, (v), (F, "glColor4ubv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4ui)(GLuint red, GLuint green, GLuint blue, GLuint alpha)
+{
+ DISPATCH(Color4ui, (red, green, blue, alpha), (F, "glColor4ui(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4uiv)(const GLuint * v)
+{
+ DISPATCH(Color4uiv, (v), (F, "glColor4uiv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4us)(GLushort red, GLushort green, GLushort blue, GLushort alpha)
+{
+ DISPATCH(Color4us, (red, green, blue, alpha), (F, "glColor4us(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Color4usv)(const GLushort * v)
+{
+ DISPATCH(Color4usv, (v), (F, "glColor4usv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EdgeFlag)(GLboolean flag)
+{
+ DISPATCH(EdgeFlag, (flag), (F, "glEdgeFlag(%d);\n", flag));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EdgeFlagv)(const GLboolean * flag)
+{
+ DISPATCH(EdgeFlagv, (flag), (F, "glEdgeFlagv(%p);\n", (const void *) flag));
+}
+
+KEYWORD1 void KEYWORD2 NAME(End)(void)
+{
+ DISPATCH(End, (), (F, "glEnd();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexd)(GLdouble c)
+{
+ DISPATCH(Indexd, (c), (F, "glIndexd(%f);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexdv)(const GLdouble * c)
+{
+ DISPATCH(Indexdv, (c), (F, "glIndexdv(%p);\n", (const void *) c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexf)(GLfloat c)
+{
+ DISPATCH(Indexf, (c), (F, "glIndexf(%f);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexfv)(const GLfloat * c)
+{
+ DISPATCH(Indexfv, (c), (F, "glIndexfv(%p);\n", (const void *) c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexi)(GLint c)
+{
+ DISPATCH(Indexi, (c), (F, "glIndexi(%d);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexiv)(const GLint * c)
+{
+ DISPATCH(Indexiv, (c), (F, "glIndexiv(%p);\n", (const void *) c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexs)(GLshort c)
+{
+ DISPATCH(Indexs, (c), (F, "glIndexs(%d);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexsv)(const GLshort * c)
+{
+ DISPATCH(Indexsv, (c), (F, "glIndexsv(%p);\n", (const void *) c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3b)(GLbyte nx, GLbyte ny, GLbyte nz)
+{
+ DISPATCH(Normal3b, (nx, ny, nz), (F, "glNormal3b(%d, %d, %d);\n", nx, ny, nz));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3bv)(const GLbyte * v)
+{
+ DISPATCH(Normal3bv, (v), (F, "glNormal3bv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3d)(GLdouble nx, GLdouble ny, GLdouble nz)
+{
+ DISPATCH(Normal3d, (nx, ny, nz), (F, "glNormal3d(%f, %f, %f);\n", nx, ny, nz));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3dv)(const GLdouble * v)
+{
+ DISPATCH(Normal3dv, (v), (F, "glNormal3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3f)(GLfloat nx, GLfloat ny, GLfloat nz)
+{
+ DISPATCH(Normal3f, (nx, ny, nz), (F, "glNormal3f(%f, %f, %f);\n", nx, ny, nz));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3fv)(const GLfloat * v)
+{
+ DISPATCH(Normal3fv, (v), (F, "glNormal3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3i)(GLint nx, GLint ny, GLint nz)
+{
+ DISPATCH(Normal3i, (nx, ny, nz), (F, "glNormal3i(%d, %d, %d);\n", nx, ny, nz));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3iv)(const GLint * v)
+{
+ DISPATCH(Normal3iv, (v), (F, "glNormal3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3s)(GLshort nx, GLshort ny, GLshort nz)
+{
+ DISPATCH(Normal3s, (nx, ny, nz), (F, "glNormal3s(%d, %d, %d);\n", nx, ny, nz));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Normal3sv)(const GLshort * v)
+{
+ DISPATCH(Normal3sv, (v), (F, "glNormal3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2d)(GLdouble x, GLdouble y)
+{
+ DISPATCH(RasterPos2d, (x, y), (F, "glRasterPos2d(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2dv)(const GLdouble * v)
+{
+ DISPATCH(RasterPos2dv, (v), (F, "glRasterPos2dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2f)(GLfloat x, GLfloat y)
+{
+ DISPATCH(RasterPos2f, (x, y), (F, "glRasterPos2f(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2fv)(const GLfloat * v)
+{
+ DISPATCH(RasterPos2fv, (v), (F, "glRasterPos2fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2i)(GLint x, GLint y)
+{
+ DISPATCH(RasterPos2i, (x, y), (F, "glRasterPos2i(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2iv)(const GLint * v)
+{
+ DISPATCH(RasterPos2iv, (v), (F, "glRasterPos2iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2s)(GLshort x, GLshort y)
+{
+ DISPATCH(RasterPos2s, (x, y), (F, "glRasterPos2s(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos2sv)(const GLshort * v)
+{
+ DISPATCH(RasterPos2sv, (v), (F, "glRasterPos2sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3d)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(RasterPos3d, (x, y, z), (F, "glRasterPos3d(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3dv)(const GLdouble * v)
+{
+ DISPATCH(RasterPos3dv, (v), (F, "glRasterPos3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(RasterPos3f, (x, y, z), (F, "glRasterPos3f(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3fv)(const GLfloat * v)
+{
+ DISPATCH(RasterPos3fv, (v), (F, "glRasterPos3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3i)(GLint x, GLint y, GLint z)
+{
+ DISPATCH(RasterPos3i, (x, y, z), (F, "glRasterPos3i(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3iv)(const GLint * v)
+{
+ DISPATCH(RasterPos3iv, (v), (F, "glRasterPos3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3s)(GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(RasterPos3s, (x, y, z), (F, "glRasterPos3s(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos3sv)(const GLshort * v)
+{
+ DISPATCH(RasterPos3sv, (v), (F, "glRasterPos3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(RasterPos4d, (x, y, z, w), (F, "glRasterPos4d(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4dv)(const GLdouble * v)
+{
+ DISPATCH(RasterPos4dv, (v), (F, "glRasterPos4dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(RasterPos4f, (x, y, z, w), (F, "glRasterPos4f(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4fv)(const GLfloat * v)
+{
+ DISPATCH(RasterPos4fv, (v), (F, "glRasterPos4fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4i)(GLint x, GLint y, GLint z, GLint w)
+{
+ DISPATCH(RasterPos4i, (x, y, z, w), (F, "glRasterPos4i(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4iv)(const GLint * v)
+{
+ DISPATCH(RasterPos4iv, (v), (F, "glRasterPos4iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4s)(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(RasterPos4s, (x, y, z, w), (F, "glRasterPos4s(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RasterPos4sv)(const GLshort * v)
+{
+ DISPATCH(RasterPos4sv, (v), (F, "glRasterPos4sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectd)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
+{
+ DISPATCH(Rectd, (x1, y1, x2, y2), (F, "glRectd(%f, %f, %f, %f);\n", x1, y1, x2, y2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectdv)(const GLdouble * v1, const GLdouble * v2)
+{
+ DISPATCH(Rectdv, (v1, v2), (F, "glRectdv(%p, %p);\n", (const void *) v1, (const void *) v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectf)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+ DISPATCH(Rectf, (x1, y1, x2, y2), (F, "glRectf(%f, %f, %f, %f);\n", x1, y1, x2, y2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectfv)(const GLfloat * v1, const GLfloat * v2)
+{
+ DISPATCH(Rectfv, (v1, v2), (F, "glRectfv(%p, %p);\n", (const void *) v1, (const void *) v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Recti)(GLint x1, GLint y1, GLint x2, GLint y2)
+{
+ DISPATCH(Recti, (x1, y1, x2, y2), (F, "glRecti(%d, %d, %d, %d);\n", x1, y1, x2, y2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectiv)(const GLint * v1, const GLint * v2)
+{
+ DISPATCH(Rectiv, (v1, v2), (F, "glRectiv(%p, %p);\n", (const void *) v1, (const void *) v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rects)(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
+{
+ DISPATCH(Rects, (x1, y1, x2, y2), (F, "glRects(%d, %d, %d, %d);\n", x1, y1, x2, y2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rectsv)(const GLshort * v1, const GLshort * v2)
+{
+ DISPATCH(Rectsv, (v1, v2), (F, "glRectsv(%p, %p);\n", (const void *) v1, (const void *) v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1d)(GLdouble s)
+{
+ DISPATCH(TexCoord1d, (s), (F, "glTexCoord1d(%f);\n", s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1dv)(const GLdouble * v)
+{
+ DISPATCH(TexCoord1dv, (v), (F, "glTexCoord1dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1f)(GLfloat s)
+{
+ DISPATCH(TexCoord1f, (s), (F, "glTexCoord1f(%f);\n", s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1fv)(const GLfloat * v)
+{
+ DISPATCH(TexCoord1fv, (v), (F, "glTexCoord1fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1i)(GLint s)
+{
+ DISPATCH(TexCoord1i, (s), (F, "glTexCoord1i(%d);\n", s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1iv)(const GLint * v)
+{
+ DISPATCH(TexCoord1iv, (v), (F, "glTexCoord1iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1s)(GLshort s)
+{
+ DISPATCH(TexCoord1s, (s), (F, "glTexCoord1s(%d);\n", s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord1sv)(const GLshort * v)
+{
+ DISPATCH(TexCoord1sv, (v), (F, "glTexCoord1sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2d)(GLdouble s, GLdouble t)
+{
+ DISPATCH(TexCoord2d, (s, t), (F, "glTexCoord2d(%f, %f);\n", s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2dv)(const GLdouble * v)
+{
+ DISPATCH(TexCoord2dv, (v), (F, "glTexCoord2dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2f)(GLfloat s, GLfloat t)
+{
+ DISPATCH(TexCoord2f, (s, t), (F, "glTexCoord2f(%f, %f);\n", s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2fv)(const GLfloat * v)
+{
+ DISPATCH(TexCoord2fv, (v), (F, "glTexCoord2fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2i)(GLint s, GLint t)
+{
+ DISPATCH(TexCoord2i, (s, t), (F, "glTexCoord2i(%d, %d);\n", s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2iv)(const GLint * v)
+{
+ DISPATCH(TexCoord2iv, (v), (F, "glTexCoord2iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2s)(GLshort s, GLshort t)
+{
+ DISPATCH(TexCoord2s, (s, t), (F, "glTexCoord2s(%d, %d);\n", s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord2sv)(const GLshort * v)
+{
+ DISPATCH(TexCoord2sv, (v), (F, "glTexCoord2sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3d)(GLdouble s, GLdouble t, GLdouble r)
+{
+ DISPATCH(TexCoord3d, (s, t, r), (F, "glTexCoord3d(%f, %f, %f);\n", s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3dv)(const GLdouble * v)
+{
+ DISPATCH(TexCoord3dv, (v), (F, "glTexCoord3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3f)(GLfloat s, GLfloat t, GLfloat r)
+{
+ DISPATCH(TexCoord3f, (s, t, r), (F, "glTexCoord3f(%f, %f, %f);\n", s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3fv)(const GLfloat * v)
+{
+ DISPATCH(TexCoord3fv, (v), (F, "glTexCoord3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3i)(GLint s, GLint t, GLint r)
+{
+ DISPATCH(TexCoord3i, (s, t, r), (F, "glTexCoord3i(%d, %d, %d);\n", s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3iv)(const GLint * v)
+{
+ DISPATCH(TexCoord3iv, (v), (F, "glTexCoord3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3s)(GLshort s, GLshort t, GLshort r)
+{
+ DISPATCH(TexCoord3s, (s, t, r), (F, "glTexCoord3s(%d, %d, %d);\n", s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord3sv)(const GLshort * v)
+{
+ DISPATCH(TexCoord3sv, (v), (F, "glTexCoord3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4d)(GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ DISPATCH(TexCoord4d, (s, t, r, q), (F, "glTexCoord4d(%f, %f, %f, %f);\n", s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4dv)(const GLdouble * v)
+{
+ DISPATCH(TexCoord4dv, (v), (F, "glTexCoord4dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4f)(GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ DISPATCH(TexCoord4f, (s, t, r, q), (F, "glTexCoord4f(%f, %f, %f, %f);\n", s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4fv)(const GLfloat * v)
+{
+ DISPATCH(TexCoord4fv, (v), (F, "glTexCoord4fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4i)(GLint s, GLint t, GLint r, GLint q)
+{
+ DISPATCH(TexCoord4i, (s, t, r, q), (F, "glTexCoord4i(%d, %d, %d, %d);\n", s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4iv)(const GLint * v)
+{
+ DISPATCH(TexCoord4iv, (v), (F, "glTexCoord4iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4s)(GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ DISPATCH(TexCoord4s, (s, t, r, q), (F, "glTexCoord4s(%d, %d, %d, %d);\n", s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoord4sv)(const GLshort * v)
+{
+ DISPATCH(TexCoord4sv, (v), (F, "glTexCoord4sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2d)(GLdouble x, GLdouble y)
+{
+ DISPATCH(Vertex2d, (x, y), (F, "glVertex2d(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2dv)(const GLdouble * v)
+{
+ DISPATCH(Vertex2dv, (v), (F, "glVertex2dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2f)(GLfloat x, GLfloat y)
+{
+ DISPATCH(Vertex2f, (x, y), (F, "glVertex2f(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2fv)(const GLfloat * v)
+{
+ DISPATCH(Vertex2fv, (v), (F, "glVertex2fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2i)(GLint x, GLint y)
+{
+ DISPATCH(Vertex2i, (x, y), (F, "glVertex2i(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2iv)(const GLint * v)
+{
+ DISPATCH(Vertex2iv, (v), (F, "glVertex2iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2s)(GLshort x, GLshort y)
+{
+ DISPATCH(Vertex2s, (x, y), (F, "glVertex2s(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex2sv)(const GLshort * v)
+{
+ DISPATCH(Vertex2sv, (v), (F, "glVertex2sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3d)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(Vertex3d, (x, y, z), (F, "glVertex3d(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3dv)(const GLdouble * v)
+{
+ DISPATCH(Vertex3dv, (v), (F, "glVertex3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(Vertex3f, (x, y, z), (F, "glVertex3f(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3fv)(const GLfloat * v)
+{
+ DISPATCH(Vertex3fv, (v), (F, "glVertex3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3i)(GLint x, GLint y, GLint z)
+{
+ DISPATCH(Vertex3i, (x, y, z), (F, "glVertex3i(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3iv)(const GLint * v)
+{
+ DISPATCH(Vertex3iv, (v), (F, "glVertex3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3s)(GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(Vertex3s, (x, y, z), (F, "glVertex3s(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex3sv)(const GLshort * v)
+{
+ DISPATCH(Vertex3sv, (v), (F, "glVertex3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4d)(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(Vertex4d, (x, y, z, w), (F, "glVertex4d(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4dv)(const GLdouble * v)
+{
+ DISPATCH(Vertex4dv, (v), (F, "glVertex4dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(Vertex4f, (x, y, z, w), (F, "glVertex4f(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4fv)(const GLfloat * v)
+{
+ DISPATCH(Vertex4fv, (v), (F, "glVertex4fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4i)(GLint x, GLint y, GLint z, GLint w)
+{
+ DISPATCH(Vertex4i, (x, y, z, w), (F, "glVertex4i(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4iv)(const GLint * v)
+{
+ DISPATCH(Vertex4iv, (v), (F, "glVertex4iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4s)(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(Vertex4s, (x, y, z, w), (F, "glVertex4s(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Vertex4sv)(const GLshort * v)
+{
+ DISPATCH(Vertex4sv, (v), (F, "glVertex4sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClipPlane)(GLenum plane, const GLdouble * equation)
+{
+ DISPATCH(ClipPlane, (plane, equation), (F, "glClipPlane(0x%x, %p);\n", plane, (const void *) equation));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorMaterial)(GLenum face, GLenum mode)
+{
+ DISPATCH(ColorMaterial, (face, mode), (F, "glColorMaterial(0x%x, 0x%x);\n", face, mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CullFace)(GLenum mode)
+{
+ DISPATCH(CullFace, (mode), (F, "glCullFace(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Fogf)(GLenum pname, GLfloat param)
+{
+ DISPATCH(Fogf, (pname, param), (F, "glFogf(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Fogfv)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(Fogfv, (pname, params), (F, "glFogfv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Fogi)(GLenum pname, GLint param)
+{
+ DISPATCH(Fogi, (pname, param), (F, "glFogi(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Fogiv)(GLenum pname, const GLint * params)
+{
+ DISPATCH(Fogiv, (pname, params), (F, "glFogiv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FrontFace)(GLenum mode)
+{
+ DISPATCH(FrontFace, (mode), (F, "glFrontFace(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Hint)(GLenum target, GLenum mode)
+{
+ DISPATCH(Hint, (target, mode), (F, "glHint(0x%x, 0x%x);\n", target, mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Lightf)(GLenum light, GLenum pname, GLfloat param)
+{
+ DISPATCH(Lightf, (light, pname, param), (F, "glLightf(0x%x, 0x%x, %f);\n", light, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Lightfv)(GLenum light, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(Lightfv, (light, pname, params), (F, "glLightfv(0x%x, 0x%x, %p);\n", light, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Lighti)(GLenum light, GLenum pname, GLint param)
+{
+ DISPATCH(Lighti, (light, pname, param), (F, "glLighti(0x%x, 0x%x, %d);\n", light, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Lightiv)(GLenum light, GLenum pname, const GLint * params)
+{
+ DISPATCH(Lightiv, (light, pname, params), (F, "glLightiv(0x%x, 0x%x, %p);\n", light, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LightModelf)(GLenum pname, GLfloat param)
+{
+ DISPATCH(LightModelf, (pname, param), (F, "glLightModelf(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LightModelfv)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(LightModelfv, (pname, params), (F, "glLightModelfv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LightModeli)(GLenum pname, GLint param)
+{
+ DISPATCH(LightModeli, (pname, param), (F, "glLightModeli(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LightModeliv)(GLenum pname, const GLint * params)
+{
+ DISPATCH(LightModeliv, (pname, params), (F, "glLightModeliv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LineStipple)(GLint factor, GLushort pattern)
+{
+ DISPATCH(LineStipple, (factor, pattern), (F, "glLineStipple(%d, %d);\n", factor, pattern));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LineWidth)(GLfloat width)
+{
+ DISPATCH(LineWidth, (width), (F, "glLineWidth(%f);\n", width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Materialf)(GLenum face, GLenum pname, GLfloat param)
+{
+ DISPATCH(Materialf, (face, pname, param), (F, "glMaterialf(0x%x, 0x%x, %f);\n", face, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Materialfv)(GLenum face, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(Materialfv, (face, pname, params), (F, "glMaterialfv(0x%x, 0x%x, %p);\n", face, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Materiali)(GLenum face, GLenum pname, GLint param)
+{
+ DISPATCH(Materiali, (face, pname, param), (F, "glMateriali(0x%x, 0x%x, %d);\n", face, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Materialiv)(GLenum face, GLenum pname, const GLint * params)
+{
+ DISPATCH(Materialiv, (face, pname, params), (F, "glMaterialiv(0x%x, 0x%x, %p);\n", face, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointSize)(GLfloat size)
+{
+ DISPATCH(PointSize, (size), (F, "glPointSize(%f);\n", size));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PolygonMode)(GLenum face, GLenum mode)
+{
+ DISPATCH(PolygonMode, (face, mode), (F, "glPolygonMode(0x%x, 0x%x);\n", face, mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PolygonStipple)(const GLubyte * mask)
+{
+ DISPATCH(PolygonStipple, (mask), (F, "glPolygonStipple(%p);\n", (const void *) mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Scissor)(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(Scissor, (x, y, width, height), (F, "glScissor(%d, %d, %d, %d);\n", x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ShadeModel)(GLenum mode)
+{
+ DISPATCH(ShadeModel, (mode), (F, "glShadeModel(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexParameterf)(GLenum target, GLenum pname, GLfloat param)
+{
+ DISPATCH(TexParameterf, (target, pname, param), (F, "glTexParameterf(0x%x, 0x%x, %f);\n", target, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexParameterfv)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(TexParameterfv, (target, pname, params), (F, "glTexParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexParameteri)(GLenum target, GLenum pname, GLint param)
+{
+ DISPATCH(TexParameteri, (target, pname, param), (F, "glTexParameteri(0x%x, 0x%x, %d);\n", target, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexParameteriv)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(TexParameteriv, (target, pname, params), (F, "glTexParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexImage1D, (target, level, internalformat, width, border, format, type, pixels), (F, "glTexImage1D(0x%x, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, internalformat, width, border, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexImage2D, (target, level, internalformat, width, height, border, format, type, pixels), (F, "glTexImage2D(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, internalformat, width, height, border, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexEnvf)(GLenum target, GLenum pname, GLfloat param)
+{
+ DISPATCH(TexEnvf, (target, pname, param), (F, "glTexEnvf(0x%x, 0x%x, %f);\n", target, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexEnvfv)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(TexEnvfv, (target, pname, params), (F, "glTexEnvfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexEnvi)(GLenum target, GLenum pname, GLint param)
+{
+ DISPATCH(TexEnvi, (target, pname, param), (F, "glTexEnvi(0x%x, 0x%x, %d);\n", target, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexEnviv)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(TexEnviv, (target, pname, params), (F, "glTexEnviv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGend)(GLenum coord, GLenum pname, GLdouble param)
+{
+ DISPATCH(TexGend, (coord, pname, param), (F, "glTexGend(0x%x, 0x%x, %f);\n", coord, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGendv)(GLenum coord, GLenum pname, const GLdouble * params)
+{
+ DISPATCH(TexGendv, (coord, pname, params), (F, "glTexGendv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGenf)(GLenum coord, GLenum pname, GLfloat param)
+{
+ DISPATCH(TexGenf, (coord, pname, param), (F, "glTexGenf(0x%x, 0x%x, %f);\n", coord, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGenfv)(GLenum coord, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(TexGenfv, (coord, pname, params), (F, "glTexGenfv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGeni)(GLenum coord, GLenum pname, GLint param)
+{
+ DISPATCH(TexGeni, (coord, pname, param), (F, "glTexGeni(0x%x, 0x%x, %d);\n", coord, pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexGeniv)(GLenum coord, GLenum pname, const GLint * params)
+{
+ DISPATCH(TexGeniv, (coord, pname, params), (F, "glTexGeniv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FeedbackBuffer)(GLsizei size, GLenum type, GLfloat * buffer)
+{
+ DISPATCH(FeedbackBuffer, (size, type, buffer), (F, "glFeedbackBuffer(%d, 0x%x, %p);\n", size, type, (const void *) buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SelectBuffer)(GLsizei size, GLuint * buffer)
+{
+ DISPATCH(SelectBuffer, (size, buffer), (F, "glSelectBuffer(%d, %p);\n", size, (const void *) buffer));
+}
+
+KEYWORD1 GLint KEYWORD2 NAME(RenderMode)(GLenum mode)
+{
+ RETURN_DISPATCH(RenderMode, (mode), (F, "glRenderMode(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(InitNames)(void)
+{
+ DISPATCH(InitNames, (), (F, "glInitNames();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadName)(GLuint name)
+{
+ DISPATCH(LoadName, (name), (F, "glLoadName(%d);\n", name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PassThrough)(GLfloat token)
+{
+ DISPATCH(PassThrough, (token), (F, "glPassThrough(%f);\n", token));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PopName)(void)
+{
+ DISPATCH(PopName, (), (F, "glPopName();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PushName)(GLuint name)
+{
+ DISPATCH(PushName, (name), (F, "glPushName(%d);\n", name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawBuffer)(GLenum mode)
+{
+ DISPATCH(DrawBuffer, (mode), (F, "glDrawBuffer(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Clear)(GLbitfield mask)
+{
+ DISPATCH(Clear, (mask), (F, "glClear(%d);\n", mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClearAccum)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ DISPATCH(ClearAccum, (red, green, blue, alpha), (F, "glClearAccum(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClearIndex)(GLfloat c)
+{
+ DISPATCH(ClearIndex, (c), (F, "glClearIndex(%f);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ DISPATCH(ClearColor, (red, green, blue, alpha), (F, "glClearColor(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClearStencil)(GLint s)
+{
+ DISPATCH(ClearStencil, (s), (F, "glClearStencil(%d);\n", s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClearDepth)(GLclampd depth)
+{
+ DISPATCH(ClearDepth, (depth), (F, "glClearDepth(%f);\n", depth));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilMask)(GLuint mask)
+{
+ DISPATCH(StencilMask, (mask), (F, "glStencilMask(%d);\n", mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ DISPATCH(ColorMask, (red, green, blue, alpha), (F, "glColorMask(%d, %d, %d, %d);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DepthMask)(GLboolean flag)
+{
+ DISPATCH(DepthMask, (flag), (F, "glDepthMask(%d);\n", flag));
+}
+
+KEYWORD1 void KEYWORD2 NAME(IndexMask)(GLuint mask)
+{
+ DISPATCH(IndexMask, (mask), (F, "glIndexMask(%d);\n", mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Accum)(GLenum op, GLfloat value)
+{
+ DISPATCH(Accum, (op, value), (F, "glAccum(0x%x, %f);\n", op, value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Disable)(GLenum cap)
+{
+ DISPATCH(Disable, (cap), (F, "glDisable(0x%x);\n", cap));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Enable)(GLenum cap)
+{
+ DISPATCH(Enable, (cap), (F, "glEnable(0x%x);\n", cap));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Finish)(void)
+{
+ DISPATCH(Finish, (), (F, "glFinish();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Flush)(void)
+{
+ DISPATCH(Flush, (), (F, "glFlush();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PopAttrib)(void)
+{
+ DISPATCH(PopAttrib, (), (F, "glPopAttrib();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PushAttrib)(GLbitfield mask)
+{
+ DISPATCH(PushAttrib, (mask), (F, "glPushAttrib(%d);\n", mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Map1d)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points)
+{
+ DISPATCH(Map1d, (target, u1, u2, stride, order, points), (F, "glMap1d(0x%x, %f, %f, %d, %d, %p);\n", target, u1, u2, stride, order, (const void *) points));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Map1f)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points)
+{
+ DISPATCH(Map1f, (target, u1, u2, stride, order, points), (F, "glMap1f(0x%x, %f, %f, %d, %d, %p);\n", target, u1, u2, stride, order, (const void *) points));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Map2d)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points)
+{
+ DISPATCH(Map2d, (target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points), (F, "glMap2d(0x%x, %f, %f, %d, %d, %f, %f, %d, %d, %p);\n", target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, (const void *) points));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Map2f)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points)
+{
+ DISPATCH(Map2f, (target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points), (F, "glMap2f(0x%x, %f, %f, %d, %d, %f, %f, %d, %d, %p);\n", target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, (const void *) points));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MapGrid1d)(GLint un, GLdouble u1, GLdouble u2)
+{
+ DISPATCH(MapGrid1d, (un, u1, u2), (F, "glMapGrid1d(%d, %f, %f);\n", un, u1, u2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MapGrid1f)(GLint un, GLfloat u1, GLfloat u2)
+{
+ DISPATCH(MapGrid1f, (un, u1, u2), (F, "glMapGrid1f(%d, %f, %f);\n", un, u1, u2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MapGrid2d)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)
+{
+ DISPATCH(MapGrid2d, (un, u1, u2, vn, v1, v2), (F, "glMapGrid2d(%d, %f, %f, %d, %f, %f);\n", un, u1, u2, vn, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MapGrid2f)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)
+{
+ DISPATCH(MapGrid2f, (un, u1, u2, vn, v1, v2), (F, "glMapGrid2f(%d, %f, %f, %d, %f, %f);\n", un, u1, u2, vn, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord1d)(GLdouble u)
+{
+ DISPATCH(EvalCoord1d, (u), (F, "glEvalCoord1d(%f);\n", u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord1dv)(const GLdouble * u)
+{
+ DISPATCH(EvalCoord1dv, (u), (F, "glEvalCoord1dv(%p);\n", (const void *) u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord1f)(GLfloat u)
+{
+ DISPATCH(EvalCoord1f, (u), (F, "glEvalCoord1f(%f);\n", u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord1fv)(const GLfloat * u)
+{
+ DISPATCH(EvalCoord1fv, (u), (F, "glEvalCoord1fv(%p);\n", (const void *) u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord2d)(GLdouble u, GLdouble v)
+{
+ DISPATCH(EvalCoord2d, (u, v), (F, "glEvalCoord2d(%f, %f);\n", u, v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord2dv)(const GLdouble * u)
+{
+ DISPATCH(EvalCoord2dv, (u), (F, "glEvalCoord2dv(%p);\n", (const void *) u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord2f)(GLfloat u, GLfloat v)
+{
+ DISPATCH(EvalCoord2f, (u, v), (F, "glEvalCoord2f(%f, %f);\n", u, v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalCoord2fv)(const GLfloat * u)
+{
+ DISPATCH(EvalCoord2fv, (u), (F, "glEvalCoord2fv(%p);\n", (const void *) u));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalMesh1)(GLenum mode, GLint i1, GLint i2)
+{
+ DISPATCH(EvalMesh1, (mode, i1, i2), (F, "glEvalMesh1(0x%x, %d, %d);\n", mode, i1, i2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalPoint1)(GLint i)
+{
+ DISPATCH(EvalPoint1, (i), (F, "glEvalPoint1(%d);\n", i));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalMesh2)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
+{
+ DISPATCH(EvalMesh2, (mode, i1, i2, j1, j2), (F, "glEvalMesh2(0x%x, %d, %d, %d, %d);\n", mode, i1, i2, j1, j2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EvalPoint2)(GLint i, GLint j)
+{
+ DISPATCH(EvalPoint2, (i, j), (F, "glEvalPoint2(%d, %d);\n", i, j));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AlphaFunc)(GLenum func, GLclampf ref)
+{
+ DISPATCH(AlphaFunc, (func, ref), (F, "glAlphaFunc(0x%x, %f);\n", func, ref));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendFunc)(GLenum sfactor, GLenum dfactor)
+{
+ DISPATCH(BlendFunc, (sfactor, dfactor), (F, "glBlendFunc(0x%x, 0x%x);\n", sfactor, dfactor));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LogicOp)(GLenum opcode)
+{
+ DISPATCH(LogicOp, (opcode), (F, "glLogicOp(0x%x);\n", opcode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilFunc)(GLenum func, GLint ref, GLuint mask)
+{
+ DISPATCH(StencilFunc, (func, ref, mask), (F, "glStencilFunc(0x%x, %d, %d);\n", func, ref, mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilOp)(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ DISPATCH(StencilOp, (fail, zfail, zpass), (F, "glStencilOp(0x%x, 0x%x, 0x%x);\n", fail, zfail, zpass));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DepthFunc)(GLenum func)
+{
+ DISPATCH(DepthFunc, (func), (F, "glDepthFunc(0x%x);\n", func));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelZoom)(GLfloat xfactor, GLfloat yfactor)
+{
+ DISPATCH(PixelZoom, (xfactor, yfactor), (F, "glPixelZoom(%f, %f);\n", xfactor, yfactor));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelTransferf)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PixelTransferf, (pname, param), (F, "glPixelTransferf(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelTransferi)(GLenum pname, GLint param)
+{
+ DISPATCH(PixelTransferi, (pname, param), (F, "glPixelTransferi(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelStoref)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PixelStoref, (pname, param), (F, "glPixelStoref(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelStorei)(GLenum pname, GLint param)
+{
+ DISPATCH(PixelStorei, (pname, param), (F, "glPixelStorei(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelMapfv)(GLenum map, GLsizei mapsize, const GLfloat * values)
+{
+ DISPATCH(PixelMapfv, (map, mapsize, values), (F, "glPixelMapfv(0x%x, %d, %p);\n", map, mapsize, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelMapuiv)(GLenum map, GLsizei mapsize, const GLuint * values)
+{
+ DISPATCH(PixelMapuiv, (map, mapsize, values), (F, "glPixelMapuiv(0x%x, %d, %p);\n", map, mapsize, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PixelMapusv)(GLenum map, GLsizei mapsize, const GLushort * values)
+{
+ DISPATCH(PixelMapusv, (map, mapsize, values), (F, "glPixelMapusv(0x%x, %d, %p);\n", map, mapsize, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ReadBuffer)(GLenum mode)
+{
+ DISPATCH(ReadBuffer, (mode), (F, "glReadBuffer(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
+{
+ DISPATCH(CopyPixels, (x, y, width, height, type), (F, "glCopyPixels(%d, %d, %d, %d, 0x%x);\n", x, y, width, height, type));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * pixels)
+{
+ DISPATCH(ReadPixels, (x, y, width, height, format, type, pixels), (F, "glReadPixels(%d, %d, %d, %d, 0x%x, 0x%x, %p);\n", x, y, width, height, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawPixels)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(DrawPixels, (width, height, format, type, pixels), (F, "glDrawPixels(%d, %d, 0x%x, 0x%x, %p);\n", width, height, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBooleanv)(GLenum pname, GLboolean * params)
+{
+ DISPATCH(GetBooleanv, (pname, params), (F, "glGetBooleanv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetClipPlane)(GLenum plane, GLdouble * equation)
+{
+ DISPATCH(GetClipPlane, (plane, equation), (F, "glGetClipPlane(0x%x, %p);\n", plane, (const void *) equation));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetDoublev)(GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetDoublev, (pname, params), (F, "glGetDoublev(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 GLenum KEYWORD2 NAME(GetError)(void)
+{
+ RETURN_DISPATCH(GetError, (), (F, "glGetError();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetFloatv)(GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetFloatv, (pname, params), (F, "glGetFloatv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetIntegerv)(GLenum pname, GLint * params)
+{
+ DISPATCH(GetIntegerv, (pname, params), (F, "glGetIntegerv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetLightfv)(GLenum light, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetLightfv, (light, pname, params), (F, "glGetLightfv(0x%x, 0x%x, %p);\n", light, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetLightiv)(GLenum light, GLenum pname, GLint * params)
+{
+ DISPATCH(GetLightiv, (light, pname, params), (F, "glGetLightiv(0x%x, 0x%x, %p);\n", light, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetMapdv)(GLenum target, GLenum query, GLdouble * v)
+{
+ DISPATCH(GetMapdv, (target, query, v), (F, "glGetMapdv(0x%x, 0x%x, %p);\n", target, query, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetMapfv)(GLenum target, GLenum query, GLfloat * v)
+{
+ DISPATCH(GetMapfv, (target, query, v), (F, "glGetMapfv(0x%x, 0x%x, %p);\n", target, query, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetMapiv)(GLenum target, GLenum query, GLint * v)
+{
+ DISPATCH(GetMapiv, (target, query, v), (F, "glGetMapiv(0x%x, 0x%x, %p);\n", target, query, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetMaterialfv)(GLenum face, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetMaterialfv, (face, pname, params), (F, "glGetMaterialfv(0x%x, 0x%x, %p);\n", face, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetMaterialiv)(GLenum face, GLenum pname, GLint * params)
+{
+ DISPATCH(GetMaterialiv, (face, pname, params), (F, "glGetMaterialiv(0x%x, 0x%x, %p);\n", face, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetPixelMapfv)(GLenum map, GLfloat * values)
+{
+ DISPATCH(GetPixelMapfv, (map, values), (F, "glGetPixelMapfv(0x%x, %p);\n", map, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetPixelMapuiv)(GLenum map, GLuint * values)
+{
+ DISPATCH(GetPixelMapuiv, (map, values), (F, "glGetPixelMapuiv(0x%x, %p);\n", map, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetPixelMapusv)(GLenum map, GLushort * values)
+{
+ DISPATCH(GetPixelMapusv, (map, values), (F, "glGetPixelMapusv(0x%x, %p);\n", map, (const void *) values));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetPolygonStipple)(GLubyte * mask)
+{
+ DISPATCH(GetPolygonStipple, (mask), (F, "glGetPolygonStipple(%p);\n", (const void *) mask));
+}
+
+KEYWORD1 const GLubyte * KEYWORD2 NAME(GetString)(GLenum name)
+{
+ RETURN_DISPATCH(GetString, (name), (F, "glGetString(0x%x);\n", name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexEnvfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetTexEnvfv, (target, pname, params), (F, "glGetTexEnvfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexEnviv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetTexEnviv, (target, pname, params), (F, "glGetTexEnviv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexGendv)(GLenum coord, GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetTexGendv, (coord, pname, params), (F, "glGetTexGendv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexGenfv)(GLenum coord, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetTexGenfv, (coord, pname, params), (F, "glGetTexGenfv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexGeniv)(GLenum coord, GLenum pname, GLint * params)
+{
+ DISPATCH(GetTexGeniv, (coord, pname, params), (F, "glGetTexGeniv(0x%x, 0x%x, %p);\n", coord, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels)
+{
+ DISPATCH(GetTexImage, (target, level, format, type, pixels), (F, "glGetTexImage(0x%x, %d, 0x%x, 0x%x, %p);\n", target, level, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetTexParameterfv, (target, pname, params), (F, "glGetTexParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetTexParameteriv, (target, pname, params), (F, "glGetTexParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetTexLevelParameterfv, (target, level, pname, params), (F, "glGetTexLevelParameterfv(0x%x, %d, 0x%x, %p);\n", target, level, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params)
+{
+ DISPATCH(GetTexLevelParameteriv, (target, level, pname, params), (F, "glGetTexLevelParameteriv(0x%x, %d, 0x%x, %p);\n", target, level, pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsEnabled)(GLenum cap)
+{
+ RETURN_DISPATCH(IsEnabled, (cap), (F, "glIsEnabled(0x%x);\n", cap));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsList)(GLuint list)
+{
+ RETURN_DISPATCH(IsList, (list), (F, "glIsList(%d);\n", list));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DepthRange)(GLclampd zNear, GLclampd zFar)
+{
+ DISPATCH(DepthRange, (zNear, zFar), (F, "glDepthRange(%f, %f);\n", zNear, zFar));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Frustum)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
+{
+ DISPATCH(Frustum, (left, right, bottom, top, zNear, zFar), (F, "glFrustum(%f, %f, %f, %f, %f, %f);\n", left, right, bottom, top, zNear, zFar));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadIdentity)(void)
+{
+ DISPATCH(LoadIdentity, (), (F, "glLoadIdentity();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadMatrixf)(const GLfloat * m)
+{
+ DISPATCH(LoadMatrixf, (m), (F, "glLoadMatrixf(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadMatrixd)(const GLdouble * m)
+{
+ DISPATCH(LoadMatrixd, (m), (F, "glLoadMatrixd(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MatrixMode)(GLenum mode)
+{
+ DISPATCH(MatrixMode, (mode), (F, "glMatrixMode(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultMatrixf)(const GLfloat * m)
+{
+ DISPATCH(MultMatrixf, (m), (F, "glMultMatrixf(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultMatrixd)(const GLdouble * m)
+{
+ DISPATCH(MultMatrixd, (m), (F, "glMultMatrixd(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Ortho)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
+{
+ DISPATCH(Ortho, (left, right, bottom, top, zNear, zFar), (F, "glOrtho(%f, %f, %f, %f, %f, %f);\n", left, right, bottom, top, zNear, zFar));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PopMatrix)(void)
+{
+ DISPATCH(PopMatrix, (), (F, "glPopMatrix();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PushMatrix)(void)
+{
+ DISPATCH(PushMatrix, (), (F, "glPushMatrix();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rotated)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(Rotated, (angle, x, y, z), (F, "glRotated(%f, %f, %f, %f);\n", angle, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Rotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(Rotatef, (angle, x, y, z), (F, "glRotatef(%f, %f, %f, %f);\n", angle, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Scaled)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(Scaled, (x, y, z), (F, "glScaled(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Scalef)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(Scalef, (x, y, z), (F, "glScalef(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Translated)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(Translated, (x, y, z), (F, "glTranslated(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Translatef)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(Translatef, (x, y, z), (F, "glTranslatef(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Viewport)(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(Viewport, (x, y, width, height), (F, "glViewport(%d, %d, %d, %d);\n", x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ArrayElement)(GLint i)
+{
+ DISPATCH(ArrayElement, (i), (F, "glArrayElement(%d);\n", i));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ArrayElementEXT)(GLint i)
+{
+ DISPATCH(ArrayElement, (i), (F, "glArrayElementEXT(%d);\n", i));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindTexture)(GLenum target, GLuint texture)
+{
+ DISPATCH(BindTexture, (target, texture), (F, "glBindTexture(0x%x, %d);\n", target, texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindTextureEXT)(GLenum target, GLuint texture)
+{
+ DISPATCH(BindTexture, (target, texture), (F, "glBindTextureEXT(0x%x, %d);\n", target, texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(ColorPointer, (size, type, stride, pointer), (F, "glColorPointer(%d, 0x%x, %d, %p);\n", size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DisableClientState)(GLenum array)
+{
+ DISPATCH(DisableClientState, (array), (F, "glDisableClientState(0x%x);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawArrays)(GLenum mode, GLint first, GLsizei count)
+{
+ DISPATCH(DrawArrays, (mode, first, count), (F, "glDrawArrays(0x%x, %d, %d);\n", mode, first, count));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawArraysEXT)(GLenum mode, GLint first, GLsizei count)
+{
+ DISPATCH(DrawArrays, (mode, first, count), (F, "glDrawArraysEXT(0x%x, %d, %d);\n", mode, first, count));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
+{
+ DISPATCH(DrawElements, (mode, count, type, indices), (F, "glDrawElements(0x%x, %d, 0x%x, %p);\n", mode, count, type, (const void *) indices));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EdgeFlagPointer)(GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(EdgeFlagPointer, (stride, pointer), (F, "glEdgeFlagPointer(%d, %p);\n", stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EnableClientState)(GLenum array)
+{
+ DISPATCH(EnableClientState, (array), (F, "glEnableClientState(0x%x);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(IndexPointer)(GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(IndexPointer, (type, stride, pointer), (F, "glIndexPointer(0x%x, %d, %p);\n", type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexub)(GLubyte c)
+{
+ DISPATCH(Indexub, (c), (F, "glIndexub(%d);\n", c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Indexubv)(const GLubyte * c)
+{
+ DISPATCH(Indexubv, (c), (F, "glIndexubv(%p);\n", (const void *) c));
+}
+
+KEYWORD1 void KEYWORD2 NAME(InterleavedArrays)(GLenum format, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(InterleavedArrays, (format, stride, pointer), (F, "glInterleavedArrays(0x%x, %d, %p);\n", format, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(NormalPointer)(GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(NormalPointer, (type, stride, pointer), (F, "glNormalPointer(0x%x, %d, %p);\n", type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PolygonOffset)(GLfloat factor, GLfloat units)
+{
+ DISPATCH(PolygonOffset, (factor, units), (F, "glPolygonOffset(%f, %f);\n", factor, units));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(TexCoordPointer, (size, type, stride, pointer), (F, "glTexCoordPointer(%d, 0x%x, %d, %p);\n", size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(VertexPointer, (size, type, stride, pointer), (F, "glVertexPointer(%d, 0x%x, %d, %p);\n", size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(AreTexturesResident)(GLsizei n, const GLuint * textures, GLboolean * residences)
+{
+ RETURN_DISPATCH(AreTexturesResident, (n, textures, residences), (F, "glAreTexturesResident(%d, %p, %p);\n", n, (const void *) textures, (const void *) residences));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 GLboolean KEYWORD2 NAME(AreTexturesResidentEXT)(GLsizei n, const GLuint * textures, GLboolean * residences)
+{
+ RETURN_DISPATCH(AreTexturesResident, (n, textures, residences), (F, "glAreTexturesResidentEXT(%d, %p, %p);\n", n, (const void *) textures, (const void *) residences));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border)
+{
+ DISPATCH(CopyTexImage1D, (target, level, internalformat, x, y, width, border), (F, "glCopyTexImage1D(0x%x, %d, 0x%x, %d, %d, %d, %d);\n", target, level, internalformat, x, y, width, border));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexImage1DEXT)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border)
+{
+ DISPATCH(CopyTexImage1D, (target, level, internalformat, x, y, width, border), (F, "glCopyTexImage1DEXT(0x%x, %d, 0x%x, %d, %d, %d, %d);\n", target, level, internalformat, x, y, width, border));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+ DISPATCH(CopyTexImage2D, (target, level, internalformat, x, y, width, height, border), (F, "glCopyTexImage2D(0x%x, %d, 0x%x, %d, %d, %d, %d, %d);\n", target, level, internalformat, x, y, width, height, border));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexImage2DEXT)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+ DISPATCH(CopyTexImage2D, (target, level, internalformat, x, y, width, height, border), (F, "glCopyTexImage2DEXT(0x%x, %d, 0x%x, %d, %d, %d, %d, %d);\n", target, level, internalformat, x, y, width, height, border));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyTexSubImage1D, (target, level, xoffset, x, y, width), (F, "glCopyTexSubImage1D(0x%x, %d, %d, %d, %d, %d);\n", target, level, xoffset, x, y, width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage1DEXT)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyTexSubImage1D, (target, level, xoffset, x, y, width), (F, "glCopyTexSubImage1DEXT(0x%x, %d, %d, %d, %d, %d);\n", target, level, xoffset, x, y, width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyTexSubImage2D, (target, level, xoffset, yoffset, x, y, width, height), (F, "glCopyTexSubImage2D(0x%x, %d, %d, %d, %d, %d, %d, %d);\n", target, level, xoffset, yoffset, x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage2DEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyTexSubImage2D, (target, level, xoffset, yoffset, x, y, width, height), (F, "glCopyTexSubImage2DEXT(0x%x, %d, %d, %d, %d, %d, %d, %d);\n", target, level, xoffset, yoffset, x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteTextures)(GLsizei n, const GLuint * textures)
+{
+ DISPATCH(DeleteTextures, (n, textures), (F, "glDeleteTextures(%d, %p);\n", n, (const void *) textures));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 void KEYWORD2 NAME(DeleteTexturesEXT)(GLsizei n, const GLuint * textures)
+{
+ DISPATCH(DeleteTextures, (n, textures), (F, "glDeleteTexturesEXT(%d, %p);\n", n, (const void *) textures));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GenTextures)(GLsizei n, GLuint * textures)
+{
+ DISPATCH(GenTextures, (n, textures), (F, "glGenTextures(%d, %p);\n", n, (const void *) textures));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 void KEYWORD2 NAME(GenTexturesEXT)(GLsizei n, GLuint * textures)
+{
+ DISPATCH(GenTextures, (n, textures), (F, "glGenTexturesEXT(%d, %p);\n", n, (const void *) textures));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetPointerv)(GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetPointerv, (pname, params), (F, "glGetPointerv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetPointervEXT)(GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetPointerv, (pname, params), (F, "glGetPointervEXT(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsTexture)(GLuint texture)
+{
+ RETURN_DISPATCH(IsTexture, (texture), (F, "glIsTexture(%d);\n", texture));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 GLboolean KEYWORD2 NAME(IsTextureEXT)(GLuint texture)
+{
+ RETURN_DISPATCH(IsTexture, (texture), (F, "glIsTextureEXT(%d);\n", texture));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(PrioritizeTextures)(GLsizei n, const GLuint * textures, const GLclampf * priorities)
+{
+ DISPATCH(PrioritizeTextures, (n, textures, priorities), (F, "glPrioritizeTextures(%d, %p, %p);\n", n, (const void *) textures, (const void *) priorities));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PrioritizeTexturesEXT)(GLsizei n, const GLuint * textures, const GLclampf * priorities)
+{
+ DISPATCH(PrioritizeTextures, (n, textures, priorities), (F, "glPrioritizeTexturesEXT(%d, %p, %p);\n", n, (const void *) textures, (const void *) priorities));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage1D, (target, level, xoffset, width, format, type, pixels), (F, "glTexSubImage1D(0x%x, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, width, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage1DEXT)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage1D, (target, level, xoffset, width, format, type, pixels), (F, "glTexSubImage1DEXT(0x%x, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, width, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage2D, (target, level, xoffset, yoffset, width, height, format, type, pixels), (F, "glTexSubImage2D(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, yoffset, width, height, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage2DEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage2D, (target, level, xoffset, yoffset, width, height, format, type, pixels), (F, "glTexSubImage2DEXT(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, yoffset, width, height, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PopClientAttrib)(void)
+{
+ DISPATCH(PopClientAttrib, (), (F, "glPopClientAttrib();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PushClientAttrib)(GLbitfield mask)
+{
+ DISPATCH(PushClientAttrib, (mask), (F, "glPushClientAttrib(%d);\n", mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ DISPATCH(BlendColor, (red, green, blue, alpha), (F, "glBlendColor(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendColorEXT)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ DISPATCH(BlendColor, (red, green, blue, alpha), (F, "glBlendColorEXT(%f, %f, %f, %f);\n", red, green, blue, alpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendEquation)(GLenum mode)
+{
+ DISPATCH(BlendEquation, (mode), (F, "glBlendEquation(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendEquationEXT)(GLenum mode)
+{
+ DISPATCH(BlendEquation, (mode), (F, "glBlendEquationEXT(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices)
+{
+ DISPATCH(DrawRangeElements, (mode, start, end, count, type, indices), (F, "glDrawRangeElements(0x%x, %d, %d, %d, 0x%x, %p);\n", mode, start, end, count, type, (const void *) indices));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawRangeElementsEXT)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices)
+{
+ DISPATCH(DrawRangeElements, (mode, start, end, count, type, indices), (F, "glDrawRangeElementsEXT(0x%x, %d, %d, %d, 0x%x, %p);\n", mode, start, end, count, type, (const void *) indices));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorTable)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table)
+{
+ DISPATCH(ColorTable, (target, internalformat, width, format, type, table), (F, "glColorTable(0x%x, 0x%x, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, format, type, (const void *) table));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_339)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_339)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table)
+{
+ DISPATCH(ColorTable, (target, internalformat, width, format, type, table), (F, "glColorTableSGI(0x%x, 0x%x, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, format, type, (const void *) table));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorTableEXT)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * table)
+{
+ DISPATCH(ColorTable, (target, internalformat, width, format, type, table), (F, "glColorTableEXT(0x%x, 0x%x, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, format, type, (const void *) table));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorTableParameterfv)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(ColorTableParameterfv, (target, pname, params), (F, "glColorTableParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_340)(GLenum target, GLenum pname, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_340)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(ColorTableParameterfv, (target, pname, params), (F, "glColorTableParameterfvSGI(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorTableParameteriv)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(ColorTableParameteriv, (target, pname, params), (F, "glColorTableParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_341)(GLenum target, GLenum pname, const GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_341)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(ColorTableParameteriv, (target, pname, params), (F, "glColorTableParameterivSGI(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyColorTable)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyColorTable, (target, internalformat, x, y, width), (F, "glCopyColorTable(0x%x, 0x%x, %d, %d, %d);\n", target, internalformat, x, y, width));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_342)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_342)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyColorTable, (target, internalformat, x, y, width), (F, "glCopyColorTableSGI(0x%x, 0x%x, %d, %d, %d);\n", target, internalformat, x, y, width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetColorTable)(GLenum target, GLenum format, GLenum type, GLvoid * table)
+{
+ DISPATCH(GetColorTable, (target, format, type, table), (F, "glGetColorTable(0x%x, 0x%x, 0x%x, %p);\n", target, format, type, (const void *) table));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_343)(GLenum target, GLenum format, GLenum type, GLvoid * table);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_343)(GLenum target, GLenum format, GLenum type, GLvoid * table)
+{
+ DISPATCH(GetColorTable, (target, format, type, table), (F, "glGetColorTableSGI(0x%x, 0x%x, 0x%x, %p);\n", target, format, type, (const void *) table));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 void KEYWORD2 NAME(GetColorTableEXT)(GLenum target, GLenum format, GLenum type, GLvoid * table)
+{
+ DISPATCH(GetColorTable, (target, format, type, table), (F, "glGetColorTableEXT(0x%x, 0x%x, 0x%x, %p);\n", target, format, type, (const void *) table));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetColorTableParameterfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetColorTableParameterfv, (target, pname, params), (F, "glGetColorTableParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_344)(GLenum target, GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_344)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetColorTableParameterfv, (target, pname, params), (F, "glGetColorTableParameterfvSGI(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 void KEYWORD2 NAME(GetColorTableParameterfvEXT)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetColorTableParameterfv, (target, pname, params), (F, "glGetColorTableParameterfvEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetColorTableParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetColorTableParameteriv, (target, pname, params), (F, "glGetColorTableParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_345)(GLenum target, GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_345)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetColorTableParameteriv, (target, pname, params), (F, "glGetColorTableParameterivSGI(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1 void KEYWORD2 NAME(GetColorTableParameterivEXT)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetColorTableParameteriv, (target, pname, params), (F, "glGetColorTableParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(ColorSubTable)(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data)
+{
+ DISPATCH(ColorSubTable, (target, start, count, format, type, data), (F, "glColorSubTable(0x%x, %d, %d, 0x%x, 0x%x, %p);\n", target, start, count, format, type, (const void *) data));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_346)(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_346)(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid * data)
+{
+ DISPATCH(ColorSubTable, (target, start, count, format, type, data), (F, "glColorSubTableEXT(0x%x, %d, %d, 0x%x, 0x%x, %p);\n", target, start, count, format, type, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyColorSubTable)(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyColorSubTable, (target, start, x, y, width), (F, "glCopyColorSubTable(0x%x, %d, %d, %d, %d);\n", target, start, x, y, width));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_347)(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_347)(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyColorSubTable, (target, start, x, y, width), (F, "glCopyColorSubTableEXT(0x%x, %d, %d, %d, %d);\n", target, start, x, y, width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionFilter1D)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image)
+{
+ DISPATCH(ConvolutionFilter1D, (target, internalformat, width, format, type, image), (F, "glConvolutionFilter1D(0x%x, 0x%x, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, format, type, (const void *) image));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_348)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_348)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid * image)
+{
+ DISPATCH(ConvolutionFilter1D, (target, internalformat, width, format, type, image), (F, "glConvolutionFilter1DEXT(0x%x, 0x%x, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, format, type, (const void *) image));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionFilter2D)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image)
+{
+ DISPATCH(ConvolutionFilter2D, (target, internalformat, width, height, format, type, image), (F, "glConvolutionFilter2D(0x%x, 0x%x, %d, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, height, format, type, (const void *) image));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_349)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_349)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * image)
+{
+ DISPATCH(ConvolutionFilter2D, (target, internalformat, width, height, format, type, image), (F, "glConvolutionFilter2DEXT(0x%x, 0x%x, %d, %d, 0x%x, 0x%x, %p);\n", target, internalformat, width, height, format, type, (const void *) image));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionParameterf)(GLenum target, GLenum pname, GLfloat params)
+{
+ DISPATCH(ConvolutionParameterf, (target, pname, params), (F, "glConvolutionParameterf(0x%x, 0x%x, %f);\n", target, pname, params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_350)(GLenum target, GLenum pname, GLfloat params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_350)(GLenum target, GLenum pname, GLfloat params)
+{
+ DISPATCH(ConvolutionParameterf, (target, pname, params), (F, "glConvolutionParameterfEXT(0x%x, 0x%x, %f);\n", target, pname, params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionParameterfv)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(ConvolutionParameterfv, (target, pname, params), (F, "glConvolutionParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_351)(GLenum target, GLenum pname, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_351)(GLenum target, GLenum pname, const GLfloat * params)
+{
+ DISPATCH(ConvolutionParameterfv, (target, pname, params), (F, "glConvolutionParameterfvEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionParameteri)(GLenum target, GLenum pname, GLint params)
+{
+ DISPATCH(ConvolutionParameteri, (target, pname, params), (F, "glConvolutionParameteri(0x%x, 0x%x, %d);\n", target, pname, params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_352)(GLenum target, GLenum pname, GLint params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_352)(GLenum target, GLenum pname, GLint params)
+{
+ DISPATCH(ConvolutionParameteri, (target, pname, params), (F, "glConvolutionParameteriEXT(0x%x, 0x%x, %d);\n", target, pname, params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ConvolutionParameteriv)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(ConvolutionParameteriv, (target, pname, params), (F, "glConvolutionParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_353)(GLenum target, GLenum pname, const GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_353)(GLenum target, GLenum pname, const GLint * params)
+{
+ DISPATCH(ConvolutionParameteriv, (target, pname, params), (F, "glConvolutionParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyConvolutionFilter1D)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyConvolutionFilter1D, (target, internalformat, x, y, width), (F, "glCopyConvolutionFilter1D(0x%x, 0x%x, %d, %d, %d);\n", target, internalformat, x, y, width));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_354)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_354)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width)
+{
+ DISPATCH(CopyConvolutionFilter1D, (target, internalformat, x, y, width), (F, "glCopyConvolutionFilter1DEXT(0x%x, 0x%x, %d, %d, %d);\n", target, internalformat, x, y, width));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyConvolutionFilter2D)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyConvolutionFilter2D, (target, internalformat, x, y, width, height), (F, "glCopyConvolutionFilter2D(0x%x, 0x%x, %d, %d, %d, %d);\n", target, internalformat, x, y, width, height));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_355)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_355)(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyConvolutionFilter2D, (target, internalformat, x, y, width, height), (F, "glCopyConvolutionFilter2DEXT(0x%x, 0x%x, %d, %d, %d, %d);\n", target, internalformat, x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetConvolutionFilter)(GLenum target, GLenum format, GLenum type, GLvoid * image)
+{
+ DISPATCH(GetConvolutionFilter, (target, format, type, image), (F, "glGetConvolutionFilter(0x%x, 0x%x, 0x%x, %p);\n", target, format, type, (const void *) image));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_356)(GLenum target, GLenum format, GLenum type, GLvoid * image);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_356)(GLenum target, GLenum format, GLenum type, GLvoid * image)
+{
+ DISPATCH(GetConvolutionFilter, (target, format, type, image), (F, "glGetConvolutionFilterEXT(0x%x, 0x%x, 0x%x, %p);\n", target, format, type, (const void *) image));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetConvolutionParameterfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetConvolutionParameterfv, (target, pname, params), (F, "glGetConvolutionParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_357)(GLenum target, GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_357)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetConvolutionParameterfv, (target, pname, params), (F, "glGetConvolutionParameterfvEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetConvolutionParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetConvolutionParameteriv, (target, pname, params), (F, "glGetConvolutionParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_358)(GLenum target, GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_358)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetConvolutionParameteriv, (target, pname, params), (F, "glGetConvolutionParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetSeparableFilter)(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span)
+{
+ DISPATCH(GetSeparableFilter, (target, format, type, row, column, span), (F, "glGetSeparableFilter(0x%x, 0x%x, 0x%x, %p, %p, %p);\n", target, format, type, (const void *) row, (const void *) column, (const void *) span));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_359)(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_359)(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span)
+{
+ DISPATCH(GetSeparableFilter, (target, format, type, row, column, span), (F, "glGetSeparableFilterEXT(0x%x, 0x%x, 0x%x, %p, %p, %p);\n", target, format, type, (const void *) row, (const void *) column, (const void *) span));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(SeparableFilter2D)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column)
+{
+ DISPATCH(SeparableFilter2D, (target, internalformat, width, height, format, type, row, column), (F, "glSeparableFilter2D(0x%x, 0x%x, %d, %d, 0x%x, 0x%x, %p, %p);\n", target, internalformat, width, height, format, type, (const void *) row, (const void *) column));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_360)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_360)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * row, const GLvoid * column)
+{
+ DISPATCH(SeparableFilter2D, (target, internalformat, width, height, format, type, row, column), (F, "glSeparableFilter2DEXT(0x%x, 0x%x, %d, %d, 0x%x, 0x%x, %p, %p);\n", target, internalformat, width, height, format, type, (const void *) row, (const void *) column));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetHistogram)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values)
+{
+ DISPATCH(GetHistogram, (target, reset, format, type, values), (F, "glGetHistogram(0x%x, %d, 0x%x, 0x%x, %p);\n", target, reset, format, type, (const void *) values));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_361)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_361)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values)
+{
+ DISPATCH(GetHistogram, (target, reset, format, type, values), (F, "glGetHistogramEXT(0x%x, %d, 0x%x, 0x%x, %p);\n", target, reset, format, type, (const void *) values));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetHistogramParameterfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetHistogramParameterfv, (target, pname, params), (F, "glGetHistogramParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_362)(GLenum target, GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_362)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetHistogramParameterfv, (target, pname, params), (F, "glGetHistogramParameterfvEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetHistogramParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetHistogramParameteriv, (target, pname, params), (F, "glGetHistogramParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_363)(GLenum target, GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_363)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetHistogramParameteriv, (target, pname, params), (F, "glGetHistogramParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetMinmax)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values)
+{
+ DISPATCH(GetMinmax, (target, reset, format, type, values), (F, "glGetMinmax(0x%x, %d, 0x%x, 0x%x, %p);\n", target, reset, format, type, (const void *) values));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_364)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_364)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values)
+{
+ DISPATCH(GetMinmax, (target, reset, format, type, values), (F, "glGetMinmaxEXT(0x%x, %d, 0x%x, 0x%x, %p);\n", target, reset, format, type, (const void *) values));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetMinmaxParameterfv)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetMinmaxParameterfv, (target, pname, params), (F, "glGetMinmaxParameterfv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_365)(GLenum target, GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_365)(GLenum target, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetMinmaxParameterfv, (target, pname, params), (F, "glGetMinmaxParameterfvEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(GetMinmaxParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetMinmaxParameteriv, (target, pname, params), (F, "glGetMinmaxParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+#ifndef GLX_INDIRECT_RENDERING
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_366)(GLenum target, GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_366)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetMinmaxParameteriv, (target, pname, params), (F, "glGetMinmaxParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+#endif /* GLX_INDIRECT_RENDERING */
+
+KEYWORD1 void KEYWORD2 NAME(Histogram)(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink)
+{
+ DISPATCH(Histogram, (target, width, internalformat, sink), (F, "glHistogram(0x%x, %d, 0x%x, %d);\n", target, width, internalformat, sink));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_367)(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_367)(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink)
+{
+ DISPATCH(Histogram, (target, width, internalformat, sink), (F, "glHistogramEXT(0x%x, %d, 0x%x, %d);\n", target, width, internalformat, sink));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Minmax)(GLenum target, GLenum internalformat, GLboolean sink)
+{
+ DISPATCH(Minmax, (target, internalformat, sink), (F, "glMinmax(0x%x, 0x%x, %d);\n", target, internalformat, sink));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_368)(GLenum target, GLenum internalformat, GLboolean sink);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_368)(GLenum target, GLenum internalformat, GLboolean sink)
+{
+ DISPATCH(Minmax, (target, internalformat, sink), (F, "glMinmaxEXT(0x%x, 0x%x, %d);\n", target, internalformat, sink));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ResetHistogram)(GLenum target)
+{
+ DISPATCH(ResetHistogram, (target), (F, "glResetHistogram(0x%x);\n", target));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_369)(GLenum target);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_369)(GLenum target)
+{
+ DISPATCH(ResetHistogram, (target), (F, "glResetHistogramEXT(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ResetMinmax)(GLenum target)
+{
+ DISPATCH(ResetMinmax, (target), (F, "glResetMinmax(0x%x);\n", target));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_370)(GLenum target);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_370)(GLenum target)
+{
+ DISPATCH(ResetMinmax, (target), (F, "glResetMinmaxEXT(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexImage3D, (target, level, internalformat, width, height, depth, border, format, type, pixels), (F, "glTexImage3D(0x%x, %d, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, internalformat, width, height, depth, border, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexImage3DEXT)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexImage3D, (target, level, internalformat, width, height, depth, border, format, type, pixels), (F, "glTexImage3DEXT(0x%x, %d, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, internalformat, width, height, depth, border, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage3D, (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), (F, "glTexSubImage3D(0x%x, %d, %d, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexSubImage3DEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid * pixels)
+{
+ DISPATCH(TexSubImage3D, (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), (F, "glTexSubImage3DEXT(0x%x, %d, %d, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p);\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, (const void *) pixels));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyTexSubImage3D, (target, level, xoffset, yoffset, zoffset, x, y, width, height), (F, "glCopyTexSubImage3D(0x%x, %d, %d, %d, %d, %d, %d, %d, %d);\n", target, level, xoffset, yoffset, zoffset, x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyTexSubImage3DEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ DISPATCH(CopyTexSubImage3D, (target, level, xoffset, yoffset, zoffset, x, y, width, height), (F, "glCopyTexSubImage3DEXT(0x%x, %d, %d, %d, %d, %d, %d, %d, %d);\n", target, level, xoffset, yoffset, zoffset, x, y, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ActiveTexture)(GLenum texture)
+{
+ DISPATCH(ActiveTextureARB, (texture), (F, "glActiveTexture(0x%x);\n", texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ActiveTextureARB)(GLenum texture)
+{
+ DISPATCH(ActiveTextureARB, (texture), (F, "glActiveTextureARB(0x%x);\n", texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClientActiveTexture)(GLenum texture)
+{
+ DISPATCH(ClientActiveTextureARB, (texture), (F, "glClientActiveTexture(0x%x);\n", texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ClientActiveTextureARB)(GLenum texture)
+{
+ DISPATCH(ClientActiveTextureARB, (texture), (F, "glClientActiveTextureARB(0x%x);\n", texture));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1d)(GLenum target, GLdouble s)
+{
+ DISPATCH(MultiTexCoord1dARB, (target, s), (F, "glMultiTexCoord1d(0x%x, %f);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1dARB)(GLenum target, GLdouble s)
+{
+ DISPATCH(MultiTexCoord1dARB, (target, s), (F, "glMultiTexCoord1dARB(0x%x, %f);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1dv)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord1dvARB, (target, v), (F, "glMultiTexCoord1dv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1dvARB)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord1dvARB, (target, v), (F, "glMultiTexCoord1dvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1f)(GLenum target, GLfloat s)
+{
+ DISPATCH(MultiTexCoord1fARB, (target, s), (F, "glMultiTexCoord1f(0x%x, %f);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1fARB)(GLenum target, GLfloat s)
+{
+ DISPATCH(MultiTexCoord1fARB, (target, s), (F, "glMultiTexCoord1fARB(0x%x, %f);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1fv)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord1fvARB, (target, v), (F, "glMultiTexCoord1fv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1fvARB)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord1fvARB, (target, v), (F, "glMultiTexCoord1fvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1i)(GLenum target, GLint s)
+{
+ DISPATCH(MultiTexCoord1iARB, (target, s), (F, "glMultiTexCoord1i(0x%x, %d);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1iARB)(GLenum target, GLint s)
+{
+ DISPATCH(MultiTexCoord1iARB, (target, s), (F, "glMultiTexCoord1iARB(0x%x, %d);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1iv)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord1ivARB, (target, v), (F, "glMultiTexCoord1iv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1ivARB)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord1ivARB, (target, v), (F, "glMultiTexCoord1ivARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1s)(GLenum target, GLshort s)
+{
+ DISPATCH(MultiTexCoord1sARB, (target, s), (F, "glMultiTexCoord1s(0x%x, %d);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1sARB)(GLenum target, GLshort s)
+{
+ DISPATCH(MultiTexCoord1sARB, (target, s), (F, "glMultiTexCoord1sARB(0x%x, %d);\n", target, s));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1sv)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord1svARB, (target, v), (F, "glMultiTexCoord1sv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord1svARB)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord1svARB, (target, v), (F, "glMultiTexCoord1svARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2d)(GLenum target, GLdouble s, GLdouble t)
+{
+ DISPATCH(MultiTexCoord2dARB, (target, s, t), (F, "glMultiTexCoord2d(0x%x, %f, %f);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2dARB)(GLenum target, GLdouble s, GLdouble t)
+{
+ DISPATCH(MultiTexCoord2dARB, (target, s, t), (F, "glMultiTexCoord2dARB(0x%x, %f, %f);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2dv)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord2dvARB, (target, v), (F, "glMultiTexCoord2dv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2dvARB)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord2dvARB, (target, v), (F, "glMultiTexCoord2dvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2f)(GLenum target, GLfloat s, GLfloat t)
+{
+ DISPATCH(MultiTexCoord2fARB, (target, s, t), (F, "glMultiTexCoord2f(0x%x, %f, %f);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2fARB)(GLenum target, GLfloat s, GLfloat t)
+{
+ DISPATCH(MultiTexCoord2fARB, (target, s, t), (F, "glMultiTexCoord2fARB(0x%x, %f, %f);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2fv)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord2fvARB, (target, v), (F, "glMultiTexCoord2fv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2fvARB)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord2fvARB, (target, v), (F, "glMultiTexCoord2fvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2i)(GLenum target, GLint s, GLint t)
+{
+ DISPATCH(MultiTexCoord2iARB, (target, s, t), (F, "glMultiTexCoord2i(0x%x, %d, %d);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2iARB)(GLenum target, GLint s, GLint t)
+{
+ DISPATCH(MultiTexCoord2iARB, (target, s, t), (F, "glMultiTexCoord2iARB(0x%x, %d, %d);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2iv)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord2ivARB, (target, v), (F, "glMultiTexCoord2iv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2ivARB)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord2ivARB, (target, v), (F, "glMultiTexCoord2ivARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2s)(GLenum target, GLshort s, GLshort t)
+{
+ DISPATCH(MultiTexCoord2sARB, (target, s, t), (F, "glMultiTexCoord2s(0x%x, %d, %d);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2sARB)(GLenum target, GLshort s, GLshort t)
+{
+ DISPATCH(MultiTexCoord2sARB, (target, s, t), (F, "glMultiTexCoord2sARB(0x%x, %d, %d);\n", target, s, t));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2sv)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord2svARB, (target, v), (F, "glMultiTexCoord2sv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord2svARB)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord2svARB, (target, v), (F, "glMultiTexCoord2svARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3d)(GLenum target, GLdouble s, GLdouble t, GLdouble r)
+{
+ DISPATCH(MultiTexCoord3dARB, (target, s, t, r), (F, "glMultiTexCoord3d(0x%x, %f, %f, %f);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3dARB)(GLenum target, GLdouble s, GLdouble t, GLdouble r)
+{
+ DISPATCH(MultiTexCoord3dARB, (target, s, t, r), (F, "glMultiTexCoord3dARB(0x%x, %f, %f, %f);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3dv)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord3dvARB, (target, v), (F, "glMultiTexCoord3dv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3dvARB)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord3dvARB, (target, v), (F, "glMultiTexCoord3dvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3f)(GLenum target, GLfloat s, GLfloat t, GLfloat r)
+{
+ DISPATCH(MultiTexCoord3fARB, (target, s, t, r), (F, "glMultiTexCoord3f(0x%x, %f, %f, %f);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r)
+{
+ DISPATCH(MultiTexCoord3fARB, (target, s, t, r), (F, "glMultiTexCoord3fARB(0x%x, %f, %f, %f);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3fv)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord3fvARB, (target, v), (F, "glMultiTexCoord3fv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3fvARB)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord3fvARB, (target, v), (F, "glMultiTexCoord3fvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3i)(GLenum target, GLint s, GLint t, GLint r)
+{
+ DISPATCH(MultiTexCoord3iARB, (target, s, t, r), (F, "glMultiTexCoord3i(0x%x, %d, %d, %d);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3iARB)(GLenum target, GLint s, GLint t, GLint r)
+{
+ DISPATCH(MultiTexCoord3iARB, (target, s, t, r), (F, "glMultiTexCoord3iARB(0x%x, %d, %d, %d);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3iv)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord3ivARB, (target, v), (F, "glMultiTexCoord3iv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3ivARB)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord3ivARB, (target, v), (F, "glMultiTexCoord3ivARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3s)(GLenum target, GLshort s, GLshort t, GLshort r)
+{
+ DISPATCH(MultiTexCoord3sARB, (target, s, t, r), (F, "glMultiTexCoord3s(0x%x, %d, %d, %d);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3sARB)(GLenum target, GLshort s, GLshort t, GLshort r)
+{
+ DISPATCH(MultiTexCoord3sARB, (target, s, t, r), (F, "glMultiTexCoord3sARB(0x%x, %d, %d, %d);\n", target, s, t, r));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3sv)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord3svARB, (target, v), (F, "glMultiTexCoord3sv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord3svARB)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord3svARB, (target, v), (F, "glMultiTexCoord3svARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4d)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ DISPATCH(MultiTexCoord4dARB, (target, s, t, r, q), (F, "glMultiTexCoord4d(0x%x, %f, %f, %f, %f);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4dARB)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ DISPATCH(MultiTexCoord4dARB, (target, s, t, r, q), (F, "glMultiTexCoord4dARB(0x%x, %f, %f, %f, %f);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4dv)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord4dvARB, (target, v), (F, "glMultiTexCoord4dv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4dvARB)(GLenum target, const GLdouble * v)
+{
+ DISPATCH(MultiTexCoord4dvARB, (target, v), (F, "glMultiTexCoord4dvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ DISPATCH(MultiTexCoord4fARB, (target, s, t, r, q), (F, "glMultiTexCoord4f(0x%x, %f, %f, %f, %f);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ DISPATCH(MultiTexCoord4fARB, (target, s, t, r, q), (F, "glMultiTexCoord4fARB(0x%x, %f, %f, %f, %f);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4fv)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord4fvARB, (target, v), (F, "glMultiTexCoord4fv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4fvARB)(GLenum target, const GLfloat * v)
+{
+ DISPATCH(MultiTexCoord4fvARB, (target, v), (F, "glMultiTexCoord4fvARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4i)(GLenum target, GLint s, GLint t, GLint r, GLint q)
+{
+ DISPATCH(MultiTexCoord4iARB, (target, s, t, r, q), (F, "glMultiTexCoord4i(0x%x, %d, %d, %d, %d);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4iARB)(GLenum target, GLint s, GLint t, GLint r, GLint q)
+{
+ DISPATCH(MultiTexCoord4iARB, (target, s, t, r, q), (F, "glMultiTexCoord4iARB(0x%x, %d, %d, %d, %d);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4iv)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord4ivARB, (target, v), (F, "glMultiTexCoord4iv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4ivARB)(GLenum target, const GLint * v)
+{
+ DISPATCH(MultiTexCoord4ivARB, (target, v), (F, "glMultiTexCoord4ivARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4s)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ DISPATCH(MultiTexCoord4sARB, (target, s, t, r, q), (F, "glMultiTexCoord4s(0x%x, %d, %d, %d, %d);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4sARB)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ DISPATCH(MultiTexCoord4sARB, (target, s, t, r, q), (F, "glMultiTexCoord4sARB(0x%x, %d, %d, %d, %d);\n", target, s, t, r, q));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4sv)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord4svARB, (target, v), (F, "glMultiTexCoord4sv(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiTexCoord4svARB)(GLenum target, const GLshort * v)
+{
+ DISPATCH(MultiTexCoord4svARB, (target, v), (F, "glMultiTexCoord4svARB(0x%x, %p);\n", target, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AttachShader)(GLuint program, GLuint shader)
+{
+ DISPATCH(AttachShader, (program, shader), (F, "glAttachShader(%d, %d);\n", program, shader));
+}
+
+KEYWORD1 GLuint KEYWORD2 NAME(CreateProgram)(void)
+{
+ RETURN_DISPATCH(CreateProgram, (), (F, "glCreateProgram();\n"));
+}
+
+KEYWORD1 GLuint KEYWORD2 NAME(CreateShader)(GLenum type)
+{
+ RETURN_DISPATCH(CreateShader, (type), (F, "glCreateShader(0x%x);\n", type));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteProgram)(GLuint program)
+{
+ DISPATCH(DeleteProgram, (program), (F, "glDeleteProgram(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteShader)(GLuint program)
+{
+ DISPATCH(DeleteShader, (program), (F, "glDeleteShader(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DetachShader)(GLuint program, GLuint shader)
+{
+ DISPATCH(DetachShader, (program, shader), (F, "glDetachShader(%d, %d);\n", program, shader));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * obj)
+{
+ DISPATCH(GetAttachedShaders, (program, maxCount, count, obj), (F, "glGetAttachedShaders(%d, %d, %p, %p);\n", program, maxCount, (const void *) count, (const void *) obj));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
+{
+ DISPATCH(GetProgramInfoLog, (program, bufSize, length, infoLog), (F, "glGetProgramInfoLog(%d, %d, %p, %p);\n", program, bufSize, (const void *) length, (const void *) infoLog));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramiv)(GLuint program, GLenum pname, GLint * params)
+{
+ DISPATCH(GetProgramiv, (program, pname, params), (F, "glGetProgramiv(%d, 0x%x, %p);\n", program, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
+{
+ DISPATCH(GetShaderInfoLog, (shader, bufSize, length, infoLog), (F, "glGetShaderInfoLog(%d, %d, %p, %p);\n", shader, bufSize, (const void *) length, (const void *) infoLog));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetShaderiv)(GLuint shader, GLenum pname, GLint * params)
+{
+ DISPATCH(GetShaderiv, (shader, pname, params), (F, "glGetShaderiv(%d, 0x%x, %p);\n", shader, pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsProgram)(GLuint program)
+{
+ RETURN_DISPATCH(IsProgram, (program), (F, "glIsProgram(%d);\n", program));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsShader)(GLuint shader)
+{
+ RETURN_DISPATCH(IsShader, (shader), (F, "glIsShader(%d);\n", shader));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ DISPATCH(StencilFuncSeparate, (face, func, ref, mask), (F, "glStencilFuncSeparate(0x%x, 0x%x, %d, %d);\n", face, func, ref, mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilMaskSeparate)(GLenum face, GLuint mask)
+{
+ DISPATCH(StencilMaskSeparate, (face, mask), (F, "glStencilMaskSeparate(0x%x, %d);\n", face, mask));
+}
+
+KEYWORD1 void KEYWORD2 NAME(StencilOpSeparate)(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
+{
+ DISPATCH(StencilOpSeparate, (face, sfail, zfail, zpass), (F, "glStencilOpSeparate(0x%x, 0x%x, 0x%x, 0x%x);\n", face, sfail, zfail, zpass));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_423)(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_423)(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
+{
+ DISPATCH(StencilOpSeparate, (face, sfail, zfail, zpass), (F, "glStencilOpSeparateATI(0x%x, 0x%x, 0x%x, 0x%x);\n", face, sfail, zfail, zpass));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix2x3fv, (location, count, transpose, value), (F, "glUniformMatrix2x3fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix2x4fv, (location, count, transpose, value), (F, "glUniformMatrix2x4fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix3x2fv, (location, count, transpose, value), (F, "glUniformMatrix3x2fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix3x4fv, (location, count, transpose, value), (F, "glUniformMatrix3x4fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix4x2fv, (location, count, transpose, value), (F, "glUniformMatrix4x2fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix4x3fv, (location, count, transpose, value), (F, "glUniformMatrix4x3fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadTransposeMatrixd)(const GLdouble * m)
+{
+ DISPATCH(LoadTransposeMatrixdARB, (m), (F, "glLoadTransposeMatrixd(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadTransposeMatrixdARB)(const GLdouble * m)
+{
+ DISPATCH(LoadTransposeMatrixdARB, (m), (F, "glLoadTransposeMatrixdARB(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadTransposeMatrixf)(const GLfloat * m)
+{
+ DISPATCH(LoadTransposeMatrixfARB, (m), (F, "glLoadTransposeMatrixf(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadTransposeMatrixfARB)(const GLfloat * m)
+{
+ DISPATCH(LoadTransposeMatrixfARB, (m), (F, "glLoadTransposeMatrixfARB(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultTransposeMatrixd)(const GLdouble * m)
+{
+ DISPATCH(MultTransposeMatrixdARB, (m), (F, "glMultTransposeMatrixd(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultTransposeMatrixdARB)(const GLdouble * m)
+{
+ DISPATCH(MultTransposeMatrixdARB, (m), (F, "glMultTransposeMatrixdARB(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultTransposeMatrixf)(const GLfloat * m)
+{
+ DISPATCH(MultTransposeMatrixfARB, (m), (F, "glMultTransposeMatrixf(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultTransposeMatrixfARB)(const GLfloat * m)
+{
+ DISPATCH(MultTransposeMatrixfARB, (m), (F, "glMultTransposeMatrixfARB(%p);\n", (const void *) m));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SampleCoverage)(GLclampf value, GLboolean invert)
+{
+ DISPATCH(SampleCoverageARB, (value, invert), (F, "glSampleCoverage(%f, %d);\n", value, invert));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SampleCoverageARB)(GLclampf value, GLboolean invert)
+{
+ DISPATCH(SampleCoverageARB, (value, invert), (F, "glSampleCoverageARB(%f, %d);\n", value, invert));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage1DARB, (target, level, internalformat, width, border, imageSize, data), (F, "glCompressedTexImage1D(0x%x, %d, 0x%x, %d, %d, %d, %p);\n", target, level, internalformat, width, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage1DARB, (target, level, internalformat, width, border, imageSize, data), (F, "glCompressedTexImage1DARB(0x%x, %d, 0x%x, %d, %d, %d, %p);\n", target, level, internalformat, width, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage2DARB, (target, level, internalformat, width, height, border, imageSize, data), (F, "glCompressedTexImage2D(0x%x, %d, 0x%x, %d, %d, %d, %d, %p);\n", target, level, internalformat, width, height, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage2DARB, (target, level, internalformat, width, height, border, imageSize, data), (F, "glCompressedTexImage2DARB(0x%x, %d, 0x%x, %d, %d, %d, %d, %p);\n", target, level, internalformat, width, height, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage3DARB, (target, level, internalformat, width, height, depth, border, imageSize, data), (F, "glCompressedTexImage3D(0x%x, %d, 0x%x, %d, %d, %d, %d, %d, %p);\n", target, level, internalformat, width, height, depth, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexImage3DARB, (target, level, internalformat, width, height, depth, border, imageSize, data), (F, "glCompressedTexImage3DARB(0x%x, %d, 0x%x, %d, %d, %d, %d, %d, %p);\n", target, level, internalformat, width, height, depth, border, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage1DARB, (target, level, xoffset, width, format, imageSize, data), (F, "glCompressedTexSubImage1D(0x%x, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, width, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage1DARB, (target, level, xoffset, width, format, imageSize, data), (F, "glCompressedTexSubImage1DARB(0x%x, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, width, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage2DARB, (target, level, xoffset, yoffset, width, height, format, imageSize, data), (F, "glCompressedTexSubImage2D(0x%x, %d, %d, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, yoffset, width, height, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage2DARB, (target, level, xoffset, yoffset, width, height, format, imageSize, data), (F, "glCompressedTexSubImage2DARB(0x%x, %d, %d, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, yoffset, width, height, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage3DARB, (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), (F, "glCompressedTexSubImage3D(0x%x, %d, %d, %d, %d, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid * data)
+{
+ DISPATCH(CompressedTexSubImage3DARB, (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), (F, "glCompressedTexSubImage3DARB(0x%x, %d, %d, %d, %d, %d, %d, %d, 0x%x, %d, %p);\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCompressedTexImage)(GLenum target, GLint level, GLvoid * img)
+{
+ DISPATCH(GetCompressedTexImageARB, (target, level, img), (F, "glGetCompressedTexImage(0x%x, %d, %p);\n", target, level, (const void *) img));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCompressedTexImageARB)(GLenum target, GLint level, GLvoid * img)
+{
+ DISPATCH(GetCompressedTexImageARB, (target, level, img), (F, "glGetCompressedTexImageARB(0x%x, %d, %p);\n", target, level, (const void *) img));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DisableVertexAttribArray)(GLuint index)
+{
+ DISPATCH(DisableVertexAttribArrayARB, (index), (F, "glDisableVertexAttribArray(%d);\n", index));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DisableVertexAttribArrayARB)(GLuint index)
+{
+ DISPATCH(DisableVertexAttribArrayARB, (index), (F, "glDisableVertexAttribArrayARB(%d);\n", index));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EnableVertexAttribArray)(GLuint index)
+{
+ DISPATCH(EnableVertexAttribArrayARB, (index), (F, "glEnableVertexAttribArray(%d);\n", index));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EnableVertexAttribArrayARB)(GLuint index)
+{
+ DISPATCH(EnableVertexAttribArrayARB, (index), (F, "glEnableVertexAttribArrayARB(%d);\n", index));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramEnvParameterdvARB)(GLenum target, GLuint index, GLdouble * params)
+{
+ DISPATCH(GetProgramEnvParameterdvARB, (target, index, params), (F, "glGetProgramEnvParameterdvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramEnvParameterfvARB)(GLenum target, GLuint index, GLfloat * params)
+{
+ DISPATCH(GetProgramEnvParameterfvARB, (target, index, params), (F, "glGetProgramEnvParameterfvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramLocalParameterdvARB)(GLenum target, GLuint index, GLdouble * params)
+{
+ DISPATCH(GetProgramLocalParameterdvARB, (target, index, params), (F, "glGetProgramLocalParameterdvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramLocalParameterfvARB)(GLenum target, GLuint index, GLfloat * params)
+{
+ DISPATCH(GetProgramLocalParameterfvARB, (target, index, params), (F, "glGetProgramLocalParameterfvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramStringARB)(GLenum target, GLenum pname, GLvoid * string)
+{
+ DISPATCH(GetProgramStringARB, (target, pname, string), (F, "glGetProgramStringARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) string));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramivARB)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetProgramivARB, (target, pname, params), (F, "glGetProgramivARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribdv)(GLuint index, GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetVertexAttribdvARB, (index, pname, params), (F, "glGetVertexAttribdv(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribdvARB)(GLuint index, GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetVertexAttribdvARB, (index, pname, params), (F, "glGetVertexAttribdvARB(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribfv)(GLuint index, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetVertexAttribfvARB, (index, pname, params), (F, "glGetVertexAttribfv(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribfvARB)(GLuint index, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetVertexAttribfvARB, (index, pname, params), (F, "glGetVertexAttribfvARB(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribiv)(GLuint index, GLenum pname, GLint * params)
+{
+ DISPATCH(GetVertexAttribivARB, (index, pname, params), (F, "glGetVertexAttribiv(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribivARB)(GLuint index, GLenum pname, GLint * params)
+{
+ DISPATCH(GetVertexAttribivARB, (index, pname, params), (F, "glGetVertexAttribivARB(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramEnvParameter4dARB)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(ProgramEnvParameter4dARB, (target, index, x, y, z, w), (F, "glProgramEnvParameter4dARB(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameter4dNV)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(ProgramEnvParameter4dARB, (target, index, x, y, z, w), (F, "glProgramParameter4dNV(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramEnvParameter4dvARB)(GLenum target, GLuint index, const GLdouble * params)
+{
+ DISPATCH(ProgramEnvParameter4dvARB, (target, index, params), (F, "glProgramEnvParameter4dvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameter4dvNV)(GLenum target, GLuint index, const GLdouble * params)
+{
+ DISPATCH(ProgramEnvParameter4dvARB, (target, index, params), (F, "glProgramParameter4dvNV(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramEnvParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(ProgramEnvParameter4fARB, (target, index, x, y, z, w), (F, "glProgramEnvParameter4fARB(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameter4fNV)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(ProgramEnvParameter4fARB, (target, index, x, y, z, w), (F, "glProgramParameter4fNV(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramEnvParameter4fvARB)(GLenum target, GLuint index, const GLfloat * params)
+{
+ DISPATCH(ProgramEnvParameter4fvARB, (target, index, params), (F, "glProgramEnvParameter4fvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameter4fvNV)(GLenum target, GLuint index, const GLfloat * params)
+{
+ DISPATCH(ProgramEnvParameter4fvARB, (target, index, params), (F, "glProgramParameter4fvNV(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramLocalParameter4dARB)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(ProgramLocalParameter4dARB, (target, index, x, y, z, w), (F, "glProgramLocalParameter4dARB(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramLocalParameter4dvARB)(GLenum target, GLuint index, const GLdouble * params)
+{
+ DISPATCH(ProgramLocalParameter4dvARB, (target, index, params), (F, "glProgramLocalParameter4dvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramLocalParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(ProgramLocalParameter4fARB, (target, index, x, y, z, w), (F, "glProgramLocalParameter4fARB(0x%x, %d, %f, %f, %f, %f);\n", target, index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramLocalParameter4fvARB)(GLenum target, GLuint index, const GLfloat * params)
+{
+ DISPATCH(ProgramLocalParameter4fvARB, (target, index, params), (F, "glProgramLocalParameter4fvARB(0x%x, %d, %p);\n", target, index, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramStringARB)(GLenum target, GLenum format, GLsizei len, const GLvoid * string)
+{
+ DISPATCH(ProgramStringARB, (target, format, len, string), (F, "glProgramStringARB(0x%x, 0x%x, %d, %p);\n", target, format, len, (const void *) string));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1d)(GLuint index, GLdouble x)
+{
+ DISPATCH(VertexAttrib1dARB, (index, x), (F, "glVertexAttrib1d(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1dARB)(GLuint index, GLdouble x)
+{
+ DISPATCH(VertexAttrib1dARB, (index, x), (F, "glVertexAttrib1dARB(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1dv)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib1dvARB, (index, v), (F, "glVertexAttrib1dv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1dvARB)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib1dvARB, (index, v), (F, "glVertexAttrib1dvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1f)(GLuint index, GLfloat x)
+{
+ DISPATCH(VertexAttrib1fARB, (index, x), (F, "glVertexAttrib1f(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1fARB)(GLuint index, GLfloat x)
+{
+ DISPATCH(VertexAttrib1fARB, (index, x), (F, "glVertexAttrib1fARB(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1fv)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib1fvARB, (index, v), (F, "glVertexAttrib1fv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1fvARB)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib1fvARB, (index, v), (F, "glVertexAttrib1fvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1s)(GLuint index, GLshort x)
+{
+ DISPATCH(VertexAttrib1sARB, (index, x), (F, "glVertexAttrib1s(%d, %d);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1sARB)(GLuint index, GLshort x)
+{
+ DISPATCH(VertexAttrib1sARB, (index, x), (F, "glVertexAttrib1sARB(%d, %d);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1sv)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib1svARB, (index, v), (F, "glVertexAttrib1sv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1svARB)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib1svARB, (index, v), (F, "glVertexAttrib1svARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2d)(GLuint index, GLdouble x, GLdouble y)
+{
+ DISPATCH(VertexAttrib2dARB, (index, x, y), (F, "glVertexAttrib2d(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2dARB)(GLuint index, GLdouble x, GLdouble y)
+{
+ DISPATCH(VertexAttrib2dARB, (index, x, y), (F, "glVertexAttrib2dARB(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2dv)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib2dvARB, (index, v), (F, "glVertexAttrib2dv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2dvARB)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib2dvARB, (index, v), (F, "glVertexAttrib2dvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2f)(GLuint index, GLfloat x, GLfloat y)
+{
+ DISPATCH(VertexAttrib2fARB, (index, x, y), (F, "glVertexAttrib2f(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2fARB)(GLuint index, GLfloat x, GLfloat y)
+{
+ DISPATCH(VertexAttrib2fARB, (index, x, y), (F, "glVertexAttrib2fARB(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2fv)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib2fvARB, (index, v), (F, "glVertexAttrib2fv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2fvARB)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib2fvARB, (index, v), (F, "glVertexAttrib2fvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2s)(GLuint index, GLshort x, GLshort y)
+{
+ DISPATCH(VertexAttrib2sARB, (index, x, y), (F, "glVertexAttrib2s(%d, %d, %d);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2sARB)(GLuint index, GLshort x, GLshort y)
+{
+ DISPATCH(VertexAttrib2sARB, (index, x, y), (F, "glVertexAttrib2sARB(%d, %d, %d);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2sv)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib2svARB, (index, v), (F, "glVertexAttrib2sv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2svARB)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib2svARB, (index, v), (F, "glVertexAttrib2svARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(VertexAttrib3dARB, (index, x, y, z), (F, "glVertexAttrib3d(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3dARB)(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(VertexAttrib3dARB, (index, x, y, z), (F, "glVertexAttrib3dARB(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3dv)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib3dvARB, (index, v), (F, "glVertexAttrib3dv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3dvARB)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib3dvARB, (index, v), (F, "glVertexAttrib3dvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(VertexAttrib3fARB, (index, x, y, z), (F, "glVertexAttrib3f(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(VertexAttrib3fARB, (index, x, y, z), (F, "glVertexAttrib3fARB(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3fv)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib3fvARB, (index, v), (F, "glVertexAttrib3fv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3fvARB)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib3fvARB, (index, v), (F, "glVertexAttrib3fvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3s)(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(VertexAttrib3sARB, (index, x, y, z), (F, "glVertexAttrib3s(%d, %d, %d, %d);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3sARB)(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(VertexAttrib3sARB, (index, x, y, z), (F, "glVertexAttrib3sARB(%d, %d, %d, %d);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3sv)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib3svARB, (index, v), (F, "glVertexAttrib3sv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3svARB)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib3svARB, (index, v), (F, "glVertexAttrib3svARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nbv)(GLuint index, const GLbyte * v)
+{
+ DISPATCH(VertexAttrib4NbvARB, (index, v), (F, "glVertexAttrib4Nbv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NbvARB)(GLuint index, const GLbyte * v)
+{
+ DISPATCH(VertexAttrib4NbvARB, (index, v), (F, "glVertexAttrib4NbvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Niv)(GLuint index, const GLint * v)
+{
+ DISPATCH(VertexAttrib4NivARB, (index, v), (F, "glVertexAttrib4Niv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NivARB)(GLuint index, const GLint * v)
+{
+ DISPATCH(VertexAttrib4NivARB, (index, v), (F, "glVertexAttrib4NivARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nsv)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib4NsvARB, (index, v), (F, "glVertexAttrib4Nsv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NsvARB)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib4NsvARB, (index, v), (F, "glVertexAttrib4NsvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nub)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ DISPATCH(VertexAttrib4NubARB, (index, x, y, z, w), (F, "glVertexAttrib4Nub(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NubARB)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ DISPATCH(VertexAttrib4NubARB, (index, x, y, z, w), (F, "glVertexAttrib4NubARB(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nubv)(GLuint index, const GLubyte * v)
+{
+ DISPATCH(VertexAttrib4NubvARB, (index, v), (F, "glVertexAttrib4Nubv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NubvARB)(GLuint index, const GLubyte * v)
+{
+ DISPATCH(VertexAttrib4NubvARB, (index, v), (F, "glVertexAttrib4NubvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nuiv)(GLuint index, const GLuint * v)
+{
+ DISPATCH(VertexAttrib4NuivARB, (index, v), (F, "glVertexAttrib4Nuiv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NuivARB)(GLuint index, const GLuint * v)
+{
+ DISPATCH(VertexAttrib4NuivARB, (index, v), (F, "glVertexAttrib4NuivARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4Nusv)(GLuint index, const GLushort * v)
+{
+ DISPATCH(VertexAttrib4NusvARB, (index, v), (F, "glVertexAttrib4Nusv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4NusvARB)(GLuint index, const GLushort * v)
+{
+ DISPATCH(VertexAttrib4NusvARB, (index, v), (F, "glVertexAttrib4NusvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4bv)(GLuint index, const GLbyte * v)
+{
+ DISPATCH(VertexAttrib4bvARB, (index, v), (F, "glVertexAttrib4bv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4bvARB)(GLuint index, const GLbyte * v)
+{
+ DISPATCH(VertexAttrib4bvARB, (index, v), (F, "glVertexAttrib4bvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(VertexAttrib4dARB, (index, x, y, z, w), (F, "glVertexAttrib4d(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4dARB)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(VertexAttrib4dARB, (index, x, y, z, w), (F, "glVertexAttrib4dARB(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4dv)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib4dvARB, (index, v), (F, "glVertexAttrib4dv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4dvARB)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib4dvARB, (index, v), (F, "glVertexAttrib4dvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(VertexAttrib4fARB, (index, x, y, z, w), (F, "glVertexAttrib4f(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(VertexAttrib4fARB, (index, x, y, z, w), (F, "glVertexAttrib4fARB(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4fv)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib4fvARB, (index, v), (F, "glVertexAttrib4fv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4fvARB)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib4fvARB, (index, v), (F, "glVertexAttrib4fvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4iv)(GLuint index, const GLint * v)
+{
+ DISPATCH(VertexAttrib4ivARB, (index, v), (F, "glVertexAttrib4iv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4ivARB)(GLuint index, const GLint * v)
+{
+ DISPATCH(VertexAttrib4ivARB, (index, v), (F, "glVertexAttrib4ivARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4s)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(VertexAttrib4sARB, (index, x, y, z, w), (F, "glVertexAttrib4s(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4sARB)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(VertexAttrib4sARB, (index, x, y, z, w), (F, "glVertexAttrib4sARB(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4sv)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib4svARB, (index, v), (F, "glVertexAttrib4sv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4svARB)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib4svARB, (index, v), (F, "glVertexAttrib4svARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4ubv)(GLuint index, const GLubyte * v)
+{
+ DISPATCH(VertexAttrib4ubvARB, (index, v), (F, "glVertexAttrib4ubv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4ubvARB)(GLuint index, const GLubyte * v)
+{
+ DISPATCH(VertexAttrib4ubvARB, (index, v), (F, "glVertexAttrib4ubvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4uiv)(GLuint index, const GLuint * v)
+{
+ DISPATCH(VertexAttrib4uivARB, (index, v), (F, "glVertexAttrib4uiv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4uivARB)(GLuint index, const GLuint * v)
+{
+ DISPATCH(VertexAttrib4uivARB, (index, v), (F, "glVertexAttrib4uivARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4usv)(GLuint index, const GLushort * v)
+{
+ DISPATCH(VertexAttrib4usvARB, (index, v), (F, "glVertexAttrib4usv(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4usvARB)(GLuint index, const GLushort * v)
+{
+ DISPATCH(VertexAttrib4usvARB, (index, v), (F, "glVertexAttrib4usvARB(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(VertexAttribPointerARB, (index, size, type, normalized, stride, pointer), (F, "glVertexAttribPointer(%d, %d, 0x%x, %d, %d, %p);\n", index, size, type, normalized, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribPointerARB)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(VertexAttribPointerARB, (index, size, type, normalized, stride, pointer), (F, "glVertexAttribPointerARB(%d, %d, 0x%x, %d, %d, %p);\n", index, size, type, normalized, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindBuffer)(GLenum target, GLuint buffer)
+{
+ DISPATCH(BindBufferARB, (target, buffer), (F, "glBindBuffer(0x%x, %d);\n", target, buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindBufferARB)(GLenum target, GLuint buffer)
+{
+ DISPATCH(BindBufferARB, (target, buffer), (F, "glBindBufferARB(0x%x, %d);\n", target, buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BufferData)(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage)
+{
+ DISPATCH(BufferDataARB, (target, size, data, usage), (F, "glBufferData(0x%x, %d, %p, 0x%x);\n", target, size, (const void *) data, usage));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BufferDataARB)(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage)
+{
+ DISPATCH(BufferDataARB, (target, size, data, usage), (F, "glBufferDataARB(0x%x, %d, %p, 0x%x);\n", target, size, (const void *) data, usage));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data)
+{
+ DISPATCH(BufferSubDataARB, (target, offset, size, data), (F, "glBufferSubData(0x%x, %d, %d, %p);\n", target, offset, size, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BufferSubDataARB)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data)
+{
+ DISPATCH(BufferSubDataARB, (target, offset, size, data), (F, "glBufferSubDataARB(0x%x, %d, %d, %p);\n", target, offset, size, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteBuffers)(GLsizei n, const GLuint * buffer)
+{
+ DISPATCH(DeleteBuffersARB, (n, buffer), (F, "glDeleteBuffers(%d, %p);\n", n, (const void *) buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteBuffersARB)(GLsizei n, const GLuint * buffer)
+{
+ DISPATCH(DeleteBuffersARB, (n, buffer), (F, "glDeleteBuffersARB(%d, %p);\n", n, (const void *) buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenBuffers)(GLsizei n, GLuint * buffer)
+{
+ DISPATCH(GenBuffersARB, (n, buffer), (F, "glGenBuffers(%d, %p);\n", n, (const void *) buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenBuffersARB)(GLsizei n, GLuint * buffer)
+{
+ DISPATCH(GenBuffersARB, (n, buffer), (F, "glGenBuffersARB(%d, %p);\n", n, (const void *) buffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetBufferParameterivARB, (target, pname, params), (F, "glGetBufferParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferParameterivARB)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetBufferParameterivARB, (target, pname, params), (F, "glGetBufferParameterivARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferPointerv)(GLenum target, GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetBufferPointervARB, (target, pname, params), (F, "glGetBufferPointerv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferPointervARB)(GLenum target, GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetBufferPointervARB, (target, pname, params), (F, "glGetBufferPointervARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data)
+{
+ DISPATCH(GetBufferSubDataARB, (target, offset, size, data), (F, "glGetBufferSubData(0x%x, %d, %d, %p);\n", target, offset, size, (const void *) data));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetBufferSubDataARB)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data)
+{
+ DISPATCH(GetBufferSubDataARB, (target, offset, size, data), (F, "glGetBufferSubDataARB(0x%x, %d, %d, %p);\n", target, offset, size, (const void *) data));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsBuffer)(GLuint buffer)
+{
+ RETURN_DISPATCH(IsBufferARB, (buffer), (F, "glIsBuffer(%d);\n", buffer));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsBufferARB)(GLuint buffer)
+{
+ RETURN_DISPATCH(IsBufferARB, (buffer), (F, "glIsBufferARB(%d);\n", buffer));
+}
+
+KEYWORD1 GLvoid * KEYWORD2 NAME(MapBuffer)(GLenum target, GLenum access)
+{
+ RETURN_DISPATCH(MapBufferARB, (target, access), (F, "glMapBuffer(0x%x, 0x%x);\n", target, access));
+}
+
+KEYWORD1 GLvoid * KEYWORD2 NAME(MapBufferARB)(GLenum target, GLenum access)
+{
+ RETURN_DISPATCH(MapBufferARB, (target, access), (F, "glMapBufferARB(0x%x, 0x%x);\n", target, access));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(UnmapBuffer)(GLenum target)
+{
+ RETURN_DISPATCH(UnmapBufferARB, (target), (F, "glUnmapBuffer(0x%x);\n", target));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(UnmapBufferARB)(GLenum target)
+{
+ RETURN_DISPATCH(UnmapBufferARB, (target), (F, "glUnmapBufferARB(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BeginQuery)(GLenum target, GLuint id)
+{
+ DISPATCH(BeginQueryARB, (target, id), (F, "glBeginQuery(0x%x, %d);\n", target, id));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BeginQueryARB)(GLenum target, GLuint id)
+{
+ DISPATCH(BeginQueryARB, (target, id), (F, "glBeginQueryARB(0x%x, %d);\n", target, id));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteQueries)(GLsizei n, const GLuint * ids)
+{
+ DISPATCH(DeleteQueriesARB, (n, ids), (F, "glDeleteQueries(%d, %p);\n", n, (const void *) ids));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteQueriesARB)(GLsizei n, const GLuint * ids)
+{
+ DISPATCH(DeleteQueriesARB, (n, ids), (F, "glDeleteQueriesARB(%d, %p);\n", n, (const void *) ids));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EndQuery)(GLenum target)
+{
+ DISPATCH(EndQueryARB, (target), (F, "glEndQuery(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EndQueryARB)(GLenum target)
+{
+ DISPATCH(EndQueryARB, (target), (F, "glEndQueryARB(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenQueries)(GLsizei n, GLuint * ids)
+{
+ DISPATCH(GenQueriesARB, (n, ids), (F, "glGenQueries(%d, %p);\n", n, (const void *) ids));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenQueriesARB)(GLsizei n, GLuint * ids)
+{
+ DISPATCH(GenQueriesARB, (n, ids), (F, "glGenQueriesARB(%d, %p);\n", n, (const void *) ids));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryObjectiv)(GLuint id, GLenum pname, GLint * params)
+{
+ DISPATCH(GetQueryObjectivARB, (id, pname, params), (F, "glGetQueryObjectiv(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryObjectivARB)(GLuint id, GLenum pname, GLint * params)
+{
+ DISPATCH(GetQueryObjectivARB, (id, pname, params), (F, "glGetQueryObjectivARB(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryObjectuiv)(GLuint id, GLenum pname, GLuint * params)
+{
+ DISPATCH(GetQueryObjectuivARB, (id, pname, params), (F, "glGetQueryObjectuiv(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint * params)
+{
+ DISPATCH(GetQueryObjectuivARB, (id, pname, params), (F, "glGetQueryObjectuivARB(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryiv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetQueryivARB, (target, pname, params), (F, "glGetQueryiv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetQueryivARB)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetQueryivARB, (target, pname, params), (F, "glGetQueryivARB(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsQuery)(GLuint id)
+{
+ RETURN_DISPATCH(IsQueryARB, (id), (F, "glIsQuery(%d);\n", id));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsQueryARB)(GLuint id)
+{
+ RETURN_DISPATCH(IsQueryARB, (id), (F, "glIsQueryARB(%d);\n", id));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AttachObjectARB)(GLhandleARB containerObj, GLhandleARB obj)
+{
+ DISPATCH(AttachObjectARB, (containerObj, obj), (F, "glAttachObjectARB(%d, %d);\n", containerObj, obj));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompileShader)(GLuint shader)
+{
+ DISPATCH(CompileShaderARB, (shader), (F, "glCompileShader(%d);\n", shader));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CompileShaderARB)(GLhandleARB shader)
+{
+ DISPATCH(CompileShaderARB, (shader), (F, "glCompileShaderARB(%d);\n", shader));
+}
+
+KEYWORD1 GLhandleARB KEYWORD2 NAME(CreateProgramObjectARB)(void)
+{
+ RETURN_DISPATCH(CreateProgramObjectARB, (), (F, "glCreateProgramObjectARB();\n"));
+}
+
+KEYWORD1 GLhandleARB KEYWORD2 NAME(CreateShaderObjectARB)(GLenum shaderType)
+{
+ RETURN_DISPATCH(CreateShaderObjectARB, (shaderType), (F, "glCreateShaderObjectARB(0x%x);\n", shaderType));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteObjectARB)(GLhandleARB obj)
+{
+ DISPATCH(DeleteObjectARB, (obj), (F, "glDeleteObjectARB(%d);\n", obj));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DetachObjectARB)(GLhandleARB containerObj, GLhandleARB attachedObj)
+{
+ DISPATCH(DetachObjectARB, (containerObj, attachedObj), (F, "glDetachObjectARB(%d, %d);\n", containerObj, attachedObj));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)
+{
+ DISPATCH(GetActiveUniformARB, (program, index, bufSize, length, size, type, name), (F, "glGetActiveUniform(%d, %d, %d, %p, %p, %p, %p);\n", program, index, bufSize, (const void *) length, (const void *) size, (const void *) type, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetActiveUniformARB)(GLhandleARB program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name)
+{
+ DISPATCH(GetActiveUniformARB, (program, index, bufSize, length, size, type, name), (F, "glGetActiveUniformARB(%d, %d, %d, %p, %p, %p, %p);\n", program, index, bufSize, (const void *) length, (const void *) size, (const void *) type, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetAttachedObjectsARB)(GLhandleARB containerObj, GLsizei maxLength, GLsizei * length, GLhandleARB * infoLog)
+{
+ DISPATCH(GetAttachedObjectsARB, (containerObj, maxLength, length, infoLog), (F, "glGetAttachedObjectsARB(%d, %d, %p, %p);\n", containerObj, maxLength, (const void *) length, (const void *) infoLog));
+}
+
+KEYWORD1 GLhandleARB KEYWORD2 NAME(GetHandleARB)(GLenum pname)
+{
+ RETURN_DISPATCH(GetHandleARB, (pname), (F, "glGetHandleARB(0x%x);\n", pname));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetInfoLogARB)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
+{
+ DISPATCH(GetInfoLogARB, (obj, maxLength, length, infoLog), (F, "glGetInfoLogARB(%d, %d, %p, %p);\n", obj, maxLength, (const void *) length, (const void *) infoLog));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetObjectParameterfvARB)(GLhandleARB obj, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetObjectParameterfvARB, (obj, pname, params), (F, "glGetObjectParameterfvARB(%d, 0x%x, %p);\n", obj, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetObjectParameterivARB)(GLhandleARB obj, GLenum pname, GLint * params)
+{
+ DISPATCH(GetObjectParameterivARB, (obj, pname, params), (F, "glGetObjectParameterivARB(%d, 0x%x, %p);\n", obj, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source)
+{
+ DISPATCH(GetShaderSourceARB, (shader, bufSize, length, source), (F, "glGetShaderSource(%d, %d, %p, %p);\n", shader, bufSize, (const void *) length, (const void *) source));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetShaderSourceARB)(GLhandleARB shader, GLsizei bufSize, GLsizei * length, GLcharARB * source)
+{
+ DISPATCH(GetShaderSourceARB, (shader, bufSize, length, source), (F, "glGetShaderSourceARB(%d, %d, %p, %p);\n", shader, bufSize, (const void *) length, (const void *) source));
+}
+
+KEYWORD1 GLint KEYWORD2 NAME(GetUniformLocation)(GLuint program, const GLchar * name)
+{
+ RETURN_DISPATCH(GetUniformLocationARB, (program, name), (F, "glGetUniformLocation(%d, %p);\n", program, (const void *) name));
+}
+
+KEYWORD1 GLint KEYWORD2 NAME(GetUniformLocationARB)(GLhandleARB program, const GLcharARB * name)
+{
+ RETURN_DISPATCH(GetUniformLocationARB, (program, name), (F, "glGetUniformLocationARB(%d, %p);\n", program, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetUniformfv)(GLuint program, GLint location, GLfloat * params)
+{
+ DISPATCH(GetUniformfvARB, (program, location, params), (F, "glGetUniformfv(%d, %d, %p);\n", program, location, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetUniformfvARB)(GLhandleARB program, GLint location, GLfloat * params)
+{
+ DISPATCH(GetUniformfvARB, (program, location, params), (F, "glGetUniformfvARB(%d, %d, %p);\n", program, location, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetUniformiv)(GLuint program, GLint location, GLint * params)
+{
+ DISPATCH(GetUniformivARB, (program, location, params), (F, "glGetUniformiv(%d, %d, %p);\n", program, location, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetUniformivARB)(GLhandleARB program, GLint location, GLint * params)
+{
+ DISPATCH(GetUniformivARB, (program, location, params), (F, "glGetUniformivARB(%d, %d, %p);\n", program, location, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LinkProgram)(GLuint program)
+{
+ DISPATCH(LinkProgramARB, (program), (F, "glLinkProgram(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LinkProgramARB)(GLhandleARB program)
+{
+ DISPATCH(LinkProgramARB, (program), (F, "glLinkProgramARB(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ShaderSource)(GLuint shader, GLsizei count, const GLchar ** string, const GLint * length)
+{
+ DISPATCH(ShaderSourceARB, (shader, count, string, length), (F, "glShaderSource(%d, %d, %p, %p);\n", shader, count, (const void *) string, (const void *) length));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ShaderSourceARB)(GLhandleARB shader, GLsizei count, const GLcharARB ** string, const GLint * length)
+{
+ DISPATCH(ShaderSourceARB, (shader, count, string, length), (F, "glShaderSourceARB(%d, %d, %p, %p);\n", shader, count, (const void *) string, (const void *) length));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1f)(GLint location, GLfloat v0)
+{
+ DISPATCH(Uniform1fARB, (location, v0), (F, "glUniform1f(%d, %f);\n", location, v0));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1fARB)(GLint location, GLfloat v0)
+{
+ DISPATCH(Uniform1fARB, (location, v0), (F, "glUniform1fARB(%d, %f);\n", location, v0));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1fv)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform1fvARB, (location, count, value), (F, "glUniform1fv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1fvARB)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform1fvARB, (location, count, value), (F, "glUniform1fvARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1i)(GLint location, GLint v0)
+{
+ DISPATCH(Uniform1iARB, (location, v0), (F, "glUniform1i(%d, %d);\n", location, v0));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1iARB)(GLint location, GLint v0)
+{
+ DISPATCH(Uniform1iARB, (location, v0), (F, "glUniform1iARB(%d, %d);\n", location, v0));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1iv)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform1ivARB, (location, count, value), (F, "glUniform1iv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform1ivARB)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform1ivARB, (location, count, value), (F, "glUniform1ivARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2f)(GLint location, GLfloat v0, GLfloat v1)
+{
+ DISPATCH(Uniform2fARB, (location, v0, v1), (F, "glUniform2f(%d, %f, %f);\n", location, v0, v1));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2fARB)(GLint location, GLfloat v0, GLfloat v1)
+{
+ DISPATCH(Uniform2fARB, (location, v0, v1), (F, "glUniform2fARB(%d, %f, %f);\n", location, v0, v1));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2fv)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform2fvARB, (location, count, value), (F, "glUniform2fv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2fvARB)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform2fvARB, (location, count, value), (F, "glUniform2fvARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2i)(GLint location, GLint v0, GLint v1)
+{
+ DISPATCH(Uniform2iARB, (location, v0, v1), (F, "glUniform2i(%d, %d, %d);\n", location, v0, v1));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2iARB)(GLint location, GLint v0, GLint v1)
+{
+ DISPATCH(Uniform2iARB, (location, v0, v1), (F, "glUniform2iARB(%d, %d, %d);\n", location, v0, v1));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2iv)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform2ivARB, (location, count, value), (F, "glUniform2iv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform2ivARB)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform2ivARB, (location, count, value), (F, "glUniform2ivARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ DISPATCH(Uniform3fARB, (location, v0, v1, v2), (F, "glUniform3f(%d, %f, %f, %f);\n", location, v0, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ DISPATCH(Uniform3fARB, (location, v0, v1, v2), (F, "glUniform3fARB(%d, %f, %f, %f);\n", location, v0, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3fv)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform3fvARB, (location, count, value), (F, "glUniform3fv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3fvARB)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform3fvARB, (location, count, value), (F, "glUniform3fvARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3i)(GLint location, GLint v0, GLint v1, GLint v2)
+{
+ DISPATCH(Uniform3iARB, (location, v0, v1, v2), (F, "glUniform3i(%d, %d, %d, %d);\n", location, v0, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3iARB)(GLint location, GLint v0, GLint v1, GLint v2)
+{
+ DISPATCH(Uniform3iARB, (location, v0, v1, v2), (F, "glUniform3iARB(%d, %d, %d, %d);\n", location, v0, v1, v2));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3iv)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform3ivARB, (location, count, value), (F, "glUniform3iv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform3ivARB)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform3ivARB, (location, count, value), (F, "glUniform3ivARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+ DISPATCH(Uniform4fARB, (location, v0, v1, v2, v3), (F, "glUniform4f(%d, %f, %f, %f, %f);\n", location, v0, v1, v2, v3));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+ DISPATCH(Uniform4fARB, (location, v0, v1, v2, v3), (F, "glUniform4fARB(%d, %f, %f, %f, %f);\n", location, v0, v1, v2, v3));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4fv)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform4fvARB, (location, count, value), (F, "glUniform4fv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4fvARB)(GLint location, GLsizei count, const GLfloat * value)
+{
+ DISPATCH(Uniform4fvARB, (location, count, value), (F, "glUniform4fvARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ DISPATCH(Uniform4iARB, (location, v0, v1, v2, v3), (F, "glUniform4i(%d, %d, %d, %d, %d);\n", location, v0, v1, v2, v3));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4iARB)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ DISPATCH(Uniform4iARB, (location, v0, v1, v2, v3), (F, "glUniform4iARB(%d, %d, %d, %d, %d);\n", location, v0, v1, v2, v3));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4iv)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform4ivARB, (location, count, value), (F, "glUniform4iv(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(Uniform4ivARB)(GLint location, GLsizei count, const GLint * value)
+{
+ DISPATCH(Uniform4ivARB, (location, count, value), (F, "glUniform4ivARB(%d, %d, %p);\n", location, count, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix2fvARB, (location, count, transpose, value), (F, "glUniformMatrix2fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix2fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix2fvARB, (location, count, transpose, value), (F, "glUniformMatrix2fvARB(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix3fvARB, (location, count, transpose, value), (F, "glUniformMatrix3fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix3fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix3fvARB, (location, count, transpose, value), (F, "glUniformMatrix3fvARB(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix4fvARB, (location, count, transpose, value), (F, "glUniformMatrix4fv(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UniformMatrix4fvARB)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+{
+ DISPATCH(UniformMatrix4fvARB, (location, count, transpose, value), (F, "glUniformMatrix4fvARB(%d, %d, %d, %p);\n", location, count, transpose, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UseProgram)(GLuint program)
+{
+ DISPATCH(UseProgramObjectARB, (program), (F, "glUseProgram(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UseProgramObjectARB)(GLhandleARB program)
+{
+ DISPATCH(UseProgramObjectARB, (program), (F, "glUseProgramObjectARB(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ValidateProgram)(GLuint program)
+{
+ DISPATCH(ValidateProgramARB, (program), (F, "glValidateProgram(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ValidateProgramARB)(GLhandleARB program)
+{
+ DISPATCH(ValidateProgramARB, (program), (F, "glValidateProgramARB(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindAttribLocation)(GLuint program, GLuint index, const GLchar * name)
+{
+ DISPATCH(BindAttribLocationARB, (program, index, name), (F, "glBindAttribLocation(%d, %d, %p);\n", program, index, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindAttribLocationARB)(GLhandleARB program, GLuint index, const GLcharARB * name)
+{
+ DISPATCH(BindAttribLocationARB, (program, index, name), (F, "glBindAttribLocationARB(%d, %d, %p);\n", program, index, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)
+{
+ DISPATCH(GetActiveAttribARB, (program, index, bufSize, length, size, type, name), (F, "glGetActiveAttrib(%d, %d, %d, %p, %p, %p, %p);\n", program, index, bufSize, (const void *) length, (const void *) size, (const void *) type, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetActiveAttribARB)(GLhandleARB program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name)
+{
+ DISPATCH(GetActiveAttribARB, (program, index, bufSize, length, size, type, name), (F, "glGetActiveAttribARB(%d, %d, %d, %p, %p, %p, %p);\n", program, index, bufSize, (const void *) length, (const void *) size, (const void *) type, (const void *) name));
+}
+
+KEYWORD1 GLint KEYWORD2 NAME(GetAttribLocation)(GLuint program, const GLchar * name)
+{
+ RETURN_DISPATCH(GetAttribLocationARB, (program, name), (F, "glGetAttribLocation(%d, %p);\n", program, (const void *) name));
+}
+
+KEYWORD1 GLint KEYWORD2 NAME(GetAttribLocationARB)(GLhandleARB program, const GLcharARB * name)
+{
+ RETURN_DISPATCH(GetAttribLocationARB, (program, name), (F, "glGetAttribLocationARB(%d, %p);\n", program, (const void *) name));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawBuffers)(GLsizei n, const GLenum * bufs)
+{
+ DISPATCH(DrawBuffersARB, (n, bufs), (F, "glDrawBuffers(%d, %p);\n", n, (const void *) bufs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawBuffersARB)(GLsizei n, const GLenum * bufs)
+{
+ DISPATCH(DrawBuffersARB, (n, bufs), (F, "glDrawBuffersARB(%d, %p);\n", n, (const void *) bufs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DrawBuffersATI)(GLsizei n, const GLenum * bufs)
+{
+ DISPATCH(DrawBuffersARB, (n, bufs), (F, "glDrawBuffersATI(%d, %p);\n", n, (const void *) bufs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ DISPATCH(RenderbufferStorageMultisample, (target, samples, internalformat, width, height), (F, "glRenderbufferStorageMultisample(0x%x, %d, 0x%x, %d, %d);\n", target, samples, internalformat, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ DISPATCH(FlushMappedBufferRange, (target, offset, length), (F, "glFlushMappedBufferRange(0x%x, %d, %d);\n", target, offset, length));
+}
+
+KEYWORD1 GLvoid * KEYWORD2 NAME(MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ RETURN_DISPATCH(MapBufferRange, (target, offset, length, access), (F, "glMapBufferRange(0x%x, %d, %d, %d);\n", target, offset, length, access));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindVertexArray)(GLuint array)
+{
+ DISPATCH(BindVertexArray, (array), (F, "glBindVertexArray(%d);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenVertexArrays)(GLsizei n, GLuint * arrays)
+{
+ DISPATCH(GenVertexArrays, (n, arrays), (F, "glGenVertexArrays(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+{
+ DISPATCH(CopyBufferSubData, (readTarget, writeTarget, readOffset, writeOffset, size), (F, "glCopyBufferSubData(0x%x, 0x%x, %d, %d, %d);\n", readTarget, writeTarget, readOffset, writeOffset, size));
+}
+
+KEYWORD1 GLenum KEYWORD2 NAME(ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ RETURN_DISPATCH(ClientWaitSync, (sync, flags, timeout), (F, "glClientWaitSync(%d, %d, %d);\n", sync, flags, timeout));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteSync)(GLsync sync)
+{
+ DISPATCH(DeleteSync, (sync), (F, "glDeleteSync(%d);\n", sync));
+}
+
+KEYWORD1 GLsync KEYWORD2 NAME(FenceSync)(GLenum condition, GLbitfield flags)
+{
+ RETURN_DISPATCH(FenceSync, (condition, flags), (F, "glFenceSync(0x%x, %d);\n", condition, flags));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetInteger64v)(GLenum pname, GLint64 * params)
+{
+ DISPATCH(GetInteger64v, (pname, params), (F, "glGetInteger64v(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)
+{
+ DISPATCH(GetSynciv, (sync, pname, bufSize, length, values), (F, "glGetSynciv(%d, 0x%x, %d, %p, %p);\n", sync, pname, bufSize, (const void *) length, (const void *) values));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsSync)(GLsync sync)
+{
+ RETURN_DISPATCH(IsSync, (sync), (F, "glIsSync(%d);\n", sync));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ DISPATCH(WaitSync, (sync, flags, timeout), (F, "glWaitSync(%d, %d, %d);\n", sync, flags, timeout));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PolygonOffsetEXT)(GLfloat factor, GLfloat bias)
+{
+ DISPATCH(PolygonOffsetEXT, (factor, bias), (F, "glPolygonOffsetEXT(%f, %f);\n", factor, bias));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_575)(GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_575)(GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetPixelTexGenParameterfvSGIS, (pname, params), (F, "glGetPixelTexGenParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_576)(GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_576)(GLenum pname, GLint * params)
+{
+ DISPATCH(GetPixelTexGenParameterivSGIS, (pname, params), (F, "glGetPixelTexGenParameterivSGIS(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_577)(GLenum pname, GLfloat param);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_577)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PixelTexGenParameterfSGIS, (pname, param), (F, "glPixelTexGenParameterfSGIS(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_578)(GLenum pname, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_578)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(PixelTexGenParameterfvSGIS, (pname, params), (F, "glPixelTexGenParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_579)(GLenum pname, GLint param);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_579)(GLenum pname, GLint param)
+{
+ DISPATCH(PixelTexGenParameteriSGIS, (pname, param), (F, "glPixelTexGenParameteriSGIS(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, const GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_580)(GLenum pname, const GLint * params)
+{
+ DISPATCH(PixelTexGenParameterivSGIS, (pname, params), (F, "glPixelTexGenParameterivSGIS(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLclampf value, GLboolean invert);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_581)(GLclampf value, GLboolean invert)
+{
+ DISPATCH(SampleMaskSGIS, (value, invert), (F, "glSampleMaskSGIS(%f, %d);\n", value, invert));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_582)(GLenum pattern);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_582)(GLenum pattern)
+{
+ DISPATCH(SamplePatternSGIS, (pattern), (F, "glSamplePatternSGIS(0x%x);\n", pattern));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer)
+{
+ DISPATCH(ColorPointerEXT, (size, type, stride, count, pointer), (F, "glColorPointerEXT(%d, 0x%x, %d, %d, %p);\n", size, type, stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EdgeFlagPointerEXT)(GLsizei stride, GLsizei count, const GLboolean * pointer)
+{
+ DISPATCH(EdgeFlagPointerEXT, (stride, count, pointer), (F, "glEdgeFlagPointerEXT(%d, %d, %p);\n", stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(IndexPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer)
+{
+ DISPATCH(IndexPointerEXT, (type, stride, count, pointer), (F, "glIndexPointerEXT(0x%x, %d, %d, %p);\n", type, stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(NormalPointerEXT)(GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer)
+{
+ DISPATCH(NormalPointerEXT, (type, stride, count, pointer), (F, "glNormalPointerEXT(0x%x, %d, %d, %p);\n", type, stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexCoordPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer)
+{
+ DISPATCH(TexCoordPointerEXT, (size, type, stride, count, pointer), (F, "glTexCoordPointerEXT(%d, 0x%x, %d, %d, %p);\n", size, type, stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexPointerEXT)(GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid * pointer)
+{
+ DISPATCH(VertexPointerEXT, (size, type, stride, count, pointer), (F, "glVertexPointerEXT(%d, 0x%x, %d, %d, %p);\n", size, type, stride, count, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterf)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterf(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterfARB)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterfARB(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterfEXT)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterfEXT(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_589)(GLenum pname, GLfloat param);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_589)(GLenum pname, GLfloat param)
+{
+ DISPATCH(PointParameterfEXT, (pname, param), (F, "glPointParameterfSGIS(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterfv)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterfvARB)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfvARB(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterfvEXT)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfvEXT(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_590)(GLenum pname, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_590)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(PointParameterfvEXT, (pname, params), (F, "glPointParameterfvSGIS(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LockArraysEXT)(GLint first, GLsizei count)
+{
+ DISPATCH(LockArraysEXT, (first, count), (F, "glLockArraysEXT(%d, %d);\n", first, count));
+}
+
+KEYWORD1 void KEYWORD2 NAME(UnlockArraysEXT)(void)
+{
+ DISPATCH(UnlockArraysEXT, (), (F, "glUnlockArraysEXT();\n"));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_593)(GLenum pname, GLdouble * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_593)(GLenum pname, GLdouble * params)
+{
+ DISPATCH(CullParameterdvEXT, (pname, params), (F, "glCullParameterdvEXT(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_594)(GLenum pname, GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_594)(GLenum pname, GLfloat * params)
+{
+ DISPATCH(CullParameterfvEXT, (pname, params), (F, "glCullParameterfvEXT(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3b)(GLbyte red, GLbyte green, GLbyte blue)
+{
+ DISPATCH(SecondaryColor3bEXT, (red, green, blue), (F, "glSecondaryColor3b(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3bEXT)(GLbyte red, GLbyte green, GLbyte blue)
+{
+ DISPATCH(SecondaryColor3bEXT, (red, green, blue), (F, "glSecondaryColor3bEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3bv)(const GLbyte * v)
+{
+ DISPATCH(SecondaryColor3bvEXT, (v), (F, "glSecondaryColor3bv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3bvEXT)(const GLbyte * v)
+{
+ DISPATCH(SecondaryColor3bvEXT, (v), (F, "glSecondaryColor3bvEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3d)(GLdouble red, GLdouble green, GLdouble blue)
+{
+ DISPATCH(SecondaryColor3dEXT, (red, green, blue), (F, "glSecondaryColor3d(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3dEXT)(GLdouble red, GLdouble green, GLdouble blue)
+{
+ DISPATCH(SecondaryColor3dEXT, (red, green, blue), (F, "glSecondaryColor3dEXT(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3dv)(const GLdouble * v)
+{
+ DISPATCH(SecondaryColor3dvEXT, (v), (F, "glSecondaryColor3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3dvEXT)(const GLdouble * v)
+{
+ DISPATCH(SecondaryColor3dvEXT, (v), (F, "glSecondaryColor3dvEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3f)(GLfloat red, GLfloat green, GLfloat blue)
+{
+ DISPATCH(SecondaryColor3fEXT, (red, green, blue), (F, "glSecondaryColor3f(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3fEXT)(GLfloat red, GLfloat green, GLfloat blue)
+{
+ DISPATCH(SecondaryColor3fEXT, (red, green, blue), (F, "glSecondaryColor3fEXT(%f, %f, %f);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3fv)(const GLfloat * v)
+{
+ DISPATCH(SecondaryColor3fvEXT, (v), (F, "glSecondaryColor3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3fvEXT)(const GLfloat * v)
+{
+ DISPATCH(SecondaryColor3fvEXT, (v), (F, "glSecondaryColor3fvEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3i)(GLint red, GLint green, GLint blue)
+{
+ DISPATCH(SecondaryColor3iEXT, (red, green, blue), (F, "glSecondaryColor3i(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3iEXT)(GLint red, GLint green, GLint blue)
+{
+ DISPATCH(SecondaryColor3iEXT, (red, green, blue), (F, "glSecondaryColor3iEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3iv)(const GLint * v)
+{
+ DISPATCH(SecondaryColor3ivEXT, (v), (F, "glSecondaryColor3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ivEXT)(const GLint * v)
+{
+ DISPATCH(SecondaryColor3ivEXT, (v), (F, "glSecondaryColor3ivEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3s)(GLshort red, GLshort green, GLshort blue)
+{
+ DISPATCH(SecondaryColor3sEXT, (red, green, blue), (F, "glSecondaryColor3s(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3sEXT)(GLshort red, GLshort green, GLshort blue)
+{
+ DISPATCH(SecondaryColor3sEXT, (red, green, blue), (F, "glSecondaryColor3sEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3sv)(const GLshort * v)
+{
+ DISPATCH(SecondaryColor3svEXT, (v), (F, "glSecondaryColor3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3svEXT)(const GLshort * v)
+{
+ DISPATCH(SecondaryColor3svEXT, (v), (F, "glSecondaryColor3svEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ub)(GLubyte red, GLubyte green, GLubyte blue)
+{
+ DISPATCH(SecondaryColor3ubEXT, (red, green, blue), (F, "glSecondaryColor3ub(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ubEXT)(GLubyte red, GLubyte green, GLubyte blue)
+{
+ DISPATCH(SecondaryColor3ubEXT, (red, green, blue), (F, "glSecondaryColor3ubEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ubv)(const GLubyte * v)
+{
+ DISPATCH(SecondaryColor3ubvEXT, (v), (F, "glSecondaryColor3ubv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ubvEXT)(const GLubyte * v)
+{
+ DISPATCH(SecondaryColor3ubvEXT, (v), (F, "glSecondaryColor3ubvEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3ui)(GLuint red, GLuint green, GLuint blue)
+{
+ DISPATCH(SecondaryColor3uiEXT, (red, green, blue), (F, "glSecondaryColor3ui(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3uiEXT)(GLuint red, GLuint green, GLuint blue)
+{
+ DISPATCH(SecondaryColor3uiEXT, (red, green, blue), (F, "glSecondaryColor3uiEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3uiv)(const GLuint * v)
+{
+ DISPATCH(SecondaryColor3uivEXT, (v), (F, "glSecondaryColor3uiv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3uivEXT)(const GLuint * v)
+{
+ DISPATCH(SecondaryColor3uivEXT, (v), (F, "glSecondaryColor3uivEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3us)(GLushort red, GLushort green, GLushort blue)
+{
+ DISPATCH(SecondaryColor3usEXT, (red, green, blue), (F, "glSecondaryColor3us(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3usEXT)(GLushort red, GLushort green, GLushort blue)
+{
+ DISPATCH(SecondaryColor3usEXT, (red, green, blue), (F, "glSecondaryColor3usEXT(%d, %d, %d);\n", red, green, blue));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3usv)(const GLushort * v)
+{
+ DISPATCH(SecondaryColor3usvEXT, (v), (F, "glSecondaryColor3usv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColor3usvEXT)(const GLushort * v)
+{
+ DISPATCH(SecondaryColor3usvEXT, (v), (F, "glSecondaryColor3usvEXT(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(SecondaryColorPointerEXT, (size, type, stride, pointer), (F, "glSecondaryColorPointer(%d, 0x%x, %d, %p);\n", size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SecondaryColorPointerEXT)(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(SecondaryColorPointerEXT, (size, type, stride, pointer), (F, "glSecondaryColorPointerEXT(%d, 0x%x, %d, %p);\n", size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiDrawArrays)(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount)
+{
+ DISPATCH(MultiDrawArraysEXT, (mode, first, count, primcount), (F, "glMultiDrawArrays(0x%x, %p, %p, %d);\n", mode, (const void *) first, (const void *) count, primcount));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiDrawArraysEXT)(GLenum mode, GLint * first, GLsizei * count, GLsizei primcount)
+{
+ DISPATCH(MultiDrawArraysEXT, (mode, first, count, primcount), (F, "glMultiDrawArraysEXT(0x%x, %p, %p, %d);\n", mode, (const void *) first, (const void *) count, primcount));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiDrawElements)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount)
+{
+ DISPATCH(MultiDrawElementsEXT, (mode, count, type, indices, primcount), (F, "glMultiDrawElements(0x%x, %p, 0x%x, %p, %d);\n", mode, (const void *) count, type, (const void *) indices, primcount));
+}
+
+KEYWORD1 void KEYWORD2 NAME(MultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount)
+{
+ DISPATCH(MultiDrawElementsEXT, (mode, count, type, indices, primcount), (F, "glMultiDrawElementsEXT(0x%x, %p, 0x%x, %p, %d);\n", mode, (const void *) count, type, (const void *) indices, primcount));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordPointer)(GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(FogCoordPointerEXT, (type, stride, pointer), (F, "glFogCoordPointer(0x%x, %d, %p);\n", type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordPointerEXT)(GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(FogCoordPointerEXT, (type, stride, pointer), (F, "glFogCoordPointerEXT(0x%x, %d, %p);\n", type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordd)(GLdouble coord)
+{
+ DISPATCH(FogCoorddEXT, (coord), (F, "glFogCoordd(%f);\n", coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoorddEXT)(GLdouble coord)
+{
+ DISPATCH(FogCoorddEXT, (coord), (F, "glFogCoorddEXT(%f);\n", coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoorddv)(const GLdouble * coord)
+{
+ DISPATCH(FogCoorddvEXT, (coord), (F, "glFogCoorddv(%p);\n", (const void *) coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoorddvEXT)(const GLdouble * coord)
+{
+ DISPATCH(FogCoorddvEXT, (coord), (F, "glFogCoorddvEXT(%p);\n", (const void *) coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordf)(GLfloat coord)
+{
+ DISPATCH(FogCoordfEXT, (coord), (F, "glFogCoordf(%f);\n", coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordfEXT)(GLfloat coord)
+{
+ DISPATCH(FogCoordfEXT, (coord), (F, "glFogCoordfEXT(%f);\n", coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordfv)(const GLfloat * coord)
+{
+ DISPATCH(FogCoordfvEXT, (coord), (F, "glFogCoordfv(%p);\n", (const void *) coord));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FogCoordfvEXT)(const GLfloat * coord)
+{
+ DISPATCH(FogCoordfvEXT, (coord), (F, "glFogCoordfvEXT(%p);\n", (const void *) coord));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_619)(GLenum mode);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_619)(GLenum mode)
+{
+ DISPATCH(PixelTexGenSGIX, (mode), (F, "glPixelTexGenSGIX(0x%x);\n", mode));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
+{
+ DISPATCH(BlendFuncSeparateEXT, (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), (F, "glBlendFuncSeparate(0x%x, 0x%x, 0x%x, 0x%x);\n", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendFuncSeparateEXT)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
+{
+ DISPATCH(BlendFuncSeparateEXT, (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), (F, "glBlendFuncSeparateEXT(0x%x, 0x%x, 0x%x, 0x%x);\n", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_620)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_620)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
+{
+ DISPATCH(BlendFuncSeparateEXT, (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), (F, "glBlendFuncSeparateINGR(0x%x, 0x%x, 0x%x, 0x%x);\n", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FlushVertexArrayRangeNV)(void)
+{
+ DISPATCH(FlushVertexArrayRangeNV, (), (F, "glFlushVertexArrayRangeNV();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexArrayRangeNV)(GLsizei length, const GLvoid * pointer)
+{
+ DISPATCH(VertexArrayRangeNV, (length, pointer), (F, "glVertexArrayRangeNV(%d, %p);\n", length, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerInputNV)(GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage)
+{
+ DISPATCH(CombinerInputNV, (stage, portion, variable, input, mapping, componentUsage), (F, "glCombinerInputNV(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x);\n", stage, portion, variable, input, mapping, componentUsage));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerOutputNV)(GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum)
+{
+ DISPATCH(CombinerOutputNV, (stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum), (F, "glCombinerOutputNV(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, %d, %d, %d);\n", stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerParameterfNV)(GLenum pname, GLfloat param)
+{
+ DISPATCH(CombinerParameterfNV, (pname, param), (F, "glCombinerParameterfNV(0x%x, %f);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerParameterfvNV)(GLenum pname, const GLfloat * params)
+{
+ DISPATCH(CombinerParameterfvNV, (pname, params), (F, "glCombinerParameterfvNV(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerParameteriNV)(GLenum pname, GLint param)
+{
+ DISPATCH(CombinerParameteriNV, (pname, param), (F, "glCombinerParameteriNV(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(CombinerParameterivNV)(GLenum pname, const GLint * params)
+{
+ DISPATCH(CombinerParameterivNV, (pname, params), (F, "glCombinerParameterivNV(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FinalCombinerInputNV)(GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage)
+{
+ DISPATCH(FinalCombinerInputNV, (variable, input, mapping, componentUsage), (F, "glFinalCombinerInputNV(0x%x, 0x%x, 0x%x, 0x%x);\n", variable, input, mapping, componentUsage));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCombinerInputParameterfvNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetCombinerInputParameterfvNV, (stage, portion, variable, pname, params), (F, "glGetCombinerInputParameterfvNV(0x%x, 0x%x, 0x%x, 0x%x, %p);\n", stage, portion, variable, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCombinerInputParameterivNV)(GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint * params)
+{
+ DISPATCH(GetCombinerInputParameterivNV, (stage, portion, variable, pname, params), (F, "glGetCombinerInputParameterivNV(0x%x, 0x%x, 0x%x, 0x%x, %p);\n", stage, portion, variable, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCombinerOutputParameterfvNV)(GLenum stage, GLenum portion, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetCombinerOutputParameterfvNV, (stage, portion, pname, params), (F, "glGetCombinerOutputParameterfvNV(0x%x, 0x%x, 0x%x, %p);\n", stage, portion, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetCombinerOutputParameterivNV)(GLenum stage, GLenum portion, GLenum pname, GLint * params)
+{
+ DISPATCH(GetCombinerOutputParameterivNV, (stage, portion, pname, params), (F, "glGetCombinerOutputParameterivNV(0x%x, 0x%x, 0x%x, %p);\n", stage, portion, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetFinalCombinerInputParameterfvNV)(GLenum variable, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetFinalCombinerInputParameterfvNV, (variable, pname, params), (F, "glGetFinalCombinerInputParameterfvNV(0x%x, 0x%x, %p);\n", variable, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetFinalCombinerInputParameterivNV)(GLenum variable, GLenum pname, GLint * params)
+{
+ DISPATCH(GetFinalCombinerInputParameterivNV, (variable, pname, params), (F, "glGetFinalCombinerInputParameterivNV(0x%x, 0x%x, %p);\n", variable, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ResizeBuffersMESA)(void)
+{
+ DISPATCH(ResizeBuffersMESA, (), (F, "glResizeBuffersMESA();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2d)(GLdouble x, GLdouble y)
+{
+ DISPATCH(WindowPos2dMESA, (x, y), (F, "glWindowPos2d(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2dARB)(GLdouble x, GLdouble y)
+{
+ DISPATCH(WindowPos2dMESA, (x, y), (F, "glWindowPos2dARB(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2dMESA)(GLdouble x, GLdouble y)
+{
+ DISPATCH(WindowPos2dMESA, (x, y), (F, "glWindowPos2dMESA(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2dv)(const GLdouble * v)
+{
+ DISPATCH(WindowPos2dvMESA, (v), (F, "glWindowPos2dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2dvARB)(const GLdouble * v)
+{
+ DISPATCH(WindowPos2dvMESA, (v), (F, "glWindowPos2dvARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2dvMESA)(const GLdouble * v)
+{
+ DISPATCH(WindowPos2dvMESA, (v), (F, "glWindowPos2dvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2f)(GLfloat x, GLfloat y)
+{
+ DISPATCH(WindowPos2fMESA, (x, y), (F, "glWindowPos2f(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2fARB)(GLfloat x, GLfloat y)
+{
+ DISPATCH(WindowPos2fMESA, (x, y), (F, "glWindowPos2fARB(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2fMESA)(GLfloat x, GLfloat y)
+{
+ DISPATCH(WindowPos2fMESA, (x, y), (F, "glWindowPos2fMESA(%f, %f);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2fv)(const GLfloat * v)
+{
+ DISPATCH(WindowPos2fvMESA, (v), (F, "glWindowPos2fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2fvARB)(const GLfloat * v)
+{
+ DISPATCH(WindowPos2fvMESA, (v), (F, "glWindowPos2fvARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2fvMESA)(const GLfloat * v)
+{
+ DISPATCH(WindowPos2fvMESA, (v), (F, "glWindowPos2fvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2i)(GLint x, GLint y)
+{
+ DISPATCH(WindowPos2iMESA, (x, y), (F, "glWindowPos2i(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2iARB)(GLint x, GLint y)
+{
+ DISPATCH(WindowPos2iMESA, (x, y), (F, "glWindowPos2iARB(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2iMESA)(GLint x, GLint y)
+{
+ DISPATCH(WindowPos2iMESA, (x, y), (F, "glWindowPos2iMESA(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2iv)(const GLint * v)
+{
+ DISPATCH(WindowPos2ivMESA, (v), (F, "glWindowPos2iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2ivARB)(const GLint * v)
+{
+ DISPATCH(WindowPos2ivMESA, (v), (F, "glWindowPos2ivARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2ivMESA)(const GLint * v)
+{
+ DISPATCH(WindowPos2ivMESA, (v), (F, "glWindowPos2ivMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2s)(GLshort x, GLshort y)
+{
+ DISPATCH(WindowPos2sMESA, (x, y), (F, "glWindowPos2s(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2sARB)(GLshort x, GLshort y)
+{
+ DISPATCH(WindowPos2sMESA, (x, y), (F, "glWindowPos2sARB(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2sMESA)(GLshort x, GLshort y)
+{
+ DISPATCH(WindowPos2sMESA, (x, y), (F, "glWindowPos2sMESA(%d, %d);\n", x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2sv)(const GLshort * v)
+{
+ DISPATCH(WindowPos2svMESA, (v), (F, "glWindowPos2sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2svARB)(const GLshort * v)
+{
+ DISPATCH(WindowPos2svMESA, (v), (F, "glWindowPos2svARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos2svMESA)(const GLshort * v)
+{
+ DISPATCH(WindowPos2svMESA, (v), (F, "glWindowPos2svMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3d)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(WindowPos3dMESA, (x, y, z), (F, "glWindowPos3d(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3dARB)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(WindowPos3dMESA, (x, y, z), (F, "glWindowPos3dARB(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3dMESA)(GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(WindowPos3dMESA, (x, y, z), (F, "glWindowPos3dMESA(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3dv)(const GLdouble * v)
+{
+ DISPATCH(WindowPos3dvMESA, (v), (F, "glWindowPos3dv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3dvARB)(const GLdouble * v)
+{
+ DISPATCH(WindowPos3dvMESA, (v), (F, "glWindowPos3dvARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3dvMESA)(const GLdouble * v)
+{
+ DISPATCH(WindowPos3dvMESA, (v), (F, "glWindowPos3dvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3f)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(WindowPos3fMESA, (x, y, z), (F, "glWindowPos3f(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3fARB)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(WindowPos3fMESA, (x, y, z), (F, "glWindowPos3fARB(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3fMESA)(GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(WindowPos3fMESA, (x, y, z), (F, "glWindowPos3fMESA(%f, %f, %f);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3fv)(const GLfloat * v)
+{
+ DISPATCH(WindowPos3fvMESA, (v), (F, "glWindowPos3fv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3fvARB)(const GLfloat * v)
+{
+ DISPATCH(WindowPos3fvMESA, (v), (F, "glWindowPos3fvARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3fvMESA)(const GLfloat * v)
+{
+ DISPATCH(WindowPos3fvMESA, (v), (F, "glWindowPos3fvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3i)(GLint x, GLint y, GLint z)
+{
+ DISPATCH(WindowPos3iMESA, (x, y, z), (F, "glWindowPos3i(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3iARB)(GLint x, GLint y, GLint z)
+{
+ DISPATCH(WindowPos3iMESA, (x, y, z), (F, "glWindowPos3iARB(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3iMESA)(GLint x, GLint y, GLint z)
+{
+ DISPATCH(WindowPos3iMESA, (x, y, z), (F, "glWindowPos3iMESA(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3iv)(const GLint * v)
+{
+ DISPATCH(WindowPos3ivMESA, (v), (F, "glWindowPos3iv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3ivARB)(const GLint * v)
+{
+ DISPATCH(WindowPos3ivMESA, (v), (F, "glWindowPos3ivARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3ivMESA)(const GLint * v)
+{
+ DISPATCH(WindowPos3ivMESA, (v), (F, "glWindowPos3ivMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3s)(GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(WindowPos3sMESA, (x, y, z), (F, "glWindowPos3s(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3sARB)(GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(WindowPos3sMESA, (x, y, z), (F, "glWindowPos3sARB(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3sMESA)(GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(WindowPos3sMESA, (x, y, z), (F, "glWindowPos3sMESA(%d, %d, %d);\n", x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3sv)(const GLshort * v)
+{
+ DISPATCH(WindowPos3svMESA, (v), (F, "glWindowPos3sv(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3svARB)(const GLshort * v)
+{
+ DISPATCH(WindowPos3svMESA, (v), (F, "glWindowPos3svARB(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos3svMESA)(const GLshort * v)
+{
+ DISPATCH(WindowPos3svMESA, (v), (F, "glWindowPos3svMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4dMESA)(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(WindowPos4dMESA, (x, y, z, w), (F, "glWindowPos4dMESA(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4dvMESA)(const GLdouble * v)
+{
+ DISPATCH(WindowPos4dvMESA, (v), (F, "glWindowPos4dvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4fMESA)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(WindowPos4fMESA, (x, y, z, w), (F, "glWindowPos4fMESA(%f, %f, %f, %f);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4fvMESA)(const GLfloat * v)
+{
+ DISPATCH(WindowPos4fvMESA, (v), (F, "glWindowPos4fvMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4iMESA)(GLint x, GLint y, GLint z, GLint w)
+{
+ DISPATCH(WindowPos4iMESA, (x, y, z, w), (F, "glWindowPos4iMESA(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4ivMESA)(const GLint * v)
+{
+ DISPATCH(WindowPos4ivMESA, (v), (F, "glWindowPos4ivMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4sMESA)(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(WindowPos4sMESA, (x, y, z, w), (F, "glWindowPos4sMESA(%d, %d, %d, %d);\n", x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(WindowPos4svMESA)(const GLshort * v)
+{
+ DISPATCH(WindowPos4svMESA, (v), (F, "glWindowPos4svMESA(%p);\n", (const void *) v));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_661)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_661)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride)
+{
+ DISPATCH(MultiModeDrawArraysIBM, (mode, first, count, primcount, modestride), (F, "glMultiModeDrawArraysIBM(%p, %p, %p, %d, %d);\n", (const void *) mode, (const void *) first, (const void *) count, primcount, modestride));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_662)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_662)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride)
+{
+ DISPATCH(MultiModeDrawElementsIBM, (mode, count, type, indices, primcount, modestride), (F, "glMultiModeDrawElementsIBM(%p, %p, 0x%x, %p, %d, %d);\n", (const void *) mode, (const void *) count, type, (const void *) indices, primcount, modestride));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_663)(GLsizei n, const GLuint * fences);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_663)(GLsizei n, const GLuint * fences)
+{
+ DISPATCH(DeleteFencesNV, (n, fences), (F, "glDeleteFencesNV(%d, %p);\n", n, (const void *) fences));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_664)(GLuint fence);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_664)(GLuint fence)
+{
+ DISPATCH(FinishFenceNV, (fence), (F, "glFinishFenceNV(%d);\n", fence));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_665)(GLsizei n, GLuint * fences);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_665)(GLsizei n, GLuint * fences)
+{
+ DISPATCH(GenFencesNV, (n, fences), (F, "glGenFencesNV(%d, %p);\n", n, (const void *) fences));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_666)(GLuint fence, GLenum pname, GLint * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_666)(GLuint fence, GLenum pname, GLint * params)
+{
+ DISPATCH(GetFenceivNV, (fence, pname, params), (F, "glGetFenceivNV(%d, 0x%x, %p);\n", fence, pname, (const void *) params));
+}
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_667)(GLuint fence);
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_667)(GLuint fence)
+{
+ RETURN_DISPATCH(IsFenceNV, (fence), (F, "glIsFenceNV(%d);\n", fence));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_668)(GLuint fence, GLenum condition);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_668)(GLuint fence, GLenum condition)
+{
+ DISPATCH(SetFenceNV, (fence, condition), (F, "glSetFenceNV(%d, 0x%x);\n", fence, condition));
+}
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_669)(GLuint fence);
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_669)(GLuint fence)
+{
+ RETURN_DISPATCH(TestFenceNV, (fence), (F, "glTestFenceNV(%d);\n", fence));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(AreProgramsResidentNV)(GLsizei n, const GLuint * ids, GLboolean * residences)
+{
+ RETURN_DISPATCH(AreProgramsResidentNV, (n, ids, residences), (F, "glAreProgramsResidentNV(%d, %p, %p);\n", n, (const void *) ids, (const void *) residences));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindProgramARB)(GLenum target, GLuint program)
+{
+ DISPATCH(BindProgramNV, (target, program), (F, "glBindProgramARB(0x%x, %d);\n", target, program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindProgramNV)(GLenum target, GLuint program)
+{
+ DISPATCH(BindProgramNV, (target, program), (F, "glBindProgramNV(0x%x, %d);\n", target, program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteProgramsARB)(GLsizei n, const GLuint * programs)
+{
+ DISPATCH(DeleteProgramsNV, (n, programs), (F, "glDeleteProgramsARB(%d, %p);\n", n, (const void *) programs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteProgramsNV)(GLsizei n, const GLuint * programs)
+{
+ DISPATCH(DeleteProgramsNV, (n, programs), (F, "glDeleteProgramsNV(%d, %p);\n", n, (const void *) programs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ExecuteProgramNV)(GLenum target, GLuint id, const GLfloat * params)
+{
+ DISPATCH(ExecuteProgramNV, (target, id, params), (F, "glExecuteProgramNV(0x%x, %d, %p);\n", target, id, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenProgramsARB)(GLsizei n, GLuint * programs)
+{
+ DISPATCH(GenProgramsNV, (n, programs), (F, "glGenProgramsARB(%d, %p);\n", n, (const void *) programs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenProgramsNV)(GLsizei n, GLuint * programs)
+{
+ DISPATCH(GenProgramsNV, (n, programs), (F, "glGenProgramsNV(%d, %p);\n", n, (const void *) programs));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramParameterdvNV)(GLenum target, GLuint index, GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetProgramParameterdvNV, (target, index, pname, params), (F, "glGetProgramParameterdvNV(0x%x, %d, 0x%x, %p);\n", target, index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramParameterfvNV)(GLenum target, GLuint index, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetProgramParameterfvNV, (target, index, pname, params), (F, "glGetProgramParameterfvNV(0x%x, %d, 0x%x, %p);\n", target, index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramStringNV)(GLuint id, GLenum pname, GLubyte * program)
+{
+ DISPATCH(GetProgramStringNV, (id, pname, program), (F, "glGetProgramStringNV(%d, 0x%x, %p);\n", id, pname, (const void *) program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramivNV)(GLuint id, GLenum pname, GLint * params)
+{
+ DISPATCH(GetProgramivNV, (id, pname, params), (F, "glGetProgramivNV(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTrackMatrixivNV)(GLenum target, GLuint address, GLenum pname, GLint * params)
+{
+ DISPATCH(GetTrackMatrixivNV, (target, address, pname, params), (F, "glGetTrackMatrixivNV(0x%x, %d, 0x%x, %p);\n", target, address, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid ** pointer)
+{
+ DISPATCH(GetVertexAttribPointervNV, (index, pname, pointer), (F, "glGetVertexAttribPointerv(%d, 0x%x, %p);\n", index, pname, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribPointervARB)(GLuint index, GLenum pname, GLvoid ** pointer)
+{
+ DISPATCH(GetVertexAttribPointervNV, (index, pname, pointer), (F, "glGetVertexAttribPointervARB(%d, 0x%x, %p);\n", index, pname, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribPointervNV)(GLuint index, GLenum pname, GLvoid ** pointer)
+{
+ DISPATCH(GetVertexAttribPointervNV, (index, pname, pointer), (F, "glGetVertexAttribPointervNV(%d, 0x%x, %p);\n", index, pname, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribdvNV)(GLuint index, GLenum pname, GLdouble * params)
+{
+ DISPATCH(GetVertexAttribdvNV, (index, pname, params), (F, "glGetVertexAttribdvNV(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribfvNV)(GLuint index, GLenum pname, GLfloat * params)
+{
+ DISPATCH(GetVertexAttribfvNV, (index, pname, params), (F, "glGetVertexAttribfvNV(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetVertexAttribivNV)(GLuint index, GLenum pname, GLint * params)
+{
+ DISPATCH(GetVertexAttribivNV, (index, pname, params), (F, "glGetVertexAttribivNV(%d, 0x%x, %p);\n", index, pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsProgramARB)(GLuint program)
+{
+ RETURN_DISPATCH(IsProgramNV, (program), (F, "glIsProgramARB(%d);\n", program));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsProgramNV)(GLuint program)
+{
+ RETURN_DISPATCH(IsProgramNV, (program), (F, "glIsProgramNV(%d);\n", program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(LoadProgramNV)(GLenum target, GLuint id, GLsizei len, const GLubyte * program)
+{
+ DISPATCH(LoadProgramNV, (target, id, len, program), (F, "glLoadProgramNV(0x%x, %d, %d, %p);\n", target, id, len, (const void *) program));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameters4dvNV)(GLenum target, GLuint index, GLuint num, const GLdouble * params)
+{
+ DISPATCH(ProgramParameters4dvNV, (target, index, num, params), (F, "glProgramParameters4dvNV(0x%x, %d, %d, %p);\n", target, index, num, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramParameters4fvNV)(GLenum target, GLuint index, GLuint num, const GLfloat * params)
+{
+ DISPATCH(ProgramParameters4fvNV, (target, index, num, params), (F, "glProgramParameters4fvNV(0x%x, %d, %d, %p);\n", target, index, num, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RequestResidentProgramsNV)(GLsizei n, const GLuint * ids)
+{
+ DISPATCH(RequestResidentProgramsNV, (n, ids), (F, "glRequestResidentProgramsNV(%d, %p);\n", n, (const void *) ids));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TrackMatrixNV)(GLenum target, GLuint address, GLenum matrix, GLenum transform)
+{
+ DISPATCH(TrackMatrixNV, (target, address, matrix, transform), (F, "glTrackMatrixNV(0x%x, %d, 0x%x, 0x%x);\n", target, address, matrix, transform));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1dNV)(GLuint index, GLdouble x)
+{
+ DISPATCH(VertexAttrib1dNV, (index, x), (F, "glVertexAttrib1dNV(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1dvNV)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib1dvNV, (index, v), (F, "glVertexAttrib1dvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1fNV)(GLuint index, GLfloat x)
+{
+ DISPATCH(VertexAttrib1fNV, (index, x), (F, "glVertexAttrib1fNV(%d, %f);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1fvNV)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib1fvNV, (index, v), (F, "glVertexAttrib1fvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1sNV)(GLuint index, GLshort x)
+{
+ DISPATCH(VertexAttrib1sNV, (index, x), (F, "glVertexAttrib1sNV(%d, %d);\n", index, x));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib1svNV)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib1svNV, (index, v), (F, "glVertexAttrib1svNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2dNV)(GLuint index, GLdouble x, GLdouble y)
+{
+ DISPATCH(VertexAttrib2dNV, (index, x, y), (F, "glVertexAttrib2dNV(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2dvNV)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib2dvNV, (index, v), (F, "glVertexAttrib2dvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y)
+{
+ DISPATCH(VertexAttrib2fNV, (index, x, y), (F, "glVertexAttrib2fNV(%d, %f, %f);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2fvNV)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib2fvNV, (index, v), (F, "glVertexAttrib2fvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2sNV)(GLuint index, GLshort x, GLshort y)
+{
+ DISPATCH(VertexAttrib2sNV, (index, x, y), (F, "glVertexAttrib2sNV(%d, %d, %d);\n", index, x, y));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib2svNV)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib2svNV, (index, v), (F, "glVertexAttrib2svNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ DISPATCH(VertexAttrib3dNV, (index, x, y, z), (F, "glVertexAttrib3dNV(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3dvNV)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib3dvNV, (index, v), (F, "glVertexAttrib3dvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ DISPATCH(VertexAttrib3fNV, (index, x, y, z), (F, "glVertexAttrib3fNV(%d, %f, %f, %f);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3fvNV)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib3fvNV, (index, v), (F, "glVertexAttrib3fvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3sNV)(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ DISPATCH(VertexAttrib3sNV, (index, x, y, z), (F, "glVertexAttrib3sNV(%d, %d, %d, %d);\n", index, x, y, z));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib3svNV)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib3svNV, (index, v), (F, "glVertexAttrib3svNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4dNV)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(VertexAttrib4dNV, (index, x, y, z, w), (F, "glVertexAttrib4dNV(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4dvNV)(GLuint index, const GLdouble * v)
+{
+ DISPATCH(VertexAttrib4dvNV, (index, v), (F, "glVertexAttrib4dvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(VertexAttrib4fNV, (index, x, y, z, w), (F, "glVertexAttrib4fNV(%d, %f, %f, %f, %f);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4fvNV)(GLuint index, const GLfloat * v)
+{
+ DISPATCH(VertexAttrib4fvNV, (index, v), (F, "glVertexAttrib4fvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4sNV)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ DISPATCH(VertexAttrib4sNV, (index, x, y, z, w), (F, "glVertexAttrib4sNV(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4svNV)(GLuint index, const GLshort * v)
+{
+ DISPATCH(VertexAttrib4svNV, (index, v), (F, "glVertexAttrib4svNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4ubNV)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ DISPATCH(VertexAttrib4ubNV, (index, x, y, z, w), (F, "glVertexAttrib4ubNV(%d, %d, %d, %d, %d);\n", index, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttrib4ubvNV)(GLuint index, const GLubyte * v)
+{
+ DISPATCH(VertexAttrib4ubvNV, (index, v), (F, "glVertexAttrib4ubvNV(%d, %p);\n", index, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribPointerNV)(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
+{
+ DISPATCH(VertexAttribPointerNV, (index, size, type, stride, pointer), (F, "glVertexAttribPointerNV(%d, %d, 0x%x, %d, %p);\n", index, size, type, stride, (const void *) pointer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs1dvNV)(GLuint index, GLsizei n, const GLdouble * v)
+{
+ DISPATCH(VertexAttribs1dvNV, (index, n, v), (F, "glVertexAttribs1dvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs1fvNV)(GLuint index, GLsizei n, const GLfloat * v)
+{
+ DISPATCH(VertexAttribs1fvNV, (index, n, v), (F, "glVertexAttribs1fvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs1svNV)(GLuint index, GLsizei n, const GLshort * v)
+{
+ DISPATCH(VertexAttribs1svNV, (index, n, v), (F, "glVertexAttribs1svNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs2dvNV)(GLuint index, GLsizei n, const GLdouble * v)
+{
+ DISPATCH(VertexAttribs2dvNV, (index, n, v), (F, "glVertexAttribs2dvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs2fvNV)(GLuint index, GLsizei n, const GLfloat * v)
+{
+ DISPATCH(VertexAttribs2fvNV, (index, n, v), (F, "glVertexAttribs2fvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs2svNV)(GLuint index, GLsizei n, const GLshort * v)
+{
+ DISPATCH(VertexAttribs2svNV, (index, n, v), (F, "glVertexAttribs2svNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs3dvNV)(GLuint index, GLsizei n, const GLdouble * v)
+{
+ DISPATCH(VertexAttribs3dvNV, (index, n, v), (F, "glVertexAttribs3dvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs3fvNV)(GLuint index, GLsizei n, const GLfloat * v)
+{
+ DISPATCH(VertexAttribs3fvNV, (index, n, v), (F, "glVertexAttribs3fvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs3svNV)(GLuint index, GLsizei n, const GLshort * v)
+{
+ DISPATCH(VertexAttribs3svNV, (index, n, v), (F, "glVertexAttribs3svNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs4dvNV)(GLuint index, GLsizei n, const GLdouble * v)
+{
+ DISPATCH(VertexAttribs4dvNV, (index, n, v), (F, "glVertexAttribs4dvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs4fvNV)(GLuint index, GLsizei n, const GLfloat * v)
+{
+ DISPATCH(VertexAttribs4fvNV, (index, n, v), (F, "glVertexAttribs4fvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs4svNV)(GLuint index, GLsizei n, const GLshort * v)
+{
+ DISPATCH(VertexAttribs4svNV, (index, n, v), (F, "glVertexAttribs4svNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(VertexAttribs4ubvNV)(GLuint index, GLsizei n, const GLubyte * v)
+{
+ DISPATCH(VertexAttribs4ubvNV, (index, n, v), (F, "glVertexAttribs4ubvNV(%d, %d, %p);\n", index, n, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexBumpParameterfvATI)(GLenum pname, GLfloat * param)
+{
+ DISPATCH(GetTexBumpParameterfvATI, (pname, param), (F, "glGetTexBumpParameterfvATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetTexBumpParameterivATI)(GLenum pname, GLint * param)
+{
+ DISPATCH(GetTexBumpParameterivATI, (pname, param), (F, "glGetTexBumpParameterivATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexBumpParameterfvATI)(GLenum pname, const GLfloat * param)
+{
+ DISPATCH(TexBumpParameterfvATI, (pname, param), (F, "glTexBumpParameterfvATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(TexBumpParameterivATI)(GLenum pname, const GLint * param)
+{
+ DISPATCH(TexBumpParameterivATI, (pname, param), (F, "glTexBumpParameterivATI(0x%x, %p);\n", pname, (const void *) param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AlphaFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
+{
+ DISPATCH(AlphaFragmentOp1ATI, (op, dst, dstMod, arg1, arg1Rep, arg1Mod), (F, "glAlphaFragmentOp1ATI(0x%x, %d, %d, %d, %d, %d);\n", op, dst, dstMod, arg1, arg1Rep, arg1Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AlphaFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod)
+{
+ DISPATCH(AlphaFragmentOp2ATI, (op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod), (F, "glAlphaFragmentOp2ATI(0x%x, %d, %d, %d, %d, %d, %d, %d, %d);\n", op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(AlphaFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod)
+{
+ DISPATCH(AlphaFragmentOp3ATI, (op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod), (F, "glAlphaFragmentOp3ATI(0x%x, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d);\n", op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BeginFragmentShaderATI)(void)
+{
+ DISPATCH(BeginFragmentShaderATI, (), (F, "glBeginFragmentShaderATI();\n"));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindFragmentShaderATI)(GLuint id)
+{
+ DISPATCH(BindFragmentShaderATI, (id), (F, "glBindFragmentShaderATI(%d);\n", id));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorFragmentOp1ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
+{
+ DISPATCH(ColorFragmentOp1ATI, (op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod), (F, "glColorFragmentOp1ATI(0x%x, %d, %d, %d, %d, %d, %d);\n", op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorFragmentOp2ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod)
+{
+ DISPATCH(ColorFragmentOp2ATI, (op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod), (F, "glColorFragmentOp2ATI(0x%x, %d, %d, %d, %d, %d, %d, %d, %d, %d);\n", op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ColorFragmentOp3ATI)(GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod)
+{
+ DISPATCH(ColorFragmentOp3ATI, (op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod), (F, "glColorFragmentOp3ATI(0x%x, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d);\n", op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteFragmentShaderATI)(GLuint id)
+{
+ DISPATCH(DeleteFragmentShaderATI, (id), (F, "glDeleteFragmentShaderATI(%d);\n", id));
+}
+
+KEYWORD1 void KEYWORD2 NAME(EndFragmentShaderATI)(void)
+{
+ DISPATCH(EndFragmentShaderATI, (), (F, "glEndFragmentShaderATI();\n"));
+}
+
+KEYWORD1 GLuint KEYWORD2 NAME(GenFragmentShadersATI)(GLuint range)
+{
+ RETURN_DISPATCH(GenFragmentShadersATI, (range), (F, "glGenFragmentShadersATI(%d);\n", range));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PassTexCoordATI)(GLuint dst, GLuint coord, GLenum swizzle)
+{
+ DISPATCH(PassTexCoordATI, (dst, coord, swizzle), (F, "glPassTexCoordATI(%d, %d, 0x%x);\n", dst, coord, swizzle));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SampleMapATI)(GLuint dst, GLuint interp, GLenum swizzle)
+{
+ DISPATCH(SampleMapATI, (dst, interp, swizzle), (F, "glSampleMapATI(%d, %d, 0x%x);\n", dst, interp, swizzle));
+}
+
+KEYWORD1 void KEYWORD2 NAME(SetFragmentShaderConstantATI)(GLuint dst, const GLfloat * value)
+{
+ DISPATCH(SetFragmentShaderConstantATI, (dst, value), (F, "glSetFragmentShaderConstantATI(%d, %p);\n", dst, (const void *) value));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameteri)(GLenum pname, GLint param)
+{
+ DISPATCH(PointParameteriNV, (pname, param), (F, "glPointParameteri(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameteriNV)(GLenum pname, GLint param)
+{
+ DISPATCH(PointParameteriNV, (pname, param), (F, "glPointParameteriNV(0x%x, %d);\n", pname, param));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameteriv)(GLenum pname, const GLint * params)
+{
+ DISPATCH(PointParameterivNV, (pname, params), (F, "glPointParameteriv(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(PointParameterivNV)(GLenum pname, const GLint * params)
+{
+ DISPATCH(PointParameterivNV, (pname, params), (F, "glPointParameterivNV(0x%x, %p);\n", pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_750)(GLenum face);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_750)(GLenum face)
+{
+ DISPATCH(ActiveStencilFaceEXT, (face), (F, "glActiveStencilFaceEXT(0x%x);\n", face));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_751)(GLuint array);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_751)(GLuint array)
+{
+ DISPATCH(BindVertexArrayAPPLE, (array), (F, "glBindVertexArrayAPPLE(%d);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteVertexArrays)(GLsizei n, const GLuint * arrays)
+{
+ DISPATCH(DeleteVertexArraysAPPLE, (n, arrays), (F, "glDeleteVertexArrays(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_752)(GLsizei n, const GLuint * arrays);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_752)(GLsizei n, const GLuint * arrays)
+{
+ DISPATCH(DeleteVertexArraysAPPLE, (n, arrays), (F, "glDeleteVertexArraysAPPLE(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_753)(GLsizei n, GLuint * arrays);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_753)(GLsizei n, GLuint * arrays)
+{
+ DISPATCH(GenVertexArraysAPPLE, (n, arrays), (F, "glGenVertexArraysAPPLE(%d, %p);\n", n, (const void *) arrays));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsVertexArray)(GLuint array)
+{
+ RETURN_DISPATCH(IsVertexArrayAPPLE, (array), (F, "glIsVertexArray(%d);\n", array));
+}
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_754)(GLuint array);
+
+KEYWORD1_ALT GLboolean KEYWORD2 NAME(_dispatch_stub_754)(GLuint array)
+{
+ RETURN_DISPATCH(IsVertexArrayAPPLE, (array), (F, "glIsVertexArrayAPPLE(%d);\n", array));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramNamedParameterdvNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble * params)
+{
+ DISPATCH(GetProgramNamedParameterdvNV, (id, len, name, params), (F, "glGetProgramNamedParameterdvNV(%d, %d, %p, %p);\n", id, len, (const void *) name, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetProgramNamedParameterfvNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat * params)
+{
+ DISPATCH(GetProgramNamedParameterfvNV, (id, len, name, params), (F, "glGetProgramNamedParameterfvNV(%d, %d, %p, %p);\n", id, len, (const void *) name, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramNamedParameter4dNV)(GLuint id, GLsizei len, const GLubyte * name, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ DISPATCH(ProgramNamedParameter4dNV, (id, len, name, x, y, z, w), (F, "glProgramNamedParameter4dNV(%d, %d, %p, %f, %f, %f, %f);\n", id, len, (const void *) name, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramNamedParameter4dvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLdouble * v)
+{
+ DISPATCH(ProgramNamedParameter4dvNV, (id, len, name, v), (F, "glProgramNamedParameter4dvNV(%d, %d, %p, %p);\n", id, len, (const void *) name, (const void *) v));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramNamedParameter4fNV)(GLuint id, GLsizei len, const GLubyte * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ DISPATCH(ProgramNamedParameter4fNV, (id, len, name, x, y, z, w), (F, "glProgramNamedParameter4fNV(%d, %d, %p, %f, %f, %f, %f);\n", id, len, (const void *) name, x, y, z, w));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProgramNamedParameter4fvNV)(GLuint id, GLsizei len, const GLubyte * name, const GLfloat * v)
+{
+ DISPATCH(ProgramNamedParameter4fvNV, (id, len, name, v), (F, "glProgramNamedParameter4fvNV(%d, %d, %p, %p);\n", id, len, (const void *) name, (const void *) v));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_761)(GLclampd zmin, GLclampd zmax);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_761)(GLclampd zmin, GLclampd zmax)
+{
+ DISPATCH(DepthBoundsEXT, (zmin, zmax), (F, "glDepthBoundsEXT(%f, %f);\n", zmin, zmax));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendEquationSeparate)(GLenum modeRGB, GLenum modeA)
+{
+ DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparate(0x%x, 0x%x);\n", modeRGB, modeA));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_762)(GLenum modeRGB, GLenum modeA);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_762)(GLenum modeRGB, GLenum modeA)
+{
+ DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparateEXT(0x%x, 0x%x);\n", modeRGB, modeA));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindFramebuffer)(GLenum target, GLuint framebuffer)
+{
+ DISPATCH(BindFramebufferEXT, (target, framebuffer), (F, "glBindFramebuffer(0x%x, %d);\n", target, framebuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindFramebufferEXT)(GLenum target, GLuint framebuffer)
+{
+ DISPATCH(BindFramebufferEXT, (target, framebuffer), (F, "glBindFramebufferEXT(0x%x, %d);\n", target, framebuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindRenderbuffer)(GLenum target, GLuint renderbuffer)
+{
+ DISPATCH(BindRenderbufferEXT, (target, renderbuffer), (F, "glBindRenderbuffer(0x%x, %d);\n", target, renderbuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BindRenderbufferEXT)(GLenum target, GLuint renderbuffer)
+{
+ DISPATCH(BindRenderbufferEXT, (target, renderbuffer), (F, "glBindRenderbufferEXT(0x%x, %d);\n", target, renderbuffer));
+}
+
+KEYWORD1 GLenum KEYWORD2 NAME(CheckFramebufferStatus)(GLenum target)
+{
+ RETURN_DISPATCH(CheckFramebufferStatusEXT, (target), (F, "glCheckFramebufferStatus(0x%x);\n", target));
+}
+
+KEYWORD1 GLenum KEYWORD2 NAME(CheckFramebufferStatusEXT)(GLenum target)
+{
+ RETURN_DISPATCH(CheckFramebufferStatusEXT, (target), (F, "glCheckFramebufferStatusEXT(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteFramebuffers)(GLsizei n, const GLuint * framebuffers)
+{
+ DISPATCH(DeleteFramebuffersEXT, (n, framebuffers), (F, "glDeleteFramebuffers(%d, %p);\n", n, (const void *) framebuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteFramebuffersEXT)(GLsizei n, const GLuint * framebuffers)
+{
+ DISPATCH(DeleteFramebuffersEXT, (n, framebuffers), (F, "glDeleteFramebuffersEXT(%d, %p);\n", n, (const void *) framebuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers)
+{
+ DISPATCH(DeleteRenderbuffersEXT, (n, renderbuffers), (F, "glDeleteRenderbuffers(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(DeleteRenderbuffersEXT)(GLsizei n, const GLuint * renderbuffers)
+{
+ DISPATCH(DeleteRenderbuffersEXT, (n, renderbuffers), (F, "glDeleteRenderbuffersEXT(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ DISPATCH(FramebufferRenderbufferEXT, (target, attachment, renderbuffertarget, renderbuffer), (F, "glFramebufferRenderbuffer(0x%x, 0x%x, 0x%x, %d);\n", target, attachment, renderbuffertarget, renderbuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ DISPATCH(FramebufferRenderbufferEXT, (target, attachment, renderbuffertarget, renderbuffer), (F, "glFramebufferRenderbufferEXT(0x%x, 0x%x, 0x%x, %d);\n", target, attachment, renderbuffertarget, renderbuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture1DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture1D(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture1DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture1DEXT(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture2DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture2D(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ DISPATCH(FramebufferTexture2DEXT, (target, attachment, textarget, texture, level), (F, "glFramebufferTexture2DEXT(0x%x, 0x%x, 0x%x, %d, %d);\n", target, attachment, textarget, texture, level));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+{
+ DISPATCH(FramebufferTexture3DEXT, (target, attachment, textarget, texture, level, zoffset), (F, "glFramebufferTexture3D(0x%x, 0x%x, 0x%x, %d, %d, %d);\n", target, attachment, textarget, texture, level, zoffset));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
+{
+ DISPATCH(FramebufferTexture3DEXT, (target, attachment, textarget, texture, level, zoffset), (F, "glFramebufferTexture3DEXT(0x%x, 0x%x, 0x%x, %d, %d, %d);\n", target, attachment, textarget, texture, level, zoffset));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenFramebuffers)(GLsizei n, GLuint * framebuffers)
+{
+ DISPATCH(GenFramebuffersEXT, (n, framebuffers), (F, "glGenFramebuffers(%d, %p);\n", n, (const void *) framebuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenFramebuffersEXT)(GLsizei n, GLuint * framebuffers)
+{
+ DISPATCH(GenFramebuffersEXT, (n, framebuffers), (F, "glGenFramebuffersEXT(%d, %p);\n", n, (const void *) framebuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenRenderbuffers)(GLsizei n, GLuint * renderbuffers)
+{
+ DISPATCH(GenRenderbuffersEXT, (n, renderbuffers), (F, "glGenRenderbuffers(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenRenderbuffersEXT)(GLsizei n, GLuint * renderbuffers)
+{
+ DISPATCH(GenRenderbuffersEXT, (n, renderbuffers), (F, "glGenRenderbuffersEXT(%d, %p);\n", n, (const void *) renderbuffers));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenerateMipmap)(GLenum target)
+{
+ DISPATCH(GenerateMipmapEXT, (target), (F, "glGenerateMipmap(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GenerateMipmapEXT)(GLenum target)
+{
+ DISPATCH(GenerateMipmapEXT, (target), (F, "glGenerateMipmapEXT(0x%x);\n", target));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params)
+{
+ DISPATCH(GetFramebufferAttachmentParameterivEXT, (target, attachment, pname, params), (F, "glGetFramebufferAttachmentParameteriv(0x%x, 0x%x, 0x%x, %p);\n", target, attachment, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint * params)
+{
+ DISPATCH(GetFramebufferAttachmentParameterivEXT, (target, attachment, pname, params), (F, "glGetFramebufferAttachmentParameterivEXT(0x%x, 0x%x, 0x%x, %p);\n", target, attachment, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetRenderbufferParameterivEXT, (target, pname, params), (F, "glGetRenderbufferParameteriv(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 void KEYWORD2 NAME(GetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint * params)
+{
+ DISPATCH(GetRenderbufferParameterivEXT, (target, pname, params), (F, "glGetRenderbufferParameterivEXT(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsFramebuffer)(GLuint framebuffer)
+{
+ RETURN_DISPATCH(IsFramebufferEXT, (framebuffer), (F, "glIsFramebuffer(%d);\n", framebuffer));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsFramebufferEXT)(GLuint framebuffer)
+{
+ RETURN_DISPATCH(IsFramebufferEXT, (framebuffer), (F, "glIsFramebufferEXT(%d);\n", framebuffer));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsRenderbuffer)(GLuint renderbuffer)
+{
+ RETURN_DISPATCH(IsRenderbufferEXT, (renderbuffer), (F, "glIsRenderbuffer(%d);\n", renderbuffer));
+}
+
+KEYWORD1 GLboolean KEYWORD2 NAME(IsRenderbufferEXT)(GLuint renderbuffer)
+{
+ RETURN_DISPATCH(IsRenderbufferEXT, (renderbuffer), (F, "glIsRenderbufferEXT(%d);\n", renderbuffer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ DISPATCH(RenderbufferStorageEXT, (target, internalformat, width, height), (F, "glRenderbufferStorage(0x%x, 0x%x, %d, %d);\n", target, internalformat, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(RenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ DISPATCH(RenderbufferStorageEXT, (target, internalformat, width, height), (F, "glRenderbufferStorageEXT(0x%x, 0x%x, %d, %d);\n", target, internalformat, width, height));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_780)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_780)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebufferEXT(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_781)(GLenum target, GLenum pname, GLint param);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_781)(GLenum target, GLenum pname, GLint param)
+{
+ DISPATCH(BufferParameteriAPPLE, (target, pname, param), (F, "glBufferParameteriAPPLE(0x%x, 0x%x, %d);\n", target, pname, param));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_782)(GLenum target, GLintptr offset, GLsizeiptr size);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_782)(GLenum target, GLintptr offset, GLsizeiptr size)
+{
+ DISPATCH(FlushMappedBufferRangeAPPLE, (target, offset, size), (F, "glFlushMappedBufferRangeAPPLE(0x%x, %d, %d);\n", target, offset, size));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ DISPATCH(FramebufferTextureLayerEXT, (target, attachment, texture, level, layer), (F, "glFramebufferTextureLayer(0x%x, 0x%x, %d, %d, %d);\n", target, attachment, texture, level, layer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(FramebufferTextureLayerEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ DISPATCH(FramebufferTextureLayerEXT, (target, attachment, texture, level, layer), (F, "glFramebufferTextureLayerEXT(0x%x, 0x%x, %d, %d, %d);\n", target, attachment, texture, level, layer));
+}
+
+KEYWORD1 void KEYWORD2 NAME(ProvokingVertexEXT)(GLenum mode)
+{
+ DISPATCH(ProvokingVertexEXT, (mode), (F, "glProvokingVertexEXT(0x%x);\n", mode));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_785)(GLenum target, GLenum pname, GLvoid ** params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_785)(GLenum target, GLenum pname, GLvoid ** params)
+{
+ DISPATCH(GetTexParameterPointervAPPLE, (target, pname, params), (F, "glGetTexParameterPointervAPPLE(0x%x, 0x%x, %p);\n", target, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_786)(GLenum target, GLsizei length, GLvoid * pointer);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_786)(GLenum target, GLsizei length, GLvoid * pointer)
+{
+ DISPATCH(TextureRangeAPPLE, (target, length, pointer), (F, "glTextureRangeAPPLE(0x%x, %d, %p);\n", target, length, (const void *) pointer));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_787)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_787)(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask)
+{
+ DISPATCH(StencilFuncSeparateATI, (frontfunc, backfunc, ref, mask), (F, "glStencilFuncSeparateATI(0x%x, 0x%x, %d, %d);\n", frontfunc, backfunc, ref, mask));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_788)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_788)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
+{
+ DISPATCH(ProgramEnvParameters4fvEXT, (target, index, count, params), (F, "glProgramEnvParameters4fvEXT(0x%x, %d, %d, %p);\n", target, index, count, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_789)(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_789)(GLenum target, GLuint index, GLsizei count, const GLfloat * params)
+{
+ DISPATCH(ProgramLocalParameters4fvEXT, (target, index, count, params), (F, "glProgramLocalParameters4fvEXT(0x%x, %d, %d, %p);\n", target, index, count, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_790)(GLuint id, GLenum pname, GLint64EXT * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_790)(GLuint id, GLenum pname, GLint64EXT * params)
+{
+ DISPATCH(GetQueryObjecti64vEXT, (id, pname, params), (F, "glGetQueryObjecti64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_791)(GLuint id, GLenum pname, GLuint64EXT * params);
+
+KEYWORD1_ALT void KEYWORD2 NAME(_dispatch_stub_791)(GLuint id, GLenum pname, GLuint64EXT * params)
+{
+ DISPATCH(GetQueryObjectui64vEXT, (id, pname, params), (F, "glGetQueryObjectui64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
+}
+
+
+#endif /* defined( NAME ) */
+
+/*
+ * This is how a dispatch table can be initialized with all the functions
+ * we generated above.
+ */
+#ifdef DISPATCH_TABLE_NAME
+
+#ifndef TABLE_ENTRY
+#error TABLE_ENTRY must be defined
+#endif
+
+static _glapi_proc DISPATCH_TABLE_NAME[] = {
+ TABLE_ENTRY(NewList),
+ TABLE_ENTRY(EndList),
+ TABLE_ENTRY(CallList),
+ TABLE_ENTRY(CallLists),
+ TABLE_ENTRY(DeleteLists),
+ TABLE_ENTRY(GenLists),
+ TABLE_ENTRY(ListBase),
+ TABLE_ENTRY(Begin),
+ TABLE_ENTRY(Bitmap),
+ TABLE_ENTRY(Color3b),
+ TABLE_ENTRY(Color3bv),
+ TABLE_ENTRY(Color3d),
+ TABLE_ENTRY(Color3dv),
+ TABLE_ENTRY(Color3f),
+ TABLE_ENTRY(Color3fv),
+ TABLE_ENTRY(Color3i),
+ TABLE_ENTRY(Color3iv),
+ TABLE_ENTRY(Color3s),
+ TABLE_ENTRY(Color3sv),
+ TABLE_ENTRY(Color3ub),
+ TABLE_ENTRY(Color3ubv),
+ TABLE_ENTRY(Color3ui),
+ TABLE_ENTRY(Color3uiv),
+ TABLE_ENTRY(Color3us),
+ TABLE_ENTRY(Color3usv),
+ TABLE_ENTRY(Color4b),
+ TABLE_ENTRY(Color4bv),
+ TABLE_ENTRY(Color4d),
+ TABLE_ENTRY(Color4dv),
+ TABLE_ENTRY(Color4f),
+ TABLE_ENTRY(Color4fv),
+ TABLE_ENTRY(Color4i),
+ TABLE_ENTRY(Color4iv),
+ TABLE_ENTRY(Color4s),
+ TABLE_ENTRY(Color4sv),
+ TABLE_ENTRY(Color4ub),
+ TABLE_ENTRY(Color4ubv),
+ TABLE_ENTRY(Color4ui),
+ TABLE_ENTRY(Color4uiv),
+ TABLE_ENTRY(Color4us),
+ TABLE_ENTRY(Color4usv),
+ TABLE_ENTRY(EdgeFlag),
+ TABLE_ENTRY(EdgeFlagv),
+ TABLE_ENTRY(End),
+ TABLE_ENTRY(Indexd),
+ TABLE_ENTRY(Indexdv),
+ TABLE_ENTRY(Indexf),
+ TABLE_ENTRY(Indexfv),
+ TABLE_ENTRY(Indexi),
+ TABLE_ENTRY(Indexiv),
+ TABLE_ENTRY(Indexs),
+ TABLE_ENTRY(Indexsv),
+ TABLE_ENTRY(Normal3b),
+ TABLE_ENTRY(Normal3bv),
+ TABLE_ENTRY(Normal3d),
+ TABLE_ENTRY(Normal3dv),
+ TABLE_ENTRY(Normal3f),
+ TABLE_ENTRY(Normal3fv),
+ TABLE_ENTRY(Normal3i),
+ TABLE_ENTRY(Normal3iv),
+ TABLE_ENTRY(Normal3s),
+ TABLE_ENTRY(Normal3sv),
+ TABLE_ENTRY(RasterPos2d),
+ TABLE_ENTRY(RasterPos2dv),
+ TABLE_ENTRY(RasterPos2f),
+ TABLE_ENTRY(RasterPos2fv),
+ TABLE_ENTRY(RasterPos2i),
+ TABLE_ENTRY(RasterPos2iv),
+ TABLE_ENTRY(RasterPos2s),
+ TABLE_ENTRY(RasterPos2sv),
+ TABLE_ENTRY(RasterPos3d),
+ TABLE_ENTRY(RasterPos3dv),
+ TABLE_ENTRY(RasterPos3f),
+ TABLE_ENTRY(RasterPos3fv),
+ TABLE_ENTRY(RasterPos3i),
+ TABLE_ENTRY(RasterPos3iv),
+ TABLE_ENTRY(RasterPos3s),
+ TABLE_ENTRY(RasterPos3sv),
+ TABLE_ENTRY(RasterPos4d),
+ TABLE_ENTRY(RasterPos4dv),
+ TABLE_ENTRY(RasterPos4f),
+ TABLE_ENTRY(RasterPos4fv),
+ TABLE_ENTRY(RasterPos4i),
+ TABLE_ENTRY(RasterPos4iv),
+ TABLE_ENTRY(RasterPos4s),
+ TABLE_ENTRY(RasterPos4sv),
+ TABLE_ENTRY(Rectd),
+ TABLE_ENTRY(Rectdv),
+ TABLE_ENTRY(Rectf),
+ TABLE_ENTRY(Rectfv),
+ TABLE_ENTRY(Recti),
+ TABLE_ENTRY(Rectiv),
+ TABLE_ENTRY(Rects),
+ TABLE_ENTRY(Rectsv),
+ TABLE_ENTRY(TexCoord1d),
+ TABLE_ENTRY(TexCoord1dv),
+ TABLE_ENTRY(TexCoord1f),
+ TABLE_ENTRY(TexCoord1fv),
+ TABLE_ENTRY(TexCoord1i),
+ TABLE_ENTRY(TexCoord1iv),
+ TABLE_ENTRY(TexCoord1s),
+ TABLE_ENTRY(TexCoord1sv),
+ TABLE_ENTRY(TexCoord2d),
+ TABLE_ENTRY(TexCoord2dv),
+ TABLE_ENTRY(TexCoord2f),
+ TABLE_ENTRY(TexCoord2fv),
+ TABLE_ENTRY(TexCoord2i),
+ TABLE_ENTRY(TexCoord2iv),
+ TABLE_ENTRY(TexCoord2s),
+ TABLE_ENTRY(TexCoord2sv),
+ TABLE_ENTRY(TexCoord3d),
+ TABLE_ENTRY(TexCoord3dv),
+ TABLE_ENTRY(TexCoord3f),
+ TABLE_ENTRY(TexCoord3fv),
+ TABLE_ENTRY(TexCoord3i),
+ TABLE_ENTRY(TexCoord3iv),
+ TABLE_ENTRY(TexCoord3s),
+ TABLE_ENTRY(TexCoord3sv),
+ TABLE_ENTRY(TexCoord4d),
+ TABLE_ENTRY(TexCoord4dv),
+ TABLE_ENTRY(TexCoord4f),
+ TABLE_ENTRY(TexCoord4fv),
+ TABLE_ENTRY(TexCoord4i),
+ TABLE_ENTRY(TexCoord4iv),
+ TABLE_ENTRY(TexCoord4s),
+ TABLE_ENTRY(TexCoord4sv),
+ TABLE_ENTRY(Vertex2d),
+ TABLE_ENTRY(Vertex2dv),
+ TABLE_ENTRY(Vertex2f),
+ TABLE_ENTRY(Vertex2fv),
+ TABLE_ENTRY(Vertex2i),
+ TABLE_ENTRY(Vertex2iv),
+ TABLE_ENTRY(Vertex2s),
+ TABLE_ENTRY(Vertex2sv),
+ TABLE_ENTRY(Vertex3d),
+ TABLE_ENTRY(Vertex3dv),
+ TABLE_ENTRY(Vertex3f),
+ TABLE_ENTRY(Vertex3fv),
+ TABLE_ENTRY(Vertex3i),
+ TABLE_ENTRY(Vertex3iv),
+ TABLE_ENTRY(Vertex3s),
+ TABLE_ENTRY(Vertex3sv),
+ TABLE_ENTRY(Vertex4d),
+ TABLE_ENTRY(Vertex4dv),
+ TABLE_ENTRY(Vertex4f),
+ TABLE_ENTRY(Vertex4fv),
+ TABLE_ENTRY(Vertex4i),
+ TABLE_ENTRY(Vertex4iv),
+ TABLE_ENTRY(Vertex4s),
+ TABLE_ENTRY(Vertex4sv),
+ TABLE_ENTRY(ClipPlane),
+ TABLE_ENTRY(ColorMaterial),
+ TABLE_ENTRY(CullFace),
+ TABLE_ENTRY(Fogf),
+ TABLE_ENTRY(Fogfv),
+ TABLE_ENTRY(Fogi),
+ TABLE_ENTRY(Fogiv),
+ TABLE_ENTRY(FrontFace),
+ TABLE_ENTRY(Hint),
+ TABLE_ENTRY(Lightf),
+ TABLE_ENTRY(Lightfv),
+ TABLE_ENTRY(Lighti),
+ TABLE_ENTRY(Lightiv),
+ TABLE_ENTRY(LightModelf),
+ TABLE_ENTRY(LightModelfv),
+ TABLE_ENTRY(LightModeli),
+ TABLE_ENTRY(LightModeliv),
+ TABLE_ENTRY(LineStipple),
+ TABLE_ENTRY(LineWidth),
+ TABLE_ENTRY(Materialf),
+ TABLE_ENTRY(Materialfv),
+ TABLE_ENTRY(Materiali),
+ TABLE_ENTRY(Materialiv),
+ TABLE_ENTRY(PointSize),
+ TABLE_ENTRY(PolygonMode),
+ TABLE_ENTRY(PolygonStipple),
+ TABLE_ENTRY(Scissor),
+ TABLE_ENTRY(ShadeModel),
+ TABLE_ENTRY(TexParameterf),
+ TABLE_ENTRY(TexParameterfv),
+ TABLE_ENTRY(TexParameteri),
+ TABLE_ENTRY(TexParameteriv),
+ TABLE_ENTRY(TexImage1D),
+ TABLE_ENTRY(TexImage2D),
+ TABLE_ENTRY(TexEnvf),
+ TABLE_ENTRY(TexEnvfv),
+ TABLE_ENTRY(TexEnvi),
+ TABLE_ENTRY(TexEnviv),
+ TABLE_ENTRY(TexGend),
+ TABLE_ENTRY(TexGendv),
+ TABLE_ENTRY(TexGenf),
+ TABLE_ENTRY(TexGenfv),
+ TABLE_ENTRY(TexGeni),
+ TABLE_ENTRY(TexGeniv),
+ TABLE_ENTRY(FeedbackBuffer),
+ TABLE_ENTRY(SelectBuffer),
+ TABLE_ENTRY(RenderMode),
+ TABLE_ENTRY(InitNames),
+ TABLE_ENTRY(LoadName),
+ TABLE_ENTRY(PassThrough),
+ TABLE_ENTRY(PopName),
+ TABLE_ENTRY(PushName),
+ TABLE_ENTRY(DrawBuffer),
+ TABLE_ENTRY(Clear),
+ TABLE_ENTRY(ClearAccum),
+ TABLE_ENTRY(ClearIndex),
+ TABLE_ENTRY(ClearColor),
+ TABLE_ENTRY(ClearStencil),
+ TABLE_ENTRY(ClearDepth),
+ TABLE_ENTRY(StencilMask),
+ TABLE_ENTRY(ColorMask),
+ TABLE_ENTRY(DepthMask),
+ TABLE_ENTRY(IndexMask),
+ TABLE_ENTRY(Accum),
+ TABLE_ENTRY(Disable),
+ TABLE_ENTRY(Enable),
+ TABLE_ENTRY(Finish),
+ TABLE_ENTRY(Flush),
+ TABLE_ENTRY(PopAttrib),
+ TABLE_ENTRY(PushAttrib),
+ TABLE_ENTRY(Map1d),
+ TABLE_ENTRY(Map1f),
+ TABLE_ENTRY(Map2d),
+ TABLE_ENTRY(Map2f),
+ TABLE_ENTRY(MapGrid1d),
+ TABLE_ENTRY(MapGrid1f),
+ TABLE_ENTRY(MapGrid2d),
+ TABLE_ENTRY(MapGrid2f),
+ TABLE_ENTRY(EvalCoord1d),
+ TABLE_ENTRY(EvalCoord1dv),
+ TABLE_ENTRY(EvalCoord1f),
+ TABLE_ENTRY(EvalCoord1fv),
+ TABLE_ENTRY(EvalCoord2d),
+ TABLE_ENTRY(EvalCoord2dv),
+ TABLE_ENTRY(EvalCoord2f),
+ TABLE_ENTRY(EvalCoord2fv),
+ TABLE_ENTRY(EvalMesh1),
+ TABLE_ENTRY(EvalPoint1),
+ TABLE_ENTRY(EvalMesh2),
+ TABLE_ENTRY(EvalPoint2),
+ TABLE_ENTRY(AlphaFunc),
+ TABLE_ENTRY(BlendFunc),
+ TABLE_ENTRY(LogicOp),
+ TABLE_ENTRY(StencilFunc),
+ TABLE_ENTRY(StencilOp),
+ TABLE_ENTRY(DepthFunc),
+ TABLE_ENTRY(PixelZoom),
+ TABLE_ENTRY(PixelTransferf),
+ TABLE_ENTRY(PixelTransferi),
+ TABLE_ENTRY(PixelStoref),
+ TABLE_ENTRY(PixelStorei),
+ TABLE_ENTRY(PixelMapfv),
+ TABLE_ENTRY(PixelMapuiv),
+ TABLE_ENTRY(PixelMapusv),
+ TABLE_ENTRY(ReadBuffer),
+ TABLE_ENTRY(CopyPixels),
+ TABLE_ENTRY(ReadPixels),
+ TABLE_ENTRY(DrawPixels),
+ TABLE_ENTRY(GetBooleanv),
+ TABLE_ENTRY(GetClipPlane),
+ TABLE_ENTRY(GetDoublev),
+ TABLE_ENTRY(GetError),
+ TABLE_ENTRY(GetFloatv),
+ TABLE_ENTRY(GetIntegerv),
+ TABLE_ENTRY(GetLightfv),
+ TABLE_ENTRY(GetLightiv),
+ TABLE_ENTRY(GetMapdv),
+ TABLE_ENTRY(GetMapfv),
+ TABLE_ENTRY(GetMapiv),
+ TABLE_ENTRY(GetMaterialfv),
+ TABLE_ENTRY(GetMaterialiv),
+ TABLE_ENTRY(GetPixelMapfv),
+ TABLE_ENTRY(GetPixelMapuiv),
+ TABLE_ENTRY(GetPixelMapusv),
+ TABLE_ENTRY(GetPolygonStipple),
+ TABLE_ENTRY(GetString),
+ TABLE_ENTRY(GetTexEnvfv),
+ TABLE_ENTRY(GetTexEnviv),
+ TABLE_ENTRY(GetTexGendv),
+ TABLE_ENTRY(GetTexGenfv),
+ TABLE_ENTRY(GetTexGeniv),
+ TABLE_ENTRY(GetTexImage),
+ TABLE_ENTRY(GetTexParameterfv),
+ TABLE_ENTRY(GetTexParameteriv),
+ TABLE_ENTRY(GetTexLevelParameterfv),
+ TABLE_ENTRY(GetTexLevelParameteriv),
+ TABLE_ENTRY(IsEnabled),
+ TABLE_ENTRY(IsList),
+ TABLE_ENTRY(DepthRange),
+ TABLE_ENTRY(Frustum),
+ TABLE_ENTRY(LoadIdentity),
+ TABLE_ENTRY(LoadMatrixf),
+ TABLE_ENTRY(LoadMatrixd),
+ TABLE_ENTRY(MatrixMode),
+ TABLE_ENTRY(MultMatrixf),
+ TABLE_ENTRY(MultMatrixd),
+ TABLE_ENTRY(Ortho),
+ TABLE_ENTRY(PopMatrix),
+ TABLE_ENTRY(PushMatrix),
+ TABLE_ENTRY(Rotated),
+ TABLE_ENTRY(Rotatef),
+ TABLE_ENTRY(Scaled),
+ TABLE_ENTRY(Scalef),
+ TABLE_ENTRY(Translated),
+ TABLE_ENTRY(Translatef),
+ TABLE_ENTRY(Viewport),
+ TABLE_ENTRY(ArrayElement),
+ TABLE_ENTRY(BindTexture),
+ TABLE_ENTRY(ColorPointer),
+ TABLE_ENTRY(DisableClientState),
+ TABLE_ENTRY(DrawArrays),
+ TABLE_ENTRY(DrawElements),
+ TABLE_ENTRY(EdgeFlagPointer),
+ TABLE_ENTRY(EnableClientState),
+ TABLE_ENTRY(IndexPointer),
+ TABLE_ENTRY(Indexub),
+ TABLE_ENTRY(Indexubv),
+ TABLE_ENTRY(InterleavedArrays),
+ TABLE_ENTRY(NormalPointer),
+ TABLE_ENTRY(PolygonOffset),
+ TABLE_ENTRY(TexCoordPointer),
+ TABLE_ENTRY(VertexPointer),
+ TABLE_ENTRY(AreTexturesResident),
+ TABLE_ENTRY(CopyTexImage1D),
+ TABLE_ENTRY(CopyTexImage2D),
+ TABLE_ENTRY(CopyTexSubImage1D),
+ TABLE_ENTRY(CopyTexSubImage2D),
+ TABLE_ENTRY(DeleteTextures),
+ TABLE_ENTRY(GenTextures),
+ TABLE_ENTRY(GetPointerv),
+ TABLE_ENTRY(IsTexture),
+ TABLE_ENTRY(PrioritizeTextures),
+ TABLE_ENTRY(TexSubImage1D),
+ TABLE_ENTRY(TexSubImage2D),
+ TABLE_ENTRY(PopClientAttrib),
+ TABLE_ENTRY(PushClientAttrib),
+ TABLE_ENTRY(BlendColor),
+ TABLE_ENTRY(BlendEquation),
+ TABLE_ENTRY(DrawRangeElements),
+ TABLE_ENTRY(ColorTable),
+ TABLE_ENTRY(ColorTableParameterfv),
+ TABLE_ENTRY(ColorTableParameteriv),
+ TABLE_ENTRY(CopyColorTable),
+ TABLE_ENTRY(GetColorTable),
+ TABLE_ENTRY(GetColorTableParameterfv),
+ TABLE_ENTRY(GetColorTableParameteriv),
+ TABLE_ENTRY(ColorSubTable),
+ TABLE_ENTRY(CopyColorSubTable),
+ TABLE_ENTRY(ConvolutionFilter1D),
+ TABLE_ENTRY(ConvolutionFilter2D),
+ TABLE_ENTRY(ConvolutionParameterf),
+ TABLE_ENTRY(ConvolutionParameterfv),
+ TABLE_ENTRY(ConvolutionParameteri),
+ TABLE_ENTRY(ConvolutionParameteriv),
+ TABLE_ENTRY(CopyConvolutionFilter1D),
+ TABLE_ENTRY(CopyConvolutionFilter2D),
+ TABLE_ENTRY(GetConvolutionFilter),
+ TABLE_ENTRY(GetConvolutionParameterfv),
+ TABLE_ENTRY(GetConvolutionParameteriv),
+ TABLE_ENTRY(GetSeparableFilter),
+ TABLE_ENTRY(SeparableFilter2D),
+ TABLE_ENTRY(GetHistogram),
+ TABLE_ENTRY(GetHistogramParameterfv),
+ TABLE_ENTRY(GetHistogramParameteriv),
+ TABLE_ENTRY(GetMinmax),
+ TABLE_ENTRY(GetMinmaxParameterfv),
+ TABLE_ENTRY(GetMinmaxParameteriv),
+ TABLE_ENTRY(Histogram),
+ TABLE_ENTRY(Minmax),
+ TABLE_ENTRY(ResetHistogram),
+ TABLE_ENTRY(ResetMinmax),
+ TABLE_ENTRY(TexImage3D),
+ TABLE_ENTRY(TexSubImage3D),
+ TABLE_ENTRY(CopyTexSubImage3D),
+ TABLE_ENTRY(ActiveTextureARB),
+ TABLE_ENTRY(ClientActiveTextureARB),
+ TABLE_ENTRY(MultiTexCoord1dARB),
+ TABLE_ENTRY(MultiTexCoord1dvARB),
+ TABLE_ENTRY(MultiTexCoord1fARB),
+ TABLE_ENTRY(MultiTexCoord1fvARB),
+ TABLE_ENTRY(MultiTexCoord1iARB),
+ TABLE_ENTRY(MultiTexCoord1ivARB),
+ TABLE_ENTRY(MultiTexCoord1sARB),
+ TABLE_ENTRY(MultiTexCoord1svARB),
+ TABLE_ENTRY(MultiTexCoord2dARB),
+ TABLE_ENTRY(MultiTexCoord2dvARB),
+ TABLE_ENTRY(MultiTexCoord2fARB),
+ TABLE_ENTRY(MultiTexCoord2fvARB),
+ TABLE_ENTRY(MultiTexCoord2iARB),
+ TABLE_ENTRY(MultiTexCoord2ivARB),
+ TABLE_ENTRY(MultiTexCoord2sARB),
+ TABLE_ENTRY(MultiTexCoord2svARB),
+ TABLE_ENTRY(MultiTexCoord3dARB),
+ TABLE_ENTRY(MultiTexCoord3dvARB),
+ TABLE_ENTRY(MultiTexCoord3fARB),
+ TABLE_ENTRY(MultiTexCoord3fvARB),
+ TABLE_ENTRY(MultiTexCoord3iARB),
+ TABLE_ENTRY(MultiTexCoord3ivARB),
+ TABLE_ENTRY(MultiTexCoord3sARB),
+ TABLE_ENTRY(MultiTexCoord3svARB),
+ TABLE_ENTRY(MultiTexCoord4dARB),
+ TABLE_ENTRY(MultiTexCoord4dvARB),
+ TABLE_ENTRY(MultiTexCoord4fARB),
+ TABLE_ENTRY(MultiTexCoord4fvARB),
+ TABLE_ENTRY(MultiTexCoord4iARB),
+ TABLE_ENTRY(MultiTexCoord4ivARB),
+ TABLE_ENTRY(MultiTexCoord4sARB),
+ TABLE_ENTRY(MultiTexCoord4svARB),
+ TABLE_ENTRY(AttachShader),
+ TABLE_ENTRY(CreateProgram),
+ TABLE_ENTRY(CreateShader),
+ TABLE_ENTRY(DeleteProgram),
+ TABLE_ENTRY(DeleteShader),
+ TABLE_ENTRY(DetachShader),
+ TABLE_ENTRY(GetAttachedShaders),
+ TABLE_ENTRY(GetProgramInfoLog),
+ TABLE_ENTRY(GetProgramiv),
+ TABLE_ENTRY(GetShaderInfoLog),
+ TABLE_ENTRY(GetShaderiv),
+ TABLE_ENTRY(IsProgram),
+ TABLE_ENTRY(IsShader),
+ TABLE_ENTRY(StencilFuncSeparate),
+ TABLE_ENTRY(StencilMaskSeparate),
+ TABLE_ENTRY(StencilOpSeparate),
+ TABLE_ENTRY(UniformMatrix2x3fv),
+ TABLE_ENTRY(UniformMatrix2x4fv),
+ TABLE_ENTRY(UniformMatrix3x2fv),
+ TABLE_ENTRY(UniformMatrix3x4fv),
+ TABLE_ENTRY(UniformMatrix4x2fv),
+ TABLE_ENTRY(UniformMatrix4x3fv),
+ TABLE_ENTRY(LoadTransposeMatrixdARB),
+ TABLE_ENTRY(LoadTransposeMatrixfARB),
+ TABLE_ENTRY(MultTransposeMatrixdARB),
+ TABLE_ENTRY(MultTransposeMatrixfARB),
+ TABLE_ENTRY(SampleCoverageARB),
+ TABLE_ENTRY(CompressedTexImage1DARB),
+ TABLE_ENTRY(CompressedTexImage2DARB),
+ TABLE_ENTRY(CompressedTexImage3DARB),
+ TABLE_ENTRY(CompressedTexSubImage1DARB),
+ TABLE_ENTRY(CompressedTexSubImage2DARB),
+ TABLE_ENTRY(CompressedTexSubImage3DARB),
+ TABLE_ENTRY(GetCompressedTexImageARB),
+ TABLE_ENTRY(DisableVertexAttribArrayARB),
+ TABLE_ENTRY(EnableVertexAttribArrayARB),
+ TABLE_ENTRY(GetProgramEnvParameterdvARB),
+ TABLE_ENTRY(GetProgramEnvParameterfvARB),
+ TABLE_ENTRY(GetProgramLocalParameterdvARB),
+ TABLE_ENTRY(GetProgramLocalParameterfvARB),
+ TABLE_ENTRY(GetProgramStringARB),
+ TABLE_ENTRY(GetProgramivARB),
+ TABLE_ENTRY(GetVertexAttribdvARB),
+ TABLE_ENTRY(GetVertexAttribfvARB),
+ TABLE_ENTRY(GetVertexAttribivARB),
+ TABLE_ENTRY(ProgramEnvParameter4dARB),
+ TABLE_ENTRY(ProgramEnvParameter4dvARB),
+ TABLE_ENTRY(ProgramEnvParameter4fARB),
+ TABLE_ENTRY(ProgramEnvParameter4fvARB),
+ TABLE_ENTRY(ProgramLocalParameter4dARB),
+ TABLE_ENTRY(ProgramLocalParameter4dvARB),
+ TABLE_ENTRY(ProgramLocalParameter4fARB),
+ TABLE_ENTRY(ProgramLocalParameter4fvARB),
+ TABLE_ENTRY(ProgramStringARB),
+ TABLE_ENTRY(VertexAttrib1dARB),
+ TABLE_ENTRY(VertexAttrib1dvARB),
+ TABLE_ENTRY(VertexAttrib1fARB),
+ TABLE_ENTRY(VertexAttrib1fvARB),
+ TABLE_ENTRY(VertexAttrib1sARB),
+ TABLE_ENTRY(VertexAttrib1svARB),
+ TABLE_ENTRY(VertexAttrib2dARB),
+ TABLE_ENTRY(VertexAttrib2dvARB),
+ TABLE_ENTRY(VertexAttrib2fARB),
+ TABLE_ENTRY(VertexAttrib2fvARB),
+ TABLE_ENTRY(VertexAttrib2sARB),
+ TABLE_ENTRY(VertexAttrib2svARB),
+ TABLE_ENTRY(VertexAttrib3dARB),
+ TABLE_ENTRY(VertexAttrib3dvARB),
+ TABLE_ENTRY(VertexAttrib3fARB),
+ TABLE_ENTRY(VertexAttrib3fvARB),
+ TABLE_ENTRY(VertexAttrib3sARB),
+ TABLE_ENTRY(VertexAttrib3svARB),
+ TABLE_ENTRY(VertexAttrib4NbvARB),
+ TABLE_ENTRY(VertexAttrib4NivARB),
+ TABLE_ENTRY(VertexAttrib4NsvARB),
+ TABLE_ENTRY(VertexAttrib4NubARB),
+ TABLE_ENTRY(VertexAttrib4NubvARB),
+ TABLE_ENTRY(VertexAttrib4NuivARB),
+ TABLE_ENTRY(VertexAttrib4NusvARB),
+ TABLE_ENTRY(VertexAttrib4bvARB),
+ TABLE_ENTRY(VertexAttrib4dARB),
+ TABLE_ENTRY(VertexAttrib4dvARB),
+ TABLE_ENTRY(VertexAttrib4fARB),
+ TABLE_ENTRY(VertexAttrib4fvARB),
+ TABLE_ENTRY(VertexAttrib4ivARB),
+ TABLE_ENTRY(VertexAttrib4sARB),
+ TABLE_ENTRY(VertexAttrib4svARB),
+ TABLE_ENTRY(VertexAttrib4ubvARB),
+ TABLE_ENTRY(VertexAttrib4uivARB),
+ TABLE_ENTRY(VertexAttrib4usvARB),
+ TABLE_ENTRY(VertexAttribPointerARB),
+ TABLE_ENTRY(BindBufferARB),
+ TABLE_ENTRY(BufferDataARB),
+ TABLE_ENTRY(BufferSubDataARB),
+ TABLE_ENTRY(DeleteBuffersARB),
+ TABLE_ENTRY(GenBuffersARB),
+ TABLE_ENTRY(GetBufferParameterivARB),
+ TABLE_ENTRY(GetBufferPointervARB),
+ TABLE_ENTRY(GetBufferSubDataARB),
+ TABLE_ENTRY(IsBufferARB),
+ TABLE_ENTRY(MapBufferARB),
+ TABLE_ENTRY(UnmapBufferARB),
+ TABLE_ENTRY(BeginQueryARB),
+ TABLE_ENTRY(DeleteQueriesARB),
+ TABLE_ENTRY(EndQueryARB),
+ TABLE_ENTRY(GenQueriesARB),
+ TABLE_ENTRY(GetQueryObjectivARB),
+ TABLE_ENTRY(GetQueryObjectuivARB),
+ TABLE_ENTRY(GetQueryivARB),
+ TABLE_ENTRY(IsQueryARB),
+ TABLE_ENTRY(AttachObjectARB),
+ TABLE_ENTRY(CompileShaderARB),
+ TABLE_ENTRY(CreateProgramObjectARB),
+ TABLE_ENTRY(CreateShaderObjectARB),
+ TABLE_ENTRY(DeleteObjectARB),
+ TABLE_ENTRY(DetachObjectARB),
+ TABLE_ENTRY(GetActiveUniformARB),
+ TABLE_ENTRY(GetAttachedObjectsARB),
+ TABLE_ENTRY(GetHandleARB),
+ TABLE_ENTRY(GetInfoLogARB),
+ TABLE_ENTRY(GetObjectParameterfvARB),
+ TABLE_ENTRY(GetObjectParameterivARB),
+ TABLE_ENTRY(GetShaderSourceARB),
+ TABLE_ENTRY(GetUniformLocationARB),
+ TABLE_ENTRY(GetUniformfvARB),
+ TABLE_ENTRY(GetUniformivARB),
+ TABLE_ENTRY(LinkProgramARB),
+ TABLE_ENTRY(ShaderSourceARB),
+ TABLE_ENTRY(Uniform1fARB),
+ TABLE_ENTRY(Uniform1fvARB),
+ TABLE_ENTRY(Uniform1iARB),
+ TABLE_ENTRY(Uniform1ivARB),
+ TABLE_ENTRY(Uniform2fARB),
+ TABLE_ENTRY(Uniform2fvARB),
+ TABLE_ENTRY(Uniform2iARB),
+ TABLE_ENTRY(Uniform2ivARB),
+ TABLE_ENTRY(Uniform3fARB),
+ TABLE_ENTRY(Uniform3fvARB),
+ TABLE_ENTRY(Uniform3iARB),
+ TABLE_ENTRY(Uniform3ivARB),
+ TABLE_ENTRY(Uniform4fARB),
+ TABLE_ENTRY(Uniform4fvARB),
+ TABLE_ENTRY(Uniform4iARB),
+ TABLE_ENTRY(Uniform4ivARB),
+ TABLE_ENTRY(UniformMatrix2fvARB),
+ TABLE_ENTRY(UniformMatrix3fvARB),
+ TABLE_ENTRY(UniformMatrix4fvARB),
+ TABLE_ENTRY(UseProgramObjectARB),
+ TABLE_ENTRY(ValidateProgramARB),
+ TABLE_ENTRY(BindAttribLocationARB),
+ TABLE_ENTRY(GetActiveAttribARB),
+ TABLE_ENTRY(GetAttribLocationARB),
+ TABLE_ENTRY(DrawBuffersARB),
+ TABLE_ENTRY(RenderbufferStorageMultisample),
+ TABLE_ENTRY(FlushMappedBufferRange),
+ TABLE_ENTRY(MapBufferRange),
+ TABLE_ENTRY(BindVertexArray),
+ TABLE_ENTRY(GenVertexArrays),
+ TABLE_ENTRY(CopyBufferSubData),
+ TABLE_ENTRY(ClientWaitSync),
+ TABLE_ENTRY(DeleteSync),
+ TABLE_ENTRY(FenceSync),
+ TABLE_ENTRY(GetInteger64v),
+ TABLE_ENTRY(GetSynciv),
+ TABLE_ENTRY(IsSync),
+ TABLE_ENTRY(WaitSync),
+ TABLE_ENTRY(PolygonOffsetEXT),
+ TABLE_ENTRY(_dispatch_stub_575),
+ TABLE_ENTRY(_dispatch_stub_576),
+ TABLE_ENTRY(_dispatch_stub_577),
+ TABLE_ENTRY(_dispatch_stub_578),
+ TABLE_ENTRY(_dispatch_stub_579),
+ TABLE_ENTRY(_dispatch_stub_580),
+ TABLE_ENTRY(_dispatch_stub_581),
+ TABLE_ENTRY(_dispatch_stub_582),
+ TABLE_ENTRY(ColorPointerEXT),
+ TABLE_ENTRY(EdgeFlagPointerEXT),
+ TABLE_ENTRY(IndexPointerEXT),
+ TABLE_ENTRY(NormalPointerEXT),
+ TABLE_ENTRY(TexCoordPointerEXT),
+ TABLE_ENTRY(VertexPointerEXT),
+ TABLE_ENTRY(PointParameterfEXT),
+ TABLE_ENTRY(PointParameterfvEXT),
+ TABLE_ENTRY(LockArraysEXT),
+ TABLE_ENTRY(UnlockArraysEXT),
+ TABLE_ENTRY(_dispatch_stub_593),
+ TABLE_ENTRY(_dispatch_stub_594),
+ TABLE_ENTRY(SecondaryColor3bEXT),
+ TABLE_ENTRY(SecondaryColor3bvEXT),
+ TABLE_ENTRY(SecondaryColor3dEXT),
+ TABLE_ENTRY(SecondaryColor3dvEXT),
+ TABLE_ENTRY(SecondaryColor3fEXT),
+ TABLE_ENTRY(SecondaryColor3fvEXT),
+ TABLE_ENTRY(SecondaryColor3iEXT),
+ TABLE_ENTRY(SecondaryColor3ivEXT),
+ TABLE_ENTRY(SecondaryColor3sEXT),
+ TABLE_ENTRY(SecondaryColor3svEXT),
+ TABLE_ENTRY(SecondaryColor3ubEXT),
+ TABLE_ENTRY(SecondaryColor3ubvEXT),
+ TABLE_ENTRY(SecondaryColor3uiEXT),
+ TABLE_ENTRY(SecondaryColor3uivEXT),
+ TABLE_ENTRY(SecondaryColor3usEXT),
+ TABLE_ENTRY(SecondaryColor3usvEXT),
+ TABLE_ENTRY(SecondaryColorPointerEXT),
+ TABLE_ENTRY(MultiDrawArraysEXT),
+ TABLE_ENTRY(MultiDrawElementsEXT),
+ TABLE_ENTRY(FogCoordPointerEXT),
+ TABLE_ENTRY(FogCoorddEXT),
+ TABLE_ENTRY(FogCoorddvEXT),
+ TABLE_ENTRY(FogCoordfEXT),
+ TABLE_ENTRY(FogCoordfvEXT),
+ TABLE_ENTRY(_dispatch_stub_619),
+ TABLE_ENTRY(BlendFuncSeparateEXT),
+ TABLE_ENTRY(FlushVertexArrayRangeNV),
+ TABLE_ENTRY(VertexArrayRangeNV),
+ TABLE_ENTRY(CombinerInputNV),
+ TABLE_ENTRY(CombinerOutputNV),
+ TABLE_ENTRY(CombinerParameterfNV),
+ TABLE_ENTRY(CombinerParameterfvNV),
+ TABLE_ENTRY(CombinerParameteriNV),
+ TABLE_ENTRY(CombinerParameterivNV),
+ TABLE_ENTRY(FinalCombinerInputNV),
+ TABLE_ENTRY(GetCombinerInputParameterfvNV),
+ TABLE_ENTRY(GetCombinerInputParameterivNV),
+ TABLE_ENTRY(GetCombinerOutputParameterfvNV),
+ TABLE_ENTRY(GetCombinerOutputParameterivNV),
+ TABLE_ENTRY(GetFinalCombinerInputParameterfvNV),
+ TABLE_ENTRY(GetFinalCombinerInputParameterivNV),
+ TABLE_ENTRY(ResizeBuffersMESA),
+ TABLE_ENTRY(WindowPos2dMESA),
+ TABLE_ENTRY(WindowPos2dvMESA),
+ TABLE_ENTRY(WindowPos2fMESA),
+ TABLE_ENTRY(WindowPos2fvMESA),
+ TABLE_ENTRY(WindowPos2iMESA),
+ TABLE_ENTRY(WindowPos2ivMESA),
+ TABLE_ENTRY(WindowPos2sMESA),
+ TABLE_ENTRY(WindowPos2svMESA),
+ TABLE_ENTRY(WindowPos3dMESA),
+ TABLE_ENTRY(WindowPos3dvMESA),
+ TABLE_ENTRY(WindowPos3fMESA),
+ TABLE_ENTRY(WindowPos3fvMESA),
+ TABLE_ENTRY(WindowPos3iMESA),
+ TABLE_ENTRY(WindowPos3ivMESA),
+ TABLE_ENTRY(WindowPos3sMESA),
+ TABLE_ENTRY(WindowPos3svMESA),
+ TABLE_ENTRY(WindowPos4dMESA),
+ TABLE_ENTRY(WindowPos4dvMESA),
+ TABLE_ENTRY(WindowPos4fMESA),
+ TABLE_ENTRY(WindowPos4fvMESA),
+ TABLE_ENTRY(WindowPos4iMESA),
+ TABLE_ENTRY(WindowPos4ivMESA),
+ TABLE_ENTRY(WindowPos4sMESA),
+ TABLE_ENTRY(WindowPos4svMESA),
+ TABLE_ENTRY(_dispatch_stub_661),
+ TABLE_ENTRY(_dispatch_stub_662),
+ TABLE_ENTRY(_dispatch_stub_663),
+ TABLE_ENTRY(_dispatch_stub_664),
+ TABLE_ENTRY(_dispatch_stub_665),
+ TABLE_ENTRY(_dispatch_stub_666),
+ TABLE_ENTRY(_dispatch_stub_667),
+ TABLE_ENTRY(_dispatch_stub_668),
+ TABLE_ENTRY(_dispatch_stub_669),
+ TABLE_ENTRY(AreProgramsResidentNV),
+ TABLE_ENTRY(BindProgramNV),
+ TABLE_ENTRY(DeleteProgramsNV),
+ TABLE_ENTRY(ExecuteProgramNV),
+ TABLE_ENTRY(GenProgramsNV),
+ TABLE_ENTRY(GetProgramParameterdvNV),
+ TABLE_ENTRY(GetProgramParameterfvNV),
+ TABLE_ENTRY(GetProgramStringNV),
+ TABLE_ENTRY(GetProgramivNV),
+ TABLE_ENTRY(GetTrackMatrixivNV),
+ TABLE_ENTRY(GetVertexAttribPointervNV),
+ TABLE_ENTRY(GetVertexAttribdvNV),
+ TABLE_ENTRY(GetVertexAttribfvNV),
+ TABLE_ENTRY(GetVertexAttribivNV),
+ TABLE_ENTRY(IsProgramNV),
+ TABLE_ENTRY(LoadProgramNV),
+ TABLE_ENTRY(ProgramParameters4dvNV),
+ TABLE_ENTRY(ProgramParameters4fvNV),
+ TABLE_ENTRY(RequestResidentProgramsNV),
+ TABLE_ENTRY(TrackMatrixNV),
+ TABLE_ENTRY(VertexAttrib1dNV),
+ TABLE_ENTRY(VertexAttrib1dvNV),
+ TABLE_ENTRY(VertexAttrib1fNV),
+ TABLE_ENTRY(VertexAttrib1fvNV),
+ TABLE_ENTRY(VertexAttrib1sNV),
+ TABLE_ENTRY(VertexAttrib1svNV),
+ TABLE_ENTRY(VertexAttrib2dNV),
+ TABLE_ENTRY(VertexAttrib2dvNV),
+ TABLE_ENTRY(VertexAttrib2fNV),
+ TABLE_ENTRY(VertexAttrib2fvNV),
+ TABLE_ENTRY(VertexAttrib2sNV),
+ TABLE_ENTRY(VertexAttrib2svNV),
+ TABLE_ENTRY(VertexAttrib3dNV),
+ TABLE_ENTRY(VertexAttrib3dvNV),
+ TABLE_ENTRY(VertexAttrib3fNV),
+ TABLE_ENTRY(VertexAttrib3fvNV),
+ TABLE_ENTRY(VertexAttrib3sNV),
+ TABLE_ENTRY(VertexAttrib3svNV),
+ TABLE_ENTRY(VertexAttrib4dNV),
+ TABLE_ENTRY(VertexAttrib4dvNV),
+ TABLE_ENTRY(VertexAttrib4fNV),
+ TABLE_ENTRY(VertexAttrib4fvNV),
+ TABLE_ENTRY(VertexAttrib4sNV),
+ TABLE_ENTRY(VertexAttrib4svNV),
+ TABLE_ENTRY(VertexAttrib4ubNV),
+ TABLE_ENTRY(VertexAttrib4ubvNV),
+ TABLE_ENTRY(VertexAttribPointerNV),
+ TABLE_ENTRY(VertexAttribs1dvNV),
+ TABLE_ENTRY(VertexAttribs1fvNV),
+ TABLE_ENTRY(VertexAttribs1svNV),
+ TABLE_ENTRY(VertexAttribs2dvNV),
+ TABLE_ENTRY(VertexAttribs2fvNV),
+ TABLE_ENTRY(VertexAttribs2svNV),
+ TABLE_ENTRY(VertexAttribs3dvNV),
+ TABLE_ENTRY(VertexAttribs3fvNV),
+ TABLE_ENTRY(VertexAttribs3svNV),
+ TABLE_ENTRY(VertexAttribs4dvNV),
+ TABLE_ENTRY(VertexAttribs4fvNV),
+ TABLE_ENTRY(VertexAttribs4svNV),
+ TABLE_ENTRY(VertexAttribs4ubvNV),
+ TABLE_ENTRY(GetTexBumpParameterfvATI),
+ TABLE_ENTRY(GetTexBumpParameterivATI),
+ TABLE_ENTRY(TexBumpParameterfvATI),
+ TABLE_ENTRY(TexBumpParameterivATI),
+ TABLE_ENTRY(AlphaFragmentOp1ATI),
+ TABLE_ENTRY(AlphaFragmentOp2ATI),
+ TABLE_ENTRY(AlphaFragmentOp3ATI),
+ TABLE_ENTRY(BeginFragmentShaderATI),
+ TABLE_ENTRY(BindFragmentShaderATI),
+ TABLE_ENTRY(ColorFragmentOp1ATI),
+ TABLE_ENTRY(ColorFragmentOp2ATI),
+ TABLE_ENTRY(ColorFragmentOp3ATI),
+ TABLE_ENTRY(DeleteFragmentShaderATI),
+ TABLE_ENTRY(EndFragmentShaderATI),
+ TABLE_ENTRY(GenFragmentShadersATI),
+ TABLE_ENTRY(PassTexCoordATI),
+ TABLE_ENTRY(SampleMapATI),
+ TABLE_ENTRY(SetFragmentShaderConstantATI),
+ TABLE_ENTRY(PointParameteriNV),
+ TABLE_ENTRY(PointParameterivNV),
+ TABLE_ENTRY(_dispatch_stub_750),
+ TABLE_ENTRY(_dispatch_stub_751),
+ TABLE_ENTRY(_dispatch_stub_752),
+ TABLE_ENTRY(_dispatch_stub_753),
+ TABLE_ENTRY(_dispatch_stub_754),
+ TABLE_ENTRY(GetProgramNamedParameterdvNV),
+ TABLE_ENTRY(GetProgramNamedParameterfvNV),
+ TABLE_ENTRY(ProgramNamedParameter4dNV),
+ TABLE_ENTRY(ProgramNamedParameter4dvNV),
+ TABLE_ENTRY(ProgramNamedParameter4fNV),
+ TABLE_ENTRY(ProgramNamedParameter4fvNV),
+ TABLE_ENTRY(_dispatch_stub_761),
+ TABLE_ENTRY(_dispatch_stub_762),
+ TABLE_ENTRY(BindFramebufferEXT),
+ TABLE_ENTRY(BindRenderbufferEXT),
+ TABLE_ENTRY(CheckFramebufferStatusEXT),
+ TABLE_ENTRY(DeleteFramebuffersEXT),
+ TABLE_ENTRY(DeleteRenderbuffersEXT),
+ TABLE_ENTRY(FramebufferRenderbufferEXT),
+ TABLE_ENTRY(FramebufferTexture1DEXT),
+ TABLE_ENTRY(FramebufferTexture2DEXT),
+ TABLE_ENTRY(FramebufferTexture3DEXT),
+ TABLE_ENTRY(GenFramebuffersEXT),
+ TABLE_ENTRY(GenRenderbuffersEXT),
+ TABLE_ENTRY(GenerateMipmapEXT),
+ TABLE_ENTRY(GetFramebufferAttachmentParameterivEXT),
+ TABLE_ENTRY(GetRenderbufferParameterivEXT),
+ TABLE_ENTRY(IsFramebufferEXT),
+ TABLE_ENTRY(IsRenderbufferEXT),
+ TABLE_ENTRY(RenderbufferStorageEXT),
+ TABLE_ENTRY(_dispatch_stub_780),
+ TABLE_ENTRY(_dispatch_stub_781),
+ TABLE_ENTRY(_dispatch_stub_782),
+ TABLE_ENTRY(FramebufferTextureLayerEXT),
+ TABLE_ENTRY(ProvokingVertexEXT),
+ TABLE_ENTRY(_dispatch_stub_785),
+ TABLE_ENTRY(_dispatch_stub_786),
+ TABLE_ENTRY(_dispatch_stub_787),
+ TABLE_ENTRY(_dispatch_stub_788),
+ TABLE_ENTRY(_dispatch_stub_789),
+ TABLE_ENTRY(_dispatch_stub_790),
+ TABLE_ENTRY(_dispatch_stub_791),
+ /* A whole bunch of no-op functions. These might be called
+ * when someone tries to call a dynamically-registered
+ * extension function without a current rendering context.
+ */
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+ TABLE_ENTRY(Unused),
+};
+#endif /* DISPATCH_TABLE_NAME */
+
+
+/*
+ * This is just used to silence compiler warnings.
+ * We list the functions which are not otherwise used.
+ */
+#ifdef UNUSED_TABLE_NAME
+static _glapi_proc UNUSED_TABLE_NAME[] = {
+ TABLE_ENTRY(ArrayElementEXT),
+ TABLE_ENTRY(BindTextureEXT),
+ TABLE_ENTRY(DrawArraysEXT),
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(AreTexturesResidentEXT),
+#endif
+ TABLE_ENTRY(CopyTexImage1DEXT),
+ TABLE_ENTRY(CopyTexImage2DEXT),
+ TABLE_ENTRY(CopyTexSubImage1DEXT),
+ TABLE_ENTRY(CopyTexSubImage2DEXT),
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(DeleteTexturesEXT),
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(GenTexturesEXT),
+#endif
+ TABLE_ENTRY(GetPointervEXT),
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(IsTextureEXT),
+#endif
+ TABLE_ENTRY(PrioritizeTexturesEXT),
+ TABLE_ENTRY(TexSubImage1DEXT),
+ TABLE_ENTRY(TexSubImage2DEXT),
+ TABLE_ENTRY(BlendColorEXT),
+ TABLE_ENTRY(BlendEquationEXT),
+ TABLE_ENTRY(DrawRangeElementsEXT),
+ TABLE_ENTRY(ColorTableEXT),
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(GetColorTableEXT),
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(GetColorTableParameterfvEXT),
+#endif
+#ifndef GLX_INDIRECT_RENDERING
+ TABLE_ENTRY(GetColorTableParameterivEXT),
+#endif
+ TABLE_ENTRY(TexImage3DEXT),
+ TABLE_ENTRY(TexSubImage3DEXT),
+ TABLE_ENTRY(CopyTexSubImage3DEXT),
+ TABLE_ENTRY(ActiveTexture),
+ TABLE_ENTRY(ClientActiveTexture),
+ TABLE_ENTRY(MultiTexCoord1d),
+ TABLE_ENTRY(MultiTexCoord1dv),
+ TABLE_ENTRY(MultiTexCoord1f),
+ TABLE_ENTRY(MultiTexCoord1fv),
+ TABLE_ENTRY(MultiTexCoord1i),
+ TABLE_ENTRY(MultiTexCoord1iv),
+ TABLE_ENTRY(MultiTexCoord1s),
+ TABLE_ENTRY(MultiTexCoord1sv),
+ TABLE_ENTRY(MultiTexCoord2d),
+ TABLE_ENTRY(MultiTexCoord2dv),
+ TABLE_ENTRY(MultiTexCoord2f),
+ TABLE_ENTRY(MultiTexCoord2fv),
+ TABLE_ENTRY(MultiTexCoord2i),
+ TABLE_ENTRY(MultiTexCoord2iv),
+ TABLE_ENTRY(MultiTexCoord2s),
+ TABLE_ENTRY(MultiTexCoord2sv),
+ TABLE_ENTRY(MultiTexCoord3d),
+ TABLE_ENTRY(MultiTexCoord3dv),
+ TABLE_ENTRY(MultiTexCoord3f),
+ TABLE_ENTRY(MultiTexCoord3fv),
+ TABLE_ENTRY(MultiTexCoord3i),
+ TABLE_ENTRY(MultiTexCoord3iv),
+ TABLE_ENTRY(MultiTexCoord3s),
+ TABLE_ENTRY(MultiTexCoord3sv),
+ TABLE_ENTRY(MultiTexCoord4d),
+ TABLE_ENTRY(MultiTexCoord4dv),
+ TABLE_ENTRY(MultiTexCoord4f),
+ TABLE_ENTRY(MultiTexCoord4fv),
+ TABLE_ENTRY(MultiTexCoord4i),
+ TABLE_ENTRY(MultiTexCoord4iv),
+ TABLE_ENTRY(MultiTexCoord4s),
+ TABLE_ENTRY(MultiTexCoord4sv),
+ TABLE_ENTRY(LoadTransposeMatrixd),
+ TABLE_ENTRY(LoadTransposeMatrixf),
+ TABLE_ENTRY(MultTransposeMatrixd),
+ TABLE_ENTRY(MultTransposeMatrixf),
+ TABLE_ENTRY(SampleCoverage),
+ TABLE_ENTRY(CompressedTexImage1D),
+ TABLE_ENTRY(CompressedTexImage2D),
+ TABLE_ENTRY(CompressedTexImage3D),
+ TABLE_ENTRY(CompressedTexSubImage1D),
+ TABLE_ENTRY(CompressedTexSubImage2D),
+ TABLE_ENTRY(CompressedTexSubImage3D),
+ TABLE_ENTRY(GetCompressedTexImage),
+ TABLE_ENTRY(DisableVertexAttribArray),
+ TABLE_ENTRY(EnableVertexAttribArray),
+ TABLE_ENTRY(GetVertexAttribdv),
+ TABLE_ENTRY(GetVertexAttribfv),
+ TABLE_ENTRY(GetVertexAttribiv),
+ TABLE_ENTRY(ProgramParameter4dNV),
+ TABLE_ENTRY(ProgramParameter4dvNV),
+ TABLE_ENTRY(ProgramParameter4fNV),
+ TABLE_ENTRY(ProgramParameter4fvNV),
+ TABLE_ENTRY(VertexAttrib1d),
+ TABLE_ENTRY(VertexAttrib1dv),
+ TABLE_ENTRY(VertexAttrib1f),
+ TABLE_ENTRY(VertexAttrib1fv),
+ TABLE_ENTRY(VertexAttrib1s),
+ TABLE_ENTRY(VertexAttrib1sv),
+ TABLE_ENTRY(VertexAttrib2d),
+ TABLE_ENTRY(VertexAttrib2dv),
+ TABLE_ENTRY(VertexAttrib2f),
+ TABLE_ENTRY(VertexAttrib2fv),
+ TABLE_ENTRY(VertexAttrib2s),
+ TABLE_ENTRY(VertexAttrib2sv),
+ TABLE_ENTRY(VertexAttrib3d),
+ TABLE_ENTRY(VertexAttrib3dv),
+ TABLE_ENTRY(VertexAttrib3f),
+ TABLE_ENTRY(VertexAttrib3fv),
+ TABLE_ENTRY(VertexAttrib3s),
+ TABLE_ENTRY(VertexAttrib3sv),
+ TABLE_ENTRY(VertexAttrib4Nbv),
+ TABLE_ENTRY(VertexAttrib4Niv),
+ TABLE_ENTRY(VertexAttrib4Nsv),
+ TABLE_ENTRY(VertexAttrib4Nub),
+ TABLE_ENTRY(VertexAttrib4Nubv),
+ TABLE_ENTRY(VertexAttrib4Nuiv),
+ TABLE_ENTRY(VertexAttrib4Nusv),
+ TABLE_ENTRY(VertexAttrib4bv),
+ TABLE_ENTRY(VertexAttrib4d),
+ TABLE_ENTRY(VertexAttrib4dv),
+ TABLE_ENTRY(VertexAttrib4f),
+ TABLE_ENTRY(VertexAttrib4fv),
+ TABLE_ENTRY(VertexAttrib4iv),
+ TABLE_ENTRY(VertexAttrib4s),
+ TABLE_ENTRY(VertexAttrib4sv),
+ TABLE_ENTRY(VertexAttrib4ubv),
+ TABLE_ENTRY(VertexAttrib4uiv),
+ TABLE_ENTRY(VertexAttrib4usv),
+ TABLE_ENTRY(VertexAttribPointer),
+ TABLE_ENTRY(BindBuffer),
+ TABLE_ENTRY(BufferData),
+ TABLE_ENTRY(BufferSubData),
+ TABLE_ENTRY(DeleteBuffers),
+ TABLE_ENTRY(GenBuffers),
+ TABLE_ENTRY(GetBufferParameteriv),
+ TABLE_ENTRY(GetBufferPointerv),
+ TABLE_ENTRY(GetBufferSubData),
+ TABLE_ENTRY(IsBuffer),
+ TABLE_ENTRY(MapBuffer),
+ TABLE_ENTRY(UnmapBuffer),
+ TABLE_ENTRY(BeginQuery),
+ TABLE_ENTRY(DeleteQueries),
+ TABLE_ENTRY(EndQuery),
+ TABLE_ENTRY(GenQueries),
+ TABLE_ENTRY(GetQueryObjectiv),
+ TABLE_ENTRY(GetQueryObjectuiv),
+ TABLE_ENTRY(GetQueryiv),
+ TABLE_ENTRY(IsQuery),
+ TABLE_ENTRY(CompileShader),
+ TABLE_ENTRY(GetActiveUniform),
+ TABLE_ENTRY(GetShaderSource),
+ TABLE_ENTRY(GetUniformLocation),
+ TABLE_ENTRY(GetUniformfv),
+ TABLE_ENTRY(GetUniformiv),
+ TABLE_ENTRY(LinkProgram),
+ TABLE_ENTRY(ShaderSource),
+ TABLE_ENTRY(Uniform1f),
+ TABLE_ENTRY(Uniform1fv),
+ TABLE_ENTRY(Uniform1i),
+ TABLE_ENTRY(Uniform1iv),
+ TABLE_ENTRY(Uniform2f),
+ TABLE_ENTRY(Uniform2fv),
+ TABLE_ENTRY(Uniform2i),
+ TABLE_ENTRY(Uniform2iv),
+ TABLE_ENTRY(Uniform3f),
+ TABLE_ENTRY(Uniform3fv),
+ TABLE_ENTRY(Uniform3i),
+ TABLE_ENTRY(Uniform3iv),
+ TABLE_ENTRY(Uniform4f),
+ TABLE_ENTRY(Uniform4fv),
+ TABLE_ENTRY(Uniform4i),
+ TABLE_ENTRY(Uniform4iv),
+ TABLE_ENTRY(UniformMatrix2fv),
+ TABLE_ENTRY(UniformMatrix3fv),
+ TABLE_ENTRY(UniformMatrix4fv),
+ TABLE_ENTRY(UseProgram),
+ TABLE_ENTRY(ValidateProgram),
+ TABLE_ENTRY(BindAttribLocation),
+ TABLE_ENTRY(GetActiveAttrib),
+ TABLE_ENTRY(GetAttribLocation),
+ TABLE_ENTRY(DrawBuffers),
+ TABLE_ENTRY(DrawBuffersATI),
+ TABLE_ENTRY(PointParameterf),
+ TABLE_ENTRY(PointParameterfARB),
+ TABLE_ENTRY(PointParameterfv),
+ TABLE_ENTRY(PointParameterfvARB),
+ TABLE_ENTRY(SecondaryColor3b),
+ TABLE_ENTRY(SecondaryColor3bv),
+ TABLE_ENTRY(SecondaryColor3d),
+ TABLE_ENTRY(SecondaryColor3dv),
+ TABLE_ENTRY(SecondaryColor3f),
+ TABLE_ENTRY(SecondaryColor3fv),
+ TABLE_ENTRY(SecondaryColor3i),
+ TABLE_ENTRY(SecondaryColor3iv),
+ TABLE_ENTRY(SecondaryColor3s),
+ TABLE_ENTRY(SecondaryColor3sv),
+ TABLE_ENTRY(SecondaryColor3ub),
+ TABLE_ENTRY(SecondaryColor3ubv),
+ TABLE_ENTRY(SecondaryColor3ui),
+ TABLE_ENTRY(SecondaryColor3uiv),
+ TABLE_ENTRY(SecondaryColor3us),
+ TABLE_ENTRY(SecondaryColor3usv),
+ TABLE_ENTRY(SecondaryColorPointer),
+ TABLE_ENTRY(MultiDrawArrays),
+ TABLE_ENTRY(MultiDrawElements),
+ TABLE_ENTRY(FogCoordPointer),
+ TABLE_ENTRY(FogCoordd),
+ TABLE_ENTRY(FogCoorddv),
+ TABLE_ENTRY(FogCoordf),
+ TABLE_ENTRY(FogCoordfv),
+ TABLE_ENTRY(BlendFuncSeparate),
+ TABLE_ENTRY(WindowPos2d),
+ TABLE_ENTRY(WindowPos2dARB),
+ TABLE_ENTRY(WindowPos2dv),
+ TABLE_ENTRY(WindowPos2dvARB),
+ TABLE_ENTRY(WindowPos2f),
+ TABLE_ENTRY(WindowPos2fARB),
+ TABLE_ENTRY(WindowPos2fv),
+ TABLE_ENTRY(WindowPos2fvARB),
+ TABLE_ENTRY(WindowPos2i),
+ TABLE_ENTRY(WindowPos2iARB),
+ TABLE_ENTRY(WindowPos2iv),
+ TABLE_ENTRY(WindowPos2ivARB),
+ TABLE_ENTRY(WindowPos2s),
+ TABLE_ENTRY(WindowPos2sARB),
+ TABLE_ENTRY(WindowPos2sv),
+ TABLE_ENTRY(WindowPos2svARB),
+ TABLE_ENTRY(WindowPos3d),
+ TABLE_ENTRY(WindowPos3dARB),
+ TABLE_ENTRY(WindowPos3dv),
+ TABLE_ENTRY(WindowPos3dvARB),
+ TABLE_ENTRY(WindowPos3f),
+ TABLE_ENTRY(WindowPos3fARB),
+ TABLE_ENTRY(WindowPos3fv),
+ TABLE_ENTRY(WindowPos3fvARB),
+ TABLE_ENTRY(WindowPos3i),
+ TABLE_ENTRY(WindowPos3iARB),
+ TABLE_ENTRY(WindowPos3iv),
+ TABLE_ENTRY(WindowPos3ivARB),
+ TABLE_ENTRY(WindowPos3s),
+ TABLE_ENTRY(WindowPos3sARB),
+ TABLE_ENTRY(WindowPos3sv),
+ TABLE_ENTRY(WindowPos3svARB),
+ TABLE_ENTRY(BindProgramARB),
+ TABLE_ENTRY(DeleteProgramsARB),
+ TABLE_ENTRY(GenProgramsARB),
+ TABLE_ENTRY(GetVertexAttribPointerv),
+ TABLE_ENTRY(GetVertexAttribPointervARB),
+ TABLE_ENTRY(IsProgramARB),
+ TABLE_ENTRY(PointParameteri),
+ TABLE_ENTRY(PointParameteriv),
+ TABLE_ENTRY(DeleteVertexArrays),
+ TABLE_ENTRY(IsVertexArray),
+ TABLE_ENTRY(BlendEquationSeparate),
+ TABLE_ENTRY(BindFramebuffer),
+ TABLE_ENTRY(BindRenderbuffer),
+ TABLE_ENTRY(CheckFramebufferStatus),
+ TABLE_ENTRY(DeleteFramebuffers),
+ TABLE_ENTRY(DeleteRenderbuffers),
+ TABLE_ENTRY(FramebufferRenderbuffer),
+ TABLE_ENTRY(FramebufferTexture1D),
+ TABLE_ENTRY(FramebufferTexture2D),
+ TABLE_ENTRY(FramebufferTexture3D),
+ TABLE_ENTRY(GenFramebuffers),
+ TABLE_ENTRY(GenRenderbuffers),
+ TABLE_ENTRY(GenerateMipmap),
+ TABLE_ENTRY(GetFramebufferAttachmentParameteriv),
+ TABLE_ENTRY(GetRenderbufferParameteriv),
+ TABLE_ENTRY(IsFramebuffer),
+ TABLE_ENTRY(IsRenderbuffer),
+ TABLE_ENTRY(RenderbufferStorage),
+ TABLE_ENTRY(BlitFramebuffer),
+ TABLE_ENTRY(FramebufferTextureLayer),
+};
+#endif /*UNUSED_TABLE_NAME*/
+
+
+# undef KEYWORD1
+# undef KEYWORD1_ALT
+# undef KEYWORD2
+# undef NAME
+# undef DISPATCH
+# undef RETURN_DISPATCH
+# undef DISPATCH_TABLE_NAME
+# undef UNUSED_TABLE_NAME
+# undef TABLE_ENTRY
+# undef HIDDEN
diff --git a/mesalib/src/mesa/glapi/glprocs.h b/mesalib/src/mesa/glapi/glprocs.h
new file mode 100644
index 000000000..ae6603262
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glprocs.h
@@ -0,0 +1,2353 @@
+/* DO NOT EDIT - This file generated automatically by gl_procs.py (from Mesa) script */
+
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2004, 2006
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL, IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/* This file is only included by glapi.c and is used for
+ * the GetProcAddress() function
+ */
+
+typedef struct {
+ GLint Name_offset;
+#if defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING)
+ _glapi_proc Address;
+#endif
+ GLuint Offset;
+} glprocs_table_t;
+
+#if !defined(NEED_FUNCTION_POINTER) && !defined(GLX_INDIRECT_RENDERING)
+# define NAME_FUNC_OFFSET(n,f1,f2,f3,o) { n , o }
+#elif defined(NEED_FUNCTION_POINTER) && !defined(GLX_INDIRECT_RENDERING)
+# define NAME_FUNC_OFFSET(n,f1,f2,f3,o) { n , (_glapi_proc) f1 , o }
+#elif defined(NEED_FUNCTION_POINTER) && defined(GLX_INDIRECT_RENDERING)
+# define NAME_FUNC_OFFSET(n,f1,f2,f3,o) { n , (_glapi_proc) f2 , o }
+#elif !defined(NEED_FUNCTION_POINTER) && defined(GLX_INDIRECT_RENDERING)
+# define NAME_FUNC_OFFSET(n,f1,f2,f3,o) { n , (_glapi_proc) f3 , o }
+#endif
+
+
+
+static const char gl_string_table[] =
+ "glNewList\0"
+ "glEndList\0"
+ "glCallList\0"
+ "glCallLists\0"
+ "glDeleteLists\0"
+ "glGenLists\0"
+ "glListBase\0"
+ "glBegin\0"
+ "glBitmap\0"
+ "glColor3b\0"
+ "glColor3bv\0"
+ "glColor3d\0"
+ "glColor3dv\0"
+ "glColor3f\0"
+ "glColor3fv\0"
+ "glColor3i\0"
+ "glColor3iv\0"
+ "glColor3s\0"
+ "glColor3sv\0"
+ "glColor3ub\0"
+ "glColor3ubv\0"
+ "glColor3ui\0"
+ "glColor3uiv\0"
+ "glColor3us\0"
+ "glColor3usv\0"
+ "glColor4b\0"
+ "glColor4bv\0"
+ "glColor4d\0"
+ "glColor4dv\0"
+ "glColor4f\0"
+ "glColor4fv\0"
+ "glColor4i\0"
+ "glColor4iv\0"
+ "glColor4s\0"
+ "glColor4sv\0"
+ "glColor4ub\0"
+ "glColor4ubv\0"
+ "glColor4ui\0"
+ "glColor4uiv\0"
+ "glColor4us\0"
+ "glColor4usv\0"
+ "glEdgeFlag\0"
+ "glEdgeFlagv\0"
+ "glEnd\0"
+ "glIndexd\0"
+ "glIndexdv\0"
+ "glIndexf\0"
+ "glIndexfv\0"
+ "glIndexi\0"
+ "glIndexiv\0"
+ "glIndexs\0"
+ "glIndexsv\0"
+ "glNormal3b\0"
+ "glNormal3bv\0"
+ "glNormal3d\0"
+ "glNormal3dv\0"
+ "glNormal3f\0"
+ "glNormal3fv\0"
+ "glNormal3i\0"
+ "glNormal3iv\0"
+ "glNormal3s\0"
+ "glNormal3sv\0"
+ "glRasterPos2d\0"
+ "glRasterPos2dv\0"
+ "glRasterPos2f\0"
+ "glRasterPos2fv\0"
+ "glRasterPos2i\0"
+ "glRasterPos2iv\0"
+ "glRasterPos2s\0"
+ "glRasterPos2sv\0"
+ "glRasterPos3d\0"
+ "glRasterPos3dv\0"
+ "glRasterPos3f\0"
+ "glRasterPos3fv\0"
+ "glRasterPos3i\0"
+ "glRasterPos3iv\0"
+ "glRasterPos3s\0"
+ "glRasterPos3sv\0"
+ "glRasterPos4d\0"
+ "glRasterPos4dv\0"
+ "glRasterPos4f\0"
+ "glRasterPos4fv\0"
+ "glRasterPos4i\0"
+ "glRasterPos4iv\0"
+ "glRasterPos4s\0"
+ "glRasterPos4sv\0"
+ "glRectd\0"
+ "glRectdv\0"
+ "glRectf\0"
+ "glRectfv\0"
+ "glRecti\0"
+ "glRectiv\0"
+ "glRects\0"
+ "glRectsv\0"
+ "glTexCoord1d\0"
+ "glTexCoord1dv\0"
+ "glTexCoord1f\0"
+ "glTexCoord1fv\0"
+ "glTexCoord1i\0"
+ "glTexCoord1iv\0"
+ "glTexCoord1s\0"
+ "glTexCoord1sv\0"
+ "glTexCoord2d\0"
+ "glTexCoord2dv\0"
+ "glTexCoord2f\0"
+ "glTexCoord2fv\0"
+ "glTexCoord2i\0"
+ "glTexCoord2iv\0"
+ "glTexCoord2s\0"
+ "glTexCoord2sv\0"
+ "glTexCoord3d\0"
+ "glTexCoord3dv\0"
+ "glTexCoord3f\0"
+ "glTexCoord3fv\0"
+ "glTexCoord3i\0"
+ "glTexCoord3iv\0"
+ "glTexCoord3s\0"
+ "glTexCoord3sv\0"
+ "glTexCoord4d\0"
+ "glTexCoord4dv\0"
+ "glTexCoord4f\0"
+ "glTexCoord4fv\0"
+ "glTexCoord4i\0"
+ "glTexCoord4iv\0"
+ "glTexCoord4s\0"
+ "glTexCoord4sv\0"
+ "glVertex2d\0"
+ "glVertex2dv\0"
+ "glVertex2f\0"
+ "glVertex2fv\0"
+ "glVertex2i\0"
+ "glVertex2iv\0"
+ "glVertex2s\0"
+ "glVertex2sv\0"
+ "glVertex3d\0"
+ "glVertex3dv\0"
+ "glVertex3f\0"
+ "glVertex3fv\0"
+ "glVertex3i\0"
+ "glVertex3iv\0"
+ "glVertex3s\0"
+ "glVertex3sv\0"
+ "glVertex4d\0"
+ "glVertex4dv\0"
+ "glVertex4f\0"
+ "glVertex4fv\0"
+ "glVertex4i\0"
+ "glVertex4iv\0"
+ "glVertex4s\0"
+ "glVertex4sv\0"
+ "glClipPlane\0"
+ "glColorMaterial\0"
+ "glCullFace\0"
+ "glFogf\0"
+ "glFogfv\0"
+ "glFogi\0"
+ "glFogiv\0"
+ "glFrontFace\0"
+ "glHint\0"
+ "glLightf\0"
+ "glLightfv\0"
+ "glLighti\0"
+ "glLightiv\0"
+ "glLightModelf\0"
+ "glLightModelfv\0"
+ "glLightModeli\0"
+ "glLightModeliv\0"
+ "glLineStipple\0"
+ "glLineWidth\0"
+ "glMaterialf\0"
+ "glMaterialfv\0"
+ "glMateriali\0"
+ "glMaterialiv\0"
+ "glPointSize\0"
+ "glPolygonMode\0"
+ "glPolygonStipple\0"
+ "glScissor\0"
+ "glShadeModel\0"
+ "glTexParameterf\0"
+ "glTexParameterfv\0"
+ "glTexParameteri\0"
+ "glTexParameteriv\0"
+ "glTexImage1D\0"
+ "glTexImage2D\0"
+ "glTexEnvf\0"
+ "glTexEnvfv\0"
+ "glTexEnvi\0"
+ "glTexEnviv\0"
+ "glTexGend\0"
+ "glTexGendv\0"
+ "glTexGenf\0"
+ "glTexGenfv\0"
+ "glTexGeni\0"
+ "glTexGeniv\0"
+ "glFeedbackBuffer\0"
+ "glSelectBuffer\0"
+ "glRenderMode\0"
+ "glInitNames\0"
+ "glLoadName\0"
+ "glPassThrough\0"
+ "glPopName\0"
+ "glPushName\0"
+ "glDrawBuffer\0"
+ "glClear\0"
+ "glClearAccum\0"
+ "glClearIndex\0"
+ "glClearColor\0"
+ "glClearStencil\0"
+ "glClearDepth\0"
+ "glStencilMask\0"
+ "glColorMask\0"
+ "glDepthMask\0"
+ "glIndexMask\0"
+ "glAccum\0"
+ "glDisable\0"
+ "glEnable\0"
+ "glFinish\0"
+ "glFlush\0"
+ "glPopAttrib\0"
+ "glPushAttrib\0"
+ "glMap1d\0"
+ "glMap1f\0"
+ "glMap2d\0"
+ "glMap2f\0"
+ "glMapGrid1d\0"
+ "glMapGrid1f\0"
+ "glMapGrid2d\0"
+ "glMapGrid2f\0"
+ "glEvalCoord1d\0"
+ "glEvalCoord1dv\0"
+ "glEvalCoord1f\0"
+ "glEvalCoord1fv\0"
+ "glEvalCoord2d\0"
+ "glEvalCoord2dv\0"
+ "glEvalCoord2f\0"
+ "glEvalCoord2fv\0"
+ "glEvalMesh1\0"
+ "glEvalPoint1\0"
+ "glEvalMesh2\0"
+ "glEvalPoint2\0"
+ "glAlphaFunc\0"
+ "glBlendFunc\0"
+ "glLogicOp\0"
+ "glStencilFunc\0"
+ "glStencilOp\0"
+ "glDepthFunc\0"
+ "glPixelZoom\0"
+ "glPixelTransferf\0"
+ "glPixelTransferi\0"
+ "glPixelStoref\0"
+ "glPixelStorei\0"
+ "glPixelMapfv\0"
+ "glPixelMapuiv\0"
+ "glPixelMapusv\0"
+ "glReadBuffer\0"
+ "glCopyPixels\0"
+ "glReadPixels\0"
+ "glDrawPixels\0"
+ "glGetBooleanv\0"
+ "glGetClipPlane\0"
+ "glGetDoublev\0"
+ "glGetError\0"
+ "glGetFloatv\0"
+ "glGetIntegerv\0"
+ "glGetLightfv\0"
+ "glGetLightiv\0"
+ "glGetMapdv\0"
+ "glGetMapfv\0"
+ "glGetMapiv\0"
+ "glGetMaterialfv\0"
+ "glGetMaterialiv\0"
+ "glGetPixelMapfv\0"
+ "glGetPixelMapuiv\0"
+ "glGetPixelMapusv\0"
+ "glGetPolygonStipple\0"
+ "glGetString\0"
+ "glGetTexEnvfv\0"
+ "glGetTexEnviv\0"
+ "glGetTexGendv\0"
+ "glGetTexGenfv\0"
+ "glGetTexGeniv\0"
+ "glGetTexImage\0"
+ "glGetTexParameterfv\0"
+ "glGetTexParameteriv\0"
+ "glGetTexLevelParameterfv\0"
+ "glGetTexLevelParameteriv\0"
+ "glIsEnabled\0"
+ "glIsList\0"
+ "glDepthRange\0"
+ "glFrustum\0"
+ "glLoadIdentity\0"
+ "glLoadMatrixf\0"
+ "glLoadMatrixd\0"
+ "glMatrixMode\0"
+ "glMultMatrixf\0"
+ "glMultMatrixd\0"
+ "glOrtho\0"
+ "glPopMatrix\0"
+ "glPushMatrix\0"
+ "glRotated\0"
+ "glRotatef\0"
+ "glScaled\0"
+ "glScalef\0"
+ "glTranslated\0"
+ "glTranslatef\0"
+ "glViewport\0"
+ "glArrayElement\0"
+ "glBindTexture\0"
+ "glColorPointer\0"
+ "glDisableClientState\0"
+ "glDrawArrays\0"
+ "glDrawElements\0"
+ "glEdgeFlagPointer\0"
+ "glEnableClientState\0"
+ "glIndexPointer\0"
+ "glIndexub\0"
+ "glIndexubv\0"
+ "glInterleavedArrays\0"
+ "glNormalPointer\0"
+ "glPolygonOffset\0"
+ "glTexCoordPointer\0"
+ "glVertexPointer\0"
+ "glAreTexturesResident\0"
+ "glCopyTexImage1D\0"
+ "glCopyTexImage2D\0"
+ "glCopyTexSubImage1D\0"
+ "glCopyTexSubImage2D\0"
+ "glDeleteTextures\0"
+ "glGenTextures\0"
+ "glGetPointerv\0"
+ "glIsTexture\0"
+ "glPrioritizeTextures\0"
+ "glTexSubImage1D\0"
+ "glTexSubImage2D\0"
+ "glPopClientAttrib\0"
+ "glPushClientAttrib\0"
+ "glBlendColor\0"
+ "glBlendEquation\0"
+ "glDrawRangeElements\0"
+ "glColorTable\0"
+ "glColorTableParameterfv\0"
+ "glColorTableParameteriv\0"
+ "glCopyColorTable\0"
+ "glGetColorTable\0"
+ "glGetColorTableParameterfv\0"
+ "glGetColorTableParameteriv\0"
+ "glColorSubTable\0"
+ "glCopyColorSubTable\0"
+ "glConvolutionFilter1D\0"
+ "glConvolutionFilter2D\0"
+ "glConvolutionParameterf\0"
+ "glConvolutionParameterfv\0"
+ "glConvolutionParameteri\0"
+ "glConvolutionParameteriv\0"
+ "glCopyConvolutionFilter1D\0"
+ "glCopyConvolutionFilter2D\0"
+ "glGetConvolutionFilter\0"
+ "glGetConvolutionParameterfv\0"
+ "glGetConvolutionParameteriv\0"
+ "glGetSeparableFilter\0"
+ "glSeparableFilter2D\0"
+ "glGetHistogram\0"
+ "glGetHistogramParameterfv\0"
+ "glGetHistogramParameteriv\0"
+ "glGetMinmax\0"
+ "glGetMinmaxParameterfv\0"
+ "glGetMinmaxParameteriv\0"
+ "glHistogram\0"
+ "glMinmax\0"
+ "glResetHistogram\0"
+ "glResetMinmax\0"
+ "glTexImage3D\0"
+ "glTexSubImage3D\0"
+ "glCopyTexSubImage3D\0"
+ "glActiveTextureARB\0"
+ "glClientActiveTextureARB\0"
+ "glMultiTexCoord1dARB\0"
+ "glMultiTexCoord1dvARB\0"
+ "glMultiTexCoord1fARB\0"
+ "glMultiTexCoord1fvARB\0"
+ "glMultiTexCoord1iARB\0"
+ "glMultiTexCoord1ivARB\0"
+ "glMultiTexCoord1sARB\0"
+ "glMultiTexCoord1svARB\0"
+ "glMultiTexCoord2dARB\0"
+ "glMultiTexCoord2dvARB\0"
+ "glMultiTexCoord2fARB\0"
+ "glMultiTexCoord2fvARB\0"
+ "glMultiTexCoord2iARB\0"
+ "glMultiTexCoord2ivARB\0"
+ "glMultiTexCoord2sARB\0"
+ "glMultiTexCoord2svARB\0"
+ "glMultiTexCoord3dARB\0"
+ "glMultiTexCoord3dvARB\0"
+ "glMultiTexCoord3fARB\0"
+ "glMultiTexCoord3fvARB\0"
+ "glMultiTexCoord3iARB\0"
+ "glMultiTexCoord3ivARB\0"
+ "glMultiTexCoord3sARB\0"
+ "glMultiTexCoord3svARB\0"
+ "glMultiTexCoord4dARB\0"
+ "glMultiTexCoord4dvARB\0"
+ "glMultiTexCoord4fARB\0"
+ "glMultiTexCoord4fvARB\0"
+ "glMultiTexCoord4iARB\0"
+ "glMultiTexCoord4ivARB\0"
+ "glMultiTexCoord4sARB\0"
+ "glMultiTexCoord4svARB\0"
+ "glAttachShader\0"
+ "glCreateProgram\0"
+ "glCreateShader\0"
+ "glDeleteProgram\0"
+ "glDeleteShader\0"
+ "glDetachShader\0"
+ "glGetAttachedShaders\0"
+ "glGetProgramInfoLog\0"
+ "glGetProgramiv\0"
+ "glGetShaderInfoLog\0"
+ "glGetShaderiv\0"
+ "glIsProgram\0"
+ "glIsShader\0"
+ "glStencilFuncSeparate\0"
+ "glStencilMaskSeparate\0"
+ "glStencilOpSeparate\0"
+ "glUniformMatrix2x3fv\0"
+ "glUniformMatrix2x4fv\0"
+ "glUniformMatrix3x2fv\0"
+ "glUniformMatrix3x4fv\0"
+ "glUniformMatrix4x2fv\0"
+ "glUniformMatrix4x3fv\0"
+ "glLoadTransposeMatrixdARB\0"
+ "glLoadTransposeMatrixfARB\0"
+ "glMultTransposeMatrixdARB\0"
+ "glMultTransposeMatrixfARB\0"
+ "glSampleCoverageARB\0"
+ "glCompressedTexImage1DARB\0"
+ "glCompressedTexImage2DARB\0"
+ "glCompressedTexImage3DARB\0"
+ "glCompressedTexSubImage1DARB\0"
+ "glCompressedTexSubImage2DARB\0"
+ "glCompressedTexSubImage3DARB\0"
+ "glGetCompressedTexImageARB\0"
+ "glDisableVertexAttribArrayARB\0"
+ "glEnableVertexAttribArrayARB\0"
+ "glGetProgramEnvParameterdvARB\0"
+ "glGetProgramEnvParameterfvARB\0"
+ "glGetProgramLocalParameterdvARB\0"
+ "glGetProgramLocalParameterfvARB\0"
+ "glGetProgramStringARB\0"
+ "glGetProgramivARB\0"
+ "glGetVertexAttribdvARB\0"
+ "glGetVertexAttribfvARB\0"
+ "glGetVertexAttribivARB\0"
+ "glProgramEnvParameter4dARB\0"
+ "glProgramEnvParameter4dvARB\0"
+ "glProgramEnvParameter4fARB\0"
+ "glProgramEnvParameter4fvARB\0"
+ "glProgramLocalParameter4dARB\0"
+ "glProgramLocalParameter4dvARB\0"
+ "glProgramLocalParameter4fARB\0"
+ "glProgramLocalParameter4fvARB\0"
+ "glProgramStringARB\0"
+ "glVertexAttrib1dARB\0"
+ "glVertexAttrib1dvARB\0"
+ "glVertexAttrib1fARB\0"
+ "glVertexAttrib1fvARB\0"
+ "glVertexAttrib1sARB\0"
+ "glVertexAttrib1svARB\0"
+ "glVertexAttrib2dARB\0"
+ "glVertexAttrib2dvARB\0"
+ "glVertexAttrib2fARB\0"
+ "glVertexAttrib2fvARB\0"
+ "glVertexAttrib2sARB\0"
+ "glVertexAttrib2svARB\0"
+ "glVertexAttrib3dARB\0"
+ "glVertexAttrib3dvARB\0"
+ "glVertexAttrib3fARB\0"
+ "glVertexAttrib3fvARB\0"
+ "glVertexAttrib3sARB\0"
+ "glVertexAttrib3svARB\0"
+ "glVertexAttrib4NbvARB\0"
+ "glVertexAttrib4NivARB\0"
+ "glVertexAttrib4NsvARB\0"
+ "glVertexAttrib4NubARB\0"
+ "glVertexAttrib4NubvARB\0"
+ "glVertexAttrib4NuivARB\0"
+ "glVertexAttrib4NusvARB\0"
+ "glVertexAttrib4bvARB\0"
+ "glVertexAttrib4dARB\0"
+ "glVertexAttrib4dvARB\0"
+ "glVertexAttrib4fARB\0"
+ "glVertexAttrib4fvARB\0"
+ "glVertexAttrib4ivARB\0"
+ "glVertexAttrib4sARB\0"
+ "glVertexAttrib4svARB\0"
+ "glVertexAttrib4ubvARB\0"
+ "glVertexAttrib4uivARB\0"
+ "glVertexAttrib4usvARB\0"
+ "glVertexAttribPointerARB\0"
+ "glBindBufferARB\0"
+ "glBufferDataARB\0"
+ "glBufferSubDataARB\0"
+ "glDeleteBuffersARB\0"
+ "glGenBuffersARB\0"
+ "glGetBufferParameterivARB\0"
+ "glGetBufferPointervARB\0"
+ "glGetBufferSubDataARB\0"
+ "glIsBufferARB\0"
+ "glMapBufferARB\0"
+ "glUnmapBufferARB\0"
+ "glBeginQueryARB\0"
+ "glDeleteQueriesARB\0"
+ "glEndQueryARB\0"
+ "glGenQueriesARB\0"
+ "glGetQueryObjectivARB\0"
+ "glGetQueryObjectuivARB\0"
+ "glGetQueryivARB\0"
+ "glIsQueryARB\0"
+ "glAttachObjectARB\0"
+ "glCompileShaderARB\0"
+ "glCreateProgramObjectARB\0"
+ "glCreateShaderObjectARB\0"
+ "glDeleteObjectARB\0"
+ "glDetachObjectARB\0"
+ "glGetActiveUniformARB\0"
+ "glGetAttachedObjectsARB\0"
+ "glGetHandleARB\0"
+ "glGetInfoLogARB\0"
+ "glGetObjectParameterfvARB\0"
+ "glGetObjectParameterivARB\0"
+ "glGetShaderSourceARB\0"
+ "glGetUniformLocationARB\0"
+ "glGetUniformfvARB\0"
+ "glGetUniformivARB\0"
+ "glLinkProgramARB\0"
+ "glShaderSourceARB\0"
+ "glUniform1fARB\0"
+ "glUniform1fvARB\0"
+ "glUniform1iARB\0"
+ "glUniform1ivARB\0"
+ "glUniform2fARB\0"
+ "glUniform2fvARB\0"
+ "glUniform2iARB\0"
+ "glUniform2ivARB\0"
+ "glUniform3fARB\0"
+ "glUniform3fvARB\0"
+ "glUniform3iARB\0"
+ "glUniform3ivARB\0"
+ "glUniform4fARB\0"
+ "glUniform4fvARB\0"
+ "glUniform4iARB\0"
+ "glUniform4ivARB\0"
+ "glUniformMatrix2fvARB\0"
+ "glUniformMatrix3fvARB\0"
+ "glUniformMatrix4fvARB\0"
+ "glUseProgramObjectARB\0"
+ "glValidateProgramARB\0"
+ "glBindAttribLocationARB\0"
+ "glGetActiveAttribARB\0"
+ "glGetAttribLocationARB\0"
+ "glDrawBuffersARB\0"
+ "glRenderbufferStorageMultisample\0"
+ "glFlushMappedBufferRange\0"
+ "glMapBufferRange\0"
+ "glBindVertexArray\0"
+ "glGenVertexArrays\0"
+ "glCopyBufferSubData\0"
+ "glClientWaitSync\0"
+ "glDeleteSync\0"
+ "glFenceSync\0"
+ "glGetInteger64v\0"
+ "glGetSynciv\0"
+ "glIsSync\0"
+ "glWaitSync\0"
+ "glPolygonOffsetEXT\0"
+ "glGetPixelTexGenParameterfvSGIS\0"
+ "glGetPixelTexGenParameterivSGIS\0"
+ "glPixelTexGenParameterfSGIS\0"
+ "glPixelTexGenParameterfvSGIS\0"
+ "glPixelTexGenParameteriSGIS\0"
+ "glPixelTexGenParameterivSGIS\0"
+ "glSampleMaskSGIS\0"
+ "glSamplePatternSGIS\0"
+ "glColorPointerEXT\0"
+ "glEdgeFlagPointerEXT\0"
+ "glIndexPointerEXT\0"
+ "glNormalPointerEXT\0"
+ "glTexCoordPointerEXT\0"
+ "glVertexPointerEXT\0"
+ "glPointParameterfEXT\0"
+ "glPointParameterfvEXT\0"
+ "glLockArraysEXT\0"
+ "glUnlockArraysEXT\0"
+ "glCullParameterdvEXT\0"
+ "glCullParameterfvEXT\0"
+ "glSecondaryColor3bEXT\0"
+ "glSecondaryColor3bvEXT\0"
+ "glSecondaryColor3dEXT\0"
+ "glSecondaryColor3dvEXT\0"
+ "glSecondaryColor3fEXT\0"
+ "glSecondaryColor3fvEXT\0"
+ "glSecondaryColor3iEXT\0"
+ "glSecondaryColor3ivEXT\0"
+ "glSecondaryColor3sEXT\0"
+ "glSecondaryColor3svEXT\0"
+ "glSecondaryColor3ubEXT\0"
+ "glSecondaryColor3ubvEXT\0"
+ "glSecondaryColor3uiEXT\0"
+ "glSecondaryColor3uivEXT\0"
+ "glSecondaryColor3usEXT\0"
+ "glSecondaryColor3usvEXT\0"
+ "glSecondaryColorPointerEXT\0"
+ "glMultiDrawArraysEXT\0"
+ "glMultiDrawElementsEXT\0"
+ "glFogCoordPointerEXT\0"
+ "glFogCoorddEXT\0"
+ "glFogCoorddvEXT\0"
+ "glFogCoordfEXT\0"
+ "glFogCoordfvEXT\0"
+ "glPixelTexGenSGIX\0"
+ "glBlendFuncSeparateEXT\0"
+ "glFlushVertexArrayRangeNV\0"
+ "glVertexArrayRangeNV\0"
+ "glCombinerInputNV\0"
+ "glCombinerOutputNV\0"
+ "glCombinerParameterfNV\0"
+ "glCombinerParameterfvNV\0"
+ "glCombinerParameteriNV\0"
+ "glCombinerParameterivNV\0"
+ "glFinalCombinerInputNV\0"
+ "glGetCombinerInputParameterfvNV\0"
+ "glGetCombinerInputParameterivNV\0"
+ "glGetCombinerOutputParameterfvNV\0"
+ "glGetCombinerOutputParameterivNV\0"
+ "glGetFinalCombinerInputParameterfvNV\0"
+ "glGetFinalCombinerInputParameterivNV\0"
+ "glResizeBuffersMESA\0"
+ "glWindowPos2dMESA\0"
+ "glWindowPos2dvMESA\0"
+ "glWindowPos2fMESA\0"
+ "glWindowPos2fvMESA\0"
+ "glWindowPos2iMESA\0"
+ "glWindowPos2ivMESA\0"
+ "glWindowPos2sMESA\0"
+ "glWindowPos2svMESA\0"
+ "glWindowPos3dMESA\0"
+ "glWindowPos3dvMESA\0"
+ "glWindowPos3fMESA\0"
+ "glWindowPos3fvMESA\0"
+ "glWindowPos3iMESA\0"
+ "glWindowPos3ivMESA\0"
+ "glWindowPos3sMESA\0"
+ "glWindowPos3svMESA\0"
+ "glWindowPos4dMESA\0"
+ "glWindowPos4dvMESA\0"
+ "glWindowPos4fMESA\0"
+ "glWindowPos4fvMESA\0"
+ "glWindowPos4iMESA\0"
+ "glWindowPos4ivMESA\0"
+ "glWindowPos4sMESA\0"
+ "glWindowPos4svMESA\0"
+ "glMultiModeDrawArraysIBM\0"
+ "glMultiModeDrawElementsIBM\0"
+ "glDeleteFencesNV\0"
+ "glFinishFenceNV\0"
+ "glGenFencesNV\0"
+ "glGetFenceivNV\0"
+ "glIsFenceNV\0"
+ "glSetFenceNV\0"
+ "glTestFenceNV\0"
+ "glAreProgramsResidentNV\0"
+ "glBindProgramNV\0"
+ "glDeleteProgramsNV\0"
+ "glExecuteProgramNV\0"
+ "glGenProgramsNV\0"
+ "glGetProgramParameterdvNV\0"
+ "glGetProgramParameterfvNV\0"
+ "glGetProgramStringNV\0"
+ "glGetProgramivNV\0"
+ "glGetTrackMatrixivNV\0"
+ "glGetVertexAttribPointervNV\0"
+ "glGetVertexAttribdvNV\0"
+ "glGetVertexAttribfvNV\0"
+ "glGetVertexAttribivNV\0"
+ "glIsProgramNV\0"
+ "glLoadProgramNV\0"
+ "glProgramParameters4dvNV\0"
+ "glProgramParameters4fvNV\0"
+ "glRequestResidentProgramsNV\0"
+ "glTrackMatrixNV\0"
+ "glVertexAttrib1dNV\0"
+ "glVertexAttrib1dvNV\0"
+ "glVertexAttrib1fNV\0"
+ "glVertexAttrib1fvNV\0"
+ "glVertexAttrib1sNV\0"
+ "glVertexAttrib1svNV\0"
+ "glVertexAttrib2dNV\0"
+ "glVertexAttrib2dvNV\0"
+ "glVertexAttrib2fNV\0"
+ "glVertexAttrib2fvNV\0"
+ "glVertexAttrib2sNV\0"
+ "glVertexAttrib2svNV\0"
+ "glVertexAttrib3dNV\0"
+ "glVertexAttrib3dvNV\0"
+ "glVertexAttrib3fNV\0"
+ "glVertexAttrib3fvNV\0"
+ "glVertexAttrib3sNV\0"
+ "glVertexAttrib3svNV\0"
+ "glVertexAttrib4dNV\0"
+ "glVertexAttrib4dvNV\0"
+ "glVertexAttrib4fNV\0"
+ "glVertexAttrib4fvNV\0"
+ "glVertexAttrib4sNV\0"
+ "glVertexAttrib4svNV\0"
+ "glVertexAttrib4ubNV\0"
+ "glVertexAttrib4ubvNV\0"
+ "glVertexAttribPointerNV\0"
+ "glVertexAttribs1dvNV\0"
+ "glVertexAttribs1fvNV\0"
+ "glVertexAttribs1svNV\0"
+ "glVertexAttribs2dvNV\0"
+ "glVertexAttribs2fvNV\0"
+ "glVertexAttribs2svNV\0"
+ "glVertexAttribs3dvNV\0"
+ "glVertexAttribs3fvNV\0"
+ "glVertexAttribs3svNV\0"
+ "glVertexAttribs4dvNV\0"
+ "glVertexAttribs4fvNV\0"
+ "glVertexAttribs4svNV\0"
+ "glVertexAttribs4ubvNV\0"
+ "glGetTexBumpParameterfvATI\0"
+ "glGetTexBumpParameterivATI\0"
+ "glTexBumpParameterfvATI\0"
+ "glTexBumpParameterivATI\0"
+ "glAlphaFragmentOp1ATI\0"
+ "glAlphaFragmentOp2ATI\0"
+ "glAlphaFragmentOp3ATI\0"
+ "glBeginFragmentShaderATI\0"
+ "glBindFragmentShaderATI\0"
+ "glColorFragmentOp1ATI\0"
+ "glColorFragmentOp2ATI\0"
+ "glColorFragmentOp3ATI\0"
+ "glDeleteFragmentShaderATI\0"
+ "glEndFragmentShaderATI\0"
+ "glGenFragmentShadersATI\0"
+ "glPassTexCoordATI\0"
+ "glSampleMapATI\0"
+ "glSetFragmentShaderConstantATI\0"
+ "glPointParameteriNV\0"
+ "glPointParameterivNV\0"
+ "glActiveStencilFaceEXT\0"
+ "glBindVertexArrayAPPLE\0"
+ "glDeleteVertexArraysAPPLE\0"
+ "glGenVertexArraysAPPLE\0"
+ "glIsVertexArrayAPPLE\0"
+ "glGetProgramNamedParameterdvNV\0"
+ "glGetProgramNamedParameterfvNV\0"
+ "glProgramNamedParameter4dNV\0"
+ "glProgramNamedParameter4dvNV\0"
+ "glProgramNamedParameter4fNV\0"
+ "glProgramNamedParameter4fvNV\0"
+ "glDepthBoundsEXT\0"
+ "glBlendEquationSeparateEXT\0"
+ "glBindFramebufferEXT\0"
+ "glBindRenderbufferEXT\0"
+ "glCheckFramebufferStatusEXT\0"
+ "glDeleteFramebuffersEXT\0"
+ "glDeleteRenderbuffersEXT\0"
+ "glFramebufferRenderbufferEXT\0"
+ "glFramebufferTexture1DEXT\0"
+ "glFramebufferTexture2DEXT\0"
+ "glFramebufferTexture3DEXT\0"
+ "glGenFramebuffersEXT\0"
+ "glGenRenderbuffersEXT\0"
+ "glGenerateMipmapEXT\0"
+ "glGetFramebufferAttachmentParameterivEXT\0"
+ "glGetRenderbufferParameterivEXT\0"
+ "glIsFramebufferEXT\0"
+ "glIsRenderbufferEXT\0"
+ "glRenderbufferStorageEXT\0"
+ "glBlitFramebufferEXT\0"
+ "glBufferParameteriAPPLE\0"
+ "glFlushMappedBufferRangeAPPLE\0"
+ "glFramebufferTextureLayerEXT\0"
+ "glProvokingVertexEXT\0"
+ "glGetTexParameterPointervAPPLE\0"
+ "glTextureRangeAPPLE\0"
+ "glStencilFuncSeparateATI\0"
+ "glProgramEnvParameters4fvEXT\0"
+ "glProgramLocalParameters4fvEXT\0"
+ "glGetQueryObjecti64vEXT\0"
+ "glGetQueryObjectui64vEXT\0"
+ "glArrayElementEXT\0"
+ "glBindTextureEXT\0"
+ "glDrawArraysEXT\0"
+ "glAreTexturesResidentEXT\0"
+ "glCopyTexImage1DEXT\0"
+ "glCopyTexImage2DEXT\0"
+ "glCopyTexSubImage1DEXT\0"
+ "glCopyTexSubImage2DEXT\0"
+ "glDeleteTexturesEXT\0"
+ "glGenTexturesEXT\0"
+ "glGetPointervEXT\0"
+ "glIsTextureEXT\0"
+ "glPrioritizeTexturesEXT\0"
+ "glTexSubImage1DEXT\0"
+ "glTexSubImage2DEXT\0"
+ "glBlendColorEXT\0"
+ "glBlendEquationEXT\0"
+ "glDrawRangeElementsEXT\0"
+ "glColorTableSGI\0"
+ "glColorTableEXT\0"
+ "glColorTableParameterfvSGI\0"
+ "glColorTableParameterivSGI\0"
+ "glCopyColorTableSGI\0"
+ "glGetColorTableSGI\0"
+ "glGetColorTableEXT\0"
+ "glGetColorTableParameterfvSGI\0"
+ "glGetColorTableParameterfvEXT\0"
+ "glGetColorTableParameterivSGI\0"
+ "glGetColorTableParameterivEXT\0"
+ "glColorSubTableEXT\0"
+ "glCopyColorSubTableEXT\0"
+ "glConvolutionFilter1DEXT\0"
+ "glConvolutionFilter2DEXT\0"
+ "glConvolutionParameterfEXT\0"
+ "glConvolutionParameterfvEXT\0"
+ "glConvolutionParameteriEXT\0"
+ "glConvolutionParameterivEXT\0"
+ "glCopyConvolutionFilter1DEXT\0"
+ "glCopyConvolutionFilter2DEXT\0"
+ "glGetConvolutionFilterEXT\0"
+ "glGetConvolutionParameterfvEXT\0"
+ "glGetConvolutionParameterivEXT\0"
+ "glGetSeparableFilterEXT\0"
+ "glSeparableFilter2DEXT\0"
+ "glGetHistogramEXT\0"
+ "glGetHistogramParameterfvEXT\0"
+ "glGetHistogramParameterivEXT\0"
+ "glGetMinmaxEXT\0"
+ "glGetMinmaxParameterfvEXT\0"
+ "glGetMinmaxParameterivEXT\0"
+ "glHistogramEXT\0"
+ "glMinmaxEXT\0"
+ "glResetHistogramEXT\0"
+ "glResetMinmaxEXT\0"
+ "glTexImage3DEXT\0"
+ "glTexSubImage3DEXT\0"
+ "glCopyTexSubImage3DEXT\0"
+ "glActiveTexture\0"
+ "glClientActiveTexture\0"
+ "glMultiTexCoord1d\0"
+ "glMultiTexCoord1dv\0"
+ "glMultiTexCoord1f\0"
+ "glMultiTexCoord1fv\0"
+ "glMultiTexCoord1i\0"
+ "glMultiTexCoord1iv\0"
+ "glMultiTexCoord1s\0"
+ "glMultiTexCoord1sv\0"
+ "glMultiTexCoord2d\0"
+ "glMultiTexCoord2dv\0"
+ "glMultiTexCoord2f\0"
+ "glMultiTexCoord2fv\0"
+ "glMultiTexCoord2i\0"
+ "glMultiTexCoord2iv\0"
+ "glMultiTexCoord2s\0"
+ "glMultiTexCoord2sv\0"
+ "glMultiTexCoord3d\0"
+ "glMultiTexCoord3dv\0"
+ "glMultiTexCoord3f\0"
+ "glMultiTexCoord3fv\0"
+ "glMultiTexCoord3i\0"
+ "glMultiTexCoord3iv\0"
+ "glMultiTexCoord3s\0"
+ "glMultiTexCoord3sv\0"
+ "glMultiTexCoord4d\0"
+ "glMultiTexCoord4dv\0"
+ "glMultiTexCoord4f\0"
+ "glMultiTexCoord4fv\0"
+ "glMultiTexCoord4i\0"
+ "glMultiTexCoord4iv\0"
+ "glMultiTexCoord4s\0"
+ "glMultiTexCoord4sv\0"
+ "glStencilOpSeparateATI\0"
+ "glLoadTransposeMatrixd\0"
+ "glLoadTransposeMatrixf\0"
+ "glMultTransposeMatrixd\0"
+ "glMultTransposeMatrixf\0"
+ "glSampleCoverage\0"
+ "glCompressedTexImage1D\0"
+ "glCompressedTexImage2D\0"
+ "glCompressedTexImage3D\0"
+ "glCompressedTexSubImage1D\0"
+ "glCompressedTexSubImage2D\0"
+ "glCompressedTexSubImage3D\0"
+ "glGetCompressedTexImage\0"
+ "glDisableVertexAttribArray\0"
+ "glEnableVertexAttribArray\0"
+ "glGetVertexAttribdv\0"
+ "glGetVertexAttribfv\0"
+ "glGetVertexAttribiv\0"
+ "glProgramParameter4dNV\0"
+ "glProgramParameter4dvNV\0"
+ "glProgramParameter4fNV\0"
+ "glProgramParameter4fvNV\0"
+ "glVertexAttrib1d\0"
+ "glVertexAttrib1dv\0"
+ "glVertexAttrib1f\0"
+ "glVertexAttrib1fv\0"
+ "glVertexAttrib1s\0"
+ "glVertexAttrib1sv\0"
+ "glVertexAttrib2d\0"
+ "glVertexAttrib2dv\0"
+ "glVertexAttrib2f\0"
+ "glVertexAttrib2fv\0"
+ "glVertexAttrib2s\0"
+ "glVertexAttrib2sv\0"
+ "glVertexAttrib3d\0"
+ "glVertexAttrib3dv\0"
+ "glVertexAttrib3f\0"
+ "glVertexAttrib3fv\0"
+ "glVertexAttrib3s\0"
+ "glVertexAttrib3sv\0"
+ "glVertexAttrib4Nbv\0"
+ "glVertexAttrib4Niv\0"
+ "glVertexAttrib4Nsv\0"
+ "glVertexAttrib4Nub\0"
+ "glVertexAttrib4Nubv\0"
+ "glVertexAttrib4Nuiv\0"
+ "glVertexAttrib4Nusv\0"
+ "glVertexAttrib4bv\0"
+ "glVertexAttrib4d\0"
+ "glVertexAttrib4dv\0"
+ "glVertexAttrib4f\0"
+ "glVertexAttrib4fv\0"
+ "glVertexAttrib4iv\0"
+ "glVertexAttrib4s\0"
+ "glVertexAttrib4sv\0"
+ "glVertexAttrib4ubv\0"
+ "glVertexAttrib4uiv\0"
+ "glVertexAttrib4usv\0"
+ "glVertexAttribPointer\0"
+ "glBindBuffer\0"
+ "glBufferData\0"
+ "glBufferSubData\0"
+ "glDeleteBuffers\0"
+ "glGenBuffers\0"
+ "glGetBufferParameteriv\0"
+ "glGetBufferPointerv\0"
+ "glGetBufferSubData\0"
+ "glIsBuffer\0"
+ "glMapBuffer\0"
+ "glUnmapBuffer\0"
+ "glBeginQuery\0"
+ "glDeleteQueries\0"
+ "glEndQuery\0"
+ "glGenQueries\0"
+ "glGetQueryObjectiv\0"
+ "glGetQueryObjectuiv\0"
+ "glGetQueryiv\0"
+ "glIsQuery\0"
+ "glCompileShader\0"
+ "glGetActiveUniform\0"
+ "glGetShaderSource\0"
+ "glGetUniformLocation\0"
+ "glGetUniformfv\0"
+ "glGetUniformiv\0"
+ "glLinkProgram\0"
+ "glShaderSource\0"
+ "glUniform1f\0"
+ "glUniform1fv\0"
+ "glUniform1i\0"
+ "glUniform1iv\0"
+ "glUniform2f\0"
+ "glUniform2fv\0"
+ "glUniform2i\0"
+ "glUniform2iv\0"
+ "glUniform3f\0"
+ "glUniform3fv\0"
+ "glUniform3i\0"
+ "glUniform3iv\0"
+ "glUniform4f\0"
+ "glUniform4fv\0"
+ "glUniform4i\0"
+ "glUniform4iv\0"
+ "glUniformMatrix2fv\0"
+ "glUniformMatrix3fv\0"
+ "glUniformMatrix4fv\0"
+ "glUseProgram\0"
+ "glValidateProgram\0"
+ "glBindAttribLocation\0"
+ "glGetActiveAttrib\0"
+ "glGetAttribLocation\0"
+ "glDrawBuffers\0"
+ "glDrawBuffersATI\0"
+ "glSampleMaskEXT\0"
+ "glSamplePatternEXT\0"
+ "glPointParameterf\0"
+ "glPointParameterfARB\0"
+ "glPointParameterfSGIS\0"
+ "glPointParameterfv\0"
+ "glPointParameterfvARB\0"
+ "glPointParameterfvSGIS\0"
+ "glSecondaryColor3b\0"
+ "glSecondaryColor3bv\0"
+ "glSecondaryColor3d\0"
+ "glSecondaryColor3dv\0"
+ "glSecondaryColor3f\0"
+ "glSecondaryColor3fv\0"
+ "glSecondaryColor3i\0"
+ "glSecondaryColor3iv\0"
+ "glSecondaryColor3s\0"
+ "glSecondaryColor3sv\0"
+ "glSecondaryColor3ub\0"
+ "glSecondaryColor3ubv\0"
+ "glSecondaryColor3ui\0"
+ "glSecondaryColor3uiv\0"
+ "glSecondaryColor3us\0"
+ "glSecondaryColor3usv\0"
+ "glSecondaryColorPointer\0"
+ "glMultiDrawArrays\0"
+ "glMultiDrawElements\0"
+ "glFogCoordPointer\0"
+ "glFogCoordd\0"
+ "glFogCoorddv\0"
+ "glFogCoordf\0"
+ "glFogCoordfv\0"
+ "glBlendFuncSeparate\0"
+ "glBlendFuncSeparateINGR\0"
+ "glWindowPos2d\0"
+ "glWindowPos2dARB\0"
+ "glWindowPos2dv\0"
+ "glWindowPos2dvARB\0"
+ "glWindowPos2f\0"
+ "glWindowPos2fARB\0"
+ "glWindowPos2fv\0"
+ "glWindowPos2fvARB\0"
+ "glWindowPos2i\0"
+ "glWindowPos2iARB\0"
+ "glWindowPos2iv\0"
+ "glWindowPos2ivARB\0"
+ "glWindowPos2s\0"
+ "glWindowPos2sARB\0"
+ "glWindowPos2sv\0"
+ "glWindowPos2svARB\0"
+ "glWindowPos3d\0"
+ "glWindowPos3dARB\0"
+ "glWindowPos3dv\0"
+ "glWindowPos3dvARB\0"
+ "glWindowPos3f\0"
+ "glWindowPos3fARB\0"
+ "glWindowPos3fv\0"
+ "glWindowPos3fvARB\0"
+ "glWindowPos3i\0"
+ "glWindowPos3iARB\0"
+ "glWindowPos3iv\0"
+ "glWindowPos3ivARB\0"
+ "glWindowPos3s\0"
+ "glWindowPos3sARB\0"
+ "glWindowPos3sv\0"
+ "glWindowPos3svARB\0"
+ "glBindProgramARB\0"
+ "glDeleteProgramsARB\0"
+ "glGenProgramsARB\0"
+ "glGetVertexAttribPointerv\0"
+ "glGetVertexAttribPointervARB\0"
+ "glIsProgramARB\0"
+ "glPointParameteri\0"
+ "glPointParameteriv\0"
+ "glDeleteVertexArrays\0"
+ "glIsVertexArray\0"
+ "glBlendEquationSeparate\0"
+ "glBlendEquationSeparateATI\0"
+ "glBindFramebuffer\0"
+ "glBindRenderbuffer\0"
+ "glCheckFramebufferStatus\0"
+ "glDeleteFramebuffers\0"
+ "glDeleteRenderbuffers\0"
+ "glFramebufferRenderbuffer\0"
+ "glFramebufferTexture1D\0"
+ "glFramebufferTexture2D\0"
+ "glFramebufferTexture3D\0"
+ "glGenFramebuffers\0"
+ "glGenRenderbuffers\0"
+ "glGenerateMipmap\0"
+ "glGetFramebufferAttachmentParameteriv\0"
+ "glGetRenderbufferParameteriv\0"
+ "glIsFramebuffer\0"
+ "glIsRenderbuffer\0"
+ "glRenderbufferStorage\0"
+ "glBlitFramebuffer\0"
+ "glFramebufferTextureLayer\0"
+ ;
+
+
+#ifdef USE_MGL_NAMESPACE
+#define gl_dispatch_stub_343 mgl_dispatch_stub_343
+#define gl_dispatch_stub_344 mgl_dispatch_stub_344
+#define gl_dispatch_stub_345 mgl_dispatch_stub_345
+#define gl_dispatch_stub_356 mgl_dispatch_stub_356
+#define gl_dispatch_stub_357 mgl_dispatch_stub_357
+#define gl_dispatch_stub_358 mgl_dispatch_stub_358
+#define gl_dispatch_stub_359 mgl_dispatch_stub_359
+#define gl_dispatch_stub_361 mgl_dispatch_stub_361
+#define gl_dispatch_stub_362 mgl_dispatch_stub_362
+#define gl_dispatch_stub_363 mgl_dispatch_stub_363
+#define gl_dispatch_stub_364 mgl_dispatch_stub_364
+#define gl_dispatch_stub_365 mgl_dispatch_stub_365
+#define gl_dispatch_stub_366 mgl_dispatch_stub_366
+#define gl_dispatch_stub_575 mgl_dispatch_stub_575
+#define gl_dispatch_stub_576 mgl_dispatch_stub_576
+#define gl_dispatch_stub_577 mgl_dispatch_stub_577
+#define gl_dispatch_stub_578 mgl_dispatch_stub_578
+#define gl_dispatch_stub_579 mgl_dispatch_stub_579
+#define gl_dispatch_stub_580 mgl_dispatch_stub_580
+#define gl_dispatch_stub_581 mgl_dispatch_stub_581
+#define gl_dispatch_stub_582 mgl_dispatch_stub_582
+#define gl_dispatch_stub_593 mgl_dispatch_stub_593
+#define gl_dispatch_stub_594 mgl_dispatch_stub_594
+#define gl_dispatch_stub_619 mgl_dispatch_stub_619
+#define gl_dispatch_stub_661 mgl_dispatch_stub_661
+#define gl_dispatch_stub_662 mgl_dispatch_stub_662
+#define gl_dispatch_stub_663 mgl_dispatch_stub_663
+#define gl_dispatch_stub_664 mgl_dispatch_stub_664
+#define gl_dispatch_stub_665 mgl_dispatch_stub_665
+#define gl_dispatch_stub_666 mgl_dispatch_stub_666
+#define gl_dispatch_stub_667 mgl_dispatch_stub_667
+#define gl_dispatch_stub_668 mgl_dispatch_stub_668
+#define gl_dispatch_stub_669 mgl_dispatch_stub_669
+#define gl_dispatch_stub_750 mgl_dispatch_stub_750
+#define gl_dispatch_stub_751 mgl_dispatch_stub_751
+#define gl_dispatch_stub_752 mgl_dispatch_stub_752
+#define gl_dispatch_stub_753 mgl_dispatch_stub_753
+#define gl_dispatch_stub_754 mgl_dispatch_stub_754
+#define gl_dispatch_stub_761 mgl_dispatch_stub_761
+#define gl_dispatch_stub_762 mgl_dispatch_stub_762
+#define gl_dispatch_stub_780 mgl_dispatch_stub_780
+#define gl_dispatch_stub_781 mgl_dispatch_stub_781
+#define gl_dispatch_stub_782 mgl_dispatch_stub_782
+#define gl_dispatch_stub_785 mgl_dispatch_stub_785
+#define gl_dispatch_stub_786 mgl_dispatch_stub_786
+#define gl_dispatch_stub_787 mgl_dispatch_stub_787
+#define gl_dispatch_stub_788 mgl_dispatch_stub_788
+#define gl_dispatch_stub_789 mgl_dispatch_stub_789
+#define gl_dispatch_stub_790 mgl_dispatch_stub_790
+#define gl_dispatch_stub_791 mgl_dispatch_stub_791
+#endif /* USE_MGL_NAMESPACE */
+
+
+#if defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING)
+void GLAPIENTRY gl_dispatch_stub_343(GLenum target, GLenum format, GLenum type, GLvoid * table);
+void GLAPIENTRY gl_dispatch_stub_344(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_345(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_356(GLenum target, GLenum format, GLenum type, GLvoid * image);
+void GLAPIENTRY gl_dispatch_stub_357(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_358(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_359(GLenum target, GLenum format, GLenum type, GLvoid * row, GLvoid * column, GLvoid * span);
+void GLAPIENTRY gl_dispatch_stub_361(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+void GLAPIENTRY gl_dispatch_stub_362(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_363(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_364(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values);
+void GLAPIENTRY gl_dispatch_stub_365(GLenum target, GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_366(GLenum target, GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_575(GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_576(GLenum pname, GLint * params);
+void GLAPIENTRY gl_dispatch_stub_577(GLenum pname, GLfloat param);
+void GLAPIENTRY gl_dispatch_stub_578(GLenum pname, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_579(GLenum pname, GLint param);
+void GLAPIENTRY gl_dispatch_stub_580(GLenum pname, const GLint * params);
+void GLAPIENTRY gl_dispatch_stub_581(GLclampf value, GLboolean invert);
+void GLAPIENTRY gl_dispatch_stub_582(GLenum pattern);
+void GLAPIENTRY gl_dispatch_stub_593(GLenum pname, GLdouble * params);
+void GLAPIENTRY gl_dispatch_stub_594(GLenum pname, GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_619(GLenum mode);
+void GLAPIENTRY gl_dispatch_stub_661(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride);
+void GLAPIENTRY gl_dispatch_stub_662(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride);
+void GLAPIENTRY gl_dispatch_stub_663(GLsizei n, const GLuint * fences);
+void GLAPIENTRY gl_dispatch_stub_664(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_665(GLsizei n, GLuint * fences);
+void GLAPIENTRY gl_dispatch_stub_666(GLuint fence, GLenum pname, GLint * params);
+GLboolean GLAPIENTRY gl_dispatch_stub_667(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_668(GLuint fence, GLenum condition);
+GLboolean GLAPIENTRY gl_dispatch_stub_669(GLuint fence);
+void GLAPIENTRY gl_dispatch_stub_750(GLenum face);
+void GLAPIENTRY gl_dispatch_stub_751(GLuint array);
+void GLAPIENTRY gl_dispatch_stub_752(GLsizei n, const GLuint * arrays);
+void GLAPIENTRY gl_dispatch_stub_753(GLsizei n, GLuint * arrays);
+GLboolean GLAPIENTRY gl_dispatch_stub_754(GLuint array);
+void GLAPIENTRY gl_dispatch_stub_761(GLclampd zmin, GLclampd zmax);
+void GLAPIENTRY gl_dispatch_stub_762(GLenum modeRGB, GLenum modeA);
+void GLAPIENTRY gl_dispatch_stub_780(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+void GLAPIENTRY gl_dispatch_stub_781(GLenum target, GLenum pname, GLint param);
+void GLAPIENTRY gl_dispatch_stub_782(GLenum target, GLintptr offset, GLsizeiptr size);
+void GLAPIENTRY gl_dispatch_stub_785(GLenum target, GLenum pname, GLvoid ** params);
+void GLAPIENTRY gl_dispatch_stub_786(GLenum target, GLsizei length, GLvoid * pointer);
+void GLAPIENTRY gl_dispatch_stub_787(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+void GLAPIENTRY gl_dispatch_stub_788(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_789(GLenum target, GLuint index, GLsizei count, const GLfloat * params);
+void GLAPIENTRY gl_dispatch_stub_790(GLuint id, GLenum pname, GLint64EXT * params);
+void GLAPIENTRY gl_dispatch_stub_791(GLuint id, GLenum pname, GLuint64EXT * params);
+#endif /* defined(NEED_FUNCTION_POINTER) || defined(GLX_INDIRECT_RENDERING) */
+
+static const glprocs_table_t static_functions[] = {
+ NAME_FUNC_OFFSET( 0, glNewList, glNewList, NULL, _gloffset_NewList),
+ NAME_FUNC_OFFSET( 10, glEndList, glEndList, NULL, _gloffset_EndList),
+ NAME_FUNC_OFFSET( 20, glCallList, glCallList, NULL, _gloffset_CallList),
+ NAME_FUNC_OFFSET( 31, glCallLists, glCallLists, NULL, _gloffset_CallLists),
+ NAME_FUNC_OFFSET( 43, glDeleteLists, glDeleteLists, NULL, _gloffset_DeleteLists),
+ NAME_FUNC_OFFSET( 57, glGenLists, glGenLists, NULL, _gloffset_GenLists),
+ NAME_FUNC_OFFSET( 68, glListBase, glListBase, NULL, _gloffset_ListBase),
+ NAME_FUNC_OFFSET( 79, glBegin, glBegin, NULL, _gloffset_Begin),
+ NAME_FUNC_OFFSET( 87, glBitmap, glBitmap, NULL, _gloffset_Bitmap),
+ NAME_FUNC_OFFSET( 96, glColor3b, glColor3b, NULL, _gloffset_Color3b),
+ NAME_FUNC_OFFSET( 106, glColor3bv, glColor3bv, NULL, _gloffset_Color3bv),
+ NAME_FUNC_OFFSET( 117, glColor3d, glColor3d, NULL, _gloffset_Color3d),
+ NAME_FUNC_OFFSET( 127, glColor3dv, glColor3dv, NULL, _gloffset_Color3dv),
+ NAME_FUNC_OFFSET( 138, glColor3f, glColor3f, NULL, _gloffset_Color3f),
+ NAME_FUNC_OFFSET( 148, glColor3fv, glColor3fv, NULL, _gloffset_Color3fv),
+ NAME_FUNC_OFFSET( 159, glColor3i, glColor3i, NULL, _gloffset_Color3i),
+ NAME_FUNC_OFFSET( 169, glColor3iv, glColor3iv, NULL, _gloffset_Color3iv),
+ NAME_FUNC_OFFSET( 180, glColor3s, glColor3s, NULL, _gloffset_Color3s),
+ NAME_FUNC_OFFSET( 190, glColor3sv, glColor3sv, NULL, _gloffset_Color3sv),
+ NAME_FUNC_OFFSET( 201, glColor3ub, glColor3ub, NULL, _gloffset_Color3ub),
+ NAME_FUNC_OFFSET( 212, glColor3ubv, glColor3ubv, NULL, _gloffset_Color3ubv),
+ NAME_FUNC_OFFSET( 224, glColor3ui, glColor3ui, NULL, _gloffset_Color3ui),
+ NAME_FUNC_OFFSET( 235, glColor3uiv, glColor3uiv, NULL, _gloffset_Color3uiv),
+ NAME_FUNC_OFFSET( 247, glColor3us, glColor3us, NULL, _gloffset_Color3us),
+ NAME_FUNC_OFFSET( 258, glColor3usv, glColor3usv, NULL, _gloffset_Color3usv),
+ NAME_FUNC_OFFSET( 270, glColor4b, glColor4b, NULL, _gloffset_Color4b),
+ NAME_FUNC_OFFSET( 280, glColor4bv, glColor4bv, NULL, _gloffset_Color4bv),
+ NAME_FUNC_OFFSET( 291, glColor4d, glColor4d, NULL, _gloffset_Color4d),
+ NAME_FUNC_OFFSET( 301, glColor4dv, glColor4dv, NULL, _gloffset_Color4dv),
+ NAME_FUNC_OFFSET( 312, glColor4f, glColor4f, NULL, _gloffset_Color4f),
+ NAME_FUNC_OFFSET( 322, glColor4fv, glColor4fv, NULL, _gloffset_Color4fv),
+ NAME_FUNC_OFFSET( 333, glColor4i, glColor4i, NULL, _gloffset_Color4i),
+ NAME_FUNC_OFFSET( 343, glColor4iv, glColor4iv, NULL, _gloffset_Color4iv),
+ NAME_FUNC_OFFSET( 354, glColor4s, glColor4s, NULL, _gloffset_Color4s),
+ NAME_FUNC_OFFSET( 364, glColor4sv, glColor4sv, NULL, _gloffset_Color4sv),
+ NAME_FUNC_OFFSET( 375, glColor4ub, glColor4ub, NULL, _gloffset_Color4ub),
+ NAME_FUNC_OFFSET( 386, glColor4ubv, glColor4ubv, NULL, _gloffset_Color4ubv),
+ NAME_FUNC_OFFSET( 398, glColor4ui, glColor4ui, NULL, _gloffset_Color4ui),
+ NAME_FUNC_OFFSET( 409, glColor4uiv, glColor4uiv, NULL, _gloffset_Color4uiv),
+ NAME_FUNC_OFFSET( 421, glColor4us, glColor4us, NULL, _gloffset_Color4us),
+ NAME_FUNC_OFFSET( 432, glColor4usv, glColor4usv, NULL, _gloffset_Color4usv),
+ NAME_FUNC_OFFSET( 444, glEdgeFlag, glEdgeFlag, NULL, _gloffset_EdgeFlag),
+ NAME_FUNC_OFFSET( 455, glEdgeFlagv, glEdgeFlagv, NULL, _gloffset_EdgeFlagv),
+ NAME_FUNC_OFFSET( 467, glEnd, glEnd, NULL, _gloffset_End),
+ NAME_FUNC_OFFSET( 473, glIndexd, glIndexd, NULL, _gloffset_Indexd),
+ NAME_FUNC_OFFSET( 482, glIndexdv, glIndexdv, NULL, _gloffset_Indexdv),
+ NAME_FUNC_OFFSET( 492, glIndexf, glIndexf, NULL, _gloffset_Indexf),
+ NAME_FUNC_OFFSET( 501, glIndexfv, glIndexfv, NULL, _gloffset_Indexfv),
+ NAME_FUNC_OFFSET( 511, glIndexi, glIndexi, NULL, _gloffset_Indexi),
+ NAME_FUNC_OFFSET( 520, glIndexiv, glIndexiv, NULL, _gloffset_Indexiv),
+ NAME_FUNC_OFFSET( 530, glIndexs, glIndexs, NULL, _gloffset_Indexs),
+ NAME_FUNC_OFFSET( 539, glIndexsv, glIndexsv, NULL, _gloffset_Indexsv),
+ NAME_FUNC_OFFSET( 549, glNormal3b, glNormal3b, NULL, _gloffset_Normal3b),
+ NAME_FUNC_OFFSET( 560, glNormal3bv, glNormal3bv, NULL, _gloffset_Normal3bv),
+ NAME_FUNC_OFFSET( 572, glNormal3d, glNormal3d, NULL, _gloffset_Normal3d),
+ NAME_FUNC_OFFSET( 583, glNormal3dv, glNormal3dv, NULL, _gloffset_Normal3dv),
+ NAME_FUNC_OFFSET( 595, glNormal3f, glNormal3f, NULL, _gloffset_Normal3f),
+ NAME_FUNC_OFFSET( 606, glNormal3fv, glNormal3fv, NULL, _gloffset_Normal3fv),
+ NAME_FUNC_OFFSET( 618, glNormal3i, glNormal3i, NULL, _gloffset_Normal3i),
+ NAME_FUNC_OFFSET( 629, glNormal3iv, glNormal3iv, NULL, _gloffset_Normal3iv),
+ NAME_FUNC_OFFSET( 641, glNormal3s, glNormal3s, NULL, _gloffset_Normal3s),
+ NAME_FUNC_OFFSET( 652, glNormal3sv, glNormal3sv, NULL, _gloffset_Normal3sv),
+ NAME_FUNC_OFFSET( 664, glRasterPos2d, glRasterPos2d, NULL, _gloffset_RasterPos2d),
+ NAME_FUNC_OFFSET( 678, glRasterPos2dv, glRasterPos2dv, NULL, _gloffset_RasterPos2dv),
+ NAME_FUNC_OFFSET( 693, glRasterPos2f, glRasterPos2f, NULL, _gloffset_RasterPos2f),
+ NAME_FUNC_OFFSET( 707, glRasterPos2fv, glRasterPos2fv, NULL, _gloffset_RasterPos2fv),
+ NAME_FUNC_OFFSET( 722, glRasterPos2i, glRasterPos2i, NULL, _gloffset_RasterPos2i),
+ NAME_FUNC_OFFSET( 736, glRasterPos2iv, glRasterPos2iv, NULL, _gloffset_RasterPos2iv),
+ NAME_FUNC_OFFSET( 751, glRasterPos2s, glRasterPos2s, NULL, _gloffset_RasterPos2s),
+ NAME_FUNC_OFFSET( 765, glRasterPos2sv, glRasterPos2sv, NULL, _gloffset_RasterPos2sv),
+ NAME_FUNC_OFFSET( 780, glRasterPos3d, glRasterPos3d, NULL, _gloffset_RasterPos3d),
+ NAME_FUNC_OFFSET( 794, glRasterPos3dv, glRasterPos3dv, NULL, _gloffset_RasterPos3dv),
+ NAME_FUNC_OFFSET( 809, glRasterPos3f, glRasterPos3f, NULL, _gloffset_RasterPos3f),
+ NAME_FUNC_OFFSET( 823, glRasterPos3fv, glRasterPos3fv, NULL, _gloffset_RasterPos3fv),
+ NAME_FUNC_OFFSET( 838, glRasterPos3i, glRasterPos3i, NULL, _gloffset_RasterPos3i),
+ NAME_FUNC_OFFSET( 852, glRasterPos3iv, glRasterPos3iv, NULL, _gloffset_RasterPos3iv),
+ NAME_FUNC_OFFSET( 867, glRasterPos3s, glRasterPos3s, NULL, _gloffset_RasterPos3s),
+ NAME_FUNC_OFFSET( 881, glRasterPos3sv, glRasterPos3sv, NULL, _gloffset_RasterPos3sv),
+ NAME_FUNC_OFFSET( 896, glRasterPos4d, glRasterPos4d, NULL, _gloffset_RasterPos4d),
+ NAME_FUNC_OFFSET( 910, glRasterPos4dv, glRasterPos4dv, NULL, _gloffset_RasterPos4dv),
+ NAME_FUNC_OFFSET( 925, glRasterPos4f, glRasterPos4f, NULL, _gloffset_RasterPos4f),
+ NAME_FUNC_OFFSET( 939, glRasterPos4fv, glRasterPos4fv, NULL, _gloffset_RasterPos4fv),
+ NAME_FUNC_OFFSET( 954, glRasterPos4i, glRasterPos4i, NULL, _gloffset_RasterPos4i),
+ NAME_FUNC_OFFSET( 968, glRasterPos4iv, glRasterPos4iv, NULL, _gloffset_RasterPos4iv),
+ NAME_FUNC_OFFSET( 983, glRasterPos4s, glRasterPos4s, NULL, _gloffset_RasterPos4s),
+ NAME_FUNC_OFFSET( 997, glRasterPos4sv, glRasterPos4sv, NULL, _gloffset_RasterPos4sv),
+ NAME_FUNC_OFFSET( 1012, glRectd, glRectd, NULL, _gloffset_Rectd),
+ NAME_FUNC_OFFSET( 1020, glRectdv, glRectdv, NULL, _gloffset_Rectdv),
+ NAME_FUNC_OFFSET( 1029, glRectf, glRectf, NULL, _gloffset_Rectf),
+ NAME_FUNC_OFFSET( 1037, glRectfv, glRectfv, NULL, _gloffset_Rectfv),
+ NAME_FUNC_OFFSET( 1046, glRecti, glRecti, NULL, _gloffset_Recti),
+ NAME_FUNC_OFFSET( 1054, glRectiv, glRectiv, NULL, _gloffset_Rectiv),
+ NAME_FUNC_OFFSET( 1063, glRects, glRects, NULL, _gloffset_Rects),
+ NAME_FUNC_OFFSET( 1071, glRectsv, glRectsv, NULL, _gloffset_Rectsv),
+ NAME_FUNC_OFFSET( 1080, glTexCoord1d, glTexCoord1d, NULL, _gloffset_TexCoord1d),
+ NAME_FUNC_OFFSET( 1093, glTexCoord1dv, glTexCoord1dv, NULL, _gloffset_TexCoord1dv),
+ NAME_FUNC_OFFSET( 1107, glTexCoord1f, glTexCoord1f, NULL, _gloffset_TexCoord1f),
+ NAME_FUNC_OFFSET( 1120, glTexCoord1fv, glTexCoord1fv, NULL, _gloffset_TexCoord1fv),
+ NAME_FUNC_OFFSET( 1134, glTexCoord1i, glTexCoord1i, NULL, _gloffset_TexCoord1i),
+ NAME_FUNC_OFFSET( 1147, glTexCoord1iv, glTexCoord1iv, NULL, _gloffset_TexCoord1iv),
+ NAME_FUNC_OFFSET( 1161, glTexCoord1s, glTexCoord1s, NULL, _gloffset_TexCoord1s),
+ NAME_FUNC_OFFSET( 1174, glTexCoord1sv, glTexCoord1sv, NULL, _gloffset_TexCoord1sv),
+ NAME_FUNC_OFFSET( 1188, glTexCoord2d, glTexCoord2d, NULL, _gloffset_TexCoord2d),
+ NAME_FUNC_OFFSET( 1201, glTexCoord2dv, glTexCoord2dv, NULL, _gloffset_TexCoord2dv),
+ NAME_FUNC_OFFSET( 1215, glTexCoord2f, glTexCoord2f, NULL, _gloffset_TexCoord2f),
+ NAME_FUNC_OFFSET( 1228, glTexCoord2fv, glTexCoord2fv, NULL, _gloffset_TexCoord2fv),
+ NAME_FUNC_OFFSET( 1242, glTexCoord2i, glTexCoord2i, NULL, _gloffset_TexCoord2i),
+ NAME_FUNC_OFFSET( 1255, glTexCoord2iv, glTexCoord2iv, NULL, _gloffset_TexCoord2iv),
+ NAME_FUNC_OFFSET( 1269, glTexCoord2s, glTexCoord2s, NULL, _gloffset_TexCoord2s),
+ NAME_FUNC_OFFSET( 1282, glTexCoord2sv, glTexCoord2sv, NULL, _gloffset_TexCoord2sv),
+ NAME_FUNC_OFFSET( 1296, glTexCoord3d, glTexCoord3d, NULL, _gloffset_TexCoord3d),
+ NAME_FUNC_OFFSET( 1309, glTexCoord3dv, glTexCoord3dv, NULL, _gloffset_TexCoord3dv),
+ NAME_FUNC_OFFSET( 1323, glTexCoord3f, glTexCoord3f, NULL, _gloffset_TexCoord3f),
+ NAME_FUNC_OFFSET( 1336, glTexCoord3fv, glTexCoord3fv, NULL, _gloffset_TexCoord3fv),
+ NAME_FUNC_OFFSET( 1350, glTexCoord3i, glTexCoord3i, NULL, _gloffset_TexCoord3i),
+ NAME_FUNC_OFFSET( 1363, glTexCoord3iv, glTexCoord3iv, NULL, _gloffset_TexCoord3iv),
+ NAME_FUNC_OFFSET( 1377, glTexCoord3s, glTexCoord3s, NULL, _gloffset_TexCoord3s),
+ NAME_FUNC_OFFSET( 1390, glTexCoord3sv, glTexCoord3sv, NULL, _gloffset_TexCoord3sv),
+ NAME_FUNC_OFFSET( 1404, glTexCoord4d, glTexCoord4d, NULL, _gloffset_TexCoord4d),
+ NAME_FUNC_OFFSET( 1417, glTexCoord4dv, glTexCoord4dv, NULL, _gloffset_TexCoord4dv),
+ NAME_FUNC_OFFSET( 1431, glTexCoord4f, glTexCoord4f, NULL, _gloffset_TexCoord4f),
+ NAME_FUNC_OFFSET( 1444, glTexCoord4fv, glTexCoord4fv, NULL, _gloffset_TexCoord4fv),
+ NAME_FUNC_OFFSET( 1458, glTexCoord4i, glTexCoord4i, NULL, _gloffset_TexCoord4i),
+ NAME_FUNC_OFFSET( 1471, glTexCoord4iv, glTexCoord4iv, NULL, _gloffset_TexCoord4iv),
+ NAME_FUNC_OFFSET( 1485, glTexCoord4s, glTexCoord4s, NULL, _gloffset_TexCoord4s),
+ NAME_FUNC_OFFSET( 1498, glTexCoord4sv, glTexCoord4sv, NULL, _gloffset_TexCoord4sv),
+ NAME_FUNC_OFFSET( 1512, glVertex2d, glVertex2d, NULL, _gloffset_Vertex2d),
+ NAME_FUNC_OFFSET( 1523, glVertex2dv, glVertex2dv, NULL, _gloffset_Vertex2dv),
+ NAME_FUNC_OFFSET( 1535, glVertex2f, glVertex2f, NULL, _gloffset_Vertex2f),
+ NAME_FUNC_OFFSET( 1546, glVertex2fv, glVertex2fv, NULL, _gloffset_Vertex2fv),
+ NAME_FUNC_OFFSET( 1558, glVertex2i, glVertex2i, NULL, _gloffset_Vertex2i),
+ NAME_FUNC_OFFSET( 1569, glVertex2iv, glVertex2iv, NULL, _gloffset_Vertex2iv),
+ NAME_FUNC_OFFSET( 1581, glVertex2s, glVertex2s, NULL, _gloffset_Vertex2s),
+ NAME_FUNC_OFFSET( 1592, glVertex2sv, glVertex2sv, NULL, _gloffset_Vertex2sv),
+ NAME_FUNC_OFFSET( 1604, glVertex3d, glVertex3d, NULL, _gloffset_Vertex3d),
+ NAME_FUNC_OFFSET( 1615, glVertex3dv, glVertex3dv, NULL, _gloffset_Vertex3dv),
+ NAME_FUNC_OFFSET( 1627, glVertex3f, glVertex3f, NULL, _gloffset_Vertex3f),
+ NAME_FUNC_OFFSET( 1638, glVertex3fv, glVertex3fv, NULL, _gloffset_Vertex3fv),
+ NAME_FUNC_OFFSET( 1650, glVertex3i, glVertex3i, NULL, _gloffset_Vertex3i),
+ NAME_FUNC_OFFSET( 1661, glVertex3iv, glVertex3iv, NULL, _gloffset_Vertex3iv),
+ NAME_FUNC_OFFSET( 1673, glVertex3s, glVertex3s, NULL, _gloffset_Vertex3s),
+ NAME_FUNC_OFFSET( 1684, glVertex3sv, glVertex3sv, NULL, _gloffset_Vertex3sv),
+ NAME_FUNC_OFFSET( 1696, glVertex4d, glVertex4d, NULL, _gloffset_Vertex4d),
+ NAME_FUNC_OFFSET( 1707, glVertex4dv, glVertex4dv, NULL, _gloffset_Vertex4dv),
+ NAME_FUNC_OFFSET( 1719, glVertex4f, glVertex4f, NULL, _gloffset_Vertex4f),
+ NAME_FUNC_OFFSET( 1730, glVertex4fv, glVertex4fv, NULL, _gloffset_Vertex4fv),
+ NAME_FUNC_OFFSET( 1742, glVertex4i, glVertex4i, NULL, _gloffset_Vertex4i),
+ NAME_FUNC_OFFSET( 1753, glVertex4iv, glVertex4iv, NULL, _gloffset_Vertex4iv),
+ NAME_FUNC_OFFSET( 1765, glVertex4s, glVertex4s, NULL, _gloffset_Vertex4s),
+ NAME_FUNC_OFFSET( 1776, glVertex4sv, glVertex4sv, NULL, _gloffset_Vertex4sv),
+ NAME_FUNC_OFFSET( 1788, glClipPlane, glClipPlane, NULL, _gloffset_ClipPlane),
+ NAME_FUNC_OFFSET( 1800, glColorMaterial, glColorMaterial, NULL, _gloffset_ColorMaterial),
+ NAME_FUNC_OFFSET( 1816, glCullFace, glCullFace, NULL, _gloffset_CullFace),
+ NAME_FUNC_OFFSET( 1827, glFogf, glFogf, NULL, _gloffset_Fogf),
+ NAME_FUNC_OFFSET( 1834, glFogfv, glFogfv, NULL, _gloffset_Fogfv),
+ NAME_FUNC_OFFSET( 1842, glFogi, glFogi, NULL, _gloffset_Fogi),
+ NAME_FUNC_OFFSET( 1849, glFogiv, glFogiv, NULL, _gloffset_Fogiv),
+ NAME_FUNC_OFFSET( 1857, glFrontFace, glFrontFace, NULL, _gloffset_FrontFace),
+ NAME_FUNC_OFFSET( 1869, glHint, glHint, NULL, _gloffset_Hint),
+ NAME_FUNC_OFFSET( 1876, glLightf, glLightf, NULL, _gloffset_Lightf),
+ NAME_FUNC_OFFSET( 1885, glLightfv, glLightfv, NULL, _gloffset_Lightfv),
+ NAME_FUNC_OFFSET( 1895, glLighti, glLighti, NULL, _gloffset_Lighti),
+ NAME_FUNC_OFFSET( 1904, glLightiv, glLightiv, NULL, _gloffset_Lightiv),
+ NAME_FUNC_OFFSET( 1914, glLightModelf, glLightModelf, NULL, _gloffset_LightModelf),
+ NAME_FUNC_OFFSET( 1928, glLightModelfv, glLightModelfv, NULL, _gloffset_LightModelfv),
+ NAME_FUNC_OFFSET( 1943, glLightModeli, glLightModeli, NULL, _gloffset_LightModeli),
+ NAME_FUNC_OFFSET( 1957, glLightModeliv, glLightModeliv, NULL, _gloffset_LightModeliv),
+ NAME_FUNC_OFFSET( 1972, glLineStipple, glLineStipple, NULL, _gloffset_LineStipple),
+ NAME_FUNC_OFFSET( 1986, glLineWidth, glLineWidth, NULL, _gloffset_LineWidth),
+ NAME_FUNC_OFFSET( 1998, glMaterialf, glMaterialf, NULL, _gloffset_Materialf),
+ NAME_FUNC_OFFSET( 2010, glMaterialfv, glMaterialfv, NULL, _gloffset_Materialfv),
+ NAME_FUNC_OFFSET( 2023, glMateriali, glMateriali, NULL, _gloffset_Materiali),
+ NAME_FUNC_OFFSET( 2035, glMaterialiv, glMaterialiv, NULL, _gloffset_Materialiv),
+ NAME_FUNC_OFFSET( 2048, glPointSize, glPointSize, NULL, _gloffset_PointSize),
+ NAME_FUNC_OFFSET( 2060, glPolygonMode, glPolygonMode, NULL, _gloffset_PolygonMode),
+ NAME_FUNC_OFFSET( 2074, glPolygonStipple, glPolygonStipple, NULL, _gloffset_PolygonStipple),
+ NAME_FUNC_OFFSET( 2091, glScissor, glScissor, NULL, _gloffset_Scissor),
+ NAME_FUNC_OFFSET( 2101, glShadeModel, glShadeModel, NULL, _gloffset_ShadeModel),
+ NAME_FUNC_OFFSET( 2114, glTexParameterf, glTexParameterf, NULL, _gloffset_TexParameterf),
+ NAME_FUNC_OFFSET( 2130, glTexParameterfv, glTexParameterfv, NULL, _gloffset_TexParameterfv),
+ NAME_FUNC_OFFSET( 2147, glTexParameteri, glTexParameteri, NULL, _gloffset_TexParameteri),
+ NAME_FUNC_OFFSET( 2163, glTexParameteriv, glTexParameteriv, NULL, _gloffset_TexParameteriv),
+ NAME_FUNC_OFFSET( 2180, glTexImage1D, glTexImage1D, NULL, _gloffset_TexImage1D),
+ NAME_FUNC_OFFSET( 2193, glTexImage2D, glTexImage2D, NULL, _gloffset_TexImage2D),
+ NAME_FUNC_OFFSET( 2206, glTexEnvf, glTexEnvf, NULL, _gloffset_TexEnvf),
+ NAME_FUNC_OFFSET( 2216, glTexEnvfv, glTexEnvfv, NULL, _gloffset_TexEnvfv),
+ NAME_FUNC_OFFSET( 2227, glTexEnvi, glTexEnvi, NULL, _gloffset_TexEnvi),
+ NAME_FUNC_OFFSET( 2237, glTexEnviv, glTexEnviv, NULL, _gloffset_TexEnviv),
+ NAME_FUNC_OFFSET( 2248, glTexGend, glTexGend, NULL, _gloffset_TexGend),
+ NAME_FUNC_OFFSET( 2258, glTexGendv, glTexGendv, NULL, _gloffset_TexGendv),
+ NAME_FUNC_OFFSET( 2269, glTexGenf, glTexGenf, NULL, _gloffset_TexGenf),
+ NAME_FUNC_OFFSET( 2279, glTexGenfv, glTexGenfv, NULL, _gloffset_TexGenfv),
+ NAME_FUNC_OFFSET( 2290, glTexGeni, glTexGeni, NULL, _gloffset_TexGeni),
+ NAME_FUNC_OFFSET( 2300, glTexGeniv, glTexGeniv, NULL, _gloffset_TexGeniv),
+ NAME_FUNC_OFFSET( 2311, glFeedbackBuffer, glFeedbackBuffer, NULL, _gloffset_FeedbackBuffer),
+ NAME_FUNC_OFFSET( 2328, glSelectBuffer, glSelectBuffer, NULL, _gloffset_SelectBuffer),
+ NAME_FUNC_OFFSET( 2343, glRenderMode, glRenderMode, NULL, _gloffset_RenderMode),
+ NAME_FUNC_OFFSET( 2356, glInitNames, glInitNames, NULL, _gloffset_InitNames),
+ NAME_FUNC_OFFSET( 2368, glLoadName, glLoadName, NULL, _gloffset_LoadName),
+ NAME_FUNC_OFFSET( 2379, glPassThrough, glPassThrough, NULL, _gloffset_PassThrough),
+ NAME_FUNC_OFFSET( 2393, glPopName, glPopName, NULL, _gloffset_PopName),
+ NAME_FUNC_OFFSET( 2403, glPushName, glPushName, NULL, _gloffset_PushName),
+ NAME_FUNC_OFFSET( 2414, glDrawBuffer, glDrawBuffer, NULL, _gloffset_DrawBuffer),
+ NAME_FUNC_OFFSET( 2427, glClear, glClear, NULL, _gloffset_Clear),
+ NAME_FUNC_OFFSET( 2435, glClearAccum, glClearAccum, NULL, _gloffset_ClearAccum),
+ NAME_FUNC_OFFSET( 2448, glClearIndex, glClearIndex, NULL, _gloffset_ClearIndex),
+ NAME_FUNC_OFFSET( 2461, glClearColor, glClearColor, NULL, _gloffset_ClearColor),
+ NAME_FUNC_OFFSET( 2474, glClearStencil, glClearStencil, NULL, _gloffset_ClearStencil),
+ NAME_FUNC_OFFSET( 2489, glClearDepth, glClearDepth, NULL, _gloffset_ClearDepth),
+ NAME_FUNC_OFFSET( 2502, glStencilMask, glStencilMask, NULL, _gloffset_StencilMask),
+ NAME_FUNC_OFFSET( 2516, glColorMask, glColorMask, NULL, _gloffset_ColorMask),
+ NAME_FUNC_OFFSET( 2528, glDepthMask, glDepthMask, NULL, _gloffset_DepthMask),
+ NAME_FUNC_OFFSET( 2540, glIndexMask, glIndexMask, NULL, _gloffset_IndexMask),
+ NAME_FUNC_OFFSET( 2552, glAccum, glAccum, NULL, _gloffset_Accum),
+ NAME_FUNC_OFFSET( 2560, glDisable, glDisable, NULL, _gloffset_Disable),
+ NAME_FUNC_OFFSET( 2570, glEnable, glEnable, NULL, _gloffset_Enable),
+ NAME_FUNC_OFFSET( 2579, glFinish, glFinish, NULL, _gloffset_Finish),
+ NAME_FUNC_OFFSET( 2588, glFlush, glFlush, NULL, _gloffset_Flush),
+ NAME_FUNC_OFFSET( 2596, glPopAttrib, glPopAttrib, NULL, _gloffset_PopAttrib),
+ NAME_FUNC_OFFSET( 2608, glPushAttrib, glPushAttrib, NULL, _gloffset_PushAttrib),
+ NAME_FUNC_OFFSET( 2621, glMap1d, glMap1d, NULL, _gloffset_Map1d),
+ NAME_FUNC_OFFSET( 2629, glMap1f, glMap1f, NULL, _gloffset_Map1f),
+ NAME_FUNC_OFFSET( 2637, glMap2d, glMap2d, NULL, _gloffset_Map2d),
+ NAME_FUNC_OFFSET( 2645, glMap2f, glMap2f, NULL, _gloffset_Map2f),
+ NAME_FUNC_OFFSET( 2653, glMapGrid1d, glMapGrid1d, NULL, _gloffset_MapGrid1d),
+ NAME_FUNC_OFFSET( 2665, glMapGrid1f, glMapGrid1f, NULL, _gloffset_MapGrid1f),
+ NAME_FUNC_OFFSET( 2677, glMapGrid2d, glMapGrid2d, NULL, _gloffset_MapGrid2d),
+ NAME_FUNC_OFFSET( 2689, glMapGrid2f, glMapGrid2f, NULL, _gloffset_MapGrid2f),
+ NAME_FUNC_OFFSET( 2701, glEvalCoord1d, glEvalCoord1d, NULL, _gloffset_EvalCoord1d),
+ NAME_FUNC_OFFSET( 2715, glEvalCoord1dv, glEvalCoord1dv, NULL, _gloffset_EvalCoord1dv),
+ NAME_FUNC_OFFSET( 2730, glEvalCoord1f, glEvalCoord1f, NULL, _gloffset_EvalCoord1f),
+ NAME_FUNC_OFFSET( 2744, glEvalCoord1fv, glEvalCoord1fv, NULL, _gloffset_EvalCoord1fv),
+ NAME_FUNC_OFFSET( 2759, glEvalCoord2d, glEvalCoord2d, NULL, _gloffset_EvalCoord2d),
+ NAME_FUNC_OFFSET( 2773, glEvalCoord2dv, glEvalCoord2dv, NULL, _gloffset_EvalCoord2dv),
+ NAME_FUNC_OFFSET( 2788, glEvalCoord2f, glEvalCoord2f, NULL, _gloffset_EvalCoord2f),
+ NAME_FUNC_OFFSET( 2802, glEvalCoord2fv, glEvalCoord2fv, NULL, _gloffset_EvalCoord2fv),
+ NAME_FUNC_OFFSET( 2817, glEvalMesh1, glEvalMesh1, NULL, _gloffset_EvalMesh1),
+ NAME_FUNC_OFFSET( 2829, glEvalPoint1, glEvalPoint1, NULL, _gloffset_EvalPoint1),
+ NAME_FUNC_OFFSET( 2842, glEvalMesh2, glEvalMesh2, NULL, _gloffset_EvalMesh2),
+ NAME_FUNC_OFFSET( 2854, glEvalPoint2, glEvalPoint2, NULL, _gloffset_EvalPoint2),
+ NAME_FUNC_OFFSET( 2867, glAlphaFunc, glAlphaFunc, NULL, _gloffset_AlphaFunc),
+ NAME_FUNC_OFFSET( 2879, glBlendFunc, glBlendFunc, NULL, _gloffset_BlendFunc),
+ NAME_FUNC_OFFSET( 2891, glLogicOp, glLogicOp, NULL, _gloffset_LogicOp),
+ NAME_FUNC_OFFSET( 2901, glStencilFunc, glStencilFunc, NULL, _gloffset_StencilFunc),
+ NAME_FUNC_OFFSET( 2915, glStencilOp, glStencilOp, NULL, _gloffset_StencilOp),
+ NAME_FUNC_OFFSET( 2927, glDepthFunc, glDepthFunc, NULL, _gloffset_DepthFunc),
+ NAME_FUNC_OFFSET( 2939, glPixelZoom, glPixelZoom, NULL, _gloffset_PixelZoom),
+ NAME_FUNC_OFFSET( 2951, glPixelTransferf, glPixelTransferf, NULL, _gloffset_PixelTransferf),
+ NAME_FUNC_OFFSET( 2968, glPixelTransferi, glPixelTransferi, NULL, _gloffset_PixelTransferi),
+ NAME_FUNC_OFFSET( 2985, glPixelStoref, glPixelStoref, NULL, _gloffset_PixelStoref),
+ NAME_FUNC_OFFSET( 2999, glPixelStorei, glPixelStorei, NULL, _gloffset_PixelStorei),
+ NAME_FUNC_OFFSET( 3013, glPixelMapfv, glPixelMapfv, NULL, _gloffset_PixelMapfv),
+ NAME_FUNC_OFFSET( 3026, glPixelMapuiv, glPixelMapuiv, NULL, _gloffset_PixelMapuiv),
+ NAME_FUNC_OFFSET( 3040, glPixelMapusv, glPixelMapusv, NULL, _gloffset_PixelMapusv),
+ NAME_FUNC_OFFSET( 3054, glReadBuffer, glReadBuffer, NULL, _gloffset_ReadBuffer),
+ NAME_FUNC_OFFSET( 3067, glCopyPixels, glCopyPixels, NULL, _gloffset_CopyPixels),
+ NAME_FUNC_OFFSET( 3080, glReadPixels, glReadPixels, NULL, _gloffset_ReadPixels),
+ NAME_FUNC_OFFSET( 3093, glDrawPixels, glDrawPixels, NULL, _gloffset_DrawPixels),
+ NAME_FUNC_OFFSET( 3106, glGetBooleanv, glGetBooleanv, NULL, _gloffset_GetBooleanv),
+ NAME_FUNC_OFFSET( 3120, glGetClipPlane, glGetClipPlane, NULL, _gloffset_GetClipPlane),
+ NAME_FUNC_OFFSET( 3135, glGetDoublev, glGetDoublev, NULL, _gloffset_GetDoublev),
+ NAME_FUNC_OFFSET( 3148, glGetError, glGetError, NULL, _gloffset_GetError),
+ NAME_FUNC_OFFSET( 3159, glGetFloatv, glGetFloatv, NULL, _gloffset_GetFloatv),
+ NAME_FUNC_OFFSET( 3171, glGetIntegerv, glGetIntegerv, NULL, _gloffset_GetIntegerv),
+ NAME_FUNC_OFFSET( 3185, glGetLightfv, glGetLightfv, NULL, _gloffset_GetLightfv),
+ NAME_FUNC_OFFSET( 3198, glGetLightiv, glGetLightiv, NULL, _gloffset_GetLightiv),
+ NAME_FUNC_OFFSET( 3211, glGetMapdv, glGetMapdv, NULL, _gloffset_GetMapdv),
+ NAME_FUNC_OFFSET( 3222, glGetMapfv, glGetMapfv, NULL, _gloffset_GetMapfv),
+ NAME_FUNC_OFFSET( 3233, glGetMapiv, glGetMapiv, NULL, _gloffset_GetMapiv),
+ NAME_FUNC_OFFSET( 3244, glGetMaterialfv, glGetMaterialfv, NULL, _gloffset_GetMaterialfv),
+ NAME_FUNC_OFFSET( 3260, glGetMaterialiv, glGetMaterialiv, NULL, _gloffset_GetMaterialiv),
+ NAME_FUNC_OFFSET( 3276, glGetPixelMapfv, glGetPixelMapfv, NULL, _gloffset_GetPixelMapfv),
+ NAME_FUNC_OFFSET( 3292, glGetPixelMapuiv, glGetPixelMapuiv, NULL, _gloffset_GetPixelMapuiv),
+ NAME_FUNC_OFFSET( 3309, glGetPixelMapusv, glGetPixelMapusv, NULL, _gloffset_GetPixelMapusv),
+ NAME_FUNC_OFFSET( 3326, glGetPolygonStipple, glGetPolygonStipple, NULL, _gloffset_GetPolygonStipple),
+ NAME_FUNC_OFFSET( 3346, glGetString, glGetString, NULL, _gloffset_GetString),
+ NAME_FUNC_OFFSET( 3358, glGetTexEnvfv, glGetTexEnvfv, NULL, _gloffset_GetTexEnvfv),
+ NAME_FUNC_OFFSET( 3372, glGetTexEnviv, glGetTexEnviv, NULL, _gloffset_GetTexEnviv),
+ NAME_FUNC_OFFSET( 3386, glGetTexGendv, glGetTexGendv, NULL, _gloffset_GetTexGendv),
+ NAME_FUNC_OFFSET( 3400, glGetTexGenfv, glGetTexGenfv, NULL, _gloffset_GetTexGenfv),
+ NAME_FUNC_OFFSET( 3414, glGetTexGeniv, glGetTexGeniv, NULL, _gloffset_GetTexGeniv),
+ NAME_FUNC_OFFSET( 3428, glGetTexImage, glGetTexImage, NULL, _gloffset_GetTexImage),
+ NAME_FUNC_OFFSET( 3442, glGetTexParameterfv, glGetTexParameterfv, NULL, _gloffset_GetTexParameterfv),
+ NAME_FUNC_OFFSET( 3462, glGetTexParameteriv, glGetTexParameteriv, NULL, _gloffset_GetTexParameteriv),
+ NAME_FUNC_OFFSET( 3482, glGetTexLevelParameterfv, glGetTexLevelParameterfv, NULL, _gloffset_GetTexLevelParameterfv),
+ NAME_FUNC_OFFSET( 3507, glGetTexLevelParameteriv, glGetTexLevelParameteriv, NULL, _gloffset_GetTexLevelParameteriv),
+ NAME_FUNC_OFFSET( 3532, glIsEnabled, glIsEnabled, NULL, _gloffset_IsEnabled),
+ NAME_FUNC_OFFSET( 3544, glIsList, glIsList, NULL, _gloffset_IsList),
+ NAME_FUNC_OFFSET( 3553, glDepthRange, glDepthRange, NULL, _gloffset_DepthRange),
+ NAME_FUNC_OFFSET( 3566, glFrustum, glFrustum, NULL, _gloffset_Frustum),
+ NAME_FUNC_OFFSET( 3576, glLoadIdentity, glLoadIdentity, NULL, _gloffset_LoadIdentity),
+ NAME_FUNC_OFFSET( 3591, glLoadMatrixf, glLoadMatrixf, NULL, _gloffset_LoadMatrixf),
+ NAME_FUNC_OFFSET( 3605, glLoadMatrixd, glLoadMatrixd, NULL, _gloffset_LoadMatrixd),
+ NAME_FUNC_OFFSET( 3619, glMatrixMode, glMatrixMode, NULL, _gloffset_MatrixMode),
+ NAME_FUNC_OFFSET( 3632, glMultMatrixf, glMultMatrixf, NULL, _gloffset_MultMatrixf),
+ NAME_FUNC_OFFSET( 3646, glMultMatrixd, glMultMatrixd, NULL, _gloffset_MultMatrixd),
+ NAME_FUNC_OFFSET( 3660, glOrtho, glOrtho, NULL, _gloffset_Ortho),
+ NAME_FUNC_OFFSET( 3668, glPopMatrix, glPopMatrix, NULL, _gloffset_PopMatrix),
+ NAME_FUNC_OFFSET( 3680, glPushMatrix, glPushMatrix, NULL, _gloffset_PushMatrix),
+ NAME_FUNC_OFFSET( 3693, glRotated, glRotated, NULL, _gloffset_Rotated),
+ NAME_FUNC_OFFSET( 3703, glRotatef, glRotatef, NULL, _gloffset_Rotatef),
+ NAME_FUNC_OFFSET( 3713, glScaled, glScaled, NULL, _gloffset_Scaled),
+ NAME_FUNC_OFFSET( 3722, glScalef, glScalef, NULL, _gloffset_Scalef),
+ NAME_FUNC_OFFSET( 3731, glTranslated, glTranslated, NULL, _gloffset_Translated),
+ NAME_FUNC_OFFSET( 3744, glTranslatef, glTranslatef, NULL, _gloffset_Translatef),
+ NAME_FUNC_OFFSET( 3757, glViewport, glViewport, NULL, _gloffset_Viewport),
+ NAME_FUNC_OFFSET( 3768, glArrayElement, glArrayElement, NULL, _gloffset_ArrayElement),
+ NAME_FUNC_OFFSET( 3783, glBindTexture, glBindTexture, NULL, _gloffset_BindTexture),
+ NAME_FUNC_OFFSET( 3797, glColorPointer, glColorPointer, NULL, _gloffset_ColorPointer),
+ NAME_FUNC_OFFSET( 3812, glDisableClientState, glDisableClientState, NULL, _gloffset_DisableClientState),
+ NAME_FUNC_OFFSET( 3833, glDrawArrays, glDrawArrays, NULL, _gloffset_DrawArrays),
+ NAME_FUNC_OFFSET( 3846, glDrawElements, glDrawElements, NULL, _gloffset_DrawElements),
+ NAME_FUNC_OFFSET( 3861, glEdgeFlagPointer, glEdgeFlagPointer, NULL, _gloffset_EdgeFlagPointer),
+ NAME_FUNC_OFFSET( 3879, glEnableClientState, glEnableClientState, NULL, _gloffset_EnableClientState),
+ NAME_FUNC_OFFSET( 3899, glIndexPointer, glIndexPointer, NULL, _gloffset_IndexPointer),
+ NAME_FUNC_OFFSET( 3914, glIndexub, glIndexub, NULL, _gloffset_Indexub),
+ NAME_FUNC_OFFSET( 3924, glIndexubv, glIndexubv, NULL, _gloffset_Indexubv),
+ NAME_FUNC_OFFSET( 3935, glInterleavedArrays, glInterleavedArrays, NULL, _gloffset_InterleavedArrays),
+ NAME_FUNC_OFFSET( 3955, glNormalPointer, glNormalPointer, NULL, _gloffset_NormalPointer),
+ NAME_FUNC_OFFSET( 3971, glPolygonOffset, glPolygonOffset, NULL, _gloffset_PolygonOffset),
+ NAME_FUNC_OFFSET( 3987, glTexCoordPointer, glTexCoordPointer, NULL, _gloffset_TexCoordPointer),
+ NAME_FUNC_OFFSET( 4005, glVertexPointer, glVertexPointer, NULL, _gloffset_VertexPointer),
+ NAME_FUNC_OFFSET( 4021, glAreTexturesResident, glAreTexturesResident, NULL, _gloffset_AreTexturesResident),
+ NAME_FUNC_OFFSET( 4043, glCopyTexImage1D, glCopyTexImage1D, NULL, _gloffset_CopyTexImage1D),
+ NAME_FUNC_OFFSET( 4060, glCopyTexImage2D, glCopyTexImage2D, NULL, _gloffset_CopyTexImage2D),
+ NAME_FUNC_OFFSET( 4077, glCopyTexSubImage1D, glCopyTexSubImage1D, NULL, _gloffset_CopyTexSubImage1D),
+ NAME_FUNC_OFFSET( 4097, glCopyTexSubImage2D, glCopyTexSubImage2D, NULL, _gloffset_CopyTexSubImage2D),
+ NAME_FUNC_OFFSET( 4117, glDeleteTextures, glDeleteTextures, NULL, _gloffset_DeleteTextures),
+ NAME_FUNC_OFFSET( 4134, glGenTextures, glGenTextures, NULL, _gloffset_GenTextures),
+ NAME_FUNC_OFFSET( 4148, glGetPointerv, glGetPointerv, NULL, _gloffset_GetPointerv),
+ NAME_FUNC_OFFSET( 4162, glIsTexture, glIsTexture, NULL, _gloffset_IsTexture),
+ NAME_FUNC_OFFSET( 4174, glPrioritizeTextures, glPrioritizeTextures, NULL, _gloffset_PrioritizeTextures),
+ NAME_FUNC_OFFSET( 4195, glTexSubImage1D, glTexSubImage1D, NULL, _gloffset_TexSubImage1D),
+ NAME_FUNC_OFFSET( 4211, glTexSubImage2D, glTexSubImage2D, NULL, _gloffset_TexSubImage2D),
+ NAME_FUNC_OFFSET( 4227, glPopClientAttrib, glPopClientAttrib, NULL, _gloffset_PopClientAttrib),
+ NAME_FUNC_OFFSET( 4245, glPushClientAttrib, glPushClientAttrib, NULL, _gloffset_PushClientAttrib),
+ NAME_FUNC_OFFSET( 4264, glBlendColor, glBlendColor, NULL, _gloffset_BlendColor),
+ NAME_FUNC_OFFSET( 4277, glBlendEquation, glBlendEquation, NULL, _gloffset_BlendEquation),
+ NAME_FUNC_OFFSET( 4293, glDrawRangeElements, glDrawRangeElements, NULL, _gloffset_DrawRangeElements),
+ NAME_FUNC_OFFSET( 4313, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
+ NAME_FUNC_OFFSET( 4326, glColorTableParameterfv, glColorTableParameterfv, NULL, _gloffset_ColorTableParameterfv),
+ NAME_FUNC_OFFSET( 4350, glColorTableParameteriv, glColorTableParameteriv, NULL, _gloffset_ColorTableParameteriv),
+ NAME_FUNC_OFFSET( 4374, glCopyColorTable, glCopyColorTable, NULL, _gloffset_CopyColorTable),
+ NAME_FUNC_OFFSET( 4391, glGetColorTable, glGetColorTable, NULL, _gloffset_GetColorTable),
+ NAME_FUNC_OFFSET( 4407, glGetColorTableParameterfv, glGetColorTableParameterfv, NULL, _gloffset_GetColorTableParameterfv),
+ NAME_FUNC_OFFSET( 4434, glGetColorTableParameteriv, glGetColorTableParameteriv, NULL, _gloffset_GetColorTableParameteriv),
+ NAME_FUNC_OFFSET( 4461, glColorSubTable, glColorSubTable, NULL, _gloffset_ColorSubTable),
+ NAME_FUNC_OFFSET( 4477, glCopyColorSubTable, glCopyColorSubTable, NULL, _gloffset_CopyColorSubTable),
+ NAME_FUNC_OFFSET( 4497, glConvolutionFilter1D, glConvolutionFilter1D, NULL, _gloffset_ConvolutionFilter1D),
+ NAME_FUNC_OFFSET( 4519, glConvolutionFilter2D, glConvolutionFilter2D, NULL, _gloffset_ConvolutionFilter2D),
+ NAME_FUNC_OFFSET( 4541, glConvolutionParameterf, glConvolutionParameterf, NULL, _gloffset_ConvolutionParameterf),
+ NAME_FUNC_OFFSET( 4565, glConvolutionParameterfv, glConvolutionParameterfv, NULL, _gloffset_ConvolutionParameterfv),
+ NAME_FUNC_OFFSET( 4590, glConvolutionParameteri, glConvolutionParameteri, NULL, _gloffset_ConvolutionParameteri),
+ NAME_FUNC_OFFSET( 4614, glConvolutionParameteriv, glConvolutionParameteriv, NULL, _gloffset_ConvolutionParameteriv),
+ NAME_FUNC_OFFSET( 4639, glCopyConvolutionFilter1D, glCopyConvolutionFilter1D, NULL, _gloffset_CopyConvolutionFilter1D),
+ NAME_FUNC_OFFSET( 4665, glCopyConvolutionFilter2D, glCopyConvolutionFilter2D, NULL, _gloffset_CopyConvolutionFilter2D),
+ NAME_FUNC_OFFSET( 4691, glGetConvolutionFilter, glGetConvolutionFilter, NULL, _gloffset_GetConvolutionFilter),
+ NAME_FUNC_OFFSET( 4714, glGetConvolutionParameterfv, glGetConvolutionParameterfv, NULL, _gloffset_GetConvolutionParameterfv),
+ NAME_FUNC_OFFSET( 4742, glGetConvolutionParameteriv, glGetConvolutionParameteriv, NULL, _gloffset_GetConvolutionParameteriv),
+ NAME_FUNC_OFFSET( 4770, glGetSeparableFilter, glGetSeparableFilter, NULL, _gloffset_GetSeparableFilter),
+ NAME_FUNC_OFFSET( 4791, glSeparableFilter2D, glSeparableFilter2D, NULL, _gloffset_SeparableFilter2D),
+ NAME_FUNC_OFFSET( 4811, glGetHistogram, glGetHistogram, NULL, _gloffset_GetHistogram),
+ NAME_FUNC_OFFSET( 4826, glGetHistogramParameterfv, glGetHistogramParameterfv, NULL, _gloffset_GetHistogramParameterfv),
+ NAME_FUNC_OFFSET( 4852, glGetHistogramParameteriv, glGetHistogramParameteriv, NULL, _gloffset_GetHistogramParameteriv),
+ NAME_FUNC_OFFSET( 4878, glGetMinmax, glGetMinmax, NULL, _gloffset_GetMinmax),
+ NAME_FUNC_OFFSET( 4890, glGetMinmaxParameterfv, glGetMinmaxParameterfv, NULL, _gloffset_GetMinmaxParameterfv),
+ NAME_FUNC_OFFSET( 4913, glGetMinmaxParameteriv, glGetMinmaxParameteriv, NULL, _gloffset_GetMinmaxParameteriv),
+ NAME_FUNC_OFFSET( 4936, glHistogram, glHistogram, NULL, _gloffset_Histogram),
+ NAME_FUNC_OFFSET( 4948, glMinmax, glMinmax, NULL, _gloffset_Minmax),
+ NAME_FUNC_OFFSET( 4957, glResetHistogram, glResetHistogram, NULL, _gloffset_ResetHistogram),
+ NAME_FUNC_OFFSET( 4974, glResetMinmax, glResetMinmax, NULL, _gloffset_ResetMinmax),
+ NAME_FUNC_OFFSET( 4988, glTexImage3D, glTexImage3D, NULL, _gloffset_TexImage3D),
+ NAME_FUNC_OFFSET( 5001, glTexSubImage3D, glTexSubImage3D, NULL, _gloffset_TexSubImage3D),
+ NAME_FUNC_OFFSET( 5017, glCopyTexSubImage3D, glCopyTexSubImage3D, NULL, _gloffset_CopyTexSubImage3D),
+ NAME_FUNC_OFFSET( 5037, glActiveTextureARB, glActiveTextureARB, NULL, _gloffset_ActiveTextureARB),
+ NAME_FUNC_OFFSET( 5056, glClientActiveTextureARB, glClientActiveTextureARB, NULL, _gloffset_ClientActiveTextureARB),
+ NAME_FUNC_OFFSET( 5081, glMultiTexCoord1dARB, glMultiTexCoord1dARB, NULL, _gloffset_MultiTexCoord1dARB),
+ NAME_FUNC_OFFSET( 5102, glMultiTexCoord1dvARB, glMultiTexCoord1dvARB, NULL, _gloffset_MultiTexCoord1dvARB),
+ NAME_FUNC_OFFSET( 5124, glMultiTexCoord1fARB, glMultiTexCoord1fARB, NULL, _gloffset_MultiTexCoord1fARB),
+ NAME_FUNC_OFFSET( 5145, glMultiTexCoord1fvARB, glMultiTexCoord1fvARB, NULL, _gloffset_MultiTexCoord1fvARB),
+ NAME_FUNC_OFFSET( 5167, glMultiTexCoord1iARB, glMultiTexCoord1iARB, NULL, _gloffset_MultiTexCoord1iARB),
+ NAME_FUNC_OFFSET( 5188, glMultiTexCoord1ivARB, glMultiTexCoord1ivARB, NULL, _gloffset_MultiTexCoord1ivARB),
+ NAME_FUNC_OFFSET( 5210, glMultiTexCoord1sARB, glMultiTexCoord1sARB, NULL, _gloffset_MultiTexCoord1sARB),
+ NAME_FUNC_OFFSET( 5231, glMultiTexCoord1svARB, glMultiTexCoord1svARB, NULL, _gloffset_MultiTexCoord1svARB),
+ NAME_FUNC_OFFSET( 5253, glMultiTexCoord2dARB, glMultiTexCoord2dARB, NULL, _gloffset_MultiTexCoord2dARB),
+ NAME_FUNC_OFFSET( 5274, glMultiTexCoord2dvARB, glMultiTexCoord2dvARB, NULL, _gloffset_MultiTexCoord2dvARB),
+ NAME_FUNC_OFFSET( 5296, glMultiTexCoord2fARB, glMultiTexCoord2fARB, NULL, _gloffset_MultiTexCoord2fARB),
+ NAME_FUNC_OFFSET( 5317, glMultiTexCoord2fvARB, glMultiTexCoord2fvARB, NULL, _gloffset_MultiTexCoord2fvARB),
+ NAME_FUNC_OFFSET( 5339, glMultiTexCoord2iARB, glMultiTexCoord2iARB, NULL, _gloffset_MultiTexCoord2iARB),
+ NAME_FUNC_OFFSET( 5360, glMultiTexCoord2ivARB, glMultiTexCoord2ivARB, NULL, _gloffset_MultiTexCoord2ivARB),
+ NAME_FUNC_OFFSET( 5382, glMultiTexCoord2sARB, glMultiTexCoord2sARB, NULL, _gloffset_MultiTexCoord2sARB),
+ NAME_FUNC_OFFSET( 5403, glMultiTexCoord2svARB, glMultiTexCoord2svARB, NULL, _gloffset_MultiTexCoord2svARB),
+ NAME_FUNC_OFFSET( 5425, glMultiTexCoord3dARB, glMultiTexCoord3dARB, NULL, _gloffset_MultiTexCoord3dARB),
+ NAME_FUNC_OFFSET( 5446, glMultiTexCoord3dvARB, glMultiTexCoord3dvARB, NULL, _gloffset_MultiTexCoord3dvARB),
+ NAME_FUNC_OFFSET( 5468, glMultiTexCoord3fARB, glMultiTexCoord3fARB, NULL, _gloffset_MultiTexCoord3fARB),
+ NAME_FUNC_OFFSET( 5489, glMultiTexCoord3fvARB, glMultiTexCoord3fvARB, NULL, _gloffset_MultiTexCoord3fvARB),
+ NAME_FUNC_OFFSET( 5511, glMultiTexCoord3iARB, glMultiTexCoord3iARB, NULL, _gloffset_MultiTexCoord3iARB),
+ NAME_FUNC_OFFSET( 5532, glMultiTexCoord3ivARB, glMultiTexCoord3ivARB, NULL, _gloffset_MultiTexCoord3ivARB),
+ NAME_FUNC_OFFSET( 5554, glMultiTexCoord3sARB, glMultiTexCoord3sARB, NULL, _gloffset_MultiTexCoord3sARB),
+ NAME_FUNC_OFFSET( 5575, glMultiTexCoord3svARB, glMultiTexCoord3svARB, NULL, _gloffset_MultiTexCoord3svARB),
+ NAME_FUNC_OFFSET( 5597, glMultiTexCoord4dARB, glMultiTexCoord4dARB, NULL, _gloffset_MultiTexCoord4dARB),
+ NAME_FUNC_OFFSET( 5618, glMultiTexCoord4dvARB, glMultiTexCoord4dvARB, NULL, _gloffset_MultiTexCoord4dvARB),
+ NAME_FUNC_OFFSET( 5640, glMultiTexCoord4fARB, glMultiTexCoord4fARB, NULL, _gloffset_MultiTexCoord4fARB),
+ NAME_FUNC_OFFSET( 5661, glMultiTexCoord4fvARB, glMultiTexCoord4fvARB, NULL, _gloffset_MultiTexCoord4fvARB),
+ NAME_FUNC_OFFSET( 5683, glMultiTexCoord4iARB, glMultiTexCoord4iARB, NULL, _gloffset_MultiTexCoord4iARB),
+ NAME_FUNC_OFFSET( 5704, glMultiTexCoord4ivARB, glMultiTexCoord4ivARB, NULL, _gloffset_MultiTexCoord4ivARB),
+ NAME_FUNC_OFFSET( 5726, glMultiTexCoord4sARB, glMultiTexCoord4sARB, NULL, _gloffset_MultiTexCoord4sARB),
+ NAME_FUNC_OFFSET( 5747, glMultiTexCoord4svARB, glMultiTexCoord4svARB, NULL, _gloffset_MultiTexCoord4svARB),
+ NAME_FUNC_OFFSET( 5769, glAttachShader, glAttachShader, NULL, _gloffset_AttachShader),
+ NAME_FUNC_OFFSET( 5784, glCreateProgram, glCreateProgram, NULL, _gloffset_CreateProgram),
+ NAME_FUNC_OFFSET( 5800, glCreateShader, glCreateShader, NULL, _gloffset_CreateShader),
+ NAME_FUNC_OFFSET( 5815, glDeleteProgram, glDeleteProgram, NULL, _gloffset_DeleteProgram),
+ NAME_FUNC_OFFSET( 5831, glDeleteShader, glDeleteShader, NULL, _gloffset_DeleteShader),
+ NAME_FUNC_OFFSET( 5846, glDetachShader, glDetachShader, NULL, _gloffset_DetachShader),
+ NAME_FUNC_OFFSET( 5861, glGetAttachedShaders, glGetAttachedShaders, NULL, _gloffset_GetAttachedShaders),
+ NAME_FUNC_OFFSET( 5882, glGetProgramInfoLog, glGetProgramInfoLog, NULL, _gloffset_GetProgramInfoLog),
+ NAME_FUNC_OFFSET( 5902, glGetProgramiv, glGetProgramiv, NULL, _gloffset_GetProgramiv),
+ NAME_FUNC_OFFSET( 5917, glGetShaderInfoLog, glGetShaderInfoLog, NULL, _gloffset_GetShaderInfoLog),
+ NAME_FUNC_OFFSET( 5936, glGetShaderiv, glGetShaderiv, NULL, _gloffset_GetShaderiv),
+ NAME_FUNC_OFFSET( 5950, glIsProgram, glIsProgram, NULL, _gloffset_IsProgram),
+ NAME_FUNC_OFFSET( 5962, glIsShader, glIsShader, NULL, _gloffset_IsShader),
+ NAME_FUNC_OFFSET( 5973, glStencilFuncSeparate, glStencilFuncSeparate, NULL, _gloffset_StencilFuncSeparate),
+ NAME_FUNC_OFFSET( 5995, glStencilMaskSeparate, glStencilMaskSeparate, NULL, _gloffset_StencilMaskSeparate),
+ NAME_FUNC_OFFSET( 6017, glStencilOpSeparate, glStencilOpSeparate, NULL, _gloffset_StencilOpSeparate),
+ NAME_FUNC_OFFSET( 6037, glUniformMatrix2x3fv, glUniformMatrix2x3fv, NULL, _gloffset_UniformMatrix2x3fv),
+ NAME_FUNC_OFFSET( 6058, glUniformMatrix2x4fv, glUniformMatrix2x4fv, NULL, _gloffset_UniformMatrix2x4fv),
+ NAME_FUNC_OFFSET( 6079, glUniformMatrix3x2fv, glUniformMatrix3x2fv, NULL, _gloffset_UniformMatrix3x2fv),
+ NAME_FUNC_OFFSET( 6100, glUniformMatrix3x4fv, glUniformMatrix3x4fv, NULL, _gloffset_UniformMatrix3x4fv),
+ NAME_FUNC_OFFSET( 6121, glUniformMatrix4x2fv, glUniformMatrix4x2fv, NULL, _gloffset_UniformMatrix4x2fv),
+ NAME_FUNC_OFFSET( 6142, glUniformMatrix4x3fv, glUniformMatrix4x3fv, NULL, _gloffset_UniformMatrix4x3fv),
+ NAME_FUNC_OFFSET( 6163, glLoadTransposeMatrixdARB, glLoadTransposeMatrixdARB, NULL, _gloffset_LoadTransposeMatrixdARB),
+ NAME_FUNC_OFFSET( 6189, glLoadTransposeMatrixfARB, glLoadTransposeMatrixfARB, NULL, _gloffset_LoadTransposeMatrixfARB),
+ NAME_FUNC_OFFSET( 6215, glMultTransposeMatrixdARB, glMultTransposeMatrixdARB, NULL, _gloffset_MultTransposeMatrixdARB),
+ NAME_FUNC_OFFSET( 6241, glMultTransposeMatrixfARB, glMultTransposeMatrixfARB, NULL, _gloffset_MultTransposeMatrixfARB),
+ NAME_FUNC_OFFSET( 6267, glSampleCoverageARB, glSampleCoverageARB, NULL, _gloffset_SampleCoverageARB),
+ NAME_FUNC_OFFSET( 6287, glCompressedTexImage1DARB, glCompressedTexImage1DARB, NULL, _gloffset_CompressedTexImage1DARB),
+ NAME_FUNC_OFFSET( 6313, glCompressedTexImage2DARB, glCompressedTexImage2DARB, NULL, _gloffset_CompressedTexImage2DARB),
+ NAME_FUNC_OFFSET( 6339, glCompressedTexImage3DARB, glCompressedTexImage3DARB, NULL, _gloffset_CompressedTexImage3DARB),
+ NAME_FUNC_OFFSET( 6365, glCompressedTexSubImage1DARB, glCompressedTexSubImage1DARB, NULL, _gloffset_CompressedTexSubImage1DARB),
+ NAME_FUNC_OFFSET( 6394, glCompressedTexSubImage2DARB, glCompressedTexSubImage2DARB, NULL, _gloffset_CompressedTexSubImage2DARB),
+ NAME_FUNC_OFFSET( 6423, glCompressedTexSubImage3DARB, glCompressedTexSubImage3DARB, NULL, _gloffset_CompressedTexSubImage3DARB),
+ NAME_FUNC_OFFSET( 6452, glGetCompressedTexImageARB, glGetCompressedTexImageARB, NULL, _gloffset_GetCompressedTexImageARB),
+ NAME_FUNC_OFFSET( 6479, glDisableVertexAttribArrayARB, glDisableVertexAttribArrayARB, NULL, _gloffset_DisableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET( 6509, glEnableVertexAttribArrayARB, glEnableVertexAttribArrayARB, NULL, _gloffset_EnableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET( 6538, glGetProgramEnvParameterdvARB, glGetProgramEnvParameterdvARB, NULL, _gloffset_GetProgramEnvParameterdvARB),
+ NAME_FUNC_OFFSET( 6568, glGetProgramEnvParameterfvARB, glGetProgramEnvParameterfvARB, NULL, _gloffset_GetProgramEnvParameterfvARB),
+ NAME_FUNC_OFFSET( 6598, glGetProgramLocalParameterdvARB, glGetProgramLocalParameterdvARB, NULL, _gloffset_GetProgramLocalParameterdvARB),
+ NAME_FUNC_OFFSET( 6630, glGetProgramLocalParameterfvARB, glGetProgramLocalParameterfvARB, NULL, _gloffset_GetProgramLocalParameterfvARB),
+ NAME_FUNC_OFFSET( 6662, glGetProgramStringARB, glGetProgramStringARB, NULL, _gloffset_GetProgramStringARB),
+ NAME_FUNC_OFFSET( 6684, glGetProgramivARB, glGetProgramivARB, NULL, _gloffset_GetProgramivARB),
+ NAME_FUNC_OFFSET( 6702, glGetVertexAttribdvARB, glGetVertexAttribdvARB, NULL, _gloffset_GetVertexAttribdvARB),
+ NAME_FUNC_OFFSET( 6725, glGetVertexAttribfvARB, glGetVertexAttribfvARB, NULL, _gloffset_GetVertexAttribfvARB),
+ NAME_FUNC_OFFSET( 6748, glGetVertexAttribivARB, glGetVertexAttribivARB, NULL, _gloffset_GetVertexAttribivARB),
+ NAME_FUNC_OFFSET( 6771, glProgramEnvParameter4dARB, glProgramEnvParameter4dARB, NULL, _gloffset_ProgramEnvParameter4dARB),
+ NAME_FUNC_OFFSET( 6798, glProgramEnvParameter4dvARB, glProgramEnvParameter4dvARB, NULL, _gloffset_ProgramEnvParameter4dvARB),
+ NAME_FUNC_OFFSET( 6826, glProgramEnvParameter4fARB, glProgramEnvParameter4fARB, NULL, _gloffset_ProgramEnvParameter4fARB),
+ NAME_FUNC_OFFSET( 6853, glProgramEnvParameter4fvARB, glProgramEnvParameter4fvARB, NULL, _gloffset_ProgramEnvParameter4fvARB),
+ NAME_FUNC_OFFSET( 6881, glProgramLocalParameter4dARB, glProgramLocalParameter4dARB, NULL, _gloffset_ProgramLocalParameter4dARB),
+ NAME_FUNC_OFFSET( 6910, glProgramLocalParameter4dvARB, glProgramLocalParameter4dvARB, NULL, _gloffset_ProgramLocalParameter4dvARB),
+ NAME_FUNC_OFFSET( 6940, glProgramLocalParameter4fARB, glProgramLocalParameter4fARB, NULL, _gloffset_ProgramLocalParameter4fARB),
+ NAME_FUNC_OFFSET( 6969, glProgramLocalParameter4fvARB, glProgramLocalParameter4fvARB, NULL, _gloffset_ProgramLocalParameter4fvARB),
+ NAME_FUNC_OFFSET( 6999, glProgramStringARB, glProgramStringARB, NULL, _gloffset_ProgramStringARB),
+ NAME_FUNC_OFFSET( 7018, glVertexAttrib1dARB, glVertexAttrib1dARB, NULL, _gloffset_VertexAttrib1dARB),
+ NAME_FUNC_OFFSET( 7038, glVertexAttrib1dvARB, glVertexAttrib1dvARB, NULL, _gloffset_VertexAttrib1dvARB),
+ NAME_FUNC_OFFSET( 7059, glVertexAttrib1fARB, glVertexAttrib1fARB, NULL, _gloffset_VertexAttrib1fARB),
+ NAME_FUNC_OFFSET( 7079, glVertexAttrib1fvARB, glVertexAttrib1fvARB, NULL, _gloffset_VertexAttrib1fvARB),
+ NAME_FUNC_OFFSET( 7100, glVertexAttrib1sARB, glVertexAttrib1sARB, NULL, _gloffset_VertexAttrib1sARB),
+ NAME_FUNC_OFFSET( 7120, glVertexAttrib1svARB, glVertexAttrib1svARB, NULL, _gloffset_VertexAttrib1svARB),
+ NAME_FUNC_OFFSET( 7141, glVertexAttrib2dARB, glVertexAttrib2dARB, NULL, _gloffset_VertexAttrib2dARB),
+ NAME_FUNC_OFFSET( 7161, glVertexAttrib2dvARB, glVertexAttrib2dvARB, NULL, _gloffset_VertexAttrib2dvARB),
+ NAME_FUNC_OFFSET( 7182, glVertexAttrib2fARB, glVertexAttrib2fARB, NULL, _gloffset_VertexAttrib2fARB),
+ NAME_FUNC_OFFSET( 7202, glVertexAttrib2fvARB, glVertexAttrib2fvARB, NULL, _gloffset_VertexAttrib2fvARB),
+ NAME_FUNC_OFFSET( 7223, glVertexAttrib2sARB, glVertexAttrib2sARB, NULL, _gloffset_VertexAttrib2sARB),
+ NAME_FUNC_OFFSET( 7243, glVertexAttrib2svARB, glVertexAttrib2svARB, NULL, _gloffset_VertexAttrib2svARB),
+ NAME_FUNC_OFFSET( 7264, glVertexAttrib3dARB, glVertexAttrib3dARB, NULL, _gloffset_VertexAttrib3dARB),
+ NAME_FUNC_OFFSET( 7284, glVertexAttrib3dvARB, glVertexAttrib3dvARB, NULL, _gloffset_VertexAttrib3dvARB),
+ NAME_FUNC_OFFSET( 7305, glVertexAttrib3fARB, glVertexAttrib3fARB, NULL, _gloffset_VertexAttrib3fARB),
+ NAME_FUNC_OFFSET( 7325, glVertexAttrib3fvARB, glVertexAttrib3fvARB, NULL, _gloffset_VertexAttrib3fvARB),
+ NAME_FUNC_OFFSET( 7346, glVertexAttrib3sARB, glVertexAttrib3sARB, NULL, _gloffset_VertexAttrib3sARB),
+ NAME_FUNC_OFFSET( 7366, glVertexAttrib3svARB, glVertexAttrib3svARB, NULL, _gloffset_VertexAttrib3svARB),
+ NAME_FUNC_OFFSET( 7387, glVertexAttrib4NbvARB, glVertexAttrib4NbvARB, NULL, _gloffset_VertexAttrib4NbvARB),
+ NAME_FUNC_OFFSET( 7409, glVertexAttrib4NivARB, glVertexAttrib4NivARB, NULL, _gloffset_VertexAttrib4NivARB),
+ NAME_FUNC_OFFSET( 7431, glVertexAttrib4NsvARB, glVertexAttrib4NsvARB, NULL, _gloffset_VertexAttrib4NsvARB),
+ NAME_FUNC_OFFSET( 7453, glVertexAttrib4NubARB, glVertexAttrib4NubARB, NULL, _gloffset_VertexAttrib4NubARB),
+ NAME_FUNC_OFFSET( 7475, glVertexAttrib4NubvARB, glVertexAttrib4NubvARB, NULL, _gloffset_VertexAttrib4NubvARB),
+ NAME_FUNC_OFFSET( 7498, glVertexAttrib4NuivARB, glVertexAttrib4NuivARB, NULL, _gloffset_VertexAttrib4NuivARB),
+ NAME_FUNC_OFFSET( 7521, glVertexAttrib4NusvARB, glVertexAttrib4NusvARB, NULL, _gloffset_VertexAttrib4NusvARB),
+ NAME_FUNC_OFFSET( 7544, glVertexAttrib4bvARB, glVertexAttrib4bvARB, NULL, _gloffset_VertexAttrib4bvARB),
+ NAME_FUNC_OFFSET( 7565, glVertexAttrib4dARB, glVertexAttrib4dARB, NULL, _gloffset_VertexAttrib4dARB),
+ NAME_FUNC_OFFSET( 7585, glVertexAttrib4dvARB, glVertexAttrib4dvARB, NULL, _gloffset_VertexAttrib4dvARB),
+ NAME_FUNC_OFFSET( 7606, glVertexAttrib4fARB, glVertexAttrib4fARB, NULL, _gloffset_VertexAttrib4fARB),
+ NAME_FUNC_OFFSET( 7626, glVertexAttrib4fvARB, glVertexAttrib4fvARB, NULL, _gloffset_VertexAttrib4fvARB),
+ NAME_FUNC_OFFSET( 7647, glVertexAttrib4ivARB, glVertexAttrib4ivARB, NULL, _gloffset_VertexAttrib4ivARB),
+ NAME_FUNC_OFFSET( 7668, glVertexAttrib4sARB, glVertexAttrib4sARB, NULL, _gloffset_VertexAttrib4sARB),
+ NAME_FUNC_OFFSET( 7688, glVertexAttrib4svARB, glVertexAttrib4svARB, NULL, _gloffset_VertexAttrib4svARB),
+ NAME_FUNC_OFFSET( 7709, glVertexAttrib4ubvARB, glVertexAttrib4ubvARB, NULL, _gloffset_VertexAttrib4ubvARB),
+ NAME_FUNC_OFFSET( 7731, glVertexAttrib4uivARB, glVertexAttrib4uivARB, NULL, _gloffset_VertexAttrib4uivARB),
+ NAME_FUNC_OFFSET( 7753, glVertexAttrib4usvARB, glVertexAttrib4usvARB, NULL, _gloffset_VertexAttrib4usvARB),
+ NAME_FUNC_OFFSET( 7775, glVertexAttribPointerARB, glVertexAttribPointerARB, NULL, _gloffset_VertexAttribPointerARB),
+ NAME_FUNC_OFFSET( 7800, glBindBufferARB, glBindBufferARB, NULL, _gloffset_BindBufferARB),
+ NAME_FUNC_OFFSET( 7816, glBufferDataARB, glBufferDataARB, NULL, _gloffset_BufferDataARB),
+ NAME_FUNC_OFFSET( 7832, glBufferSubDataARB, glBufferSubDataARB, NULL, _gloffset_BufferSubDataARB),
+ NAME_FUNC_OFFSET( 7851, glDeleteBuffersARB, glDeleteBuffersARB, NULL, _gloffset_DeleteBuffersARB),
+ NAME_FUNC_OFFSET( 7870, glGenBuffersARB, glGenBuffersARB, NULL, _gloffset_GenBuffersARB),
+ NAME_FUNC_OFFSET( 7886, glGetBufferParameterivARB, glGetBufferParameterivARB, NULL, _gloffset_GetBufferParameterivARB),
+ NAME_FUNC_OFFSET( 7912, glGetBufferPointervARB, glGetBufferPointervARB, NULL, _gloffset_GetBufferPointervARB),
+ NAME_FUNC_OFFSET( 7935, glGetBufferSubDataARB, glGetBufferSubDataARB, NULL, _gloffset_GetBufferSubDataARB),
+ NAME_FUNC_OFFSET( 7957, glIsBufferARB, glIsBufferARB, NULL, _gloffset_IsBufferARB),
+ NAME_FUNC_OFFSET( 7971, glMapBufferARB, glMapBufferARB, NULL, _gloffset_MapBufferARB),
+ NAME_FUNC_OFFSET( 7986, glUnmapBufferARB, glUnmapBufferARB, NULL, _gloffset_UnmapBufferARB),
+ NAME_FUNC_OFFSET( 8003, glBeginQueryARB, glBeginQueryARB, NULL, _gloffset_BeginQueryARB),
+ NAME_FUNC_OFFSET( 8019, glDeleteQueriesARB, glDeleteQueriesARB, NULL, _gloffset_DeleteQueriesARB),
+ NAME_FUNC_OFFSET( 8038, glEndQueryARB, glEndQueryARB, NULL, _gloffset_EndQueryARB),
+ NAME_FUNC_OFFSET( 8052, glGenQueriesARB, glGenQueriesARB, NULL, _gloffset_GenQueriesARB),
+ NAME_FUNC_OFFSET( 8068, glGetQueryObjectivARB, glGetQueryObjectivARB, NULL, _gloffset_GetQueryObjectivARB),
+ NAME_FUNC_OFFSET( 8090, glGetQueryObjectuivARB, glGetQueryObjectuivARB, NULL, _gloffset_GetQueryObjectuivARB),
+ NAME_FUNC_OFFSET( 8113, glGetQueryivARB, glGetQueryivARB, NULL, _gloffset_GetQueryivARB),
+ NAME_FUNC_OFFSET( 8129, glIsQueryARB, glIsQueryARB, NULL, _gloffset_IsQueryARB),
+ NAME_FUNC_OFFSET( 8142, glAttachObjectARB, glAttachObjectARB, NULL, _gloffset_AttachObjectARB),
+ NAME_FUNC_OFFSET( 8160, glCompileShaderARB, glCompileShaderARB, NULL, _gloffset_CompileShaderARB),
+ NAME_FUNC_OFFSET( 8179, glCreateProgramObjectARB, glCreateProgramObjectARB, NULL, _gloffset_CreateProgramObjectARB),
+ NAME_FUNC_OFFSET( 8204, glCreateShaderObjectARB, glCreateShaderObjectARB, NULL, _gloffset_CreateShaderObjectARB),
+ NAME_FUNC_OFFSET( 8228, glDeleteObjectARB, glDeleteObjectARB, NULL, _gloffset_DeleteObjectARB),
+ NAME_FUNC_OFFSET( 8246, glDetachObjectARB, glDetachObjectARB, NULL, _gloffset_DetachObjectARB),
+ NAME_FUNC_OFFSET( 8264, glGetActiveUniformARB, glGetActiveUniformARB, NULL, _gloffset_GetActiveUniformARB),
+ NAME_FUNC_OFFSET( 8286, glGetAttachedObjectsARB, glGetAttachedObjectsARB, NULL, _gloffset_GetAttachedObjectsARB),
+ NAME_FUNC_OFFSET( 8310, glGetHandleARB, glGetHandleARB, NULL, _gloffset_GetHandleARB),
+ NAME_FUNC_OFFSET( 8325, glGetInfoLogARB, glGetInfoLogARB, NULL, _gloffset_GetInfoLogARB),
+ NAME_FUNC_OFFSET( 8341, glGetObjectParameterfvARB, glGetObjectParameterfvARB, NULL, _gloffset_GetObjectParameterfvARB),
+ NAME_FUNC_OFFSET( 8367, glGetObjectParameterivARB, glGetObjectParameterivARB, NULL, _gloffset_GetObjectParameterivARB),
+ NAME_FUNC_OFFSET( 8393, glGetShaderSourceARB, glGetShaderSourceARB, NULL, _gloffset_GetShaderSourceARB),
+ NAME_FUNC_OFFSET( 8414, glGetUniformLocationARB, glGetUniformLocationARB, NULL, _gloffset_GetUniformLocationARB),
+ NAME_FUNC_OFFSET( 8438, glGetUniformfvARB, glGetUniformfvARB, NULL, _gloffset_GetUniformfvARB),
+ NAME_FUNC_OFFSET( 8456, glGetUniformivARB, glGetUniformivARB, NULL, _gloffset_GetUniformivARB),
+ NAME_FUNC_OFFSET( 8474, glLinkProgramARB, glLinkProgramARB, NULL, _gloffset_LinkProgramARB),
+ NAME_FUNC_OFFSET( 8491, glShaderSourceARB, glShaderSourceARB, NULL, _gloffset_ShaderSourceARB),
+ NAME_FUNC_OFFSET( 8509, glUniform1fARB, glUniform1fARB, NULL, _gloffset_Uniform1fARB),
+ NAME_FUNC_OFFSET( 8524, glUniform1fvARB, glUniform1fvARB, NULL, _gloffset_Uniform1fvARB),
+ NAME_FUNC_OFFSET( 8540, glUniform1iARB, glUniform1iARB, NULL, _gloffset_Uniform1iARB),
+ NAME_FUNC_OFFSET( 8555, glUniform1ivARB, glUniform1ivARB, NULL, _gloffset_Uniform1ivARB),
+ NAME_FUNC_OFFSET( 8571, glUniform2fARB, glUniform2fARB, NULL, _gloffset_Uniform2fARB),
+ NAME_FUNC_OFFSET( 8586, glUniform2fvARB, glUniform2fvARB, NULL, _gloffset_Uniform2fvARB),
+ NAME_FUNC_OFFSET( 8602, glUniform2iARB, glUniform2iARB, NULL, _gloffset_Uniform2iARB),
+ NAME_FUNC_OFFSET( 8617, glUniform2ivARB, glUniform2ivARB, NULL, _gloffset_Uniform2ivARB),
+ NAME_FUNC_OFFSET( 8633, glUniform3fARB, glUniform3fARB, NULL, _gloffset_Uniform3fARB),
+ NAME_FUNC_OFFSET( 8648, glUniform3fvARB, glUniform3fvARB, NULL, _gloffset_Uniform3fvARB),
+ NAME_FUNC_OFFSET( 8664, glUniform3iARB, glUniform3iARB, NULL, _gloffset_Uniform3iARB),
+ NAME_FUNC_OFFSET( 8679, glUniform3ivARB, glUniform3ivARB, NULL, _gloffset_Uniform3ivARB),
+ NAME_FUNC_OFFSET( 8695, glUniform4fARB, glUniform4fARB, NULL, _gloffset_Uniform4fARB),
+ NAME_FUNC_OFFSET( 8710, glUniform4fvARB, glUniform4fvARB, NULL, _gloffset_Uniform4fvARB),
+ NAME_FUNC_OFFSET( 8726, glUniform4iARB, glUniform4iARB, NULL, _gloffset_Uniform4iARB),
+ NAME_FUNC_OFFSET( 8741, glUniform4ivARB, glUniform4ivARB, NULL, _gloffset_Uniform4ivARB),
+ NAME_FUNC_OFFSET( 8757, glUniformMatrix2fvARB, glUniformMatrix2fvARB, NULL, _gloffset_UniformMatrix2fvARB),
+ NAME_FUNC_OFFSET( 8779, glUniformMatrix3fvARB, glUniformMatrix3fvARB, NULL, _gloffset_UniformMatrix3fvARB),
+ NAME_FUNC_OFFSET( 8801, glUniformMatrix4fvARB, glUniformMatrix4fvARB, NULL, _gloffset_UniformMatrix4fvARB),
+ NAME_FUNC_OFFSET( 8823, glUseProgramObjectARB, glUseProgramObjectARB, NULL, _gloffset_UseProgramObjectARB),
+ NAME_FUNC_OFFSET( 8845, glValidateProgramARB, glValidateProgramARB, NULL, _gloffset_ValidateProgramARB),
+ NAME_FUNC_OFFSET( 8866, glBindAttribLocationARB, glBindAttribLocationARB, NULL, _gloffset_BindAttribLocationARB),
+ NAME_FUNC_OFFSET( 8890, glGetActiveAttribARB, glGetActiveAttribARB, NULL, _gloffset_GetActiveAttribARB),
+ NAME_FUNC_OFFSET( 8911, glGetAttribLocationARB, glGetAttribLocationARB, NULL, _gloffset_GetAttribLocationARB),
+ NAME_FUNC_OFFSET( 8934, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
+ NAME_FUNC_OFFSET( 8951, glRenderbufferStorageMultisample, glRenderbufferStorageMultisample, NULL, _gloffset_RenderbufferStorageMultisample),
+ NAME_FUNC_OFFSET( 8984, glFlushMappedBufferRange, glFlushMappedBufferRange, NULL, _gloffset_FlushMappedBufferRange),
+ NAME_FUNC_OFFSET( 9009, glMapBufferRange, glMapBufferRange, NULL, _gloffset_MapBufferRange),
+ NAME_FUNC_OFFSET( 9026, glBindVertexArray, glBindVertexArray, NULL, _gloffset_BindVertexArray),
+ NAME_FUNC_OFFSET( 9044, glGenVertexArrays, glGenVertexArrays, NULL, _gloffset_GenVertexArrays),
+ NAME_FUNC_OFFSET( 9062, glCopyBufferSubData, glCopyBufferSubData, NULL, _gloffset_CopyBufferSubData),
+ NAME_FUNC_OFFSET( 9082, glClientWaitSync, glClientWaitSync, NULL, _gloffset_ClientWaitSync),
+ NAME_FUNC_OFFSET( 9099, glDeleteSync, glDeleteSync, NULL, _gloffset_DeleteSync),
+ NAME_FUNC_OFFSET( 9112, glFenceSync, glFenceSync, NULL, _gloffset_FenceSync),
+ NAME_FUNC_OFFSET( 9124, glGetInteger64v, glGetInteger64v, NULL, _gloffset_GetInteger64v),
+ NAME_FUNC_OFFSET( 9140, glGetSynciv, glGetSynciv, NULL, _gloffset_GetSynciv),
+ NAME_FUNC_OFFSET( 9152, glIsSync, glIsSync, NULL, _gloffset_IsSync),
+ NAME_FUNC_OFFSET( 9161, glWaitSync, glWaitSync, NULL, _gloffset_WaitSync),
+ NAME_FUNC_OFFSET( 9172, glPolygonOffsetEXT, glPolygonOffsetEXT, NULL, _gloffset_PolygonOffsetEXT),
+ NAME_FUNC_OFFSET( 9191, gl_dispatch_stub_575, gl_dispatch_stub_575, NULL, _gloffset_GetPixelTexGenParameterfvSGIS),
+ NAME_FUNC_OFFSET( 9223, gl_dispatch_stub_576, gl_dispatch_stub_576, NULL, _gloffset_GetPixelTexGenParameterivSGIS),
+ NAME_FUNC_OFFSET( 9255, gl_dispatch_stub_577, gl_dispatch_stub_577, NULL, _gloffset_PixelTexGenParameterfSGIS),
+ NAME_FUNC_OFFSET( 9283, gl_dispatch_stub_578, gl_dispatch_stub_578, NULL, _gloffset_PixelTexGenParameterfvSGIS),
+ NAME_FUNC_OFFSET( 9312, gl_dispatch_stub_579, gl_dispatch_stub_579, NULL, _gloffset_PixelTexGenParameteriSGIS),
+ NAME_FUNC_OFFSET( 9340, gl_dispatch_stub_580, gl_dispatch_stub_580, NULL, _gloffset_PixelTexGenParameterivSGIS),
+ NAME_FUNC_OFFSET( 9369, gl_dispatch_stub_581, gl_dispatch_stub_581, NULL, _gloffset_SampleMaskSGIS),
+ NAME_FUNC_OFFSET( 9386, gl_dispatch_stub_582, gl_dispatch_stub_582, NULL, _gloffset_SamplePatternSGIS),
+ NAME_FUNC_OFFSET( 9406, glColorPointerEXT, glColorPointerEXT, NULL, _gloffset_ColorPointerEXT),
+ NAME_FUNC_OFFSET( 9424, glEdgeFlagPointerEXT, glEdgeFlagPointerEXT, NULL, _gloffset_EdgeFlagPointerEXT),
+ NAME_FUNC_OFFSET( 9445, glIndexPointerEXT, glIndexPointerEXT, NULL, _gloffset_IndexPointerEXT),
+ NAME_FUNC_OFFSET( 9463, glNormalPointerEXT, glNormalPointerEXT, NULL, _gloffset_NormalPointerEXT),
+ NAME_FUNC_OFFSET( 9482, glTexCoordPointerEXT, glTexCoordPointerEXT, NULL, _gloffset_TexCoordPointerEXT),
+ NAME_FUNC_OFFSET( 9503, glVertexPointerEXT, glVertexPointerEXT, NULL, _gloffset_VertexPointerEXT),
+ NAME_FUNC_OFFSET( 9522, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET( 9543, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET( 9565, glLockArraysEXT, glLockArraysEXT, NULL, _gloffset_LockArraysEXT),
+ NAME_FUNC_OFFSET( 9581, glUnlockArraysEXT, glUnlockArraysEXT, NULL, _gloffset_UnlockArraysEXT),
+ NAME_FUNC_OFFSET( 9599, gl_dispatch_stub_593, gl_dispatch_stub_593, NULL, _gloffset_CullParameterdvEXT),
+ NAME_FUNC_OFFSET( 9620, gl_dispatch_stub_594, gl_dispatch_stub_594, NULL, _gloffset_CullParameterfvEXT),
+ NAME_FUNC_OFFSET( 9641, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
+ NAME_FUNC_OFFSET( 9663, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
+ NAME_FUNC_OFFSET( 9686, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
+ NAME_FUNC_OFFSET( 9708, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
+ NAME_FUNC_OFFSET( 9731, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
+ NAME_FUNC_OFFSET( 9753, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
+ NAME_FUNC_OFFSET( 9776, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
+ NAME_FUNC_OFFSET( 9798, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
+ NAME_FUNC_OFFSET( 9821, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
+ NAME_FUNC_OFFSET( 9843, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
+ NAME_FUNC_OFFSET( 9866, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
+ NAME_FUNC_OFFSET( 9889, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
+ NAME_FUNC_OFFSET( 9913, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
+ NAME_FUNC_OFFSET( 9936, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
+ NAME_FUNC_OFFSET( 9960, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
+ NAME_FUNC_OFFSET( 9983, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
+ NAME_FUNC_OFFSET(10007, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
+ NAME_FUNC_OFFSET(10034, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
+ NAME_FUNC_OFFSET(10055, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
+ NAME_FUNC_OFFSET(10078, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
+ NAME_FUNC_OFFSET(10099, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
+ NAME_FUNC_OFFSET(10114, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
+ NAME_FUNC_OFFSET(10130, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
+ NAME_FUNC_OFFSET(10145, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
+ NAME_FUNC_OFFSET(10161, gl_dispatch_stub_619, gl_dispatch_stub_619, NULL, _gloffset_PixelTexGenSGIX),
+ NAME_FUNC_OFFSET(10179, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(10202, glFlushVertexArrayRangeNV, glFlushVertexArrayRangeNV, NULL, _gloffset_FlushVertexArrayRangeNV),
+ NAME_FUNC_OFFSET(10228, glVertexArrayRangeNV, glVertexArrayRangeNV, NULL, _gloffset_VertexArrayRangeNV),
+ NAME_FUNC_OFFSET(10249, glCombinerInputNV, glCombinerInputNV, NULL, _gloffset_CombinerInputNV),
+ NAME_FUNC_OFFSET(10267, glCombinerOutputNV, glCombinerOutputNV, NULL, _gloffset_CombinerOutputNV),
+ NAME_FUNC_OFFSET(10286, glCombinerParameterfNV, glCombinerParameterfNV, NULL, _gloffset_CombinerParameterfNV),
+ NAME_FUNC_OFFSET(10309, glCombinerParameterfvNV, glCombinerParameterfvNV, NULL, _gloffset_CombinerParameterfvNV),
+ NAME_FUNC_OFFSET(10333, glCombinerParameteriNV, glCombinerParameteriNV, NULL, _gloffset_CombinerParameteriNV),
+ NAME_FUNC_OFFSET(10356, glCombinerParameterivNV, glCombinerParameterivNV, NULL, _gloffset_CombinerParameterivNV),
+ NAME_FUNC_OFFSET(10380, glFinalCombinerInputNV, glFinalCombinerInputNV, NULL, _gloffset_FinalCombinerInputNV),
+ NAME_FUNC_OFFSET(10403, glGetCombinerInputParameterfvNV, glGetCombinerInputParameterfvNV, NULL, _gloffset_GetCombinerInputParameterfvNV),
+ NAME_FUNC_OFFSET(10435, glGetCombinerInputParameterivNV, glGetCombinerInputParameterivNV, NULL, _gloffset_GetCombinerInputParameterivNV),
+ NAME_FUNC_OFFSET(10467, glGetCombinerOutputParameterfvNV, glGetCombinerOutputParameterfvNV, NULL, _gloffset_GetCombinerOutputParameterfvNV),
+ NAME_FUNC_OFFSET(10500, glGetCombinerOutputParameterivNV, glGetCombinerOutputParameterivNV, NULL, _gloffset_GetCombinerOutputParameterivNV),
+ NAME_FUNC_OFFSET(10533, glGetFinalCombinerInputParameterfvNV, glGetFinalCombinerInputParameterfvNV, NULL, _gloffset_GetFinalCombinerInputParameterfvNV),
+ NAME_FUNC_OFFSET(10570, glGetFinalCombinerInputParameterivNV, glGetFinalCombinerInputParameterivNV, NULL, _gloffset_GetFinalCombinerInputParameterivNV),
+ NAME_FUNC_OFFSET(10607, glResizeBuffersMESA, glResizeBuffersMESA, NULL, _gloffset_ResizeBuffersMESA),
+ NAME_FUNC_OFFSET(10627, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(10645, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(10664, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(10682, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(10701, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(10719, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(10738, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(10756, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(10775, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(10793, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(10812, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(10830, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(10849, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(10867, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(10886, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(10904, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(10923, glWindowPos4dMESA, glWindowPos4dMESA, NULL, _gloffset_WindowPos4dMESA),
+ NAME_FUNC_OFFSET(10941, glWindowPos4dvMESA, glWindowPos4dvMESA, NULL, _gloffset_WindowPos4dvMESA),
+ NAME_FUNC_OFFSET(10960, glWindowPos4fMESA, glWindowPos4fMESA, NULL, _gloffset_WindowPos4fMESA),
+ NAME_FUNC_OFFSET(10978, glWindowPos4fvMESA, glWindowPos4fvMESA, NULL, _gloffset_WindowPos4fvMESA),
+ NAME_FUNC_OFFSET(10997, glWindowPos4iMESA, glWindowPos4iMESA, NULL, _gloffset_WindowPos4iMESA),
+ NAME_FUNC_OFFSET(11015, glWindowPos4ivMESA, glWindowPos4ivMESA, NULL, _gloffset_WindowPos4ivMESA),
+ NAME_FUNC_OFFSET(11034, glWindowPos4sMESA, glWindowPos4sMESA, NULL, _gloffset_WindowPos4sMESA),
+ NAME_FUNC_OFFSET(11052, glWindowPos4svMESA, glWindowPos4svMESA, NULL, _gloffset_WindowPos4svMESA),
+ NAME_FUNC_OFFSET(11071, gl_dispatch_stub_661, gl_dispatch_stub_661, NULL, _gloffset_MultiModeDrawArraysIBM),
+ NAME_FUNC_OFFSET(11096, gl_dispatch_stub_662, gl_dispatch_stub_662, NULL, _gloffset_MultiModeDrawElementsIBM),
+ NAME_FUNC_OFFSET(11123, gl_dispatch_stub_663, gl_dispatch_stub_663, NULL, _gloffset_DeleteFencesNV),
+ NAME_FUNC_OFFSET(11140, gl_dispatch_stub_664, gl_dispatch_stub_664, NULL, _gloffset_FinishFenceNV),
+ NAME_FUNC_OFFSET(11156, gl_dispatch_stub_665, gl_dispatch_stub_665, NULL, _gloffset_GenFencesNV),
+ NAME_FUNC_OFFSET(11170, gl_dispatch_stub_666, gl_dispatch_stub_666, NULL, _gloffset_GetFenceivNV),
+ NAME_FUNC_OFFSET(11185, gl_dispatch_stub_667, gl_dispatch_stub_667, NULL, _gloffset_IsFenceNV),
+ NAME_FUNC_OFFSET(11197, gl_dispatch_stub_668, gl_dispatch_stub_668, NULL, _gloffset_SetFenceNV),
+ NAME_FUNC_OFFSET(11210, gl_dispatch_stub_669, gl_dispatch_stub_669, NULL, _gloffset_TestFenceNV),
+ NAME_FUNC_OFFSET(11224, glAreProgramsResidentNV, glAreProgramsResidentNV, NULL, _gloffset_AreProgramsResidentNV),
+ NAME_FUNC_OFFSET(11248, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
+ NAME_FUNC_OFFSET(11264, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
+ NAME_FUNC_OFFSET(11283, glExecuteProgramNV, glExecuteProgramNV, NULL, _gloffset_ExecuteProgramNV),
+ NAME_FUNC_OFFSET(11302, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
+ NAME_FUNC_OFFSET(11318, glGetProgramParameterdvNV, glGetProgramParameterdvNV, NULL, _gloffset_GetProgramParameterdvNV),
+ NAME_FUNC_OFFSET(11344, glGetProgramParameterfvNV, glGetProgramParameterfvNV, NULL, _gloffset_GetProgramParameterfvNV),
+ NAME_FUNC_OFFSET(11370, glGetProgramStringNV, glGetProgramStringNV, NULL, _gloffset_GetProgramStringNV),
+ NAME_FUNC_OFFSET(11391, glGetProgramivNV, glGetProgramivNV, NULL, _gloffset_GetProgramivNV),
+ NAME_FUNC_OFFSET(11408, glGetTrackMatrixivNV, glGetTrackMatrixivNV, NULL, _gloffset_GetTrackMatrixivNV),
+ NAME_FUNC_OFFSET(11429, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(11457, glGetVertexAttribdvNV, glGetVertexAttribdvNV, NULL, _gloffset_GetVertexAttribdvNV),
+ NAME_FUNC_OFFSET(11479, glGetVertexAttribfvNV, glGetVertexAttribfvNV, NULL, _gloffset_GetVertexAttribfvNV),
+ NAME_FUNC_OFFSET(11501, glGetVertexAttribivNV, glGetVertexAttribivNV, NULL, _gloffset_GetVertexAttribivNV),
+ NAME_FUNC_OFFSET(11523, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
+ NAME_FUNC_OFFSET(11537, glLoadProgramNV, glLoadProgramNV, NULL, _gloffset_LoadProgramNV),
+ NAME_FUNC_OFFSET(11553, glProgramParameters4dvNV, glProgramParameters4dvNV, NULL, _gloffset_ProgramParameters4dvNV),
+ NAME_FUNC_OFFSET(11578, glProgramParameters4fvNV, glProgramParameters4fvNV, NULL, _gloffset_ProgramParameters4fvNV),
+ NAME_FUNC_OFFSET(11603, glRequestResidentProgramsNV, glRequestResidentProgramsNV, NULL, _gloffset_RequestResidentProgramsNV),
+ NAME_FUNC_OFFSET(11631, glTrackMatrixNV, glTrackMatrixNV, NULL, _gloffset_TrackMatrixNV),
+ NAME_FUNC_OFFSET(11647, glVertexAttrib1dNV, glVertexAttrib1dNV, NULL, _gloffset_VertexAttrib1dNV),
+ NAME_FUNC_OFFSET(11666, glVertexAttrib1dvNV, glVertexAttrib1dvNV, NULL, _gloffset_VertexAttrib1dvNV),
+ NAME_FUNC_OFFSET(11686, glVertexAttrib1fNV, glVertexAttrib1fNV, NULL, _gloffset_VertexAttrib1fNV),
+ NAME_FUNC_OFFSET(11705, glVertexAttrib1fvNV, glVertexAttrib1fvNV, NULL, _gloffset_VertexAttrib1fvNV),
+ NAME_FUNC_OFFSET(11725, glVertexAttrib1sNV, glVertexAttrib1sNV, NULL, _gloffset_VertexAttrib1sNV),
+ NAME_FUNC_OFFSET(11744, glVertexAttrib1svNV, glVertexAttrib1svNV, NULL, _gloffset_VertexAttrib1svNV),
+ NAME_FUNC_OFFSET(11764, glVertexAttrib2dNV, glVertexAttrib2dNV, NULL, _gloffset_VertexAttrib2dNV),
+ NAME_FUNC_OFFSET(11783, glVertexAttrib2dvNV, glVertexAttrib2dvNV, NULL, _gloffset_VertexAttrib2dvNV),
+ NAME_FUNC_OFFSET(11803, glVertexAttrib2fNV, glVertexAttrib2fNV, NULL, _gloffset_VertexAttrib2fNV),
+ NAME_FUNC_OFFSET(11822, glVertexAttrib2fvNV, glVertexAttrib2fvNV, NULL, _gloffset_VertexAttrib2fvNV),
+ NAME_FUNC_OFFSET(11842, glVertexAttrib2sNV, glVertexAttrib2sNV, NULL, _gloffset_VertexAttrib2sNV),
+ NAME_FUNC_OFFSET(11861, glVertexAttrib2svNV, glVertexAttrib2svNV, NULL, _gloffset_VertexAttrib2svNV),
+ NAME_FUNC_OFFSET(11881, glVertexAttrib3dNV, glVertexAttrib3dNV, NULL, _gloffset_VertexAttrib3dNV),
+ NAME_FUNC_OFFSET(11900, glVertexAttrib3dvNV, glVertexAttrib3dvNV, NULL, _gloffset_VertexAttrib3dvNV),
+ NAME_FUNC_OFFSET(11920, glVertexAttrib3fNV, glVertexAttrib3fNV, NULL, _gloffset_VertexAttrib3fNV),
+ NAME_FUNC_OFFSET(11939, glVertexAttrib3fvNV, glVertexAttrib3fvNV, NULL, _gloffset_VertexAttrib3fvNV),
+ NAME_FUNC_OFFSET(11959, glVertexAttrib3sNV, glVertexAttrib3sNV, NULL, _gloffset_VertexAttrib3sNV),
+ NAME_FUNC_OFFSET(11978, glVertexAttrib3svNV, glVertexAttrib3svNV, NULL, _gloffset_VertexAttrib3svNV),
+ NAME_FUNC_OFFSET(11998, glVertexAttrib4dNV, glVertexAttrib4dNV, NULL, _gloffset_VertexAttrib4dNV),
+ NAME_FUNC_OFFSET(12017, glVertexAttrib4dvNV, glVertexAttrib4dvNV, NULL, _gloffset_VertexAttrib4dvNV),
+ NAME_FUNC_OFFSET(12037, glVertexAttrib4fNV, glVertexAttrib4fNV, NULL, _gloffset_VertexAttrib4fNV),
+ NAME_FUNC_OFFSET(12056, glVertexAttrib4fvNV, glVertexAttrib4fvNV, NULL, _gloffset_VertexAttrib4fvNV),
+ NAME_FUNC_OFFSET(12076, glVertexAttrib4sNV, glVertexAttrib4sNV, NULL, _gloffset_VertexAttrib4sNV),
+ NAME_FUNC_OFFSET(12095, glVertexAttrib4svNV, glVertexAttrib4svNV, NULL, _gloffset_VertexAttrib4svNV),
+ NAME_FUNC_OFFSET(12115, glVertexAttrib4ubNV, glVertexAttrib4ubNV, NULL, _gloffset_VertexAttrib4ubNV),
+ NAME_FUNC_OFFSET(12135, glVertexAttrib4ubvNV, glVertexAttrib4ubvNV, NULL, _gloffset_VertexAttrib4ubvNV),
+ NAME_FUNC_OFFSET(12156, glVertexAttribPointerNV, glVertexAttribPointerNV, NULL, _gloffset_VertexAttribPointerNV),
+ NAME_FUNC_OFFSET(12180, glVertexAttribs1dvNV, glVertexAttribs1dvNV, NULL, _gloffset_VertexAttribs1dvNV),
+ NAME_FUNC_OFFSET(12201, glVertexAttribs1fvNV, glVertexAttribs1fvNV, NULL, _gloffset_VertexAttribs1fvNV),
+ NAME_FUNC_OFFSET(12222, glVertexAttribs1svNV, glVertexAttribs1svNV, NULL, _gloffset_VertexAttribs1svNV),
+ NAME_FUNC_OFFSET(12243, glVertexAttribs2dvNV, glVertexAttribs2dvNV, NULL, _gloffset_VertexAttribs2dvNV),
+ NAME_FUNC_OFFSET(12264, glVertexAttribs2fvNV, glVertexAttribs2fvNV, NULL, _gloffset_VertexAttribs2fvNV),
+ NAME_FUNC_OFFSET(12285, glVertexAttribs2svNV, glVertexAttribs2svNV, NULL, _gloffset_VertexAttribs2svNV),
+ NAME_FUNC_OFFSET(12306, glVertexAttribs3dvNV, glVertexAttribs3dvNV, NULL, _gloffset_VertexAttribs3dvNV),
+ NAME_FUNC_OFFSET(12327, glVertexAttribs3fvNV, glVertexAttribs3fvNV, NULL, _gloffset_VertexAttribs3fvNV),
+ NAME_FUNC_OFFSET(12348, glVertexAttribs3svNV, glVertexAttribs3svNV, NULL, _gloffset_VertexAttribs3svNV),
+ NAME_FUNC_OFFSET(12369, glVertexAttribs4dvNV, glVertexAttribs4dvNV, NULL, _gloffset_VertexAttribs4dvNV),
+ NAME_FUNC_OFFSET(12390, glVertexAttribs4fvNV, glVertexAttribs4fvNV, NULL, _gloffset_VertexAttribs4fvNV),
+ NAME_FUNC_OFFSET(12411, glVertexAttribs4svNV, glVertexAttribs4svNV, NULL, _gloffset_VertexAttribs4svNV),
+ NAME_FUNC_OFFSET(12432, glVertexAttribs4ubvNV, glVertexAttribs4ubvNV, NULL, _gloffset_VertexAttribs4ubvNV),
+ NAME_FUNC_OFFSET(12454, glGetTexBumpParameterfvATI, glGetTexBumpParameterfvATI, NULL, _gloffset_GetTexBumpParameterfvATI),
+ NAME_FUNC_OFFSET(12481, glGetTexBumpParameterivATI, glGetTexBumpParameterivATI, NULL, _gloffset_GetTexBumpParameterivATI),
+ NAME_FUNC_OFFSET(12508, glTexBumpParameterfvATI, glTexBumpParameterfvATI, NULL, _gloffset_TexBumpParameterfvATI),
+ NAME_FUNC_OFFSET(12532, glTexBumpParameterivATI, glTexBumpParameterivATI, NULL, _gloffset_TexBumpParameterivATI),
+ NAME_FUNC_OFFSET(12556, glAlphaFragmentOp1ATI, glAlphaFragmentOp1ATI, NULL, _gloffset_AlphaFragmentOp1ATI),
+ NAME_FUNC_OFFSET(12578, glAlphaFragmentOp2ATI, glAlphaFragmentOp2ATI, NULL, _gloffset_AlphaFragmentOp2ATI),
+ NAME_FUNC_OFFSET(12600, glAlphaFragmentOp3ATI, glAlphaFragmentOp3ATI, NULL, _gloffset_AlphaFragmentOp3ATI),
+ NAME_FUNC_OFFSET(12622, glBeginFragmentShaderATI, glBeginFragmentShaderATI, NULL, _gloffset_BeginFragmentShaderATI),
+ NAME_FUNC_OFFSET(12647, glBindFragmentShaderATI, glBindFragmentShaderATI, NULL, _gloffset_BindFragmentShaderATI),
+ NAME_FUNC_OFFSET(12671, glColorFragmentOp1ATI, glColorFragmentOp1ATI, NULL, _gloffset_ColorFragmentOp1ATI),
+ NAME_FUNC_OFFSET(12693, glColorFragmentOp2ATI, glColorFragmentOp2ATI, NULL, _gloffset_ColorFragmentOp2ATI),
+ NAME_FUNC_OFFSET(12715, glColorFragmentOp3ATI, glColorFragmentOp3ATI, NULL, _gloffset_ColorFragmentOp3ATI),
+ NAME_FUNC_OFFSET(12737, glDeleteFragmentShaderATI, glDeleteFragmentShaderATI, NULL, _gloffset_DeleteFragmentShaderATI),
+ NAME_FUNC_OFFSET(12763, glEndFragmentShaderATI, glEndFragmentShaderATI, NULL, _gloffset_EndFragmentShaderATI),
+ NAME_FUNC_OFFSET(12786, glGenFragmentShadersATI, glGenFragmentShadersATI, NULL, _gloffset_GenFragmentShadersATI),
+ NAME_FUNC_OFFSET(12810, glPassTexCoordATI, glPassTexCoordATI, NULL, _gloffset_PassTexCoordATI),
+ NAME_FUNC_OFFSET(12828, glSampleMapATI, glSampleMapATI, NULL, _gloffset_SampleMapATI),
+ NAME_FUNC_OFFSET(12843, glSetFragmentShaderConstantATI, glSetFragmentShaderConstantATI, NULL, _gloffset_SetFragmentShaderConstantATI),
+ NAME_FUNC_OFFSET(12874, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
+ NAME_FUNC_OFFSET(12894, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
+ NAME_FUNC_OFFSET(12915, gl_dispatch_stub_750, gl_dispatch_stub_750, NULL, _gloffset_ActiveStencilFaceEXT),
+ NAME_FUNC_OFFSET(12938, gl_dispatch_stub_751, gl_dispatch_stub_751, NULL, _gloffset_BindVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(12961, gl_dispatch_stub_752, gl_dispatch_stub_752, NULL, _gloffset_DeleteVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(12987, gl_dispatch_stub_753, gl_dispatch_stub_753, NULL, _gloffset_GenVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(13010, gl_dispatch_stub_754, gl_dispatch_stub_754, NULL, _gloffset_IsVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(13031, glGetProgramNamedParameterdvNV, glGetProgramNamedParameterdvNV, NULL, _gloffset_GetProgramNamedParameterdvNV),
+ NAME_FUNC_OFFSET(13062, glGetProgramNamedParameterfvNV, glGetProgramNamedParameterfvNV, NULL, _gloffset_GetProgramNamedParameterfvNV),
+ NAME_FUNC_OFFSET(13093, glProgramNamedParameter4dNV, glProgramNamedParameter4dNV, NULL, _gloffset_ProgramNamedParameter4dNV),
+ NAME_FUNC_OFFSET(13121, glProgramNamedParameter4dvNV, glProgramNamedParameter4dvNV, NULL, _gloffset_ProgramNamedParameter4dvNV),
+ NAME_FUNC_OFFSET(13150, glProgramNamedParameter4fNV, glProgramNamedParameter4fNV, NULL, _gloffset_ProgramNamedParameter4fNV),
+ NAME_FUNC_OFFSET(13178, glProgramNamedParameter4fvNV, glProgramNamedParameter4fvNV, NULL, _gloffset_ProgramNamedParameter4fvNV),
+ NAME_FUNC_OFFSET(13207, gl_dispatch_stub_761, gl_dispatch_stub_761, NULL, _gloffset_DepthBoundsEXT),
+ NAME_FUNC_OFFSET(13224, gl_dispatch_stub_762, gl_dispatch_stub_762, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(13251, glBindFramebufferEXT, glBindFramebufferEXT, NULL, _gloffset_BindFramebufferEXT),
+ NAME_FUNC_OFFSET(13272, glBindRenderbufferEXT, glBindRenderbufferEXT, NULL, _gloffset_BindRenderbufferEXT),
+ NAME_FUNC_OFFSET(13294, glCheckFramebufferStatusEXT, glCheckFramebufferStatusEXT, NULL, _gloffset_CheckFramebufferStatusEXT),
+ NAME_FUNC_OFFSET(13322, glDeleteFramebuffersEXT, glDeleteFramebuffersEXT, NULL, _gloffset_DeleteFramebuffersEXT),
+ NAME_FUNC_OFFSET(13346, glDeleteRenderbuffersEXT, glDeleteRenderbuffersEXT, NULL, _gloffset_DeleteRenderbuffersEXT),
+ NAME_FUNC_OFFSET(13371, glFramebufferRenderbufferEXT, glFramebufferRenderbufferEXT, NULL, _gloffset_FramebufferRenderbufferEXT),
+ NAME_FUNC_OFFSET(13400, glFramebufferTexture1DEXT, glFramebufferTexture1DEXT, NULL, _gloffset_FramebufferTexture1DEXT),
+ NAME_FUNC_OFFSET(13426, glFramebufferTexture2DEXT, glFramebufferTexture2DEXT, NULL, _gloffset_FramebufferTexture2DEXT),
+ NAME_FUNC_OFFSET(13452, glFramebufferTexture3DEXT, glFramebufferTexture3DEXT, NULL, _gloffset_FramebufferTexture3DEXT),
+ NAME_FUNC_OFFSET(13478, glGenFramebuffersEXT, glGenFramebuffersEXT, NULL, _gloffset_GenFramebuffersEXT),
+ NAME_FUNC_OFFSET(13499, glGenRenderbuffersEXT, glGenRenderbuffersEXT, NULL, _gloffset_GenRenderbuffersEXT),
+ NAME_FUNC_OFFSET(13521, glGenerateMipmapEXT, glGenerateMipmapEXT, NULL, _gloffset_GenerateMipmapEXT),
+ NAME_FUNC_OFFSET(13541, glGetFramebufferAttachmentParameterivEXT, glGetFramebufferAttachmentParameterivEXT, NULL, _gloffset_GetFramebufferAttachmentParameterivEXT),
+ NAME_FUNC_OFFSET(13582, glGetRenderbufferParameterivEXT, glGetRenderbufferParameterivEXT, NULL, _gloffset_GetRenderbufferParameterivEXT),
+ NAME_FUNC_OFFSET(13614, glIsFramebufferEXT, glIsFramebufferEXT, NULL, _gloffset_IsFramebufferEXT),
+ NAME_FUNC_OFFSET(13633, glIsRenderbufferEXT, glIsRenderbufferEXT, NULL, _gloffset_IsRenderbufferEXT),
+ NAME_FUNC_OFFSET(13653, glRenderbufferStorageEXT, glRenderbufferStorageEXT, NULL, _gloffset_RenderbufferStorageEXT),
+ NAME_FUNC_OFFSET(13678, gl_dispatch_stub_780, gl_dispatch_stub_780, NULL, _gloffset_BlitFramebufferEXT),
+ NAME_FUNC_OFFSET(13699, gl_dispatch_stub_781, gl_dispatch_stub_781, NULL, _gloffset_BufferParameteriAPPLE),
+ NAME_FUNC_OFFSET(13723, gl_dispatch_stub_782, gl_dispatch_stub_782, NULL, _gloffset_FlushMappedBufferRangeAPPLE),
+ NAME_FUNC_OFFSET(13753, glFramebufferTextureLayerEXT, glFramebufferTextureLayerEXT, NULL, _gloffset_FramebufferTextureLayerEXT),
+ NAME_FUNC_OFFSET(13782, glProvokingVertexEXT, glProvokingVertexEXT, NULL, _gloffset_ProvokingVertexEXT),
+ NAME_FUNC_OFFSET(13803, gl_dispatch_stub_785, gl_dispatch_stub_785, NULL, _gloffset_GetTexParameterPointervAPPLE),
+ NAME_FUNC_OFFSET(13834, gl_dispatch_stub_786, gl_dispatch_stub_786, NULL, _gloffset_TextureRangeAPPLE),
+ NAME_FUNC_OFFSET(13854, gl_dispatch_stub_787, gl_dispatch_stub_787, NULL, _gloffset_StencilFuncSeparateATI),
+ NAME_FUNC_OFFSET(13879, gl_dispatch_stub_788, gl_dispatch_stub_788, NULL, _gloffset_ProgramEnvParameters4fvEXT),
+ NAME_FUNC_OFFSET(13908, gl_dispatch_stub_789, gl_dispatch_stub_789, NULL, _gloffset_ProgramLocalParameters4fvEXT),
+ NAME_FUNC_OFFSET(13939, gl_dispatch_stub_790, gl_dispatch_stub_790, NULL, _gloffset_GetQueryObjecti64vEXT),
+ NAME_FUNC_OFFSET(13963, gl_dispatch_stub_791, gl_dispatch_stub_791, NULL, _gloffset_GetQueryObjectui64vEXT),
+ NAME_FUNC_OFFSET(13988, glArrayElement, glArrayElement, NULL, _gloffset_ArrayElement),
+ NAME_FUNC_OFFSET(14006, glBindTexture, glBindTexture, NULL, _gloffset_BindTexture),
+ NAME_FUNC_OFFSET(14023, glDrawArrays, glDrawArrays, NULL, _gloffset_DrawArrays),
+ NAME_FUNC_OFFSET(14039, glAreTexturesResident, glAreTexturesResidentEXT, glAreTexturesResidentEXT, _gloffset_AreTexturesResident),
+ NAME_FUNC_OFFSET(14064, glCopyTexImage1D, glCopyTexImage1D, NULL, _gloffset_CopyTexImage1D),
+ NAME_FUNC_OFFSET(14084, glCopyTexImage2D, glCopyTexImage2D, NULL, _gloffset_CopyTexImage2D),
+ NAME_FUNC_OFFSET(14104, glCopyTexSubImage1D, glCopyTexSubImage1D, NULL, _gloffset_CopyTexSubImage1D),
+ NAME_FUNC_OFFSET(14127, glCopyTexSubImage2D, glCopyTexSubImage2D, NULL, _gloffset_CopyTexSubImage2D),
+ NAME_FUNC_OFFSET(14150, glDeleteTextures, glDeleteTexturesEXT, glDeleteTexturesEXT, _gloffset_DeleteTextures),
+ NAME_FUNC_OFFSET(14170, glGenTextures, glGenTexturesEXT, glGenTexturesEXT, _gloffset_GenTextures),
+ NAME_FUNC_OFFSET(14187, glGetPointerv, glGetPointerv, NULL, _gloffset_GetPointerv),
+ NAME_FUNC_OFFSET(14204, glIsTexture, glIsTextureEXT, glIsTextureEXT, _gloffset_IsTexture),
+ NAME_FUNC_OFFSET(14219, glPrioritizeTextures, glPrioritizeTextures, NULL, _gloffset_PrioritizeTextures),
+ NAME_FUNC_OFFSET(14243, glTexSubImage1D, glTexSubImage1D, NULL, _gloffset_TexSubImage1D),
+ NAME_FUNC_OFFSET(14262, glTexSubImage2D, glTexSubImage2D, NULL, _gloffset_TexSubImage2D),
+ NAME_FUNC_OFFSET(14281, glBlendColor, glBlendColor, NULL, _gloffset_BlendColor),
+ NAME_FUNC_OFFSET(14297, glBlendEquation, glBlendEquation, NULL, _gloffset_BlendEquation),
+ NAME_FUNC_OFFSET(14316, glDrawRangeElements, glDrawRangeElements, NULL, _gloffset_DrawRangeElements),
+ NAME_FUNC_OFFSET(14339, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
+ NAME_FUNC_OFFSET(14355, glColorTable, glColorTable, NULL, _gloffset_ColorTable),
+ NAME_FUNC_OFFSET(14371, glColorTableParameterfv, glColorTableParameterfv, NULL, _gloffset_ColorTableParameterfv),
+ NAME_FUNC_OFFSET(14398, glColorTableParameteriv, glColorTableParameteriv, NULL, _gloffset_ColorTableParameteriv),
+ NAME_FUNC_OFFSET(14425, glCopyColorTable, glCopyColorTable, NULL, _gloffset_CopyColorTable),
+ NAME_FUNC_OFFSET(14445, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
+ NAME_FUNC_OFFSET(14464, glGetColorTable, glGetColorTableEXT, glGetColorTableEXT, _gloffset_GetColorTable),
+ NAME_FUNC_OFFSET(14483, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
+ NAME_FUNC_OFFSET(14513, glGetColorTableParameterfv, glGetColorTableParameterfvEXT, glGetColorTableParameterfvEXT, _gloffset_GetColorTableParameterfv),
+ NAME_FUNC_OFFSET(14543, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
+ NAME_FUNC_OFFSET(14573, glGetColorTableParameteriv, glGetColorTableParameterivEXT, glGetColorTableParameterivEXT, _gloffset_GetColorTableParameteriv),
+ NAME_FUNC_OFFSET(14603, glColorSubTable, glColorSubTable, NULL, _gloffset_ColorSubTable),
+ NAME_FUNC_OFFSET(14622, glCopyColorSubTable, glCopyColorSubTable, NULL, _gloffset_CopyColorSubTable),
+ NAME_FUNC_OFFSET(14645, glConvolutionFilter1D, glConvolutionFilter1D, NULL, _gloffset_ConvolutionFilter1D),
+ NAME_FUNC_OFFSET(14670, glConvolutionFilter2D, glConvolutionFilter2D, NULL, _gloffset_ConvolutionFilter2D),
+ NAME_FUNC_OFFSET(14695, glConvolutionParameterf, glConvolutionParameterf, NULL, _gloffset_ConvolutionParameterf),
+ NAME_FUNC_OFFSET(14722, glConvolutionParameterfv, glConvolutionParameterfv, NULL, _gloffset_ConvolutionParameterfv),
+ NAME_FUNC_OFFSET(14750, glConvolutionParameteri, glConvolutionParameteri, NULL, _gloffset_ConvolutionParameteri),
+ NAME_FUNC_OFFSET(14777, glConvolutionParameteriv, glConvolutionParameteriv, NULL, _gloffset_ConvolutionParameteriv),
+ NAME_FUNC_OFFSET(14805, glCopyConvolutionFilter1D, glCopyConvolutionFilter1D, NULL, _gloffset_CopyConvolutionFilter1D),
+ NAME_FUNC_OFFSET(14834, glCopyConvolutionFilter2D, glCopyConvolutionFilter2D, NULL, _gloffset_CopyConvolutionFilter2D),
+ NAME_FUNC_OFFSET(14863, glGetConvolutionFilter, gl_dispatch_stub_356, gl_dispatch_stub_356, _gloffset_GetConvolutionFilter),
+ NAME_FUNC_OFFSET(14889, glGetConvolutionParameterfv, gl_dispatch_stub_357, gl_dispatch_stub_357, _gloffset_GetConvolutionParameterfv),
+ NAME_FUNC_OFFSET(14920, glGetConvolutionParameteriv, gl_dispatch_stub_358, gl_dispatch_stub_358, _gloffset_GetConvolutionParameteriv),
+ NAME_FUNC_OFFSET(14951, glGetSeparableFilter, gl_dispatch_stub_359, gl_dispatch_stub_359, _gloffset_GetSeparableFilter),
+ NAME_FUNC_OFFSET(14975, glSeparableFilter2D, glSeparableFilter2D, NULL, _gloffset_SeparableFilter2D),
+ NAME_FUNC_OFFSET(14998, glGetHistogram, gl_dispatch_stub_361, gl_dispatch_stub_361, _gloffset_GetHistogram),
+ NAME_FUNC_OFFSET(15016, glGetHistogramParameterfv, gl_dispatch_stub_362, gl_dispatch_stub_362, _gloffset_GetHistogramParameterfv),
+ NAME_FUNC_OFFSET(15045, glGetHistogramParameteriv, gl_dispatch_stub_363, gl_dispatch_stub_363, _gloffset_GetHistogramParameteriv),
+ NAME_FUNC_OFFSET(15074, glGetMinmax, gl_dispatch_stub_364, gl_dispatch_stub_364, _gloffset_GetMinmax),
+ NAME_FUNC_OFFSET(15089, glGetMinmaxParameterfv, gl_dispatch_stub_365, gl_dispatch_stub_365, _gloffset_GetMinmaxParameterfv),
+ NAME_FUNC_OFFSET(15115, glGetMinmaxParameteriv, gl_dispatch_stub_366, gl_dispatch_stub_366, _gloffset_GetMinmaxParameteriv),
+ NAME_FUNC_OFFSET(15141, glHistogram, glHistogram, NULL, _gloffset_Histogram),
+ NAME_FUNC_OFFSET(15156, glMinmax, glMinmax, NULL, _gloffset_Minmax),
+ NAME_FUNC_OFFSET(15168, glResetHistogram, glResetHistogram, NULL, _gloffset_ResetHistogram),
+ NAME_FUNC_OFFSET(15188, glResetMinmax, glResetMinmax, NULL, _gloffset_ResetMinmax),
+ NAME_FUNC_OFFSET(15205, glTexImage3D, glTexImage3D, NULL, _gloffset_TexImage3D),
+ NAME_FUNC_OFFSET(15221, glTexSubImage3D, glTexSubImage3D, NULL, _gloffset_TexSubImage3D),
+ NAME_FUNC_OFFSET(15240, glCopyTexSubImage3D, glCopyTexSubImage3D, NULL, _gloffset_CopyTexSubImage3D),
+ NAME_FUNC_OFFSET(15263, glActiveTextureARB, glActiveTextureARB, NULL, _gloffset_ActiveTextureARB),
+ NAME_FUNC_OFFSET(15279, glClientActiveTextureARB, glClientActiveTextureARB, NULL, _gloffset_ClientActiveTextureARB),
+ NAME_FUNC_OFFSET(15301, glMultiTexCoord1dARB, glMultiTexCoord1dARB, NULL, _gloffset_MultiTexCoord1dARB),
+ NAME_FUNC_OFFSET(15319, glMultiTexCoord1dvARB, glMultiTexCoord1dvARB, NULL, _gloffset_MultiTexCoord1dvARB),
+ NAME_FUNC_OFFSET(15338, glMultiTexCoord1fARB, glMultiTexCoord1fARB, NULL, _gloffset_MultiTexCoord1fARB),
+ NAME_FUNC_OFFSET(15356, glMultiTexCoord1fvARB, glMultiTexCoord1fvARB, NULL, _gloffset_MultiTexCoord1fvARB),
+ NAME_FUNC_OFFSET(15375, glMultiTexCoord1iARB, glMultiTexCoord1iARB, NULL, _gloffset_MultiTexCoord1iARB),
+ NAME_FUNC_OFFSET(15393, glMultiTexCoord1ivARB, glMultiTexCoord1ivARB, NULL, _gloffset_MultiTexCoord1ivARB),
+ NAME_FUNC_OFFSET(15412, glMultiTexCoord1sARB, glMultiTexCoord1sARB, NULL, _gloffset_MultiTexCoord1sARB),
+ NAME_FUNC_OFFSET(15430, glMultiTexCoord1svARB, glMultiTexCoord1svARB, NULL, _gloffset_MultiTexCoord1svARB),
+ NAME_FUNC_OFFSET(15449, glMultiTexCoord2dARB, glMultiTexCoord2dARB, NULL, _gloffset_MultiTexCoord2dARB),
+ NAME_FUNC_OFFSET(15467, glMultiTexCoord2dvARB, glMultiTexCoord2dvARB, NULL, _gloffset_MultiTexCoord2dvARB),
+ NAME_FUNC_OFFSET(15486, glMultiTexCoord2fARB, glMultiTexCoord2fARB, NULL, _gloffset_MultiTexCoord2fARB),
+ NAME_FUNC_OFFSET(15504, glMultiTexCoord2fvARB, glMultiTexCoord2fvARB, NULL, _gloffset_MultiTexCoord2fvARB),
+ NAME_FUNC_OFFSET(15523, glMultiTexCoord2iARB, glMultiTexCoord2iARB, NULL, _gloffset_MultiTexCoord2iARB),
+ NAME_FUNC_OFFSET(15541, glMultiTexCoord2ivARB, glMultiTexCoord2ivARB, NULL, _gloffset_MultiTexCoord2ivARB),
+ NAME_FUNC_OFFSET(15560, glMultiTexCoord2sARB, glMultiTexCoord2sARB, NULL, _gloffset_MultiTexCoord2sARB),
+ NAME_FUNC_OFFSET(15578, glMultiTexCoord2svARB, glMultiTexCoord2svARB, NULL, _gloffset_MultiTexCoord2svARB),
+ NAME_FUNC_OFFSET(15597, glMultiTexCoord3dARB, glMultiTexCoord3dARB, NULL, _gloffset_MultiTexCoord3dARB),
+ NAME_FUNC_OFFSET(15615, glMultiTexCoord3dvARB, glMultiTexCoord3dvARB, NULL, _gloffset_MultiTexCoord3dvARB),
+ NAME_FUNC_OFFSET(15634, glMultiTexCoord3fARB, glMultiTexCoord3fARB, NULL, _gloffset_MultiTexCoord3fARB),
+ NAME_FUNC_OFFSET(15652, glMultiTexCoord3fvARB, glMultiTexCoord3fvARB, NULL, _gloffset_MultiTexCoord3fvARB),
+ NAME_FUNC_OFFSET(15671, glMultiTexCoord3iARB, glMultiTexCoord3iARB, NULL, _gloffset_MultiTexCoord3iARB),
+ NAME_FUNC_OFFSET(15689, glMultiTexCoord3ivARB, glMultiTexCoord3ivARB, NULL, _gloffset_MultiTexCoord3ivARB),
+ NAME_FUNC_OFFSET(15708, glMultiTexCoord3sARB, glMultiTexCoord3sARB, NULL, _gloffset_MultiTexCoord3sARB),
+ NAME_FUNC_OFFSET(15726, glMultiTexCoord3svARB, glMultiTexCoord3svARB, NULL, _gloffset_MultiTexCoord3svARB),
+ NAME_FUNC_OFFSET(15745, glMultiTexCoord4dARB, glMultiTexCoord4dARB, NULL, _gloffset_MultiTexCoord4dARB),
+ NAME_FUNC_OFFSET(15763, glMultiTexCoord4dvARB, glMultiTexCoord4dvARB, NULL, _gloffset_MultiTexCoord4dvARB),
+ NAME_FUNC_OFFSET(15782, glMultiTexCoord4fARB, glMultiTexCoord4fARB, NULL, _gloffset_MultiTexCoord4fARB),
+ NAME_FUNC_OFFSET(15800, glMultiTexCoord4fvARB, glMultiTexCoord4fvARB, NULL, _gloffset_MultiTexCoord4fvARB),
+ NAME_FUNC_OFFSET(15819, glMultiTexCoord4iARB, glMultiTexCoord4iARB, NULL, _gloffset_MultiTexCoord4iARB),
+ NAME_FUNC_OFFSET(15837, glMultiTexCoord4ivARB, glMultiTexCoord4ivARB, NULL, _gloffset_MultiTexCoord4ivARB),
+ NAME_FUNC_OFFSET(15856, glMultiTexCoord4sARB, glMultiTexCoord4sARB, NULL, _gloffset_MultiTexCoord4sARB),
+ NAME_FUNC_OFFSET(15874, glMultiTexCoord4svARB, glMultiTexCoord4svARB, NULL, _gloffset_MultiTexCoord4svARB),
+ NAME_FUNC_OFFSET(15893, glStencilOpSeparate, glStencilOpSeparate, NULL, _gloffset_StencilOpSeparate),
+ NAME_FUNC_OFFSET(15916, glLoadTransposeMatrixdARB, glLoadTransposeMatrixdARB, NULL, _gloffset_LoadTransposeMatrixdARB),
+ NAME_FUNC_OFFSET(15939, glLoadTransposeMatrixfARB, glLoadTransposeMatrixfARB, NULL, _gloffset_LoadTransposeMatrixfARB),
+ NAME_FUNC_OFFSET(15962, glMultTransposeMatrixdARB, glMultTransposeMatrixdARB, NULL, _gloffset_MultTransposeMatrixdARB),
+ NAME_FUNC_OFFSET(15985, glMultTransposeMatrixfARB, glMultTransposeMatrixfARB, NULL, _gloffset_MultTransposeMatrixfARB),
+ NAME_FUNC_OFFSET(16008, glSampleCoverageARB, glSampleCoverageARB, NULL, _gloffset_SampleCoverageARB),
+ NAME_FUNC_OFFSET(16025, glCompressedTexImage1DARB, glCompressedTexImage1DARB, NULL, _gloffset_CompressedTexImage1DARB),
+ NAME_FUNC_OFFSET(16048, glCompressedTexImage2DARB, glCompressedTexImage2DARB, NULL, _gloffset_CompressedTexImage2DARB),
+ NAME_FUNC_OFFSET(16071, glCompressedTexImage3DARB, glCompressedTexImage3DARB, NULL, _gloffset_CompressedTexImage3DARB),
+ NAME_FUNC_OFFSET(16094, glCompressedTexSubImage1DARB, glCompressedTexSubImage1DARB, NULL, _gloffset_CompressedTexSubImage1DARB),
+ NAME_FUNC_OFFSET(16120, glCompressedTexSubImage2DARB, glCompressedTexSubImage2DARB, NULL, _gloffset_CompressedTexSubImage2DARB),
+ NAME_FUNC_OFFSET(16146, glCompressedTexSubImage3DARB, glCompressedTexSubImage3DARB, NULL, _gloffset_CompressedTexSubImage3DARB),
+ NAME_FUNC_OFFSET(16172, glGetCompressedTexImageARB, glGetCompressedTexImageARB, NULL, _gloffset_GetCompressedTexImageARB),
+ NAME_FUNC_OFFSET(16196, glDisableVertexAttribArrayARB, glDisableVertexAttribArrayARB, NULL, _gloffset_DisableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET(16223, glEnableVertexAttribArrayARB, glEnableVertexAttribArrayARB, NULL, _gloffset_EnableVertexAttribArrayARB),
+ NAME_FUNC_OFFSET(16249, glGetVertexAttribdvARB, glGetVertexAttribdvARB, NULL, _gloffset_GetVertexAttribdvARB),
+ NAME_FUNC_OFFSET(16269, glGetVertexAttribfvARB, glGetVertexAttribfvARB, NULL, _gloffset_GetVertexAttribfvARB),
+ NAME_FUNC_OFFSET(16289, glGetVertexAttribivARB, glGetVertexAttribivARB, NULL, _gloffset_GetVertexAttribivARB),
+ NAME_FUNC_OFFSET(16309, glProgramEnvParameter4dARB, glProgramEnvParameter4dARB, NULL, _gloffset_ProgramEnvParameter4dARB),
+ NAME_FUNC_OFFSET(16332, glProgramEnvParameter4dvARB, glProgramEnvParameter4dvARB, NULL, _gloffset_ProgramEnvParameter4dvARB),
+ NAME_FUNC_OFFSET(16356, glProgramEnvParameter4fARB, glProgramEnvParameter4fARB, NULL, _gloffset_ProgramEnvParameter4fARB),
+ NAME_FUNC_OFFSET(16379, glProgramEnvParameter4fvARB, glProgramEnvParameter4fvARB, NULL, _gloffset_ProgramEnvParameter4fvARB),
+ NAME_FUNC_OFFSET(16403, glVertexAttrib1dARB, glVertexAttrib1dARB, NULL, _gloffset_VertexAttrib1dARB),
+ NAME_FUNC_OFFSET(16420, glVertexAttrib1dvARB, glVertexAttrib1dvARB, NULL, _gloffset_VertexAttrib1dvARB),
+ NAME_FUNC_OFFSET(16438, glVertexAttrib1fARB, glVertexAttrib1fARB, NULL, _gloffset_VertexAttrib1fARB),
+ NAME_FUNC_OFFSET(16455, glVertexAttrib1fvARB, glVertexAttrib1fvARB, NULL, _gloffset_VertexAttrib1fvARB),
+ NAME_FUNC_OFFSET(16473, glVertexAttrib1sARB, glVertexAttrib1sARB, NULL, _gloffset_VertexAttrib1sARB),
+ NAME_FUNC_OFFSET(16490, glVertexAttrib1svARB, glVertexAttrib1svARB, NULL, _gloffset_VertexAttrib1svARB),
+ NAME_FUNC_OFFSET(16508, glVertexAttrib2dARB, glVertexAttrib2dARB, NULL, _gloffset_VertexAttrib2dARB),
+ NAME_FUNC_OFFSET(16525, glVertexAttrib2dvARB, glVertexAttrib2dvARB, NULL, _gloffset_VertexAttrib2dvARB),
+ NAME_FUNC_OFFSET(16543, glVertexAttrib2fARB, glVertexAttrib2fARB, NULL, _gloffset_VertexAttrib2fARB),
+ NAME_FUNC_OFFSET(16560, glVertexAttrib2fvARB, glVertexAttrib2fvARB, NULL, _gloffset_VertexAttrib2fvARB),
+ NAME_FUNC_OFFSET(16578, glVertexAttrib2sARB, glVertexAttrib2sARB, NULL, _gloffset_VertexAttrib2sARB),
+ NAME_FUNC_OFFSET(16595, glVertexAttrib2svARB, glVertexAttrib2svARB, NULL, _gloffset_VertexAttrib2svARB),
+ NAME_FUNC_OFFSET(16613, glVertexAttrib3dARB, glVertexAttrib3dARB, NULL, _gloffset_VertexAttrib3dARB),
+ NAME_FUNC_OFFSET(16630, glVertexAttrib3dvARB, glVertexAttrib3dvARB, NULL, _gloffset_VertexAttrib3dvARB),
+ NAME_FUNC_OFFSET(16648, glVertexAttrib3fARB, glVertexAttrib3fARB, NULL, _gloffset_VertexAttrib3fARB),
+ NAME_FUNC_OFFSET(16665, glVertexAttrib3fvARB, glVertexAttrib3fvARB, NULL, _gloffset_VertexAttrib3fvARB),
+ NAME_FUNC_OFFSET(16683, glVertexAttrib3sARB, glVertexAttrib3sARB, NULL, _gloffset_VertexAttrib3sARB),
+ NAME_FUNC_OFFSET(16700, glVertexAttrib3svARB, glVertexAttrib3svARB, NULL, _gloffset_VertexAttrib3svARB),
+ NAME_FUNC_OFFSET(16718, glVertexAttrib4NbvARB, glVertexAttrib4NbvARB, NULL, _gloffset_VertexAttrib4NbvARB),
+ NAME_FUNC_OFFSET(16737, glVertexAttrib4NivARB, glVertexAttrib4NivARB, NULL, _gloffset_VertexAttrib4NivARB),
+ NAME_FUNC_OFFSET(16756, glVertexAttrib4NsvARB, glVertexAttrib4NsvARB, NULL, _gloffset_VertexAttrib4NsvARB),
+ NAME_FUNC_OFFSET(16775, glVertexAttrib4NubARB, glVertexAttrib4NubARB, NULL, _gloffset_VertexAttrib4NubARB),
+ NAME_FUNC_OFFSET(16794, glVertexAttrib4NubvARB, glVertexAttrib4NubvARB, NULL, _gloffset_VertexAttrib4NubvARB),
+ NAME_FUNC_OFFSET(16814, glVertexAttrib4NuivARB, glVertexAttrib4NuivARB, NULL, _gloffset_VertexAttrib4NuivARB),
+ NAME_FUNC_OFFSET(16834, glVertexAttrib4NusvARB, glVertexAttrib4NusvARB, NULL, _gloffset_VertexAttrib4NusvARB),
+ NAME_FUNC_OFFSET(16854, glVertexAttrib4bvARB, glVertexAttrib4bvARB, NULL, _gloffset_VertexAttrib4bvARB),
+ NAME_FUNC_OFFSET(16872, glVertexAttrib4dARB, glVertexAttrib4dARB, NULL, _gloffset_VertexAttrib4dARB),
+ NAME_FUNC_OFFSET(16889, glVertexAttrib4dvARB, glVertexAttrib4dvARB, NULL, _gloffset_VertexAttrib4dvARB),
+ NAME_FUNC_OFFSET(16907, glVertexAttrib4fARB, glVertexAttrib4fARB, NULL, _gloffset_VertexAttrib4fARB),
+ NAME_FUNC_OFFSET(16924, glVertexAttrib4fvARB, glVertexAttrib4fvARB, NULL, _gloffset_VertexAttrib4fvARB),
+ NAME_FUNC_OFFSET(16942, glVertexAttrib4ivARB, glVertexAttrib4ivARB, NULL, _gloffset_VertexAttrib4ivARB),
+ NAME_FUNC_OFFSET(16960, glVertexAttrib4sARB, glVertexAttrib4sARB, NULL, _gloffset_VertexAttrib4sARB),
+ NAME_FUNC_OFFSET(16977, glVertexAttrib4svARB, glVertexAttrib4svARB, NULL, _gloffset_VertexAttrib4svARB),
+ NAME_FUNC_OFFSET(16995, glVertexAttrib4ubvARB, glVertexAttrib4ubvARB, NULL, _gloffset_VertexAttrib4ubvARB),
+ NAME_FUNC_OFFSET(17014, glVertexAttrib4uivARB, glVertexAttrib4uivARB, NULL, _gloffset_VertexAttrib4uivARB),
+ NAME_FUNC_OFFSET(17033, glVertexAttrib4usvARB, glVertexAttrib4usvARB, NULL, _gloffset_VertexAttrib4usvARB),
+ NAME_FUNC_OFFSET(17052, glVertexAttribPointerARB, glVertexAttribPointerARB, NULL, _gloffset_VertexAttribPointerARB),
+ NAME_FUNC_OFFSET(17074, glBindBufferARB, glBindBufferARB, NULL, _gloffset_BindBufferARB),
+ NAME_FUNC_OFFSET(17087, glBufferDataARB, glBufferDataARB, NULL, _gloffset_BufferDataARB),
+ NAME_FUNC_OFFSET(17100, glBufferSubDataARB, glBufferSubDataARB, NULL, _gloffset_BufferSubDataARB),
+ NAME_FUNC_OFFSET(17116, glDeleteBuffersARB, glDeleteBuffersARB, NULL, _gloffset_DeleteBuffersARB),
+ NAME_FUNC_OFFSET(17132, glGenBuffersARB, glGenBuffersARB, NULL, _gloffset_GenBuffersARB),
+ NAME_FUNC_OFFSET(17145, glGetBufferParameterivARB, glGetBufferParameterivARB, NULL, _gloffset_GetBufferParameterivARB),
+ NAME_FUNC_OFFSET(17168, glGetBufferPointervARB, glGetBufferPointervARB, NULL, _gloffset_GetBufferPointervARB),
+ NAME_FUNC_OFFSET(17188, glGetBufferSubDataARB, glGetBufferSubDataARB, NULL, _gloffset_GetBufferSubDataARB),
+ NAME_FUNC_OFFSET(17207, glIsBufferARB, glIsBufferARB, NULL, _gloffset_IsBufferARB),
+ NAME_FUNC_OFFSET(17218, glMapBufferARB, glMapBufferARB, NULL, _gloffset_MapBufferARB),
+ NAME_FUNC_OFFSET(17230, glUnmapBufferARB, glUnmapBufferARB, NULL, _gloffset_UnmapBufferARB),
+ NAME_FUNC_OFFSET(17244, glBeginQueryARB, glBeginQueryARB, NULL, _gloffset_BeginQueryARB),
+ NAME_FUNC_OFFSET(17257, glDeleteQueriesARB, glDeleteQueriesARB, NULL, _gloffset_DeleteQueriesARB),
+ NAME_FUNC_OFFSET(17273, glEndQueryARB, glEndQueryARB, NULL, _gloffset_EndQueryARB),
+ NAME_FUNC_OFFSET(17284, glGenQueriesARB, glGenQueriesARB, NULL, _gloffset_GenQueriesARB),
+ NAME_FUNC_OFFSET(17297, glGetQueryObjectivARB, glGetQueryObjectivARB, NULL, _gloffset_GetQueryObjectivARB),
+ NAME_FUNC_OFFSET(17316, glGetQueryObjectuivARB, glGetQueryObjectuivARB, NULL, _gloffset_GetQueryObjectuivARB),
+ NAME_FUNC_OFFSET(17336, glGetQueryivARB, glGetQueryivARB, NULL, _gloffset_GetQueryivARB),
+ NAME_FUNC_OFFSET(17349, glIsQueryARB, glIsQueryARB, NULL, _gloffset_IsQueryARB),
+ NAME_FUNC_OFFSET(17359, glCompileShaderARB, glCompileShaderARB, NULL, _gloffset_CompileShaderARB),
+ NAME_FUNC_OFFSET(17375, glGetActiveUniformARB, glGetActiveUniformARB, NULL, _gloffset_GetActiveUniformARB),
+ NAME_FUNC_OFFSET(17394, glGetShaderSourceARB, glGetShaderSourceARB, NULL, _gloffset_GetShaderSourceARB),
+ NAME_FUNC_OFFSET(17412, glGetUniformLocationARB, glGetUniformLocationARB, NULL, _gloffset_GetUniformLocationARB),
+ NAME_FUNC_OFFSET(17433, glGetUniformfvARB, glGetUniformfvARB, NULL, _gloffset_GetUniformfvARB),
+ NAME_FUNC_OFFSET(17448, glGetUniformivARB, glGetUniformivARB, NULL, _gloffset_GetUniformivARB),
+ NAME_FUNC_OFFSET(17463, glLinkProgramARB, glLinkProgramARB, NULL, _gloffset_LinkProgramARB),
+ NAME_FUNC_OFFSET(17477, glShaderSourceARB, glShaderSourceARB, NULL, _gloffset_ShaderSourceARB),
+ NAME_FUNC_OFFSET(17492, glUniform1fARB, glUniform1fARB, NULL, _gloffset_Uniform1fARB),
+ NAME_FUNC_OFFSET(17504, glUniform1fvARB, glUniform1fvARB, NULL, _gloffset_Uniform1fvARB),
+ NAME_FUNC_OFFSET(17517, glUniform1iARB, glUniform1iARB, NULL, _gloffset_Uniform1iARB),
+ NAME_FUNC_OFFSET(17529, glUniform1ivARB, glUniform1ivARB, NULL, _gloffset_Uniform1ivARB),
+ NAME_FUNC_OFFSET(17542, glUniform2fARB, glUniform2fARB, NULL, _gloffset_Uniform2fARB),
+ NAME_FUNC_OFFSET(17554, glUniform2fvARB, glUniform2fvARB, NULL, _gloffset_Uniform2fvARB),
+ NAME_FUNC_OFFSET(17567, glUniform2iARB, glUniform2iARB, NULL, _gloffset_Uniform2iARB),
+ NAME_FUNC_OFFSET(17579, glUniform2ivARB, glUniform2ivARB, NULL, _gloffset_Uniform2ivARB),
+ NAME_FUNC_OFFSET(17592, glUniform3fARB, glUniform3fARB, NULL, _gloffset_Uniform3fARB),
+ NAME_FUNC_OFFSET(17604, glUniform3fvARB, glUniform3fvARB, NULL, _gloffset_Uniform3fvARB),
+ NAME_FUNC_OFFSET(17617, glUniform3iARB, glUniform3iARB, NULL, _gloffset_Uniform3iARB),
+ NAME_FUNC_OFFSET(17629, glUniform3ivARB, glUniform3ivARB, NULL, _gloffset_Uniform3ivARB),
+ NAME_FUNC_OFFSET(17642, glUniform4fARB, glUniform4fARB, NULL, _gloffset_Uniform4fARB),
+ NAME_FUNC_OFFSET(17654, glUniform4fvARB, glUniform4fvARB, NULL, _gloffset_Uniform4fvARB),
+ NAME_FUNC_OFFSET(17667, glUniform4iARB, glUniform4iARB, NULL, _gloffset_Uniform4iARB),
+ NAME_FUNC_OFFSET(17679, glUniform4ivARB, glUniform4ivARB, NULL, _gloffset_Uniform4ivARB),
+ NAME_FUNC_OFFSET(17692, glUniformMatrix2fvARB, glUniformMatrix2fvARB, NULL, _gloffset_UniformMatrix2fvARB),
+ NAME_FUNC_OFFSET(17711, glUniformMatrix3fvARB, glUniformMatrix3fvARB, NULL, _gloffset_UniformMatrix3fvARB),
+ NAME_FUNC_OFFSET(17730, glUniformMatrix4fvARB, glUniformMatrix4fvARB, NULL, _gloffset_UniformMatrix4fvARB),
+ NAME_FUNC_OFFSET(17749, glUseProgramObjectARB, glUseProgramObjectARB, NULL, _gloffset_UseProgramObjectARB),
+ NAME_FUNC_OFFSET(17762, glValidateProgramARB, glValidateProgramARB, NULL, _gloffset_ValidateProgramARB),
+ NAME_FUNC_OFFSET(17780, glBindAttribLocationARB, glBindAttribLocationARB, NULL, _gloffset_BindAttribLocationARB),
+ NAME_FUNC_OFFSET(17801, glGetActiveAttribARB, glGetActiveAttribARB, NULL, _gloffset_GetActiveAttribARB),
+ NAME_FUNC_OFFSET(17819, glGetAttribLocationARB, glGetAttribLocationARB, NULL, _gloffset_GetAttribLocationARB),
+ NAME_FUNC_OFFSET(17839, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
+ NAME_FUNC_OFFSET(17853, glDrawBuffersARB, glDrawBuffersARB, NULL, _gloffset_DrawBuffersARB),
+ NAME_FUNC_OFFSET(17870, gl_dispatch_stub_581, gl_dispatch_stub_581, NULL, _gloffset_SampleMaskSGIS),
+ NAME_FUNC_OFFSET(17886, gl_dispatch_stub_582, gl_dispatch_stub_582, NULL, _gloffset_SamplePatternSGIS),
+ NAME_FUNC_OFFSET(17905, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(17923, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(17944, glPointParameterfEXT, glPointParameterfEXT, NULL, _gloffset_PointParameterfEXT),
+ NAME_FUNC_OFFSET(17966, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(17985, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(18007, glPointParameterfvEXT, glPointParameterfvEXT, NULL, _gloffset_PointParameterfvEXT),
+ NAME_FUNC_OFFSET(18030, glSecondaryColor3bEXT, glSecondaryColor3bEXT, NULL, _gloffset_SecondaryColor3bEXT),
+ NAME_FUNC_OFFSET(18049, glSecondaryColor3bvEXT, glSecondaryColor3bvEXT, NULL, _gloffset_SecondaryColor3bvEXT),
+ NAME_FUNC_OFFSET(18069, glSecondaryColor3dEXT, glSecondaryColor3dEXT, NULL, _gloffset_SecondaryColor3dEXT),
+ NAME_FUNC_OFFSET(18088, glSecondaryColor3dvEXT, glSecondaryColor3dvEXT, NULL, _gloffset_SecondaryColor3dvEXT),
+ NAME_FUNC_OFFSET(18108, glSecondaryColor3fEXT, glSecondaryColor3fEXT, NULL, _gloffset_SecondaryColor3fEXT),
+ NAME_FUNC_OFFSET(18127, glSecondaryColor3fvEXT, glSecondaryColor3fvEXT, NULL, _gloffset_SecondaryColor3fvEXT),
+ NAME_FUNC_OFFSET(18147, glSecondaryColor3iEXT, glSecondaryColor3iEXT, NULL, _gloffset_SecondaryColor3iEXT),
+ NAME_FUNC_OFFSET(18166, glSecondaryColor3ivEXT, glSecondaryColor3ivEXT, NULL, _gloffset_SecondaryColor3ivEXT),
+ NAME_FUNC_OFFSET(18186, glSecondaryColor3sEXT, glSecondaryColor3sEXT, NULL, _gloffset_SecondaryColor3sEXT),
+ NAME_FUNC_OFFSET(18205, glSecondaryColor3svEXT, glSecondaryColor3svEXT, NULL, _gloffset_SecondaryColor3svEXT),
+ NAME_FUNC_OFFSET(18225, glSecondaryColor3ubEXT, glSecondaryColor3ubEXT, NULL, _gloffset_SecondaryColor3ubEXT),
+ NAME_FUNC_OFFSET(18245, glSecondaryColor3ubvEXT, glSecondaryColor3ubvEXT, NULL, _gloffset_SecondaryColor3ubvEXT),
+ NAME_FUNC_OFFSET(18266, glSecondaryColor3uiEXT, glSecondaryColor3uiEXT, NULL, _gloffset_SecondaryColor3uiEXT),
+ NAME_FUNC_OFFSET(18286, glSecondaryColor3uivEXT, glSecondaryColor3uivEXT, NULL, _gloffset_SecondaryColor3uivEXT),
+ NAME_FUNC_OFFSET(18307, glSecondaryColor3usEXT, glSecondaryColor3usEXT, NULL, _gloffset_SecondaryColor3usEXT),
+ NAME_FUNC_OFFSET(18327, glSecondaryColor3usvEXT, glSecondaryColor3usvEXT, NULL, _gloffset_SecondaryColor3usvEXT),
+ NAME_FUNC_OFFSET(18348, glSecondaryColorPointerEXT, glSecondaryColorPointerEXT, NULL, _gloffset_SecondaryColorPointerEXT),
+ NAME_FUNC_OFFSET(18372, glMultiDrawArraysEXT, glMultiDrawArraysEXT, NULL, _gloffset_MultiDrawArraysEXT),
+ NAME_FUNC_OFFSET(18390, glMultiDrawElementsEXT, glMultiDrawElementsEXT, NULL, _gloffset_MultiDrawElementsEXT),
+ NAME_FUNC_OFFSET(18410, glFogCoordPointerEXT, glFogCoordPointerEXT, NULL, _gloffset_FogCoordPointerEXT),
+ NAME_FUNC_OFFSET(18428, glFogCoorddEXT, glFogCoorddEXT, NULL, _gloffset_FogCoorddEXT),
+ NAME_FUNC_OFFSET(18440, glFogCoorddvEXT, glFogCoorddvEXT, NULL, _gloffset_FogCoorddvEXT),
+ NAME_FUNC_OFFSET(18453, glFogCoordfEXT, glFogCoordfEXT, NULL, _gloffset_FogCoordfEXT),
+ NAME_FUNC_OFFSET(18465, glFogCoordfvEXT, glFogCoordfvEXT, NULL, _gloffset_FogCoordfvEXT),
+ NAME_FUNC_OFFSET(18478, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(18498, glBlendFuncSeparateEXT, glBlendFuncSeparateEXT, NULL, _gloffset_BlendFuncSeparateEXT),
+ NAME_FUNC_OFFSET(18522, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(18536, glWindowPos2dMESA, glWindowPos2dMESA, NULL, _gloffset_WindowPos2dMESA),
+ NAME_FUNC_OFFSET(18553, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(18568, glWindowPos2dvMESA, glWindowPos2dvMESA, NULL, _gloffset_WindowPos2dvMESA),
+ NAME_FUNC_OFFSET(18586, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(18600, glWindowPos2fMESA, glWindowPos2fMESA, NULL, _gloffset_WindowPos2fMESA),
+ NAME_FUNC_OFFSET(18617, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(18632, glWindowPos2fvMESA, glWindowPos2fvMESA, NULL, _gloffset_WindowPos2fvMESA),
+ NAME_FUNC_OFFSET(18650, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(18664, glWindowPos2iMESA, glWindowPos2iMESA, NULL, _gloffset_WindowPos2iMESA),
+ NAME_FUNC_OFFSET(18681, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(18696, glWindowPos2ivMESA, glWindowPos2ivMESA, NULL, _gloffset_WindowPos2ivMESA),
+ NAME_FUNC_OFFSET(18714, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(18728, glWindowPos2sMESA, glWindowPos2sMESA, NULL, _gloffset_WindowPos2sMESA),
+ NAME_FUNC_OFFSET(18745, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(18760, glWindowPos2svMESA, glWindowPos2svMESA, NULL, _gloffset_WindowPos2svMESA),
+ NAME_FUNC_OFFSET(18778, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(18792, glWindowPos3dMESA, glWindowPos3dMESA, NULL, _gloffset_WindowPos3dMESA),
+ NAME_FUNC_OFFSET(18809, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(18824, glWindowPos3dvMESA, glWindowPos3dvMESA, NULL, _gloffset_WindowPos3dvMESA),
+ NAME_FUNC_OFFSET(18842, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(18856, glWindowPos3fMESA, glWindowPos3fMESA, NULL, _gloffset_WindowPos3fMESA),
+ NAME_FUNC_OFFSET(18873, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(18888, glWindowPos3fvMESA, glWindowPos3fvMESA, NULL, _gloffset_WindowPos3fvMESA),
+ NAME_FUNC_OFFSET(18906, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(18920, glWindowPos3iMESA, glWindowPos3iMESA, NULL, _gloffset_WindowPos3iMESA),
+ NAME_FUNC_OFFSET(18937, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(18952, glWindowPos3ivMESA, glWindowPos3ivMESA, NULL, _gloffset_WindowPos3ivMESA),
+ NAME_FUNC_OFFSET(18970, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(18984, glWindowPos3sMESA, glWindowPos3sMESA, NULL, _gloffset_WindowPos3sMESA),
+ NAME_FUNC_OFFSET(19001, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(19016, glWindowPos3svMESA, glWindowPos3svMESA, NULL, _gloffset_WindowPos3svMESA),
+ NAME_FUNC_OFFSET(19034, glBindProgramNV, glBindProgramNV, NULL, _gloffset_BindProgramNV),
+ NAME_FUNC_OFFSET(19051, glDeleteProgramsNV, glDeleteProgramsNV, NULL, _gloffset_DeleteProgramsNV),
+ NAME_FUNC_OFFSET(19071, glGenProgramsNV, glGenProgramsNV, NULL, _gloffset_GenProgramsNV),
+ NAME_FUNC_OFFSET(19088, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(19114, glGetVertexAttribPointervNV, glGetVertexAttribPointervNV, NULL, _gloffset_GetVertexAttribPointervNV),
+ NAME_FUNC_OFFSET(19143, glIsProgramNV, glIsProgramNV, NULL, _gloffset_IsProgramNV),
+ NAME_FUNC_OFFSET(19158, glPointParameteriNV, glPointParameteriNV, NULL, _gloffset_PointParameteriNV),
+ NAME_FUNC_OFFSET(19176, glPointParameterivNV, glPointParameterivNV, NULL, _gloffset_PointParameterivNV),
+ NAME_FUNC_OFFSET(19195, gl_dispatch_stub_752, gl_dispatch_stub_752, NULL, _gloffset_DeleteVertexArraysAPPLE),
+ NAME_FUNC_OFFSET(19216, gl_dispatch_stub_754, gl_dispatch_stub_754, NULL, _gloffset_IsVertexArrayAPPLE),
+ NAME_FUNC_OFFSET(19232, gl_dispatch_stub_762, gl_dispatch_stub_762, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(19256, gl_dispatch_stub_762, gl_dispatch_stub_762, NULL, _gloffset_BlendEquationSeparateEXT),
+ NAME_FUNC_OFFSET(19283, glBindFramebufferEXT, glBindFramebufferEXT, NULL, _gloffset_BindFramebufferEXT),
+ NAME_FUNC_OFFSET(19301, glBindRenderbufferEXT, glBindRenderbufferEXT, NULL, _gloffset_BindRenderbufferEXT),
+ NAME_FUNC_OFFSET(19320, glCheckFramebufferStatusEXT, glCheckFramebufferStatusEXT, NULL, _gloffset_CheckFramebufferStatusEXT),
+ NAME_FUNC_OFFSET(19345, glDeleteFramebuffersEXT, glDeleteFramebuffersEXT, NULL, _gloffset_DeleteFramebuffersEXT),
+ NAME_FUNC_OFFSET(19366, glDeleteRenderbuffersEXT, glDeleteRenderbuffersEXT, NULL, _gloffset_DeleteRenderbuffersEXT),
+ NAME_FUNC_OFFSET(19388, glFramebufferRenderbufferEXT, glFramebufferRenderbufferEXT, NULL, _gloffset_FramebufferRenderbufferEXT),
+ NAME_FUNC_OFFSET(19414, glFramebufferTexture1DEXT, glFramebufferTexture1DEXT, NULL, _gloffset_FramebufferTexture1DEXT),
+ NAME_FUNC_OFFSET(19437, glFramebufferTexture2DEXT, glFramebufferTexture2DEXT, NULL, _gloffset_FramebufferTexture2DEXT),
+ NAME_FUNC_OFFSET(19460, glFramebufferTexture3DEXT, glFramebufferTexture3DEXT, NULL, _gloffset_FramebufferTexture3DEXT),
+ NAME_FUNC_OFFSET(19483, glGenFramebuffersEXT, glGenFramebuffersEXT, NULL, _gloffset_GenFramebuffersEXT),
+ NAME_FUNC_OFFSET(19501, glGenRenderbuffersEXT, glGenRenderbuffersEXT, NULL, _gloffset_GenRenderbuffersEXT),
+ NAME_FUNC_OFFSET(19520, glGenerateMipmapEXT, glGenerateMipmapEXT, NULL, _gloffset_GenerateMipmapEXT),
+ NAME_FUNC_OFFSET(19537, glGetFramebufferAttachmentParameterivEXT, glGetFramebufferAttachmentParameterivEXT, NULL, _gloffset_GetFramebufferAttachmentParameterivEXT),
+ NAME_FUNC_OFFSET(19575, glGetRenderbufferParameterivEXT, glGetRenderbufferParameterivEXT, NULL, _gloffset_GetRenderbufferParameterivEXT),
+ NAME_FUNC_OFFSET(19604, glIsFramebufferEXT, glIsFramebufferEXT, NULL, _gloffset_IsFramebufferEXT),
+ NAME_FUNC_OFFSET(19620, glIsRenderbufferEXT, glIsRenderbufferEXT, NULL, _gloffset_IsRenderbufferEXT),
+ NAME_FUNC_OFFSET(19637, glRenderbufferStorageEXT, glRenderbufferStorageEXT, NULL, _gloffset_RenderbufferStorageEXT),
+ NAME_FUNC_OFFSET(19659, gl_dispatch_stub_780, gl_dispatch_stub_780, NULL, _gloffset_BlitFramebufferEXT),
+ NAME_FUNC_OFFSET(19677, glFramebufferTextureLayerEXT, glFramebufferTextureLayerEXT, NULL, _gloffset_FramebufferTextureLayerEXT),
+ NAME_FUNC_OFFSET(-1, NULL, NULL, NULL, 0)
+};
+
+#undef NAME_FUNC_OFFSET
diff --git a/mesalib/src/mesa/glapi/glthread.c b/mesalib/src/mesa/glapi/glthread.c
new file mode 100644
index 000000000..737fd4d6a
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glthread.c
@@ -0,0 +1,326 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * XXX There's probably some work to do in order to make this file
+ * truly reusable outside of Mesa. First, the glheader.h include must go.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "main/compiler.h"
+#include "glthread.h"
+
+
+/*
+ * This file should still compile even when THREADS is not defined.
+ * This is to make things easier to deal with on the makefile scene..
+ */
+#ifdef THREADS
+#include <errno.h>
+
+/*
+ * Error messages
+ */
+#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data"
+#define GET_TSD_ERROR "_glthread_: failed to get thread specific data"
+#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data"
+
+
+/*
+ * Magic number to determine if a TSD object has been initialized.
+ * Kind of a hack but there doesn't appear to be a better cross-platform
+ * solution.
+ */
+#define INIT_MAGIC 0xff8adc98
+
+
+
+/*
+ * POSIX Threads -- The best way to go if your platform supports them.
+ * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly
+ * has them, and many of the free Unixes now have them.
+ * Be sure to use appropriate -mt or -D_REENTRANT type
+ * compile flags when building.
+ */
+#ifdef PTHREADS
+
+unsigned long
+_glthread_GetID(void)
+{
+ return (unsigned long) pthread_self();
+}
+
+
+void
+_glthread_InitTSD(_glthread_TSD *tsd)
+{
+ if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
+ perror(INIT_TSD_ERROR);
+ exit(-1);
+ }
+ tsd->initMagic = INIT_MAGIC;
+}
+
+
+void *
+_glthread_GetTSD(_glthread_TSD *tsd)
+{
+ if (tsd->initMagic != (int) INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ return pthread_getspecific(tsd->key);
+}
+
+
+void
+_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
+{
+ if (tsd->initMagic != (int) INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ if (pthread_setspecific(tsd->key, ptr) != 0) {
+ perror(SET_TSD_ERROR);
+ exit(-1);
+ }
+}
+
+#endif /* PTHREADS */
+
+
+
+/*
+ * Solaris/Unix International Threads -- Use only if POSIX threads
+ * aren't available on your Unix platform. Solaris 2.[34] are examples
+ * of platforms where this is the case. Be sure to use -mt and/or
+ * -D_REENTRANT when compiling.
+ */
+#ifdef SOLARIS_THREADS
+#define USE_LOCK_FOR_KEY /* undef this to try a version without
+ lock for the global key... */
+
+unsigned long
+_glthread_GetID(void)
+{
+ abort(); /* XXX not implemented yet */
+ return (unsigned long) 0;
+}
+
+
+void
+_glthread_InitTSD(_glthread_TSD *tsd)
+{
+ if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 ||
+ (errno = thr_keycreate(&(tsd->key), free)) != 0) {
+ perror(INIT_TSD_ERROR);
+ exit(-1);
+ }
+ tsd->initMagic = INIT_MAGIC;
+}
+
+
+void *
+_glthread_GetTSD(_glthread_TSD *tsd)
+{
+ void* ret;
+ if (tsd->initMagic != INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+#ifdef USE_LOCK_FOR_KEY
+ mutex_lock(&tsd->keylock);
+ thr_getspecific(tsd->key, &ret);
+ mutex_unlock(&tsd->keylock);
+#else
+ if ((errno = thr_getspecific(tsd->key, &ret)) != 0) {
+ perror(GET_TSD_ERROR);
+ exit(-1);
+ }
+#endif
+ return ret;
+}
+
+
+void
+_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
+{
+ if (tsd->initMagic != INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ if ((errno = thr_setspecific(tsd->key, ptr)) != 0) {
+ perror(SET_TSD_ERROR);
+ exit(-1);
+ }
+}
+
+#undef USE_LOCK_FOR_KEY
+#endif /* SOLARIS_THREADS */
+
+
+
+/*
+ * Win32 Threads. The only available option for Windows 95/NT.
+ * Be sure that you compile using the Multithreaded runtime, otherwise
+ * bad things will happen.
+ */
+#ifdef WIN32_THREADS
+
+void FreeTSD(_glthread_TSD *p)
+{
+ if (p->initMagic==INIT_MAGIC) {
+ TlsFree(p->key);
+ p->initMagic=0;
+ }
+}
+
+void InsteadOf_exit(int nCode)
+{
+ DWORD dwErr=GetLastError();
+}
+
+unsigned long
+_glthread_GetID(void)
+{
+ return GetCurrentThreadId();
+}
+
+
+void
+_glthread_InitTSD(_glthread_TSD *tsd)
+{
+ tsd->key = TlsAlloc();
+ if (tsd->key == TLS_OUT_OF_INDEXES) {
+ perror("Mesa:_glthread_InitTSD");
+ InsteadOf_exit(-1);
+ }
+ tsd->initMagic = INIT_MAGIC;
+}
+
+
+void *
+_glthread_GetTSD(_glthread_TSD *tsd)
+{
+ if (tsd->initMagic != INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ return TlsGetValue(tsd->key);
+}
+
+
+void
+_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
+{
+ /* the following code assumes that the _glthread_TSD has been initialized
+ to zero at creation */
+ if (tsd->initMagic != INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ if (TlsSetValue(tsd->key, ptr) == 0) {
+ perror("Mesa:_glthread_SetTSD");
+ InsteadOf_exit(-1);
+ }
+}
+
+#endif /* WIN32_THREADS */
+
+/*
+ * BeOS threads
+ */
+#ifdef BEOS_THREADS
+
+unsigned long
+_glthread_GetID(void)
+{
+ return (unsigned long) find_thread(NULL);
+}
+
+void
+_glthread_InitTSD(_glthread_TSD *tsd)
+{
+ tsd->key = tls_allocate();
+ tsd->initMagic = INIT_MAGIC;
+}
+
+void *
+_glthread_GetTSD(_glthread_TSD *tsd)
+{
+ if (tsd->initMagic != (int) INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ return tls_get(tsd->key);
+}
+
+void
+_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
+{
+ if (tsd->initMagic != (int) INIT_MAGIC) {
+ _glthread_InitTSD(tsd);
+ }
+ tls_set(tsd->key, ptr);
+}
+
+#endif /* BEOS_THREADS */
+
+
+
+#else /* THREADS */
+
+
+/*
+ * no-op functions
+ */
+
+unsigned long
+_glthread_GetID(void)
+{
+ return 0;
+}
+
+
+void
+_glthread_InitTSD(_glthread_TSD *tsd)
+{
+ (void) tsd;
+}
+
+
+void *
+_glthread_GetTSD(_glthread_TSD *tsd)
+{
+ (void) tsd;
+ return NULL;
+}
+
+
+void
+_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
+{
+ (void) tsd;
+ (void) ptr;
+}
+
+
+#endif /* THREADS */
diff --git a/mesalib/src/mesa/glapi/glthread.h b/mesalib/src/mesa/glapi/glthread.h
new file mode 100644
index 000000000..8ec933a85
--- /dev/null
+++ b/mesalib/src/mesa/glapi/glthread.h
@@ -0,0 +1,333 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * Thread support for gl dispatch.
+ *
+ * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu)
+ * and Christoph Poliwoda (poliwoda@volumegraphics.com)
+ * Revised by Keith Whitwell
+ * Adapted for new gl dispatcher by Brian Paul
+ *
+ *
+ *
+ * DOCUMENTATION
+ *
+ * This thread module exports the following types:
+ * _glthread_TSD Thread-specific data area
+ * _glthread_Thread Thread datatype
+ * _glthread_Mutex Mutual exclusion lock
+ *
+ * Macros:
+ * _glthread_DECLARE_STATIC_MUTEX(name) Declare a non-local mutex
+ * _glthread_INIT_MUTEX(name) Initialize a mutex
+ * _glthread_LOCK_MUTEX(name) Lock a mutex
+ * _glthread_UNLOCK_MUTEX(name) Unlock a mutex
+ *
+ * Functions:
+ * _glthread_GetID(v) Get integer thread ID
+ * _glthread_InitTSD() Initialize thread-specific data
+ * _glthread_GetTSD() Get thread-specific data
+ * _glthread_SetTSD() Set thread-specific data
+ *
+ */
+
+/*
+ * If this file is accidentally included by a non-threaded build,
+ * it should not cause the build to fail, or otherwise cause problems.
+ * In general, it should only be included when needed however.
+ */
+
+#ifndef GLTHREAD_H
+#define GLTHREAD_H
+
+
+#if defined(USE_MGL_NAMESPACE)
+#define _glapi_Dispatch _mglapi_Dispatch
+#endif
+
+
+
+#if (defined(PTHREADS) || defined(SOLARIS_THREADS) ||\
+ defined(WIN32_THREADS) || defined(BEOS_THREADS)) \
+ && !defined(THREADS)
+# define THREADS
+#endif
+
+#ifdef VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+/*
+ * POSIX threads. This should be your choice in the Unix world
+ * whenever possible. When building with POSIX threads, be sure
+ * to enable any compiler flags which will cause the MT-safe
+ * libc (if one exists) to be used when linking, as well as any
+ * header macros for MT-safe errno, etc. For Solaris, this is the -mt
+ * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable
+ * proper compiling for MT-safe libc etc.
+ */
+#if defined(PTHREADS)
+#include <pthread.h> /* POSIX threads headers */
+
+typedef struct {
+ pthread_key_t key;
+ int initMagic;
+} _glthread_TSD;
+
+typedef pthread_t _glthread_Thread;
+
+typedef pthread_mutex_t _glthread_Mutex;
+
+#define _glthread_DECLARE_STATIC_MUTEX(name) \
+ static _glthread_Mutex name = PTHREAD_MUTEX_INITIALIZER
+
+#define _glthread_INIT_MUTEX(name) \
+ pthread_mutex_init(&(name), NULL)
+
+#define _glthread_DESTROY_MUTEX(name) \
+ pthread_mutex_destroy(&(name))
+
+#define _glthread_LOCK_MUTEX(name) \
+ (void) pthread_mutex_lock(&(name))
+
+#define _glthread_UNLOCK_MUTEX(name) \
+ (void) pthread_mutex_unlock(&(name))
+
+typedef pthread_cond_t _glthread_Cond;
+
+#define _glthread_DECLARE_STATIC_COND(name) \
+ static _glthread_Cond name = PTHREAD_COND_INITIALIZER
+
+#define _glthread_INIT_COND(cond) \
+ pthread_cond_init(&(cond), NULL)
+
+#define _glthread_DESTROY_COND(name) \
+ pthread_cond_destroy(&(name))
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ pthread_cond_wait(&(cond), &(mutex))
+
+#define _glthread_COND_SIGNAL(cond) \
+ pthread_cond_signal(&(cond))
+
+#define _glthread_COND_BROADCAST(cond) \
+ pthread_cond_broadcast(&(cond))
+
+
+#else /* PTHREADS */
+
+typedef unsigned int _glthread_Cond;
+#define _glthread_DECLARE_STATIC_COND(name) \
+// #warning Condition variables not implemented.
+
+#define _glthread_INIT_COND(cond) \
+ ASSERT(0);
+
+#define _glthread_DESTROY_COND(name) \
+ ASSERT(0);
+
+#define _glthread_COND_WAIT(cond, mutex) \
+ ASSERT(0);
+
+#define _glthread_COND_SIGNAL(cond) \
+ ASSERT(0);
+
+#define _glthread_COND_BROADCAST(cond) \
+ ASSERT(0);
+
+#endif
+
+
+/*
+ * Solaris threads. Use only up to Solaris 2.4.
+ * Solaris 2.5 and higher provide POSIX threads.
+ * Be sure to compile with -mt on the Solaris compilers, or
+ * use -D_REENTRANT if using gcc.
+ */
+#ifdef SOLARIS_THREADS
+#include <thread.h>
+
+typedef struct {
+ thread_key_t key;
+ mutex_t keylock;
+ int initMagic;
+} _glthread_TSD;
+
+typedef thread_t _glthread_Thread;
+
+typedef mutex_t _glthread_Mutex;
+
+/* XXX need to really implement mutex-related macros */
+#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0
+#define _glthread_INIT_MUTEX(name) (void) name
+#define _glthread_DESTROY_MUTEX(name) (void) name
+#define _glthread_LOCK_MUTEX(name) (void) name
+#define _glthread_UNLOCK_MUTEX(name) (void) name
+
+#endif /* SOLARIS_THREADS */
+
+
+
+
+/*
+ * Windows threads. Should work with Windows NT and 95.
+ * IMPORTANT: Link with multithreaded runtime library when THREADS are
+ * used!
+ */
+#ifdef WIN32_THREADS
+#include <windows.h>
+
+typedef struct {
+ DWORD key;
+ int initMagic;
+} _glthread_TSD;
+
+typedef HANDLE _glthread_Thread;
+
+typedef CRITICAL_SECTION _glthread_Mutex;
+
+#define _glthread_DECLARE_STATIC_MUTEX(name) /*static*/ _glthread_Mutex name = {0,0,0,0,0,0}
+#define _glthread_INIT_MUTEX(name) InitializeCriticalSection(&name)
+#define _glthread_DESTROY_MUTEX(name) DeleteCriticalSection(&name)
+#define _glthread_LOCK_MUTEX(name) EnterCriticalSection(&name)
+#define _glthread_UNLOCK_MUTEX(name) LeaveCriticalSection(&name)
+
+#endif /* WIN32_THREADS */
+
+
+/*
+ * BeOS threads. R5.x required.
+ */
+#ifdef BEOS_THREADS
+
+/* Problem with OS.h and this file on haiku */
+#ifndef __HAIKU__
+#include <kernel/OS.h>
+#endif
+
+#include <support/TLS.h>
+
+/* The only two typedefs required here
+ * this is cause of the OS.h problem
+ */
+#ifdef __HAIKU__
+typedef int32 thread_id;
+typedef int32 sem_id;
+#endif
+
+typedef struct {
+ int32 key;
+ int initMagic;
+} _glthread_TSD;
+
+typedef thread_id _glthread_Thread;
+
+/* Use Benaphore, aka speeder semaphore */
+typedef struct {
+ int32 lock;
+ sem_id sem;
+} benaphore;
+typedef benaphore _glthread_Mutex;
+
+#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = { 0, 0 }
+#define _glthread_INIT_MUTEX(name) name.sem = create_sem(0, #name"_benaphore"), name.lock = 0
+#define _glthread_DESTROY_MUTEX(name) delete_sem(name.sem), name.lock = 0
+#define _glthread_LOCK_MUTEX(name) if (name.sem == 0) _glthread_INIT_MUTEX(name); \
+ if (atomic_add(&(name.lock), 1) >= 1) acquire_sem(name.sem)
+#define _glthread_UNLOCK_MUTEX(name) if (atomic_add(&(name.lock), -1) > 1) release_sem(name.sem)
+
+#endif /* BEOS_THREADS */
+
+
+
+#ifndef THREADS
+
+/*
+ * THREADS not defined
+ */
+
+typedef unsigned _glthread_TSD;
+
+typedef unsigned _glthread_Thread;
+
+typedef unsigned _glthread_Mutex;
+
+#define _glthread_DECLARE_STATIC_MUTEX(name) static _glthread_Mutex name = 0
+
+#define _glthread_INIT_MUTEX(name) (void) name
+
+#define _glthread_DESTROY_MUTEX(name) (void) name
+
+#define _glthread_LOCK_MUTEX(name) (void) name
+
+#define _glthread_UNLOCK_MUTEX(name) (void) name
+
+#endif /* THREADS */
+
+
+
+/*
+ * Platform independent thread specific data API.
+ */
+
+extern unsigned long
+_glthread_GetID(void);
+
+
+extern void
+_glthread_InitTSD(_glthread_TSD *);
+
+
+extern void *
+_glthread_GetTSD(_glthread_TSD *);
+
+
+extern void
+_glthread_SetTSD(_glthread_TSD *, void *);
+
+#if !defined __GNUC__ || __GNUC__ < 3
+# define __builtin_expect(x, y) x
+#endif
+
+#if defined(GLX_USE_TLS)
+
+extern __thread struct _glapi_table * _glapi_tls_Dispatch
+ __attribute__((tls_model("initial-exec")));
+
+#define GET_DISPATCH() _glapi_tls_Dispatch
+
+#elif !defined(GL_CALL)
+# if defined(THREADS)
+# define GET_DISPATCH() \
+ ((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \
+ ? _glapi_Dispatch : _glapi_get_dispatch())
+# else
+# define GET_DISPATCH() _glapi_Dispatch
+# endif /* defined(THREADS) */
+#endif /* ndef GL_CALL */
+
+
+#endif /* THREADS_H */
diff --git a/mesalib/src/mesa/main/accum.c b/mesalib/src/mesa/main/accum.c
new file mode 100644
index 000000000..2345695f3
--- /dev/null
+++ b/mesalib/src/mesa/main/accum.c
@@ -0,0 +1,108 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 "glheader.h"
+#include "accum.h"
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "state.h"
+#include "mtypes.h"
+
+
+void GLAPIENTRY
+_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+{
+ GLfloat tmp[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ tmp[0] = CLAMP( red, -1.0F, 1.0F );
+ tmp[1] = CLAMP( green, -1.0F, 1.0F );
+ tmp[2] = CLAMP( blue, -1.0F, 1.0F );
+ tmp[3] = CLAMP( alpha, -1.0F, 1.0F );
+
+ if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_ACCUM);
+ COPY_4FV( ctx->Accum.ClearColor, tmp );
+}
+
+
+void GLAPIENTRY
+_mesa_Accum( GLenum op, GLfloat value )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (op) {
+ case GL_ADD:
+ case GL_MULT:
+ case GL_ACCUM:
+ case GL_LOAD:
+ case GL_RETURN:
+ /* OK */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glAccum(op)");
+ return;
+ }
+
+ if (ctx->DrawBuffer->Visual.haveAccumBuffer == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glAccum(no accum buffer)");
+ return;
+ }
+
+ if (ctx->DrawBuffer != ctx->ReadBuffer) {
+ /* See GLX_SGI_make_current_read or WGL_ARB_make_current_read,
+ * or GL_EXT_framebuffer_blit.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glAccum(different read/draw buffers)");
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glAccum(incomplete framebuffer)");
+ return;
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ ctx->Driver.Accum(ctx, op, value);
+ }
+}
+
+
+
+void
+_mesa_init_accum( GLcontext *ctx )
+{
+ /* Accumulate buffer group */
+ ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 );
+}
diff --git a/mesalib/src/mesa/main/accum.h b/mesalib/src/mesa/main/accum.h
new file mode 100644
index 000000000..ce92688a5
--- /dev/null
+++ b/mesalib/src/mesa/main/accum.h
@@ -0,0 +1,62 @@
+/**
+ * \file accum.h
+ * Accumulation buffer operations.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef ACCUM_H
+#define ACCUM_H
+
+
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_Accum( GLenum op, GLfloat value );
+
+
+extern void GLAPIENTRY
+_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
+
+extern void
+_mesa_init_accum( GLcontext *ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_accum( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c
new file mode 100644
index 000000000..2462a1b00
--- /dev/null
+++ b/mesalib/src/mesa/main/api_arrayelt.c
@@ -0,0 +1,1319 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "api_arrayelt.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "glapi/glapioffsets.h"
+#include "glapi/dispatch.h"
+
+typedef void (GLAPIENTRY *array_func)( const void * );
+
+typedef struct {
+ const struct gl_client_array *array;
+ int offset;
+} AEarray;
+
+typedef void (GLAPIENTRY *attrib_func)( GLuint indx, const void *data );
+
+typedef struct {
+ const struct gl_client_array *array;
+ attrib_func func;
+ GLuint index;
+} AEattrib;
+
+typedef struct {
+ AEarray arrays[32];
+ AEattrib attribs[VERT_ATTRIB_MAX + 1];
+ GLuint NewState;
+
+ struct gl_buffer_object *vbo[VERT_ATTRIB_MAX];
+ GLuint nr_vbos;
+ GLboolean mapped_vbos;
+
+} AEcontext;
+
+#define AE_CONTEXT(ctx) ((AEcontext *)(ctx)->aelt_context)
+
+
+/*
+ * Convert GL_BYTE, GL_UNSIGNED_BYTE, .. GL_DOUBLE into an integer
+ * in the range [0, 7]. Luckily these type tokens are sequentially
+ * numbered in gl.h, except for GL_DOUBLE.
+ */
+#define TYPE_IDX(t) ( (t) == GL_DOUBLE ? 7 : (t) & 7 )
+
+static const int ColorFuncs[2][8] = {
+ {
+ _gloffset_Color3bv,
+ _gloffset_Color3ubv,
+ _gloffset_Color3sv,
+ _gloffset_Color3usv,
+ _gloffset_Color3iv,
+ _gloffset_Color3uiv,
+ _gloffset_Color3fv,
+ _gloffset_Color3dv,
+ },
+ {
+ _gloffset_Color4bv,
+ _gloffset_Color4ubv,
+ _gloffset_Color4sv,
+ _gloffset_Color4usv,
+ _gloffset_Color4iv,
+ _gloffset_Color4uiv,
+ _gloffset_Color4fv,
+ _gloffset_Color4dv,
+ },
+};
+
+static const int VertexFuncs[3][8] = {
+ {
+ -1,
+ -1,
+ _gloffset_Vertex2sv,
+ -1,
+ _gloffset_Vertex2iv,
+ -1,
+ _gloffset_Vertex2fv,
+ _gloffset_Vertex2dv,
+ },
+ {
+ -1,
+ -1,
+ _gloffset_Vertex3sv,
+ -1,
+ _gloffset_Vertex3iv,
+ -1,
+ _gloffset_Vertex3fv,
+ _gloffset_Vertex3dv,
+ },
+ {
+ -1,
+ -1,
+ _gloffset_Vertex4sv,
+ -1,
+ _gloffset_Vertex4iv,
+ -1,
+ _gloffset_Vertex4fv,
+ _gloffset_Vertex4dv,
+ },
+};
+
+static const int IndexFuncs[8] = {
+ -1,
+ _gloffset_Indexubv,
+ _gloffset_Indexsv,
+ -1,
+ _gloffset_Indexiv,
+ -1,
+ _gloffset_Indexfv,
+ _gloffset_Indexdv,
+};
+
+static const int NormalFuncs[8] = {
+ _gloffset_Normal3bv,
+ -1,
+ _gloffset_Normal3sv,
+ -1,
+ _gloffset_Normal3iv,
+ -1,
+ _gloffset_Normal3fv,
+ _gloffset_Normal3dv,
+};
+
+/* Note: _gloffset_* for these may not be a compile-time constant. */
+static int SecondaryColorFuncs[8];
+static int FogCoordFuncs[8];
+
+
+/**
+ ** GL_NV_vertex_program
+ **/
+
+/* GL_BYTE attributes */
+
+static void GLAPIENTRY VertexAttrib1NbvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1bvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NbvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2bvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NbvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]),
+ BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3bvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NbvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]),
+ BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]),
+ BYTE_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4bvNV(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_BYTE attributes */
+
+static void GLAPIENTRY VertexAttrib1NubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1ubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2ubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2])));
+}
+static void GLAPIENTRY VertexAttrib3ubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]),
+ UBYTE_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4ubvNV(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_SHORT attributes */
+
+static void GLAPIENTRY VertexAttrib1NsvNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1svNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NsvNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2svNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NsvNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3svNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NsvNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]),
+ SHORT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4svNV(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_SHORT attributes */
+
+static void GLAPIENTRY VertexAttrib1NusvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1usvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NusvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2usvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NusvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3usvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NusvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]),
+ USHORT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4usvNV(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_INT attributes */
+
+static void GLAPIENTRY VertexAttrib1NivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1ivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2ivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3ivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]),
+ INT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4ivNV(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_INT attributes */
+
+static void GLAPIENTRY VertexAttrib1NuivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1uivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NuivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2uivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NuivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3uivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NuivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]),
+ UINT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4uivNV(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_FLOAT attributes */
+
+static void GLAPIENTRY VertexAttrib1fvNV(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib2fvNV(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib3fvNV(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib4fvNV(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvNV(GET_DISPATCH(), (index, v));
+}
+
+/* GL_DOUBLE attributes */
+
+static void GLAPIENTRY VertexAttrib1dvNV(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib1dvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib2dvNV(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib2dvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib3dvNV(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib3dvNV(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib4dvNV(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib4dvNV(GET_DISPATCH(), (index, v));
+}
+
+
+/*
+ * Array [size][type] of VertexAttrib functions
+ */
+static attrib_func AttribFuncsNV[2][4][8] = {
+ {
+ /* non-normalized */
+ {
+ /* size 1 */
+ (attrib_func) VertexAttrib1bvNV,
+ (attrib_func) VertexAttrib1ubvNV,
+ (attrib_func) VertexAttrib1svNV,
+ (attrib_func) VertexAttrib1usvNV,
+ (attrib_func) VertexAttrib1ivNV,
+ (attrib_func) VertexAttrib1uivNV,
+ (attrib_func) VertexAttrib1fvNV,
+ (attrib_func) VertexAttrib1dvNV
+ },
+ {
+ /* size 2 */
+ (attrib_func) VertexAttrib2bvNV,
+ (attrib_func) VertexAttrib2ubvNV,
+ (attrib_func) VertexAttrib2svNV,
+ (attrib_func) VertexAttrib2usvNV,
+ (attrib_func) VertexAttrib2ivNV,
+ (attrib_func) VertexAttrib2uivNV,
+ (attrib_func) VertexAttrib2fvNV,
+ (attrib_func) VertexAttrib2dvNV
+ },
+ {
+ /* size 3 */
+ (attrib_func) VertexAttrib3bvNV,
+ (attrib_func) VertexAttrib3ubvNV,
+ (attrib_func) VertexAttrib3svNV,
+ (attrib_func) VertexAttrib3usvNV,
+ (attrib_func) VertexAttrib3ivNV,
+ (attrib_func) VertexAttrib3uivNV,
+ (attrib_func) VertexAttrib3fvNV,
+ (attrib_func) VertexAttrib3dvNV
+ },
+ {
+ /* size 4 */
+ (attrib_func) VertexAttrib4bvNV,
+ (attrib_func) VertexAttrib4ubvNV,
+ (attrib_func) VertexAttrib4svNV,
+ (attrib_func) VertexAttrib4usvNV,
+ (attrib_func) VertexAttrib4ivNV,
+ (attrib_func) VertexAttrib4uivNV,
+ (attrib_func) VertexAttrib4fvNV,
+ (attrib_func) VertexAttrib4dvNV
+ }
+ },
+ {
+ /* normalized (except for float/double) */
+ {
+ /* size 1 */
+ (attrib_func) VertexAttrib1NbvNV,
+ (attrib_func) VertexAttrib1NubvNV,
+ (attrib_func) VertexAttrib1NsvNV,
+ (attrib_func) VertexAttrib1NusvNV,
+ (attrib_func) VertexAttrib1NivNV,
+ (attrib_func) VertexAttrib1NuivNV,
+ (attrib_func) VertexAttrib1fvNV,
+ (attrib_func) VertexAttrib1dvNV
+ },
+ {
+ /* size 2 */
+ (attrib_func) VertexAttrib2NbvNV,
+ (attrib_func) VertexAttrib2NubvNV,
+ (attrib_func) VertexAttrib2NsvNV,
+ (attrib_func) VertexAttrib2NusvNV,
+ (attrib_func) VertexAttrib2NivNV,
+ (attrib_func) VertexAttrib2NuivNV,
+ (attrib_func) VertexAttrib2fvNV,
+ (attrib_func) VertexAttrib2dvNV
+ },
+ {
+ /* size 3 */
+ (attrib_func) VertexAttrib3NbvNV,
+ (attrib_func) VertexAttrib3NubvNV,
+ (attrib_func) VertexAttrib3NsvNV,
+ (attrib_func) VertexAttrib3NusvNV,
+ (attrib_func) VertexAttrib3NivNV,
+ (attrib_func) VertexAttrib3NuivNV,
+ (attrib_func) VertexAttrib3fvNV,
+ (attrib_func) VertexAttrib3dvNV
+ },
+ {
+ /* size 4 */
+ (attrib_func) VertexAttrib4NbvNV,
+ (attrib_func) VertexAttrib4NubvNV,
+ (attrib_func) VertexAttrib4NsvNV,
+ (attrib_func) VertexAttrib4NusvNV,
+ (attrib_func) VertexAttrib4NivNV,
+ (attrib_func) VertexAttrib4NuivNV,
+ (attrib_func) VertexAttrib4fvNV,
+ (attrib_func) VertexAttrib4dvNV
+ }
+ }
+};
+
+
+/**
+ ** GL_ARB_vertex_program
+ **/
+
+/* GL_BYTE attributes */
+
+static void GLAPIENTRY VertexAttrib1NbvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1bvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NbvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2bvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NbvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]),
+ BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3bvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NbvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]),
+ BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]),
+ BYTE_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4bvARB(GLuint index, const GLbyte *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_BYTE attributes */
+
+static void GLAPIENTRY VertexAttrib1NubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1ubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2ubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2])));
+}
+static void GLAPIENTRY VertexAttrib3ubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]),
+ UBYTE_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4ubvARB(GLuint index, const GLubyte *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_SHORT attributes */
+
+static void GLAPIENTRY VertexAttrib1NsvARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1svARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NsvARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2svARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NsvARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3svARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NsvARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]),
+ SHORT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4svARB(GLuint index, const GLshort *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_SHORT attributes */
+
+static void GLAPIENTRY VertexAttrib1NusvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1usvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NusvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2usvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NusvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3usvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NusvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]),
+ USHORT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4usvARB(GLuint index, const GLushort *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_INT attributes */
+
+static void GLAPIENTRY VertexAttrib1NivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1ivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2ivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3ivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]),
+ INT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4ivARB(GLuint index, const GLint *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_UNSIGNED_INT attributes */
+
+static void GLAPIENTRY VertexAttrib1NuivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0])));
+}
+
+static void GLAPIENTRY VertexAttrib1uivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), (index, (GLfloat)v[0]));
+}
+
+static void GLAPIENTRY VertexAttrib2NuivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1])));
+}
+
+static void GLAPIENTRY VertexAttrib2uivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1]));
+}
+
+static void GLAPIENTRY VertexAttrib3NuivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2])));
+}
+
+static void GLAPIENTRY VertexAttrib3uivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2]));
+}
+
+static void GLAPIENTRY VertexAttrib4NuivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]),
+ UINT_TO_FLOAT(v[3])));
+}
+
+static void GLAPIENTRY VertexAttrib4uivARB(GLuint index, const GLuint *v)
+{
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), (index, (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3]));
+}
+
+/* GL_FLOAT attributes */
+
+static void GLAPIENTRY VertexAttrib1fvARB(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib2fvARB(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib3fvARB(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib4fvARB(GLuint index, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvARB(GET_DISPATCH(), (index, v));
+}
+
+/* GL_DOUBLE attributes */
+
+static void GLAPIENTRY VertexAttrib1dvARB(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib1dvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib2dvARB(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib2dvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib3dvARB(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib3dvARB(GET_DISPATCH(), (index, v));
+}
+
+static void GLAPIENTRY VertexAttrib4dvARB(GLuint index, const GLdouble *v)
+{
+ CALL_VertexAttrib4dvARB(GET_DISPATCH(), (index, v));
+}
+
+
+/*
+ * Array [size][type] of VertexAttrib functions
+ */
+static attrib_func AttribFuncsARB[2][4][8] = {
+ {
+ /* non-normalized */
+ {
+ /* size 1 */
+ (attrib_func) VertexAttrib1bvARB,
+ (attrib_func) VertexAttrib1ubvARB,
+ (attrib_func) VertexAttrib1svARB,
+ (attrib_func) VertexAttrib1usvARB,
+ (attrib_func) VertexAttrib1ivARB,
+ (attrib_func) VertexAttrib1uivARB,
+ (attrib_func) VertexAttrib1fvARB,
+ (attrib_func) VertexAttrib1dvARB
+ },
+ {
+ /* size 2 */
+ (attrib_func) VertexAttrib2bvARB,
+ (attrib_func) VertexAttrib2ubvARB,
+ (attrib_func) VertexAttrib2svARB,
+ (attrib_func) VertexAttrib2usvARB,
+ (attrib_func) VertexAttrib2ivARB,
+ (attrib_func) VertexAttrib2uivARB,
+ (attrib_func) VertexAttrib2fvARB,
+ (attrib_func) VertexAttrib2dvARB
+ },
+ {
+ /* size 3 */
+ (attrib_func) VertexAttrib3bvARB,
+ (attrib_func) VertexAttrib3ubvARB,
+ (attrib_func) VertexAttrib3svARB,
+ (attrib_func) VertexAttrib3usvARB,
+ (attrib_func) VertexAttrib3ivARB,
+ (attrib_func) VertexAttrib3uivARB,
+ (attrib_func) VertexAttrib3fvARB,
+ (attrib_func) VertexAttrib3dvARB
+ },
+ {
+ /* size 4 */
+ (attrib_func) VertexAttrib4bvARB,
+ (attrib_func) VertexAttrib4ubvARB,
+ (attrib_func) VertexAttrib4svARB,
+ (attrib_func) VertexAttrib4usvARB,
+ (attrib_func) VertexAttrib4ivARB,
+ (attrib_func) VertexAttrib4uivARB,
+ (attrib_func) VertexAttrib4fvARB,
+ (attrib_func) VertexAttrib4dvARB
+ }
+ },
+ {
+ /* normalized (except for float/double) */
+ {
+ /* size 1 */
+ (attrib_func) VertexAttrib1NbvARB,
+ (attrib_func) VertexAttrib1NubvARB,
+ (attrib_func) VertexAttrib1NsvARB,
+ (attrib_func) VertexAttrib1NusvARB,
+ (attrib_func) VertexAttrib1NivARB,
+ (attrib_func) VertexAttrib1NuivARB,
+ (attrib_func) VertexAttrib1fvARB,
+ (attrib_func) VertexAttrib1dvARB
+ },
+ {
+ /* size 2 */
+ (attrib_func) VertexAttrib2NbvARB,
+ (attrib_func) VertexAttrib2NubvARB,
+ (attrib_func) VertexAttrib2NsvARB,
+ (attrib_func) VertexAttrib2NusvARB,
+ (attrib_func) VertexAttrib2NivARB,
+ (attrib_func) VertexAttrib2NuivARB,
+ (attrib_func) VertexAttrib2fvARB,
+ (attrib_func) VertexAttrib2dvARB
+ },
+ {
+ /* size 3 */
+ (attrib_func) VertexAttrib3NbvARB,
+ (attrib_func) VertexAttrib3NubvARB,
+ (attrib_func) VertexAttrib3NsvARB,
+ (attrib_func) VertexAttrib3NusvARB,
+ (attrib_func) VertexAttrib3NivARB,
+ (attrib_func) VertexAttrib3NuivARB,
+ (attrib_func) VertexAttrib3fvARB,
+ (attrib_func) VertexAttrib3dvARB
+ },
+ {
+ /* size 4 */
+ (attrib_func) VertexAttrib4NbvARB,
+ (attrib_func) VertexAttrib4NubvARB,
+ (attrib_func) VertexAttrib4NsvARB,
+ (attrib_func) VertexAttrib4NusvARB,
+ (attrib_func) VertexAttrib4NivARB,
+ (attrib_func) VertexAttrib4NuivARB,
+ (attrib_func) VertexAttrib4fvARB,
+ (attrib_func) VertexAttrib4dvARB
+ }
+ }
+};
+
+/**********************************************************************/
+
+
+GLboolean _ae_create_context( GLcontext *ctx )
+{
+ if (ctx->aelt_context)
+ return GL_TRUE;
+
+ /* These _gloffset_* values may not be compile-time constants */
+ SecondaryColorFuncs[0] = _gloffset_SecondaryColor3bvEXT;
+ SecondaryColorFuncs[1] = _gloffset_SecondaryColor3ubvEXT;
+ SecondaryColorFuncs[2] = _gloffset_SecondaryColor3svEXT;
+ SecondaryColorFuncs[3] = _gloffset_SecondaryColor3usvEXT;
+ SecondaryColorFuncs[4] = _gloffset_SecondaryColor3ivEXT;
+ SecondaryColorFuncs[5] = _gloffset_SecondaryColor3uivEXT;
+ SecondaryColorFuncs[6] = _gloffset_SecondaryColor3fvEXT;
+ SecondaryColorFuncs[7] = _gloffset_SecondaryColor3dvEXT;
+
+ FogCoordFuncs[0] = -1;
+ FogCoordFuncs[1] = -1;
+ FogCoordFuncs[2] = -1;
+ FogCoordFuncs[3] = -1;
+ FogCoordFuncs[4] = -1;
+ FogCoordFuncs[5] = -1;
+ FogCoordFuncs[6] = _gloffset_FogCoordfvEXT;
+ FogCoordFuncs[7] = _gloffset_FogCoorddvEXT;
+
+ ctx->aelt_context = CALLOC( sizeof(AEcontext) );
+ if (!ctx->aelt_context)
+ return GL_FALSE;
+
+ AE_CONTEXT(ctx)->NewState = ~0;
+ return GL_TRUE;
+}
+
+
+void _ae_destroy_context( GLcontext *ctx )
+{
+ if ( AE_CONTEXT( ctx ) ) {
+ FREE( ctx->aelt_context );
+ ctx->aelt_context = NULL;
+ }
+}
+
+static void check_vbo( AEcontext *actx,
+ struct gl_buffer_object *vbo )
+{
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) {
+ GLuint i;
+ for (i = 0; i < actx->nr_vbos; i++)
+ if (actx->vbo[i] == vbo)
+ return;
+ assert(actx->nr_vbos < VERT_ATTRIB_MAX);
+ actx->vbo[actx->nr_vbos++] = vbo;
+ }
+}
+
+
+/**
+ * Make a list of per-vertex functions to call for each glArrayElement call.
+ * These functions access the array data (i.e. glVertex, glColor, glNormal,
+ * etc).
+ * Note: this may be called during display list construction.
+ */
+static void _ae_update_state( GLcontext *ctx )
+{
+ AEcontext *actx = AE_CONTEXT(ctx);
+ AEarray *aa = actx->arrays;
+ AEattrib *at = actx->attribs;
+ GLuint i;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+
+ actx->nr_vbos = 0;
+
+ /* conventional vertex arrays */
+ if (arrayObj->Index.Enabled) {
+ aa->array = &arrayObj->Index;
+ aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ if (arrayObj->EdgeFlag.Enabled) {
+ aa->array = &arrayObj->EdgeFlag;
+ aa->offset = _gloffset_EdgeFlagv;
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ if (arrayObj->Normal.Enabled) {
+ aa->array = &arrayObj->Normal;
+ aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ if (arrayObj->Color.Enabled) {
+ aa->array = &arrayObj->Color;
+ aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ if (arrayObj->SecondaryColor.Enabled) {
+ aa->array = &arrayObj->SecondaryColor;
+ aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ if (arrayObj->FogCoord.Enabled) {
+ aa->array = &arrayObj->FogCoord;
+ aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ struct gl_client_array *attribArray = &arrayObj->TexCoord[i];
+ if (attribArray->Enabled) {
+ /* NOTE: we use generic glVertexAttribNV functions here.
+ * If we ever remove GL_NV_vertex_program this will have to change.
+ */
+ at->array = attribArray;
+ ASSERT(!at->array->Normalized);
+ at->func = AttribFuncsNV[at->array->Normalized]
+ [at->array->Size-1]
+ [TYPE_IDX(at->array->Type)];
+ at->index = VERT_ATTRIB_TEX0 + i;
+ check_vbo(actx, at->array->BufferObj);
+ at++;
+ }
+ }
+
+ /* generic vertex attribute arrays */
+ for (i = 1; i < Elements(arrayObj->VertexAttrib); i++) { /* skip zero! */
+ struct gl_client_array *attribArray = &arrayObj->VertexAttrib[i];
+ if (attribArray->Enabled) {
+ at->array = attribArray;
+ /* Note: we can't grab the _glapi_Dispatch->VertexAttrib1fvNV
+ * function pointer here (for float arrays) since the pointer may
+ * change from one execution of _ae_loopback_array_elt() to
+ * the next. Doing so caused UT to break.
+ */
+ if (ctx->VertexProgram._Enabled
+ && ctx->VertexProgram.Current->IsNVProgram) {
+ at->func = AttribFuncsNV[at->array->Normalized]
+ [at->array->Size-1]
+ [TYPE_IDX(at->array->Type)];
+ }
+ else {
+ at->func = AttribFuncsARB[at->array->Normalized]
+ [at->array->Size-1]
+ [TYPE_IDX(at->array->Type)];
+ }
+ at->index = i;
+ check_vbo(actx, at->array->BufferObj);
+ at++;
+ }
+ }
+
+ /* finally, vertex position */
+ if (arrayObj->VertexAttrib[0].Enabled) {
+ /* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's
+ * issued as the last (provoking) attribute).
+ */
+ aa->array = &arrayObj->VertexAttrib[0];
+ assert(aa->array->Size >= 2); /* XXX fix someday? */
+ aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+ else if (arrayObj->Vertex.Enabled) {
+ aa->array = &arrayObj->Vertex;
+ aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
+ check_vbo(actx, aa->array->BufferObj);
+ aa++;
+ }
+
+ check_vbo(actx, ctx->Array.ElementArrayBufferObj);
+
+ ASSERT(at - actx->attribs <= VERT_ATTRIB_MAX);
+ ASSERT(aa - actx->arrays < 32);
+ at->func = NULL; /* terminate the list */
+ aa->offset = -1; /* terminate the list */
+
+ actx->NewState = 0;
+}
+
+void _ae_map_vbos( GLcontext *ctx )
+{
+ AEcontext *actx = AE_CONTEXT(ctx);
+ GLuint i;
+
+ if (actx->mapped_vbos)
+ return;
+
+ if (actx->NewState)
+ _ae_update_state(ctx);
+
+ for (i = 0; i < actx->nr_vbos; i++)
+ ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_DYNAMIC_DRAW_ARB,
+ actx->vbo[i]);
+
+ if (actx->nr_vbos)
+ actx->mapped_vbos = GL_TRUE;
+}
+
+void _ae_unmap_vbos( GLcontext *ctx )
+{
+ AEcontext *actx = AE_CONTEXT(ctx);
+ GLuint i;
+
+ if (!actx->mapped_vbos)
+ return;
+
+ assert (!actx->NewState);
+
+ for (i = 0; i < actx->nr_vbos; i++)
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ actx->vbo[i]);
+
+ actx->mapped_vbos = GL_FALSE;
+}
+
+
+/**
+ * Called via glArrayElement() and glDrawArrays().
+ * Issue the glNormal, glVertex, glColor, glVertexAttrib, etc functions
+ * for all enabled vertex arrays (for elt-th element).
+ * Note: this may be called during display list construction.
+ */
+void GLAPIENTRY _ae_loopback_array_elt( GLint elt )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const AEcontext *actx = AE_CONTEXT(ctx);
+ const AEarray *aa;
+ const AEattrib *at;
+ const struct _glapi_table * const disp = GET_DISPATCH();
+ GLboolean do_map;
+
+ if (actx->NewState) {
+ assert(!actx->mapped_vbos);
+ _ae_update_state( ctx );
+ }
+
+ do_map = actx->nr_vbos && !actx->mapped_vbos;
+
+ /*
+ */
+ if (do_map)
+ _ae_map_vbos(ctx);
+
+ /* generic attributes */
+ for (at = actx->attribs; at->func; at++) {
+ const GLubyte *src
+ = ADD_POINTERS(at->array->BufferObj->Pointer, at->array->Ptr)
+ + elt * at->array->StrideB;
+ at->func( at->index, src );
+ }
+
+ /* conventional arrays */
+ for (aa = actx->arrays; aa->offset != -1 ; aa++) {
+ const GLubyte *src
+ = ADD_POINTERS(aa->array->BufferObj->Pointer, aa->array->Ptr)
+ + elt * aa->array->StrideB;
+ CALL_by_offset( disp, (array_func), aa->offset,
+ ((const void *) src) );
+ }
+
+ if (do_map)
+ _ae_unmap_vbos(ctx);
+}
+
+
+void _ae_invalidate_state( GLcontext *ctx, GLuint new_state )
+{
+ AEcontext *actx = AE_CONTEXT(ctx);
+
+
+ /* Only interested in this subset of mesa state. Need to prune
+ * this down as both tnl/ and the drivers can raise statechanges
+ * for arcane reasons in the middle of seemingly atomic operations
+ * like DrawElements, over which we'd like to keep a known set of
+ * arrays and vbo's mapped.
+ *
+ * Luckily, neither the drivers nor tnl muck with the state that
+ * concerns us here:
+ */
+ new_state &= _NEW_ARRAY | _NEW_PROGRAM;
+ if (new_state) {
+ assert(!actx->mapped_vbos);
+ actx->NewState |= new_state;
+ }
+}
diff --git a/mesalib/src/mesa/main/api_arrayelt.h b/mesalib/src/mesa/main/api_arrayelt.h
new file mode 100644
index 000000000..e621724fb
--- /dev/null
+++ b/mesalib/src/mesa/main/api_arrayelt.h
@@ -0,0 +1,42 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef API_ARRAYELT_H
+#define API_ARRAYELT_H
+
+#include "mtypes.h"
+
+extern GLboolean _ae_create_context( GLcontext *ctx );
+extern void _ae_destroy_context( GLcontext *ctx );
+extern void _ae_invalidate_state( GLcontext *ctx, GLuint new_state );
+extern void GLAPIENTRY _ae_loopback_array_elt( GLint elt );
+
+/* May optionally be called before a batch of element calls:
+ */
+extern void _ae_map_vbos( GLcontext *ctx );
+extern void _ae_unmap_vbos( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/api_exec.c b/mesalib/src/mesa/main/api_exec.c
new file mode 100644
index 000000000..02550ae10
--- /dev/null
+++ b/mesalib/src/mesa/main/api_exec.c
@@ -0,0 +1,925 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file api_exec.c
+ * Initialize dispatch table with the immidiate mode functions.
+ */
+
+
+#include "mfeatures.h"
+#if FEATURE_accum
+#include "accum.h"
+#endif
+#include "api_loopback.h"
+#include "api_exec.h"
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+#include "shader/arbprogram.h"
+#endif
+#if FEATURE_ATI_fragment_shader
+#include "shader/atifragshader.h"
+#endif
+#if FEATURE_attrib_stack
+#include "attrib.h"
+#endif
+#include "blend.h"
+#if FEATURE_ARB_vertex_buffer_object
+#include "bufferobj.h"
+#endif
+#include "arrayobj.h"
+#if FEATURE_draw_read_buffer
+#include "buffers.h"
+#endif
+#include "clear.h"
+#include "clip.h"
+#if FEATURE_colortable
+#include "colortab.h"
+#endif
+#include "context.h"
+#if FEATURE_convolve
+#include "convolve.h"
+#endif
+#include "depth.h"
+#if FEATURE_dlist
+#include "dlist.h"
+#endif
+#if FEATURE_drawpix
+#include "drawpix.h"
+#include "rastpos.h"
+#endif
+#include "enable.h"
+#if FEATURE_evaluators
+#include "eval.h"
+#endif
+#include "get.h"
+#if FEATURE_feedback
+#include "feedback.h"
+#endif
+#include "fog.h"
+#if FEATURE_EXT_framebuffer_object
+#include "fbobject.h"
+#endif
+#include "ffvertex_prog.h"
+#include "framebuffer.h"
+#include "hint.h"
+#if FEATURE_histogram
+#include "histogram.h"
+#endif
+#include "imports.h"
+#include "light.h"
+#include "lines.h"
+#include "macros.h"
+#include "matrix.h"
+#include "multisample.h"
+#if FEATURE_pixel_transfer
+#include "pixel.h"
+#endif
+#include "pixelstore.h"
+#include "points.h"
+#include "polygon.h"
+#if FEATURE_ARB_occlusion_query || FEATURE_EXT_timer_query
+#include "queryobj.h"
+#endif
+#include "readpix.h"
+#include "scissor.h"
+#include "state.h"
+#include "stencil.h"
+#include "texenv.h"
+#include "texgetimage.h"
+#include "teximage.h"
+#if FEATURE_texgen
+#include "texgen.h"
+#endif
+#include "texobj.h"
+#include "texparam.h"
+#include "texstate.h"
+#include "mtypes.h"
+#include "varray.h"
+#include "viewport.h"
+#if FEATURE_NV_vertex_program
+#include "shader/nvprogram.h"
+#endif
+#if FEATURE_NV_fragment_program
+#include "shader/nvprogram.h"
+#include "shader/program.h"
+#include "texenvprogram.h"
+#endif
+#if FEATURE_ARB_shader_objects
+#include "shaders.h"
+#endif
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+#endif
+#include "debug.h"
+#include "glapi/dispatch.h"
+
+
+
+/**
+ * Initialize a dispatch table with pointers to Mesa's immediate-mode
+ * commands.
+ *
+ * Pointers to glBegin()/glEnd() object commands and a few others
+ * are provided via the GLvertexformat interface.
+ *
+ * \param ctx GL context to which \c exec belongs.
+ * \param exec dispatch table.
+ */
+void
+_mesa_init_exec_table(struct _glapi_table *exec)
+{
+#if _HAVE_FULL_GL
+ _mesa_loopback_init_api_table( exec );
+#endif
+
+ /* load the dispatch slots we understand */
+ SET_AlphaFunc(exec, _mesa_AlphaFunc);
+ SET_BlendFunc(exec, _mesa_BlendFunc);
+ SET_Clear(exec, _mesa_Clear);
+ SET_ClearColor(exec, _mesa_ClearColor);
+ SET_ClearStencil(exec, _mesa_ClearStencil);
+ SET_ColorMask(exec, _mesa_ColorMask);
+ SET_CullFace(exec, _mesa_CullFace);
+ SET_Disable(exec, _mesa_Disable);
+#if FEATURE_draw_read_buffer
+ SET_DrawBuffer(exec, _mesa_DrawBuffer);
+ SET_ReadBuffer(exec, _mesa_ReadBuffer);
+#endif
+ SET_Enable(exec, _mesa_Enable);
+ SET_Finish(exec, _mesa_Finish);
+ SET_Flush(exec, _mesa_Flush);
+ SET_FrontFace(exec, _mesa_FrontFace);
+ SET_Frustum(exec, _mesa_Frustum);
+ SET_GetError(exec, _mesa_GetError);
+ SET_GetFloatv(exec, _mesa_GetFloatv);
+ SET_GetString(exec, _mesa_GetString);
+ SET_LineStipple(exec, _mesa_LineStipple);
+ SET_LineWidth(exec, _mesa_LineWidth);
+ SET_LoadIdentity(exec, _mesa_LoadIdentity);
+ SET_LoadMatrixf(exec, _mesa_LoadMatrixf);
+ SET_LogicOp(exec, _mesa_LogicOp);
+ SET_MatrixMode(exec, _mesa_MatrixMode);
+ SET_MultMatrixf(exec, _mesa_MultMatrixf);
+ SET_Ortho(exec, _mesa_Ortho);
+ SET_PixelStorei(exec, _mesa_PixelStorei);
+ SET_PopMatrix(exec, _mesa_PopMatrix);
+ SET_PushMatrix(exec, _mesa_PushMatrix);
+ SET_Rotatef(exec, _mesa_Rotatef);
+ SET_Scalef(exec, _mesa_Scalef);
+ SET_Scissor(exec, _mesa_Scissor);
+ SET_ShadeModel(exec, _mesa_ShadeModel);
+ SET_StencilFunc(exec, _mesa_StencilFunc);
+ SET_StencilMask(exec, _mesa_StencilMask);
+ SET_StencilOp(exec, _mesa_StencilOp);
+ SET_TexEnvfv(exec, _mesa_TexEnvfv);
+ SET_TexEnvi(exec, _mesa_TexEnvi);
+ SET_TexImage2D(exec, _mesa_TexImage2D);
+ SET_TexParameteri(exec, _mesa_TexParameteri);
+ SET_Translatef(exec, _mesa_Translatef);
+ SET_Viewport(exec, _mesa_Viewport);
+#if FEATURE_accum
+ SET_Accum(exec, _mesa_Accum);
+ SET_ClearAccum(exec, _mesa_ClearAccum);
+#endif
+#if FEATURE_dlist
+ SET_CallList(exec, _mesa_CallList);
+ SET_CallLists(exec, _mesa_CallLists);
+ SET_DeleteLists(exec, _mesa_DeleteLists);
+ SET_EndList(exec, _mesa_EndList);
+ SET_GenLists(exec, _mesa_GenLists);
+ SET_IsList(exec, _mesa_IsList);
+ SET_ListBase(exec, _mesa_ListBase);
+ SET_NewList(exec, _mesa_NewList);
+#endif
+ SET_ClearDepth(exec, _mesa_ClearDepth);
+ SET_ClearIndex(exec, _mesa_ClearIndex);
+ SET_ClipPlane(exec, _mesa_ClipPlane);
+ SET_ColorMaterial(exec, _mesa_ColorMaterial);
+ SET_CullParameterfvEXT(exec, _mesa_CullParameterfvEXT);
+ SET_CullParameterdvEXT(exec, _mesa_CullParameterdvEXT);
+ SET_DepthFunc(exec, _mesa_DepthFunc);
+ SET_DepthMask(exec, _mesa_DepthMask);
+ SET_DepthRange(exec, _mesa_DepthRange);
+#if FEATURE_drawpix
+ SET_Bitmap(exec, _mesa_Bitmap);
+ SET_CopyPixels(exec, _mesa_CopyPixels);
+ SET_DrawPixels(exec, _mesa_DrawPixels);
+#endif
+#if FEATURE_feedback
+ SET_InitNames(exec, _mesa_InitNames);
+ SET_FeedbackBuffer(exec, _mesa_FeedbackBuffer);
+ SET_LoadName(exec, _mesa_LoadName);
+ SET_PassThrough(exec, _mesa_PassThrough);
+ SET_PopName(exec, _mesa_PopName);
+ SET_PushName(exec, _mesa_PushName);
+ SET_SelectBuffer(exec, _mesa_SelectBuffer);
+ SET_RenderMode(exec, _mesa_RenderMode);
+#endif
+ SET_FogCoordPointerEXT(exec, _mesa_FogCoordPointerEXT);
+ SET_Fogf(exec, _mesa_Fogf);
+ SET_Fogfv(exec, _mesa_Fogfv);
+ SET_Fogi(exec, _mesa_Fogi);
+ SET_Fogiv(exec, _mesa_Fogiv);
+ SET_GetClipPlane(exec, _mesa_GetClipPlane);
+ SET_GetBooleanv(exec, _mesa_GetBooleanv);
+ SET_GetDoublev(exec, _mesa_GetDoublev);
+ SET_GetIntegerv(exec, _mesa_GetIntegerv);
+ SET_GetLightfv(exec, _mesa_GetLightfv);
+ SET_GetLightiv(exec, _mesa_GetLightiv);
+ SET_GetMaterialfv(exec, _mesa_GetMaterialfv);
+ SET_GetMaterialiv(exec, _mesa_GetMaterialiv);
+ SET_GetPolygonStipple(exec, _mesa_GetPolygonStipple);
+ SET_GetTexEnvfv(exec, _mesa_GetTexEnvfv);
+ SET_GetTexEnviv(exec, _mesa_GetTexEnviv);
+ SET_GetTexLevelParameterfv(exec, _mesa_GetTexLevelParameterfv);
+ SET_GetTexLevelParameteriv(exec, _mesa_GetTexLevelParameteriv);
+ SET_GetTexParameterfv(exec, _mesa_GetTexParameterfv);
+ SET_GetTexParameteriv(exec, _mesa_GetTexParameteriv);
+ SET_GetTexImage(exec, _mesa_GetTexImage);
+ SET_Hint(exec, _mesa_Hint);
+ SET_IndexMask(exec, _mesa_IndexMask);
+ SET_IsEnabled(exec, _mesa_IsEnabled);
+ SET_LightModelf(exec, _mesa_LightModelf);
+ SET_LightModelfv(exec, _mesa_LightModelfv);
+ SET_LightModeli(exec, _mesa_LightModeli);
+ SET_LightModeliv(exec, _mesa_LightModeliv);
+ SET_Lightf(exec, _mesa_Lightf);
+ SET_Lightfv(exec, _mesa_Lightfv);
+ SET_Lighti(exec, _mesa_Lighti);
+ SET_Lightiv(exec, _mesa_Lightiv);
+ SET_LoadMatrixd(exec, _mesa_LoadMatrixd);
+#if FEATURE_evaluators
+ SET_GetMapdv(exec, _mesa_GetMapdv);
+ SET_GetMapfv(exec, _mesa_GetMapfv);
+ SET_GetMapiv(exec, _mesa_GetMapiv);
+ SET_Map1d(exec, _mesa_Map1d);
+ SET_Map1f(exec, _mesa_Map1f);
+ SET_Map2d(exec, _mesa_Map2d);
+ SET_Map2f(exec, _mesa_Map2f);
+ SET_MapGrid1d(exec, _mesa_MapGrid1d);
+ SET_MapGrid1f(exec, _mesa_MapGrid1f);
+ SET_MapGrid2d(exec, _mesa_MapGrid2d);
+ SET_MapGrid2f(exec, _mesa_MapGrid2f);
+#endif
+ SET_MultMatrixd(exec, _mesa_MultMatrixd);
+#if FEATURE_pixel_transfer
+ SET_GetPixelMapfv(exec, _mesa_GetPixelMapfv);
+ SET_GetPixelMapuiv(exec, _mesa_GetPixelMapuiv);
+ SET_GetPixelMapusv(exec, _mesa_GetPixelMapusv);
+ SET_PixelMapfv(exec, _mesa_PixelMapfv);
+ SET_PixelMapuiv(exec, _mesa_PixelMapuiv);
+ SET_PixelMapusv(exec, _mesa_PixelMapusv);
+ SET_PixelTransferf(exec, _mesa_PixelTransferf);
+ SET_PixelTransferi(exec, _mesa_PixelTransferi);
+ SET_PixelZoom(exec, _mesa_PixelZoom);
+#endif
+ SET_PixelStoref(exec, _mesa_PixelStoref);
+ SET_PointSize(exec, _mesa_PointSize);
+ SET_PolygonMode(exec, _mesa_PolygonMode);
+ SET_PolygonOffset(exec, _mesa_PolygonOffset);
+ SET_PolygonStipple(exec, _mesa_PolygonStipple);
+#if FEATURE_attrib_stack
+ SET_PopAttrib(exec, _mesa_PopAttrib);
+ SET_PushAttrib(exec, _mesa_PushAttrib);
+ SET_PopClientAttrib(exec, _mesa_PopClientAttrib);
+ SET_PushClientAttrib(exec, _mesa_PushClientAttrib);
+#endif
+#if FEATURE_drawpix
+ SET_RasterPos2f(exec, _mesa_RasterPos2f);
+ SET_RasterPos2fv(exec, _mesa_RasterPos2fv);
+ SET_RasterPos2i(exec, _mesa_RasterPos2i);
+ SET_RasterPos2iv(exec, _mesa_RasterPos2iv);
+ SET_RasterPos2d(exec, _mesa_RasterPos2d);
+ SET_RasterPos2dv(exec, _mesa_RasterPos2dv);
+ SET_RasterPos2s(exec, _mesa_RasterPos2s);
+ SET_RasterPos2sv(exec, _mesa_RasterPos2sv);
+ SET_RasterPos3d(exec, _mesa_RasterPos3d);
+ SET_RasterPos3dv(exec, _mesa_RasterPos3dv);
+ SET_RasterPos3f(exec, _mesa_RasterPos3f);
+ SET_RasterPos3fv(exec, _mesa_RasterPos3fv);
+ SET_RasterPos3i(exec, _mesa_RasterPos3i);
+ SET_RasterPos3iv(exec, _mesa_RasterPos3iv);
+ SET_RasterPos3s(exec, _mesa_RasterPos3s);
+ SET_RasterPos3sv(exec, _mesa_RasterPos3sv);
+ SET_RasterPos4d(exec, _mesa_RasterPos4d);
+ SET_RasterPos4dv(exec, _mesa_RasterPos4dv);
+ SET_RasterPos4f(exec, _mesa_RasterPos4f);
+ SET_RasterPos4fv(exec, _mesa_RasterPos4fv);
+ SET_RasterPos4i(exec, _mesa_RasterPos4i);
+ SET_RasterPos4iv(exec, _mesa_RasterPos4iv);
+ SET_RasterPos4s(exec, _mesa_RasterPos4s);
+ SET_RasterPos4sv(exec, _mesa_RasterPos4sv);
+#endif
+ SET_ReadPixels(exec, _mesa_ReadPixels);
+ SET_Rotated(exec, _mesa_Rotated);
+ SET_Scaled(exec, _mesa_Scaled);
+ SET_SecondaryColorPointerEXT(exec, _mesa_SecondaryColorPointerEXT);
+ SET_TexEnvf(exec, _mesa_TexEnvf);
+ SET_TexEnviv(exec, _mesa_TexEnviv);
+
+#if FEATURE_texgen
+ SET_GetTexGendv(exec, _mesa_GetTexGendv);
+ SET_GetTexGenfv(exec, _mesa_GetTexGenfv);
+ SET_GetTexGeniv(exec, _mesa_GetTexGeniv);
+ SET_TexGend(exec, _mesa_TexGend);
+ SET_TexGendv(exec, _mesa_TexGendv);
+ SET_TexGenf(exec, _mesa_TexGenf);
+ SET_TexGenfv(exec, _mesa_TexGenfv);
+ SET_TexGeni(exec, _mesa_TexGeni);
+ SET_TexGeniv(exec, _mesa_TexGeniv);
+#endif
+
+ SET_TexImage1D(exec, _mesa_TexImage1D);
+ SET_TexParameterf(exec, _mesa_TexParameterf);
+ SET_TexParameterfv(exec, _mesa_TexParameterfv);
+ SET_TexParameteriv(exec, _mesa_TexParameteriv);
+ SET_Translated(exec, _mesa_Translated);
+
+ /* 1.1 */
+ SET_BindTexture(exec, _mesa_BindTexture);
+ SET_DeleteTextures(exec, _mesa_DeleteTextures);
+ SET_GenTextures(exec, _mesa_GenTextures);
+#if _HAVE_FULL_GL
+ SET_AreTexturesResident(exec, _mesa_AreTexturesResident);
+ SET_ColorPointer(exec, _mesa_ColorPointer);
+ SET_CopyTexImage1D(exec, _mesa_CopyTexImage1D);
+ SET_CopyTexImage2D(exec, _mesa_CopyTexImage2D);
+ SET_CopyTexSubImage1D(exec, _mesa_CopyTexSubImage1D);
+ SET_CopyTexSubImage2D(exec, _mesa_CopyTexSubImage2D);
+ SET_DisableClientState(exec, _mesa_DisableClientState);
+ SET_EdgeFlagPointer(exec, _mesa_EdgeFlagPointer);
+ SET_EnableClientState(exec, _mesa_EnableClientState);
+ SET_GetPointerv(exec, _mesa_GetPointerv);
+ SET_IndexPointer(exec, _mesa_IndexPointer);
+ SET_InterleavedArrays(exec, _mesa_InterleavedArrays);
+ SET_IsTexture(exec, _mesa_IsTexture);
+ SET_NormalPointer(exec, _mesa_NormalPointer);
+ SET_PrioritizeTextures(exec, _mesa_PrioritizeTextures);
+ SET_TexCoordPointer(exec, _mesa_TexCoordPointer);
+ SET_TexSubImage1D(exec, _mesa_TexSubImage1D);
+ SET_TexSubImage2D(exec, _mesa_TexSubImage2D);
+ SET_VertexPointer(exec, _mesa_VertexPointer);
+#endif
+
+ /* 1.2 */
+#if _HAVE_FULL_GL
+ SET_CopyTexSubImage3D(exec, _mesa_CopyTexSubImage3D);
+ SET_TexImage3D(exec, _mesa_TexImage3D);
+ SET_TexSubImage3D(exec, _mesa_TexSubImage3D);
+#endif
+
+ /* OpenGL 1.2 GL_ARB_imaging */
+ SET_BlendColor(exec, _mesa_BlendColor);
+ SET_BlendEquation(exec, _mesa_BlendEquation);
+ SET_BlendEquationSeparateEXT(exec, _mesa_BlendEquationSeparateEXT);
+
+#if FEATURE_colortable
+ SET_ColorSubTable(exec, _mesa_ColorSubTable);
+ SET_ColorTable(exec, _mesa_ColorTable);
+ SET_ColorTableParameterfv(exec, _mesa_ColorTableParameterfv);
+ SET_ColorTableParameteriv(exec, _mesa_ColorTableParameteriv);
+ SET_CopyColorSubTable(exec, _mesa_CopyColorSubTable);
+ SET_CopyColorTable(exec, _mesa_CopyColorTable);
+ SET_GetColorTable(exec, _mesa_GetColorTable);
+ SET_GetColorTableParameterfv(exec, _mesa_GetColorTableParameterfv);
+ SET_GetColorTableParameteriv(exec, _mesa_GetColorTableParameteriv);
+#endif
+
+#if FEATURE_convolve
+ SET_ConvolutionFilter1D(exec, _mesa_ConvolutionFilter1D);
+ SET_ConvolutionFilter2D(exec, _mesa_ConvolutionFilter2D);
+ SET_ConvolutionParameterf(exec, _mesa_ConvolutionParameterf);
+ SET_ConvolutionParameterfv(exec, _mesa_ConvolutionParameterfv);
+ SET_ConvolutionParameteri(exec, _mesa_ConvolutionParameteri);
+ SET_ConvolutionParameteriv(exec, _mesa_ConvolutionParameteriv);
+ SET_CopyConvolutionFilter1D(exec, _mesa_CopyConvolutionFilter1D);
+ SET_CopyConvolutionFilter2D(exec, _mesa_CopyConvolutionFilter2D);
+ SET_GetConvolutionFilter(exec, _mesa_GetConvolutionFilter);
+ SET_GetConvolutionParameterfv(exec, _mesa_GetConvolutionParameterfv);
+ SET_GetConvolutionParameteriv(exec, _mesa_GetConvolutionParameteriv);
+ SET_SeparableFilter2D(exec, _mesa_SeparableFilter2D);
+#endif
+#if FEATURE_histogram
+ SET_GetHistogram(exec, _mesa_GetHistogram);
+ SET_GetHistogramParameterfv(exec, _mesa_GetHistogramParameterfv);
+ SET_GetHistogramParameteriv(exec, _mesa_GetHistogramParameteriv);
+ SET_GetMinmax(exec, _mesa_GetMinmax);
+ SET_GetMinmaxParameterfv(exec, _mesa_GetMinmaxParameterfv);
+ SET_GetMinmaxParameteriv(exec, _mesa_GetMinmaxParameteriv);
+ SET_GetSeparableFilter(exec, _mesa_GetSeparableFilter);
+ SET_Histogram(exec, _mesa_Histogram);
+ SET_Minmax(exec, _mesa_Minmax);
+ SET_ResetHistogram(exec, _mesa_ResetHistogram);
+ SET_ResetMinmax(exec, _mesa_ResetMinmax);
+#endif
+
+ /* OpenGL 2.0 */
+ SET_StencilFuncSeparate(exec, _mesa_StencilFuncSeparate);
+ SET_StencilMaskSeparate(exec, _mesa_StencilMaskSeparate);
+ SET_StencilOpSeparate(exec, _mesa_StencilOpSeparate);
+#if FEATURE_ARB_shader_objects
+ SET_AttachShader(exec, _mesa_AttachShader);
+ SET_CreateProgram(exec, _mesa_CreateProgram);
+ SET_CreateShader(exec, _mesa_CreateShader);
+ SET_DeleteProgram(exec, _mesa_DeleteProgram);
+ SET_DeleteShader(exec, _mesa_DeleteShader);
+ SET_DetachShader(exec, _mesa_DetachShader);
+ SET_GetAttachedShaders(exec, _mesa_GetAttachedShaders);
+ SET_GetProgramiv(exec, _mesa_GetProgramiv);
+ SET_GetProgramInfoLog(exec, _mesa_GetProgramInfoLog);
+ SET_GetShaderiv(exec, _mesa_GetShaderiv);
+ SET_GetShaderInfoLog(exec, _mesa_GetShaderInfoLog);
+ SET_IsProgram(exec, _mesa_IsProgram);
+ SET_IsShader(exec, _mesa_IsShader);
+#endif
+
+ /* OpenGL 2.1 */
+#if FEATURE_ARB_shader_objects
+ SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
+ SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
+ SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
+ SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
+ SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
+ SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
+#endif
+
+
+ /* 2. GL_EXT_blend_color */
+#if 0
+/* SET_BlendColorEXT(exec, _mesa_BlendColorEXT); */
+#endif
+
+ /* 3. GL_EXT_polygon_offset */
+#if _HAVE_FULL_GL
+ SET_PolygonOffsetEXT(exec, _mesa_PolygonOffsetEXT);
+#endif
+
+ /* 6. GL_EXT_texture3d */
+#if 0
+/* SET_CopyTexSubImage3DEXT(exec, _mesa_CopyTexSubImage3D); */
+/* SET_TexImage3DEXT(exec, _mesa_TexImage3DEXT); */
+/* SET_TexSubImage3DEXT(exec, _mesa_TexSubImage3D); */
+#endif
+
+ /* 11. GL_EXT_histogram */
+#if 0
+ SET_GetHistogramEXT(exec, _mesa_GetHistogram);
+ SET_GetHistogramParameterfvEXT(exec, _mesa_GetHistogramParameterfv);
+ SET_GetHistogramParameterivEXT(exec, _mesa_GetHistogramParameteriv);
+ SET_GetMinmaxEXT(exec, _mesa_GetMinmax);
+ SET_GetMinmaxParameterfvEXT(exec, _mesa_GetMinmaxParameterfv);
+ SET_GetMinmaxParameterivEXT(exec, _mesa_GetMinmaxParameteriv);
+#endif
+
+ /* 14. SGI_color_table */
+#if 0
+ SET_ColorTableSGI(exec, _mesa_ColorTable);
+ SET_ColorSubTableSGI(exec, _mesa_ColorSubTable);
+ SET_GetColorTableSGI(exec, _mesa_GetColorTable);
+ SET_GetColorTableParameterfvSGI(exec, _mesa_GetColorTableParameterfv);
+ SET_GetColorTableParameterivSGI(exec, _mesa_GetColorTableParameteriv);
+#endif
+
+ /* 30. GL_EXT_vertex_array */
+#if _HAVE_FULL_GL
+ SET_ColorPointerEXT(exec, _mesa_ColorPointerEXT);
+ SET_EdgeFlagPointerEXT(exec, _mesa_EdgeFlagPointerEXT);
+ SET_IndexPointerEXT(exec, _mesa_IndexPointerEXT);
+ SET_NormalPointerEXT(exec, _mesa_NormalPointerEXT);
+ SET_TexCoordPointerEXT(exec, _mesa_TexCoordPointerEXT);
+ SET_VertexPointerEXT(exec, _mesa_VertexPointerEXT);
+#endif
+
+ /* 37. GL_EXT_blend_minmax */
+#if 0
+ SET_BlendEquationEXT(exec, _mesa_BlendEquationEXT);
+#endif
+
+ /* 54. GL_EXT_point_parameters */
+#if _HAVE_FULL_GL
+ SET_PointParameterfEXT(exec, _mesa_PointParameterf);
+ SET_PointParameterfvEXT(exec, _mesa_PointParameterfv);
+#endif
+
+ /* 97. GL_EXT_compiled_vertex_array */
+#if _HAVE_FULL_GL
+ SET_LockArraysEXT(exec, _mesa_LockArraysEXT);
+ SET_UnlockArraysEXT(exec, _mesa_UnlockArraysEXT);
+#endif
+
+ /* 148. GL_EXT_multi_draw_arrays */
+#if _HAVE_FULL_GL
+ SET_MultiDrawArraysEXT(exec, _mesa_MultiDrawArraysEXT);
+#endif
+
+ /* 173. GL_INGR_blend_func_separate */
+#if _HAVE_FULL_GL
+ SET_BlendFuncSeparateEXT(exec, _mesa_BlendFuncSeparateEXT);
+#endif
+
+ /* 196. GL_MESA_resize_buffers */
+#if _HAVE_FULL_GL
+ SET_ResizeBuffersMESA(exec, _mesa_ResizeBuffersMESA);
+#endif
+
+ /* 197. GL_MESA_window_pos */
+#if FEATURE_drawpix
+ SET_WindowPos2dMESA(exec, _mesa_WindowPos2dMESA);
+ SET_WindowPos2dvMESA(exec, _mesa_WindowPos2dvMESA);
+ SET_WindowPos2fMESA(exec, _mesa_WindowPos2fMESA);
+ SET_WindowPos2fvMESA(exec, _mesa_WindowPos2fvMESA);
+ SET_WindowPos2iMESA(exec, _mesa_WindowPos2iMESA);
+ SET_WindowPos2ivMESA(exec, _mesa_WindowPos2ivMESA);
+ SET_WindowPos2sMESA(exec, _mesa_WindowPos2sMESA);
+ SET_WindowPos2svMESA(exec, _mesa_WindowPos2svMESA);
+ SET_WindowPos3dMESA(exec, _mesa_WindowPos3dMESA);
+ SET_WindowPos3dvMESA(exec, _mesa_WindowPos3dvMESA);
+ SET_WindowPos3fMESA(exec, _mesa_WindowPos3fMESA);
+ SET_WindowPos3fvMESA(exec, _mesa_WindowPos3fvMESA);
+ SET_WindowPos3iMESA(exec, _mesa_WindowPos3iMESA);
+ SET_WindowPos3ivMESA(exec, _mesa_WindowPos3ivMESA);
+ SET_WindowPos3sMESA(exec, _mesa_WindowPos3sMESA);
+ SET_WindowPos3svMESA(exec, _mesa_WindowPos3svMESA);
+ SET_WindowPos4dMESA(exec, _mesa_WindowPos4dMESA);
+ SET_WindowPos4dvMESA(exec, _mesa_WindowPos4dvMESA);
+ SET_WindowPos4fMESA(exec, _mesa_WindowPos4fMESA);
+ SET_WindowPos4fvMESA(exec, _mesa_WindowPos4fvMESA);
+ SET_WindowPos4iMESA(exec, _mesa_WindowPos4iMESA);
+ SET_WindowPos4ivMESA(exec, _mesa_WindowPos4ivMESA);
+ SET_WindowPos4sMESA(exec, _mesa_WindowPos4sMESA);
+ SET_WindowPos4svMESA(exec, _mesa_WindowPos4svMESA);
+#endif
+
+ /* 200. GL_IBM_multimode_draw_arrays */
+#if _HAVE_FULL_GL
+ SET_MultiModeDrawArraysIBM(exec, _mesa_MultiModeDrawArraysIBM);
+ SET_MultiModeDrawElementsIBM(exec, _mesa_MultiModeDrawElementsIBM);
+#endif
+
+ /* 233. GL_NV_vertex_program */
+#if FEATURE_NV_vertex_program
+ SET_BindProgramNV(exec, _mesa_BindProgram);
+ SET_DeleteProgramsNV(exec, _mesa_DeletePrograms);
+ SET_ExecuteProgramNV(exec, _mesa_ExecuteProgramNV);
+ SET_GenProgramsNV(exec, _mesa_GenPrograms);
+ SET_AreProgramsResidentNV(exec, _mesa_AreProgramsResidentNV);
+ SET_RequestResidentProgramsNV(exec, _mesa_RequestResidentProgramsNV);
+ SET_GetProgramParameterfvNV(exec, _mesa_GetProgramParameterfvNV);
+ SET_GetProgramParameterdvNV(exec, _mesa_GetProgramParameterdvNV);
+ SET_GetProgramivNV(exec, _mesa_GetProgramivNV);
+ SET_GetProgramStringNV(exec, _mesa_GetProgramStringNV);
+ SET_GetTrackMatrixivNV(exec, _mesa_GetTrackMatrixivNV);
+ SET_GetVertexAttribdvNV(exec, _mesa_GetVertexAttribdvNV);
+ SET_GetVertexAttribfvNV(exec, _mesa_GetVertexAttribfvNV);
+ SET_GetVertexAttribivNV(exec, _mesa_GetVertexAttribivNV);
+ SET_GetVertexAttribPointervNV(exec, _mesa_GetVertexAttribPointervNV);
+ SET_IsProgramNV(exec, _mesa_IsProgramARB);
+ SET_LoadProgramNV(exec, _mesa_LoadProgramNV);
+ SET_ProgramEnvParameter4dARB(exec, _mesa_ProgramEnvParameter4dARB); /* alias to ProgramParameter4dNV */
+ SET_ProgramEnvParameter4dvARB(exec, _mesa_ProgramEnvParameter4dvARB); /* alias to ProgramParameter4dvNV */
+ SET_ProgramEnvParameter4fARB(exec, _mesa_ProgramEnvParameter4fARB); /* alias to ProgramParameter4fNV */
+ SET_ProgramEnvParameter4fvARB(exec, _mesa_ProgramEnvParameter4fvARB); /* alias to ProgramParameter4fvNV */
+ SET_ProgramParameters4dvNV(exec, _mesa_ProgramParameters4dvNV);
+ SET_ProgramParameters4fvNV(exec, _mesa_ProgramParameters4fvNV);
+ SET_TrackMatrixNV(exec, _mesa_TrackMatrixNV);
+ SET_VertexAttribPointerNV(exec, _mesa_VertexAttribPointerNV);
+ /* glVertexAttrib*NV functions handled in api_loopback.c */
+#endif
+
+ /* 273. GL_APPLE_vertex_array_object */
+ SET_BindVertexArrayAPPLE(exec, _mesa_BindVertexArrayAPPLE);
+ SET_DeleteVertexArraysAPPLE(exec, _mesa_DeleteVertexArraysAPPLE);
+ SET_GenVertexArraysAPPLE(exec, _mesa_GenVertexArraysAPPLE);
+ SET_IsVertexArrayAPPLE(exec, _mesa_IsVertexArrayAPPLE);
+
+ /* 282. GL_NV_fragment_program */
+#if FEATURE_NV_fragment_program
+ SET_ProgramNamedParameter4fNV(exec, _mesa_ProgramNamedParameter4fNV);
+ SET_ProgramNamedParameter4dNV(exec, _mesa_ProgramNamedParameter4dNV);
+ SET_ProgramNamedParameter4fvNV(exec, _mesa_ProgramNamedParameter4fvNV);
+ SET_ProgramNamedParameter4dvNV(exec, _mesa_ProgramNamedParameter4dvNV);
+ SET_GetProgramNamedParameterfvNV(exec, _mesa_GetProgramNamedParameterfvNV);
+ SET_GetProgramNamedParameterdvNV(exec, _mesa_GetProgramNamedParameterdvNV);
+ SET_ProgramLocalParameter4dARB(exec, _mesa_ProgramLocalParameter4dARB);
+ SET_ProgramLocalParameter4dvARB(exec, _mesa_ProgramLocalParameter4dvARB);
+ SET_ProgramLocalParameter4fARB(exec, _mesa_ProgramLocalParameter4fARB);
+ SET_ProgramLocalParameter4fvARB(exec, _mesa_ProgramLocalParameter4fvARB);
+ SET_GetProgramLocalParameterdvARB(exec, _mesa_GetProgramLocalParameterdvARB);
+ SET_GetProgramLocalParameterfvARB(exec, _mesa_GetProgramLocalParameterfvARB);
+#endif
+
+ /* 262. GL_NV_point_sprite */
+#if _HAVE_FULL_GL
+ SET_PointParameteriNV(exec, _mesa_PointParameteri);
+ SET_PointParameterivNV(exec, _mesa_PointParameteriv);
+#endif
+
+ /* 268. GL_EXT_stencil_two_side */
+#if _HAVE_FULL_GL
+ SET_ActiveStencilFaceEXT(exec, _mesa_ActiveStencilFaceEXT);
+#endif
+
+ /* ???. GL_EXT_depth_bounds_test */
+ SET_DepthBoundsEXT(exec, _mesa_DepthBoundsEXT);
+
+ SET_ProvokingVertexEXT(exec, _mesa_ProvokingVertexEXT);
+
+ /* ARB 1. GL_ARB_multitexture */
+#if _HAVE_FULL_GL
+ SET_ActiveTextureARB(exec, _mesa_ActiveTextureARB);
+ SET_ClientActiveTextureARB(exec, _mesa_ClientActiveTextureARB);
+#endif
+
+ /* ARB 3. GL_ARB_transpose_matrix */
+#if _HAVE_FULL_GL
+ SET_LoadTransposeMatrixdARB(exec, _mesa_LoadTransposeMatrixdARB);
+ SET_LoadTransposeMatrixfARB(exec, _mesa_LoadTransposeMatrixfARB);
+ SET_MultTransposeMatrixdARB(exec, _mesa_MultTransposeMatrixdARB);
+ SET_MultTransposeMatrixfARB(exec, _mesa_MultTransposeMatrixfARB);
+#endif
+
+ /* ARB 5. GL_ARB_multisample */
+#if _HAVE_FULL_GL
+ SET_SampleCoverageARB(exec, _mesa_SampleCoverageARB);
+#endif
+
+ /* ARB 12. GL_ARB_texture_compression */
+#if _HAVE_FULL_GL
+ SET_CompressedTexImage3DARB(exec, _mesa_CompressedTexImage3DARB);
+ SET_CompressedTexImage2DARB(exec, _mesa_CompressedTexImage2DARB);
+ SET_CompressedTexImage1DARB(exec, _mesa_CompressedTexImage1DARB);
+ SET_CompressedTexSubImage3DARB(exec, _mesa_CompressedTexSubImage3DARB);
+ SET_CompressedTexSubImage2DARB(exec, _mesa_CompressedTexSubImage2DARB);
+ SET_CompressedTexSubImage1DARB(exec, _mesa_CompressedTexSubImage1DARB);
+ SET_GetCompressedTexImageARB(exec, _mesa_GetCompressedTexImageARB);
+#endif
+
+ /* ARB 14. GL_ARB_point_parameters */
+ /* reuse EXT_point_parameters functions */
+
+ /* ARB 26. GL_ARB_vertex_program */
+ /* ARB 27. GL_ARB_fragment_program */
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ /* glVertexAttrib1sARB aliases glVertexAttrib1sNV */
+ /* glVertexAttrib1fARB aliases glVertexAttrib1fNV */
+ /* glVertexAttrib1dARB aliases glVertexAttrib1dNV */
+ /* glVertexAttrib2sARB aliases glVertexAttrib2sNV */
+ /* glVertexAttrib2fARB aliases glVertexAttrib2fNV */
+ /* glVertexAttrib2dARB aliases glVertexAttrib2dNV */
+ /* glVertexAttrib3sARB aliases glVertexAttrib3sNV */
+ /* glVertexAttrib3fARB aliases glVertexAttrib3fNV */
+ /* glVertexAttrib3dARB aliases glVertexAttrib3dNV */
+ /* glVertexAttrib4sARB aliases glVertexAttrib4sNV */
+ /* glVertexAttrib4fARB aliases glVertexAttrib4fNV */
+ /* glVertexAttrib4dARB aliases glVertexAttrib4dNV */
+ /* glVertexAttrib4NubARB aliases glVertexAttrib4NubNV */
+ /* glVertexAttrib1svARB aliases glVertexAttrib1svNV */
+ /* glVertexAttrib1fvARB aliases glVertexAttrib1fvNV */
+ /* glVertexAttrib1dvARB aliases glVertexAttrib1dvNV */
+ /* glVertexAttrib2svARB aliases glVertexAttrib2svNV */
+ /* glVertexAttrib2fvARB aliases glVertexAttrib2fvNV */
+ /* glVertexAttrib2dvARB aliases glVertexAttrib2dvNV */
+ /* glVertexAttrib3svARB aliases glVertexAttrib3svNV */
+ /* glVertexAttrib3fvARB aliases glVertexAttrib3fvNV */
+ /* glVertexAttrib3dvARB aliases glVertexAttrib3dvNV */
+ /* glVertexAttrib4svARB aliases glVertexAttrib4svNV */
+ /* glVertexAttrib4fvARB aliases glVertexAttrib4fvNV */
+ /* glVertexAttrib4dvARB aliases glVertexAttrib4dvNV */
+ /* glVertexAttrib4NubvARB aliases glVertexAttrib4NubvNV */
+ /* glVertexAttrib4bvARB handled in api_loopback.c */
+ /* glVertexAttrib4ivARB handled in api_loopback.c */
+ /* glVertexAttrib4ubvARB handled in api_loopback.c */
+ /* glVertexAttrib4usvARB handled in api_loopback.c */
+ /* glVertexAttrib4uivARB handled in api_loopback.c */
+ /* glVertexAttrib4NbvARB handled in api_loopback.c */
+ /* glVertexAttrib4NsvARB handled in api_loopback.c */
+ /* glVertexAttrib4NivARB handled in api_loopback.c */
+ /* glVertexAttrib4NusvARB handled in api_loopback.c */
+ /* glVertexAttrib4NuivARB handled in api_loopback.c */
+ SET_VertexAttribPointerARB(exec, _mesa_VertexAttribPointerARB);
+ SET_EnableVertexAttribArrayARB(exec, _mesa_EnableVertexAttribArrayARB);
+ SET_DisableVertexAttribArrayARB(exec, _mesa_DisableVertexAttribArrayARB);
+ SET_ProgramStringARB(exec, _mesa_ProgramStringARB);
+ /* glBindProgramARB aliases glBindProgramNV */
+ /* glDeleteProgramsARB aliases glDeleteProgramsNV */
+ /* glGenProgramsARB aliases glGenProgramsNV */
+ /* glIsProgramARB aliases glIsProgramNV */
+ SET_GetVertexAttribdvARB(exec, _mesa_GetVertexAttribdvARB);
+ SET_GetVertexAttribfvARB(exec, _mesa_GetVertexAttribfvARB);
+ SET_GetVertexAttribivARB(exec, _mesa_GetVertexAttribivARB);
+ /* glGetVertexAttribPointervARB aliases glGetVertexAttribPointervNV */
+ SET_ProgramEnvParameter4dARB(exec, _mesa_ProgramEnvParameter4dARB);
+ SET_ProgramEnvParameter4dvARB(exec, _mesa_ProgramEnvParameter4dvARB);
+ SET_ProgramEnvParameter4fARB(exec, _mesa_ProgramEnvParameter4fARB);
+ SET_ProgramEnvParameter4fvARB(exec, _mesa_ProgramEnvParameter4fvARB);
+ SET_ProgramLocalParameter4dARB(exec, _mesa_ProgramLocalParameter4dARB);
+ SET_ProgramLocalParameter4dvARB(exec, _mesa_ProgramLocalParameter4dvARB);
+ SET_ProgramLocalParameter4fARB(exec, _mesa_ProgramLocalParameter4fARB);
+ SET_ProgramLocalParameter4fvARB(exec, _mesa_ProgramLocalParameter4fvARB);
+ SET_GetProgramEnvParameterdvARB(exec, _mesa_GetProgramEnvParameterdvARB);
+ SET_GetProgramEnvParameterfvARB(exec, _mesa_GetProgramEnvParameterfvARB);
+ SET_GetProgramLocalParameterdvARB(exec, _mesa_GetProgramLocalParameterdvARB);
+ SET_GetProgramLocalParameterfvARB(exec, _mesa_GetProgramLocalParameterfvARB);
+ SET_GetProgramivARB(exec, _mesa_GetProgramivARB);
+ SET_GetProgramStringARB(exec, _mesa_GetProgramStringARB);
+#endif
+
+ /* ARB 28. GL_ARB_vertex_buffer_object */
+#if FEATURE_ARB_vertex_buffer_object
+ SET_BindBufferARB(exec, _mesa_BindBufferARB);
+ SET_BufferDataARB(exec, _mesa_BufferDataARB);
+ SET_BufferSubDataARB(exec, _mesa_BufferSubDataARB);
+ SET_DeleteBuffersARB(exec, _mesa_DeleteBuffersARB);
+ SET_GenBuffersARB(exec, _mesa_GenBuffersARB);
+ SET_GetBufferParameterivARB(exec, _mesa_GetBufferParameterivARB);
+ SET_GetBufferPointervARB(exec, _mesa_GetBufferPointervARB);
+ SET_GetBufferSubDataARB(exec, _mesa_GetBufferSubDataARB);
+ SET_IsBufferARB(exec, _mesa_IsBufferARB);
+ SET_MapBufferARB(exec, _mesa_MapBufferARB);
+ SET_UnmapBufferARB(exec, _mesa_UnmapBufferARB);
+#endif
+
+ /* ARB 29. GL_ARB_occlusion_query */
+#if FEATURE_ARB_occlusion_query
+ SET_GenQueriesARB(exec, _mesa_GenQueriesARB);
+ SET_DeleteQueriesARB(exec, _mesa_DeleteQueriesARB);
+ SET_IsQueryARB(exec, _mesa_IsQueryARB);
+ SET_BeginQueryARB(exec, _mesa_BeginQueryARB);
+ SET_EndQueryARB(exec, _mesa_EndQueryARB);
+ SET_GetQueryivARB(exec, _mesa_GetQueryivARB);
+ SET_GetQueryObjectivARB(exec, _mesa_GetQueryObjectivARB);
+ SET_GetQueryObjectuivARB(exec, _mesa_GetQueryObjectuivARB);
+#endif
+
+ /* ARB 37. GL_ARB_draw_buffers */
+#if FEATURE_draw_read_buffer
+ SET_DrawBuffersARB(exec, _mesa_DrawBuffersARB);
+#endif
+
+#if FEATURE_ARB_shader_objects
+ SET_DeleteObjectARB(exec, _mesa_DeleteObjectARB);
+ SET_GetHandleARB(exec, _mesa_GetHandleARB);
+ SET_DetachObjectARB(exec, _mesa_DetachObjectARB);
+ SET_CreateShaderObjectARB(exec, _mesa_CreateShaderObjectARB);
+ SET_ShaderSourceARB(exec, _mesa_ShaderSourceARB);
+ SET_CompileShaderARB(exec, _mesa_CompileShaderARB);
+ SET_CreateProgramObjectARB(exec, _mesa_CreateProgramObjectARB);
+ SET_AttachObjectARB(exec, _mesa_AttachObjectARB);
+ SET_LinkProgramARB(exec, _mesa_LinkProgramARB);
+ SET_UseProgramObjectARB(exec, _mesa_UseProgramObjectARB);
+ SET_ValidateProgramARB(exec, _mesa_ValidateProgramARB);
+ SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
+ SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
+ SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
+ SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
+ SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
+ SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
+ SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
+ SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
+ SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
+ SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
+ SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
+ SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
+ SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
+ SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
+ SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
+ SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
+ SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
+ SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
+ SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
+ SET_GetObjectParameterfvARB(exec, _mesa_GetObjectParameterfvARB);
+ SET_GetObjectParameterivARB(exec, _mesa_GetObjectParameterivARB);
+ SET_GetInfoLogARB(exec, _mesa_GetInfoLogARB);
+ SET_GetAttachedObjectsARB(exec, _mesa_GetAttachedObjectsARB);
+ SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
+ SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
+ SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
+ SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
+ SET_GetShaderSourceARB(exec, _mesa_GetShaderSourceARB);
+#endif /* FEATURE_ARB_shader_objects */
+
+#if FEATURE_ARB_vertex_shader
+ SET_BindAttribLocationARB(exec, _mesa_BindAttribLocationARB);
+ SET_GetActiveAttribARB(exec, _mesa_GetActiveAttribARB);
+ SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB);
+#endif /* FEATURE_ARB_vertex_shader */
+
+ /* GL_ARB_sync */
+#if FEATURE_ARB_sync
+ SET_IsSync(exec, _mesa_IsSync);
+ SET_DeleteSync(exec, _mesa_DeleteSync);
+ SET_FenceSync(exec, _mesa_FenceSync);
+ SET_ClientWaitSync(exec, _mesa_ClientWaitSync);
+ SET_WaitSync(exec, _mesa_WaitSync);
+ SET_GetInteger64v(exec, _mesa_GetInteger64v);
+ SET_GetSynciv(exec, _mesa_GetSynciv);
+#endif
+
+ /* GL_ATI_fragment_shader */
+#if FEATURE_ATI_fragment_shader
+ SET_GenFragmentShadersATI(exec, _mesa_GenFragmentShadersATI);
+ SET_BindFragmentShaderATI(exec, _mesa_BindFragmentShaderATI);
+ SET_DeleteFragmentShaderATI(exec, _mesa_DeleteFragmentShaderATI);
+ SET_BeginFragmentShaderATI(exec, _mesa_BeginFragmentShaderATI);
+ SET_EndFragmentShaderATI(exec, _mesa_EndFragmentShaderATI);
+ SET_PassTexCoordATI(exec, _mesa_PassTexCoordATI);
+ SET_SampleMapATI(exec, _mesa_SampleMapATI);
+ SET_ColorFragmentOp1ATI(exec, _mesa_ColorFragmentOp1ATI);
+ SET_ColorFragmentOp2ATI(exec, _mesa_ColorFragmentOp2ATI);
+ SET_ColorFragmentOp3ATI(exec, _mesa_ColorFragmentOp3ATI);
+ SET_AlphaFragmentOp1ATI(exec, _mesa_AlphaFragmentOp1ATI);
+ SET_AlphaFragmentOp2ATI(exec, _mesa_AlphaFragmentOp2ATI);
+ SET_AlphaFragmentOp3ATI(exec, _mesa_AlphaFragmentOp3ATI);
+ SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI);
+#endif
+
+ /* GL_ATI_envmap_bumpmap */
+ SET_GetTexBumpParameterivATI(exec, _mesa_GetTexBumpParameterivATI);
+ SET_GetTexBumpParameterfvATI(exec, _mesa_GetTexBumpParameterfvATI);
+ SET_TexBumpParameterivATI(exec, _mesa_TexBumpParameterivATI);
+ SET_TexBumpParameterfvATI(exec, _mesa_TexBumpParameterfvATI);
+
+#if FEATURE_EXT_framebuffer_object
+ SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT);
+ SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT);
+ SET_DeleteRenderbuffersEXT(exec, _mesa_DeleteRenderbuffersEXT);
+ SET_GenRenderbuffersEXT(exec, _mesa_GenRenderbuffersEXT);
+ SET_RenderbufferStorageEXT(exec, _mesa_RenderbufferStorageEXT);
+ SET_GetRenderbufferParameterivEXT(exec, _mesa_GetRenderbufferParameterivEXT);
+ SET_IsFramebufferEXT(exec, _mesa_IsFramebufferEXT);
+ SET_BindFramebufferEXT(exec, _mesa_BindFramebufferEXT);
+ SET_DeleteFramebuffersEXT(exec, _mesa_DeleteFramebuffersEXT);
+ SET_GenFramebuffersEXT(exec, _mesa_GenFramebuffersEXT);
+ SET_CheckFramebufferStatusEXT(exec, _mesa_CheckFramebufferStatusEXT);
+ SET_FramebufferTexture1DEXT(exec, _mesa_FramebufferTexture1DEXT);
+ SET_FramebufferTexture2DEXT(exec, _mesa_FramebufferTexture2DEXT);
+ SET_FramebufferTexture3DEXT(exec, _mesa_FramebufferTexture3DEXT);
+ SET_FramebufferRenderbufferEXT(exec, _mesa_FramebufferRenderbufferEXT);
+ SET_GetFramebufferAttachmentParameterivEXT(exec, _mesa_GetFramebufferAttachmentParameterivEXT);
+ SET_GenerateMipmapEXT(exec, _mesa_GenerateMipmapEXT);
+#endif
+
+#if FEATURE_EXT_timer_query
+ SET_GetQueryObjecti64vEXT(exec, _mesa_GetQueryObjecti64vEXT);
+ SET_GetQueryObjectui64vEXT(exec, _mesa_GetQueryObjectui64vEXT);
+#endif
+
+#if FEATURE_EXT_framebuffer_blit
+ SET_BlitFramebufferEXT(exec, _mesa_BlitFramebufferEXT);
+#endif
+
+ /* GL_EXT_gpu_program_parameters */
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ SET_ProgramEnvParameters4fvEXT(exec, _mesa_ProgramEnvParameters4fvEXT);
+ SET_ProgramLocalParameters4fvEXT(exec, _mesa_ProgramLocalParameters4fvEXT);
+#endif
+
+ /* GL_MESA_texture_array / GL_EXT_texture_array */
+#if FEATURE_EXT_framebuffer_object
+ SET_FramebufferTextureLayerEXT(exec, _mesa_FramebufferTextureLayerEXT);
+#endif
+
+ /* GL_ATI_separate_stencil */
+ SET_StencilFuncSeparateATI(exec, _mesa_StencilFuncSeparateATI);
+
+#if FEATURE_ARB_framebuffer_object
+ /* The ARB_fbo functions are the union of
+ * GL_EXT_fbo, GL_EXT_framebuffer_blit, GL_EXT_texture_array
+ */
+ SET_RenderbufferStorageMultisample(exec, _mesa_RenderbufferStorageMultisample);
+#endif
+
+#if FEATURE_ARB_map_buffer_range
+ SET_MapBufferRange(exec, _mesa_MapBufferRange);
+ SET_FlushMappedBufferRange(exec, _mesa_FlushMappedBufferRange);
+#endif
+
+ /* GL_ARB_copy_buffer */
+ SET_CopyBufferSubData(exec, _mesa_CopyBufferSubData);
+
+ /* GL_ARB_vertex_array_object */
+ SET_BindVertexArray(exec, _mesa_BindVertexArray);
+ SET_GenVertexArrays(exec, _mesa_GenVertexArrays);
+}
diff --git a/mesalib/src/mesa/main/api_exec.h b/mesalib/src/mesa/main/api_exec.h
new file mode 100644
index 000000000..4bd715053
--- /dev/null
+++ b/mesalib/src/mesa/main/api_exec.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 API_EXEC_H
+#define API_EXEC_H
+
+
+struct _glapi_table;
+
+
+extern void
+_mesa_init_exec_table(struct _glapi_table *exec);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c
new file mode 100644
index 000000000..0e3f5ff95
--- /dev/null
+++ b/mesalib/src/mesa/main/api_loopback.c
@@ -0,0 +1,1657 @@
+/**
+ * \file api_loopback.c
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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 "glheader.h"
+#include "macros.h"
+#include "api_loopback.h"
+#include "mtypes.h"
+#include "glapi/glapi.h"
+#include "glapi/glapitable.h"
+#include "glapi/glthread.h"
+#include "glapi/dispatch.h"
+
+/* KW: A set of functions to convert unusual Color/Normal/Vertex/etc
+ * calls to a smaller set of driver-provided formats. Currently just
+ * go back to dispatch to find these (eg. call glNormal3f directly),
+ * hence 'loopback'.
+ *
+ * The driver must supply all of the remaining entry points, which are
+ * listed in dd.h. The easiest way for a driver to do this is to
+ * install the supplied software t&l module.
+ */
+#define COLORF(r,g,b,a) CALL_Color4f(GET_DISPATCH(), (r,g,b,a))
+#define VERTEX2(x,y) CALL_Vertex2f(GET_DISPATCH(), (x,y))
+#define VERTEX3(x,y,z) CALL_Vertex3f(GET_DISPATCH(), (x,y,z))
+#define VERTEX4(x,y,z,w) CALL_Vertex4f(GET_DISPATCH(), (x,y,z,w))
+#define NORMAL(x,y,z) CALL_Normal3f(GET_DISPATCH(), (x,y,z))
+#define TEXCOORD1(s) CALL_TexCoord1f(GET_DISPATCH(), (s))
+#define TEXCOORD2(s,t) CALL_TexCoord2f(GET_DISPATCH(), (s,t))
+#define TEXCOORD3(s,t,u) CALL_TexCoord3f(GET_DISPATCH(), (s,t,u))
+#define TEXCOORD4(s,t,u,v) CALL_TexCoord4f(GET_DISPATCH(), (s,t,u,v))
+#define INDEX(c) CALL_Indexf(GET_DISPATCH(), (c))
+#define MULTI_TEXCOORD1(z,s) CALL_MultiTexCoord1fARB(GET_DISPATCH(), (z,s))
+#define MULTI_TEXCOORD2(z,s,t) CALL_MultiTexCoord2fARB(GET_DISPATCH(), (z,s,t))
+#define MULTI_TEXCOORD3(z,s,t,u) CALL_MultiTexCoord3fARB(GET_DISPATCH(), (z,s,t,u))
+#define MULTI_TEXCOORD4(z,s,t,u,v) CALL_MultiTexCoord4fARB(GET_DISPATCH(), (z,s,t,u,v))
+#define EVALCOORD1(x) CALL_EvalCoord1f(GET_DISPATCH(), (x))
+#define EVALCOORD2(x,y) CALL_EvalCoord2f(GET_DISPATCH(), (x,y))
+#define MATERIALFV(a,b,c) CALL_Materialfv(GET_DISPATCH(), (a,b,c))
+#define RECTF(a,b,c,d) CALL_Rectf(GET_DISPATCH(), (a,b,c,d))
+
+#define ATTRIB1NV(index,x) CALL_VertexAttrib1fNV(GET_DISPATCH(), (index,x))
+#define ATTRIB2NV(index,x,y) CALL_VertexAttrib2fNV(GET_DISPATCH(), (index,x,y))
+#define ATTRIB3NV(index,x,y,z) CALL_VertexAttrib3fNV(GET_DISPATCH(), (index,x,y,z))
+#define ATTRIB4NV(index,x,y,z,w) CALL_VertexAttrib4fNV(GET_DISPATCH(), (index,x,y,z,w))
+#define ATTRIB1ARB(index,x) CALL_VertexAttrib1fARB(GET_DISPATCH(), (index,x))
+#define ATTRIB2ARB(index,x,y) CALL_VertexAttrib2fARB(GET_DISPATCH(), (index,x,y))
+#define ATTRIB3ARB(index,x,y,z) CALL_VertexAttrib3fARB(GET_DISPATCH(), (index,x,y,z))
+#define ATTRIB4ARB(index,x,y,z,w) CALL_VertexAttrib4fARB(GET_DISPATCH(), (index,x,y,z,w))
+#define FOGCOORDF(x) CALL_FogCoordfEXT(GET_DISPATCH(), (x))
+#define SECONDARYCOLORF(a,b,c) CALL_SecondaryColor3fEXT(GET_DISPATCH(), (a,b,c))
+
+static void GLAPIENTRY
+loopback_Color3b_f( GLbyte red, GLbyte green, GLbyte blue )
+{
+ COLORF( BYTE_TO_FLOAT(red),
+ BYTE_TO_FLOAT(green),
+ BYTE_TO_FLOAT(blue),
+ 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3d_f( GLdouble red, GLdouble green, GLdouble blue )
+{
+ COLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue, 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3i_f( GLint red, GLint green, GLint blue )
+{
+ COLORF( INT_TO_FLOAT(red), INT_TO_FLOAT(green),
+ INT_TO_FLOAT(blue), 1.0);
+}
+
+static void GLAPIENTRY
+loopback_Color3s_f( GLshort red, GLshort green, GLshort blue )
+{
+ COLORF( SHORT_TO_FLOAT(red), SHORT_TO_FLOAT(green),
+ SHORT_TO_FLOAT(blue), 1.0);
+}
+
+static void GLAPIENTRY
+loopback_Color3ui_f( GLuint red, GLuint green, GLuint blue )
+{
+ COLORF( UINT_TO_FLOAT(red), UINT_TO_FLOAT(green),
+ UINT_TO_FLOAT(blue), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3us_f( GLushort red, GLushort green, GLushort blue )
+{
+ COLORF( USHORT_TO_FLOAT(red), USHORT_TO_FLOAT(green),
+ USHORT_TO_FLOAT(blue), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3ub_f( GLubyte red, GLubyte green, GLubyte blue )
+{
+ COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green),
+ UBYTE_TO_FLOAT(blue), 1.0 );
+}
+
+
+static void GLAPIENTRY
+loopback_Color3bv_f( const GLbyte *v )
+{
+ COLORF( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3dv_f( const GLdouble *v )
+{
+ COLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3iv_f( const GLint *v )
+{
+ COLORF( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3sv_f( const GLshort *v )
+{
+ COLORF( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3uiv_f( const GLuint *v )
+{
+ COLORF( UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3usv_f( const GLushort *v )
+{
+ COLORF( USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]), 1.0 );
+}
+
+static void GLAPIENTRY
+loopback_Color3ubv_f( const GLubyte *v )
+{
+ COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]), 1.0 );
+}
+
+
+static void GLAPIENTRY
+loopback_Color4b_f( GLbyte red, GLbyte green, GLbyte blue,
+ GLbyte alpha )
+{
+ COLORF( BYTE_TO_FLOAT(red), BYTE_TO_FLOAT(green),
+ BYTE_TO_FLOAT(blue), BYTE_TO_FLOAT(alpha) );
+}
+
+static void GLAPIENTRY
+loopback_Color4d_f( GLdouble red, GLdouble green, GLdouble blue,
+ GLdouble alpha )
+{
+ COLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue, (GLfloat) alpha );
+}
+
+static void GLAPIENTRY
+loopback_Color4i_f( GLint red, GLint green, GLint blue, GLint alpha )
+{
+ COLORF( INT_TO_FLOAT(red), INT_TO_FLOAT(green),
+ INT_TO_FLOAT(blue), INT_TO_FLOAT(alpha) );
+}
+
+static void GLAPIENTRY
+loopback_Color4s_f( GLshort red, GLshort green, GLshort blue,
+ GLshort alpha )
+{
+ COLORF( SHORT_TO_FLOAT(red), SHORT_TO_FLOAT(green),
+ SHORT_TO_FLOAT(blue), SHORT_TO_FLOAT(alpha) );
+}
+
+static void GLAPIENTRY
+loopback_Color4ui_f( GLuint red, GLuint green, GLuint blue, GLuint alpha )
+{
+ COLORF( UINT_TO_FLOAT(red), UINT_TO_FLOAT(green),
+ UINT_TO_FLOAT(blue), UINT_TO_FLOAT(alpha) );
+}
+
+static void GLAPIENTRY
+loopback_Color4us_f( GLushort red, GLushort green, GLushort blue, GLushort alpha )
+{
+ COLORF( USHORT_TO_FLOAT(red), USHORT_TO_FLOAT(green),
+ USHORT_TO_FLOAT(blue), USHORT_TO_FLOAT(alpha) );
+}
+
+static void GLAPIENTRY
+loopback_Color4ub_f( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+{
+ COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green),
+ UBYTE_TO_FLOAT(blue), UBYTE_TO_FLOAT(alpha) );
+}
+
+
+static void GLAPIENTRY
+loopback_Color4iv_f( const GLint *v )
+{
+ COLORF( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3]) );
+}
+
+
+static void GLAPIENTRY
+loopback_Color4bv_f( const GLbyte *v )
+{
+ COLORF( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]), BYTE_TO_FLOAT(v[3]) );
+}
+
+static void GLAPIENTRY
+loopback_Color4dv_f( const GLdouble *v )
+{
+ COLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+
+static void GLAPIENTRY
+loopback_Color4sv_f( const GLshort *v)
+{
+ COLORF( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]), SHORT_TO_FLOAT(v[3]) );
+}
+
+
+static void GLAPIENTRY
+loopback_Color4uiv_f( const GLuint *v)
+{
+ COLORF( UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]), UINT_TO_FLOAT(v[3]) );
+}
+
+static void GLAPIENTRY
+loopback_Color4usv_f( const GLushort *v)
+{
+ COLORF( USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]), USHORT_TO_FLOAT(v[3]) );
+}
+
+static void GLAPIENTRY
+loopback_Color4ubv_f( const GLubyte *v)
+{
+ COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]) );
+}
+
+
+static void GLAPIENTRY
+loopback_FogCoorddEXT( GLdouble d )
+{
+ FOGCOORDF( (GLfloat) d );
+}
+
+static void GLAPIENTRY
+loopback_FogCoorddvEXT( const GLdouble *v )
+{
+ FOGCOORDF( (GLfloat) *v );
+}
+
+
+static void GLAPIENTRY
+loopback_Indexd( GLdouble c )
+{
+ INDEX( (GLfloat) c );
+}
+
+static void GLAPIENTRY
+loopback_Indexi( GLint c )
+{
+ INDEX( (GLfloat) c );
+}
+
+static void GLAPIENTRY
+loopback_Indexs( GLshort c )
+{
+ INDEX( (GLfloat) c );
+}
+
+static void GLAPIENTRY
+loopback_Indexub( GLubyte c )
+{
+ INDEX( (GLfloat) c );
+}
+
+static void GLAPIENTRY
+loopback_Indexdv( const GLdouble *c )
+{
+ INDEX( (GLfloat) *c );
+}
+
+static void GLAPIENTRY
+loopback_Indexiv( const GLint *c )
+{
+ INDEX( (GLfloat) *c );
+}
+
+static void GLAPIENTRY
+loopback_Indexsv( const GLshort *c )
+{
+ INDEX( (GLfloat) *c );
+}
+
+static void GLAPIENTRY
+loopback_Indexubv( const GLubyte *c )
+{
+ INDEX( (GLfloat) *c );
+}
+
+
+static void GLAPIENTRY
+loopback_EdgeFlagv(const GLboolean *flag)
+{
+ CALL_EdgeFlag(GET_DISPATCH(), (*flag));
+}
+
+
+static void GLAPIENTRY
+loopback_Normal3b( GLbyte nx, GLbyte ny, GLbyte nz )
+{
+ NORMAL( BYTE_TO_FLOAT(nx), BYTE_TO_FLOAT(ny), BYTE_TO_FLOAT(nz) );
+}
+
+static void GLAPIENTRY
+loopback_Normal3d( GLdouble nx, GLdouble ny, GLdouble nz )
+{
+ NORMAL((GLfloat) nx, (GLfloat) ny, (GLfloat) nz);
+}
+
+static void GLAPIENTRY
+loopback_Normal3i( GLint nx, GLint ny, GLint nz )
+{
+ NORMAL( INT_TO_FLOAT(nx), INT_TO_FLOAT(ny), INT_TO_FLOAT(nz) );
+}
+
+static void GLAPIENTRY
+loopback_Normal3s( GLshort nx, GLshort ny, GLshort nz )
+{
+ NORMAL( SHORT_TO_FLOAT(nx), SHORT_TO_FLOAT(ny), SHORT_TO_FLOAT(nz) );
+}
+
+static void GLAPIENTRY
+loopback_Normal3bv( const GLbyte *v )
+{
+ NORMAL( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]), BYTE_TO_FLOAT(v[2]) );
+}
+
+static void GLAPIENTRY
+loopback_Normal3dv( const GLdouble *v )
+{
+ NORMAL( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_Normal3iv( const GLint *v )
+{
+ NORMAL( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]), INT_TO_FLOAT(v[2]) );
+}
+
+static void GLAPIENTRY
+loopback_Normal3sv( const GLshort *v )
+{
+ NORMAL( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]), SHORT_TO_FLOAT(v[2]) );
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1d( GLdouble s )
+{
+ TEXCOORD1((GLfloat) s);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1i( GLint s )
+{
+ TEXCOORD1((GLfloat) s);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1s( GLshort s )
+{
+ TEXCOORD1((GLfloat) s);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2d( GLdouble s, GLdouble t )
+{
+ TEXCOORD2((GLfloat) s,(GLfloat) t);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2s( GLshort s, GLshort t )
+{
+ TEXCOORD2((GLfloat) s,(GLfloat) t);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2i( GLint s, GLint t )
+{
+ TEXCOORD2((GLfloat) s,(GLfloat) t);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3d( GLdouble s, GLdouble t, GLdouble r )
+{
+ TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3i( GLint s, GLint t, GLint r )
+{
+ TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3s( GLshort s, GLshort t, GLshort r )
+{
+ TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q )
+{
+ TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4i( GLint s, GLint t, GLint r, GLint q )
+{
+ TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q )
+{
+ TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1dv( const GLdouble *v )
+{
+ TEXCOORD1((GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1iv( const GLint *v )
+{
+ TEXCOORD1((GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord1sv( const GLshort *v )
+{
+ TEXCOORD1((GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2dv( const GLdouble *v )
+{
+ TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2iv( const GLint *v )
+{
+ TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord2sv( const GLshort *v )
+{
+ TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3dv( const GLdouble *v )
+{
+ TEXCOORD3((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3iv( const GLint *v )
+{
+ TEXCOORD3((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord3sv( const GLshort *v )
+{
+ TEXCOORD3((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4dv( const GLdouble *v )
+{
+ TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4iv( const GLint *v )
+{
+ TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_TexCoord4sv( const GLshort *v )
+{
+ TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_Vertex2d( GLdouble x, GLdouble y )
+{
+ VERTEX2( (GLfloat) x, (GLfloat) y );
+}
+
+static void GLAPIENTRY
+loopback_Vertex2i( GLint x, GLint y )
+{
+ VERTEX2( (GLfloat) x, (GLfloat) y );
+}
+
+static void GLAPIENTRY
+loopback_Vertex2s( GLshort x, GLshort y )
+{
+ VERTEX2( (GLfloat) x, (GLfloat) y );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3d( GLdouble x, GLdouble y, GLdouble z )
+{
+ VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3i( GLint x, GLint y, GLint z )
+{
+ VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3s( GLshort x, GLshort y, GLshort z )
+{
+ VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w )
+{
+ VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4i( GLint x, GLint y, GLint z, GLint w )
+{
+ VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4s( GLshort x, GLshort y, GLshort z, GLshort w )
+{
+ VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w );
+}
+
+static void GLAPIENTRY
+loopback_Vertex2dv( const GLdouble *v )
+{
+ VERTEX2( (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex2iv( const GLint *v )
+{
+ VERTEX2( (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex2sv( const GLshort *v )
+{
+ VERTEX2( (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3dv( const GLdouble *v )
+{
+ VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3iv( const GLint *v )
+{
+ VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex3sv( const GLshort *v )
+{
+ VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4dv( const GLdouble *v )
+{
+ VERTEX4( (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4iv( const GLint *v )
+{
+ VERTEX4( (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_Vertex4sv( const GLshort *v )
+{
+ VERTEX4( (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1dARB(GLenum target, GLdouble s)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) s );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1dvARB(GLenum target, const GLdouble *v)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) v[0] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1iARB(GLenum target, GLint s)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) s );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1ivARB(GLenum target, const GLint *v)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) v[0] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1sARB(GLenum target, GLshort s)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) s );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord1svARB(GLenum target, const GLshort *v)
+{
+ MULTI_TEXCOORD1( target, (GLfloat) v[0] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2dvARB(GLenum target, const GLdouble *v)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2iARB(GLenum target, GLint s, GLint t)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2ivARB(GLenum target, const GLint *v)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2sARB(GLenum target, GLshort s, GLshort t)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord2svARB(GLenum target, const GLshort *v)
+{
+ MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3dvARB(GLenum target, const GLdouble *v)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3ivARB(GLenum target, const GLint *v)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord3svARB(GLenum target, const GLshort *v)
+{
+ MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t,
+ (GLfloat) r, (GLfloat) q );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4dvARB(GLenum target, const GLdouble *v)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t,
+ (GLfloat) r, (GLfloat) q );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4ivARB(GLenum target, const GLint *v)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t,
+ (GLfloat) r, (GLfloat) q );
+}
+
+static void GLAPIENTRY
+loopback_MultiTexCoord4svARB(GLenum target, const GLshort *v)
+{
+ MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3] );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord2dv( const GLdouble *u )
+{
+ EVALCOORD2( (GLfloat) u[0], (GLfloat) u[1] );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord2fv( const GLfloat *u )
+{
+ EVALCOORD2( u[0], u[1] );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord2d( GLdouble u, GLdouble v )
+{
+ EVALCOORD2( (GLfloat) u, (GLfloat) v );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord1dv( const GLdouble *u )
+{
+ EVALCOORD1( (GLfloat) *u );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord1fv( const GLfloat *u )
+{
+ EVALCOORD1( (GLfloat) *u );
+}
+
+static void GLAPIENTRY
+loopback_EvalCoord1d( GLdouble u )
+{
+ EVALCOORD1( (GLfloat) u );
+}
+
+static void GLAPIENTRY
+loopback_Materialf( GLenum face, GLenum pname, GLfloat param )
+{
+ GLfloat fparam[4];
+ fparam[0] = param;
+ MATERIALFV( face, pname, fparam );
+}
+
+static void GLAPIENTRY
+loopback_Materiali(GLenum face, GLenum pname, GLint param )
+{
+ GLfloat p = (GLfloat) param;
+ MATERIALFV(face, pname, &p);
+}
+
+static void GLAPIENTRY
+loopback_Materialiv(GLenum face, GLenum pname, const GLint *params )
+{
+ GLfloat fparam[4];
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ case GL_EMISSION:
+ case GL_AMBIENT_AND_DIFFUSE:
+ fparam[0] = INT_TO_FLOAT( params[0] );
+ fparam[1] = INT_TO_FLOAT( params[1] );
+ fparam[2] = INT_TO_FLOAT( params[2] );
+ fparam[3] = INT_TO_FLOAT( params[3] );
+ break;
+ case GL_SHININESS:
+ fparam[0] = (GLfloat) params[0];
+ break;
+ case GL_COLOR_INDEXES:
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = (GLfloat) params[1];
+ fparam[2] = (GLfloat) params[2];
+ break;
+ default:
+ ;
+ }
+ MATERIALFV(face, pname, fparam);
+}
+
+
+static void GLAPIENTRY
+loopback_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
+{
+ RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
+}
+
+static void GLAPIENTRY
+loopback_Rectdv(const GLdouble *v1, const GLdouble *v2)
+{
+ RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
+}
+
+static void GLAPIENTRY
+loopback_Rectfv(const GLfloat *v1, const GLfloat *v2)
+{
+ RECTF(v1[0], v1[1], v2[0], v2[1]);
+}
+
+static void GLAPIENTRY
+loopback_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
+{
+ RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
+}
+
+static void GLAPIENTRY
+loopback_Rectiv(const GLint *v1, const GLint *v2)
+{
+ RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
+}
+
+static void GLAPIENTRY
+loopback_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
+{
+ RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
+}
+
+static void GLAPIENTRY
+loopback_Rectsv(const GLshort *v1, const GLshort *v2)
+{
+ RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3bEXT_f( GLbyte red, GLbyte green, GLbyte blue )
+{
+ SECONDARYCOLORF( BYTE_TO_FLOAT(red),
+ BYTE_TO_FLOAT(green),
+ BYTE_TO_FLOAT(blue) );
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3dEXT_f( GLdouble red, GLdouble green, GLdouble blue )
+{
+ SECONDARYCOLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue );
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3iEXT_f( GLint red, GLint green, GLint blue )
+{
+ SECONDARYCOLORF( INT_TO_FLOAT(red),
+ INT_TO_FLOAT(green),
+ INT_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3sEXT_f( GLshort red, GLshort green, GLshort blue )
+{
+ SECONDARYCOLORF(SHORT_TO_FLOAT(red),
+ SHORT_TO_FLOAT(green),
+ SHORT_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3uiEXT_f( GLuint red, GLuint green, GLuint blue )
+{
+ SECONDARYCOLORF(UINT_TO_FLOAT(red),
+ UINT_TO_FLOAT(green),
+ UINT_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3usEXT_f( GLushort red, GLushort green, GLushort blue )
+{
+ SECONDARYCOLORF(USHORT_TO_FLOAT(red),
+ USHORT_TO_FLOAT(green),
+ USHORT_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3ubEXT_f( GLubyte red, GLubyte green, GLubyte blue )
+{
+ SECONDARYCOLORF(UBYTE_TO_FLOAT(red),
+ UBYTE_TO_FLOAT(green),
+ UBYTE_TO_FLOAT(blue));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3bvEXT_f( const GLbyte *v )
+{
+ SECONDARYCOLORF(BYTE_TO_FLOAT(v[0]),
+ BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3dvEXT_f( const GLdouble *v )
+{
+ SECONDARYCOLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] );
+}
+static void GLAPIENTRY
+loopback_SecondaryColor3ivEXT_f( const GLint *v )
+{
+ SECONDARYCOLORF(INT_TO_FLOAT(v[0]),
+ INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3svEXT_f( const GLshort *v )
+{
+ SECONDARYCOLORF(SHORT_TO_FLOAT(v[0]),
+ SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3uivEXT_f( const GLuint *v )
+{
+ SECONDARYCOLORF(UINT_TO_FLOAT(v[0]),
+ UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3usvEXT_f( const GLushort *v )
+{
+ SECONDARYCOLORF(USHORT_TO_FLOAT(v[0]),
+ USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]));
+}
+
+static void GLAPIENTRY
+loopback_SecondaryColor3ubvEXT_f( const GLubyte *v )
+{
+ SECONDARYCOLORF(UBYTE_TO_FLOAT(v[0]),
+ UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]));
+}
+
+
+/*
+ * GL_NV_vertex_program:
+ * Always loop-back to one of the VertexAttrib[1234]f[v]NV functions.
+ */
+
+static void GLAPIENTRY
+loopback_VertexAttrib1sNV(GLuint index, GLshort x)
+{
+ ATTRIB1NV(index, (GLfloat) x);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1dNV(GLuint index, GLdouble x)
+{
+ ATTRIB1NV(index, (GLfloat) x);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2sNV(GLuint index, GLshort x, GLshort y)
+{
+ ATTRIB2NV(index, (GLfloat) x, y);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2dNV(GLuint index, GLdouble x, GLdouble y)
+{
+ ATTRIB2NV(index, (GLfloat) x, (GLfloat) y);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3sNV(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ ATTRIB3NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4sNV(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4ubNV(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ ATTRIB4NV(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y),
+ UBYTE_TO_FLOAT(z), UBYTE_TO_FLOAT(w));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1svNV(GLuint index, const GLshort *v)
+{
+ ATTRIB1NV(index, (GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1dvNV(GLuint index, const GLdouble *v)
+{
+ ATTRIB1NV(index, (GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2svNV(GLuint index, const GLshort *v)
+{
+ ATTRIB2NV(index, (GLfloat) v[0], (GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2dvNV(GLuint index, const GLdouble *v)
+{
+ ATTRIB2NV(index, (GLfloat) v[0], (GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3svNV(GLuint index, const GLshort *v)
+{
+ ATTRIB3NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3dvNV(GLuint index, const GLdouble *v)
+{
+ ATTRIB3NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4svNV(GLuint index, const GLshort *v)
+{
+ ATTRIB4NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat)v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4dvNV(GLuint index, const GLdouble *v)
+{
+ ATTRIB4NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4ubvNV(GLuint index, const GLubyte *v)
+{
+ ATTRIB4NV(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]));
+}
+
+
+static void GLAPIENTRY
+loopback_VertexAttribs1svNV(GLuint index, GLsizei n, const GLshort *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib1svNV(index + i, v + i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs1fvNV(GLuint index, GLsizei n, const GLfloat *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ ATTRIB1NV(index + i, v[i]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs1dvNV(GLuint index, GLsizei n, const GLdouble *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib1dvNV(index + i, v + i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs2svNV(GLuint index, GLsizei n, const GLshort *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib2svNV(index + i, v + 2 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs2fvNV(GLuint index, GLsizei n, const GLfloat *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ ATTRIB2NV(index + i, v[2 * i], v[2 * i + 1]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs2dvNV(GLuint index, GLsizei n, const GLdouble *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib2dvNV(index + i, v + 2 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs3svNV(GLuint index, GLsizei n, const GLshort *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib3svNV(index + i, v + 3 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs3fvNV(GLuint index, GLsizei n, const GLfloat *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ ATTRIB3NV(index + i, v[3 * i], v[3 * i + 1], v[3 * i + 2]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs3dvNV(GLuint index, GLsizei n, const GLdouble *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib3dvNV(index + i, v + 3 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs4svNV(GLuint index, GLsizei n, const GLshort *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib4svNV(index + i, v + 4 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs4fvNV(GLuint index, GLsizei n, const GLfloat *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ ATTRIB4NV(index + i, v[4 * i], v[4 * i + 1], v[4 * i + 2], v[4 * i + 3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs4dvNV(GLuint index, GLsizei n, const GLdouble *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib4dvNV(index + i, v + 4 * i);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttribs4ubvNV(GLuint index, GLsizei n, const GLubyte *v)
+{
+ GLint i;
+ for (i = n - 1; i >= 0; i--)
+ loopback_VertexAttrib4ubvNV(index + i, v + 4 * i);
+}
+
+
+/*
+ * GL_ARB_vertex_program
+ * Always loop-back to one of the VertexAttrib[1234]f[v]ARB functions.
+ */
+
+static void GLAPIENTRY
+loopback_VertexAttrib1sARB(GLuint index, GLshort x)
+{
+ ATTRIB1ARB(index, (GLfloat) x);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1dARB(GLuint index, GLdouble x)
+{
+ ATTRIB1ARB(index, (GLfloat) x);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2sARB(GLuint index, GLshort x, GLshort y)
+{
+ ATTRIB2ARB(index, (GLfloat) x, y);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y)
+{
+ ATTRIB2ARB(index, (GLfloat) x, (GLfloat) y);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ ATTRIB3ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1svARB(GLuint index, const GLshort *v)
+{
+ ATTRIB1ARB(index, (GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib1dvARB(GLuint index, const GLdouble *v)
+{
+ ATTRIB1ARB(index, (GLfloat) v[0]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2svARB(GLuint index, const GLshort *v)
+{
+ ATTRIB2ARB(index, (GLfloat) v[0], (GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib2dvARB(GLuint index, const GLdouble *v)
+{
+ ATTRIB2ARB(index, (GLfloat) v[0], (GLfloat) v[1]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3svARB(GLuint index, const GLshort *v)
+{
+ ATTRIB3ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib3dvARB(GLuint index, const GLdouble *v)
+{
+ ATTRIB3ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4svARB(GLuint index, const GLshort *v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat)v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4dvARB(GLuint index, const GLdouble *v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4bvARB(GLuint index, const GLbyte * v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4ivARB(GLuint index, const GLint * v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4ubvARB(GLuint index, const GLubyte * v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4usvARB(GLuint index, const GLushort * v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4uivARB(GLuint index, const GLuint * v)
+{
+ ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NbvARB(GLuint index, const GLbyte * v)
+{
+ ATTRIB4ARB(index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]),
+ BYTE_TO_FLOAT(v[2]), BYTE_TO_FLOAT(v[3]));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NsvARB(GLuint index, const GLshort * v)
+{
+ ATTRIB4ARB(index, SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]),
+ SHORT_TO_FLOAT(v[2]), SHORT_TO_FLOAT(v[3]));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NivARB(GLuint index, const GLint * v)
+{
+ ATTRIB4ARB(index, INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]),
+ INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3]));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ ATTRIB4ARB(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y),
+ UBYTE_TO_FLOAT(z), UBYTE_TO_FLOAT(w));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NubvARB(GLuint index, const GLubyte * v)
+{
+ ATTRIB4ARB(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]),
+ UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NusvARB(GLuint index, const GLushort * v)
+{
+ ATTRIB4ARB(index, USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]),
+ USHORT_TO_FLOAT(v[2]), USHORT_TO_FLOAT(v[3]));
+}
+
+static void GLAPIENTRY
+loopback_VertexAttrib4NuivARB(GLuint index, const GLuint * v)
+{
+ ATTRIB4ARB(index, UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]),
+ UINT_TO_FLOAT(v[2]), UINT_TO_FLOAT(v[3]));
+}
+
+
+
+
+/*
+ * This code never registers handlers for any of the entry points
+ * listed in vtxfmt.h.
+ */
+void
+_mesa_loopback_init_api_table( struct _glapi_table *dest )
+{
+ SET_Color3b(dest, loopback_Color3b_f);
+ SET_Color3d(dest, loopback_Color3d_f);
+ SET_Color3i(dest, loopback_Color3i_f);
+ SET_Color3s(dest, loopback_Color3s_f);
+ SET_Color3ui(dest, loopback_Color3ui_f);
+ SET_Color3us(dest, loopback_Color3us_f);
+ SET_Color3ub(dest, loopback_Color3ub_f);
+ SET_Color4b(dest, loopback_Color4b_f);
+ SET_Color4d(dest, loopback_Color4d_f);
+ SET_Color4i(dest, loopback_Color4i_f);
+ SET_Color4s(dest, loopback_Color4s_f);
+ SET_Color4ui(dest, loopback_Color4ui_f);
+ SET_Color4us(dest, loopback_Color4us_f);
+ SET_Color4ub(dest, loopback_Color4ub_f);
+ SET_Color3bv(dest, loopback_Color3bv_f);
+ SET_Color3dv(dest, loopback_Color3dv_f);
+ SET_Color3iv(dest, loopback_Color3iv_f);
+ SET_Color3sv(dest, loopback_Color3sv_f);
+ SET_Color3uiv(dest, loopback_Color3uiv_f);
+ SET_Color3usv(dest, loopback_Color3usv_f);
+ SET_Color3ubv(dest, loopback_Color3ubv_f);
+ SET_Color4bv(dest, loopback_Color4bv_f);
+ SET_Color4dv(dest, loopback_Color4dv_f);
+ SET_Color4iv(dest, loopback_Color4iv_f);
+ SET_Color4sv(dest, loopback_Color4sv_f);
+ SET_Color4uiv(dest, loopback_Color4uiv_f);
+ SET_Color4usv(dest, loopback_Color4usv_f);
+ SET_Color4ubv(dest, loopback_Color4ubv_f);
+
+ SET_SecondaryColor3bEXT(dest, loopback_SecondaryColor3bEXT_f);
+ SET_SecondaryColor3dEXT(dest, loopback_SecondaryColor3dEXT_f);
+ SET_SecondaryColor3iEXT(dest, loopback_SecondaryColor3iEXT_f);
+ SET_SecondaryColor3sEXT(dest, loopback_SecondaryColor3sEXT_f);
+ SET_SecondaryColor3uiEXT(dest, loopback_SecondaryColor3uiEXT_f);
+ SET_SecondaryColor3usEXT(dest, loopback_SecondaryColor3usEXT_f);
+ SET_SecondaryColor3ubEXT(dest, loopback_SecondaryColor3ubEXT_f);
+ SET_SecondaryColor3bvEXT(dest, loopback_SecondaryColor3bvEXT_f);
+ SET_SecondaryColor3dvEXT(dest, loopback_SecondaryColor3dvEXT_f);
+ SET_SecondaryColor3ivEXT(dest, loopback_SecondaryColor3ivEXT_f);
+ SET_SecondaryColor3svEXT(dest, loopback_SecondaryColor3svEXT_f);
+ SET_SecondaryColor3uivEXT(dest, loopback_SecondaryColor3uivEXT_f);
+ SET_SecondaryColor3usvEXT(dest, loopback_SecondaryColor3usvEXT_f);
+ SET_SecondaryColor3ubvEXT(dest, loopback_SecondaryColor3ubvEXT_f);
+
+ SET_EdgeFlagv(dest, loopback_EdgeFlagv);
+
+ SET_Indexd(dest, loopback_Indexd);
+ SET_Indexi(dest, loopback_Indexi);
+ SET_Indexs(dest, loopback_Indexs);
+ SET_Indexub(dest, loopback_Indexub);
+ SET_Indexdv(dest, loopback_Indexdv);
+ SET_Indexiv(dest, loopback_Indexiv);
+ SET_Indexsv(dest, loopback_Indexsv);
+ SET_Indexubv(dest, loopback_Indexubv);
+ SET_Normal3b(dest, loopback_Normal3b);
+ SET_Normal3d(dest, loopback_Normal3d);
+ SET_Normal3i(dest, loopback_Normal3i);
+ SET_Normal3s(dest, loopback_Normal3s);
+ SET_Normal3bv(dest, loopback_Normal3bv);
+ SET_Normal3dv(dest, loopback_Normal3dv);
+ SET_Normal3iv(dest, loopback_Normal3iv);
+ SET_Normal3sv(dest, loopback_Normal3sv);
+ SET_TexCoord1d(dest, loopback_TexCoord1d);
+ SET_TexCoord1i(dest, loopback_TexCoord1i);
+ SET_TexCoord1s(dest, loopback_TexCoord1s);
+ SET_TexCoord2d(dest, loopback_TexCoord2d);
+ SET_TexCoord2s(dest, loopback_TexCoord2s);
+ SET_TexCoord2i(dest, loopback_TexCoord2i);
+ SET_TexCoord3d(dest, loopback_TexCoord3d);
+ SET_TexCoord3i(dest, loopback_TexCoord3i);
+ SET_TexCoord3s(dest, loopback_TexCoord3s);
+ SET_TexCoord4d(dest, loopback_TexCoord4d);
+ SET_TexCoord4i(dest, loopback_TexCoord4i);
+ SET_TexCoord4s(dest, loopback_TexCoord4s);
+ SET_TexCoord1dv(dest, loopback_TexCoord1dv);
+ SET_TexCoord1iv(dest, loopback_TexCoord1iv);
+ SET_TexCoord1sv(dest, loopback_TexCoord1sv);
+ SET_TexCoord2dv(dest, loopback_TexCoord2dv);
+ SET_TexCoord2iv(dest, loopback_TexCoord2iv);
+ SET_TexCoord2sv(dest, loopback_TexCoord2sv);
+ SET_TexCoord3dv(dest, loopback_TexCoord3dv);
+ SET_TexCoord3iv(dest, loopback_TexCoord3iv);
+ SET_TexCoord3sv(dest, loopback_TexCoord3sv);
+ SET_TexCoord4dv(dest, loopback_TexCoord4dv);
+ SET_TexCoord4iv(dest, loopback_TexCoord4iv);
+ SET_TexCoord4sv(dest, loopback_TexCoord4sv);
+ SET_Vertex2d(dest, loopback_Vertex2d);
+ SET_Vertex2i(dest, loopback_Vertex2i);
+ SET_Vertex2s(dest, loopback_Vertex2s);
+ SET_Vertex3d(dest, loopback_Vertex3d);
+ SET_Vertex3i(dest, loopback_Vertex3i);
+ SET_Vertex3s(dest, loopback_Vertex3s);
+ SET_Vertex4d(dest, loopback_Vertex4d);
+ SET_Vertex4i(dest, loopback_Vertex4i);
+ SET_Vertex4s(dest, loopback_Vertex4s);
+ SET_Vertex2dv(dest, loopback_Vertex2dv);
+ SET_Vertex2iv(dest, loopback_Vertex2iv);
+ SET_Vertex2sv(dest, loopback_Vertex2sv);
+ SET_Vertex3dv(dest, loopback_Vertex3dv);
+ SET_Vertex3iv(dest, loopback_Vertex3iv);
+ SET_Vertex3sv(dest, loopback_Vertex3sv);
+ SET_Vertex4dv(dest, loopback_Vertex4dv);
+ SET_Vertex4iv(dest, loopback_Vertex4iv);
+ SET_Vertex4sv(dest, loopback_Vertex4sv);
+ SET_MultiTexCoord1dARB(dest, loopback_MultiTexCoord1dARB);
+ SET_MultiTexCoord1dvARB(dest, loopback_MultiTexCoord1dvARB);
+ SET_MultiTexCoord1iARB(dest, loopback_MultiTexCoord1iARB);
+ SET_MultiTexCoord1ivARB(dest, loopback_MultiTexCoord1ivARB);
+ SET_MultiTexCoord1sARB(dest, loopback_MultiTexCoord1sARB);
+ SET_MultiTexCoord1svARB(dest, loopback_MultiTexCoord1svARB);
+ SET_MultiTexCoord2dARB(dest, loopback_MultiTexCoord2dARB);
+ SET_MultiTexCoord2dvARB(dest, loopback_MultiTexCoord2dvARB);
+ SET_MultiTexCoord2iARB(dest, loopback_MultiTexCoord2iARB);
+ SET_MultiTexCoord2ivARB(dest, loopback_MultiTexCoord2ivARB);
+ SET_MultiTexCoord2sARB(dest, loopback_MultiTexCoord2sARB);
+ SET_MultiTexCoord2svARB(dest, loopback_MultiTexCoord2svARB);
+ SET_MultiTexCoord3dARB(dest, loopback_MultiTexCoord3dARB);
+ SET_MultiTexCoord3dvARB(dest, loopback_MultiTexCoord3dvARB);
+ SET_MultiTexCoord3iARB(dest, loopback_MultiTexCoord3iARB);
+ SET_MultiTexCoord3ivARB(dest, loopback_MultiTexCoord3ivARB);
+ SET_MultiTexCoord3sARB(dest, loopback_MultiTexCoord3sARB);
+ SET_MultiTexCoord3svARB(dest, loopback_MultiTexCoord3svARB);
+ SET_MultiTexCoord4dARB(dest, loopback_MultiTexCoord4dARB);
+ SET_MultiTexCoord4dvARB(dest, loopback_MultiTexCoord4dvARB);
+ SET_MultiTexCoord4iARB(dest, loopback_MultiTexCoord4iARB);
+ SET_MultiTexCoord4ivARB(dest, loopback_MultiTexCoord4ivARB);
+ SET_MultiTexCoord4sARB(dest, loopback_MultiTexCoord4sARB);
+ SET_MultiTexCoord4svARB(dest, loopback_MultiTexCoord4svARB);
+ SET_EvalCoord2dv(dest, loopback_EvalCoord2dv);
+ SET_EvalCoord2fv(dest, loopback_EvalCoord2fv);
+ SET_EvalCoord2d(dest, loopback_EvalCoord2d);
+ SET_EvalCoord1dv(dest, loopback_EvalCoord1dv);
+ SET_EvalCoord1fv(dest, loopback_EvalCoord1fv);
+ SET_EvalCoord1d(dest, loopback_EvalCoord1d);
+ SET_Materialf(dest, loopback_Materialf);
+ SET_Materiali(dest, loopback_Materiali);
+ SET_Materialiv(dest, loopback_Materialiv);
+ SET_Rectd(dest, loopback_Rectd);
+ SET_Rectdv(dest, loopback_Rectdv);
+ SET_Rectfv(dest, loopback_Rectfv);
+ SET_Recti(dest, loopback_Recti);
+ SET_Rectiv(dest, loopback_Rectiv);
+ SET_Rects(dest, loopback_Rects);
+ SET_Rectsv(dest, loopback_Rectsv);
+ SET_FogCoorddEXT(dest, loopback_FogCoorddEXT);
+ SET_FogCoorddvEXT(dest, loopback_FogCoorddvEXT);
+
+ SET_VertexAttrib1sNV(dest, loopback_VertexAttrib1sNV);
+ SET_VertexAttrib1dNV(dest, loopback_VertexAttrib1dNV);
+ SET_VertexAttrib2sNV(dest, loopback_VertexAttrib2sNV);
+ SET_VertexAttrib2dNV(dest, loopback_VertexAttrib2dNV);
+ SET_VertexAttrib3sNV(dest, loopback_VertexAttrib3sNV);
+ SET_VertexAttrib3dNV(dest, loopback_VertexAttrib3dNV);
+ SET_VertexAttrib4sNV(dest, loopback_VertexAttrib4sNV);
+ SET_VertexAttrib4dNV(dest, loopback_VertexAttrib4dNV);
+ SET_VertexAttrib4ubNV(dest, loopback_VertexAttrib4ubNV);
+ SET_VertexAttrib1svNV(dest, loopback_VertexAttrib1svNV);
+ SET_VertexAttrib1dvNV(dest, loopback_VertexAttrib1dvNV);
+ SET_VertexAttrib2svNV(dest, loopback_VertexAttrib2svNV);
+ SET_VertexAttrib2dvNV(dest, loopback_VertexAttrib2dvNV);
+ SET_VertexAttrib3svNV(dest, loopback_VertexAttrib3svNV);
+ SET_VertexAttrib3dvNV(dest, loopback_VertexAttrib3dvNV);
+ SET_VertexAttrib4svNV(dest, loopback_VertexAttrib4svNV);
+ SET_VertexAttrib4dvNV(dest, loopback_VertexAttrib4dvNV);
+ SET_VertexAttrib4ubvNV(dest, loopback_VertexAttrib4ubvNV);
+ SET_VertexAttribs1svNV(dest, loopback_VertexAttribs1svNV);
+ SET_VertexAttribs1fvNV(dest, loopback_VertexAttribs1fvNV);
+ SET_VertexAttribs1dvNV(dest, loopback_VertexAttribs1dvNV);
+ SET_VertexAttribs2svNV(dest, loopback_VertexAttribs2svNV);
+ SET_VertexAttribs2fvNV(dest, loopback_VertexAttribs2fvNV);
+ SET_VertexAttribs2dvNV(dest, loopback_VertexAttribs2dvNV);
+ SET_VertexAttribs3svNV(dest, loopback_VertexAttribs3svNV);
+ SET_VertexAttribs3fvNV(dest, loopback_VertexAttribs3fvNV);
+ SET_VertexAttribs3dvNV(dest, loopback_VertexAttribs3dvNV);
+ SET_VertexAttribs4svNV(dest, loopback_VertexAttribs4svNV);
+ SET_VertexAttribs4fvNV(dest, loopback_VertexAttribs4fvNV);
+ SET_VertexAttribs4dvNV(dest, loopback_VertexAttribs4dvNV);
+ SET_VertexAttribs4ubvNV(dest, loopback_VertexAttribs4ubvNV);
+
+ SET_VertexAttrib1sARB(dest, loopback_VertexAttrib1sARB);
+ SET_VertexAttrib1dARB(dest, loopback_VertexAttrib1dARB);
+ SET_VertexAttrib2sARB(dest, loopback_VertexAttrib2sARB);
+ SET_VertexAttrib2dARB(dest, loopback_VertexAttrib2dARB);
+ SET_VertexAttrib3sARB(dest, loopback_VertexAttrib3sARB);
+ SET_VertexAttrib3dARB(dest, loopback_VertexAttrib3dARB);
+ SET_VertexAttrib4sARB(dest, loopback_VertexAttrib4sARB);
+ SET_VertexAttrib4dARB(dest, loopback_VertexAttrib4dARB);
+ SET_VertexAttrib1svARB(dest, loopback_VertexAttrib1svARB);
+ SET_VertexAttrib1dvARB(dest, loopback_VertexAttrib1dvARB);
+ SET_VertexAttrib2svARB(dest, loopback_VertexAttrib2svARB);
+ SET_VertexAttrib2dvARB(dest, loopback_VertexAttrib2dvARB);
+ SET_VertexAttrib3svARB(dest, loopback_VertexAttrib3svARB);
+ SET_VertexAttrib3dvARB(dest, loopback_VertexAttrib3dvARB);
+ SET_VertexAttrib4svARB(dest, loopback_VertexAttrib4svARB);
+ SET_VertexAttrib4dvARB(dest, loopback_VertexAttrib4dvARB);
+ SET_VertexAttrib4NubARB(dest, loopback_VertexAttrib4NubARB);
+ SET_VertexAttrib4NubvARB(dest, loopback_VertexAttrib4NubvARB);
+ SET_VertexAttrib4bvARB(dest, loopback_VertexAttrib4bvARB);
+ SET_VertexAttrib4ivARB(dest, loopback_VertexAttrib4ivARB);
+ SET_VertexAttrib4ubvARB(dest, loopback_VertexAttrib4ubvARB);
+ SET_VertexAttrib4usvARB(dest, loopback_VertexAttrib4usvARB);
+ SET_VertexAttrib4uivARB(dest, loopback_VertexAttrib4uivARB);
+ SET_VertexAttrib4NbvARB(dest, loopback_VertexAttrib4NbvARB);
+ SET_VertexAttrib4NsvARB(dest, loopback_VertexAttrib4NsvARB);
+ SET_VertexAttrib4NivARB(dest, loopback_VertexAttrib4NivARB);
+ SET_VertexAttrib4NusvARB(dest, loopback_VertexAttrib4NusvARB);
+ SET_VertexAttrib4NuivARB(dest, loopback_VertexAttrib4NuivARB);
+}
diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h
new file mode 100644
index 000000000..6f85bbc1d
--- /dev/null
+++ b/mesalib/src/mesa/main/api_loopback.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef API_LOOPBACK_H
+#define API_LOOPBACK_H
+
+#include "glheader.h"
+
+
+struct _glapi_table;
+
+extern void _mesa_loopback_init_api_table( struct _glapi_table *dest );
+
+#endif
diff --git a/mesalib/src/mesa/main/api_noop.c b/mesalib/src/mesa/main/api_noop.c
new file mode 100644
index 000000000..09ba7e506
--- /dev/null
+++ b/mesalib/src/mesa/main/api_noop.c
@@ -0,0 +1,1000 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "api_noop.h"
+#include "api_validate.h"
+#include "api_arrayelt.h"
+#include "context.h"
+#include "light.h"
+#include "macros.h"
+#if FEATURE_dlist
+#include "dlist.h"
+#endif
+#include "glapi/dispatch.h"
+
+
+/**
+ * \file
+ * Just update the ctx->Current vertex attributes.
+ * These functions are used when outside glBegin/glEnd or outside display
+ * lists.
+ */
+
+
+static void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] = (GLfloat)b;
+}
+
+static void GLAPIENTRY _mesa_noop_Indexf( GLfloat f )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = f;
+}
+
+static void GLAPIENTRY _mesa_noop_Indexfv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0] = *v;
+}
+
+static void GLAPIENTRY _mesa_noop_FogCoordfEXT( GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_FOG];
+ dest[0] = a;
+ dest[1] = 0.0;
+ dest[2] = 0.0;
+ dest[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_FogCoordfvEXT( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_FOG];
+ dest[0] = v[0];
+ dest[1] = 0.0;
+ dest[2] = 0.0;
+ dest[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_Normal3f( GLfloat a, GLfloat b, GLfloat c )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = c;
+ dest[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_Normal3fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_Color4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ color[0] = a;
+ color[1] = b;
+ color[2] = c;
+ color[3] = d;
+}
+
+static void GLAPIENTRY _mesa_noop_Color4fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ color[0] = v[0];
+ color[1] = v[1];
+ color[2] = v[2];
+ color[3] = v[3];
+}
+
+static void GLAPIENTRY _mesa_noop_Color3f( GLfloat a, GLfloat b, GLfloat c )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ color[0] = a;
+ color[1] = b;
+ color[2] = c;
+ color[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_Color3fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ color[0] = v[0];
+ color[1] = v[1];
+ color[2] = v[2];
+ color[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord1fARB( GLenum target, GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = a;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = v[0];
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord2fARB( GLenum target, GLfloat a, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = 0;
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = 0;
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord3fARB( GLenum target, GLfloat a, GLfloat b, GLfloat c)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = c;
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord3fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = 1;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord4fARB( GLenum target, GLfloat a, GLfloat b,
+ GLfloat c, GLfloat d )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = c;
+ dest[3] = d;
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_MultiTexCoord4fvARB( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint unit = target - GL_TEXTURE0_ARB;
+
+ /* unit is unsigned -- cannot be less than zero.
+ */
+ if (unit < MAX_TEXTURE_COORD_UNITS)
+ {
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = v[3];
+ }
+}
+
+static void GLAPIENTRY _mesa_noop_SecondaryColor3fEXT( GLfloat a, GLfloat b, GLfloat c )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
+ color[0] = a;
+ color[1] = b;
+ color[2] = c;
+ color[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_SecondaryColor3fvEXT( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
+ color[0] = v[0];
+ color[1] = v[1];
+ color[2] = v[2];
+ color[3] = 1.0;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord1f( GLfloat a )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = a;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord1fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = v[0];
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord2f( GLfloat a, GLfloat b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = 0;
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord2fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = 0;
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord3f( GLfloat a, GLfloat b, GLfloat c )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = c;
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord3fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = 1;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = a;
+ dest[1] = b;
+ dest[2] = c;
+ dest[3] = d;
+}
+
+static void GLAPIENTRY _mesa_noop_TexCoord4fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+ dest[0] = v[0];
+ dest[1] = v[1];
+ dest[2] = v[2];
+ dest[3] = v[3];
+}
+
+
+/**
+ * GL_NV_vertex_program attributes.
+ * Note that these attributes alias the conventional vertex attributes.
+ */
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib1fNV( GLuint index, GLfloat x )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], x, 0, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib1fNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], v[0], 0, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib1fvNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], x, y, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib2fNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib2fvNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib3fNV( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib3fNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib3fvNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, w);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib4fNV(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], v[3]);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib4fvNV(index)" );
+}
+
+
+
+/**
+ * GL_ARB_vertex_program attributes.
+ * Note that these attributes DO NOT alias the conventional vertex attributes.
+ */
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib1fARB( GLuint index, GLfloat x )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, 0, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib1fARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib1fvARB( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], 0, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib1fvARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib2fARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib2fvARB( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], 0, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib2fvARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib3fARB( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, z, 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib3fARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib3fvARB( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], v[2], 1);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib3fvARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib4fARB( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], x, y, z, w);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib4fARB(index)" );
+}
+
+static void GLAPIENTRY _mesa_noop_VertexAttrib4fvARB( GLuint index, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS) {
+ ASSIGN_4V(ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index], v[0], v[1], v[2], v[3]);
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexAttrib4fvARB(index)" );
+}
+
+
+
+/**
+ * Called by glMaterial*()
+ */
+void GLAPIENTRY
+_mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i, nr;
+ struct gl_material *mat = &ctx->Light.Material;
+ GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0,
+ "_mesa_noop_Materialfv" );
+
+ if (ctx->Light.ColorMaterialEnabled)
+ bitmask &= ~ctx->Light.ColorMaterialBitmask;
+
+ if (bitmask == 0)
+ return;
+
+ switch (pname) {
+ case GL_SHININESS: nr = 1; break;
+ case GL_COLOR_INDEXES: nr = 3; break;
+ default: nr = 4 ; break;
+ }
+
+ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+ if (bitmask & (1<<i))
+ COPY_SZ_4V( mat->Attrib[i], nr, params );
+
+ _mesa_update_material( ctx, bitmask );
+}
+
+
+/**
+ * These really are noops outside begin/end:
+ */
+static void GLAPIENTRY _mesa_noop_Vertex2fv( const GLfloat *v )
+{
+ (void) v;
+}
+
+static void GLAPIENTRY _mesa_noop_Vertex3fv( const GLfloat *v )
+{
+ (void) v;
+}
+
+static void GLAPIENTRY _mesa_noop_Vertex4fv( const GLfloat *v )
+{
+ (void) v;
+}
+
+static void GLAPIENTRY _mesa_noop_Vertex2f( GLfloat a, GLfloat b )
+{
+ (void) a; (void) b;
+}
+
+static void GLAPIENTRY _mesa_noop_Vertex3f( GLfloat a, GLfloat b, GLfloat c )
+{
+ (void) a; (void) b; (void) c;
+}
+
+static void GLAPIENTRY _mesa_noop_Vertex4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d )
+{
+ (void) a; (void) b; (void) c; (void) d;
+}
+
+
+#if FEATURE_evaluators
+/* Similarly, these have no effect outside begin/end:
+ */
+static void GLAPIENTRY _mesa_noop_EvalCoord1f( GLfloat a )
+{
+ (void) a;
+}
+
+static void GLAPIENTRY _mesa_noop_EvalCoord1fv( const GLfloat *v )
+{
+ (void) v;
+}
+
+static void GLAPIENTRY _mesa_noop_EvalCoord2f( GLfloat a, GLfloat b )
+{
+ (void) a; (void) b;
+}
+
+static void GLAPIENTRY _mesa_noop_EvalCoord2fv( const GLfloat *v )
+{
+ (void) v;
+}
+
+static void GLAPIENTRY _mesa_noop_EvalPoint1( GLint a )
+{
+ (void) a;
+}
+
+static void GLAPIENTRY _mesa_noop_EvalPoint2( GLint a, GLint b )
+{
+ (void) a; (void) b;
+}
+#endif /* FEATURE_evaluators */
+
+
+/* Begin -- call into driver, should result in the vtxfmt being
+ * swapped out:
+ */
+static void GLAPIENTRY _mesa_noop_Begin( GLenum mode )
+{
+ (void) mode;
+}
+
+
+/* End -- just raise an error
+ */
+static void GLAPIENTRY _mesa_noop_End( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd(no glBegin)" );
+}
+
+
+/**
+ * Execute a glRectf() function. This is not suitable for GL_COMPILE
+ * modes (as the test for outside begin/end is not compiled),
+ * but may be useful for drivers in circumstances which exclude
+ * display list interactions.
+ *
+ * (None of the functions in this file are suitable for GL_COMPILE
+ * modes).
+ */
+void GLAPIENTRY
+_mesa_noop_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ {
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ }
+
+ CALL_Begin(GET_DISPATCH(), (GL_QUADS));
+ CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
+ CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
+ CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
+ CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+/**
+ * Some very basic support for arrays. Drivers without explicit array
+ * support can hook these in, but still need to supply an array-elt
+ * implementation.
+ */
+static void GLAPIENTRY
+_mesa_noop_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ CALL_Begin(GET_DISPATCH(), (mode));
+ for (i = 0; i < count; i++)
+ CALL_ArrayElement(GET_DISPATCH(), (start + i));
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+static void GLAPIENTRY
+_mesa_noop_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ return;
+
+ CALL_Begin(GET_DISPATCH(), (mode));
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_INT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ break;
+ }
+
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+static void GLAPIENTRY
+_mesa_noop_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (_mesa_validate_DrawRangeElements( ctx, mode,
+ start, end,
+ count, type, indices ))
+ CALL_DrawElements(GET_DISPATCH(), (mode, count, type, indices));
+}
+
+/* GL_EXT_multi_draw_arrays */
+void GLAPIENTRY
+_mesa_noop_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ GLsizei i;
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ CALL_DrawElements(GET_DISPATCH(), (mode, count[i], type, indices[i]));
+ }
+ }
+}
+
+/*
+ * Eval Mesh
+ */
+
+/**
+ * KW:
+ * If are compiling, we don't know whether eval will produce a
+ * vertex when it is run in the future. If this is pure immediate
+ * mode, eval is a noop if neither vertex map is enabled.
+ *
+ * Thus we need to have a check in the display list code or elsewhere
+ * for eval(1,2) vertices in the case where map(1,2)_vertex is
+ * disabled, and to purge those vertices from the vb.
+ */
+void GLAPIENTRY
+_mesa_noop_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ GLfloat u, du;
+ GLenum prim;
+
+ switch (mode) {
+ case GL_POINT:
+ prim = GL_POINTS;
+ break;
+ case GL_LINE:
+ prim = GL_LINE_STRIP;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
+ return;
+ }
+
+ /* No effect if vertex maps disabled.
+ */
+ if (!ctx->Eval.Map1Vertex4 &&
+ !ctx->Eval.Map1Vertex3 &&
+ !(ctx->VertexProgram._Enabled && ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]))
+ return;
+
+ du = ctx->Eval.MapGrid1du;
+ u = ctx->Eval.MapGrid1u1 + i1 * du;
+
+ CALL_Begin(GET_DISPATCH(), (prim));
+ for (i=i1;i<=i2;i++,u+=du) {
+ CALL_EvalCoord1f(GET_DISPATCH(), (u));
+ }
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+
+void GLAPIENTRY
+_mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat u, du, v, dv, v1, u1;
+ GLint i, j;
+
+ switch (mode) {
+ case GL_POINT:
+ case GL_LINE:
+ case GL_FILL:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
+ return;
+ }
+
+ /* No effect if vertex maps disabled.
+ */
+ if (!ctx->Eval.Map2Vertex4 &&
+ !ctx->Eval.Map2Vertex3 &&
+ !(ctx->VertexProgram._Enabled && ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]))
+ return;
+
+ du = ctx->Eval.MapGrid2du;
+ dv = ctx->Eval.MapGrid2dv;
+ v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
+ u1 = ctx->Eval.MapGrid2u1 + i1 * du;
+
+ switch (mode) {
+ case GL_POINT:
+ CALL_Begin(GET_DISPATCH(), (GL_POINTS));
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
+ }
+ }
+ CALL_End(GET_DISPATCH(), ());
+ break;
+ case GL_LINE:
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
+ }
+ CALL_End(GET_DISPATCH(), ());
+ }
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
+ }
+ CALL_End(GET_DISPATCH(), ());
+ }
+ break;
+ case GL_FILL:
+ for (v=v1,j=j1;j<j2;j++,v+=dv) {
+ CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
+ CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
+ }
+ CALL_End(GET_DISPATCH(), ());
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
+ return;
+ }
+}
+
+
+
+/**
+ * Build a vertexformat of functions to use outside begin/end pairs.
+ *
+ * TODO -- build a whole dispatch table for this purpose, and likewise
+ * for inside begin/end.
+ */
+void
+_mesa_noop_vtxfmt_init( GLvertexformat *vfmt )
+{
+ vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ vfmt->Begin = _mesa_noop_Begin;
+#if FEATURE_dlist
+ vfmt->CallList = _mesa_CallList;
+ vfmt->CallLists = _mesa_CallLists;
+#endif
+ vfmt->Color3f = _mesa_noop_Color3f;
+ vfmt->Color3fv = _mesa_noop_Color3fv;
+ vfmt->Color4f = _mesa_noop_Color4f;
+ vfmt->Color4fv = _mesa_noop_Color4fv;
+ vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
+ vfmt->End = _mesa_noop_End;
+#if FEATURE_evaluators
+ vfmt->EvalCoord1f = _mesa_noop_EvalCoord1f;
+ vfmt->EvalCoord1fv = _mesa_noop_EvalCoord1fv;
+ vfmt->EvalCoord2f = _mesa_noop_EvalCoord2f;
+ vfmt->EvalCoord2fv = _mesa_noop_EvalCoord2fv;
+ vfmt->EvalPoint1 = _mesa_noop_EvalPoint1;
+ vfmt->EvalPoint2 = _mesa_noop_EvalPoint2;
+#endif
+ vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
+ vfmt->Indexf = _mesa_noop_Indexf;
+ vfmt->Indexfv = _mesa_noop_Indexfv;
+ vfmt->Materialfv = _mesa_noop_Materialfv;
+ vfmt->MultiTexCoord1fARB = _mesa_noop_MultiTexCoord1fARB;
+ vfmt->MultiTexCoord1fvARB = _mesa_noop_MultiTexCoord1fvARB;
+ vfmt->MultiTexCoord2fARB = _mesa_noop_MultiTexCoord2fARB;
+ vfmt->MultiTexCoord2fvARB = _mesa_noop_MultiTexCoord2fvARB;
+ vfmt->MultiTexCoord3fARB = _mesa_noop_MultiTexCoord3fARB;
+ vfmt->MultiTexCoord3fvARB = _mesa_noop_MultiTexCoord3fvARB;
+ vfmt->MultiTexCoord4fARB = _mesa_noop_MultiTexCoord4fARB;
+ vfmt->MultiTexCoord4fvARB = _mesa_noop_MultiTexCoord4fvARB;
+ vfmt->Normal3f = _mesa_noop_Normal3f;
+ vfmt->Normal3fv = _mesa_noop_Normal3fv;
+ vfmt->SecondaryColor3fEXT = _mesa_noop_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = _mesa_noop_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = _mesa_noop_TexCoord1f;
+ vfmt->TexCoord1fv = _mesa_noop_TexCoord1fv;
+ vfmt->TexCoord2f = _mesa_noop_TexCoord2f;
+ vfmt->TexCoord2fv = _mesa_noop_TexCoord2fv;
+ vfmt->TexCoord3f = _mesa_noop_TexCoord3f;
+ vfmt->TexCoord3fv = _mesa_noop_TexCoord3fv;
+ vfmt->TexCoord4f = _mesa_noop_TexCoord4f;
+ vfmt->TexCoord4fv = _mesa_noop_TexCoord4fv;
+ vfmt->Vertex2f = _mesa_noop_Vertex2f;
+ vfmt->Vertex2fv = _mesa_noop_Vertex2fv;
+ vfmt->Vertex3f = _mesa_noop_Vertex3f;
+ vfmt->Vertex3fv = _mesa_noop_Vertex3fv;
+ vfmt->Vertex4f = _mesa_noop_Vertex4f;
+ vfmt->Vertex4fv = _mesa_noop_Vertex4fv;
+ vfmt->VertexAttrib1fNV = _mesa_noop_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = _mesa_noop_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = _mesa_noop_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = _mesa_noop_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = _mesa_noop_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = _mesa_noop_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = _mesa_noop_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = _mesa_noop_VertexAttrib4fvNV;
+ vfmt->VertexAttrib1fARB = _mesa_noop_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = _mesa_noop_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = _mesa_noop_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = _mesa_noop_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = _mesa_noop_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = _mesa_noop_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = _mesa_noop_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = _mesa_noop_VertexAttrib4fvARB;
+
+ vfmt->Rectf = _mesa_noop_Rectf;
+
+ vfmt->DrawArrays = _mesa_noop_DrawArrays;
+ vfmt->DrawElements = _mesa_noop_DrawElements;
+ vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements;
+ vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
+ vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+}
diff --git a/mesalib/src/mesa/main/api_noop.h b/mesalib/src/mesa/main/api_noop.h
new file mode 100644
index 000000000..a7956d00b
--- /dev/null
+++ b/mesalib/src/mesa/main/api_noop.h
@@ -0,0 +1,50 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 _API_NOOP_H
+#define _API_NOOP_H
+
+#include "mtypes.h"
+#include "context.h"
+
+extern void GLAPIENTRY
+_mesa_noop_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+
+extern void GLAPIENTRY
+_mesa_noop_EvalMesh1(GLenum mode, GLint i1, GLint i2);
+
+extern void GLAPIENTRY
+_mesa_noop_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+
+extern void GLAPIENTRY
+_mesa_noop_Materialfv(GLenum face, GLenum pname, const GLfloat *param);
+
+extern void GLAPIENTRY
+_mesa_noop_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount);
+
+extern void
+_mesa_noop_vtxfmt_init(GLvertexformat *vfmt);
+
+#endif
diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c
new file mode 100644
index 000000000..507e21fe8
--- /dev/null
+++ b/mesalib/src/mesa/main/api_validate.c
@@ -0,0 +1,300 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "api_validate.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+
+
+
+/**
+ * \return number of bytes in array [count] of type.
+ */
+static GLsizei
+index_bytes(GLenum type, GLsizei count)
+{
+ if (type == GL_UNSIGNED_INT) {
+ return count * sizeof(GLuint);
+ }
+ else if (type == GL_UNSIGNED_BYTE) {
+ return count * sizeof(GLubyte);
+ }
+ else {
+ ASSERT(type == GL_UNSIGNED_SHORT);
+ return count * sizeof(GLushort);
+ }
+}
+
+
+/**
+ * Find the max index in the given element/index buffer
+ */
+GLuint
+_mesa_max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
+ const void *indices,
+ struct gl_buffer_object *elementBuf)
+{
+ const GLubyte *map = NULL;
+ GLuint max = 0;
+ GLuint i;
+
+ if (_mesa_is_bufferobj(elementBuf)) {
+ /* elements are in a user-defined buffer object. need to map it */
+ map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY, elementBuf);
+ /* Actual address is the sum of pointers */
+ indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
+ }
+
+ if (type == GL_UNSIGNED_INT) {
+ for (i = 0; i < count; i++)
+ if (((GLuint *) indices)[i] > max)
+ max = ((GLuint *) indices)[i];
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ for (i = 0; i < count; i++)
+ if (((GLushort *) indices)[i] > max)
+ max = ((GLushort *) indices)[i];
+ }
+ else {
+ ASSERT(type == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++)
+ if (((GLubyte *) indices)[i] > max)
+ max = ((GLubyte *) indices)[i];
+ }
+
+ if (map) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, elementBuf);
+ }
+
+ return max;
+}
+
+
+/**
+ * Check if OK to draw arrays/elements.
+ */
+static GLboolean
+check_valid_to_render(GLcontext *ctx, const char *function)
+{
+ if (!_mesa_valid_to_render(ctx, function)) {
+ return GL_FALSE;
+ }
+
+#if FEATURE_es2_glsl
+ /* For ES2, we can draw if any vertex array is enabled (and we should
+ * always have a vertex program/shader).
+ */
+ if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current)
+ return GL_FALSE;
+#else
+ /* For regular OpenGL, only draw if we have vertex positions (regardless
+ * of whether or not we have a vertex program/shader).
+ */
+ if (!ctx->Array.ArrayObj->Vertex.Enabled &&
+ !ctx->Array.ArrayObj->VertexAttrib[0].Enabled)
+ return GL_FALSE;
+#endif
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Error checking for glDrawElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
+GLboolean
+_mesa_validate_DrawElements(GLcontext *ctx,
+ GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (count <= 0) {
+ if (count < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
+ return GL_FALSE;
+ }
+
+ if (mode > GL_POLYGON) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)" );
+ return GL_FALSE;
+ }
+
+ if (type != GL_UNSIGNED_INT &&
+ type != GL_UNSIGNED_BYTE &&
+ type != GL_UNSIGNED_SHORT)
+ {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ return GL_FALSE;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (!check_valid_to_render(ctx, "glDrawElements"))
+ return GL_FALSE;
+
+ /* Vertex buffer object tests */
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ /* use indices in the buffer object */
+ /* make sure count doesn't go outside buffer bounds */
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
+ _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
+ return GL_FALSE;
+ }
+ }
+ else {
+ /* not using a VBO */
+ if (!indices)
+ return GL_FALSE;
+ }
+
+ if (ctx->Const.CheckArrayBounds) {
+ /* find max array index */
+ GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
+ ctx->Array.ElementArrayBufferObj);
+ if (max >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ _mesa_warning(ctx, "glDrawElements() index=%u is "
+ "out of bounds (max=%u)", max, ctx->Array.ArrayObj->_MaxElement);
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Error checking for glDrawRangeElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
+GLboolean
+_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (count <= 0) {
+ if (count < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
+ return GL_FALSE;
+ }
+
+ if (mode > GL_POLYGON) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" );
+ return GL_FALSE;
+ }
+
+ if (end < start) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
+ return GL_FALSE;
+ }
+
+ if (type != GL_UNSIGNED_INT &&
+ type != GL_UNSIGNED_BYTE &&
+ type != GL_UNSIGNED_SHORT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" );
+ return GL_FALSE;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (!check_valid_to_render(ctx, "glDrawRangeElements"))
+ return GL_FALSE;
+
+ /* Vertex buffer object tests */
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ /* use indices in the buffer object */
+ /* make sure count doesn't go outside buffer bounds */
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
+ _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
+ return GL_FALSE;
+ }
+ }
+ else {
+ /* not using a VBO */
+ if (!indices)
+ return GL_FALSE;
+ }
+
+ if (ctx->Const.CheckArrayBounds) {
+ GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
+ ctx->Array.ElementArrayBufferObj);
+ if (max >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called from the tnl module to error check the function parameters and
+ * verify that we really can draw something.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
+GLboolean
+_mesa_validate_DrawArrays(GLcontext *ctx,
+ GLenum mode, GLint start, GLsizei count)
+{
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (count <= 0) {
+ if (count < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
+ return GL_FALSE;
+ }
+
+ if (mode > GL_POLYGON) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
+ return GL_FALSE;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (!check_valid_to_render(ctx, "glDrawArrays"))
+ return GL_FALSE;
+
+ if (ctx->Const.CheckArrayBounds) {
+ if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/api_validate.h b/mesalib/src/mesa/main/api_validate.h
new file mode 100644
index 000000000..ff82a2966
--- /dev/null
+++ b/mesalib/src/mesa/main/api_validate.h
@@ -0,0 +1,55 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef API_VALIDATE_H
+#define API_VALIDATE_H
+
+
+#include "mtypes.h"
+
+
+extern GLuint
+_mesa_max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
+ const void *indices,
+ struct gl_buffer_object *elementBuf);
+
+extern GLboolean
+_mesa_validate_DrawArrays(GLcontext *ctx,
+ GLenum mode, GLint start, GLsizei count);
+
+extern GLboolean
+_mesa_validate_DrawElements(GLcontext *ctx,
+ GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices);
+
+extern GLboolean
+_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c
new file mode 100644
index 000000000..fd35d4e38
--- /dev/null
+++ b/mesalib/src/mesa/main/arrayobj.c
@@ -0,0 +1,572 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2006
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 OR IBM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/**
+ * \file arrayobj.c
+ * Functions for the GL_APPLE_vertex_array_object extension.
+ *
+ * \todo
+ * The code in this file borrows a lot from bufferobj.c. There's a certain
+ * amount of cruft left over from that origin that may be unnecessary.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "hash.h"
+#include "imports.h"
+#include "context.h"
+#if FEATURE_ARB_vertex_buffer_object
+#include "bufferobj.h"
+#endif
+#include "arrayobj.h"
+#include "macros.h"
+#include "glapi/dispatch.h"
+
+
+/**
+ * Look up the array object for the given ID.
+ *
+ * \returns
+ * Either a pointer to the array object with the specified ID or \c NULL for
+ * a non-existent ID. The spec defines ID 0 as being technically
+ * non-existent.
+ */
+
+static INLINE struct gl_array_object *
+lookup_arrayobj(GLcontext *ctx, GLuint id)
+{
+ if (id == 0)
+ return NULL;
+ else
+ return (struct gl_array_object *)
+ _mesa_HashLookup(ctx->Array.Objects, id);
+}
+
+
+/**
+ * For all the vertex arrays in the array object, unbind any pointers
+ * to any buffer objects (VBOs).
+ * This is done just prior to array object destruction.
+ */
+static void
+unbind_array_object_vbos(GLcontext *ctx, struct gl_array_object *obj)
+{
+ GLuint i;
+
+ _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Weight.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Normal.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Color.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->SecondaryColor.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->FogCoord.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Index.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->EdgeFlag.BufferObj, NULL);
+
+ for (i = 0; i < Elements(obj->TexCoord); i++)
+ _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL);
+
+ for (i = 0; i < Elements(obj->VertexAttrib); i++)
+ _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL);
+}
+
+
+/**
+ * Allocate and initialize a new vertex array object.
+ *
+ * This function is intended to be called via
+ * \c dd_function_table::NewArrayObject.
+ */
+struct gl_array_object *
+_mesa_new_array_object( GLcontext *ctx, GLuint name )
+{
+ struct gl_array_object *obj = CALLOC_STRUCT(gl_array_object);
+ if (obj)
+ _mesa_initialize_array_object(ctx, obj, name);
+ return obj;
+}
+
+
+/**
+ * Delete an array object.
+ *
+ * This function is intended to be called via
+ * \c dd_function_table::DeleteArrayObject.
+ */
+void
+_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj )
+{
+ (void) ctx;
+ unbind_array_object_vbos(ctx, obj);
+ _glthread_DESTROY_MUTEX(obj->Mutex);
+ _mesa_free(obj);
+}
+
+
+/**
+ * Set ptr to arrayObj w/ reference counting.
+ */
+void
+_mesa_reference_array_object(GLcontext *ctx,
+ struct gl_array_object **ptr,
+ struct gl_array_object *arrayObj)
+{
+ if (*ptr == arrayObj)
+ return;
+
+ if (*ptr) {
+ /* Unreference the old array object */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_array_object *oldObj = *ptr;
+
+ _glthread_LOCK_MUTEX(oldObj->Mutex);
+ ASSERT(oldObj->RefCount > 0);
+ oldObj->RefCount--;
+#if 0
+ printf("ArrayObj %p %d DECR to %d\n",
+ (void *) oldObj, oldObj->Name, oldObj->RefCount);
+#endif
+ deleteFlag = (oldObj->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldObj->Mutex);
+
+ if (deleteFlag) {
+ ASSERT(ctx->Driver.DeleteArrayObject);
+ ctx->Driver.DeleteArrayObject(ctx, oldObj);
+ }
+
+ *ptr = NULL;
+ }
+ ASSERT(!*ptr);
+
+ if (arrayObj) {
+ /* reference new array object */
+ _glthread_LOCK_MUTEX(arrayObj->Mutex);
+ if (arrayObj->RefCount == 0) {
+ /* this array's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted array object");
+ *ptr = NULL;
+ }
+ else {
+ arrayObj->RefCount++;
+#if 0
+ printf("ArrayObj %p %d INCR to %d\n",
+ (void *) arrayObj, arrayObj->Name, arrayObj->RefCount);
+#endif
+ *ptr = arrayObj;
+ }
+ _glthread_UNLOCK_MUTEX(arrayObj->Mutex);
+ }
+}
+
+
+
+static void
+init_array(GLcontext *ctx,
+ struct gl_client_array *array, GLint size, GLint type)
+{
+ array->Size = size;
+ array->Type = type;
+ array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
+ array->Stride = 0;
+ array->StrideB = 0;
+ array->Ptr = NULL;
+ array->Enabled = GL_FALSE;
+ array->Normalized = GL_FALSE;
+#if FEATURE_ARB_vertex_buffer_object
+ /* Vertex array buffers */
+ _mesa_reference_buffer_object(ctx, &array->BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+}
+
+
+/**
+ * Initialize a gl_array_object's arrays.
+ */
+void
+_mesa_initialize_array_object( GLcontext *ctx,
+ struct gl_array_object *obj,
+ GLuint name )
+{
+ GLuint i;
+
+ obj->Name = name;
+
+ _glthread_INIT_MUTEX(obj->Mutex);
+ obj->RefCount = 1;
+
+ /* Init the individual arrays */
+ init_array(ctx, &obj->Vertex, 4, GL_FLOAT);
+ init_array(ctx, &obj->Weight, 1, GL_FLOAT);
+ init_array(ctx, &obj->Normal, 3, GL_FLOAT);
+ init_array(ctx, &obj->Color, 4, GL_FLOAT);
+ init_array(ctx, &obj->SecondaryColor, 4, GL_FLOAT);
+ init_array(ctx, &obj->FogCoord, 1, GL_FLOAT);
+ init_array(ctx, &obj->Index, 1, GL_FLOAT);
+ for (i = 0; i < Elements(obj->TexCoord); i++) {
+ init_array(ctx, &obj->TexCoord[i], 4, GL_FLOAT);
+ }
+ init_array(ctx, &obj->EdgeFlag, 1, GL_BOOL);
+ for (i = 0; i < Elements(obj->VertexAttrib); i++) {
+ init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT);
+ }
+
+#if FEATURE_point_size_array
+ init_array(ctx, &obj->PointSize, 1, GL_FLOAT);
+#endif
+}
+
+
+/**
+ * Add the given array object to the array object pool.
+ */
+static void
+save_array_object( GLcontext *ctx, struct gl_array_object *obj )
+{
+ if (obj->Name > 0) {
+ /* insert into hash table */
+ _mesa_HashInsert(ctx->Array.Objects, obj->Name, obj);
+ }
+}
+
+
+/**
+ * Remove the given array object from the array object pool.
+ * Do not deallocate the array object though.
+ */
+static void
+remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
+{
+ if (obj->Name > 0) {
+ /* remove from hash table */
+ _mesa_HashRemove(ctx->Array.Objects, obj->Name);
+ }
+}
+
+
+
+/**
+ * Compute the index of the last array element that can be safely accessed
+ * in a vertex array. We can really only do this when the array lives in
+ * a VBO.
+ * The array->_MaxElement field will be updated.
+ * Later in glDrawArrays/Elements/etc we can do some bounds checking.
+ */
+static void
+compute_max_element(struct gl_client_array *array)
+{
+ if (array->BufferObj->Name) {
+ /* Compute the max element we can access in the VBO without going
+ * out of bounds.
+ */
+ array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size
+ - (GLsizeiptrARB) array->Ptr + array->StrideB
+ - array->_ElementSize) / array->StrideB;
+ if (0)
+ _mesa_printf("%s Object %u Size %u MaxElement %u\n",
+ __FUNCTION__,
+ array->BufferObj->Name,
+ (GLuint) array->BufferObj->Size,
+ array->_MaxElement);
+ }
+ else {
+ /* user-space array, no idea how big it is */
+ array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
+ }
+}
+
+
+/**
+ * Helper for update_arrays().
+ * \return min(current min, array->_MaxElement).
+ */
+static GLuint
+update_min(GLuint min, struct gl_client_array *array)
+{
+ compute_max_element(array);
+ if (array->Enabled)
+ return MIN2(min, array->_MaxElement);
+ else
+ return min;
+}
+
+
+/**
+ * Examine vertex arrays to update the gl_array_object::_MaxElement field.
+ */
+void
+_mesa_update_array_object_max_element(GLcontext *ctx,
+ struct gl_array_object *arrayObj)
+{
+ GLuint i, min = ~0;
+
+ min = update_min(min, &arrayObj->Vertex);
+ min = update_min(min, &arrayObj->Weight);
+ min = update_min(min, &arrayObj->Normal);
+ min = update_min(min, &arrayObj->Color);
+ min = update_min(min, &arrayObj->SecondaryColor);
+ min = update_min(min, &arrayObj->FogCoord);
+ min = update_min(min, &arrayObj->Index);
+ min = update_min(min, &arrayObj->EdgeFlag);
+#if FEATURE_point_size_array
+ min = update_min(min, &arrayObj->PointSize);
+#endif
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
+ min = update_min(min, &arrayObj->TexCoord[i]);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
+
+ /* _MaxElement is one past the last legal array element */
+ arrayObj->_MaxElement = min;
+}
+
+
+/**********************************************************************/
+/* API Functions */
+/**********************************************************************/
+
+
+/**
+ * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE().
+ * \param genRequired specifies behavour when id was not generated with
+ * glGenVertexArrays().
+ */
+static void
+bind_vertex_array(GLcontext *ctx, GLuint id, GLboolean genRequired)
+{
+ struct gl_array_object * const oldObj = ctx->Array.ArrayObj;
+ struct gl_array_object *newObj = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ ASSERT(oldObj != NULL);
+
+ if ( oldObj->Name == id )
+ return; /* rebinding the same array object- no change */
+
+ /*
+ * Get pointer to new array object (newObj)
+ */
+ if (id == 0) {
+ /* The spec says there is no array object named 0, but we use
+ * one internally because it simplifies things.
+ */
+ newObj = ctx->Array.DefaultArrayObj;
+ }
+ else {
+ /* non-default array object */
+ newObj = lookup_arrayobj(ctx, id);
+ if (!newObj) {
+ if (genRequired) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)");
+ return;
+ }
+
+ /* For APPLE version, generate a new array object now */
+ newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
+ if (!newObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
+ return;
+ }
+ save_array_object(ctx, newObj);
+ }
+ }
+
+ ctx->NewState |= _NEW_ARRAY;
+ ctx->Array.NewState |= _NEW_ARRAY_ALL;
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj);
+
+ /* Pass BindVertexArray call to device driver */
+ if (ctx->Driver.BindArrayObject && newObj)
+ ctx->Driver.BindArrayObject(ctx, newObj);
+}
+
+
+/**
+ * ARB version of glBindVertexArray()
+ * This function behaves differently from glBindVertexArrayAPPLE() in
+ * that this function requires all ids to have been previously generated
+ * by glGenVertexArrays[APPLE]().
+ */
+void GLAPIENTRY
+_mesa_BindVertexArray( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_TRUE);
+}
+
+
+/**
+ * Bind a new array.
+ *
+ * \todo
+ * The binding could be done more efficiently by comparing the non-NULL
+ * pointers in the old and new objects. The only arrays that are "dirty" are
+ * the ones that are non-NULL in either object.
+ */
+void GLAPIENTRY
+_mesa_BindVertexArrayAPPLE( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_FALSE);
+}
+
+
+/**
+ * Delete a set of array objects.
+ *
+ * \param n Number of array objects to delete.
+ * \param ids Array of \c n array object IDs.
+ */
+void GLAPIENTRY
+_mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArrayAPPLE(n)");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]);
+
+ if ( obj != NULL ) {
+ ASSERT( obj->Name == ids[i] );
+
+ /* If the array object is currently bound, the spec says "the binding
+ * for that object reverts to zero and the default vertex array
+ * becomes current."
+ */
+ if ( obj == ctx->Array.ArrayObj ) {
+ CALL_BindVertexArrayAPPLE( ctx->Exec, (0) );
+ }
+
+ /* The ID is immediately freed for re-use */
+ remove_array_object(ctx, obj);
+
+ /* Unreference the array object.
+ * If refcount hits zero, the object will be deleted.
+ */
+ _mesa_reference_array_object(ctx, &obj, NULL);
+ }
+ }
+}
+
+
+/**
+ * Generate a set of unique array object IDs and store them in \c arrays.
+ * Helper for _mesa_GenVertexArrays[APPLE]() functions below.
+ * \param n Number of IDs to generate.
+ * \param arrays Array of \c n locations to store the IDs.
+ * \param vboOnly Will arrays have to reside in VBOs?
+ */
+static void
+gen_vertex_arrays(GLcontext *ctx, GLsizei n, GLuint *arrays, GLboolean vboOnly)
+{
+ GLuint first;
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE");
+ return;
+ }
+
+ if (!arrays) {
+ return;
+ }
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
+
+ /* Allocate new, empty array objects and return identifiers */
+ for (i = 0; i < n; i++) {
+ struct gl_array_object *obj;
+ GLuint name = first + i;
+
+ obj = (*ctx->Driver.NewArrayObject)( ctx, name );
+ if (!obj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE");
+ return;
+ }
+ obj->VBOonly = vboOnly;
+ save_array_object(ctx, obj);
+ arrays[i] = first + i;
+ }
+}
+
+
+/**
+ * ARB version of glGenVertexArrays()
+ * All arrays will be required to live in VBOs.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_TRUE);
+}
+
+
+/**
+ * APPLE version of glGenVertexArraysAPPLE()
+ * Arrays may live in VBOs or ordinary memory.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_FALSE);
+}
+
+
+/**
+ * Determine if ID is the name of an array object.
+ *
+ * \param id ID of the potential array object.
+ * \return \c GL_TRUE if \c id is the name of a array object,
+ * \c GL_FALSE otherwise.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsVertexArrayAPPLE( GLuint id )
+{
+ struct gl_array_object * obj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (id == 0)
+ return GL_FALSE;
+
+ obj = lookup_arrayobj(ctx, id);
+
+ return (obj != NULL) ? GL_TRUE : GL_FALSE;
+}
diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h
new file mode 100644
index 000000000..8999edc72
--- /dev/null
+++ b/mesalib/src/mesa/main/arrayobj.h
@@ -0,0 +1,83 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2006
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 OR IBM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION 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 ARRAYOBJ_H
+#define ARRAYOBJ_H
+
+#include "context.h"
+
+/**
+ * \file arrayobj.h
+ * Functions for the GL_APPLE_vertex_array_object extension.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Brian Paul
+ */
+
+/*
+ * Internal functions
+ */
+
+extern struct gl_array_object *
+_mesa_new_array_object( GLcontext *ctx, GLuint name );
+
+extern void
+_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj );
+
+extern void
+_mesa_reference_array_object(GLcontext *ctx,
+ struct gl_array_object **ptr,
+ struct gl_array_object *arrayObj);
+
+extern void
+_mesa_initialize_array_object( GLcontext *ctx,
+ struct gl_array_object *obj, GLuint name );
+
+
+extern void
+_mesa_update_array_object_max_element(GLcontext *ctx,
+ struct gl_array_object *arrayObj);
+
+
+/*
+ * API functions
+ */
+
+
+void GLAPIENTRY _mesa_BindVertexArray( GLuint id );
+
+void GLAPIENTRY _mesa_BindVertexArrayAPPLE( GLuint id );
+
+void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids);
+
+void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays);
+
+void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer);
+
+GLboolean GLAPIENTRY _mesa_IsVertexArrayAPPLE( GLuint id );
+
+#endif /* ARRAYOBJ_H */
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
new file mode 100644
index 000000000..ab99ca1c6
--- /dev/null
+++ b/mesalib/src/mesa/main/attrib.c
@@ -0,0 +1,1501 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "glheader.h"
+#include "imports.h"
+#include "accum.h"
+#include "arrayobj.h"
+#include "attrib.h"
+#include "blend.h"
+#include "buffers.h"
+#include "bufferobj.h"
+#include "clear.h"
+#include "colormac.h"
+#include "colortab.h"
+#include "context.h"
+#include "depth.h"
+#include "enable.h"
+#include "enums.h"
+#include "fog.h"
+#include "hint.h"
+#include "light.h"
+#include "lines.h"
+#include "matrix.h"
+#include "multisample.h"
+#include "points.h"
+#include "polygon.h"
+#include "scissor.h"
+#include "simple_list.h"
+#include "stencil.h"
+#include "texenv.h"
+#include "texgen.h"
+#include "texobj.h"
+#include "texparam.h"
+#include "texstate.h"
+#include "varray.h"
+#include "viewport.h"
+#include "mtypes.h"
+
+
+/**
+ * glEnable()/glDisable() attribute group (GL_ENABLE_BIT).
+ */
+struct gl_enable_attrib
+{
+ GLboolean AlphaTest;
+ GLboolean AutoNormal;
+ GLboolean Blend;
+ GLbitfield ClipPlanes;
+ GLboolean ColorMaterial;
+ GLboolean ColorTable[COLORTABLE_MAX];
+ GLboolean Convolution1D;
+ GLboolean Convolution2D;
+ GLboolean Separable2D;
+ GLboolean CullFace;
+ GLboolean DepthTest;
+ GLboolean Dither;
+ GLboolean Fog;
+ GLboolean Histogram;
+ GLboolean Light[MAX_LIGHTS];
+ GLboolean Lighting;
+ GLboolean LineSmooth;
+ GLboolean LineStipple;
+ GLboolean IndexLogicOp;
+ GLboolean ColorLogicOp;
+
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+
+ GLboolean MinMax;
+ GLboolean Normalize;
+ GLboolean PixelTexture;
+ GLboolean PointSmooth;
+ GLboolean PolygonOffsetPoint;
+ GLboolean PolygonOffsetLine;
+ GLboolean PolygonOffsetFill;
+ GLboolean PolygonSmooth;
+ GLboolean PolygonStipple;
+ GLboolean RescaleNormals;
+ GLboolean Scissor;
+ GLboolean Stencil;
+ GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */
+ GLboolean MultisampleEnabled; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */
+ GLboolean SampleAlphaToOne; /* GL_ARB_multisample */
+ GLboolean SampleCoverage; /* GL_ARB_multisample */
+ GLboolean SampleCoverageInvert; /* GL_ARB_multisample */
+ GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */
+
+ GLbitfield Texture[MAX_TEXTURE_UNITS];
+ GLbitfield TexGen[MAX_TEXTURE_UNITS];
+
+ /* SGI_texture_color_table */
+ GLboolean TextureColorTable[MAX_TEXTURE_UNITS];
+
+ /* GL_ARB_vertex_program / GL_NV_vertex_program */
+ GLboolean VertexProgram;
+ GLboolean VertexProgramPointSize;
+ GLboolean VertexProgramTwoSide;
+
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ GLboolean PointSprite;
+ GLboolean FragmentShaderATI;
+};
+
+
+/**
+ * Node for the attribute stack.
+ */
+struct gl_attrib_node
+{
+ GLbitfield kind;
+ void *data;
+ struct gl_attrib_node *next;
+};
+
+
+
+/**
+ * Special struct for saving/restoring texture state (GL_TEXTURE_BIT)
+ */
+struct texture_state
+{
+ struct gl_texture_attrib Texture; /**< The usual context state */
+
+ /** to save per texture object state (wrap modes, filters, etc): */
+ struct gl_texture_object SavedObj[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
+
+ /**
+ * To save references to texture objects (so they don't get accidentally
+ * deleted while saved in the attribute stack).
+ */
+ struct gl_texture_object *SavedTexRef[MAX_TEXTURE_UNITS][NUM_TEXTURE_TARGETS];
+};
+
+
+/**
+ * Allocate new attribute node of given type/kind. Attach payload data.
+ * Insert it into the linked list named by 'head'.
+ */
+static void
+save_attrib_data(struct gl_attrib_node **head,
+ GLbitfield kind, void *payload)
+{
+ struct gl_attrib_node *n = MALLOC_STRUCT(gl_attrib_node);
+ if (n) {
+ n->kind = kind;
+ n->data = payload;
+ /* insert at head */
+ n->next = *head;
+ *head = n;
+ }
+ else {
+ /* out of memory! */
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_PushAttrib(GLbitfield mask)
+{
+ struct gl_attrib_node *head;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask);
+
+ if (ctx->AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH) {
+ _mesa_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) );
+ save_attrib_data(&head, GL_ACCUM_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ GLuint i;
+ struct gl_colorbuffer_attrib *attr;
+ attr = MALLOC_STRUCT( gl_colorbuffer_attrib );
+ MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) );
+ /* push the Draw FBO's DrawBuffer[] state, not ctx->Color.DrawBuffer[] */
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i ++)
+ attr->DrawBuffer[i] = ctx->DrawBuffer->ColorDrawBuffer[i];
+ save_attrib_data(&head, GL_COLOR_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_CURRENT_BIT) {
+ struct gl_current_attrib *attr;
+ FLUSH_CURRENT( ctx, 0 );
+ attr = MALLOC_STRUCT( gl_current_attrib );
+ MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) );
+ save_attrib_data(&head, GL_CURRENT_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_DEPTH_BUFFER_BIT, attr);
+ }
+
+ 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;
+ attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled;
+ attr->ColorMaterial = ctx->Light.ColorMaterialEnabled;
+ for (i = 0; i < COLORTABLE_MAX; i++) {
+ attr->ColorTable[i] = ctx->Pixel.ColorTableEnabled[i];
+ }
+ attr->Convolution1D = ctx->Pixel.Convolution1DEnabled;
+ attr->Convolution2D = ctx->Pixel.Convolution2DEnabled;
+ attr->Separable2D = ctx->Pixel.Separable2DEnabled;
+ attr->CullFace = ctx->Polygon.CullFlag;
+ attr->DepthTest = ctx->Depth.Test;
+ attr->Dither = ctx->Color.DitherFlag;
+ attr->Fog = ctx->Fog.Enabled;
+ for (i = 0; i < ctx->Const.MaxLights; 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->Histogram = ctx->Pixel.HistogramEnabled;
+ attr->MinMax = ctx->Pixel.MinMaxEnabled;
+ 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;
+ MEMCPY(attr->Map1Attrib, ctx->Eval.Map1Attrib, sizeof(ctx->Eval.Map1Attrib));
+ 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;
+ MEMCPY(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib));
+ attr->Normalize = ctx->Transform.Normalize;
+ attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped;
+ attr->PointSmooth = ctx->Point.SmoothFlag;
+ attr->PointSprite = ctx->Point.PointSprite;
+ 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->StencilTwoSide = ctx->Stencil.TestTwoSide;
+ attr->MultisampleEnabled = ctx->Multisample.Enabled;
+ attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage;
+ attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne;
+ attr->SampleCoverage = ctx->Multisample.SampleCoverage;
+ attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ attr->Texture[i] = ctx->Texture.Unit[i].Enabled;
+ attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
+ attr->TextureColorTable[i] = ctx->Texture.Unit[i].ColorTableEnabled;
+ }
+ /* GL_NV_vertex_program */
+ attr->VertexProgram = ctx->VertexProgram.Enabled;
+ attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled;
+ attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled;
+ save_attrib_data(&head, GL_ENABLE_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_EVAL_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_FOG_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_HINT_BIT, attr);
+ }
+
+ if (mask & GL_LIGHTING_BIT) {
+ struct gl_light_attrib *attr;
+ FLUSH_CURRENT(ctx, 0); /* flush material changes */
+ attr = MALLOC_STRUCT( gl_light_attrib );
+ MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) );
+ save_attrib_data(&head, GL_LIGHTING_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_LINE_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_LIST_BIT, attr);
+ }
+
+ 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) );
+ /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */
+ attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
+ save_attrib_data(&head, GL_PIXEL_MODE_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_POINT_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_POLYGON_BIT, attr);
+ }
+
+ if (mask & GL_POLYGON_STIPPLE_BIT) {
+ GLuint *stipple;
+ stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) );
+ MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
+ save_attrib_data(&head, GL_POLYGON_STIPPLE_BIT, stipple);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_SCISSOR_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_STENCIL_BUFFER_BIT, attr);
+ }
+
+ if (mask & GL_TEXTURE_BIT) {
+ struct texture_state *texstate = CALLOC_STRUCT(texture_state);
+ GLuint u, tex;
+
+ if (!texstate) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
+ goto end;
+ }
+
+ _mesa_lock_context_textures(ctx);
+
+ /* copy/save the bulk of texture state here */
+ _mesa_memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture));
+
+ /* Save references to the currently bound texture objects so they don't
+ * accidentally get deleted while referenced in the attribute stack.
+ */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
+ }
+
+ /* copy state/contents of the currently bound texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_copy_texture_object(&texstate->SavedObj[u][tex],
+ ctx->Texture.Unit[u].CurrentTex[tex]);
+ }
+ }
+
+ _mesa_unlock_context_textures(ctx);
+
+ save_attrib_data(&head, GL_TEXTURE_BIT, texstate);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_TRANSFORM_BIT, attr);
+ }
+
+ 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) );
+ save_attrib_data(&head, GL_VIEWPORT_BIT, attr);
+ }
+
+ /* GL_ARB_multisample */
+ if (mask & GL_MULTISAMPLE_BIT_ARB) {
+ struct gl_multisample_attrib *attr;
+ attr = MALLOC_STRUCT( gl_multisample_attrib );
+ MEMCPY( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) );
+ save_attrib_data(&head, GL_MULTISAMPLE_BIT_ARB, attr);
+ }
+
+end:
+ ctx->AttribStack[ctx->AttribStackDepth] = head;
+ ctx->AttribStackDepth++;
+}
+
+
+
+static void
+pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
+{
+ const GLuint curTexUnitSave = ctx->Texture.CurrentUnit;
+ GLuint i;
+
+#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \
+ if ((VALUE) != (NEWVALUE)) { \
+ _mesa_set_enable( ctx, ENUM, (NEWVALUE) ); \
+ }
+
+ TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST);
+ TEST_AND_UPDATE(ctx->Color.BlendEnabled, enable->Blend, GL_BLEND);
+
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ const GLuint mask = 1 << i;
+ if ((ctx->Transform.ClipPlanesEnabled & mask) != (enable->ClipPlanes & mask))
+ _mesa_set_enable(ctx, (GLenum) (GL_CLIP_PLANE0 + i),
+ (GLboolean) ((enable->ClipPlanes & mask) ? GL_TRUE : GL_FALSE));
+ }
+
+ TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial,
+ GL_COLOR_MATERIAL);
+ TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION],
+ enable->ColorTable[COLORTABLE_PRECONVOLUTION],
+ GL_COLOR_TABLE);
+ TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION],
+ enable->ColorTable[COLORTABLE_POSTCONVOLUTION],
+ GL_POST_CONVOLUTION_COLOR_TABLE);
+ TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX],
+ enable->ColorTable[COLORTABLE_POSTCOLORMATRIX],
+ GL_POST_COLOR_MATRIX_COLOR_TABLE);
+ TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE);
+ TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST);
+ TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER);
+ TEST_AND_UPDATE(ctx->Pixel.Convolution1DEnabled, enable->Convolution1D,
+ GL_CONVOLUTION_1D);
+ TEST_AND_UPDATE(ctx->Pixel.Convolution2DEnabled, enable->Convolution2D,
+ GL_CONVOLUTION_2D);
+ TEST_AND_UPDATE(ctx->Pixel.Separable2DEnabled, enable->Separable2D,
+ GL_SEPARABLE_2D);
+ 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);
+ for (i = 0; i < 16; i++) {
+ TEST_AND_UPDATE(ctx->Eval.Map1Attrib[i], enable->Map1Attrib[i],
+ GL_MAP1_VERTEX_ATTRIB0_4_NV + i);
+ }
+
+ 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);
+ for (i = 0; i < 16; i++) {
+ TEST_AND_UPDATE(ctx->Eval.Map2Attrib[i], enable->Map2Attrib[i],
+ GL_MAP2_VERTEX_ATTRIB0_4_NV + i);
+ }
+
+ TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL);
+ 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->Transform.RasterPositionUnclipped,
+ enable->RasterPositionUnclipped,
+ GL_RASTER_POSITION_UNCLIPPED_IBM);
+ TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth,
+ GL_POINT_SMOOTH);
+ if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) {
+ TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite,
+ GL_POINT_SPRITE_NV);
+ }
+ 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->Extensions.EXT_stencil_two_side) {
+ TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT);
+ }
+ TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled,
+ GL_MULTISAMPLE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage,
+ enable->SampleAlphaToCoverage,
+ GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne,
+ enable->SampleAlphaToOne,
+ GL_SAMPLE_ALPHA_TO_ONE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleCoverage,
+ enable->SampleCoverage,
+ GL_SAMPLE_COVERAGE_ARB);
+ TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert,
+ enable->SampleCoverageInvert,
+ GL_SAMPLE_COVERAGE_INVERT_ARB);
+ /* GL_ARB_vertex_program, GL_NV_vertex_program */
+ TEST_AND_UPDATE(ctx->VertexProgram.Enabled,
+ enable->VertexProgram,
+ GL_VERTEX_PROGRAM_ARB);
+ TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled,
+ enable->VertexProgramPointSize,
+ GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
+ TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled,
+ enable->VertexProgramTwoSide,
+ GL_VERTEX_PROGRAM_TWO_SIDE_ARB);
+
+#undef TEST_AND_UPDATE
+
+ /* texture unit enables */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ const GLbitfield enabled = enable->Texture[i];
+ const GLbitfield genEnabled = enable->TexGen[i];
+
+ if (ctx->Texture.Unit[i].Enabled != enabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+
+ _mesa_set_enable(ctx, GL_TEXTURE_1D,
+ (enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D,
+ (enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D,
+ (enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
+ if (ctx->Extensions.NV_texture_rectangle) {
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_ARB,
+ (enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP,
+ (enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ }
+
+ if (ctx->Texture.Unit[i].TexGenEnabled != genEnabled) {
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + i);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
+ (genEnabled & S_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
+ (genEnabled & T_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
+ (genEnabled & R_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
+ (genEnabled & Q_BIT) ? GL_TRUE : GL_FALSE);
+ }
+
+ /* GL_SGI_texture_color_table */
+ ctx->Texture.Unit[i].ColorTableEnabled = enable->TextureColorTable[i];
+ }
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0 + curTexUnitSave);
+}
+
+
+/**
+ * Pop/restore texture attribute/group state.
+ */
+static void
+pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
+{
+ GLuint u;
+
+ _mesa_lock_context_textures(ctx);
+
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
+ GLuint tgt;
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
+ _mesa_set_enable(ctx, GL_TEXTURE_1D,
+ (unit->Enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D,
+ (unit->Enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_3D,
+ (unit->Enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE);
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB,
+ (unit->Enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.NV_texture_rectangle) {
+ _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV,
+ (unit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE);
+ }
+ if (ctx->Extensions.MESA_texture_array) {
+ _mesa_set_enable(ctx, GL_TEXTURE_1D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_1D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ _mesa_set_enable(ctx, GL_TEXTURE_2D_ARRAY_EXT,
+ (unit->Enabled & TEXTURE_2D_ARRAY_BIT) ? GL_TRUE : GL_FALSE);
+ }
+
+ if (ctx->Extensions.SGI_texture_color_table) {
+ _mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI,
+ unit->ColorTableEnabled);
+ }
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode);
+ _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor);
+ _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenS.Mode);
+ _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenT.Mode);
+ _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenR.Mode);
+ _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenQ.Mode);
+ _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->GenS.ObjectPlane);
+ _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->GenT.ObjectPlane);
+ _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->GenR.ObjectPlane);
+ _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->GenQ.ObjectPlane);
+ /* Eye plane done differently to avoid re-transformation */
+ {
+ struct gl_texture_unit *destUnit = &ctx->Texture.Unit[u];
+ COPY_4FV(destUnit->GenS.EyePlane, unit->GenS.EyePlane);
+ COPY_4FV(destUnit->GenT.EyePlane, unit->GenT.EyePlane);
+ COPY_4FV(destUnit->GenR.EyePlane, unit->GenR.EyePlane);
+ COPY_4FV(destUnit->GenQ.EyePlane, unit->GenQ.EyePlane);
+ if (ctx->Driver.TexGen) {
+ ctx->Driver.TexGen(ctx, GL_S, GL_EYE_PLANE, unit->GenS.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_T, GL_EYE_PLANE, unit->GenT.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_R, GL_EYE_PLANE, unit->GenR.EyePlane);
+ ctx->Driver.TexGen(ctx, GL_Q, GL_EYE_PLANE, unit->GenQ.EyePlane);
+ }
+ }
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_S,
+ ((unit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_T,
+ ((unit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_R,
+ ((unit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE));
+ _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q,
+ ((unit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE));
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
+ GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias);
+ }
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB,
+ unit->Combine.ModeRGB);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA,
+ unit->Combine.ModeA);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB,
+ unit->Combine.SourceRGB[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB,
+ unit->Combine.SourceRGB[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB,
+ unit->Combine.SourceRGB[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA,
+ unit->Combine.SourceA[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA,
+ unit->Combine.SourceA[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA,
+ unit->Combine.SourceA[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
+ unit->Combine.OperandRGB[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB,
+ unit->Combine.OperandRGB[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB,
+ unit->Combine.OperandRGB[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
+ unit->Combine.OperandA[0]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
+ unit->Combine.OperandA[1]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
+ unit->Combine.OperandA[2]);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE,
+ 1 << unit->Combine.ScaleShiftRGB);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE,
+ 1 << unit->Combine.ScaleShiftA);
+ }
+
+ /* Restore texture object state for each target */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ const struct gl_texture_object *obj = NULL;
+ GLenum target;
+
+ obj = &texstate->SavedObj[u][tgt];
+
+ /* don't restore state for unsupported targets to prevent
+ * raising GL errors.
+ */
+ if (obj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
+ !ctx->Extensions.ARB_texture_cube_map) {
+ continue;
+ }
+ else if (obj->Target == GL_TEXTURE_RECTANGLE_NV &&
+ !ctx->Extensions.NV_texture_rectangle) {
+ continue;
+ }
+ else if ((obj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
+ obj->Target == GL_TEXTURE_2D_ARRAY_EXT) &&
+ !ctx->Extensions.MESA_texture_array) {
+ continue;
+ }
+
+ target = obj->Target;
+
+ _mesa_BindTexture(target, obj->Name);
+
+ _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, obj->BorderColor);
+ _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR);
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, obj->MinFilter);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter);
+ _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod);
+ _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod);
+ _mesa_TexParameterf(target, GL_TEXTURE_LOD_BIAS, obj->LodBias);
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel);
+ if (target != GL_TEXTURE_RECTANGLE_ARB)
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel);
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
+ obj->MaxAnisotropy);
+ }
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ _mesa_TexParameterf(target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
+ obj->CompareFailValue);
+ }
+ }
+
+ /* remove saved references to the texture objects */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
+ }
+ }
+
+ _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
+
+ _mesa_unlock_context_textures(ctx);
+}
+
+
+/*
+ * This function is kind of long just because we have to call a lot
+ * of device driver functions to update device driver state.
+ *
+ * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions
+ * in order to restore GL state. This isn't terribly efficient but it
+ * ensures that dirty flags and any derived state gets updated correctly.
+ * We could at least check if the value to restore equals the current value
+ * and then skip the Mesa call.
+ */
+void GLAPIENTRY
+_mesa_PopAttrib(void)
+{
+ struct gl_attrib_node *attr, *next;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->AttribStackDepth == 0) {
+ _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" );
+ return;
+ }
+
+ ctx->AttribStackDepth--;
+ attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+ while (attr) {
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ _mesa_debug(ctx, "glPopAttrib %s\n",
+ _mesa_lookup_enum_by_nr(attr->kind));
+ }
+
+ switch (attr->kind) {
+ case GL_ACCUM_BUFFER_BIT:
+ {
+ const struct gl_accum_attrib *accum;
+ accum = (const struct gl_accum_attrib *) attr->data;
+ _mesa_ClearAccum(accum->ClearColor[0],
+ accum->ClearColor[1],
+ accum->ClearColor[2],
+ accum->ClearColor[3]);
+ }
+ break;
+ case GL_COLOR_BUFFER_BIT:
+ {
+ const struct gl_colorbuffer_attrib *color;
+ color = (const struct gl_colorbuffer_attrib *) attr->data;
+ _mesa_ClearIndex((GLfloat) color->ClearIndex);
+ _mesa_ClearColor(color->ClearColor[0],
+ color->ClearColor[1],
+ color->ClearColor[2],
+ color->ClearColor[3]);
+ _mesa_IndexMask(color->IndexMask);
+ _mesa_ColorMask((GLboolean) (color->ColorMask[0] != 0),
+ (GLboolean) (color->ColorMask[1] != 0),
+ (GLboolean) (color->ColorMask[2] != 0),
+ (GLboolean) (color->ColorMask[3] != 0));
+ {
+ /* Need to determine if more than one color output is
+ * specified. If so, call glDrawBuffersARB, else call
+ * glDrawBuffer(). This is a subtle, but essential point
+ * since GL_FRONT (for example) is illegal for the former
+ * function, but legal for the later.
+ */
+ GLboolean multipleBuffers = GL_FALSE;
+ GLuint i;
+
+ for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (color->DrawBuffer[i] != GL_NONE) {
+ multipleBuffers = GL_TRUE;
+ break;
+ }
+ }
+ /* Call the API_level functions, not _mesa_drawbuffers()
+ * since we need to do error checking on the pop'd
+ * GL_DRAW_BUFFER.
+ * Ex: if GL_FRONT were pushed, but we're popping with a
+ * user FBO bound, GL_FRONT will be illegal and we'll need
+ * to record that error. Per OpenGL ARB decision.
+ */
+ if (multipleBuffers)
+ _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers,
+ color->DrawBuffer);
+ else
+ _mesa_DrawBuffer(color->DrawBuffer[0]);
+ }
+ _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled);
+ _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef);
+ _mesa_set_enable(ctx, GL_BLEND, color->BlendEnabled);
+ _mesa_BlendFuncSeparateEXT(color->BlendSrcRGB,
+ color->BlendDstRGB,
+ color->BlendSrcA,
+ color->BlendDstA);
+ /* This special case is because glBlendEquationSeparateEXT
+ * cannot take GL_LOGIC_OP as a parameter.
+ */
+ if ( color->BlendEquationRGB == color->BlendEquationA ) {
+ _mesa_BlendEquation(color->BlendEquationRGB);
+ }
+ else {
+ _mesa_BlendEquationSeparateEXT(color->BlendEquationRGB,
+ color->BlendEquationA);
+ }
+ _mesa_BlendColor(color->BlendColor[0],
+ color->BlendColor[1],
+ color->BlendColor[2],
+ color->BlendColor[3]);
+ _mesa_LogicOp(color->LogicOp);
+ _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP,
+ color->ColorLogicOpEnabled);
+ _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP,
+ color->IndexLogicOpEnabled);
+ _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag);
+ }
+ break;
+ case GL_CURRENT_BIT:
+ FLUSH_CURRENT( ctx, 0 );
+ MEMCPY( &ctx->Current, attr->data,
+ sizeof(struct gl_current_attrib) );
+ break;
+ case GL_DEPTH_BUFFER_BIT:
+ {
+ const struct gl_depthbuffer_attrib *depth;
+ depth = (const struct gl_depthbuffer_attrib *) attr->data;
+ _mesa_DepthFunc(depth->Func);
+ _mesa_ClearDepth(depth->Clear);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test);
+ _mesa_DepthMask(depth->Mask);
+ }
+ break;
+ case GL_ENABLE_BIT:
+ {
+ const struct gl_enable_attrib *enable;
+ enable = (const struct gl_enable_attrib *) attr->data;
+ pop_enable_group(ctx, enable);
+ ctx->NewState |= _NEW_ALL;
+ }
+ break;
+ case GL_EVAL_BIT:
+ MEMCPY( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) );
+ ctx->NewState |= _NEW_EVAL;
+ break;
+ case GL_FOG_BIT:
+ {
+ const struct gl_fog_attrib *fog;
+ fog = (const struct gl_fog_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_FOG, fog->Enabled);
+ _mesa_Fogfv(GL_FOG_COLOR, fog->Color);
+ _mesa_Fogf(GL_FOG_DENSITY, fog->Density);
+ _mesa_Fogf(GL_FOG_START, fog->Start);
+ _mesa_Fogf(GL_FOG_END, fog->End);
+ _mesa_Fogf(GL_FOG_INDEX, fog->Index);
+ _mesa_Fogi(GL_FOG_MODE, fog->Mode);
+ }
+ break;
+ case GL_HINT_BIT:
+ {
+ const struct gl_hint_attrib *hint;
+ hint = (const struct gl_hint_attrib *) attr->data;
+ _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT,
+ hint->PerspectiveCorrection );
+ _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth);
+ _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth);
+ _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth);
+ _mesa_Hint(GL_FOG_HINT, hint->Fog);
+ _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,
+ hint->ClipVolumeClipping);
+ _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB,
+ hint->TextureCompression);
+ }
+ break;
+ case GL_LIGHTING_BIT:
+ {
+ GLuint i;
+ const struct gl_light_attrib *light;
+ light = (const struct gl_light_attrib *) attr->data;
+ /* lighting enable */
+ _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled);
+ /* per-light state */
+ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top))
+ _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+
+ for (i = 0; i < ctx->Const.MaxLights; i++) {
+ const struct gl_light *l = &light->Light[i];
+ _mesa_set_enable(ctx, GL_LIGHT0 + i, l->Enabled);
+ _mesa_light(ctx, i, GL_AMBIENT, l->Ambient);
+ _mesa_light(ctx, i, GL_DIFFUSE, l->Diffuse);
+ _mesa_light(ctx, i, GL_SPECULAR, l->Specular );
+ _mesa_light(ctx, i, GL_POSITION, l->EyePosition);
+ _mesa_light(ctx, i, GL_SPOT_DIRECTION, l->SpotDirection);
+ _mesa_light(ctx, i, GL_SPOT_EXPONENT, &l->SpotExponent);
+ _mesa_light(ctx, i, GL_SPOT_CUTOFF, &l->SpotCutoff);
+ _mesa_light(ctx, i, GL_CONSTANT_ATTENUATION,
+ &l->ConstantAttenuation);
+ _mesa_light(ctx, i, GL_LINEAR_ATTENUATION,
+ &l->LinearAttenuation);
+ _mesa_light(ctx, i, GL_QUADRATIC_ATTENUATION,
+ &l->QuadraticAttenuation);
+ }
+ /* light model */
+ _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT,
+ light->Model.Ambient);
+ _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,
+ (GLfloat) light->Model.LocalViewer);
+ _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE,
+ (GLfloat) light->Model.TwoSide);
+ _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL,
+ (GLfloat) light->Model.ColorControl);
+ /* shade model */
+ _mesa_ShadeModel(light->ShadeModel);
+ /* color material */
+ _mesa_ColorMaterial(light->ColorMaterialFace,
+ light->ColorMaterialMode);
+ _mesa_set_enable(ctx, GL_COLOR_MATERIAL,
+ light->ColorMaterialEnabled);
+ /* materials */
+ MEMCPY(&ctx->Light.Material, &light->Material,
+ sizeof(struct gl_material));
+ }
+ break;
+ case GL_LINE_BIT:
+ {
+ const struct gl_line_attrib *line;
+ line = (const struct gl_line_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag);
+ _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag);
+ _mesa_LineStipple(line->StippleFactor, line->StipplePattern);
+ _mesa_LineWidth(line->Width);
+ }
+ 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) );
+ /* XXX what other pixel state needs to be set by function calls? */
+ _mesa_ReadBuffer(ctx->Pixel.ReadBuffer);
+ ctx->NewState |= _NEW_PIXEL;
+ break;
+ case GL_POINT_BIT:
+ {
+ const struct gl_point_attrib *point;
+ point = (const struct gl_point_attrib *) attr->data;
+ _mesa_PointSize(point->Size);
+ _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag);
+ if (ctx->Extensions.EXT_point_parameters) {
+ _mesa_PointParameterfv(GL_DISTANCE_ATTENUATION_EXT,
+ point->Params);
+ _mesa_PointParameterf(GL_POINT_SIZE_MIN_EXT,
+ point->MinSize);
+ _mesa_PointParameterf(GL_POINT_SIZE_MAX_EXT,
+ point->MaxSize);
+ _mesa_PointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT,
+ point->Threshold);
+ }
+ if (ctx->Extensions.NV_point_sprite
+ || ctx->Extensions.ARB_point_sprite) {
+ GLuint u;
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV,
+ (GLint) point->CoordReplace[u]);
+ }
+ _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite);
+ if (ctx->Extensions.NV_point_sprite)
+ _mesa_PointParameteri(GL_POINT_SPRITE_R_MODE_NV,
+ ctx->Point.SpriteRMode);
+ _mesa_PointParameterf(GL_POINT_SPRITE_COORD_ORIGIN,
+ (GLfloat)ctx->Point.SpriteOrigin);
+ }
+ }
+ break;
+ case GL_POLYGON_BIT:
+ {
+ const struct gl_polygon_attrib *polygon;
+ polygon = (const struct gl_polygon_attrib *) attr->data;
+ _mesa_CullFace(polygon->CullFaceMode);
+ _mesa_FrontFace(polygon->FrontFace);
+ _mesa_PolygonMode(GL_FRONT, polygon->FrontMode);
+ _mesa_PolygonMode(GL_BACK, polygon->BackMode);
+ _mesa_PolygonOffset(polygon->OffsetFactor,
+ polygon->OffsetUnits);
+ _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag);
+ _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag);
+ _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT,
+ polygon->OffsetPoint);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE,
+ polygon->OffsetLine);
+ _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL,
+ polygon->OffsetFill);
+ }
+ break;
+ case GL_POLYGON_STIPPLE_BIT:
+ MEMCPY( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) );
+ ctx->NewState |= _NEW_POLYGONSTIPPLE;
+ if (ctx->Driver.PolygonStipple)
+ ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data );
+ break;
+ case GL_SCISSOR_BIT:
+ {
+ const struct gl_scissor_attrib *scissor;
+ scissor = (const struct gl_scissor_attrib *) attr->data;
+ _mesa_Scissor(scissor->X, scissor->Y,
+ scissor->Width, scissor->Height);
+ _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled);
+ }
+ break;
+ case GL_STENCIL_BUFFER_BIT:
+ {
+ const struct gl_stencil_attrib *stencil;
+ stencil = (const struct gl_stencil_attrib *) attr->data;
+ _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled);
+ _mesa_ClearStencil(stencil->Clear);
+ if (ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT,
+ stencil->TestTwoSide);
+ _mesa_ActiveStencilFaceEXT(stencil->ActiveFace
+ ? GL_BACK : GL_FRONT);
+ }
+ /* front state */
+ _mesa_StencilFuncSeparate(GL_FRONT,
+ stencil->Function[0],
+ stencil->Ref[0],
+ stencil->ValueMask[0]);
+ _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]);
+ _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0],
+ stencil->ZFailFunc[0],
+ stencil->ZPassFunc[0]);
+ /* back state */
+ _mesa_StencilFuncSeparate(GL_BACK,
+ stencil->Function[1],
+ stencil->Ref[1],
+ stencil->ValueMask[1]);
+ _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]);
+ _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1],
+ stencil->ZFailFunc[1],
+ stencil->ZPassFunc[1]);
+ }
+ break;
+ case GL_TRANSFORM_BIT:
+ {
+ GLuint i;
+ const struct gl_transform_attrib *xform;
+ xform = (const struct gl_transform_attrib *) attr->data;
+ _mesa_MatrixMode(xform->MatrixMode);
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+ /* restore clip planes */
+ for (i = 0; i < MAX_CLIP_PLANES; i++) {
+ const GLuint mask = 1 << i;
+ const GLfloat *eyePlane = xform->EyeUserPlane[i];
+ COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane);
+ if (xform->ClipPlanesEnabled & mask) {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE);
+ }
+ else {
+ _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE);
+ }
+ if (ctx->Driver.ClipPlane)
+ ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane );
+ }
+
+ /* normalize/rescale */
+ if (xform->Normalize != ctx->Transform.Normalize)
+ _mesa_set_enable(ctx, GL_NORMALIZE,ctx->Transform.Normalize);
+ if (xform->RescaleNormals != ctx->Transform.RescaleNormals)
+ _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT,
+ ctx->Transform.RescaleNormals);
+ }
+ break;
+ case GL_TEXTURE_BIT:
+ /* Take care of texture object reference counters */
+ {
+ struct texture_state *texstate
+ = (struct texture_state *) attr->data;
+ pop_texture_group(ctx, texstate);
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ break;
+ case GL_VIEWPORT_BIT:
+ {
+ const struct gl_viewport_attrib *vp;
+ vp = (const struct gl_viewport_attrib *) attr->data;
+ _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height);
+ _mesa_DepthRange(vp->Near, vp->Far);
+ }
+ break;
+ case GL_MULTISAMPLE_BIT_ARB:
+ {
+ const struct gl_multisample_attrib *ms;
+ ms = (const struct gl_multisample_attrib *) attr->data;
+ _mesa_SampleCoverageARB(ms->SampleCoverageValue,
+ ms->SampleCoverageInvert);
+ }
+ break;
+
+ default:
+ _mesa_problem( ctx, "Bad attrib flag in PopAttrib");
+ break;
+ }
+
+ next = attr->next;
+ FREE( attr->data );
+ FREE( attr );
+ attr = next;
+ }
+}
+
+
+/**
+ * Helper for incrementing/decrementing vertex buffer object reference
+ * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group.
+ */
+static void
+adjust_buffer_object_ref_counts(struct gl_array_object *arrayObj, GLint step)
+{
+ GLuint i;
+
+ arrayObj->Vertex.BufferObj->RefCount += step;
+ arrayObj->Weight.BufferObj->RefCount += step;
+ arrayObj->Normal.BufferObj->RefCount += step;
+ arrayObj->Color.BufferObj->RefCount += step;
+ arrayObj->SecondaryColor.BufferObj->RefCount += step;
+ arrayObj->FogCoord.BufferObj->RefCount += step;
+ arrayObj->Index.BufferObj->RefCount += step;
+ arrayObj->EdgeFlag.BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ arrayObj->TexCoord[i].BufferObj->RefCount += step;
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ arrayObj->VertexAttrib[i].BufferObj->RefCount += step;
+}
+
+
+/**
+ * Copy gl_pixelstore_attrib from src to dst, updating buffer
+ * object refcounts.
+ */
+static void
+copy_pixelstore(GLcontext *ctx,
+ struct gl_pixelstore_attrib *dst,
+ const struct gl_pixelstore_attrib *src)
+{
+ dst->Alignment = src->Alignment;
+ dst->RowLength = src->RowLength;
+ dst->SkipPixels = src->SkipPixels;
+ dst->SkipRows = src->SkipRows;
+ dst->ImageHeight = src->ImageHeight;
+ dst->SkipImages = src->SkipImages;
+ dst->SwapBytes = src->SwapBytes;
+ dst->LsbFirst = src->LsbFirst;
+ dst->ClientStorage = src->ClientStorage;
+ dst->Invert = src->Invert;
+ _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
+}
+
+
+#define GL_CLIENT_PACK_BIT (1<<20)
+#define GL_CLIENT_UNPACK_BIT (1<<21)
+
+
+void GLAPIENTRY
+_mesa_PushClientAttrib(GLbitfield mask)
+{
+ struct gl_attrib_node *head;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) {
+ _mesa_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 = CALLOC_STRUCT( gl_pixelstore_attrib );
+ copy_pixelstore(ctx, attr, &ctx->Pack);
+ save_attrib_data(&head, GL_CLIENT_PACK_BIT, attr);
+ /* unpacking attribs */
+ attr = CALLOC_STRUCT( gl_pixelstore_attrib );
+ copy_pixelstore(ctx, attr, &ctx->Unpack);
+ save_attrib_data(&head, GL_CLIENT_UNPACK_BIT, attr);
+ }
+
+ if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+ struct gl_array_attrib *attr;
+ struct gl_array_object *obj;
+
+ attr = MALLOC_STRUCT( gl_array_attrib );
+ obj = MALLOC_STRUCT( gl_array_object );
+
+#if FEATURE_ARB_vertex_buffer_object
+ /* increment ref counts since we're copying pointers to these objects */
+ ctx->Array.ArrayBufferObj->RefCount++;
+ ctx->Array.ElementArrayBufferObj->RefCount++;
+#endif
+
+ MEMCPY( attr, &ctx->Array, sizeof(struct gl_array_attrib) );
+ MEMCPY( obj, ctx->Array.ArrayObj, sizeof(struct gl_array_object) );
+
+ attr->ArrayObj = obj;
+
+ save_attrib_data(&head, GL_CLIENT_VERTEX_ARRAY_BIT, attr);
+
+ /* bump reference counts on buffer objects */
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, 1);
+ }
+
+ ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
+ ctx->ClientAttribStackDepth++;
+}
+
+
+
+
+void GLAPIENTRY
+_mesa_PopClientAttrib(void)
+{
+ struct gl_attrib_node *node, *next;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->ClientAttribStackDepth == 0) {
+ _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" );
+ return;
+ }
+
+ ctx->ClientAttribStackDepth--;
+ node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
+
+ while (node) {
+ switch (node->kind) {
+ case GL_CLIENT_PACK_BIT:
+ {
+ struct gl_pixelstore_attrib *store =
+ (struct gl_pixelstore_attrib *) node->data;
+ copy_pixelstore(ctx, &ctx->Pack, store);
+ _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
+ }
+ ctx->NewState |= _NEW_PACKUNPACK;
+ break;
+ case GL_CLIENT_UNPACK_BIT:
+ {
+ struct gl_pixelstore_attrib *store =
+ (struct gl_pixelstore_attrib *) node->data;
+ copy_pixelstore(ctx, &ctx->Unpack, store);
+ _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL);
+ }
+ ctx->NewState |= _NEW_PACKUNPACK;
+ break;
+ case GL_CLIENT_VERTEX_ARRAY_BIT: {
+ struct gl_array_attrib * data =
+ (struct gl_array_attrib *) node->data;
+
+ adjust_buffer_object_ref_counts(ctx->Array.ArrayObj, -1);
+
+ ctx->Array.ActiveTexture = data->ActiveTexture;
+ if (data->LockCount != 0)
+ _mesa_LockArraysEXT(data->LockFirst, data->LockCount);
+ else if (ctx->Array.LockCount)
+ _mesa_UnlockArraysEXT();
+
+ _mesa_BindVertexArrayAPPLE( data->ArrayObj->Name );
+
+#if FEATURE_ARB_vertex_buffer_object
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB,
+ data->ArrayBufferObj->Name);
+ _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
+ data->ElementArrayBufferObj->Name);
+#endif
+
+ MEMCPY( ctx->Array.ArrayObj, data->ArrayObj,
+ sizeof( struct gl_array_object ) );
+
+ FREE( data->ArrayObj );
+
+ /* FIXME: Should some bits in ctx->Array->NewState also be set
+ * FIXME: here? It seems like it should be set to inclusive-or
+ * FIXME: of the old ArrayObj->_Enabled and the new _Enabled.
+ */
+
+ ctx->NewState |= _NEW_ARRAY;
+ break;
+ }
+ default:
+ _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib");
+ break;
+ }
+
+ next = node->next;
+ FREE( node->data );
+ FREE( node );
+ node = next;
+ }
+}
+
+
+/**
+ * Free any attribute state data that might be attached to the context.
+ */
+void
+_mesa_free_attrib_data(GLcontext *ctx)
+{
+ while (ctx->AttribStackDepth > 0) {
+ struct gl_attrib_node *attr, *next;
+
+ ctx->AttribStackDepth--;
+ attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+ while (attr) {
+ if (attr->kind == GL_TEXTURE_BIT) {
+ struct texture_state *texstate = (struct texture_state*)attr->data;
+ GLuint u, tgt;
+ /* clear references to the saved texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&texstate->SavedTexRef[u][tgt], NULL);
+ }
+ }
+ }
+ else {
+ /* any other chunks of state that requires special handling? */
+ }
+
+ next = attr->next;
+ _mesa_free(attr->data);
+ _mesa_free(attr);
+ attr = next;
+ }
+ }
+}
+
+
+void _mesa_init_attrib( GLcontext *ctx )
+{
+ /* Renderer and client attribute stacks */
+ ctx->AttribStackDepth = 0;
+ ctx->ClientAttribStackDepth = 0;
+}
diff --git a/mesalib/src/mesa/main/attrib.h b/mesalib/src/mesa/main/attrib.h
new file mode 100644
index 000000000..2cf8fe693
--- /dev/null
+++ b/mesalib/src/mesa/main/attrib.h
@@ -0,0 +1,60 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_PushAttrib( GLbitfield mask );
+
+extern void GLAPIENTRY
+_mesa_PopAttrib( void );
+
+extern void GLAPIENTRY
+_mesa_PushClientAttrib( GLbitfield mask );
+
+extern void GLAPIENTRY
+_mesa_PopClientAttrib( void );
+
+extern void
+_mesa_init_attrib( GLcontext *ctx );
+
+extern void
+_mesa_free_attrib_data( GLcontext *ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_attrib( c ) ((void)0)
+#define _mesa_free_attrib_data( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/bitset.h b/mesalib/src/mesa/main/bitset.h
new file mode 100644
index 000000000..8bd4526cb
--- /dev/null
+++ b/mesalib/src/mesa/main/bitset.h
@@ -0,0 +1,122 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+/**
+ * \file bitset.h
+ * \brief Bitset of arbitrary size definitions.
+ * \author Michal Krol
+ */
+
+/****************************************************************************
+ * generic bitset implementation
+ */
+
+#define BITSET_WORD GLuint
+#define BITSET_WORDBITS (sizeof (BITSET_WORD) * 8)
+
+/* bitset declarations
+ */
+#define BITSET_DECLARE(name, size) \
+ BITSET_WORD name[((size) + BITSET_WORDBITS - 1) / BITSET_WORDBITS]
+
+/* bitset operations
+ */
+#define BITSET_COPY(x, y) _mesa_memcpy( (x), (y), sizeof (x) )
+#define BITSET_EQUAL(x, y) (_mesa_memcmp( (x), (y), sizeof (x) ) == 0)
+#define BITSET_ZERO(x) _mesa_memset( (x), 0, sizeof (x) )
+#define BITSET_ONES(x) _mesa_memset( (x), 0xff, sizeof (x) )
+
+#define BITSET_BITWORD(b) ((b) / BITSET_WORDBITS)
+#define BITSET_BIT(b) (1 << ((b) % BITSET_WORDBITS))
+
+/* single bit operations
+ */
+#define BITSET_TEST(x, b) ((x)[BITSET_BITWORD(b)] & BITSET_BIT(b))
+#define BITSET_SET(x, b) ((x)[BITSET_BITWORD(b)] |= BITSET_BIT(b))
+#define BITSET_CLEAR(x, b) ((x)[BITSET_BITWORD(b)] &= ~BITSET_BIT(b))
+
+#define BITSET_MASK(b) ((b) == BITSET_WORDBITS ? ~0 : BITSET_BIT(b) - 1)
+#define BITSET_RANGE(b, e) (BITSET_MASK((e) + 1) & ~BITSET_MASK(b))
+
+/* bit range operations
+ */
+#define BITSET_TEST_RANGE(x, b, e) \
+ (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
+ ((x)[BITSET_BITWORD(b)] & BITSET_RANGE(b, e)) : \
+ (assert (!"BITSET_TEST_RANGE: bit range crosses word boundary"), 0))
+#define BITSET_SET_RANGE(x, b, e) \
+ (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
+ ((x)[BITSET_BITWORD(b)] |= BITSET_RANGE(b, e)) : \
+ (assert (!"BITSET_SET_RANGE: bit range crosses word boundary"), 0))
+#define BITSET_CLEAR_RANGE(x, b, e) \
+ (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
+ ((x)[BITSET_BITWORD(b)] &= ~BITSET_RANGE(b, e)) : \
+ (assert (!"BITSET_CLEAR_RANGE: bit range crosses word boundary"), 0))
+
+/****************************************************************************
+ * 64-bit bitset implementation
+ */
+
+#define BITSET64_WORD GLuint
+#define BITSET64_WORDBITS (sizeof (BITSET64_WORD) * 8)
+
+/* bitset declarations
+ */
+#define BITSET64_DECLARE(name, size) \
+ GLuint name[2]
+
+/* bitset operations
+ */
+#define BITSET64_COPY(x, y) do { (x)[0] = (y)[0]; (x)[1] = (y)[1]; } while (0)
+#define BITSET64_EQUAL(x, y) ( (x)[0] == (y)[0] && (x)[1] == (y)[1] )
+#define BITSET64_ZERO(x) do { (x)[0] = 0; (x)[1] = 0; } while (0)
+#define BITSET64_ONES(x) do { (x)[0] = 0xFF; (x)[1] = 0xFF; } while (0)
+
+#define BITSET64_BITWORD(b) ((b) / BITSET64_WORDBITS)
+#define BITSET64_BIT(b) (1 << ((b) % BITSET64_WORDBITS))
+
+/* single bit operations
+ */
+#define BITSET64_TEST(x, b) ((x)[BITSET64_BITWORD(b)] & BITSET64_BIT(b))
+#define BITSET64_SET(x, b) ((x)[BITSET64_BITWORD(b)] |= BITSET64_BIT(b))
+#define BITSET64_CLEAR(x, b) ((x)[BITSET64_BITWORD(b)] &= ~BITSET64_BIT(b))
+
+#define BITSET64_MASK(b) ((b) == BITSET64_WORDBITS ? ~0 : BITSET64_BIT(b) - 1)
+#define BITSET64_RANGE(b, e) (BITSET64_MASK((e) + 1) & ~BITSET64_MASK(b))
+
+/* bit range operations
+ */
+#define BITSET64_TEST_RANGE(x, b, e) \
+ (BITSET64_BITWORD(b) == BITSET64_BITWORD(e) ? \
+ ((x)[BITSET64_BITWORD(b)] & BITSET64_RANGE(b, e)) : \
+ (assert (!"BITSET64_TEST_RANGE: bit range crosses word boundary"), 0))
+#define BITSET64_SET_RANGE(x, b, e) \
+ (BITSET64_BITWORD(b) == BITSET64_BITWORD(e) ? \
+ ((x)[BITSET64_BITWORD(b)] |= BITSET64_RANGE(b, e)) : \
+ (assert (!"BITSET64_SET_RANGE: bit range crosses word boundary"), 0))
+#define BITSET64_CLEAR_RANGE(x, b, e) \
+ (BITSET64_BITWORD(b) == BITSET64_BITWORD(e) ? \
+ ((x)[BITSET64_BITWORD(b)] &= ~BITSET64_RANGE(b, e)) : \
+ (assert (!"BITSET64_CLEAR_RANGE: bit range crosses word boundary"), 0))
+
diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c
new file mode 100644
index 000000000..39cf6153e
--- /dev/null
+++ b/mesalib/src/mesa/main/blend.c
@@ -0,0 +1,592 @@
+/**
+ * \file blend.c
+ * Blending operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "blend.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "glapi/glapitable.h"
+
+
+/**
+ * Specify the blending operation.
+ *
+ * \param sfactor source factor operator.
+ * \param dfactor destination factor operator.
+ *
+ * \sa glBlendFunc, glBlendFuncSeparateEXT
+ */
+void GLAPIENTRY
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
+{
+ _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
+}
+
+
+/**
+ * Process GL_EXT_blend_func_separate().
+ *
+ * \param sfactorRGB RGB source factor operator.
+ * \param dfactorRGB RGB destination factor operator.
+ * \param sfactorA alpha source factor operator.
+ * \param dfactorA alpha destination factor operator.
+ *
+ * Verifies the parameters and updates gl_colorbuffer_attrib.
+ * On a change, flush the vertices and notify the driver via
+ * dd_function_table::BlendFuncSeparate.
+ */
+void GLAPIENTRY
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
+ _mesa_lookup_enum_by_nr(sfactorRGB),
+ _mesa_lookup_enum_by_nr(dfactorRGB),
+ _mesa_lookup_enum_by_nr(sfactorA),
+ _mesa_lookup_enum_by_nr(dfactorA));
+
+ switch (sfactorRGB) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (!ctx->Extensions.NV_blend_square) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
+ return;
+ }
+ /* fall-through */
+ 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:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)");
+ return;
+ }
+
+ switch (dfactorRGB) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ if (!ctx->Extensions.NV_blend_square) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
+ return;
+ }
+ /* fall-through */
+ 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:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)");
+ return;
+ }
+
+ switch (sfactorA) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (!ctx->Extensions.NV_blend_square) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
+ return;
+ }
+ /* fall-through */
+ 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:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)");
+ return;
+ }
+
+ switch (dfactorA) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ if (!ctx->Extensions.NV_blend_square) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)");
+ return;
+ }
+ /* fall-through */
+ 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:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)" );
+ return;
+ }
+
+ if (ctx->Color.BlendSrcRGB == sfactorRGB &&
+ ctx->Color.BlendDstRGB == dfactorRGB &&
+ ctx->Color.BlendSrcA == sfactorA &&
+ ctx->Color.BlendDstA == dfactorA)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+
+ ctx->Color.BlendSrcRGB = sfactorRGB;
+ ctx->Color.BlendDstRGB = dfactorRGB;
+ ctx->Color.BlendSrcA = sfactorA;
+ ctx->Color.BlendDstA = dfactorA;
+
+ if (ctx->Driver.BlendFuncSeparate) {
+ (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA );
+ }
+}
+
+
+#if _HAVE_FULL_GL
+
+static GLboolean
+_mesa_validate_blend_equation( GLcontext *ctx,
+ GLenum mode, GLboolean is_separate )
+{
+ switch (mode) {
+ case GL_FUNC_ADD:
+ break;
+ case GL_MIN:
+ case GL_MAX:
+ if (!ctx->Extensions.EXT_blend_minmax &&
+ !ctx->Extensions.ARB_imaging) {
+ return GL_FALSE;
+ }
+ break;
+ /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
+ */
+ case GL_LOGIC_OP:
+ if (!ctx->Extensions.EXT_blend_logic_op || is_separate) {
+ return GL_FALSE;
+ }
+ break;
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ if (!ctx->Extensions.EXT_blend_subtract &&
+ !ctx->Extensions.ARB_imaging) {
+ return GL_FALSE;
+ }
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/* This is really an extension function! */
+void GLAPIENTRY
+_mesa_BlendEquation( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBlendEquation %s\n",
+ _mesa_lookup_enum_by_nr(mode));
+
+ if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+ return;
+ }
+
+ if ( (ctx->Color.BlendEquationRGB == mode) &&
+ (ctx->Color.BlendEquationA == mode) )
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.BlendEquationRGB = mode;
+ ctx->Color.BlendEquationA = mode;
+
+ if (ctx->Driver.BlendEquationSeparate)
+ (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
+}
+
+
+void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
+ _mesa_lookup_enum_by_nr(modeRGB),
+ _mesa_lookup_enum_by_nr(modeA));
+
+ if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlendEquationSeparateEXT not supported by driver");
+ return;
+ }
+
+ if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
+ return;
+ }
+
+ if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
+ return;
+ }
+
+
+ if ( (ctx->Color.BlendEquationRGB == modeRGB) &&
+ (ctx->Color.BlendEquationA == modeA) )
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.BlendEquationRGB = modeRGB;
+ ctx->Color.BlendEquationA = modeA;
+
+ if (ctx->Driver.BlendEquationSeparate)
+ (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA );
+}
+#endif
+
+
+/**
+ * Set the blending color.
+ *
+ * \param red red color component.
+ * \param green green color component.
+ * \param blue blue color component.
+ * \param alpha alpha color component.
+ *
+ * \sa glBlendColor().
+ *
+ * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
+ * change, flushes the vertices and notifies the driver via
+ * dd_function_table::BlendColor callback.
+ */
+void GLAPIENTRY
+_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{
+ GLfloat tmp[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ tmp[0] = CLAMP( red, 0.0F, 1.0F );
+ tmp[1] = CLAMP( green, 0.0F, 1.0F );
+ tmp[2] = CLAMP( blue, 0.0F, 1.0F );
+ tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
+
+ if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4FV( ctx->Color.BlendColor, tmp );
+
+ if (ctx->Driver.BlendColor)
+ (*ctx->Driver.BlendColor)(ctx, tmp);
+}
+
+
+/**
+ * Specify the alpha test function.
+ *
+ * \param func alpha comparison function.
+ * \param ref reference value.
+ *
+ * Verifies the parameters and updates gl_colorbuffer_attrib.
+ * On a change, flushes the vertices and notifies the driver via
+ * dd_function_table::AlphaFunc callback.
+ */
+void GLAPIENTRY
+_mesa_AlphaFunc( GLenum func, GLclampf ref )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (func) {
+ case GL_NEVER:
+ case GL_LESS:
+ case GL_EQUAL:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ case GL_GEQUAL:
+ case GL_ALWAYS:
+ ref = CLAMP(ref, 0.0F, 1.0F);
+
+ if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.AlphaFunc = func;
+ ctx->Color.AlphaRef = ref;
+
+ if (ctx->Driver.AlphaFunc)
+ ctx->Driver.AlphaFunc(ctx, func, ref);
+ return;
+
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
+ return;
+ }
+}
+
+
+/**
+ * Specify a logic pixel operation for color index rendering.
+ *
+ * \param opcode operation.
+ *
+ * Verifies that \p opcode is a valid enum and updates
+gl_colorbuffer_attrib::LogicOp.
+ * On a change, flushes the vertices and notifies the driver via the
+ * dd_function_table::LogicOpcode callback.
+ */
+void GLAPIENTRY
+_mesa_LogicOp( GLenum opcode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (opcode) {
+ case GL_CLEAR:
+ case GL_SET:
+ case GL_COPY:
+ case GL_COPY_INVERTED:
+ case GL_NOOP:
+ case GL_INVERT:
+ case GL_AND:
+ case GL_NAND:
+ case GL_OR:
+ case GL_NOR:
+ case GL_XOR:
+ case GL_EQUIV:
+ case GL_AND_REVERSE:
+ case GL_AND_INVERTED:
+ case GL_OR_REVERSE:
+ case GL_OR_INVERTED:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
+ return;
+ }
+
+ if (ctx->Color.LogicOp == opcode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.LogicOp = opcode;
+
+ if (ctx->Driver.LogicOpcode)
+ ctx->Driver.LogicOpcode( ctx, opcode );
+}
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_IndexMask( GLuint mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Color.IndexMask == mask)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.IndexMask = mask;
+
+ if (ctx->Driver.IndexMask)
+ ctx->Driver.IndexMask( ctx, mask );
+}
+#endif
+
+
+/**
+ * Enable or disable writing of frame buffer color components.
+ *
+ * \param red whether to mask writing of the red color component.
+ * \param green whether to mask writing of the green color component.
+ * \param blue whether to mask writing of the blue color component.
+ * \param alpha whether to mask writing of the alpha color component.
+ *
+ * \sa glColorMask().
+ *
+ * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
+ * change, flushes the vertices and notifies the driver via the
+ * dd_function_table::ColorMask callback.
+ */
+void GLAPIENTRY
+_mesa_ColorMask( GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLubyte tmp[4];
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
+
+ /* Shouldn't have any information about channel depth in core mesa
+ * -- should probably store these as the native booleans:
+ */
+ tmp[RCOMP] = red ? 0xff : 0x0;
+ tmp[GCOMP] = green ? 0xff : 0x0;
+ tmp[BCOMP] = blue ? 0xff : 0x0;
+ tmp[ACOMP] = alpha ? 0xff : 0x0;
+
+ if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4UBV(ctx->Color.ColorMask, tmp);
+
+ if (ctx->Driver.ColorMask)
+ ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
+}
+
+
+extern void GLAPIENTRY
+_mesa_ClampColorARB(GLenum target, GLenum clamp)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
+ return;
+ }
+
+ switch (target) {
+ case GL_CLAMP_VERTEX_COLOR_ARB:
+ ctx->Light.ClampVertexColor = clamp;
+ break;
+ case GL_CLAMP_FRAGMENT_COLOR_ARB:
+ ctx->Color.ClampFragmentColor = clamp;
+ break;
+ case GL_CLAMP_READ_COLOR_ARB:
+ ctx->Color.ClampReadColor = clamp;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
+ return;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialization of the context's Color attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes the related fields in the context color attribute group,
+ * __GLcontextRec::Color.
+ */
+void _mesa_init_color( GLcontext * ctx )
+{
+ /* Color buffer group */
+ ctx->Color.IndexMask = ~0u;
+ ctx->Color.ColorMask[0] = 0xff;
+ ctx->Color.ColorMask[1] = 0xff;
+ ctx->Color.ColorMask[2] = 0xff;
+ ctx->Color.ColorMask[3] = 0xff;
+ ctx->Color.ClearIndex = 0;
+ ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
+ 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.BlendEquationRGB = GL_FUNC_ADD;
+ ctx->Color.BlendEquationA = GL_FUNC_ADD;
+ 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._LogicOpEnabled = GL_FALSE;
+ ctx->Color.LogicOp = GL_COPY;
+ ctx->Color.DitherFlag = GL_TRUE;
+
+ if (ctx->Visual.doubleBufferMode) {
+ ctx->Color.DrawBuffer[0] = GL_BACK;
+ }
+ else {
+ ctx->Color.DrawBuffer[0] = GL_FRONT;
+ }
+
+ ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
+ ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h
new file mode 100644
index 000000000..5c0f2783a
--- /dev/null
+++ b/mesalib/src/mesa/main/blend.h
@@ -0,0 +1,83 @@
+/**
+ * \file blend.h
+ * Blending functions operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor );
+
+
+extern void GLAPIENTRY
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA );
+
+
+extern void GLAPIENTRY
+_mesa_BlendEquation( GLenum mode );
+
+
+extern void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA );
+
+
+extern void GLAPIENTRY
+_mesa_BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
+
+extern void GLAPIENTRY
+_mesa_AlphaFunc( GLenum func, GLclampf ref );
+
+
+extern void GLAPIENTRY
+_mesa_LogicOp( GLenum opcode );
+
+
+extern void GLAPIENTRY
+_mesa_IndexMask( GLuint mask );
+
+extern void GLAPIENTRY
+_mesa_ColorMask( GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha );
+
+
+extern void GLAPIENTRY
+_mesa_ClampColorARB(GLenum target, GLenum clamp);
+
+
+extern void
+_mesa_init_color( GLcontext * ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
new file mode 100644
index 000000000..189b5e165
--- /dev/null
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -0,0 +1,1678 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file bufferobj.c
+ * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
+ * \author Brian Paul, Ian Romanick
+ */
+
+
+#include "glheader.h"
+#include "hash.h"
+#include "imports.h"
+#include "image.h"
+#include "context.h"
+#include "bufferobj.h"
+
+
+/* Debug flags */
+/*#define VBO_DEBUG*/
+/*#define BOUNDS_CHECK*/
+
+
+#ifdef FEATURE_OES_mapbuffer
+#define DEFAULT_ACCESS GL_MAP_WRITE_BIT
+#else
+#define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
+#endif
+
+
+/**
+ * Get the buffer object bound to the specified target in a GL context.
+ *
+ * \param ctx GL context
+ * \param target Buffer object target to be retrieved. Currently this must
+ * be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER.
+ * \return A pointer to the buffer object bound to \c target in the
+ * specified context or \c NULL if \c target is invalid.
+ */
+static INLINE struct gl_buffer_object *
+get_buffer(GLcontext *ctx, GLenum target)
+{
+ struct gl_buffer_object * bufObj = NULL;
+
+ switch (target) {
+ case GL_ARRAY_BUFFER_ARB:
+ bufObj = ctx->Array.ArrayBufferObj;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ bufObj = ctx->Array.ElementArrayBufferObj;
+ break;
+ case GL_PIXEL_PACK_BUFFER_EXT:
+ bufObj = ctx->Pack.BufferObj;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_EXT:
+ bufObj = ctx->Unpack.BufferObj;
+ break;
+ case GL_COPY_READ_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bufObj = ctx->CopyReadBuffer;
+ }
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bufObj = ctx->CopyWriteBuffer;
+ }
+ break;
+ default:
+ /* error must be recorded by caller */
+ return NULL;
+ }
+
+ /* bufObj should point to NullBufferObj or a user-created buffer object */
+ ASSERT(bufObj);
+
+ return bufObj;
+}
+
+
+/**
+ * Convert a GLbitfield describing the mapped buffer access flags
+ * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
+ */
+static GLenum
+simplified_access_mode(GLbitfield access)
+{
+ const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+ if ((access & rwFlags) == rwFlags)
+ return GL_READ_WRITE;
+ if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
+ return GL_READ_ONLY;
+ if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
+ return GL_WRITE_ONLY;
+ return GL_READ_WRITE; /* this should never happen, but no big deal */
+}
+
+
+/**
+ * Tests the subdata range parameters and sets the GL error code for
+ * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
+ *
+ * \param ctx GL context.
+ * \param target Buffer object target on which to operate.
+ * \param offset Offset of the first byte of the subdata range.
+ * \param size Size, in bytes, of the subdata range.
+ * \param caller Name of calling function for recording errors.
+ * \return A pointer to the buffer object bound to \c target in the
+ * specified context or \c NULL if any of the parameter or state
+ * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB
+ * are invalid.
+ *
+ * \sa glBufferSubDataARB, glGetBufferSubDataARB
+ */
+static struct gl_buffer_object *
+buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
+ GLintptrARB offset, GLsizeiptrARB size,
+ const char *caller )
+{
+ struct gl_buffer_object *bufObj;
+
+ if (size < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
+ return NULL;
+ }
+
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
+ return NULL;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
+ return NULL;
+ }
+ if (offset + size > bufObj->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "%s(size + offset > buffer size)", caller);
+ return NULL;
+ }
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* Buffer is currently mapped */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
+ return NULL;
+ }
+
+ return bufObj;
+}
+
+
+/**
+ * Allocate and initialize a new buffer object.
+ *
+ * Default callback for the \c dd_function_table::NewBufferObject() hook.
+ */
+static struct gl_buffer_object *
+_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct gl_buffer_object *obj;
+
+ (void) ctx;
+
+ obj = MALLOC_STRUCT(gl_buffer_object);
+ _mesa_initialize_buffer_object(obj, name, target);
+ return obj;
+}
+
+
+/**
+ * Delete a buffer object.
+ *
+ * Default callback for the \c dd_function_table::DeleteBuffer() hook.
+ */
+static void
+_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
+{
+ (void) ctx;
+
+ if (bufObj->Data)
+ _mesa_free(bufObj->Data);
+
+ /* assign strange values here to help w/ debugging */
+ bufObj->RefCount = -1000;
+ bufObj->Name = ~0;
+
+ _mesa_free(bufObj);
+}
+
+
+
+/**
+ * Set ptr to bufObj w/ reference counting.
+ */
+void
+_mesa_reference_buffer_object(GLcontext *ctx,
+ struct gl_buffer_object **ptr,
+ struct gl_buffer_object *bufObj)
+{
+ if (*ptr == bufObj)
+ return;
+
+ if (*ptr) {
+ /* Unreference the old buffer */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_buffer_object *oldObj = *ptr;
+
+ /*_glthread_LOCK_MUTEX(oldObj->Mutex);*/
+ ASSERT(oldObj->RefCount > 0);
+ oldObj->RefCount--;
+#if 0
+ printf("BufferObj %p %d DECR to %d\n",
+ (void *) oldObj, oldObj->Name, oldObj->RefCount);
+#endif
+ deleteFlag = (oldObj->RefCount == 0);
+ /*_glthread_UNLOCK_MUTEX(oldObj->Mutex);*/
+
+ if (deleteFlag) {
+
+ /* some sanity checking: don't delete a buffer still in use */
+#if 0
+ /* unfortunately, these tests are invalid during context tear-down */
+ ASSERT(ctx->Array.ArrayBufferObj != bufObj);
+ ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
+ ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
+#endif
+
+ ASSERT(ctx->Driver.DeleteBuffer);
+ ctx->Driver.DeleteBuffer(ctx, oldObj);
+ }
+
+ *ptr = NULL;
+ }
+ ASSERT(!*ptr);
+
+ if (bufObj) {
+ /* reference new buffer */
+ /*_glthread_LOCK_MUTEX(tex->Mutex);*/
+ if (bufObj->RefCount == 0) {
+ /* this buffer's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted buffer object");
+ *ptr = NULL;
+ }
+ else {
+ bufObj->RefCount++;
+#if 0
+ printf("BufferObj %p %d INCR to %d\n",
+ (void *) bufObj, bufObj->Name, bufObj->RefCount);
+#endif
+ *ptr = bufObj;
+ }
+ /*_glthread_UNLOCK_MUTEX(tex->Mutex);*/
+ }
+}
+
+
+/**
+ * Initialize a buffer object to default values.
+ */
+void
+_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
+ GLuint name, GLenum target )
+{
+ (void) target;
+
+ _mesa_bzero(obj, sizeof(struct gl_buffer_object));
+ obj->RefCount = 1;
+ obj->Name = name;
+ obj->Usage = GL_STATIC_DRAW_ARB;
+ obj->AccessFlags = DEFAULT_ACCESS;
+}
+
+
+/**
+ * Allocate space for and store data in a buffer object. Any data that was
+ * previously stored in the buffer object is lost. If \c data is \c NULL,
+ * memory will be allocated, but no copy will occur.
+ *
+ * This is the default callback for \c dd_function_table::BufferData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx GL context.
+ * \param target Buffer object target on which to operate.
+ * \param size Size, in bytes, of the new data store.
+ * \param data Pointer to the data to store in the buffer object. This
+ * pointer may be \c NULL.
+ * \param usage Hints about how the data will be used.
+ * \param bufObj Object to be used.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure
+ * \sa glBufferDataARB, dd_function_table::BufferData.
+ */
+static GLboolean
+_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+ const GLvoid * data, GLenum usage,
+ struct gl_buffer_object * bufObj )
+{
+ void * new_data;
+
+ (void) ctx; (void) target;
+
+ new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size );
+ if (new_data) {
+ bufObj->Data = (GLubyte *) new_data;
+ bufObj->Size = size;
+ bufObj->Usage = usage;
+
+ if (data) {
+ _mesa_memcpy( bufObj->Data, data, size );
+ }
+
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Replace data in a subrange of buffer object. If the data range
+ * specified by \c size + \c offset extends beyond the end of the buffer or
+ * if \c data is \c NULL, no copy is performed.
+ *
+ * This is the default callback for \c dd_function_table::BufferSubData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx GL context.
+ * \param target Buffer object target on which to operate.
+ * \param offset Offset of the first byte to be modified.
+ * \param size Size, in bytes, of the data range.
+ * \param data Pointer to the data to store in the buffer object.
+ * \param bufObj Object to be used.
+ *
+ * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
+ */
+static void
+_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, const GLvoid * data,
+ struct gl_buffer_object * bufObj )
+{
+ (void) ctx; (void) target;
+
+ /* this should have been caught in _mesa_BufferSubData() */
+ ASSERT(size + offset <= bufObj->Size);
+
+ if (bufObj->Data) {
+ _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size );
+ }
+}
+
+
+/**
+ * Retrieve data from a subrange of buffer object. If the data range
+ * specified by \c size + \c offset extends beyond the end of the buffer or
+ * if \c data is \c NULL, no copy is performed.
+ *
+ * This is the default callback for \c dd_function_table::GetBufferSubData()
+ * Note that all GL error checking will have been done already.
+ *
+ * \param ctx GL context.
+ * \param target Buffer object target on which to operate.
+ * \param offset Offset of the first byte to be fetched.
+ * \param size Size, in bytes, of the data range.
+ * \param data Destination for data
+ * \param bufObj Object to be used.
+ *
+ * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
+ */
+static void
+_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, GLvoid * data,
+ struct gl_buffer_object * bufObj )
+{
+ (void) ctx; (void) target;
+
+ if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
+ _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size );
+ }
+}
+
+
+/**
+ * Default callback for \c dd_function_tabel::MapBuffer().
+ *
+ * The function parameters will have been already tested for errors.
+ *
+ * \param ctx GL context.
+ * \param target Buffer object target on which to operate.
+ * \param access Information about how the buffer will be accessed.
+ * \param bufObj Object to be mapped.
+ * \return A pointer to the object's internal data store that can be accessed
+ * by the processor
+ *
+ * \sa glMapBufferARB, dd_function_table::MapBuffer
+ */
+static void *
+_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *bufObj )
+{
+ (void) ctx;
+ (void) target;
+ (void) access;
+ /* Just return a direct pointer to the data */
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* already mapped! */
+ return NULL;
+ }
+ bufObj->Pointer = bufObj->Data;
+ bufObj->Length = bufObj->Size;
+ bufObj->Offset = 0;
+ return bufObj->Pointer;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::MapBufferRange().
+ * Called via glMapBufferRange().
+ */
+static void *
+_mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset,
+ GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *bufObj )
+{
+ (void) ctx;
+ (void) target;
+ assert(!_mesa_bufferobj_mapped(bufObj));
+ /* Just return a direct pointer to the data */
+ bufObj->Pointer = bufObj->Data + offset;
+ bufObj->Length = length;
+ bufObj->Offset = offset;
+ bufObj->AccessFlags = access;
+ return bufObj->Pointer;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::FlushMappedBufferRange().
+ * Called via glFlushMappedBufferRange().
+ */
+static void
+_mesa_buffer_flush_mapped_range( GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj )
+{
+ (void) ctx;
+ (void) target;
+ (void) offset;
+ (void) length;
+ (void) obj;
+ /* no-op */
+}
+
+
+/**
+ * Default callback for \c dd_function_table::MapBuffer().
+ *
+ * The input parameters will have been already tested for errors.
+ *
+ * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
+ */
+static GLboolean
+_mesa_buffer_unmap( GLcontext *ctx, GLenum target,
+ struct gl_buffer_object *bufObj )
+{
+ (void) ctx;
+ (void) target;
+ /* XXX we might assert here that bufObj->Pointer is non-null */
+ bufObj->Pointer = NULL;
+ bufObj->Length = 0;
+ bufObj->Offset = 0;
+ bufObj->AccessFlags = 0x0;
+ return GL_TRUE;
+}
+
+
+/**
+ * Default fallback for \c dd_function_table::CopyBufferSubData().
+ * Called via glCopyBuffserSubData().
+ */
+static void
+_mesa_copy_buffer_subdata(GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GLubyte *srcPtr, *dstPtr;
+
+ /* buffer should not already be mapped */
+ assert(!_mesa_bufferobj_mapped(src));
+ assert(!_mesa_bufferobj_mapped(dst));
+
+ srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER,
+ GL_READ_ONLY, src);
+ dstPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_WRITE_BUFFER,
+ GL_WRITE_ONLY, dst);
+
+ if (srcPtr && dstPtr)
+ _mesa_memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_COPY_READ_BUFFER, src);
+ ctx->Driver.UnmapBuffer(ctx, GL_COPY_WRITE_BUFFER, dst);
+}
+
+
+
+/**
+ * Initialize the state associated with buffer objects
+ */
+void
+_mesa_init_buffer_objects( GLcontext *ctx )
+{
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
+ ctx->Shared->NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj,
+ ctx->Shared->NullBufferObj);
+
+ _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
+ ctx->Shared->NullBufferObj);
+ _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
+ ctx->Shared->NullBufferObj);
+}
+
+
+/**
+ * Bind the specified target to buffer for the specified context.
+ */
+static void
+bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
+{
+ struct gl_buffer_object *oldBufObj;
+ struct gl_buffer_object *newBufObj = NULL;
+ struct gl_buffer_object **bindTarget = NULL;
+
+ switch (target) {
+ case GL_ARRAY_BUFFER_ARB:
+ bindTarget = &ctx->Array.ArrayBufferObj;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_ARB:
+ bindTarget = &ctx->Array.ElementArrayBufferObj;
+ break;
+ case GL_PIXEL_PACK_BUFFER_EXT:
+ bindTarget = &ctx->Pack.BufferObj;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_EXT:
+ bindTarget = &ctx->Unpack.BufferObj;
+ break;
+ case GL_COPY_READ_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bindTarget = &ctx->CopyReadBuffer;
+ }
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ if (ctx->Extensions.ARB_copy_buffer) {
+ bindTarget = &ctx->CopyWriteBuffer;
+ }
+ break;
+ default:
+ ; /* no-op / we'll hit the follow error test next */
+ }
+
+ if (!bindTarget) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)");
+ return;
+ }
+
+ /* Get pointer to old buffer object (to be unbound) */
+ oldBufObj = get_buffer(ctx, target);
+ if (oldBufObj && oldBufObj->Name == buffer)
+ return; /* rebinding the same buffer object- no change */
+
+ /*
+ * Get pointer to new buffer object (newBufObj)
+ */
+ if (buffer == 0) {
+ /* The spec says there's not a buffer object named 0, but we use
+ * one internally because it simplifies things.
+ */
+ newBufObj = ctx->Shared->NullBufferObj;
+ }
+ else {
+ /* non-default buffer object */
+ newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ if (!newBufObj) {
+ /* if this is a new buffer object id, allocate a buffer object now */
+ ASSERT(ctx->Driver.NewBufferObject);
+ newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
+ if (!newBufObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj);
+ }
+ }
+
+ /* bind new buffer */
+ _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
+
+ /* Pass BindBuffer call to device driver */
+ if (ctx->Driver.BindBuffer)
+ ctx->Driver.BindBuffer( ctx, target, newBufObj );
+}
+
+
+/**
+ * Update the default buffer objects in the given context to reference those
+ * specified in the shared state and release those referencing the old
+ * shared state.
+ */
+void
+_mesa_update_default_objects_buffer_objects(GLcontext *ctx)
+{
+ /* Bind the NullBufferObj to remove references to those
+ * in the shared context hash table.
+ */
+ bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
+ bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
+ bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+}
+
+
+/**
+ * When we're about to read pixel data out of a PBO (via glDrawPixels,
+ * glTexImage, etc) or write data into a PBO (via glReadPixels,
+ * glGetTexImage, etc) we call this function to check that we're not
+ * going to read out of bounds.
+ *
+ * XXX This would also be a convenient time to check that the PBO isn't
+ * currently mapped. Whoever calls this function should check for that.
+ * Remember, we can't use a PBO when it's mapped!
+ *
+ * If we're not using a PBO, this is a no-op.
+ *
+ * \param width width of image to read/write
+ * \param height height of image to read/write
+ * \param depth depth of image to read/write
+ * \param format format of image to read/write
+ * \param type datatype of image to read/write
+ * \param ptr the user-provided pointer/offset
+ * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
+ * go out of bounds.
+ */
+GLboolean
+_mesa_validate_pbo_access(GLuint dimensions,
+ const struct gl_pixelstore_attrib *pack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr)
+{
+ GLvoid *start, *end;
+ const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
+
+ if (!_mesa_is_bufferobj(pack->BufferObj))
+ return GL_TRUE; /* no PBO, OK */
+
+ if (pack->BufferObj->Size == 0)
+ /* no buffer! */
+ return GL_FALSE;
+
+ /* get address of first pixel we'll read */
+ start = _mesa_image_address(dimensions, pack, ptr, width, height,
+ format, type, 0, 0, 0);
+
+ /* get address just past the last pixel we'll read */
+ end = _mesa_image_address(dimensions, pack, ptr, width, height,
+ format, type, depth-1, height-1, width);
+
+
+ sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
+
+ if ((const GLubyte *) start > sizeAddr) {
+ /* This will catch negative values / wrap-around */
+ return GL_FALSE;
+ }
+ if ((const GLubyte *) end > sizeAddr) {
+ /* Image read goes beyond end of buffer */
+ return GL_FALSE;
+ }
+
+ /* OK! */
+ return GL_TRUE;
+}
+
+
+/**
+ * For commands that read from a PBO (glDrawPixels, glTexImage,
+ * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
+ * and return the pointer into the PBO. If we're not reading from a
+ * PBO, return \p src as-is.
+ * If non-null return, must call _mesa_unmap_pbo_source() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+const GLvoid *
+_mesa_map_pbo_source(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *src)
+{
+ const GLubyte *buf;
+
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* unpack from PBO */
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB,
+ unpack->BufferObj);
+ if (!buf)
+ return NULL;
+
+ buf = ADD_POINTERS(buf, src);
+ }
+ else {
+ /* unpack from normal memory */
+ buf = src;
+ }
+
+ return buf;
+}
+
+
+/**
+ * Combine PBO-read validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
+ */
+const GLvoid *
+_mesa_map_validate_pbo_source(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where)
+{
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
+
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
+ }
+
+ ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+ return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_source()
+ */
+void
+_mesa_unmap_pbo_source(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack)
+{
+ ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+ }
+}
+
+
+/**
+ * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
+ * if we're writing to a PBO, map it write-only and return the pointer
+ * into the PBO. If we're not writing to a PBO, return \p dst as-is.
+ * If non-null return, must call _mesa_unmap_pbo_dest() when done.
+ *
+ * \return NULL if error, else pointer to start of data
+ */
+void *
+_mesa_map_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+ void *buf;
+
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
+ /* pack into PBO */
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ pack->BufferObj);
+ if (!buf)
+ return NULL;
+
+ buf = ADD_POINTERS(buf, dest);
+ }
+ else {
+ /* pack to normal memory */
+ buf = dest;
+ }
+
+ return buf;
+}
+
+
+/**
+ * Combine PBO-write validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_dest
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_dest().
+ */
+GLvoid *
+_mesa_map_validate_pbo_dest(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where)
+{
+ ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* non-PBO access: no validation to be done */
+ return ptr;
+ }
+
+ if (!_mesa_validate_pbo_access(dimensions, unpack,
+ width, height, depth, format, type, ptr)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(out of bounds PBO access)", where);
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+ return NULL;
+ }
+
+ ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
+ return ptr;
+}
+
+
+/**
+ * Counterpart to _mesa_map_pbo_dest()
+ */
+void
+_mesa_unmap_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack)
+{
+ ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
+ if (_mesa_is_bufferobj(pack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
+ }
+}
+
+
+
+/**
+ * Return the gl_buffer_object for the given ID.
+ * Always return NULL for ID 0.
+ */
+struct gl_buffer_object *
+_mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer)
+{
+ if (buffer == 0)
+ return NULL;
+ else
+ return (struct gl_buffer_object *)
+ _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
+}
+
+
+/**
+ * If *ptr points to obj, set ptr = the Null/default buffer object.
+ * This is a helper for buffer object deletion.
+ * The GL spec says that deleting a buffer object causes it to get
+ * unbound from all arrays in the current context.
+ */
+static void
+unbind(GLcontext *ctx,
+ struct gl_buffer_object **ptr,
+ struct gl_buffer_object *obj)
+{
+ if (*ptr == obj) {
+ _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
+ }
+}
+
+
+/**
+ * Plug default/fallback buffer object functions into the device
+ * driver hooks.
+ */
+void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver)
+{
+ /* GL_ARB_vertex/pixel_buffer_object */
+ driver->NewBufferObject = _mesa_new_buffer_object;
+ driver->DeleteBuffer = _mesa_delete_buffer_object;
+ driver->BindBuffer = NULL;
+ driver->BufferData = _mesa_buffer_data;
+ driver->BufferSubData = _mesa_buffer_subdata;
+ driver->GetBufferSubData = _mesa_buffer_get_subdata;
+ driver->MapBuffer = _mesa_buffer_map;
+ driver->UnmapBuffer = _mesa_buffer_unmap;
+
+ /* GL_ARB_map_buffer_range */
+ driver->MapBufferRange = _mesa_buffer_map_range;
+ driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
+
+ /* GL_ARB_copy_buffer */
+ driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
+}
+
+
+
+/**********************************************************************/
+/* API Functions */
+/**********************************************************************/
+
+void GLAPIENTRY
+_mesa_BindBufferARB(GLenum target, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ bind_buffer_object(ctx, target, buffer);
+}
+
+
+/**
+ * Delete a set of buffer objects.
+ *
+ * \param n Number of buffer objects to delete.
+ * \param ids Array of \c n buffer object IDs.
+ */
+void GLAPIENTRY
+_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
+ return;
+ }
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ for (i = 0; i < n; i++) {
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
+ if (bufObj) {
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint j;
+
+ ASSERT(bufObj->Name == ids[i]);
+
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* if mapped, unmap it now */
+ ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ bufObj->Pointer = NULL;
+ }
+
+ /* unbind any vertex pointers bound to this buffer */
+ unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Weight.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Normal.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Color.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->Index.BufferObj, bufObj);
+ unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj);
+ for (j = 0; j < Elements(arrayObj->TexCoord); j++) {
+ unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj);
+ }
+ for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) {
+ unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj);
+ }
+
+ if (ctx->Array.ArrayBufferObj == bufObj) {
+ _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
+ }
+ if (ctx->Array.ElementArrayBufferObj == bufObj) {
+ _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
+ }
+
+ /* unbind any pixel pack/unpack pointers bound to this buffer */
+ if (ctx->Pack.BufferObj == bufObj) {
+ _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
+ }
+ if (ctx->Unpack.BufferObj == bufObj) {
+ _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
+ }
+
+ /* The ID is immediately freed for re-use */
+ _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name);
+ _mesa_reference_buffer_object(ctx, &bufObj, NULL);
+ }
+ }
+
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+/**
+ * Generate a set of unique buffer object IDs and store them in \c buffer.
+ *
+ * \param n Number of IDs to generate.
+ * \param buffer Array of \c n locations to store the IDs.
+ */
+void GLAPIENTRY
+_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
+ return;
+ }
+
+ if (!buffer) {
+ return;
+ }
+
+ /*
+ * This must be atomic (generation and allocation of buffer object IDs)
+ */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
+
+ /* Allocate new, empty buffer objects and return identifiers */
+ for (i = 0; i < n; i++) {
+ struct gl_buffer_object *bufObj;
+ GLuint name = first + i;
+ GLenum target = 0;
+ bufObj = ctx->Driver.NewBufferObject( ctx, name, target );
+ if (!bufObj) {
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj);
+ buffer[i] = first + i;
+ }
+
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+/**
+ * Determine if ID is the name of a buffer object.
+ *
+ * \param id ID of the potential buffer object.
+ * \return \c GL_TRUE if \c id is the name of a buffer object,
+ * \c GL_FALSE otherwise.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsBufferARB(GLuint id)
+{
+ struct gl_buffer_object *bufObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ bufObj = _mesa_lookup_bufferobj(ctx, id);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ return bufObj ? GL_TRUE : GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
+ const GLvoid * data, GLenum usage)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (size < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
+ return;
+ }
+
+ switch (usage) {
+ case GL_STREAM_DRAW_ARB:
+ case GL_STREAM_READ_ARB:
+ case GL_STREAM_COPY_ARB:
+ case GL_STATIC_DRAW_ARB:
+ case GL_STATIC_READ_ARB:
+ case GL_STATIC_COPY_ARB:
+ case GL_DYNAMIC_DRAW_ARB:
+ case GL_DYNAMIC_READ_ARB:
+ case GL_DYNAMIC_COPY_ARB:
+ /* OK */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)");
+ return;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
+ return;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" );
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ /* Unmap the existing buffer. We'll replace it now. Not an error. */
+ ctx->Driver.UnmapBuffer(ctx, target, bufObj);
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ ASSERT(bufObj->Pointer == NULL);
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+
+ bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+ _mesa_printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
+ bufObj->Name, size, data, usage);
+#endif
+
+#ifdef BOUNDS_CHECK
+ size += 100;
+#endif
+
+ ASSERT(ctx->Driver.BufferData);
+ if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, const GLvoid * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
+ "glBufferSubDataARB" );
+ if (!bufObj) {
+ /* error already recorded */
+ return;
+ }
+
+ bufObj->Written = GL_TRUE;
+
+ ASSERT(ctx->Driver.BufferSubData);
+ ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, void * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
+ "glGetBufferSubDataARB" );
+ if (!bufObj) {
+ /* error already recorded */
+ return;
+ }
+
+ ASSERT(ctx->Driver.GetBufferSubData);
+ ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj );
+}
+
+
+void * GLAPIENTRY
+_mesa_MapBufferARB(GLenum target, GLenum access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object * bufObj;
+ GLbitfield accessFlags;
+ void *map;
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+ switch (access) {
+ case GL_READ_ONLY_ARB:
+ accessFlags = GL_MAP_READ_BIT;
+ break;
+ case GL_WRITE_ONLY_ARB:
+ accessFlags = GL_MAP_WRITE_BIT;
+ break;
+ case GL_READ_WRITE_ARB:
+ accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
+ return NULL;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" );
+ return NULL;
+ }
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
+ return NULL;
+ }
+
+ ASSERT(ctx->Driver.MapBuffer);
+ map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
+ if (!map) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+ return NULL;
+ }
+ else {
+ /* The driver callback should have set these fields.
+ * This is important because other modules (like VBO) might call
+ * the driver function directly.
+ */
+ ASSERT(bufObj->Pointer == map);
+ ASSERT(bufObj->Length == bufObj->Size);
+ ASSERT(bufObj->Offset == 0);
+ bufObj->AccessFlags = accessFlags;
+ }
+
+ if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+ bufObj->Written = GL_TRUE;
+
+#ifdef VBO_DEBUG
+ _mesa_printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
+ bufObj->Name, bufObj->Size, access);
+ if (access == GL_WRITE_ONLY_ARB) {
+ GLuint i;
+ GLubyte *b = (GLubyte *) bufObj->Pointer;
+ for (i = 0; i < bufObj->Size; i++)
+ b[i] = i & 0xff;
+ }
+#endif
+
+#ifdef BOUNDS_CHECK
+ {
+ GLubyte *buf = (GLubyte *) bufObj->Pointer;
+ GLuint i;
+ /* buffer is 100 bytes larger than requested, fill with magic value */
+ for (i = 0; i < 100; i++) {
+ buf[bufObj->Size - i - 1] = 123;
+ }
+ }
+#endif
+
+ return bufObj->Pointer;
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_UnmapBufferARB(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ GLboolean status = GL_TRUE;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
+ return GL_FALSE;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
+ return GL_FALSE;
+ }
+ if (!_mesa_bufferobj_mapped(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
+ return GL_FALSE;
+ }
+
+#ifdef BOUNDS_CHECK
+ if (bufObj->Access != GL_READ_ONLY_ARB) {
+ GLubyte *buf = (GLubyte *) bufObj->Pointer;
+ GLuint i;
+ /* check that last 100 bytes are still = magic value */
+ for (i = 0; i < 100; i++) {
+ GLuint pos = bufObj->Size - i - 1;
+ if (buf[pos] != 123) {
+ _mesa_warning(ctx, "Out of bounds buffer object write detected"
+ " at position %d (value = %u)\n",
+ pos, buf[pos]);
+ }
+ }
+ }
+#endif
+
+#ifdef VBO_DEBUG
+ if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
+ GLuint i, unchanged = 0;
+ GLubyte *b = (GLubyte *) bufObj->Pointer;
+ GLint pos = -1;
+ /* check which bytes changed */
+ for (i = 0; i < bufObj->Size - 1; i++) {
+ if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
+ unchanged++;
+ if (pos == -1)
+ pos = i;
+ }
+ }
+ if (unchanged) {
+ _mesa_printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
+ bufObj->Name, unchanged, bufObj->Size, pos);
+ }
+ }
+#endif
+
+ status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
+ bufObj->AccessFlags = DEFAULT_ACCESS;
+ ASSERT(bufObj->Pointer == NULL);
+ ASSERT(bufObj->Offset == 0);
+ ASSERT(bufObj->Length == 0);
+
+ return status;
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" );
+ return;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_BUFFER_SIZE_ARB:
+ *params = (GLint) bufObj->Size;
+ break;
+ case GL_BUFFER_USAGE_ARB:
+ *params = bufObj->Usage;
+ break;
+ case GL_BUFFER_ACCESS_ARB:
+ *params = simplified_access_mode(bufObj->AccessFlags);
+ break;
+ case GL_BUFFER_MAPPED_ARB:
+ *params = _mesa_bufferobj_mapped(bufObj);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object * bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (pname != GL_BUFFER_MAP_POINTER_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
+ return;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
+ return;
+ }
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
+ return;
+ }
+
+ *params = bufObj->Pointer;
+}
+
+
+void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *src, *dst;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ src = get_buffer(ctx, readTarget);
+ if (!src || !_mesa_is_bufferobj(src)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyBuffserSubData(readTarget = 0x%x)", readTarget);
+ return;
+ }
+
+ dst = get_buffer(ctx, writeTarget);
+ if (!dst || !_mesa_is_bufferobj(dst)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget);
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(src)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyBuffserSubData(readBuffer is mapped)");
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(dst)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyBuffserSubData(writeBuffer is mapped)");
+ return;
+ }
+
+ if (readOffset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(readOffset = %d)", readOffset);
+ return;
+ }
+
+ if (writeOffset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(writeOffset = %d)", writeOffset);
+ return;
+ }
+
+ if (readOffset + size > src->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(readOffset + size = %d)",
+ readOffset, size);
+ return;
+ }
+
+ if (writeOffset + size > dst->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(writeOffset + size = %d)",
+ writeOffset, size);
+ return;
+ }
+
+ if (src == dst) {
+ if (readOffset + size <= writeOffset) {
+ /* OK */
+ }
+ else if (writeOffset + size <= readOffset) {
+ /* OK */
+ }
+ else {
+ /* overlapping src/dst is illegal */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyBuffserSubData(overlapping src/dst)");
+ return;
+ }
+ }
+
+ ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ void *map;
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(extension not supported)");
+ return NULL;
+ }
+
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset = %ld)", offset);
+ return NULL;
+ }
+
+ if (length < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(length = %ld)", length);
+ return NULL;
+ }
+
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(access indicates neither read or write)");
+ return NULL;
+ }
+
+ if (access & GL_MAP_READ_BIT) {
+ if ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
+ (access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
+ (access & GL_MAP_UNSYNCHRONIZED_BIT)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(invalid access flags)");
+ return NULL;
+ }
+ }
+
+ if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
+ ((access & GL_MAP_WRITE_BIT) == 0)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(invalid access flags)");
+ return NULL;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj || !_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMapBufferRange(target = 0x%x)", target);
+ return NULL;
+ }
+
+ if (offset + length > bufObj->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset + length > size)");
+ return NULL;
+ }
+
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(buffer already mapped)");
+ return NULL;
+ }
+
+ ASSERT(ctx->Driver.MapBufferRange);
+ map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
+ access, bufObj);
+ if (!map) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+ }
+ else {
+ /* The driver callback should have set all these fields.
+ * This is important because other modules (like VBO) might call
+ * the driver function directly.
+ */
+ ASSERT(bufObj->Pointer == map);
+ ASSERT(bufObj->Length == length);
+ ASSERT(bufObj->Offset == offset);
+ ASSERT(bufObj->AccessFlags == access);
+ }
+
+ return map;
+}
+
+
+/**
+ * See GL_ARB_map_buffer_range spec
+ */
+void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_buffer_object *bufObj;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_map_buffer_range) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(extension not supported)");
+ return;
+ }
+
+ if (offset < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset = %ld)", offset);
+ return;
+ }
+
+ if (length < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(length = %ld)", length);
+ return;
+ }
+
+ bufObj = get_buffer(ctx, target);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMapBufferRange(target = 0x%x)", target);
+ return;
+ }
+
+ if (!_mesa_is_bufferobj(bufObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(current buffer is 0)");
+ return;
+ }
+
+ if (!_mesa_bufferobj_mapped(bufObj)) {
+ /* buffer is not mapped */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(buffer is not mapped)");
+ return;
+ }
+
+ if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
+ return;
+ }
+
+ if (offset + length > bufObj->Length) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
+ offset, length, bufObj->Length);
+ return;
+ }
+
+ ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
+
+ if (ctx->Driver.FlushMappedBufferRange)
+ ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj);
+}
diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h
new file mode 100644
index 000000000..9f732ec0c
--- /dev/null
+++ b/mesalib/src/mesa/main/bufferobj.h
@@ -0,0 +1,172 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 BUFFEROBJ_H
+#define BUFFEROBJ_H
+
+
+#include "context.h"
+
+
+/*
+ * Internal functions
+ */
+
+
+/** Is the given buffer object currently mapped? */
+static INLINE GLboolean
+_mesa_bufferobj_mapped(const struct gl_buffer_object *obj)
+{
+ return obj->Pointer != NULL;
+}
+
+/**
+ * Is the given buffer object a user-created buffer object?
+ * Mesa uses default buffer objects in several places. Default buffers
+ * always have Name==0. User created buffers have Name!=0.
+ */
+static INLINE GLboolean
+_mesa_is_bufferobj(const struct gl_buffer_object *obj)
+{
+ return obj->Name != 0;
+}
+
+
+extern void
+_mesa_init_buffer_objects( GLcontext *ctx );
+
+extern void
+_mesa_update_default_objects_buffer_objects(GLcontext *ctx);
+
+
+extern struct gl_buffer_object *
+_mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer);
+
+extern void
+_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
+ GLuint name, GLenum target );
+
+extern void
+_mesa_reference_buffer_object(GLcontext *ctx,
+ struct gl_buffer_object **ptr,
+ struct gl_buffer_object *bufObj);
+
+extern GLboolean
+_mesa_validate_pbo_access(GLuint dimensions,
+ const struct gl_pixelstore_attrib *pack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr);
+
+extern const GLvoid *
+_mesa_map_pbo_source(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *src);
+
+extern const GLvoid *
+_mesa_map_validate_pbo_source(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *ptr,
+ const char *where);
+
+extern void
+_mesa_unmap_pbo_source(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack);
+
+extern void *
+_mesa_map_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest);
+
+extern GLvoid *
+_mesa_map_validate_pbo_dest(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, GLvoid *ptr,
+ const char *where);
+
+extern void
+_mesa_unmap_pbo_dest(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *pack);
+
+
+extern void
+_mesa_init_buffer_object_functions(struct dd_function_table *driver);
+
+
+/*
+ * API functions
+ */
+
+extern void GLAPIENTRY
+_mesa_BindBufferARB(GLenum target, GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_DeleteBuffersARB(GLsizei n, const GLuint * buffer);
+
+extern void GLAPIENTRY
+_mesa_GenBuffersARB(GLsizei n, GLuint * buffer);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsBufferARB(GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
+
+extern void GLAPIENTRY
+_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
+
+extern void GLAPIENTRY
+_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data);
+
+extern void * GLAPIENTRY
+_mesa_MapBufferARB(GLenum target, GLenum access);
+
+extern GLboolean GLAPIENTRY
+_mesa_UnmapBufferARB(GLenum target);
+
+extern void GLAPIENTRY
+_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params);
+
+extern void GLAPIENTRY
+_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size);
+
+extern void * GLAPIENTRY
+_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access);
+
+extern void GLAPIENTRY
+_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+
+#endif
diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c
new file mode 100644
index 000000000..d8b5f3b1f
--- /dev/null
+++ b/mesalib/src/mesa/main/buffers.c
@@ -0,0 +1,502 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file buffers.c
+ * glReadBuffer, DrawBuffer functions.
+ */
+
+
+
+#include "glheader.h"
+#include "buffers.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "fbobject.h"
+#include "state.h"
+
+
+#define BAD_MASK ~0u
+
+
+/**
+ * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are
+ * available to the rendering context (for drawing or reading).
+ * This depends on the type of framebuffer. For window system framebuffers
+ * we look at the framebuffer's visual. But for user-create framebuffers we
+ * look at the number of supported color attachments.
+ * \param fb the framebuffer to draw to, or read from
+ * \return bitmask of BUFFER_BIT_* flags
+ */
+static GLbitfield
+supported_buffer_bitmask(const GLcontext *ctx, const struct gl_framebuffer *fb)
+{
+ GLbitfield mask = 0x0;
+
+ if (fb->Name > 0) {
+ /* A user-created renderbuffer */
+ GLuint i;
+ ASSERT(ctx->Extensions.EXT_framebuffer_object);
+ for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
+ mask |= (BUFFER_BIT_COLOR0 << i);
+ }
+ }
+ else {
+ /* A window system framebuffer */
+ GLint i;
+ mask = BUFFER_BIT_FRONT_LEFT; /* always have this */
+ if (fb->Visual.stereoMode) {
+ mask |= BUFFER_BIT_FRONT_RIGHT;
+ if (fb->Visual.doubleBufferMode) {
+ mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
+ }
+ }
+ else if (fb->Visual.doubleBufferMode) {
+ mask |= BUFFER_BIT_BACK_LEFT;
+ }
+
+ for (i = 0; i < fb->Visual.numAuxBuffers; i++) {
+ mask |= (BUFFER_BIT_AUX0 << i);
+ }
+ }
+
+ return mask;
+}
+
+
+/**
+ * Helper routine used by glDrawBuffer and glDrawBuffersARB.
+ * Given a GLenum naming one or more color buffers (such as
+ * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags.
+ */
+static GLbitfield
+draw_buffer_enum_to_bitmask(GLenum buffer)
+{
+ switch (buffer) {
+ case GL_NONE:
+ return 0;
+ case GL_FRONT:
+ return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT;
+ case GL_BACK:
+ return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT;
+ case GL_RIGHT:
+ return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
+ case GL_FRONT_RIGHT:
+ return BUFFER_BIT_FRONT_RIGHT;
+ case GL_BACK_RIGHT:
+ return BUFFER_BIT_BACK_RIGHT;
+ case GL_BACK_LEFT:
+ return BUFFER_BIT_BACK_LEFT;
+ case GL_FRONT_AND_BACK:
+ return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT
+ | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT;
+ case GL_LEFT:
+ return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT;
+ case GL_FRONT_LEFT:
+ return BUFFER_BIT_FRONT_LEFT;
+ case GL_AUX0:
+ return BUFFER_BIT_AUX0;
+ case GL_AUX1:
+ case GL_AUX2:
+ case GL_AUX3:
+ return 1 << BUFFER_COUNT; /* invalid, but not BAD_MASK */
+ case GL_COLOR_ATTACHMENT0_EXT:
+ return BUFFER_BIT_COLOR0;
+ case GL_COLOR_ATTACHMENT1_EXT:
+ return BUFFER_BIT_COLOR1;
+ case GL_COLOR_ATTACHMENT2_EXT:
+ return BUFFER_BIT_COLOR2;
+ case GL_COLOR_ATTACHMENT3_EXT:
+ return BUFFER_BIT_COLOR3;
+ case GL_COLOR_ATTACHMENT4_EXT:
+ return BUFFER_BIT_COLOR4;
+ case GL_COLOR_ATTACHMENT5_EXT:
+ return BUFFER_BIT_COLOR5;
+ case GL_COLOR_ATTACHMENT6_EXT:
+ return BUFFER_BIT_COLOR6;
+ case GL_COLOR_ATTACHMENT7_EXT:
+ return BUFFER_BIT_COLOR7;
+ default:
+ /* error */
+ return BAD_MASK;
+ }
+}
+
+
+/**
+ * Helper routine used by glReadBuffer.
+ * Given a GLenum naming a color buffer, return the index of the corresponding
+ * renderbuffer (a BUFFER_* value).
+ * return -1 for an invalid buffer.
+ */
+static GLint
+read_buffer_enum_to_index(GLenum buffer)
+{
+ switch (buffer) {
+ case GL_FRONT:
+ return BUFFER_FRONT_LEFT;
+ case GL_BACK:
+ return BUFFER_BACK_LEFT;
+ case GL_RIGHT:
+ return BUFFER_FRONT_RIGHT;
+ case GL_FRONT_RIGHT:
+ return BUFFER_FRONT_RIGHT;
+ case GL_BACK_RIGHT:
+ return BUFFER_BACK_RIGHT;
+ case GL_BACK_LEFT:
+ return BUFFER_BACK_LEFT;
+ case GL_LEFT:
+ return BUFFER_FRONT_LEFT;
+ case GL_FRONT_LEFT:
+ return BUFFER_FRONT_LEFT;
+ case GL_AUX0:
+ return BUFFER_AUX0;
+ case GL_AUX1:
+ case GL_AUX2:
+ case GL_AUX3:
+ return BUFFER_COUNT; /* invalid, but not -1 */
+ case GL_COLOR_ATTACHMENT0_EXT:
+ return BUFFER_COLOR0;
+ case GL_COLOR_ATTACHMENT1_EXT:
+ return BUFFER_COLOR1;
+ case GL_COLOR_ATTACHMENT2_EXT:
+ return BUFFER_COLOR2;
+ case GL_COLOR_ATTACHMENT3_EXT:
+ return BUFFER_COLOR3;
+ case GL_COLOR_ATTACHMENT4_EXT:
+ return BUFFER_COLOR4;
+ case GL_COLOR_ATTACHMENT5_EXT:
+ return BUFFER_COLOR5;
+ case GL_COLOR_ATTACHMENT6_EXT:
+ return BUFFER_COLOR6;
+ case GL_COLOR_ATTACHMENT7_EXT:
+ return BUFFER_COLOR7;
+ default:
+ /* error */
+ return -1;
+ }
+}
+
+
+/**
+ * Called by glDrawBuffer().
+ * Specify which renderbuffer(s) to draw into for the first color output.
+ * <buffer> can name zero, one, two or four renderbuffers!
+ * \sa _mesa_DrawBuffersARB
+ *
+ * \param buffer buffer token such as GL_LEFT or GL_FRONT_AND_BACK, etc.
+ *
+ * Note that the behaviour of this function depends on whether the
+ * current ctx->DrawBuffer is a window-system framebuffer (Name=0) or
+ * a user-created framebuffer object (Name!=0).
+ * In the former case, we update the per-context ctx->Color.DrawBuffer
+ * state var _and_ the FB's ColorDrawBuffer state.
+ * In the later case, we update the FB's ColorDrawBuffer state only.
+ *
+ * Furthermore, upon a MakeCurrent() or BindFramebuffer() call, if the
+ * new FB is a window system FB, we need to re-update the FB's
+ * ColorDrawBuffer state to match the context. This is handled in
+ * _mesa_update_framebuffer().
+ *
+ * See the GL_EXT_framebuffer_object spec for more info.
+ */
+void GLAPIENTRY
+_mesa_DrawBuffer(GLenum buffer)
+{
+ GLbitfield destMask;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+ }
+
+ if (buffer == GL_NONE) {
+ destMask = 0x0;
+ }
+ else {
+ const GLbitfield supportedMask
+ = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ destMask = draw_buffer_enum_to_bitmask(buffer);
+ if (destMask == BAD_MASK) {
+ /* totally bogus buffer */
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer=0x%x)", buffer);
+ return;
+ }
+ destMask &= supportedMask;
+ if (destMask == 0x0) {
+ /* none of the named color buffers exist! */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawBuffer(buffer=0x%x)", buffer);
+ return;
+ }
+ }
+
+ /* if we get here, there's no error so set new state */
+ _mesa_drawbuffers(ctx, 1, &buffer, &destMask);
+
+ /*
+ * Call device driver function.
+ */
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, 1, &buffer);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, buffer);
+}
+
+
+/**
+ * Called by glDrawBuffersARB; specifies the destination color renderbuffers
+ * for N fragment program color outputs.
+ * \sa _mesa_DrawBuffer
+ * \param n number of outputs
+ * \param buffers array [n] of renderbuffer names. Unlike glDrawBuffer, the
+ * names cannot specify more than one buffer. For example,
+ * GL_FRONT_AND_BACK is illegal.
+ */
+void GLAPIENTRY
+_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers)
+{
+ GLint output;
+ GLbitfield usedBufferMask, supportedMask;
+ GLbitfield destMask[MAX_DRAW_BUFFERS];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* Turns out n==0 is a valid input that should not produce an error.
+ * The remaining code below correctly handles the n==0 case.
+ */
+ if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
+ return;
+ }
+
+ supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
+ usedBufferMask = 0x0;
+
+ /* complicated error checking... */
+ for (output = 0; output < n; output++) {
+ if (buffers[output] == GL_NONE) {
+ destMask[output] = 0x0;
+ }
+ else {
+ destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
+ if (destMask[output] == BAD_MASK
+ || _mesa_bitcount(destMask[output]) > 1) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
+ return;
+ }
+ destMask[output] &= supportedMask;
+ if (destMask[output] == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawBuffersARB(unsupported buffer)");
+ return;
+ }
+ if (destMask[output] & usedBufferMask) {
+ /* can't specify a dest buffer more than once! */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawBuffersARB(duplicated buffer)");
+ return;
+ }
+
+ /* update bitmask */
+ usedBufferMask |= destMask[output];
+ }
+ }
+
+ /* OK, if we get here, there were no errors so set the new state */
+ _mesa_drawbuffers(ctx, n, buffers, destMask);
+
+ /*
+ * Call device driver function. Note that n can be equal to 0,
+ * in which case we don't want to reference buffers[0], which
+ * may not be valid.
+ */
+ if (ctx->Driver.DrawBuffers)
+ ctx->Driver.DrawBuffers(ctx, n, buffers);
+ else if (ctx->Driver.DrawBuffer)
+ ctx->Driver.DrawBuffer(ctx, n>0? buffers[0]:GL_NONE);
+}
+
+
+/**
+ * Helper function to set the GL_DRAW_BUFFER state in the context and
+ * current FBO.
+ *
+ * All error checking will have been done prior to calling this function
+ * so nothing should go wrong at this point.
+ *
+ * \param ctx current context
+ * \param n number of color outputs to set
+ * \param buffers array[n] of colorbuffer names, like GL_LEFT.
+ * \param destMask array[n] of BUFFER_BIT_* bitmasks which correspond to the
+ * colorbuffer names. (i.e. GL_FRONT_AND_BACK =>
+ * BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
+ */
+void
+_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
+ const GLbitfield *destMask)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ GLbitfield mask[MAX_DRAW_BUFFERS];
+
+ if (!destMask) {
+ /* compute destMask values now */
+ const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
+ GLuint output;
+ for (output = 0; output < n; output++) {
+ mask[output] = draw_buffer_enum_to_bitmask(buffers[output]);
+ ASSERT(mask[output] != BAD_MASK);
+ mask[output] &= supportedMask;
+ }
+ destMask = mask;
+ }
+
+ if (n == 1) {
+ GLuint buf, count = 0;
+ /* init to -1 to help catch errors */
+ fb->_ColorDrawBufferIndexes[0] = -1;
+ for (buf = 0; buf < BUFFER_COUNT; buf++) {
+ if (destMask[0] & (1 << buf)) {
+ fb->_ColorDrawBufferIndexes[count] = buf;
+ count++;
+ }
+ }
+ fb->ColorDrawBuffer[0] = buffers[0];
+ fb->_NumColorDrawBuffers = count;
+ }
+ else {
+ GLuint buf, count = 0;
+ for (buf = 0; buf < n; buf++ ) {
+ if (destMask[buf]) {
+ fb->_ColorDrawBufferIndexes[buf] = _mesa_ffs(destMask[buf]) - 1;
+ fb->ColorDrawBuffer[buf] = buffers[buf];
+ count = buf + 1;
+ }
+ else {
+ fb->_ColorDrawBufferIndexes[buf] = -1;
+ }
+ }
+ /* set remaining outputs to -1 (GL_NONE) */
+ while (buf < ctx->Const.MaxDrawBuffers) {
+ fb->_ColorDrawBufferIndexes[buf] = -1;
+ fb->ColorDrawBuffer[buf] = GL_NONE;
+ buf++;
+ }
+ fb->_NumColorDrawBuffers = count;
+ }
+
+ if (fb->Name == 0) {
+ /* also set context drawbuffer state */
+ GLuint buf;
+ for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
+ ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
+ }
+ }
+
+ ctx->NewState |= _NEW_BUFFERS;
+}
+
+
+/**
+ * Like \sa _mesa_drawbuffers(), this is a helper function for setting
+ * GL_READ_BUFFER state in the context and current FBO.
+ * \param ctx the rendering context
+ * \param buffer GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc.
+ * \param bufferIndex the numerical index corresponding to 'buffer'
+ */
+void
+_mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex)
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+
+ if (fb->Name == 0) {
+ /* Only update the per-context READ_BUFFER state if we're bound to
+ * a window-system framebuffer.
+ */
+ ctx->Pixel.ReadBuffer = buffer;
+ }
+
+ fb->ColorReadBuffer = buffer;
+ fb->_ColorReadBufferIndex = bufferIndex;
+
+ ctx->NewState |= _NEW_BUFFERS;
+}
+
+
+
+/**
+ * Called by glReadBuffer to set the source renderbuffer for reading pixels.
+ * \param mode color buffer such as GL_FRONT, GL_BACK, etc.
+ */
+void GLAPIENTRY
+_mesa_ReadBuffer(GLenum buffer)
+{
+ struct gl_framebuffer *fb;
+ GLbitfield supportedMask;
+ GLint srcBuffer;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+
+ fb = ctx->ReadBuffer;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer));
+
+ if (fb->Name > 0 && buffer == GL_NONE) {
+ /* This is legal for user-created framebuffer objects */
+ srcBuffer = -1;
+ }
+ else {
+ /* general case / window-system framebuffer */
+ srcBuffer = read_buffer_enum_to_index(buffer);
+ if (srcBuffer == -1) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glReadBuffer(buffer=0x%x)", buffer);
+ return;
+ }
+ supportedMask = supported_buffer_bitmask(ctx, fb);
+ if (((1 << srcBuffer) & supportedMask) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadBuffer(buffer=0x%x)", buffer);
+ return;
+ }
+ }
+
+ /* OK, all error checking has been completed now */
+
+ _mesa_readbuffer(ctx, buffer, srcBuffer);
+ ctx->NewState |= _NEW_BUFFERS;
+
+ /*
+ * Call device driver function.
+ */
+ if (ctx->Driver.ReadBuffer)
+ (*ctx->Driver.ReadBuffer)(ctx, buffer);
+}
diff --git a/mesalib/src/mesa/main/buffers.h b/mesalib/src/mesa/main/buffers.h
new file mode 100644
index 000000000..8a7e7b5c1
--- /dev/null
+++ b/mesalib/src/mesa/main/buffers.h
@@ -0,0 +1,56 @@
+/**
+ * \file buffers.h
+ * Frame buffer management functions declarations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 BUFFERS_H
+#define BUFFERS_H
+
+
+#include "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_DrawBuffer( GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers);
+
+extern void
+_mesa_drawbuffers(GLcontext *ctx, GLuint n, const GLenum *buffers,
+ const GLbitfield *destMask);
+
+extern void
+_mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex);
+
+extern void GLAPIENTRY
+_mesa_ReadBuffer( GLenum mode );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c
new file mode 100644
index 000000000..63388f42e
--- /dev/null
+++ b/mesalib/src/mesa/main/clear.c
@@ -0,0 +1,184 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file clear.c
+ * glClearColor, glClearIndex, glClear() functions.
+ */
+
+
+
+#include "glheader.h"
+#include "clear.h"
+#include "context.h"
+#include "colormac.h"
+#include "state.h"
+
+
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_ClearIndex( GLfloat c )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Color.ClearIndex == (GLuint) c)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.ClearIndex = (GLuint) c;
+
+ if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) {
+ /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */
+ (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex );
+ }
+}
+#endif
+
+
+/**
+ * Specify the clear values for the color buffers.
+ *
+ * \param red red color component.
+ * \param green green color component.
+ * \param blue blue color component.
+ * \param alpha alpha component.
+ *
+ * \sa glClearColor().
+ *
+ * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a
+ * change, flushes the vertices and notifies the driver via the
+ * dd_function_table::ClearColor callback.
+ */
+void GLAPIENTRY
+_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{
+ GLfloat tmp[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ tmp[0] = CLAMP(red, 0.0F, 1.0F);
+ tmp[1] = CLAMP(green, 0.0F, 1.0F);
+ tmp[2] = CLAMP(blue, 0.0F, 1.0F);
+ tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
+
+ if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4V(ctx->Color.ClearColor, tmp);
+
+ if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) {
+ /* it's OK to call glClearColor in CI mode but it should be a NOP */
+ (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
+ }
+}
+
+
+/**
+ * Clear buffers.
+ *
+ * \param mask bit-mask indicating the buffers to be cleared.
+ *
+ * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState
+ * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin,
+ * etc. If the rasterization mode is set to GL_RENDER then requests the driver
+ * to clear the buffers, via the dd_function_table::Clear callback.
+ */
+void GLAPIENTRY
+_mesa_Clear( GLbitfield mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glClear 0x%x\n", mask);
+
+ if (mask & ~(GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT |
+ GL_ACCUM_BUFFER_BIT)) {
+ /* invalid bit set */
+ _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask);
+ return;
+ }
+
+ if (ctx->NewState) {
+ _mesa_update_state( ctx ); /* update _Xmin, etc */
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glClear(incomplete framebuffer)");
+ return;
+ }
+
+ if (ctx->DrawBuffer->Width == 0 || ctx->DrawBuffer->Height == 0 ||
+ ctx->DrawBuffer->_Xmin >= ctx->DrawBuffer->_Xmax ||
+ ctx->DrawBuffer->_Ymin >= ctx->DrawBuffer->_Ymax)
+ return;
+
+ if (ctx->RenderMode == GL_RENDER) {
+ GLbitfield bufferMask;
+
+ /* don't clear depth buffer if depth writing disabled */
+ if (!ctx->Depth.Mask)
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+
+ /* Build the bitmask to send to device driver's Clear function.
+ * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4
+ * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the
+ * BUFFER_BIT_COLORn flags.
+ */
+ bufferMask = 0;
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ GLuint i;
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]);
+ }
+ }
+
+ if ((mask & GL_DEPTH_BUFFER_BIT)
+ && ctx->DrawBuffer->Visual.haveDepthBuffer) {
+ bufferMask |= BUFFER_BIT_DEPTH;
+ }
+
+ if ((mask & GL_STENCIL_BUFFER_BIT)
+ && ctx->DrawBuffer->Visual.haveStencilBuffer) {
+ bufferMask |= BUFFER_BIT_STENCIL;
+ }
+
+ if ((mask & GL_ACCUM_BUFFER_BIT)
+ && ctx->DrawBuffer->Visual.haveAccumBuffer) {
+ bufferMask |= BUFFER_BIT_ACCUM;
+ }
+
+ ASSERT(ctx->Driver.Clear);
+ ctx->Driver.Clear(ctx, bufferMask);
+ }
+}
diff --git a/mesalib/src/mesa/main/clear.h b/mesalib/src/mesa/main/clear.h
new file mode 100644
index 000000000..9a54ba14b
--- /dev/null
+++ b/mesalib/src/mesa/main/clear.h
@@ -0,0 +1,44 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 CLEAR_H
+#define CLEAR_H
+
+
+#include "main/mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_ClearIndex( GLfloat c );
+
+extern void GLAPIENTRY
+_mesa_ClearColor( GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha );
+
+extern void GLAPIENTRY
+_mesa_Clear( GLbitfield mask );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/clip.c b/mesalib/src/mesa/main/clip.c
new file mode 100644
index 000000000..96c80e6ef
--- /dev/null
+++ b/mesalib/src/mesa/main/clip.c
@@ -0,0 +1,159 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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 "glheader.h"
+#include "clip.h"
+#include "context.h"
+#include "macros.h"
+#include "mtypes.h"
+
+#include "math/m_matrix.h"
+
+
+
+/**********************************************************************/
+/* Get/Set User clip-planes. */
+/**********************************************************************/
+
+
+
+void GLAPIENTRY
+_mesa_ClipPlane( GLenum plane, const GLdouble *eq )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint p;
+ GLfloat equation[4];
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+ if (p < 0 || p >= (GLint) ctx->Const.MaxClipPlanes) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glClipPlane" );
+ return;
+ }
+
+ equation[0] = (GLfloat) eq[0];
+ equation[1] = (GLfloat) eq[1];
+ equation[2] = (GLfloat) eq[2];
+ equation[3] = (GLfloat) eq[3];
+
+ /*
+ * 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 (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top))
+ _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+
+ _mesa_transform_vector( equation, equation,
+ ctx->ModelviewMatrixStack.Top->inv );
+
+ if (TEST_EQ_4V(ctx->Transform.EyeUserPlane[p], equation))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ COPY_4FV(ctx->Transform.EyeUserPlane[p], equation);
+
+ /* Update derived state. This state also depends on the projection
+ * matrix, and is recalculated on changes to the projection matrix by
+ * code in _mesa_update_state().
+ */
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+ _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrixStack.Top->inv );
+ }
+
+ if (ctx->Driver.ClipPlane)
+ ctx->Driver.ClipPlane( ctx, plane, equation );
+}
+
+
+void GLAPIENTRY
+_mesa_GetClipPlane( GLenum plane, GLdouble *equation )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint p;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ p = (GLint) (plane - GL_CLIP_PLANE0);
+ if (p < 0 || p >= (GLint) ctx->Const.MaxClipPlanes) {
+ _mesa_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];
+}
+
+void GLAPIENTRY
+_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (cap) {
+ case GL_CULL_VERTEX_EYE_POSITION_EXT:
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ COPY_4FV(ctx->Transform.CullEyePos, v);
+
+ _mesa_transform_vector( ctx->Transform.CullObjPos,
+ ctx->Transform.CullEyePos,
+ ctx->ModelviewMatrixStack.Top->inv );
+ break;
+
+ case GL_CULL_VERTEX_OBJECT_POSITION_EXT:
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ COPY_4FV(ctx->Transform.CullObjPos, v);
+
+ _mesa_transform_vector( ctx->Transform.CullEyePos,
+ ctx->Transform.CullObjPos,
+ ctx->ModelviewMatrixStack.Top->m );
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCullParameterfvEXT" );
+ }
+}
+
+void GLAPIENTRY
+_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v)
+{
+ GLfloat f[4];
+
+ f[0] = (GLfloat)v[0];
+ f[1] = (GLfloat)v[1];
+ f[2] = (GLfloat)v[2];
+ f[3] = (GLfloat)v[3];
+
+ _mesa_CullParameterfvEXT(cap, f);
+}
+
diff --git a/mesalib/src/mesa/main/clip.h b/mesalib/src/mesa/main/clip.h
new file mode 100644
index 000000000..d53afb45b
--- /dev/null
+++ b/mesalib/src/mesa/main/clip.h
@@ -0,0 +1,49 @@
+/**
+ * \file clip.h
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef CLIP_H
+#define CLIP_H
+
+#include "mtypes.h"
+
+extern void GLAPIENTRY
+_mesa_ClipPlane( GLenum plane, const GLdouble *equation );
+
+extern void GLAPIENTRY
+_mesa_GetClipPlane( GLenum plane, GLdouble *equation );
+
+extern void GLAPIENTRY
+_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h
new file mode 100644
index 000000000..815624ee5
--- /dev/null
+++ b/mesalib/src/mesa/main/colormac.h
@@ -0,0 +1,222 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file colormac.h
+ * Color-related macros
+ */
+
+
+#ifndef COLORMAC_H
+#define COLORMAC_H
+
+
+#include "imports.h"
+#include "config.h"
+#include "macros.h"
+
+
+/** \def BYTE_TO_CHAN
+ * Convert from GLbyte to GLchan */
+
+/** \def UBYTE_TO_CHAN
+ * Convert from GLubyte to GLchan */
+
+/** \def SHORT_TO_CHAN
+ * Convert from GLshort to GLchan */
+
+/** \def USHORT_TO_CHAN
+ * Convert from GLushort to GLchan */
+
+/** \def INT_TO_CHAN
+ * Convert from GLint to GLchan */
+
+/** \def UINT_TO_CHAN
+ * Convert from GLuint to GLchan */
+
+/** \def CHAN_TO_UBYTE
+ * Convert from GLchan to GLubyte */
+
+/** \def CHAN_TO_FLOAT
+ * Convert from GLchan to GLfloat */
+
+/** \def CLAMPED_FLOAT_TO_CHAN
+ * Convert from GLclampf to GLchan */
+
+/** \def UNCLAMPED_FLOAT_TO_CHAN
+ * Convert from GLfloat to GLchan */
+
+/** \def COPY_CHAN4
+ * Copy a GLchan[4] array */
+
+#if CHAN_BITS == 8
+
+#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (GLchan) (b))
+#define UBYTE_TO_CHAN(b) (b)
+#define SHORT_TO_CHAN(s) ((s) < 0 ? 0 : (GLchan) ((s) >> 7))
+#define USHORT_TO_CHAN(s) ((GLchan) ((s) >> 8))
+#define INT_TO_CHAN(i) ((i) < 0 ? 0 : (GLchan) ((i) >> 23))
+#define UINT_TO_CHAN(i) ((GLchan) ((i) >> 24))
+
+#define CHAN_TO_UBYTE(c) (c)
+#define CHAN_TO_FLOAT(c) UBYTE_TO_FLOAT(c)
+
+#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_UBYTE(c, f)
+#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_UBYTE(c, f)
+
+#define COPY_CHAN4(DST, SRC) COPY_4UBV(DST, SRC)
+
+#elif CHAN_BITS == 16
+
+#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (((GLchan) (b)) * 516))
+#define UBYTE_TO_CHAN(b) ((((GLchan) (b)) << 8) | ((GLchan) (b)))
+#define SHORT_TO_CHAN(s) ((s) < 0 ? 0 : (GLchan) (s))
+#define USHORT_TO_CHAN(s) (s)
+#define INT_TO_CHAN(i) ((i) < 0 ? 0 : (GLchan) ((i) >> 15))
+#define UINT_TO_CHAN(i) ((GLchan) ((i) >> 16))
+
+#define CHAN_TO_UBYTE(c) ((c) >> 8)
+#define CHAN_TO_FLOAT(c) ((GLfloat) ((c) * (1.0 / CHAN_MAXF)))
+
+#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_USHORT(c, f)
+#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_USHORT(c, f)
+
+#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
+
+#elif CHAN_BITS == 32
+
+/* XXX floating-point color channels not fully thought-out */
+#define BYTE_TO_CHAN(b) ((GLfloat) ((b) * (1.0F / 127.0F)))
+#define UBYTE_TO_CHAN(b) ((GLfloat) ((b) * (1.0F / 255.0F)))
+#define SHORT_TO_CHAN(s) ((GLfloat) ((s) * (1.0F / 32767.0F)))
+#define USHORT_TO_CHAN(s) ((GLfloat) ((s) * (1.0F / 65535.0F)))
+#define INT_TO_CHAN(i) ((GLfloat) ((i) * (1.0F / 2147483647.0F)))
+#define UINT_TO_CHAN(i) ((GLfloat) ((i) * (1.0F / 4294967295.0F)))
+
+#define CHAN_TO_UBYTE(c) FLOAT_TO_UBYTE(c)
+#define CHAN_TO_FLOAT(c) (c)
+
+#define CLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
+#define UNCLAMPED_FLOAT_TO_CHAN(c, f) c = (f)
+
+#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC)
+
+#else
+
+#error unexpected CHAN_BITS size
+
+#endif
+
+
+/**
+ * Convert 3 channels at once.
+ *
+ * \param dst pointer to destination GLchan[3] array.
+ * \param f pointer to source GLfloat[3] array.
+ *
+ * \sa #UNCLAMPED_FLOAT_TO_CHAN.
+ */
+#define UNCLAMPED_FLOAT_TO_RGB_CHAN(dst, f) \
+do { \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[0], f[0]); \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[1], f[1]); \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[2], f[2]); \
+} while (0)
+
+
+/**
+ * Convert 4 channels at once.
+ *
+ * \param dst pointer to destination GLchan[4] array.
+ * \param f pointer to source GLfloat[4] array.
+ *
+ * \sa #UNCLAMPED_FLOAT_TO_CHAN.
+ */
+#define UNCLAMPED_FLOAT_TO_RGBA_CHAN(dst, f) \
+do { \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[0], f[0]); \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[1], f[1]); \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[2], f[2]); \
+ UNCLAMPED_FLOAT_TO_CHAN(dst[3], f[3]); \
+} while (0)
+
+
+
+/**
+ * \name Generic color packing macros. All inputs should be GLubytes.
+ *
+ * \todo We may move these into texstore.h at some point.
+ */
+/*@{*/
+
+#define PACK_COLOR_8888( X, Y, Z, W ) \
+ (((X) << 24) | ((Y) << 16) | ((Z) << 8) | (W))
+
+#define PACK_COLOR_8888_REV( X, Y, Z, W ) \
+ (((W) << 24) | ((Z) << 16) | ((Y) << 8) | (X))
+
+#define PACK_COLOR_888( X, Y, Z ) \
+ (((X) << 16) | ((Y) << 8) | (Z))
+
+#define PACK_COLOR_565( X, Y, Z ) \
+ ((((X) & 0xf8) << 8) | (((Y) & 0xfc) << 3) | (((Z) & 0xf8) >> 3))
+
+#define PACK_COLOR_565_REV( X, Y, Z ) \
+ (((X) & 0xf8) | ((Y) & 0xe0) >> 5 | (((Y) & 0x1c) << 11) | (((Z) & 0xf8) << 5))
+
+#define PACK_COLOR_5551( R, G, B, A ) \
+ ((((R) & 0xf8) << 8) | (((G) & 0xf8) << 3) | (((B) & 0xf8) >> 2) | \
+ ((A) ? 1 : 0))
+
+#define PACK_COLOR_1555( A, B, G, R ) \
+ ((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \
+ ((A) ? 0x8000 : 0))
+
+#define PACK_COLOR_1555_REV( A, B, G, R ) \
+ ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \
+ ((A) ? 0x80 : 0))
+
+#define PACK_COLOR_4444( R, G, B, A ) \
+ ((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4))
+
+#define PACK_COLOR_4444_REV( R, G, B, A ) \
+ ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4))
+
+#define PACK_COLOR_88( L, A ) \
+ (((L) << 8) | (A))
+
+#define PACK_COLOR_88_REV( L, A ) \
+ (((A) << 8) | (L))
+
+#define PACK_COLOR_332( R, G, B ) \
+ (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6))
+
+#define PACK_COLOR_233( B, G, R ) \
+ (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5))
+
+/*@}*/
+
+
+#endif /* COLORMAC_H */
diff --git a/mesalib/src/mesa/main/colortab.c b/mesalib/src/mesa/main/colortab.c
new file mode 100644
index 000000000..5a7de5f20
--- /dev/null
+++ b/mesalib/src/mesa/main/colortab.c
@@ -0,0 +1,1102 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "bufferobj.h"
+#include "colortab.h"
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "state.h"
+#include "teximage.h"
+
+
+/**
+ * Given an internalFormat token passed to glColorTable,
+ * return the corresponding base format.
+ * Return -1 if invalid token.
+ */
+static GLint
+base_colortab_format( GLenum format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ 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 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 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 */
+ }
+}
+
+
+
+/**
+ * Examine table's format and set the component sizes accordingly.
+ */
+static void
+set_component_sizes( struct gl_color_table *table )
+{
+ /* assuming the ubyte table */
+ const GLubyte sz = 8;
+
+ switch (table->_BaseFormat) {
+ case GL_ALPHA:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ case GL_LUMINANCE:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = 0;
+ table->IntensitySize = 0;
+ table->LuminanceSize = sz;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = sz;
+ break;
+ case GL_INTENSITY:
+ table->RedSize = 0;
+ table->GreenSize = 0;
+ table->BlueSize = 0;
+ table->AlphaSize = 0;
+ table->IntensitySize = sz;
+ table->LuminanceSize = 0;
+ break;
+ case GL_RGB:
+ table->RedSize = sz;
+ table->GreenSize = sz;
+ table->BlueSize = sz;
+ table->AlphaSize = 0;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ case GL_RGBA:
+ table->RedSize = sz;
+ table->GreenSize = sz;
+ table->BlueSize = sz;
+ table->AlphaSize = sz;
+ table->IntensitySize = 0;
+ table->LuminanceSize = 0;
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected format in set_component_sizes");
+ }
+}
+
+
+
+/**
+ * Update/replace all or part of a color table. Helper function
+ * used by _mesa_ColorTable() and _mesa_ColorSubTable().
+ * The table->Table buffer should already be allocated.
+ * \param start first entry to update
+ * \param count number of entries to update
+ * \param format format of user-provided table data
+ * \param type datatype of user-provided table data
+ * \param data user-provided table data
+ * \param [rgba]Scale - RGBA scale factors
+ * \param [rgba]Bias - RGBA bias factors
+ */
+static void
+store_colortable_entries(GLcontext *ctx, struct gl_color_table *table,
+ GLsizei start, GLsizei count,
+ GLenum format, GLenum type, const GLvoid *data,
+ GLfloat rScale, GLfloat rBias,
+ GLfloat gScale, GLfloat gBias,
+ GLfloat bScale, GLfloat bBias,
+ GLfloat aScale, GLfloat aBias)
+{
+ data = _mesa_map_validate_pbo_source(ctx,
+ 1, &ctx->Unpack, count, 1, 1,
+ format, type, data,
+ "glColor[Sub]Table");
+ if (!data)
+ return;
+
+ {
+ /* convert user-provided data to GLfloat values */
+ GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4];
+ GLfloat *tableF;
+ GLint i;
+
+ _mesa_unpack_color_span_float(ctx,
+ count, /* number of pixels */
+ table->_BaseFormat, /* dest format */
+ tempTab, /* dest address */
+ format, type, /* src format/type */
+ data, /* src data */
+ &ctx->Unpack,
+ IMAGE_CLAMP_BIT); /* transfer ops */
+
+ /* the destination */
+ tableF = table->TableF;
+
+ /* Apply scale & bias & clamp now */
+ switch (table->_BaseFormat) {
+ case GL_INTENSITY:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_LUMINANCE:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_ALPHA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_RGB:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F);
+ tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F);
+ }
+ break;
+ case GL_RGBA:
+ for (i = 0; i < count; i++) {
+ GLuint j = start + i;
+ tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F);
+ tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F);
+ tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F);
+ tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad format in store_colortable_entries");
+ return;
+ }
+ }
+
+ /* update the ubyte table */
+ {
+ const GLint comps = _mesa_components_in_format(table->_BaseFormat);
+ const GLfloat *tableF = table->TableF + start * comps;
+ GLubyte *tableUB = table->TableUB + start * comps;
+ GLint i;
+ for (i = 0; i < count * comps; i++) {
+ CLAMPED_FLOAT_TO_UBYTE(tableUB[i], tableF[i]);
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorTable( GLenum target, GLenum internalFormat,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid *data )
+{
+ static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj = NULL;
+ struct gl_color_table *table = NULL;
+ GLboolean proxy = GL_FALSE;
+ GLint baseFormat;
+ const GLfloat *scale = one, *bias = zero;
+ GLint comps;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ case GL_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_PROXY_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
+ proxy = GL_TRUE;
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
+ return;
+ }
+ table = &(texUnit->ColorTable);
+ scale = ctx->Pixel.TextureColorTableScale;
+ bias = ctx->Pixel.TextureColorTableBias;
+ break;
+ case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
+ return;
+ }
+ table = &(texUnit->ProxyColorTable);
+ proxy = GL_TRUE;
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
+ proxy = GL_TRUE;
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
+ proxy = GL_TRUE;
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ proxy = _mesa_is_proxy_texture(target);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
+ format == GL_INTENSITY) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)");
+ return;
+ }
+
+ baseFormat = base_colortab_format(internalFormat);
+ if (baseFormat < 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || (width != 0 && !_mesa_is_pow_two(width))) {
+ /* error */
+ if (proxy) {
+ table->Size = 0;
+ table->InternalFormat = (GLenum) 0;
+ table->_BaseFormat = (GLenum) 0;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width);
+ }
+ return;
+ }
+
+ if (width > (GLsizei) ctx->Const.MaxColorTableSize) {
+ if (proxy) {
+ table->Size = 0;
+ table->InternalFormat = (GLenum) 0;
+ table->_BaseFormat = (GLenum) 0;
+ }
+ else {
+ _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)");
+ }
+ return;
+ }
+
+ table->Size = width;
+ table->InternalFormat = internalFormat;
+ table->_BaseFormat = (GLenum) baseFormat;
+
+ comps = _mesa_components_in_format(table->_BaseFormat);
+ assert(comps > 0); /* error should have been caught sooner */
+
+ if (!proxy) {
+ _mesa_free_colortable_data(table);
+
+ if (width > 0) {
+ table->TableF = (GLfloat *) _mesa_malloc(comps * width * sizeof(GLfloat));
+ table->TableUB = (GLubyte *) _mesa_malloc(comps * width * sizeof(GLubyte));
+
+ if (!table->TableF || !table->TableUB) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable");
+ return;
+ }
+
+ store_colortable_entries(ctx, table,
+ 0, width, /* start, count */
+ format, type, data,
+ scale[0], bias[0],
+ scale[1], bias[1],
+ scale[2], bias[2],
+ scale[3], bias[3]);
+ }
+ } /* proxy */
+
+ /* do this after the table's Type and Format are set */
+ set_component_sizes(table);
+
+ if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
+ /* texture object palette, texObj==NULL means the shared palette */
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
+ }
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorSubTable( GLenum target, GLsizei start,
+ GLsizei count, GLenum format, GLenum type,
+ const GLvoid *data )
+{
+ static const GLfloat one[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static const GLfloat zero[4] = { 0.0, 0.0, 0.0, 0.0 };
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj = NULL;
+ struct gl_color_table *table = NULL;
+ const GLfloat *scale = one, *bias = zero;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ case GL_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
+ return;
+ }
+ table = &(texUnit->ColorTable);
+ scale = ctx->Pixel.TextureColorTableScale;
+ bias = ctx->Pixel.TextureColorTableBias;
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ default:
+ /* try texture targets */
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texObj && !_mesa_is_proxy_texture(target)) {
+ table = &texObj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)");
+ return;
+ }
+ }
+
+ assert(table);
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type) ||
+ format == GL_INTENSITY) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)");
+ return;
+ }
+
+ if (count < 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
+ return;
+ }
+
+ /* error should have been caught sooner */
+ assert(_mesa_components_in_format(table->_BaseFormat) > 0);
+
+ if (start + count > (GLint) table->Size) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)");
+ return;
+ }
+
+ if (!table->TableF || !table->TableUB) {
+ /* a GL_OUT_OF_MEMORY error would have been recorded previously */
+ return;
+ }
+
+ store_colortable_entries(ctx, table, start, count,
+ format, type, data,
+ scale[0], bias[0],
+ scale[1], bias[1],
+ scale[2], bias[2],
+ scale[3], bias[3]);
+
+ if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) {
+ /* per-texture object palette */
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
+ }
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyColorTable(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* Select buffer to read from */
+ ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width );
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyColorSubTable(GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width );
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetColorTable( GLenum target, GLenum format,
+ GLenum type, GLvoid *data )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_color_table *table = NULL;
+ GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ case GL_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
+ return;
+ }
+ table = &(texUnit->ColorTable);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj && !_mesa_is_proxy_texture(target)) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)");
+ return;
+ }
+ }
+ }
+
+ ASSERT(table);
+
+ if (table->Size <= 0) {
+ return;
+ }
+
+ switch (table->_BaseFormat) {
+ case GL_ALPHA:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] = 0;
+ rgba[i][GCOMP] = 0;
+ rgba[i][BCOMP] = 0;
+ rgba[i][ACOMP] = table->TableF[i];
+ }
+ }
+ break;
+ case GL_LUMINANCE:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = table->TableF[i];
+ rgba[i][ACOMP] = 1.0F;
+ }
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = table->TableF[i*2+0];
+ rgba[i][ACOMP] = table->TableF[i*2+1];
+ }
+ }
+ break;
+ case GL_INTENSITY:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] =
+ rgba[i][ACOMP] = table->TableF[i];
+ }
+ }
+ break;
+ case GL_RGB:
+ {
+ GLuint i;
+ for (i = 0; i < table->Size; i++) {
+ rgba[i][RCOMP] = table->TableF[i*3+0];
+ rgba[i][GCOMP] = table->TableF[i*3+1];
+ rgba[i][BCOMP] = table->TableF[i*3+2];
+ rgba[i][ACOMP] = 1.0F;
+ }
+ }
+ break;
+ case GL_RGBA:
+ _mesa_memcpy(rgba, table->TableF, 4 * table->Size * sizeof(GLfloat));
+ break;
+ default:
+ _mesa_problem(ctx, "bad table format in glGetColorTable");
+ return;
+ }
+
+ data = _mesa_map_validate_pbo_dest(ctx,
+ 1, &ctx->Pack, table->Size, 1, 1,
+ format, type, data,
+ "glGetColorTable");
+ if (!data)
+ return;
+
+ _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
+ format, type, data, &ctx->Pack, 0x0);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ GLfloat *scale, *bias;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_COLOR_TABLE_SGI:
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ scale = ctx->Pixel.TextureColorTableScale;
+ bias = ctx->Pixel.TextureColorTableBias;
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+ bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameter(target)");
+ return;
+ }
+
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ COPY_4V(scale, params);
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ COPY_4V(bias, params);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)");
+ return;
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GLfloat fparams[4];
+ if (pname == GL_COLOR_TABLE_SGI ||
+ pname == GL_TEXTURE_COLOR_TABLE_SGI ||
+ pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
+ pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI) {
+ /* four values */
+ fparams[0] = (GLfloat) params[0];
+ fparams[1] = (GLfloat) params[1];
+ fparams[2] = (GLfloat) params[2];
+ fparams[3] = (GLfloat) params[3];
+ }
+ else {
+ /* one values */
+ fparams[0] = (GLfloat) params[0];
+ }
+ _mesa_ColorTableParameterfv(target, pname, fparams);
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_color_table *table = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ case GL_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION]);
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION]);
+ return;
+ }
+ break;
+ case GL_PROXY_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
+ return;
+ }
+ table = &(texUnit->ColorTable);
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ COPY_4V(params, ctx->Pixel.TextureColorTableScale);
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ COPY_4V(params, ctx->Pixel.TextureColorTableBias);
+ return;
+ }
+ break;
+ case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
+ return;
+ }
+ table = &(texUnit->ProxyColorTable);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION]);
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION]);
+ return;
+ }
+ break;
+ case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX]);
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ COPY_4V(params, ctx->Pixel.ColorTableBias[COLORTABLE_POSTCOLORMATRIX]);
+ return;
+ }
+ break;
+ case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ default:
+ /* try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetColorTableParameterfv(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ switch (pname) {
+ case GL_COLOR_TABLE_FORMAT:
+ *params = (GLfloat) table->InternalFormat;
+ break;
+ case GL_COLOR_TABLE_WIDTH:
+ *params = (GLfloat) table->Size;
+ break;
+ case GL_COLOR_TABLE_RED_SIZE:
+ *params = (GLfloat) table->RedSize;
+ break;
+ case GL_COLOR_TABLE_GREEN_SIZE:
+ *params = (GLfloat) table->GreenSize;
+ break;
+ case GL_COLOR_TABLE_BLUE_SIZE:
+ *params = (GLfloat) table->BlueSize;
+ break;
+ case GL_COLOR_TABLE_ALPHA_SIZE:
+ *params = (GLfloat) table->AlphaSize;
+ break;
+ case GL_COLOR_TABLE_LUMINANCE_SIZE:
+ *params = (GLfloat) table->LuminanceSize;
+ break;
+ case GL_COLOR_TABLE_INTENSITY_SIZE:
+ *params = (GLfloat) table->IntensitySize;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" );
+ return;
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_color_table *table = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ table = &ctx->Texture.Palette;
+ break;
+ case GL_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_PRECONVOLUTION];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_PRECONVOLUTION];
+ params[0] = (GLint) scale[0];
+ params[1] = (GLint) scale[1];
+ params[2] = (GLint) scale[2];
+ params[3] = (GLint) scale[3];
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_PRECONVOLUTION];
+ params[0] = (GLint) bias[0];
+ params[1] = (GLint) bias[1];
+ params[2] = (GLint) bias[2];
+ params[3] = (GLint) bias[3];
+ return;
+ }
+ break;
+ case GL_PROXY_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
+ return;
+ }
+ table = &(texUnit->ColorTable);
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ params[0] = (GLint) ctx->Pixel.TextureColorTableScale[0];
+ params[1] = (GLint) ctx->Pixel.TextureColorTableScale[1];
+ params[2] = (GLint) ctx->Pixel.TextureColorTableScale[2];
+ params[3] = (GLint) ctx->Pixel.TextureColorTableScale[3];
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ params[0] = (GLint) ctx->Pixel.TextureColorTableBias[0];
+ params[1] = (GLint) ctx->Pixel.TextureColorTableBias[1];
+ params[2] = (GLint) ctx->Pixel.TextureColorTableBias[2];
+ params[3] = (GLint) ctx->Pixel.TextureColorTableBias[3];
+ return;
+ }
+ break;
+ case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
+ if (!ctx->Extensions.SGI_texture_color_table) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
+ return;
+ }
+ table = &(texUnit->ProxyColorTable);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCONVOLUTION];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCONVOLUTION];
+ params[0] = (GLint) scale[0];
+ params[1] = (GLint) scale[1];
+ params[2] = (GLint) scale[2];
+ params[3] = (GLint) scale[3];
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ GLfloat *bias = ctx->Pixel.ColorTableBias[COLORTABLE_POSTCONVOLUTION];
+ params[0] = (GLint) bias[0];
+ params[1] = (GLint) bias[1];
+ params[2] = (GLint) bias[2];
+ params[3] = (GLint) bias[3];
+ return;
+ }
+ break;
+ case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX];
+ if (pname == GL_COLOR_TABLE_SCALE_SGI) {
+ GLfloat *scale = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+ params[0] = (GLint) scale[0];
+ params[0] = (GLint) scale[1];
+ params[0] = (GLint) scale[2];
+ params[0] = (GLint) scale[3];
+ return;
+ }
+ else if (pname == GL_COLOR_TABLE_BIAS_SGI) {
+ GLfloat *bias = ctx->Pixel.ColorTableScale[COLORTABLE_POSTCOLORMATRIX];
+ params[0] = (GLint) bias[0];
+ params[1] = (GLint) bias[1];
+ params[2] = (GLint) bias[2];
+ params[3] = (GLint) bias[3];
+ return;
+ }
+ break;
+ case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
+ table = &ctx->ProxyColorTable[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ default:
+ /* Try texture targets */
+ {
+ struct gl_texture_object *texobj
+ = _mesa_select_tex_object(ctx, texUnit, target);
+ if (texobj) {
+ table = &texobj->Palette;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetColorTableParameteriv(target)");
+ return;
+ }
+ }
+ }
+
+ assert(table);
+
+ switch (pname) {
+ case GL_COLOR_TABLE_FORMAT:
+ *params = table->InternalFormat;
+ break;
+ case GL_COLOR_TABLE_WIDTH:
+ *params = table->Size;
+ break;
+ case GL_COLOR_TABLE_RED_SIZE:
+ *params = table->RedSize;
+ break;
+ case GL_COLOR_TABLE_GREEN_SIZE:
+ *params = table->GreenSize;
+ break;
+ case GL_COLOR_TABLE_BLUE_SIZE:
+ *params = table->BlueSize;
+ break;
+ case GL_COLOR_TABLE_ALPHA_SIZE:
+ *params = table->AlphaSize;
+ break;
+ case GL_COLOR_TABLE_LUMINANCE_SIZE:
+ *params = table->LuminanceSize;
+ break;
+ case GL_COLOR_TABLE_INTENSITY_SIZE:
+ *params = table->IntensitySize;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" );
+ return;
+ }
+}
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+
+void
+_mesa_init_colortable( struct gl_color_table *p )
+{
+ p->TableF = NULL;
+ p->TableUB = NULL;
+ p->Size = 0;
+ p->InternalFormat = GL_RGBA;
+}
+
+
+
+void
+_mesa_free_colortable_data( struct gl_color_table *p )
+{
+ if (p->TableF) {
+ _mesa_free(p->TableF);
+ p->TableF = NULL;
+ }
+ if (p->TableUB) {
+ _mesa_free(p->TableUB);
+ p->TableUB = NULL;
+ }
+}
+
+
+/*
+ * Initialize all colortables for a context.
+ */
+void
+_mesa_init_colortables( GLcontext * ctx )
+{
+ GLuint i;
+ for (i = 0; i < COLORTABLE_MAX; i++) {
+ _mesa_init_colortable(&ctx->ColorTable[i]);
+ _mesa_init_colortable(&ctx->ProxyColorTable[i]);
+ }
+}
+
+
+/*
+ * Free all colortable data for a context
+ */
+void
+_mesa_free_colortables_data( GLcontext *ctx )
+{
+ GLuint i;
+ for (i = 0; i < COLORTABLE_MAX; i++) {
+ _mesa_free_colortable_data(&ctx->ColorTable[i]);
+ _mesa_free_colortable_data(&ctx->ProxyColorTable[i]);
+ }
+}
diff --git a/mesalib/src/mesa/main/colortab.h b/mesalib/src/mesa/main/colortab.h
new file mode 100644
index 000000000..b6ff737a6
--- /dev/null
+++ b/mesalib/src/mesa/main/colortab.h
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_ColorTable( GLenum target, GLenum internalformat,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid *table );
+
+extern void GLAPIENTRY
+_mesa_ColorSubTable( GLenum target, GLsizei start,
+ GLsizei count, GLenum format, GLenum type,
+ const GLvoid *table );
+
+extern void GLAPIENTRY
+_mesa_CopyColorSubTable(GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width);
+
+extern void GLAPIENTRY
+_mesa_CopyColorTable(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width);
+
+extern void GLAPIENTRY
+_mesa_GetColorTable( GLenum target, GLenum format,
+ GLenum type, GLvoid *table );
+
+extern void GLAPIENTRY
+_mesa_ColorTableParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_ColorTableParameteriv(GLenum target, GLenum pname,
+ const GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params );
+
+
+
+extern void
+_mesa_init_colortable( struct gl_color_table *table );
+
+extern void
+_mesa_free_colortable_data( struct gl_color_table *table );
+
+extern void
+_mesa_init_colortables( GLcontext *ctx );
+
+extern void
+_mesa_free_colortables_data( GLcontext *ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_colortable( p ) ((void) 0)
+
+/** No-op */
+#define _mesa_free_colortable_data( p ) ((void) 0)
+
+/** No-op */
+#define _mesa_init_colortables( p ) ((void)0)
+
+/** No-op */
+#define _mesa_free_colortables_data( p ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h
new file mode 100644
index 000000000..9319505a7
--- /dev/null
+++ b/mesalib/src/mesa/main/compiler.h
@@ -0,0 +1,484 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file compiler.h
+ * Compiler-related stuff.
+ */
+
+
+#ifndef COMPILER_H
+#define COMPILER_H
+
+
+#include <assert.h>
+#include <ctype.h>
+#if defined(__alpha__) && defined(CCPML)
+#include <cpml.h> /* use Compaq's Fast Math Library on Alpha */
+#else
+#include <math.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if defined(__linux__) && defined(__i386__)
+#include <fpu_control.h>
+#endif
+#include <float.h>
+#include <stdarg.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Get standard integer types
+ */
+#if defined(_MSC_VER)
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int16 uint16_t;
+# ifndef __eglplatform_h_
+ typedef __int32 int32_t;
+# endif
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+
+# if defined(_WIN64)
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+# else
+ typedef __int32 intptr_t;
+ typedef unsigned __int32 uintptr_t;
+# endif
+
+# define INT64_C(__val) __val##i64
+# define UINT64_C(__val) __val##ui64
+#else
+# include <stdint.h>
+#endif
+
+
+/**
+ * Sun compilers define __i386 instead of the gcc-style __i386__
+ */
+#ifdef __SUNPRO_C
+# if !defined(__i386__) && defined(__i386)
+# define __i386__
+# elif !defined(__amd64__) && defined(__amd64)
+# define __amd64__
+# elif !defined(__sparc__) && defined(__sparc)
+# define __sparc__
+# endif
+# if !defined(__volatile)
+# define __volatile volatile
+# endif
+#endif
+
+
+/**
+ * finite macro.
+ */
+#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(BUILD_FOR_SNAP)
+# define __WIN32__
+# define finite _finite
+#elif defined(__WATCOMC__)
+# define finite _finite
+#endif
+
+
+/**
+ * Disable assorted warnings
+ */
+#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP)
+# if !defined(__GNUC__) /* mingw environment */
+# pragma warning( disable : 4068 ) /* unknown pragma */
+# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
+# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
+# pragma warning( disable : 4127 ) /* conditional expression is constant */
+# if defined(MESA_MINWARN)
+# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
+# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
+# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
+# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
+# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
+# endif
+# endif
+#endif
+#if defined(__WATCOMC__)
+# pragma disable_message(201) /* Disable unreachable code warnings */
+#endif
+
+
+
+/**
+ * Function inlining
+ */
+#if defined(__GNUC__)
+# define INLINE __inline__
+#elif defined(__MSC__)
+# define INLINE __inline
+#elif defined(_MSC_VER)
+# define INLINE __inline
+#elif defined(__ICL)
+# define INLINE __inline
+#elif defined(__INTEL_COMPILER)
+# define INLINE inline
+#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
+# define INLINE __inline
+#elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
+# define INLINE inline
+# define __inline inline
+# define __inline__ inline
+#elif (__STDC_VERSION__ >= 199901L) /* C99 */
+# define INLINE inline
+#else
+# define INLINE
+#endif
+
+
+/**
+ * PUBLIC/USED macros
+ *
+ * If we build the library with gcc's -fvisibility=hidden flag, we'll
+ * use the PUBLIC macro to mark functions that are to be exported.
+ *
+ * We also need to define a USED attribute, so the optimizer doesn't
+ * inline a static function that we later use in an alias. - ajax
+ */
+#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
+# define PUBLIC __attribute__((visibility("default")))
+# define USED __attribute__((used))
+#else
+# define PUBLIC
+# define USED
+#endif
+
+
+/**
+ * Some compilers don't like some of Mesa's const usage. In those places use
+ * CONST instead of const. Pass -DNO_CONST to compilers where this matters.
+ */
+#ifdef NO_CONST
+# define CONST
+#else
+# define CONST const
+#endif
+
+
+/**
+ * __builtin_expect macros
+ */
+#if (!defined(__GNUC__) || __GNUC__ < 3) && (!defined(__IBMC__) || __IBMC__ < 900)
+# define __builtin_expect(x, y) x
+#endif
+
+
+/**
+ * The __FUNCTION__ gcc variable is generally only used for debugging.
+ * If we're not using gcc, define __FUNCTION__ as a cpp symbol here.
+ * Don't define it if using a newer Windows compiler.
+ */
+#ifndef __FUNCTION__
+# if defined(__VMS)
+# define __FUNCTION__ "VMS$NL:"
+# elif ((!defined __GNUC__) || (__GNUC__ < 2)) && (!defined __xlC__) && \
+ (!defined(_MSC_VER) || _MSC_VER < 1300)
+# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \
+ (defined(__SUNPRO_C) && defined(__C99FEATURES__))
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ "<unknown>"
+# endif
+# endif
+#endif
+
+
+/**
+ * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN.
+ * Do not use them unless absolutely necessary!
+ * Try to use a runtime test instead.
+ * For now, only used by some DRI hardware drivers for color/texel packing.
+ */
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+#if defined(__linux__)
+#include <byteswap.h>
+#define CPU_TO_LE32( x ) bswap_32( x )
+#elif defined(__APPLE__)
+#include <CoreFoundation/CFByteOrder.h>
+#define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x )
+#else /*__linux__ __APPLE__*/
+#include <sys/endian.h>
+#define CPU_TO_LE32( x ) bswap32( x )
+#endif /*__linux__*/
+#define MESA_BIG_ENDIAN 1
+#else
+#define CPU_TO_LE32( x ) ( x )
+#define MESA_LITTLE_ENDIAN 1
+#endif
+#define LE32_TO_CPU( x ) CPU_TO_LE32( x )
+
+
+
+#if !defined(CAPI) && defined(WIN32) && !defined(BUILD_FOR_SNAP)
+#define CAPI _cdecl
+#endif
+
+
+/**
+ * Create a macro so that asm functions can be linked into compilers other
+ * than GNU C
+ */
+#ifndef _ASMAPI
+#if defined(WIN32) && !defined(BUILD_FOR_SNAP)/* was: !defined( __GNUC__ ) && !defined( VMS ) && !defined( __INTEL_COMPILER )*/
+#define _ASMAPI __cdecl
+#else
+#define _ASMAPI
+#endif
+#ifdef PTR_DECL_IN_FRONT
+#define _ASMAPIP * _ASMAPI
+#else
+#define _ASMAPIP _ASMAPI *
+#endif
+#endif
+
+#ifdef USE_X86_ASM
+#define _NORMAPI _ASMAPI
+#define _NORMAPIP _ASMAPIP
+#else
+#define _NORMAPI
+#define _NORMAPIP *
+#endif
+
+
+/* This is a macro on IRIX */
+#ifdef _P
+#undef _P
+#endif
+
+
+/* Turn off macro checking systems used by other libraries */
+#ifdef CHECK
+#undef CHECK
+#endif
+
+
+/**
+ * ASSERT macro
+ */
+#if !defined(_WIN32_WCE)
+#if defined(BUILD_FOR_SNAP) && defined(CHECKED)
+# define ASSERT(X) _CHECK(X)
+#elif defined(DEBUG)
+# define ASSERT(X) assert(X)
+#else
+# define ASSERT(X)
+#endif
+#endif
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/**
+ * LONGSTRING macro
+ * gcc -pedantic warns about long string literals, LONGSTRING silences that.
+ */
+#if !defined(__GNUC__) || (__GNUC__ < 2) || \
+ ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
+# define LONGSTRING
+#else
+# define LONGSTRING __extension__
+#endif
+
+
+#ifndef M_PI
+#define M_PI (3.1415926536)
+#endif
+
+#ifndef M_E
+#define M_E (2.7182818284590452354)
+#endif
+
+#ifndef ONE_DIV_LN2
+#define ONE_DIV_LN2 (1.442695040888963456)
+#endif
+
+#ifndef ONE_DIV_SQRT_LN2
+#define ONE_DIV_SQRT_LN2 (1.201122408786449815)
+#endif
+
+#ifndef FLT_MAX_EXP
+#define FLT_MAX_EXP 128
+#endif
+
+
+/**
+ * USE_IEEE: Determine if we're using IEEE floating point
+ */
+#if defined(__i386__) || defined(__386__) || defined(__sparc__) || \
+ defined(__s390x__) || defined(__powerpc__) || \
+ defined(__x86_64__) || \
+ defined(ia64) || defined(__ia64__) || \
+ defined(__hppa__) || defined(hpux) || \
+ defined(__mips) || defined(_MIPS_ARCH) || \
+ defined(__arm__) || \
+ defined(__sh__) || defined(__m32r__) || \
+ (defined(__sun) && defined(_IEEE_754)) || \
+ (defined(__alpha__) && (defined(__IEEE_FLOAT) || !defined(VMS)))
+#define USE_IEEE
+#define IEEE_ONE 0x3f800000
+#endif
+
+
+/**
+ * START/END_FAST_MATH macros:
+ *
+ * START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
+ * original mode to a temporary).
+ * END_FAST_MATH: Restore x86 FPU to original mode.
+ */
+#if defined(__GNUC__) && defined(__i386__)
+/*
+ * Set the x86 FPU control word to guarentee only 32 bits of precision
+ * are stored in registers. Allowing the FPU to store more introduces
+ * differences between situations where numbers are pulled out of memory
+ * vs. situations where the compiler is able to optimize register usage.
+ *
+ * In the worst case, we force the compiler to use a memory access to
+ * truncate the float, by specifying the 'volatile' keyword.
+ */
+/* Hardware default: All exceptions masked, extended double precision,
+ * round to nearest (IEEE compliant):
+ */
+#define DEFAULT_X86_FPU 0x037f
+/* All exceptions masked, single precision, round to nearest:
+ */
+#define FAST_X86_FPU 0x003f
+/* The fldcw instruction will cause any pending FP exceptions to be
+ * raised prior to entering the block, and we clear any pending
+ * exceptions before exiting the block. Hence, asm code has free
+ * reign over the FPU while in the fast math block.
+ */
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) \
+do { \
+ static GLuint mask = DEFAULT_X86_FPU; \
+ __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
+ __asm__ ( "fldcw %0" : : "m" (mask) ); \
+} while (0)
+#else
+#define START_FAST_MATH(x) \
+do { \
+ static GLuint mask = FAST_X86_FPU; \
+ __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
+ __asm__ ( "fldcw %0" : : "m" (mask) ); \
+} while (0)
+#endif
+/* Restore original FPU mode, and clear any exceptions that may have
+ * occurred in the FAST_MATH block.
+ */
+#define END_FAST_MATH(x) \
+do { \
+ __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
+} while (0)
+
+#elif defined(__WATCOMC__) && defined(__386__)
+#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
+#define FAST_X86_FPU 0x003f /* See GCC comments above */
+void _watcom_start_fast_math(unsigned short *x,unsigned short *mask);
+#pragma aux _watcom_start_fast_math = \
+ "fnstcw word ptr [eax]" \
+ "fldcw word ptr [ecx]" \
+ parm [eax] [ecx] \
+ modify exact [];
+void _watcom_end_fast_math(unsigned short *x);
+#pragma aux _watcom_end_fast_math = \
+ "fnclex" \
+ "fldcw word ptr [eax]" \
+ parm [eax] \
+ modify exact [];
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) \
+do { \
+ static GLushort mask = DEFAULT_X86_FPU; \
+ _watcom_start_fast_math(&x,&mask); \
+} while (0)
+#else
+#define START_FAST_MATH(x) \
+do { \
+ static GLushort mask = FAST_X86_FPU; \
+ _watcom_start_fast_math(&x,&mask); \
+} while (0)
+#endif
+#define END_FAST_MATH(x) _watcom_end_fast_math(&x)
+
+#elif defined(_MSC_VER) && defined(_M_IX86)
+#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
+#define FAST_X86_FPU 0x003f /* See GCC comments above */
+#if defined(NO_FAST_MATH)
+#define START_FAST_MATH(x) do {\
+ static GLuint mask = DEFAULT_X86_FPU;\
+ __asm fnstcw word ptr [x]\
+ __asm fldcw word ptr [mask]\
+} while(0)
+#else
+#define START_FAST_MATH(x) do {\
+ static GLuint mask = FAST_X86_FPU;\
+ __asm fnstcw word ptr [x]\
+ __asm fldcw word ptr [mask]\
+} while(0)
+#endif
+#define END_FAST_MATH(x) do {\
+ __asm fnclex\
+ __asm fldcw word ptr [x]\
+} while(0)
+
+#else
+#define START_FAST_MATH(x) x = 0
+#define END_FAST_MATH(x) (void)(x)
+#endif
+
+
+#ifndef Elements
+#define Elements(x) (sizeof(x)/sizeof(*(x)))
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* COMPILER_H */
diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h
new file mode 100644
index 000000000..8a09efdb5
--- /dev/null
+++ b/mesalib/src/mesa/main/config.h
@@ -0,0 +1,323 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file config.h
+ * Tunable configuration parameters.
+ */
+
+#ifndef MESA_CONFIG_H_INCLUDED
+#define MESA_CONFIG_H_INCLUDED
+
+
+/**
+ * \name 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 color matrix stack depth */
+#define MAX_COLOR_STACK_DEPTH 4
+
+/** 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
+
+/** Maximum number of auxillary color buffers */
+#define MAX_AUX_BUFFERS 1
+
+/** 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
+
+/** Minimum point size */
+#define MIN_POINT_SIZE 1.0
+/** Maximum point size */
+#define MAX_POINT_SIZE 60.0
+/** Point size granularity */
+#define POINT_SIZE_GRANULARITY 0.1
+
+/** Minimum line width */
+#define MIN_LINE_WIDTH 1.0
+/** Maximum line width */
+#define MAX_LINE_WIDTH 10.0
+/** Line width granularity */
+#define LINE_WIDTH_GRANULARITY 0.1
+
+/** Max texture palette / color table size */
+#define MAX_COLOR_TABLE_SIZE 256
+
+/** Number of 1D/2D texture mipmap levels */
+#define MAX_TEXTURE_LEVELS 13
+
+/** Number of 3D texture mipmap levels */
+#define MAX_3D_TEXTURE_LEVELS 9
+
+/** Number of cube texture mipmap levels - GL_ARB_texture_cube_map */
+#define MAX_CUBE_TEXTURE_LEVELS 13
+
+/** Maximum rectangular texture size - GL_NV_texture_rectangle */
+#define MAX_TEXTURE_RECT_SIZE 4096
+
+/** Maximum number of layers in a 1D or 2D array texture - GL_MESA_texture_array */
+#define MAX_ARRAY_TEXTURE_LAYERS 64
+
+/**
+ * Max number of texture coordinate units. This mainly just applies to
+ * the fixed-function vertex code. This will be difficult to raise above
+ * eight because of various vertex attribute bitvectors.
+ */
+#define MAX_TEXTURE_COORD_UNITS 8
+
+/**
+ * Max number of texture image units. Also determines number of texture
+ * samplers in shaders.
+ */
+#define MAX_TEXTURE_IMAGE_UNITS 16
+
+/**
+ * Larger of MAX_TEXTURE_COORD_UNITS and MAX_TEXTURE_IMAGE_UNITS.
+ * This value is only used for dimensioning arrays.
+ * Either MAX_TEXTURE_COORD_UNITS or MAX_TEXTURE_IMAGE_UNITS (or the
+ * corresponding ctx->Const.MaxTextureCoord/ImageUnits fields) should be
+ * used almost everywhere else.
+ */
+#define MAX_TEXTURE_UNITS ((MAX_TEXTURE_COORD_UNITS > MAX_TEXTURE_IMAGE_UNITS) ? MAX_TEXTURE_COORD_UNITS : MAX_TEXTURE_IMAGE_UNITS)
+
+
+/**
+ * Maximum viewport/image width. Must accomodate all texture sizes too.
+ */
+
+#ifndef MAX_WIDTH
+# define MAX_WIDTH 4096
+#endif
+/** Maximum viewport/image height */
+#ifndef MAX_HEIGHT
+# define MAX_HEIGHT 4096
+#endif
+
+/** Maxmimum size for CVA. May be overridden by the drivers. */
+#define MAX_ARRAY_LOCK_SIZE 3000
+
+/** Subpixel precision for antialiasing, window coordinate snapping */
+#define SUB_PIXEL_BITS 4
+
+/** Size of histogram tables */
+#define HISTOGRAM_TABLE_SIZE 256
+
+/** Max convolution filter width */
+#define MAX_CONVOLUTION_WIDTH 9
+/** Max convolution filter height */
+#define MAX_CONVOLUTION_HEIGHT 9
+
+/** For GL_ARB_texture_compression */
+#define MAX_COMPRESSED_TEXTURE_FORMATS 25
+
+/** For GL_EXT_texture_filter_anisotropic */
+#define MAX_TEXTURE_MAX_ANISOTROPY 16.0
+
+/** For GL_EXT_texture_lod_bias (typically MAX_TEXTURE_LEVELS - 1) */
+#define MAX_TEXTURE_LOD_BIAS 12.0
+
+/** For any program target/extension */
+/*@{*/
+#define MAX_PROGRAM_INSTRUCTIONS (16 * 1024)
+
+/**
+ * Per-program constants (power of two)
+ *
+ * \c MAX_PROGRAM_LOCAL_PARAMS and \c MAX_UNIFORMS are just the assmebly shader
+ * and GLSL shader names for the same thing. They should \b always have the
+ * same value. Each refers to the number of vec4 values supplied as
+ * per-program parameters.
+ */
+/*@{*/
+#define MAX_PROGRAM_LOCAL_PARAMS 1024
+#define MAX_UNIFORMS 1024
+/*@}*/
+
+/**
+ * Per-context constants (power of two)
+ *
+ * \note
+ * This value should always be less than or equal to \c MAX_PROGRAM_LOCAL_PARAMS
+ * and \c MAX_VERTEX_PROGRAM_PARAMS. Otherwise some applications will make
+ * incorrect assumptions.
+ */
+#define MAX_PROGRAM_ENV_PARAMS 256
+
+#define MAX_PROGRAM_MATRICES 8
+#define MAX_PROGRAM_MATRIX_STACK_DEPTH 4
+#define MAX_PROGRAM_CALL_DEPTH 8
+#define MAX_PROGRAM_TEMPS 256
+#define MAX_PROGRAM_ADDRESS_REGS 2
+#define MAX_VARYING 16 /**< number of float[4] vectors */
+#define MAX_SAMPLERS MAX_TEXTURE_IMAGE_UNITS
+#define MAX_PROGRAM_INPUTS 32
+#define MAX_PROGRAM_OUTPUTS 32
+/*@}*/
+
+/** For GL_ARB_vertex_program */
+/*@{*/
+#define MAX_VERTEX_PROGRAM_ADDRESS_REGS 1
+#define MAX_VERTEX_PROGRAM_PARAMS MAX_UNIFORMS
+/*@}*/
+
+/** For GL_ARB_fragment_program */
+/*@{*/
+#define MAX_FRAGMENT_PROGRAM_ADDRESS_REGS 0
+/*@}*/
+
+/** For GL_NV_vertex_program */
+/*@{*/
+#define MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS 128
+#define MAX_NV_VERTEX_PROGRAM_TEMPS 12
+#define MAX_NV_VERTEX_PROGRAM_PARAMS 96
+#define MAX_NV_VERTEX_PROGRAM_INPUTS 16
+#define MAX_NV_VERTEX_PROGRAM_OUTPUTS 15
+/*@}*/
+
+/** For GL_NV_fragment_program */
+/*@{*/
+#define MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS 1024 /* 72 for GL_ARB_f_p */
+#define MAX_NV_FRAGMENT_PROGRAM_TEMPS 96
+#define MAX_NV_FRAGMENT_PROGRAM_PARAMS 64
+#define MAX_NV_FRAGMENT_PROGRAM_INPUTS 12
+#define MAX_NV_FRAGMENT_PROGRAM_OUTPUTS 3
+#define MAX_NV_FRAGMENT_PROGRAM_WRITE_ONLYS 2
+/*@}*/
+
+
+/** For GL_ARB_vertex_shader */
+/*@{*/
+#define MAX_VERTEX_GENERIC_ATTRIBS 16
+#define MAX_VERTEX_TEXTURE_IMAGE_UNITS MAX_TEXTURE_IMAGE_UNITS
+#define MAX_COMBINED_TEXTURE_IMAGE_UNITS MAX_TEXTURE_IMAGE_UNITS
+/*@}*/
+
+
+/** For GL_ARB_draw_buffers */
+/*@{*/
+#define MAX_DRAW_BUFFERS 4
+/*@}*/
+
+
+/** For GL_EXT_framebuffer_object */
+/*@{*/
+#define MAX_COLOR_ATTACHMENTS 8
+/*@}*/
+
+/** For GL_ATI_envmap_bump - support bump mapping on first 8 units */
+#define SUPPORTED_ATI_BUMP_UNITS 0xff
+
+/**
+ * \name Mesa-specific parameters
+ */
+/*@{*/
+
+
+/**
+ * If non-zero use GLdouble for walking triangle edges, for better accuracy.
+ */
+#define TRIANGLE_WALK_DOUBLE 0
+
+
+/**
+ * Bits per depth buffer value (max is 32).
+ */
+#ifndef DEFAULT_SOFTWARE_DEPTH_BITS
+#define DEFAULT_SOFTWARE_DEPTH_BITS 16
+#endif
+/** Depth buffer data type */
+#if DEFAULT_SOFTWARE_DEPTH_BITS <= 16
+#define DEFAULT_SOFTWARE_DEPTH_TYPE GLushort
+#else
+#define DEFAULT_SOFTWARE_DEPTH_TYPE GLuint
+#endif
+
+
+/**
+ * Bits per stencil value: 8
+ */
+#define STENCIL_BITS 8
+
+
+/**
+ * Bits per color channel: 8, 16 or 32
+ */
+#ifndef CHAN_BITS
+#define CHAN_BITS 8
+#endif
+
+
+/*
+ * Color channel component order
+ *
+ * \note Changes will almost certainly cause problems at this time.
+ */
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+
+
+/**
+ * Maximum number of temporary vertices required for clipping.
+ *
+ * Used in array_cache and tnl modules.
+ */
+#define MAX_CLIPPED_VERTICES ((2 * (6 + MAX_CLIP_PLANES))+1)
+
+
+#endif /* MESA_CONFIG_H_INCLUDED */
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
new file mode 100644
index 000000000..f6d4ac459
--- /dev/null
+++ b/mesalib/src/mesa/main/context.c
@@ -0,0 +1,1672 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file context.c
+ * Mesa context/visual/framebuffer management functions.
+ * \author Brian Paul
+ */
+
+/**
+ * \mainpage Mesa Main Module
+ *
+ * \section MainIntroduction Introduction
+ *
+ * The Mesa Main module consists of all the files in the main/ directory.
+ * Among the features of this module are:
+ * <UL>
+ * <LI> Structures to represent most GL state </LI>
+ * <LI> State set/get functions </LI>
+ * <LI> Display lists </LI>
+ * <LI> Texture unit, object and image handling </LI>
+ * <LI> Matrix and attribute stacks </LI>
+ * </UL>
+ *
+ * Other modules are responsible for API dispatch, vertex transformation,
+ * point/line/triangle setup, rasterization, vertex array caching,
+ * vertex/fragment programs/shaders, etc.
+ *
+ *
+ * \section AboutDoxygen About Doxygen
+ *
+ * If you're viewing this information as Doxygen-generated HTML you'll
+ * see the documentation index at the top of this page.
+ *
+ * The first line lists the Mesa source code modules.
+ * The second line lists the indexes available for viewing the documentation
+ * for each module.
+ *
+ * Selecting the <b>Main page</b> link will display a summary of the module
+ * (this page).
+ *
+ * Selecting <b>Data Structures</b> will list all C structures.
+ *
+ * Selecting the <b>File List</b> link will list all the source files in
+ * the module.
+ * Selecting a filename will show a list of all functions defined in that file.
+ *
+ * Selecting the <b>Data Fields</b> link will display a list of all
+ * documented structure members.
+ *
+ * Selecting the <b>Globals</b> link will display a list
+ * of all functions, structures, global variables and macros in the module.
+ *
+ */
+
+
+#include "glheader.h"
+#include "mfeatures.h"
+#include "imports.h"
+#if FEATURE_accum
+#include "accum.h"
+#endif
+#include "api_exec.h"
+#include "arrayobj.h"
+#if FEATURE_attrib_stack
+#include "attrib.h"
+#endif
+#include "blend.h"
+#include "buffers.h"
+#include "bufferobj.h"
+#if FEATURE_colortable
+#include "colortab.h"
+#endif
+#include "context.h"
+#include "cpuinfo.h"
+#include "debug.h"
+#include "depth.h"
+#if FEATURE_dlist
+#include "dlist.h"
+#endif
+#if FEATURE_evaluators
+#include "eval.h"
+#endif
+#include "enums.h"
+#include "extensions.h"
+#include "fbobject.h"
+#if FEATURE_feedback
+#include "feedback.h"
+#endif
+#include "fog.h"
+#include "framebuffer.h"
+#include "get.h"
+#if FEATURE_histogram
+#include "histogram.h"
+#endif
+#include "hint.h"
+#include "hash.h"
+#include "light.h"
+#include "lines.h"
+#include "macros.h"
+#include "matrix.h"
+#include "multisample.h"
+#include "pixel.h"
+#include "pixelstore.h"
+#include "points.h"
+#include "polygon.h"
+#if FEATURE_ARB_occlusion_query
+#include "queryobj.h"
+#endif
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+#endif
+#if FEATURE_drawpix
+#include "rastpos.h"
+#endif
+#include "scissor.h"
+#include "shared.h"
+#include "simple_list.h"
+#include "state.h"
+#include "stencil.h"
+#include "texcompress.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "texstate.h"
+#include "mtypes.h"
+#include "varray.h"
+#include "version.h"
+#include "viewport.h"
+#include "vtxfmt.h"
+#include "glapi/glthread.h"
+#include "glapi/glapioffsets.h"
+#include "glapi/glapitable.h"
+#include "shader/program.h"
+#include "shader/prog_print.h"
+#include "shader/shader_api.h"
+#if FEATURE_ATI_fragment_shader
+#include "shader/atifragshader.h"
+#endif
+#if _HAVE_FULL_GL
+#include "math/m_matrix.h"
+#endif
+
+#ifdef USE_SPARC_ASM
+#include "sparc/sparc.h"
+#endif
+
+#ifndef MESA_VERBOSE
+int MESA_VERBOSE = 0;
+#endif
+
+#ifndef MESA_DEBUG_FLAGS
+int MESA_DEBUG_FLAGS = 0;
+#endif
+
+
+/* ubyte -> float conversion */
+GLfloat _mesa_ubyte_to_float_color_tab[256];
+
+
+
+/**
+ * Swap buffers notification callback.
+ *
+ * \param ctx GL context.
+ *
+ * Called by window system just before swapping buffers.
+ * We have to finish any pending rendering.
+ */
+void
+_mesa_notifySwapBuffers(__GLcontext *ctx)
+{
+ FLUSH_CURRENT( ctx, 0 );
+ if (ctx->Driver.Flush) {
+ ctx->Driver.Flush(ctx);
+ }
+}
+
+
+/**********************************************************************/
+/** \name GL Visual allocation/destruction */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * Allocates a GLvisual structure and initializes it via
+ * _mesa_initialize_visual().
+ *
+ * \param rgbFlag GL_TRUE for RGB(A) mode, GL_FALSE for Color Index mode.
+ * \param dbFlag double buffering
+ * \param stereoFlag stereo buffer
+ * \param depthBits requested bits per depth buffer value. Any value in [0, 32]
+ * is acceptable but the actual depth type will be GLushort or GLuint as
+ * needed.
+ * \param stencilBits requested minimum bits per stencil buffer value
+ * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number of bits per color component in accum buffer.
+ * \param indexBits number of bits per pixel if \p rgbFlag is GL_FALSE
+ * \param redBits number of bits per color component in frame buffer for RGB(A)
+ * mode. We always use 8 in core Mesa though.
+ * \param greenBits same as above.
+ * \param blueBits same as above.
+ * \param alphaBits same as above.
+ * \param numSamples not really used.
+ *
+ * \return pointer to new GLvisual or NULL if requested parameters can't be
+ * met.
+ *
+ * \note Need to add params for level and numAuxBuffers (at least)
+ */
+GLvisual *
+_mesa_create_visual( GLboolean rgbFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits,
+ GLint indexBits,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumRedBits,
+ GLint accumGreenBits,
+ GLint accumBlueBits,
+ GLint accumAlphaBits,
+ GLint numSamples )
+{
+ GLvisual *vis = (GLvisual *) _mesa_calloc(sizeof(GLvisual));
+ if (vis) {
+ if (!_mesa_initialize_visual(vis, rgbFlag, dbFlag, stereoFlag,
+ redBits, greenBits, blueBits, alphaBits,
+ indexBits, depthBits, stencilBits,
+ accumRedBits, accumGreenBits,
+ accumBlueBits, accumAlphaBits,
+ numSamples)) {
+ _mesa_free(vis);
+ return NULL;
+ }
+ }
+ return vis;
+}
+
+/**
+ * Makes some sanity checks and fills in the fields of the
+ * GLvisual object with the given parameters. If the caller needs
+ * to set additional fields, he should just probably init the whole GLvisual
+ * object himself.
+ * \return GL_TRUE on success, or GL_FALSE on failure.
+ *
+ * \sa _mesa_create_visual() above for the parameter description.
+ */
+GLboolean
+_mesa_initialize_visual( GLvisual *vis,
+ GLboolean rgbFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits,
+ GLint indexBits,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumRedBits,
+ GLint accumGreenBits,
+ GLint accumBlueBits,
+ GLint accumAlphaBits,
+ GLint numSamples )
+{
+ assert(vis);
+
+ if (depthBits < 0 || depthBits > 32) {
+ return GL_FALSE;
+ }
+ if (stencilBits < 0 || stencilBits > STENCIL_BITS) {
+ return GL_FALSE;
+ }
+ assert(accumRedBits >= 0);
+ assert(accumGreenBits >= 0);
+ assert(accumBlueBits >= 0);
+ assert(accumAlphaBits >= 0);
+
+ vis->rgbMode = rgbFlag;
+ vis->doubleBufferMode = dbFlag;
+ vis->stereoMode = stereoFlag;
+
+ vis->redBits = redBits;
+ vis->greenBits = greenBits;
+ vis->blueBits = blueBits;
+ vis->alphaBits = alphaBits;
+ vis->rgbBits = redBits + greenBits + blueBits;
+
+ vis->indexBits = indexBits;
+ vis->depthBits = depthBits;
+ vis->stencilBits = stencilBits;
+
+ vis->accumRedBits = accumRedBits;
+ vis->accumGreenBits = accumGreenBits;
+ vis->accumBlueBits = accumBlueBits;
+ vis->accumAlphaBits = accumAlphaBits;
+
+ vis->haveAccumBuffer = accumRedBits > 0;
+ vis->haveDepthBuffer = depthBits > 0;
+ vis->haveStencilBuffer = stencilBits > 0;
+
+ vis->numAuxBuffers = 0;
+ vis->level = 0;
+ vis->pixmapMode = 0;
+ vis->sampleBuffers = numSamples > 0 ? 1 : 0;
+ vis->samples = numSamples;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Destroy a visual and free its memory.
+ *
+ * \param vis visual.
+ *
+ * Frees the visual structure.
+ */
+void
+_mesa_destroy_visual( GLvisual *vis )
+{
+ _mesa_free(vis);
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Context allocation, initialization, destroying
+ *
+ * The purpose of the most initialization functions here is to provide the
+ * default state values according to the OpenGL specification.
+ */
+/**********************************************************************/
+/*@{*/
+
+
+/**
+ * This is lame. gdb only seems to recognize enum types that are
+ * actually used somewhere. We want to be able to print/use enum
+ * values such as TEXTURE_2D_INDEX in gdb. But we don't actually use
+ * the gl_texture_index type anywhere. Thus, this lame function.
+ */
+static void
+dummy_enum_func(void)
+{
+ gl_buffer_index bi;
+ gl_colortable_index ci;
+ gl_face_index fi;
+ gl_frag_attrib fa;
+ gl_frag_result fr;
+ gl_texture_index ti;
+ gl_vert_attrib va;
+ gl_vert_result vr;
+
+ (void) bi;
+ (void) ci;
+ (void) fi;
+ (void) fa;
+ (void) fr;
+ (void) ti;
+ (void) va;
+ (void) vr;
+}
+
+
+/**
+ * One-time initialization mutex lock.
+ *
+ * \sa Used by one_time_init().
+ */
+_glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
+
+/**
+ * Calls all the various one-time-init functions in Mesa.
+ *
+ * While holding a global mutex lock, calls several initialization functions,
+ * and sets the glapi callbacks if the \c MESA_DEBUG environment variable is
+ * defined.
+ *
+ * \sa _math_init().
+ */
+static void
+one_time_init( GLcontext *ctx )
+{
+ static GLboolean alreadyCalled = GL_FALSE;
+ (void) ctx;
+ _glthread_LOCK_MUTEX(OneTimeLock);
+ if (!alreadyCalled) {
+ GLuint i;
+
+ /* do some implementation tests */
+ assert( sizeof(GLbyte) == 1 );
+ assert( sizeof(GLubyte) == 1 );
+ assert( sizeof(GLshort) == 2 );
+ assert( sizeof(GLushort) == 2 );
+ assert( sizeof(GLint) == 4 );
+ assert( sizeof(GLuint) == 4 );
+
+ _mesa_get_cpu_features();
+
+ _mesa_init_sqrt_table();
+
+ for (i = 0; i < 256; i++) {
+ _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F;
+ }
+
+ if (_mesa_getenv("MESA_DEBUG")) {
+ _glapi_noop_enable_warnings(GL_TRUE);
+ _glapi_set_warning_func( (_glapi_warning_func) _mesa_warning );
+ }
+ else {
+ _glapi_noop_enable_warnings(GL_FALSE);
+ }
+
+#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
+ _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
+ MESA_VERSION_STRING, __DATE__, __TIME__);
+#endif
+
+ alreadyCalled = GL_TRUE;
+ }
+ _glthread_UNLOCK_MUTEX(OneTimeLock);
+
+ dummy_enum_func();
+}
+
+
+/**
+ * Initialize fields of gl_current_attrib (aka ctx->Current.*)
+ */
+static void
+_mesa_init_current(GLcontext *ctx)
+{
+ GLuint i;
+
+ /* Init all to (0,0,0,1) */
+ for (i = 0; i < Elements(ctx->Current.Attrib); i++) {
+ ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 );
+ }
+
+ /* redo special cases: */
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 );
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 );
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX], 1.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG], 1.0, 0.0, 0.0, 1.0 );
+}
+
+
+/**
+ * Init vertex/fragment program limits.
+ * Important: drivers should override these with actual limits.
+ */
+static void
+init_program_limits(GLenum type, struct gl_program_constants *prog)
+{
+ prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxAluInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexInstructions = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTexIndirections = MAX_PROGRAM_INSTRUCTIONS;
+ prog->MaxTemps = MAX_PROGRAM_TEMPS;
+ prog->MaxEnvParams = MAX_PROGRAM_ENV_PARAMS;
+ prog->MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
+ prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
+
+ if (type == GL_VERTEX_PROGRAM_ARB) {
+ prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+ }
+ else {
+ prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
+ prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+ }
+
+ /* Set the native limits to zero. This implies that there is no native
+ * support for shaders. Let the drivers fill in the actual values.
+ */
+ prog->MaxNativeInstructions = 0;
+ prog->MaxNativeAluInstructions = 0;
+ prog->MaxNativeTexInstructions = 0;
+ prog->MaxNativeTexIndirections = 0;
+ prog->MaxNativeAttribs = 0;
+ prog->MaxNativeTemps = 0;
+ prog->MaxNativeAddressRegs = 0;
+ prog->MaxNativeParameters = 0;
+}
+
+
+/**
+ * Initialize fields of gl_constants (aka ctx->Const.*).
+ * Use defaults from config.h. The device drivers will often override
+ * some of these values (such as number of texture units).
+ */
+static void
+_mesa_init_constants(GLcontext *ctx)
+{
+ assert(ctx);
+
+ assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
+ assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
+
+ /* Max texture size should be <= max viewport size (render to texture) */
+ assert((1 << (MAX_TEXTURE_LEVELS - 1)) <= MAX_WIDTH);
+
+ /* Constants, may be overriden (usually only reduced) by device drivers */
+ ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
+ ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
+ ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
+ ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
+ ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS;
+ ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS;
+ ctx->Const.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits,
+ ctx->Const.MaxTextureImageUnits);
+ ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
+ ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
+ ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
+ ctx->Const.SubPixelBits = SUB_PIXEL_BITS;
+ ctx->Const.MinPointSize = MIN_POINT_SIZE;
+ ctx->Const.MaxPointSize = MAX_POINT_SIZE;
+ ctx->Const.MinPointSizeAA = MIN_POINT_SIZE;
+ ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE;
+ ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY;
+ ctx->Const.MinLineWidth = MIN_LINE_WIDTH;
+ ctx->Const.MaxLineWidth = MAX_LINE_WIDTH;
+ ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH;
+ ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH;
+ ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY;
+ ctx->Const.MaxColorTableSize = MAX_COLOR_TABLE_SIZE;
+ ctx->Const.MaxConvolutionWidth = MAX_CONVOLUTION_WIDTH;
+ ctx->Const.MaxConvolutionHeight = MAX_CONVOLUTION_HEIGHT;
+ ctx->Const.MaxClipPlanes = MAX_CLIP_PLANES;
+ ctx->Const.MaxLights = MAX_LIGHTS;
+ ctx->Const.MaxShininess = 128.0;
+ ctx->Const.MaxSpotExponent = 128.0;
+ ctx->Const.MaxViewportWidth = MAX_WIDTH;
+ ctx->Const.MaxViewportHeight = MAX_HEIGHT;
+#if FEATURE_ARB_vertex_program
+ init_program_limits(GL_VERTEX_PROGRAM_ARB, &ctx->Const.VertexProgram);
+#endif
+#if FEATURE_ARB_fragment_program
+ init_program_limits(GL_FRAGMENT_PROGRAM_ARB, &ctx->Const.FragmentProgram);
+#endif
+ ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
+ ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
+
+ /* CheckArrayBounds is overriden by drivers/x11 for X server */
+ ctx->Const.CheckArrayBounds = GL_FALSE;
+
+ /* GL_ARB_draw_buffers */
+ ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+
+ /* GL_OES_read_format */
+ ctx->Const.ColorReadFormat = GL_RGBA;
+ ctx->Const.ColorReadType = GL_UNSIGNED_BYTE;
+
+#if FEATURE_EXT_framebuffer_object
+ ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS;
+ ctx->Const.MaxRenderbufferSize = MAX_WIDTH;
+#endif
+
+#if FEATURE_ARB_vertex_shader
+ ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+ ctx->Const.MaxVarying = MAX_VARYING;
+#endif
+
+ /* GL_ARB_framebuffer_object */
+ ctx->Const.MaxSamples = 0;
+
+ /* GL_ARB_sync */
+ ctx->Const.MaxServerWaitTimeout = (GLuint64) ~0;
+
+ /* GL_ATI_envmap_bumpmap */
+ ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
+
+ /* GL_EXT_provoking_vertex */
+ ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE;
+
+ /* sanity checks */
+ ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
+ ctx->Const.MaxTextureCoordUnits));
+ ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
+ ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= MAX_PROGRAM_LOCAL_PARAMS);
+
+ ASSERT(MAX_NV_FRAGMENT_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
+ ASSERT(MAX_NV_VERTEX_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
+ ASSERT(MAX_NV_VERTEX_PROGRAM_INPUTS <= VERT_ATTRIB_MAX);
+ ASSERT(MAX_NV_VERTEX_PROGRAM_OUTPUTS <= VERT_RESULT_MAX);
+
+ /* check that we don't exceed various 32-bit bitfields */
+ ASSERT(VERT_RESULT_MAX <= 32);
+ ASSERT(FRAG_ATTRIB_MAX <= 32);
+}
+
+
+/**
+ * Do some sanity checks on the limits/constants for the given context.
+ * Only called the first time a context is bound.
+ */
+static void
+check_context_limits(GLcontext *ctx)
+{
+ /* Many context limits/constants are limited by the size of
+ * internal arrays.
+ */
+ assert(ctx->Const.MaxTextureImageUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.MaxTextureCoordUnits <= MAX_TEXTURE_COORD_UNITS);
+ assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_IMAGE_UNITS);
+ assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_COORD_UNITS);
+
+ /* number of coord units cannot be greater than number of image units */
+ assert(ctx->Const.MaxTextureCoordUnits <= ctx->Const.MaxTextureImageUnits);
+
+ assert(ctx->Const.MaxTextureLevels <= MAX_TEXTURE_LEVELS);
+ assert(ctx->Const.Max3DTextureLevels <= MAX_3D_TEXTURE_LEVELS);
+ assert(ctx->Const.MaxCubeTextureLevels <= MAX_CUBE_TEXTURE_LEVELS);
+ assert(ctx->Const.MaxTextureRectSize <= MAX_TEXTURE_RECT_SIZE);
+
+ /* make sure largest texture image is <= MAX_WIDTH in size */
+ assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= MAX_WIDTH);
+ assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= MAX_WIDTH);
+ assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= MAX_WIDTH);
+
+ assert(ctx->Const.MaxViewportWidth <= MAX_WIDTH);
+ assert(ctx->Const.MaxViewportHeight <= MAX_WIDTH);
+
+ assert(ctx->Const.MaxDrawBuffers <= MAX_DRAW_BUFFERS);
+
+ /* XXX probably add more tests */
+}
+
+
+/**
+ * Initialize the attribute groups in a GL context.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes all the attributes, calling the respective <tt>init*</tt>
+ * functions for the more complex data structures.
+ */
+static GLboolean
+init_attrib_groups(GLcontext *ctx)
+{
+ assert(ctx);
+
+ /* Constants */
+ _mesa_init_constants( ctx );
+
+ /* Extensions */
+ _mesa_init_extensions( ctx );
+
+ /* Attribute Groups */
+#if FEATURE_accum
+ _mesa_init_accum( ctx );
+#endif
+#if FEATURE_attrib_stack
+ _mesa_init_attrib( ctx );
+#endif
+ _mesa_init_buffer_objects( ctx );
+ _mesa_init_color( ctx );
+#if FEATURE_colortable
+ _mesa_init_colortables( ctx );
+#endif
+ _mesa_init_current( ctx );
+ _mesa_init_depth( ctx );
+ _mesa_init_debug( ctx );
+#if FEATURE_dlist
+ _mesa_init_display_list( ctx );
+#endif
+#if FEATURE_evaluators
+ _mesa_init_eval( ctx );
+#endif
+ _mesa_init_fbobjects( ctx );
+#if FEATURE_feedback
+ _mesa_init_feedback( ctx );
+#else
+ ctx->RenderMode = GL_RENDER;
+#endif
+ _mesa_init_fog( ctx );
+#if FEATURE_histogram
+ _mesa_init_histogram( ctx );
+#endif
+ _mesa_init_hint( ctx );
+ _mesa_init_line( ctx );
+ _mesa_init_lighting( ctx );
+ _mesa_init_matrix( ctx );
+ _mesa_init_multisample( ctx );
+ _mesa_init_pixel( ctx );
+ _mesa_init_pixelstore( ctx );
+ _mesa_init_point( ctx );
+ _mesa_init_polygon( ctx );
+ _mesa_init_program( ctx );
+#if FEATURE_ARB_occlusion_query
+ _mesa_init_query( ctx );
+#endif
+#if FEATURE_ARB_sync
+ _mesa_init_sync( ctx );
+#endif
+#if FEATURE_drawpix
+ _mesa_init_rastpos( ctx );
+#endif
+ _mesa_init_scissor( ctx );
+ _mesa_init_shader_state( ctx );
+ _mesa_init_stencil( ctx );
+ _mesa_init_transform( ctx );
+ _mesa_init_varray( ctx );
+ _mesa_init_viewport( ctx );
+
+ if (!_mesa_init_texture( ctx ))
+ return GL_FALSE;
+
+#if FEATURE_texture_s3tc
+ _mesa_init_texture_s3tc( ctx );
+#endif
+#if FEATURE_texture_fxt1
+ _mesa_init_texture_fxt1( ctx );
+#endif
+
+ /* Miscellaneous */
+ ctx->NewState = _NEW_ALL;
+ ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ ctx->varying_vp_inputs = ~0;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Update default objects in a GL context with respect to shared state.
+ *
+ * \param ctx GL context.
+ *
+ * Removes references to old default objects, (texture objects, program
+ * objects, etc.) and changes to reference those from the current shared
+ * state.
+ */
+static GLboolean
+update_default_objects(GLcontext *ctx)
+{
+ assert(ctx);
+
+ _mesa_update_default_objects_program(ctx);
+ _mesa_update_default_objects_texture(ctx);
+ _mesa_update_default_objects_buffer_objects(ctx);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * This is the default function we plug into all dispatch table slots
+ * This helps prevents a segfault when someone calls a GL function without
+ * first checking if the extension's supported.
+ */
+static int
+generic_nop(void)
+{
+ _mesa_warning(NULL, "User called no-op dispatch function (an unsupported extension function?)");
+ return 0;
+}
+
+
+/**
+ * Allocate and initialize a new dispatch table.
+ */
+static struct _glapi_table *
+alloc_dispatch_table(void)
+{
+ /* Find the larger of Mesa's dispatch table and libGL's dispatch table.
+ * In practice, this'll be the same for stand-alone Mesa. But for DRI
+ * Mesa we do this to accomodate different versions of libGL and various
+ * DRI drivers.
+ */
+ GLint numEntries = MAX2(_glapi_get_dispatch_table_size(),
+ sizeof(struct _glapi_table) / sizeof(_glapi_proc));
+ struct _glapi_table *table =
+ (struct _glapi_table *) _mesa_malloc(numEntries * sizeof(_glapi_proc));
+ if (table) {
+ _glapi_proc *entry = (_glapi_proc *) table;
+ GLint i;
+ for (i = 0; i < numEntries; i++) {
+ entry[i] = (_glapi_proc) generic_nop;
+ }
+ }
+ return table;
+}
+
+
+/**
+ * Initialize a GLcontext struct (rendering context).
+ *
+ * This includes allocating all the other structs and arrays which hang off of
+ * the context by pointers.
+ * Note that the driver needs to pass in its dd_function_table here since
+ * we need to at least call driverFunctions->NewTextureObject to create the
+ * default texture objects.
+ *
+ * Called by _mesa_create_context().
+ *
+ * Performs the imports and exports callback tables initialization, and
+ * miscellaneous one-time initializations. If no shared context is supplied one
+ * is allocated, and increase its reference count. Setups the GL API dispatch
+ * tables. Initialize the TNL module. Sets the maximum Z buffer depth.
+ * Finally queries the \c MESA_DEBUG and \c MESA_VERBOSE environment variables
+ * for debug flags.
+ *
+ * \param ctx the context to initialize
+ * \param visual describes the visual attributes for this context
+ * \param share_list points to context to share textures, display lists,
+ * etc with, or NULL
+ * \param driverFunctions table of device driver functions for this context
+ * to use
+ * \param driverContext pointer to driver-specific context data
+ */
+GLboolean
+_mesa_initialize_context(GLcontext *ctx,
+ const GLvisual *visual,
+ GLcontext *share_list,
+ const struct dd_function_table *driverFunctions,
+ void *driverContext)
+{
+ struct gl_shared_state *shared;
+
+ /*ASSERT(driverContext);*/
+ assert(driverFunctions->NewTextureObject);
+ assert(driverFunctions->FreeTexImageData);
+
+ /* misc one-time initializations */
+ one_time_init(ctx);
+
+ ctx->Visual = *visual;
+ ctx->DrawBuffer = NULL;
+ ctx->ReadBuffer = NULL;
+ ctx->WinSysDrawBuffer = NULL;
+ ctx->WinSysReadBuffer = NULL;
+
+ /* Plug in driver functions and context pointer here.
+ * This is important because when we call alloc_shared_state() below
+ * we'll call ctx->Driver.NewTextureObject() to create the default
+ * textures.
+ */
+ ctx->Driver = *driverFunctions;
+ ctx->DriverCtx = driverContext;
+
+ if (share_list) {
+ /* share state with another context */
+ shared = share_list->Shared;
+ }
+ else {
+ /* allocate new, unshared state */
+ shared = _mesa_alloc_shared_state(ctx);
+ if (!shared)
+ return GL_FALSE;
+ }
+
+ _glthread_LOCK_MUTEX(shared->Mutex);
+ ctx->Shared = shared;
+ shared->RefCount++;
+ _glthread_UNLOCK_MUTEX(shared->Mutex);
+
+ if (!init_attrib_groups( ctx )) {
+ _mesa_free_shared_state(ctx, ctx->Shared);
+ return GL_FALSE;
+ }
+
+ /* setup the API dispatch tables */
+ ctx->Exec = alloc_dispatch_table();
+ ctx->Save = alloc_dispatch_table();
+ if (!ctx->Exec || !ctx->Save) {
+ _mesa_free_shared_state(ctx, ctx->Shared);
+ if (ctx->Exec)
+ _mesa_free(ctx->Exec);
+ }
+#if FEATURE_dispatch
+ _mesa_init_exec_table(ctx->Exec);
+#endif
+ ctx->CurrentDispatch = ctx->Exec;
+#if FEATURE_dlist
+ _mesa_init_dlist_table(ctx->Save);
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+#endif
+ /* Neutral tnl module stuff */
+ _mesa_init_exec_vtxfmt( ctx );
+ ctx->TnlModule.Current = NULL;
+ ctx->TnlModule.SwapCount = 0;
+
+ ctx->FragmentProgram._MaintainTexEnvProgram
+ = (_mesa_getenv("MESA_TEX_PROG") != NULL);
+
+ ctx->VertexProgram._MaintainTnlProgram
+ = (_mesa_getenv("MESA_TNL_PROG") != NULL);
+ if (ctx->VertexProgram._MaintainTnlProgram) {
+ /* this is required... */
+ ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+ }
+
+#ifdef FEATURE_extra_context_init
+ _mesa_initialize_context_extra(ctx);
+#endif
+
+ ctx->FirstTimeCurrent = GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Allocate and initialize a GLcontext structure.
+ * Note that the driver needs to pass in its dd_function_table here since
+ * we need to at least call driverFunctions->NewTextureObject to initialize
+ * the rendering context.
+ *
+ * \param visual a GLvisual pointer (we copy the struct contents)
+ * \param share_list another context to share display lists with or NULL
+ * \param driverFunctions points to the dd_function_table into which the
+ * driver has plugged in all its special functions.
+ * \param driverContext points to the device driver's private context state
+ *
+ * \return pointer to a new __GLcontextRec or NULL if error.
+ */
+GLcontext *
+_mesa_create_context(const GLvisual *visual,
+ GLcontext *share_list,
+ const struct dd_function_table *driverFunctions,
+ void *driverContext)
+{
+ GLcontext *ctx;
+
+ ASSERT(visual);
+ /*ASSERT(driverContext);*/
+
+ ctx = (GLcontext *) _mesa_calloc(sizeof(GLcontext));
+ if (!ctx)
+ return NULL;
+
+ if (_mesa_initialize_context(ctx, visual, share_list,
+ driverFunctions, driverContext)) {
+ return ctx;
+ }
+ else {
+ _mesa_free(ctx);
+ return NULL;
+ }
+}
+
+
+/**
+ * Free the data associated with the given context.
+ *
+ * But doesn't free the GLcontext struct itself.
+ *
+ * \sa _mesa_initialize_context() and init_attrib_groups().
+ */
+void
+_mesa_free_context_data( GLcontext *ctx )
+{
+ GLint RefCount;
+
+ if (!_mesa_get_current_context()){
+ /* No current context, but we may need one in order to delete
+ * texture objs, etc. So temporarily bind the context now.
+ */
+ _mesa_make_current(ctx, NULL, NULL);
+ }
+
+ /* unreference WinSysDraw/Read buffers */
+ _mesa_reference_framebuffer(&ctx->WinSysDrawBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->WinSysReadBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->DrawBuffer, NULL);
+ _mesa_reference_framebuffer(&ctx->ReadBuffer, NULL);
+
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
+
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+
+#if FEATURE_attrib_stack
+ _mesa_free_attrib_data(ctx);
+#endif
+ _mesa_free_lighting_data( ctx );
+#if FEATURE_evaluators
+ _mesa_free_eval_data( ctx );
+#endif
+ _mesa_free_texture_data( ctx );
+ _mesa_free_matrix_data( ctx );
+ _mesa_free_viewport_data( ctx );
+#if FEATURE_colortable
+ _mesa_free_colortables_data( ctx );
+#endif
+ _mesa_free_program_data(ctx);
+ _mesa_free_shader_state(ctx);
+#if FEATURE_ARB_occlusion_query
+ _mesa_free_query_data(ctx);
+#endif
+#if FEATURE_ARB_sync
+ _mesa_free_sync_data(ctx);
+#endif
+ _mesa_free_varray_data(ctx);
+
+ _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
+
+#if FEATURE_ARB_pixel_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL);
+#endif
+
+ /* free dispatch tables */
+ _mesa_free(ctx->Exec);
+ _mesa_free(ctx->Save);
+
+ /* Shared context state (display lists, textures, etc) */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ RefCount = --ctx->Shared->RefCount;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ assert(RefCount >= 0);
+ if (RefCount == 0) {
+ /* free shared state */
+ _mesa_free_shared_state( ctx, ctx->Shared );
+ }
+
+ if (ctx->Extensions.String)
+ _mesa_free((void *) ctx->Extensions.String);
+
+ /* unbind the context if it's currently bound */
+ if (ctx == _mesa_get_current_context()) {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+}
+
+
+/**
+ * Destroy a GLcontext structure.
+ *
+ * \param ctx GL context.
+ *
+ * Calls _mesa_free_context_data() and frees the GLcontext structure itself.
+ */
+void
+_mesa_destroy_context( GLcontext *ctx )
+{
+ if (ctx) {
+ _mesa_free_context_data(ctx);
+ _mesa_free( (void *) ctx );
+ }
+}
+
+
+#if _HAVE_FULL_GL
+/**
+ * Copy attribute groups from one context to another.
+ *
+ * \param src source context
+ * \param dst destination context
+ * \param mask bitwise OR of GL_*_BIT flags
+ *
+ * According to the bits specified in \p mask, copies the corresponding
+ * attributes from \p src into \p dst. For many of the attributes a simple \c
+ * memcpy is not enough due to the existence of internal pointers in their data
+ * structures.
+ */
+void
+_mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
+{
+ if (mask & GL_ACCUM_BUFFER_BIT) {
+ /* OK to memcpy */
+ dst->Accum = src->Accum;
+ }
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ /* OK to memcpy */
+ dst->Color = src->Color;
+ }
+ if (mask & GL_CURRENT_BIT) {
+ /* OK to memcpy */
+ dst->Current = src->Current;
+ }
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ /* OK to memcpy */
+ dst->Depth = src->Depth;
+ }
+ if (mask & GL_ENABLE_BIT) {
+ /* no op */
+ }
+ if (mask & GL_EVAL_BIT) {
+ /* OK to memcpy */
+ dst->Eval = src->Eval;
+ }
+ if (mask & GL_FOG_BIT) {
+ /* OK to memcpy */
+ dst->Fog = src->Fog;
+ }
+ if (mask & GL_HINT_BIT) {
+ /* OK to memcpy */
+ dst->Hint = src->Hint;
+ }
+ if (mask & GL_LIGHTING_BIT) {
+ GLuint i;
+ /* begin with memcpy */
+ dst->Light = src->Light;
+ /* fixup linked lists to prevent pointer insanity */
+ make_empty_list( &(dst->Light.EnabledList) );
+ for (i = 0; i < MAX_LIGHTS; i++) {
+ if (dst->Light.Light[i].Enabled) {
+ insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i]));
+ }
+ }
+ }
+ if (mask & GL_LINE_BIT) {
+ /* OK to memcpy */
+ dst->Line = src->Line;
+ }
+ if (mask & GL_LIST_BIT) {
+ /* OK to memcpy */
+ dst->List = src->List;
+ }
+ if (mask & GL_PIXEL_MODE_BIT) {
+ /* OK to memcpy */
+ dst->Pixel = src->Pixel;
+ }
+ if (mask & GL_POINT_BIT) {
+ /* OK to memcpy */
+ dst->Point = src->Point;
+ }
+ if (mask & GL_POLYGON_BIT) {
+ /* OK to memcpy */
+ dst->Polygon = src->Polygon;
+ }
+ if (mask & GL_POLYGON_STIPPLE_BIT) {
+ /* Use loop instead of MEMCPY due to problem with Portland Group's
+ * C compiler. Reported by John Stone.
+ */
+ GLuint i;
+ for (i = 0; i < 32; i++) {
+ dst->PolygonStipple[i] = src->PolygonStipple[i];
+ }
+ }
+ if (mask & GL_SCISSOR_BIT) {
+ /* OK to memcpy */
+ dst->Scissor = src->Scissor;
+ }
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ /* OK to memcpy */
+ dst->Stencil = src->Stencil;
+ }
+ if (mask & GL_TEXTURE_BIT) {
+ /* Cannot memcpy because of pointers */
+ _mesa_copy_texture_state(src, dst);
+ }
+ if (mask & GL_TRANSFORM_BIT) {
+ /* OK to memcpy */
+ dst->Transform = src->Transform;
+ }
+ if (mask & GL_VIEWPORT_BIT) {
+ /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
+ dst->Viewport.X = src->Viewport.X;
+ dst->Viewport.Y = src->Viewport.Y;
+ dst->Viewport.Width = src->Viewport.Width;
+ dst->Viewport.Height = src->Viewport.Height;
+ dst->Viewport.Near = src->Viewport.Near;
+ dst->Viewport.Far = src->Viewport.Far;
+ _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap);
+ }
+
+ /* XXX FIXME: Call callbacks?
+ */
+ dst->NewState = _NEW_ALL;
+}
+#endif
+
+
+/**
+ * Check if the given context can render into the given framebuffer
+ * by checking visual attributes.
+ *
+ * Most of these tests could go away because Mesa is now pretty flexible
+ * in terms of mixing rendering contexts with framebuffers. As long
+ * as RGB vs. CI mode agree, we're probably good.
+ *
+ * \return GL_TRUE if compatible, GL_FALSE otherwise.
+ */
+static GLboolean
+check_compatible(const GLcontext *ctx, const GLframebuffer *buffer)
+{
+ const GLvisual *ctxvis = &ctx->Visual;
+ const GLvisual *bufvis = &buffer->Visual;
+
+ if (ctxvis == bufvis)
+ return GL_TRUE;
+
+ if (ctxvis->rgbMode != bufvis->rgbMode)
+ return GL_FALSE;
+#if 0
+ /* disabling this fixes the fgl_glxgears pbuffer demo */
+ if (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode)
+ return GL_FALSE;
+#endif
+ if (ctxvis->stereoMode && !bufvis->stereoMode)
+ return GL_FALSE;
+ if (ctxvis->haveAccumBuffer && !bufvis->haveAccumBuffer)
+ return GL_FALSE;
+ if (ctxvis->haveDepthBuffer && !bufvis->haveDepthBuffer)
+ return GL_FALSE;
+ if (ctxvis->haveStencilBuffer && !bufvis->haveStencilBuffer)
+ return GL_FALSE;
+ if (ctxvis->redMask && ctxvis->redMask != bufvis->redMask)
+ return GL_FALSE;
+ if (ctxvis->greenMask && ctxvis->greenMask != bufvis->greenMask)
+ return GL_FALSE;
+ if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask)
+ return GL_FALSE;
+#if 0
+ /* disabled (see bug 11161) */
+ if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits)
+ return GL_FALSE;
+#endif
+ if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do one-time initialization for the given framebuffer. Specifically,
+ * ask the driver for the window's current size and update the framebuffer
+ * object to match.
+ * Really, the device driver should totally take care of this.
+ */
+static void
+initialize_framebuffer_size(GLcontext *ctx, GLframebuffer *fb)
+{
+ GLuint width, height;
+ if (ctx->Driver.GetBufferSize) {
+ ctx->Driver.GetBufferSize(fb, &width, &height);
+ if (ctx->Driver.ResizeBuffers)
+ ctx->Driver.ResizeBuffers(ctx, fb, width, height);
+ fb->Initialized = GL_TRUE;
+ }
+}
+
+
+/**
+ * Check if the viewport/scissor size has not yet been initialized.
+ * Initialize the size if the given width and height are non-zero.
+ */
+void
+_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height)
+{
+ if (!ctx->ViewportInitialized && width > 0 && height > 0) {
+ /* Note: set flag here, before calling _mesa_set_viewport(), to prevent
+ * potential infinite recursion.
+ */
+ ctx->ViewportInitialized = GL_TRUE;
+ _mesa_set_viewport(ctx, 0, 0, width, height);
+ _mesa_set_scissor(ctx, 0, 0, width, height);
+ }
+}
+
+
+/**
+ * Bind the given context to the given drawBuffer and readBuffer and
+ * make it the current context for the calling thread.
+ * We'll render into the drawBuffer and read pixels from the
+ * readBuffer (i.e. glRead/CopyPixels, glCopyTexImage, etc).
+ *
+ * We check that the context's and framebuffer's visuals are compatible
+ * and return immediately if they're not.
+ *
+ * \param newCtx the new GL context. If NULL then there will be no current GL
+ * context.
+ * \param drawBuffer the drawing framebuffer
+ * \param readBuffer the reading framebuffer
+ */
+GLboolean
+_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
+ GLframebuffer *readBuffer )
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(newCtx, "_mesa_make_current()\n");
+
+ /* Check that the context's and framebuffer's visuals are compatible.
+ */
+ if (newCtx && drawBuffer && newCtx->WinSysDrawBuffer != drawBuffer) {
+ if (!check_compatible(newCtx, drawBuffer)) {
+ _mesa_warning(newCtx,
+ "MakeCurrent: incompatible visuals for context and drawbuffer");
+ return GL_FALSE;
+ }
+ }
+ if (newCtx && readBuffer && newCtx->WinSysReadBuffer != readBuffer) {
+ if (!check_compatible(newCtx, readBuffer)) {
+ _mesa_warning(newCtx,
+ "MakeCurrent: incompatible visuals for context and readbuffer");
+ return GL_FALSE;
+ }
+ }
+
+ /* We used to call _glapi_check_multithread() here. Now do it in drivers */
+ _glapi_set_context((void *) newCtx);
+ ASSERT(_mesa_get_current_context() == newCtx);
+
+ if (!newCtx) {
+ _glapi_set_dispatch(NULL); /* none current */
+ }
+ else {
+ _glapi_set_dispatch(newCtx->CurrentDispatch);
+
+ if (drawBuffer && readBuffer) {
+ /* TODO: check if newCtx and buffer's visual match??? */
+
+ ASSERT(drawBuffer->Name == 0);
+ ASSERT(readBuffer->Name == 0);
+ _mesa_reference_framebuffer(&newCtx->WinSysDrawBuffer, drawBuffer);
+ _mesa_reference_framebuffer(&newCtx->WinSysReadBuffer, readBuffer);
+
+ /*
+ * Only set the context's Draw/ReadBuffer fields if they're NULL
+ * or not bound to a user-created FBO.
+ */
+ if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
+ /* KW: merge conflict here, revisit.
+ */
+ /* fix up the fb fields - these will end up wrong otherwise
+ * if the DRIdrawable changes, and everything relies on them.
+ * This is a bit messy (same as needed in _mesa_BindFramebufferEXT)
+ */
+ unsigned int i;
+ GLenum buffers[MAX_DRAW_BUFFERS];
+
+ _mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
+
+ for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
+ buffers[i] = newCtx->Color.DrawBuffer[i];
+ }
+
+ _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
+ }
+ if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
+ _mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
+ }
+
+ /* XXX only set this flag if we're really changing the draw/read
+ * framebuffer bindings.
+ */
+ newCtx->NewState |= _NEW_BUFFERS;
+
+#if 1
+ /* We want to get rid of these lines: */
+
+#if _HAVE_FULL_GL
+ if (!drawBuffer->Initialized) {
+ initialize_framebuffer_size(newCtx, drawBuffer);
+ }
+ if (readBuffer != drawBuffer && !readBuffer->Initialized) {
+ initialize_framebuffer_size(newCtx, readBuffer);
+ }
+
+ _mesa_resizebuffers(newCtx);
+#endif
+
+#else
+ /* We want the drawBuffer and readBuffer to be initialized by
+ * the driver.
+ * This generally means the Width and Height match the actual
+ * window size and the renderbuffers (both hardware and software
+ * based) are allocated to match. The later can generally be
+ * done with a call to _mesa_resize_framebuffer().
+ *
+ * It's theoretically possible for a buffer to have zero width
+ * or height, but for now, assert check that the driver did what's
+ * expected of it.
+ */
+ ASSERT(drawBuffer->Width > 0);
+ ASSERT(drawBuffer->Height > 0);
+#endif
+
+ if (drawBuffer) {
+ _mesa_check_init_viewport(newCtx,
+ drawBuffer->Width, drawBuffer->Height);
+ }
+ }
+
+ if (newCtx->FirstTimeCurrent) {
+ check_context_limits(newCtx);
+
+ /* We can use this to help debug user's problems. Tell them to set
+ * the MESA_INFO env variable before running their app. Then the
+ * first time each context is made current we'll print some useful
+ * information.
+ */
+ if (_mesa_getenv("MESA_INFO")) {
+ _mesa_print_info();
+ }
+
+ newCtx->FirstTimeCurrent = GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Make context 'ctx' share the display lists, textures and programs
+ * that are associated with 'ctxToShare'.
+ * Any display lists, textures or programs associated with 'ctx' will
+ * be deleted if nobody else is sharing them.
+ */
+GLboolean
+_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
+{
+ if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
+ struct gl_shared_state *oldSharedState = ctx->Shared;
+ GLint RefCount;
+
+ ctx->Shared = ctxToShare->Shared;
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ ctx->Shared->RefCount++;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ update_default_objects(ctx);
+
+ _glthread_LOCK_MUTEX(oldSharedState->Mutex);
+ RefCount = --oldSharedState->RefCount;
+ _glthread_UNLOCK_MUTEX(oldSharedState->Mutex);
+
+ if (RefCount == 0) {
+ _mesa_free_shared_state(ctx, oldSharedState);
+ }
+
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/**
+ * \return pointer to the current GL context for this thread.
+ *
+ * Calls _glapi_get_context(). This isn't the fastest way to get the current
+ * context. If you need speed, see the #GET_CURRENT_CONTEXT macro in
+ * context.h.
+ */
+GLcontext *
+_mesa_get_current_context( void )
+{
+ return (GLcontext *) _glapi_get_context();
+}
+
+
+/**
+ * Get context's current API dispatch table.
+ *
+ * It'll either be the immediate-mode execute dispatcher or the display list
+ * compile dispatcher.
+ *
+ * \param ctx GL context.
+ *
+ * \return pointer to dispatch_table.
+ *
+ * Simply returns __GLcontextRec::CurrentDispatch.
+ */
+struct _glapi_table *
+_mesa_get_dispatch(GLcontext *ctx)
+{
+ return ctx->CurrentDispatch;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Miscellaneous functions */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * Record an error.
+ *
+ * \param ctx GL context.
+ * \param error error code.
+ *
+ * Records the given error code and call the driver's dd_function_table::Error
+ * function if defined.
+ *
+ * \sa
+ * This is called via _mesa_error().
+ */
+void
+_mesa_record_error(GLcontext *ctx, GLenum error)
+{
+ if (!ctx)
+ return;
+
+ 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 glFinish().
+ *
+ * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the
+ * dd_function_table::Finish driver callback, if not NULL.
+ */
+void GLAPIENTRY
+_mesa_Finish(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT( ctx, 0 );
+ if (ctx->Driver.Finish) {
+ ctx->Driver.Finish(ctx);
+ }
+}
+
+
+/**
+ * Execute glFlush().
+ *
+ * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the
+ * dd_function_table::Flush driver callback, if not NULL.
+ */
+void GLAPIENTRY
+_mesa_Flush(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT( ctx, 0 );
+ if (ctx->Driver.Flush) {
+ ctx->Driver.Flush(ctx);
+ }
+}
+
+
+/**
+ * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over
+ * MUL/MAD, or vice versa, call this function to register that.
+ * Otherwise we default to MUL/MAD.
+ */
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag )
+{
+ ctx->mvp_with_dp4 = flag;
+}
+
+
+
+/**
+ * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
+ * is called to see if it's valid to render. This involves checking that
+ * the current shader is valid and the framebuffer is complete.
+ * If an error is detected it'll be recorded here.
+ * \return GL_TRUE if OK to render, GL_FALSE if not
+ */
+GLboolean
+_mesa_valid_to_render(GLcontext *ctx, const char *where)
+{
+ if (ctx->Shader.CurrentProgram) {
+ /* using shaders */
+ if (!ctx->Shader.CurrentProgram->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(shader not linked), where");
+ return GL_FALSE;
+ }
+#if 0 /* not normally enabled */
+ {
+ char errMsg[100];
+ if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
+ errMsg)) {
+ _mesa_warning(ctx, "Shader program %u is invalid: %s",
+ ctx->Shader.CurrentProgram->Name, errMsg);
+ }
+ }
+#endif
+ }
+ else {
+ if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(vertex program not valid)", where);
+ return GL_FALSE;
+ }
+ if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(fragment program not valid)", where);
+ return GL_FALSE;
+ }
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "%s(incomplete framebuffer)", where);
+ return GL_FALSE;
+ }
+
+#ifdef DEBUG
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ if (shProg) {
+ if (!shProg->_Used) {
+ /* This is the first time this shader is being used.
+ * Append shader's constants/uniforms to log file.
+ */
+ GLuint i;
+ for (i = 0; i < shProg->NumShaders; i++) {
+ struct gl_shader *sh = shProg->Shaders[i];
+ if (sh->Type == GL_VERTEX_SHADER) {
+ _mesa_append_uniforms_to_file(sh,
+ &shProg->VertexProgram->Base);
+ }
+ else if (sh->Type == GL_FRAGMENT_SHADER) {
+ _mesa_append_uniforms_to_file(sh,
+ &shProg->FragmentProgram->Base);
+ }
+ }
+ shProg->_Used = GL_TRUE;
+ }
+ }
+ }
+#endif
+
+ return GL_TRUE;
+}
+
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h
new file mode 100644
index 000000000..5587695fa
--- /dev/null
+++ b/mesalib/src/mesa/main/context.h
@@ -0,0 +1,308 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/**
+ * \file context.h
+ * Mesa context and visual-related functions.
+ *
+ * There are three large Mesa data types/classes 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
+ * data types. 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 data types.
+ */
+
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+
+#include "imports.h"
+#include "mtypes.h"
+
+
+struct _glapi_table;
+
+
+/** \name Visual-related functions */
+/*@{*/
+
+extern GLvisual *
+_mesa_create_visual( GLboolean rgbFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits,
+ GLint indexBits,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumRedBits,
+ GLint accumGreenBits,
+ GLint accumBlueBits,
+ GLint accumAlphaBits,
+ GLint numSamples );
+
+extern GLboolean
+_mesa_initialize_visual( GLvisual *v,
+ GLboolean rgbFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits,
+ GLint indexBits,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumRedBits,
+ GLint accumGreenBits,
+ GLint accumBlueBits,
+ GLint accumAlphaBits,
+ GLint numSamples );
+
+extern void
+_mesa_destroy_visual( GLvisual *vis );
+
+/*@}*/
+
+
+/** \name Context-related functions */
+/*@{*/
+
+extern GLcontext *
+_mesa_create_context( const GLvisual *visual,
+ GLcontext *share_list,
+ const struct dd_function_table *driverFunctions,
+ void *driverContext );
+
+extern GLboolean
+_mesa_initialize_context( GLcontext *ctx,
+ const GLvisual *visual,
+ GLcontext *share_list,
+ const struct dd_function_table *driverFunctions,
+ void *driverContext );
+
+extern void
+_mesa_initialize_context_extra(GLcontext *ctx);
+
+extern void
+_mesa_free_context_data( GLcontext *ctx );
+
+extern void
+_mesa_destroy_context( GLcontext *ctx );
+
+
+extern void
+_mesa_copy_context(const GLcontext *src, GLcontext *dst, GLuint mask);
+
+
+extern void
+_mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height);
+
+extern GLboolean
+_mesa_make_current( GLcontext *ctx, GLframebuffer *drawBuffer,
+ GLframebuffer *readBuffer );
+
+extern GLboolean
+_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare);
+
+extern GLcontext *
+_mesa_get_current_context(void);
+
+/*@}*/
+
+
+extern void
+_mesa_notifySwapBuffers(__GLcontext *gc);
+
+
+extern struct _glapi_table *
+_mesa_get_dispatch(GLcontext *ctx);
+
+
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag );
+
+
+extern GLboolean
+_mesa_valid_to_render(GLcontext *ctx, const char *where);
+
+
+
+/** \name Miscellaneous */
+/*@{*/
+
+extern void
+_mesa_record_error( GLcontext *ctx, GLenum error );
+
+extern void GLAPIENTRY
+_mesa_Finish( void );
+
+extern void GLAPIENTRY
+_mesa_Flush( void );
+
+/*@}*/
+
+
+/**
+ * \name Macros for flushing buffered rendering commands before state changes,
+ * checking if inside glBegin/glEnd, etc.
+ */
+/*@{*/
+
+/**
+ * Flush vertices.
+ *
+ * \param ctx GL context.
+ * \param newstate new state.
+ *
+ * Checks if dd_function_table::NeedFlush is marked to flush stored vertices,
+ * and calls dd_function_table::FlushVertices if so. Marks
+ * __GLcontextRec::NewState with \p newstate.
+ */
+#define FLUSH_VERTICES(ctx, newstate) \
+do { \
+ if (MESA_VERBOSE & VERBOSE_STATE) \
+ _mesa_debug(ctx, "FLUSH_VERTICES in %s\n", MESA_FUNCTION);\
+ if (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) \
+ ctx->Driver.FlushVertices(ctx, FLUSH_STORED_VERTICES); \
+ ctx->NewState |= newstate; \
+} while (0)
+
+/**
+ * Flush current state.
+ *
+ * \param ctx GL context.
+ * \param newstate new state.
+ *
+ * Checks if dd_function_table::NeedFlush is marked to flush current state,
+ * and calls dd_function_table::FlushVertices if so. Marks
+ * __GLcontextRec::NewState with \p newstate.
+ */
+#define FLUSH_CURRENT(ctx, newstate) \
+do { \
+ if (MESA_VERBOSE & VERBOSE_STATE) \
+ _mesa_debug(ctx, "FLUSH_CURRENT in %s\n", MESA_FUNCTION); \
+ if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) \
+ ctx->Driver.FlushVertices(ctx, FLUSH_UPDATE_CURRENT); \
+ ctx->NewState |= newstate; \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair, with return value.
+ *
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval) \
+do { \
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { \
+ _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd"); \
+ return retval; \
+ } \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair.
+ *
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END(ctx) \
+do { \
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { \
+ _mesa_error(ctx, GL_INVALID_OPERATION, "Inside glBegin/glEnd"); \
+ return; \
+ } \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices.
+ *
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx) \
+do { \
+ ASSERT_OUTSIDE_BEGIN_END(ctx); \
+ FLUSH_VERTICES(ctx, 0); \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices, with return value.
+ *
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval) \
+do { \
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval); \
+ FLUSH_VERTICES(ctx, 0); \
+} while (0)
+
+/*@}*/
+
+
+
+/**
+ * Is the secondary color needed?
+ */
+#define NEED_SECONDARY_COLOR(CTX) \
+ (((CTX)->Light.Enabled && \
+ (CTX)->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) \
+ || (CTX)->Fog.ColorSumEnabled \
+ || ((CTX)->VertexProgram._Current && \
+ ((CTX)->VertexProgram._Current != (CTX)->VertexProgram._TnlProgram) && \
+ ((CTX)->VertexProgram._Current->Base.InputsRead & VERT_BIT_COLOR1)) \
+ || ((CTX)->FragmentProgram._Current && \
+ ((CTX)->FragmentProgram._Current != (CTX)->FragmentProgram._TexEnvProgram) && \
+ ((CTX)->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL1)) \
+ )
+
+
+/**
+ * Is RGBA LogicOp enabled?
+ */
+#define RGBA_LOGICOP_ENABLED(CTX) \
+ ((CTX)->Color.ColorLogicOpEnabled || \
+ ((CTX)->Color.BlendEnabled && (CTX)->Color.BlendEquationRGB == GL_LOGIC_OP))
+
+
+#endif /* CONTEXT_H */
diff --git a/mesalib/src/mesa/main/convolve.c b/mesalib/src/mesa/main/convolve.c
new file mode 100644
index 000000000..70951112a
--- /dev/null
+++ b/mesalib/src/mesa/main/convolve.c
@@ -0,0 +1,1427 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * Image convolution functions.
+ *
+ * Notes: filter kernel elements are indexed by <n> and <m> as in
+ * the GL spec.
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "convolve.h"
+#include "context.h"
+#include "image.h"
+#include "mtypes.h"
+#include "pixel.h"
+#include "state.h"
+
+
+/*
+ * Given an internalFormat token passed to glConvolutionFilter
+ * or glSeparableFilter, return the corresponding base format.
+ * Return -1 if invalid token.
+ */
+static GLint
+base_filter_format( GLenum format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ 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 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 GLAPIENTRY
+_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image)
+{
+ GLint baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (target != GL_CONVOLUTION_1D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)");
+ return;
+ }
+
+ baseFormat = base_filter_format(internalFormat);
+ if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)");
+ return;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)");
+ return;
+ }
+
+ if (format == GL_COLOR_INDEX ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_COMPONENT ||
+ format == GL_INTENSITY ||
+ type == GL_BITMAP) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)");
+ return;
+ }
+
+ ctx->Convolution1D.Format = format;
+ ctx->Convolution1D.InternalFormat = internalFormat;
+ ctx->Convolution1D.Width = width;
+ ctx->Convolution1D.Height = 1;
+
+ image = _mesa_map_validate_pbo_source(ctx,
+ 1, &ctx->Unpack, width, 1, 1,
+ format, type, image,
+ "glConvolutionFilter1D");
+ if (!image)
+ return;
+
+ _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
+ ctx->Convolution1D.Filter,
+ format, type, image, &ctx->Unpack,
+ 0); /* transferOps */
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ _mesa_scale_and_bias_rgba(width,
+ (GLfloat (*)[4]) ctx->Convolution1D.Filter,
+ ctx->Pixel.ConvolutionFilterScale[0][0],
+ ctx->Pixel.ConvolutionFilterScale[0][1],
+ ctx->Pixel.ConvolutionFilterScale[0][2],
+ ctx->Pixel.ConvolutionFilterScale[0][3],
+ ctx->Pixel.ConvolutionFilterBias[0][0],
+ ctx->Pixel.ConvolutionFilterBias[0][1],
+ ctx->Pixel.ConvolutionFilterBias[0][2],
+ ctx->Pixel.ConvolutionFilterBias[0][3]);
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image)
+{
+ GLint baseFormat;
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (target != GL_CONVOLUTION_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)");
+ return;
+ }
+
+ baseFormat = base_filter_format(internalFormat);
+ if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)");
+ return;
+ }
+ if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)");
+ return;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)");
+ return;
+ }
+ if (format == GL_COLOR_INDEX ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_COMPONENT ||
+ format == GL_INTENSITY ||
+ type == GL_BITMAP) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)");
+ return;
+ }
+
+ /* this should have been caught earlier */
+ assert(_mesa_components_in_format(format));
+
+ ctx->Convolution2D.Format = format;
+ ctx->Convolution2D.InternalFormat = internalFormat;
+ ctx->Convolution2D.Width = width;
+ ctx->Convolution2D.Height = height;
+
+ image = _mesa_map_validate_pbo_source(ctx,
+ 2, &ctx->Unpack, width, height, 1,
+ format, type, image,
+ "glConvolutionFilter2D");
+ if (!image)
+ return;
+
+ /* Unpack filter image. We always store filters in RGBA format. */
+ for (i = 0; i < height; i++) {
+ const GLvoid *src = _mesa_image_address2d(&ctx->Unpack, image, width,
+ height, format, type, i, 0);
+ GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4;
+ _mesa_unpack_color_span_float(ctx, width, GL_RGBA, dst,
+ format, type, src, &ctx->Unpack,
+ 0); /* transferOps */
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ _mesa_scale_and_bias_rgba(width * height,
+ (GLfloat (*)[4]) ctx->Convolution2D.Filter,
+ ctx->Pixel.ConvolutionFilterScale[1][0],
+ ctx->Pixel.ConvolutionFilterScale[1][1],
+ ctx->Pixel.ConvolutionFilterScale[1][2],
+ ctx->Pixel.ConvolutionFilterScale[1][3],
+ ctx->Pixel.ConvolutionFilterBias[1][0],
+ ctx->Pixel.ConvolutionFilterBias[1][1],
+ ctx->Pixel.ConvolutionFilterBias[1][2],
+ ctx->Pixel.ConvolutionFilterBias[1][3]);
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_MODE:
+ if (param == (GLfloat) GL_REDUCE ||
+ param == (GLfloat) GL_CONSTANT_BORDER ||
+ param == (GLfloat) GL_REPLICATE_BORDER) {
+ ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)");
+ return;
+ }
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)");
+ return;
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_COLOR:
+ COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params);
+ break;
+ case GL_CONVOLUTION_BORDER_MODE:
+ if (params[0] == (GLfloat) GL_REDUCE ||
+ params[0] == (GLfloat) GL_CONSTANT_BORDER ||
+ params[0] == (GLfloat) GL_REPLICATE_BORDER) {
+ ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)");
+ return;
+ }
+ break;
+ case GL_CONVOLUTION_FILTER_SCALE:
+ COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params);
+ break;
+ case GL_CONVOLUTION_FILTER_BIAS:
+ COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)");
+ return;
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_MODE:
+ if (param == (GLint) GL_REDUCE ||
+ param == (GLint) GL_CONSTANT_BORDER ||
+ param == (GLint) GL_REPLICATE_BORDER) {
+ ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)");
+ return;
+ }
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)");
+ return;
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_COLOR:
+ ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]);
+ ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]);
+ ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]);
+ ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]);
+ break;
+ case GL_CONVOLUTION_BORDER_MODE:
+ if (params[0] == (GLint) GL_REDUCE ||
+ params[0] == (GLint) GL_CONSTANT_BORDER ||
+ params[0] == (GLint) GL_REPLICATE_BORDER) {
+ ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)");
+ return;
+ }
+ break;
+ case GL_CONVOLUTION_FILTER_SCALE:
+ /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */
+ /* need cast to prevent compiler warnings */
+ ctx->Pixel.ConvolutionFilterScale[c][0] = (GLfloat) params[0];
+ ctx->Pixel.ConvolutionFilterScale[c][1] = (GLfloat) params[1];
+ ctx->Pixel.ConvolutionFilterScale[c][2] = (GLfloat) params[2];
+ ctx->Pixel.ConvolutionFilterScale[c][3] = (GLfloat) params[3];
+ break;
+ case GL_CONVOLUTION_FILTER_BIAS:
+ /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */
+ /* need cast to prevent compiler warnings */
+ ctx->Pixel.ConvolutionFilterBias[c][0] = (GLfloat) params[0];
+ ctx->Pixel.ConvolutionFilterBias[c][1] = (GLfloat) params[1];
+ ctx->Pixel.ConvolutionFilterBias[c][2] = (GLfloat) params[2];
+ ctx->Pixel.ConvolutionFilterBias[c][3] = (GLfloat) params[3];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)");
+ return;
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+void GLAPIENTRY
+_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width)
+{
+ GLint baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (target != GL_CONVOLUTION_1D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)");
+ return;
+ }
+
+ baseFormat = base_filter_format(internalFormat);
+ if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)");
+ return;
+ }
+
+ ctx->Driver.CopyConvolutionFilter1D( ctx, target,
+ internalFormat, x, y, width);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GLint baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (target != GL_CONVOLUTION_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)");
+ return;
+ }
+
+ baseFormat = base_filter_format(internalFormat);
+ if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)");
+ return;
+ }
+ if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)");
+ return;
+ }
+
+ ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y,
+ width, height );
+}
+
+
+void GLAPIENTRY
+_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid *image)
+{
+ struct gl_convolution_attrib *filter;
+ GLuint row;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)");
+ return;
+ }
+
+ if (format == GL_COLOR_INDEX ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_COMPONENT ||
+ format == GL_INTENSITY ||
+ type == GL_BITMAP) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
+ return;
+ }
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ filter = &(ctx->Convolution1D);
+ break;
+ case GL_CONVOLUTION_2D:
+ filter = &(ctx->Convolution2D);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)");
+ return;
+ }
+
+ image = _mesa_map_validate_pbo_dest(ctx, 2, &ctx->Pack,
+ filter->Width, filter->Height, 1,
+ format, type, image,
+ "glGetConvolutionFilter");
+ if (!image)
+ return;
+
+ for (row = 0; row < filter->Height; row++) {
+ GLvoid *dst = _mesa_image_address2d(&ctx->Pack, image, filter->Width,
+ filter->Height, format, type,
+ row, 0);
+ GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + row * filter->Width * 4);
+ _mesa_pack_rgba_span_float(ctx, filter->Width, src,
+ format, type, dst, &ctx->Pack, 0x0);
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+void GLAPIENTRY
+_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const struct gl_convolution_attrib *conv;
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ conv = &ctx->Convolution1D;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ conv = &ctx->Convolution2D;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ conv = &ctx->Separable2D;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_COLOR:
+ COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]);
+ break;
+ case GL_CONVOLUTION_BORDER_MODE:
+ *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c];
+ break;
+ case GL_CONVOLUTION_FILTER_SCALE:
+ COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]);
+ break;
+ case GL_CONVOLUTION_FILTER_BIAS:
+ COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]);
+ break;
+ case GL_CONVOLUTION_FORMAT:
+ *params = (GLfloat) conv->Format;
+ break;
+ case GL_CONVOLUTION_WIDTH:
+ *params = (GLfloat) conv->Width;
+ break;
+ case GL_CONVOLUTION_HEIGHT:
+ *params = (GLfloat) conv->Height;
+ break;
+ case GL_MAX_CONVOLUTION_WIDTH:
+ *params = (GLfloat) ctx->Const.MaxConvolutionWidth;
+ break;
+ case GL_MAX_CONVOLUTION_HEIGHT:
+ *params = (GLfloat) ctx->Const.MaxConvolutionHeight;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const struct gl_convolution_attrib *conv;
+ GLuint c;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_CONVOLUTION_1D:
+ c = 0;
+ conv = &ctx->Convolution1D;
+ break;
+ case GL_CONVOLUTION_2D:
+ c = 1;
+ conv = &ctx->Convolution2D;
+ break;
+ case GL_SEPARABLE_2D:
+ c = 2;
+ conv = &ctx->Separable2D;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_CONVOLUTION_BORDER_COLOR:
+ params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]);
+ params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]);
+ params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]);
+ params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]);
+ break;
+ case GL_CONVOLUTION_BORDER_MODE:
+ *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c];
+ break;
+ case GL_CONVOLUTION_FILTER_SCALE:
+ params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0];
+ params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1];
+ params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2];
+ params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3];
+ break;
+ case GL_CONVOLUTION_FILTER_BIAS:
+ params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0];
+ params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1];
+ params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2];
+ params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3];
+ break;
+ case GL_CONVOLUTION_FORMAT:
+ *params = (GLint) conv->Format;
+ break;
+ case GL_CONVOLUTION_WIDTH:
+ *params = (GLint) conv->Width;
+ break;
+ case GL_CONVOLUTION_HEIGHT:
+ *params = (GLint) conv->Height;
+ break;
+ case GL_MAX_CONVOLUTION_WIDTH:
+ *params = (GLint) ctx->Const.MaxConvolutionWidth;
+ break;
+ case GL_MAX_CONVOLUTION_HEIGHT:
+ *params = (GLint) ctx->Const.MaxConvolutionHeight;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid *row, GLvoid *column, GLvoid *span)
+{
+ const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
+ struct gl_convolution_attrib *filter;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (target != GL_SEPARABLE_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)");
+ return;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetConvolutionFilter(format or type)");
+ return;
+ }
+
+ if (format == GL_COLOR_INDEX ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_COMPONENT ||
+ format == GL_INTENSITY ||
+ type == GL_BITMAP) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)");
+ return;
+ }
+
+ filter = &ctx->Separable2D;
+
+ /* Get row filter */
+ row = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ filter->Width, 1, 1,
+ format, type, row,
+ "glGetConvolutionFilter");
+ if (row) {
+ GLvoid *dst = _mesa_image_address1d(&ctx->Pack, row, filter->Width,
+ format, type, 0);
+ _mesa_pack_rgba_span_float(ctx, filter->Width,
+ (GLfloat (*)[4]) filter->Filter,
+ format, type, dst, &ctx->Pack, 0x0);
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+ }
+
+ /* get column filter */
+ column = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ filter->Height, 1, 1,
+ format, type, column,
+ "glGetConvolutionFilter");
+ if (column) {
+ GLvoid *dst = _mesa_image_address1d(&ctx->Pack, column, filter->Height,
+ format, type, 0);
+ GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + colStart);
+ _mesa_pack_rgba_span_float(ctx, filter->Height, src,
+ format, type, dst, &ctx->Pack, 0x0);
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+ }
+
+ (void) span; /* unused at this time */
+}
+
+
+void GLAPIENTRY
+_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column)
+{
+ const GLint colStart = MAX_CONVOLUTION_WIDTH * 4;
+ GLint baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (target != GL_SEPARABLE_2D) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)");
+ return;
+ }
+
+ baseFormat = base_filter_format(internalFormat);
+ if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)");
+ return;
+ }
+
+ if (width < 0 || width > MAX_CONVOLUTION_WIDTH) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)");
+ return;
+ }
+ if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)");
+ return;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(format or type)");
+ return;
+ }
+
+ if (format == GL_COLOR_INDEX ||
+ format == GL_STENCIL_INDEX ||
+ format == GL_DEPTH_COMPONENT ||
+ format == GL_INTENSITY ||
+ type == GL_BITMAP) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)");
+ return;
+ }
+
+ ctx->Separable2D.Format = format;
+ ctx->Separable2D.InternalFormat = internalFormat;
+ ctx->Separable2D.Width = width;
+ ctx->Separable2D.Height = height;
+
+ /* unpack row filter */
+ row = _mesa_map_validate_pbo_source(ctx, 1, &ctx->Unpack,
+ width, 1, 1,
+ format, type, row,
+ "glSeparableFilter2D");
+ if (row) {
+ _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
+ ctx->Separable2D.Filter,
+ format, type, row, &ctx->Unpack,
+ 0x0); /* transferOps */
+ _mesa_scale_and_bias_rgba(width,
+ (GLfloat (*)[4]) ctx->Separable2D.Filter,
+ ctx->Pixel.ConvolutionFilterScale[2][0],
+ ctx->Pixel.ConvolutionFilterScale[2][1],
+ ctx->Pixel.ConvolutionFilterScale[2][2],
+ ctx->Pixel.ConvolutionFilterScale[2][3],
+ ctx->Pixel.ConvolutionFilterBias[2][0],
+ ctx->Pixel.ConvolutionFilterBias[2][1],
+ ctx->Pixel.ConvolutionFilterBias[2][2],
+ ctx->Pixel.ConvolutionFilterBias[2][3]);
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+ }
+
+ /* unpack column filter */
+ column = _mesa_map_validate_pbo_source(ctx, 1, &ctx->Unpack,
+ height, 1, 1,
+ format, type, column,
+ "glSeparableFilter2D");
+ if (column) {
+ _mesa_unpack_color_span_float(ctx, height, GL_RGBA,
+ &ctx->Separable2D.Filter[colStart],
+ format, type, column, &ctx->Unpack,
+ 0); /* transferOps */
+
+ _mesa_scale_and_bias_rgba(height,
+ (GLfloat (*)[4]) (ctx->Separable2D.Filter + colStart),
+ ctx->Pixel.ConvolutionFilterScale[2][0],
+ ctx->Pixel.ConvolutionFilterScale[2][1],
+ ctx->Pixel.ConvolutionFilterScale[2][2],
+ ctx->Pixel.ConvolutionFilterScale[2][3],
+ ctx->Pixel.ConvolutionFilterBias[2][0],
+ ctx->Pixel.ConvolutionFilterBias[2][1],
+ ctx->Pixel.ConvolutionFilterBias[2][2],
+ ctx->Pixel.ConvolutionFilterBias[2][3]);
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+ }
+
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ ctx->Unpack.BufferObj);
+ }
+
+ ctx->NewState |= _NEW_PIXEL;
+}
+
+
+/**********************************************************************/
+/*** image convolution functions ***/
+/**********************************************************************/
+
+static void
+convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4],
+ GLint filterWidth, const GLfloat filter[][4],
+ GLfloat dest[][4])
+{
+ GLint dstWidth;
+ GLint i, n;
+
+ if (filterWidth >= 1)
+ dstWidth = srcWidth - (filterWidth - 1);
+ else
+ dstWidth = srcWidth;
+
+ if (dstWidth <= 0)
+ return; /* null result */
+
+ for (i = 0; i < dstWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (n = 0; n < filterWidth; n++) {
+ sumR += src[i + n][RCOMP] * filter[n][RCOMP];
+ sumG += src[i + n][GCOMP] * filter[n][GCOMP];
+ sumB += src[i + n][BCOMP] * filter[n][BCOMP];
+ sumA += src[i + n][ACOMP] * filter[n][ACOMP];
+ }
+ dest[i][RCOMP] = sumR;
+ dest[i][GCOMP] = sumG;
+ dest[i][BCOMP] = sumB;
+ dest[i][ACOMP] = sumA;
+ }
+}
+
+
+static void
+convolve_1d_constant(GLint srcWidth, const GLfloat src[][4],
+ GLint filterWidth, const GLfloat filter[][4],
+ GLfloat dest[][4],
+ const GLfloat borderColor[4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ GLint i, n;
+
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (n = 0; n < filterWidth; n++) {
+ if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) {
+ sumR += borderColor[RCOMP] * filter[n][RCOMP];
+ sumG += borderColor[GCOMP] * filter[n][GCOMP];
+ sumB += borderColor[BCOMP] * filter[n][BCOMP];
+ sumA += borderColor[ACOMP] * filter[n][ACOMP];
+ }
+ else {
+ sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
+ sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
+ sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
+ sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
+ }
+ }
+ dest[i][RCOMP] = sumR;
+ dest[i][GCOMP] = sumG;
+ dest[i][BCOMP] = sumB;
+ dest[i][ACOMP] = sumA;
+ }
+}
+
+
+static void
+convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4],
+ GLint filterWidth, const GLfloat filter[][4],
+ GLfloat dest[][4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ GLint i, n;
+
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (n = 0; n < filterWidth; n++) {
+ if (i + n < halfFilterWidth) {
+ sumR += src[0][RCOMP] * filter[n][RCOMP];
+ sumG += src[0][GCOMP] * filter[n][GCOMP];
+ sumB += src[0][BCOMP] * filter[n][BCOMP];
+ sumA += src[0][ACOMP] * filter[n][ACOMP];
+ }
+ else if (i + n - halfFilterWidth >= srcWidth) {
+ sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP];
+ sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP];
+ sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP];
+ sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP];
+ }
+ else {
+ sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP];
+ sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP];
+ sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP];
+ sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP];
+ }
+ }
+ dest[i][RCOMP] = sumR;
+ dest[i][GCOMP] = sumG;
+ dest[i][BCOMP] = sumB;
+ dest[i][ACOMP] = sumA;
+ }
+}
+
+
+static void
+convolve_2d_reduce(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat filter[][4],
+ GLfloat dest[][4])
+{
+ GLint dstWidth, dstHeight;
+ GLint i, j, n, m;
+
+ if (filterWidth >= 1)
+ dstWidth = srcWidth - (filterWidth - 1);
+ else
+ dstWidth = srcWidth;
+
+ if (filterHeight >= 1)
+ dstHeight = srcHeight - (filterHeight - 1);
+ else
+ dstHeight = srcHeight;
+
+ if (dstWidth <= 0 || dstHeight <= 0)
+ return;
+
+ for (j = 0; j < dstHeight; j++) {
+ for (i = 0; i < dstWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ const GLint k = (j + m) * srcWidth + i + n;
+ const GLint f = m * filterWidth + n;
+ sumR += src[k][RCOMP] * filter[f][RCOMP];
+ sumG += src[k][GCOMP] * filter[f][GCOMP];
+ sumB += src[k][BCOMP] * filter[f][BCOMP];
+ sumA += src[k][ACOMP] * filter[f][ACOMP];
+ }
+ }
+ dest[j * dstWidth + i][RCOMP] = sumR;
+ dest[j * dstWidth + i][GCOMP] = sumG;
+ dest[j * dstWidth + i][BCOMP] = sumB;
+ dest[j * dstWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+static void
+convolve_2d_constant(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat filter[][4],
+ GLfloat dest[][4],
+ const GLfloat borderColor[4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ const GLint halfFilterHeight = filterHeight / 2;
+ GLint i, j, n, m;
+
+ for (j = 0; j < srcHeight; j++) {
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ const GLint f = m * filterWidth + n;
+ const GLint is = i + n - halfFilterWidth;
+ const GLint js = j + m - halfFilterHeight;
+ if (is < 0 || is >= srcWidth ||
+ js < 0 || js >= srcHeight) {
+ sumR += borderColor[RCOMP] * filter[f][RCOMP];
+ sumG += borderColor[GCOMP] * filter[f][GCOMP];
+ sumB += borderColor[BCOMP] * filter[f][BCOMP];
+ sumA += borderColor[ACOMP] * filter[f][ACOMP];
+ }
+ else {
+ const GLint k = js * srcWidth + is;
+ sumR += src[k][RCOMP] * filter[f][RCOMP];
+ sumG += src[k][GCOMP] * filter[f][GCOMP];
+ sumB += src[k][BCOMP] * filter[f][BCOMP];
+ sumA += src[k][ACOMP] * filter[f][ACOMP];
+ }
+ }
+ }
+ dest[j * srcWidth + i][RCOMP] = sumR;
+ dest[j * srcWidth + i][GCOMP] = sumG;
+ dest[j * srcWidth + i][BCOMP] = sumB;
+ dest[j * srcWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+static void
+convolve_2d_replicate(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat filter[][4],
+ GLfloat dest[][4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ const GLint halfFilterHeight = filterHeight / 2;
+ GLint i, j, n, m;
+
+ for (j = 0; j < srcHeight; j++) {
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ const GLint f = m * filterWidth + n;
+ GLint is = i + n - halfFilterWidth;
+ GLint js = j + m - halfFilterHeight;
+ GLint k;
+ if (is < 0)
+ is = 0;
+ else if (is >= srcWidth)
+ is = srcWidth - 1;
+ if (js < 0)
+ js = 0;
+ else if (js >= srcHeight)
+ js = srcHeight - 1;
+ k = js * srcWidth + is;
+ sumR += src[k][RCOMP] * filter[f][RCOMP];
+ sumG += src[k][GCOMP] * filter[f][GCOMP];
+ sumB += src[k][BCOMP] * filter[f][BCOMP];
+ sumA += src[k][ACOMP] * filter[f][ACOMP];
+ }
+ }
+ dest[j * srcWidth + i][RCOMP] = sumR;
+ dest[j * srcWidth + i][GCOMP] = sumG;
+ dest[j * srcWidth + i][BCOMP] = sumB;
+ dest[j * srcWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+static void
+convolve_sep_reduce(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat rowFilt[][4],
+ const GLfloat colFilt[][4],
+ GLfloat dest[][4])
+{
+ GLint dstWidth, dstHeight;
+ GLint i, j, n, m;
+
+ if (filterWidth >= 1)
+ dstWidth = srcWidth - (filterWidth - 1);
+ else
+ dstWidth = srcWidth;
+
+ if (filterHeight >= 1)
+ dstHeight = srcHeight - (filterHeight - 1);
+ else
+ dstHeight = srcHeight;
+
+ if (dstWidth <= 0 || dstHeight <= 0)
+ return;
+
+ for (j = 0; j < dstHeight; j++) {
+ for (i = 0; i < dstWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ GLint k = (j + m) * srcWidth + i + n;
+ sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
+ sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
+ sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
+ sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
+ }
+ }
+ dest[j * dstWidth + i][RCOMP] = sumR;
+ dest[j * dstWidth + i][GCOMP] = sumG;
+ dest[j * dstWidth + i][BCOMP] = sumB;
+ dest[j * dstWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+static void
+convolve_sep_constant(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat rowFilt[][4],
+ const GLfloat colFilt[][4],
+ GLfloat dest[][4],
+ const GLfloat borderColor[4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ const GLint halfFilterHeight = filterHeight / 2;
+ GLint i, j, n, m;
+
+ for (j = 0; j < srcHeight; j++) {
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ const GLint is = i + n - halfFilterWidth;
+ const GLint js = j + m - halfFilterHeight;
+ if (is < 0 || is >= srcWidth ||
+ js < 0 || js >= srcHeight) {
+ sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
+ sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
+ sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
+ sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
+ }
+ else {
+ GLint k = js * srcWidth + is;
+ sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
+ sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
+ sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
+ sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
+ }
+
+ }
+ }
+ dest[j * srcWidth + i][RCOMP] = sumR;
+ dest[j * srcWidth + i][GCOMP] = sumG;
+ dest[j * srcWidth + i][BCOMP] = sumB;
+ dest[j * srcWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+static void
+convolve_sep_replicate(GLint srcWidth, GLint srcHeight,
+ const GLfloat src[][4],
+ GLint filterWidth, GLint filterHeight,
+ const GLfloat rowFilt[][4],
+ const GLfloat colFilt[][4],
+ GLfloat dest[][4])
+{
+ const GLint halfFilterWidth = filterWidth / 2;
+ const GLint halfFilterHeight = filterHeight / 2;
+ GLint i, j, n, m;
+
+ for (j = 0; j < srcHeight; j++) {
+ for (i = 0; i < srcWidth; i++) {
+ GLfloat sumR = 0.0;
+ GLfloat sumG = 0.0;
+ GLfloat sumB = 0.0;
+ GLfloat sumA = 0.0;
+ for (m = 0; m < filterHeight; m++) {
+ for (n = 0; n < filterWidth; n++) {
+ GLint is = i + n - halfFilterWidth;
+ GLint js = j + m - halfFilterHeight;
+ GLint k;
+ if (is < 0)
+ is = 0;
+ else if (is >= srcWidth)
+ is = srcWidth - 1;
+ if (js < 0)
+ js = 0;
+ else if (js >= srcHeight)
+ js = srcHeight - 1;
+ k = js * srcWidth + is;
+ sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP];
+ sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP];
+ sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP];
+ sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP];
+ }
+ }
+ dest[j * srcWidth + i][RCOMP] = sumR;
+ dest[j * srcWidth + i][GCOMP] = sumG;
+ dest[j * srcWidth + i][BCOMP] = sumB;
+ dest[j * srcWidth + i][ACOMP] = sumA;
+ }
+ }
+}
+
+
+
+void
+_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ switch (ctx->Pixel.ConvolutionBorderMode[0]) {
+ case GL_REDUCE:
+ convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution1D.Width,
+ (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
+ (GLfloat (*)[4]) dstImage);
+ *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
+ break;
+ case GL_CONSTANT_BORDER:
+ convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution1D.Width,
+ (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
+ (GLfloat (*)[4]) dstImage,
+ ctx->Pixel.ConvolutionBorderColor[0]);
+ break;
+ case GL_REPLICATE_BORDER:
+ convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution1D.Width,
+ (const GLfloat (*)[4]) ctx->Convolution1D.Filter,
+ (GLfloat (*)[4]) dstImage);
+ break;
+ default:
+ ;
+ }
+}
+
+
+void
+_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ switch (ctx->Pixel.ConvolutionBorderMode[1]) {
+ case GL_REDUCE:
+ convolve_2d_reduce(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution2D.Width,
+ ctx->Convolution2D.Height,
+ (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
+ (GLfloat (*)[4]) dstImage);
+ *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
+ *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
+ break;
+ case GL_CONSTANT_BORDER:
+ convolve_2d_constant(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution2D.Width,
+ ctx->Convolution2D.Height,
+ (const GLfloat (*)[4]) ctx->Convolution2D.Filter,
+ (GLfloat (*)[4]) dstImage,
+ ctx->Pixel.ConvolutionBorderColor[1]);
+ break;
+ case GL_REPLICATE_BORDER:
+ convolve_2d_replicate(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Convolution2D.Width,
+ ctx->Convolution2D.Height,
+ (const GLfloat (*)[4])ctx->Convolution2D.Filter,
+ (GLfloat (*)[4]) dstImage);
+ break;
+ default:
+ ;
+ }
+}
+
+
+void
+_mesa_convolve_sep_image(const GLcontext *ctx,
+ GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage)
+{
+ const GLfloat *rowFilter = ctx->Separable2D.Filter;
+ const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH;
+
+ switch (ctx->Pixel.ConvolutionBorderMode[2]) {
+ case GL_REDUCE:
+ convolve_sep_reduce(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Separable2D.Width,
+ ctx->Separable2D.Height,
+ (const GLfloat (*)[4]) rowFilter,
+ (const GLfloat (*)[4]) colFilter,
+ (GLfloat (*)[4]) dstImage);
+ *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
+ *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
+ break;
+ case GL_CONSTANT_BORDER:
+ convolve_sep_constant(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Separable2D.Width,
+ ctx->Separable2D.Height,
+ (const GLfloat (*)[4]) rowFilter,
+ (const GLfloat (*)[4]) colFilter,
+ (GLfloat (*)[4]) dstImage,
+ ctx->Pixel.ConvolutionBorderColor[2]);
+ break;
+ case GL_REPLICATE_BORDER:
+ convolve_sep_replicate(*width, *height,
+ (const GLfloat (*)[4]) srcImage,
+ ctx->Separable2D.Width,
+ ctx->Separable2D.Height,
+ (const GLfloat (*)[4]) rowFilter,
+ (const GLfloat (*)[4]) colFilter,
+ (GLfloat (*)[4]) dstImage);
+ break;
+ default:
+ ;
+ }
+}
+
+
+
+/*
+ * This function computes an image's size after convolution.
+ * If the convolution border mode is GL_REDUCE, the post-convolution
+ * image will be smaller than the original.
+ */
+void
+_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
+ GLsizei *width, GLsizei *height)
+{
+ if (ctx->Pixel.Convolution1DEnabled
+ && dimensions == 1
+ && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
+ *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
+ }
+ else if (ctx->Pixel.Convolution2DEnabled
+ && dimensions > 1
+ && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
+ *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
+ *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
+ }
+ else if (ctx->Pixel.Separable2DEnabled
+ && dimensions > 1
+ && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
+ *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
+ *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
+ }
+}
diff --git a/mesalib/src/mesa/main/convolve.h b/mesalib/src/mesa/main/convolve.h
new file mode 100644
index 000000000..4505cdae0
--- /dev/null
+++ b/mesalib/src/mesa/main/convolve.h
@@ -0,0 +1,114 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef CONVOLVE_H
+#define CONVOLVE_H
+
+
+#include "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+extern void GLAPIENTRY
+_mesa_ConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width,
+ GLenum format, GLenum type, const GLvoid *image);
+
+extern void GLAPIENTRY
+_mesa_ConvolutionFilter2D(GLenum target, GLenum internalformat, GLsizei width,
+ GLsizei height, GLenum format, GLenum type,
+ const GLvoid *image);
+
+extern void GLAPIENTRY
+_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat params);
+
+extern void GLAPIENTRY
+_mesa_ConvolutionParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint params);
+
+extern void GLAPIENTRY
+_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params);
+
+extern void GLAPIENTRY
+_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width);
+
+extern void GLAPIENTRY
+_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid *image);
+
+extern void GLAPIENTRY
+_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid *row, GLvoid *column, GLvoid *span);
+
+extern void GLAPIENTRY
+_mesa_SeparableFilter2D(GLenum target, GLenum internalformat,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *row, const GLvoid *column);
+
+
+
+extern void
+_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width,
+ const GLfloat *srcImage, GLfloat *dstImage);
+
+
+extern void
+_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage);
+
+
+extern void
+_mesa_convolve_sep_image(const GLcontext *ctx,
+ GLsizei *width, GLsizei *height,
+ const GLfloat *srcImage, GLfloat *dstImage);
+
+
+extern void
+_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions,
+ GLsizei *width, GLsizei *height);
+
+#else
+#define _mesa_adjust_image_for_convolution(c, d, w, h) ((void)0)
+#define _mesa_convolve_1d_image(c,w,s,d) ((void)0)
+#define _mesa_convolve_2d_image(c,w,h,s,d) ((void)0)
+#define _mesa_convolve_sep_image(c,w,h,s,d) ((void)0)
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/cpuinfo.c b/mesalib/src/mesa/main/cpuinfo.c
new file mode 100644
index 000000000..b4bfb40eb
--- /dev/null
+++ b/mesalib/src/mesa/main/cpuinfo.c
@@ -0,0 +1,109 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "main/imports.h"
+#include "main/cpuinfo.h"
+
+
+/**
+ * This function should be called before the various "cpu_has_foo" macros
+ * are used.
+ */
+void
+_mesa_get_cpu_features(void)
+{
+#ifdef USE_X86_ASM
+ _mesa_get_x86_features();
+#endif
+}
+
+
+/**
+ * Return a string describing the CPU architexture and extensions that
+ * Mesa is using (such as SSE or Altivec).
+ * \return information string, free it with _mesa_free()
+ */
+char *
+_mesa_get_cpu_string(void)
+{
+#define MAX_STRING 50
+ char *buffer;
+
+ buffer = (char *) _mesa_malloc(MAX_STRING);
+ if (!buffer)
+ return NULL;
+
+ buffer[0] = 0;
+
+#ifdef USE_X86_ASM
+
+ if (_mesa_x86_cpu_features) {
+ strcat(buffer, "x86");
+ }
+
+# ifdef USE_MMX_ASM
+ if (cpu_has_mmx) {
+ strcat(buffer, (cpu_has_mmxext) ? "/MMX+" : "/MMX");
+ }
+# endif
+# ifdef USE_3DNOW_ASM
+ if (cpu_has_3dnow) {
+ strcat(buffer, (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!");
+ }
+# endif
+# ifdef USE_SSE_ASM
+ if (cpu_has_xmm) {
+ strcat(buffer, (cpu_has_xmm2) ? "/SSE2" : "/SSE");
+ }
+# endif
+
+#elif defined(USE_SPARC_ASM)
+
+ strcat(buffer, "SPARC");
+
+#elif defined(USE_PPC_ASM)
+
+ if (_mesa_ppc_cpu_features) {
+ strcat(buffer, (cpu_has_64) ? "PowerPC 64" : "PowerPC");
+ }
+
+# ifdef USE_VMX_ASM
+
+ if (cpu_has_vmx) {
+ strcat(buffer, "/Altivec");
+ }
+
+# endif
+
+ if (! cpu_has_fpu) {
+ strcat(buffer, "/No FPU");
+ }
+
+#endif
+
+ assert(_mesa_strlen(buffer) < MAX_STRING);
+
+ return buffer;
+}
diff --git a/mesalib/src/mesa/main/cpuinfo.h b/mesalib/src/mesa/main/cpuinfo.h
new file mode 100644
index 000000000..c41a90b07
--- /dev/null
+++ b/mesalib/src/mesa/main/cpuinfo.h
@@ -0,0 +1,47 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 CPUINFO_H
+#define CPUINFO_H
+
+
+#if defined(USE_X86_ASM)
+#include "x86/common_x86_asm.h"
+#endif
+
+#if defined(USE_PPC_ASM)
+#include "ppc/common_ppc_features.h"
+#endif
+
+
+extern void
+_mesa_get_cpu_features(void);
+
+
+extern char *
+_mesa_get_cpu_string(void);
+
+
+#endif /* CPUINFO_H */
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
new file mode 100644
index 000000000..4a700b5cb
--- /dev/null
+++ b/mesalib/src/mesa/main/dd.h
@@ -0,0 +1,1195 @@
+/**
+ * \file dd.h
+ * Device driver interfaces.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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
+
+/* THIS FILE ONLY INCLUDED BY mtypes.h !!!!! */
+
+struct gl_pixelstore_attrib;
+struct gl_display_list;
+
+#if FEATURE_ARB_vertex_buffer_object
+/* Modifies GL_MAP_UNSYNCHRONIZED_BIT to allow driver to fail (return
+ * NULL) if buffer is unavailable for immediate mapping.
+ *
+ * Does GL_MAP_INVALIDATE_RANGE_BIT do this? It seems so, but it
+ * would require more book-keeping in the driver than seems necessary
+ * at this point.
+ *
+ * Does GL_MAP_INVALDIATE_BUFFER_BIT do this? Not really -- we don't
+ * want to provoke the driver to throw away the old storage, we will
+ * respect the contents of already referenced data.
+ */
+#define MESA_MAP_NOWAIT_BIT 0x0040
+#endif
+
+
+/**
+ * Device driver function table.
+ * Core Mesa uses these function pointers to call into device drivers.
+ * Most of these functions directly correspond to OpenGL state commands.
+ * Core Mesa will call these functions after error checking has been done
+ * so that the drivers don't have to worry about error testing.
+ *
+ * Vertex transformation/clipping/lighting is patched into the T&L module.
+ * Rasterization functions are patched into the swrast module.
+ *
+ * Note: when new functions are added here, the drivers/common/driverfuncs.c
+ * file should be updated too!!!
+ */
+struct dd_function_table {
+ /**
+ * Return a string as needed by glGetString().
+ * Only the GL_RENDERER query must be implemented. Otherwise, NULL can be
+ * returned.
+ */
+ const GLubyte * (*GetString)( GLcontext *ctx, GLenum name );
+
+ /**
+ * Notify the driver after Mesa has made some internal state changes.
+ *
+ * This is in addition to any state change callbacks Mesa may already have
+ * made.
+ */
+ void (*UpdateState)( GLcontext *ctx, GLbitfield new_state );
+
+ /**
+ * Get the width and height of the named buffer/window.
+ *
+ * Mesa uses this to determine when the driver's window size has changed.
+ * XXX OBSOLETE: this function will be removed in the future.
+ */
+ void (*GetBufferSize)( GLframebuffer *buffer,
+ GLuint *width, GLuint *height );
+
+ /**
+ * Resize the given framebuffer to the given size.
+ * XXX OBSOLETE: this function will be removed in the future.
+ */
+ void (*ResizeBuffers)( GLcontext *ctx, GLframebuffer *fb,
+ GLuint width, GLuint height);
+
+ /**
+ * Called whenever an error is generated.
+ * __GLcontextRec::ErrorValue contains the error value.
+ */
+ void (*Error)( GLcontext *ctx );
+
+ /**
+ * This is called whenever glFinish() is called.
+ */
+ void (*Finish)( GLcontext *ctx );
+
+ /**
+ * This is called whenever glFlush() is called.
+ */
+ void (*Flush)( GLcontext *ctx );
+
+ /**
+ * Clear the color/depth/stencil/accum buffer(s).
+ * \param buffers a bitmask of BUFFER_BIT_* flags indicating which
+ * renderbuffers need to be cleared.
+ */
+ void (*Clear)( GLcontext *ctx, GLbitfield buffers );
+
+ /**
+ * Execute glAccum command.
+ */
+ void (*Accum)( GLcontext *ctx, GLenum op, GLfloat value );
+
+
+ /**
+ * Execute glRasterPos, updating the ctx->Current.Raster fields
+ */
+ void (*RasterPos)( GLcontext *ctx, const GLfloat v[4] );
+
+ /**
+ * \name Image-related functions
+ */
+ /*@{*/
+
+ /**
+ * Called by glDrawPixels().
+ * \p unpack describes how to unpack the source image data.
+ */
+ void (*DrawPixels)( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels );
+
+ /**
+ * Called by glReadPixels().
+ */
+ void (*ReadPixels)( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ GLvoid *dest );
+
+ /**
+ * Called by glCopyPixels().
+ */
+ void (*CopyPixels)( GLcontext *ctx, GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type );
+
+ /**
+ * Called by glBitmap().
+ */
+ void (*Bitmap)( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap );
+ /*@}*/
+
+
+ /**
+ * \name Texture image functions
+ */
+ /*@{*/
+
+ /**
+ * Choose texture format.
+ *
+ * This is called by the \c _mesa_store_tex[sub]image[123]d() fallback
+ * functions. The driver should examine \p internalFormat and return a
+ * pointer to an appropriate gl_texture_format.
+ */
+ const struct gl_texture_format *(*ChooseTextureFormat)( GLcontext *ctx,
+ GLint internalFormat, GLenum srcFormat, GLenum srcType );
+
+ /**
+ * Called by glTexImage1D().
+ *
+ * \param target user specified.
+ * \param format user specified.
+ * \param type user specified.
+ * \param pixels user specified.
+ * \param packing indicates the image packing of pixels.
+ * \param texObj is the target texture object.
+ * \param texImage is the target texture image. It will have the texture \p
+ * width, \p height, \p depth, \p border and \p internalFormat information.
+ *
+ * \p retainInternalCopy is returned by this function and indicates whether
+ * core Mesa should keep an internal copy of the texture image.
+ *
+ * Drivers should call a fallback routine from texstore.c if needed.
+ */
+ void (*TexImage1D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glTexImage2D().
+ *
+ * \sa dd_function_table::TexImage1D.
+ */
+ void (*TexImage2D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glTexImage3D().
+ *
+ * \sa dd_function_table::TexImage1D.
+ */
+ void (*TexImage3D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glTexSubImage1D().
+ *
+ * \param target user specified.
+ * \param level user specified.
+ * \param xoffset user specified.
+ * \param yoffset user specified.
+ * \param zoffset user specified.
+ * \param width user specified.
+ * \param height user specified.
+ * \param depth user specified.
+ * \param format user specified.
+ * \param type user specified.
+ * \param pixels user specified.
+ * \param packing indicates the image packing of pixels.
+ * \param texObj is the target texture object.
+ * \param texImage is the target texture image. It will have the texture \p
+ * width, \p height, \p border and \p internalFormat information.
+ *
+ * The driver should use a fallback routine from texstore.c if needed.
+ */
+ void (*TexSubImage1D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glTexSubImage2D().
+ *
+ * \sa dd_function_table::TexSubImage1D.
+ */
+ void (*TexSubImage2D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glTexSubImage3D().
+ *
+ * \sa dd_function_table::TexSubImage1D.
+ */
+ void (*TexSubImage3D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLint depth,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glGetTexImage().
+ */
+ void (*GetTexImage)( GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glCopyTexImage1D().
+ *
+ * Drivers should use a fallback routine from texstore.c if needed.
+ */
+ void (*CopyTexImage1D)( GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLint border );
+
+ /**
+ * Called by glCopyTexImage2D().
+ *
+ * Drivers should use a fallback routine from texstore.c if needed.
+ */
+ void (*CopyTexImage2D)( GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border );
+
+ /**
+ * Called by glCopyTexSubImage1D().
+ *
+ * Drivers should use a fallback routine from texstore.c if needed.
+ */
+ void (*CopyTexSubImage1D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset,
+ GLint x, GLint y, GLsizei width );
+ /**
+ * Called by glCopyTexSubImage2D().
+ *
+ * Drivers should use a fallback routine from texstore.c if needed.
+ */
+ void (*CopyTexSubImage2D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+ /**
+ * Called by glCopyTexSubImage3D().
+ *
+ * Drivers should use a fallback routine from texstore.c if needed.
+ */
+ void (*CopyTexSubImage3D)( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+ /**
+ * Called by glGenerateMipmap() or when GL_GENERATE_MIPMAP_SGIS is enabled.
+ */
+ void (*GenerateMipmap)(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+ /**
+ * Called by glTexImage[123]D when user specifies a proxy texture
+ * target.
+ *
+ * \return GL_TRUE if the proxy test passes, or GL_FALSE if the test fails.
+ */
+ GLboolean (*TestProxyTexImage)(GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLint width, GLint height,
+ GLint depth, GLint border);
+ /*@}*/
+
+
+ /**
+ * \name Compressed texture functions
+ */
+ /*@{*/
+
+ /**
+ * Called by glCompressedTexImage1D().
+ *
+ * \param target user specified.
+ * \param format user specified.
+ * \param type user specified.
+ * \param pixels user specified.
+ * \param packing indicates the image packing of pixels.
+ * \param texObj is the target texture object.
+ * \param texImage is the target texture image. It will have the texture \p
+ * width, \p height, \p depth, \p border and \p internalFormat information.
+ *
+ * \a retainInternalCopy is returned by this function and indicates whether
+ * core Mesa should keep an internal copy of the texture image.
+ */
+ void (*CompressedTexImage1D)( GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+ /**
+ * Called by glCompressedTexImage2D().
+ *
+ * \sa dd_function_table::CompressedTexImage1D.
+ */
+ void (*CompressedTexImage2D)( GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+ /**
+ * Called by glCompressedTexImage3D().
+ *
+ * \sa dd_function_table::CompressedTexImage3D.
+ */
+ void (*CompressedTexImage3D)( GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage );
+
+ /**
+ * Called by glCompressedTexSubImage1D().
+ *
+ * \param target user specified.
+ * \param level user specified.
+ * \param xoffset user specified.
+ * \param yoffset user specified.
+ * \param zoffset user specified.
+ * \param width user specified.
+ * \param height user specified.
+ * \param depth user specified.
+ * \param imageSize user specified.
+ * \param data user specified.
+ * \param texObj is the target texture object.
+ * \param texImage is the target texture image. It will have the texture \p
+ * width, \p height, \p depth, \p border and \p internalFormat information.
+ */
+ void (*CompressedTexSubImage1D)(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+ /**
+ * Called by glCompressedTexSubImage2D().
+ *
+ * \sa dd_function_table::CompressedTexImage3D.
+ */
+ void (*CompressedTexSubImage2D)(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLint height,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+ /**
+ * Called by glCompressedTexSubImage3D().
+ *
+ * \sa dd_function_table::CompressedTexImage3D.
+ */
+ void (*CompressedTexSubImage3D)(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLint height, GLint depth,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+ /**
+ * Called by glGetCompressedTexImage.
+ */
+ void (*GetCompressedTexImage)(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+ /**
+ * Called to query number of bytes of storage needed to store the
+ * specified compressed texture.
+ */
+ GLuint (*CompressedTextureSize)( GLcontext *ctx, GLsizei width,
+ GLsizei height, GLsizei depth,
+ GLenum format );
+ /*@}*/
+
+ /**
+ * \name Texture object functions
+ */
+ /*@{*/
+
+ /**
+ * Called by glBindTexture().
+ */
+ void (*BindTexture)( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj );
+
+ /**
+ * Called to allocate a new texture object.
+ * A new gl_texture_object should be returned. The driver should
+ * attach to it any device-specific info it needs.
+ */
+ struct gl_texture_object * (*NewTextureObject)( GLcontext *ctx, GLuint name,
+ GLenum target );
+ /**
+ * Called when a texture object is about to be deallocated.
+ *
+ * Driver should delete the gl_texture_object object and anything
+ * hanging off of it.
+ */
+ void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj );
+
+ /**
+ * Called to allocate a new texture image object.
+ */
+ struct gl_texture_image * (*NewTextureImage)( GLcontext *ctx );
+
+ /**
+ * Called to free tImage->Data.
+ */
+ void (*FreeTexImageData)( GLcontext *ctx, struct gl_texture_image *tImage );
+
+ /** Map texture image data into user space */
+ void (*MapTexture)( GLcontext *ctx, struct gl_texture_object *tObj );
+ /** Unmap texture images from user space */
+ void (*UnmapTexture)( GLcontext *ctx, struct gl_texture_object *tObj );
+
+ /**
+ * Note: no context argument. This function doesn't initially look
+ * like it belongs here, except that the driver is the only entity
+ * that knows for sure how the texture memory is allocated - via
+ * the above callbacks. There is then an argument that the driver
+ * knows what memcpy paths might be fast. Typically this is invoked with
+ *
+ * to -- a pointer into texture memory allocated by NewTextureImage() above.
+ * from -- a pointer into client memory or a mesa temporary.
+ * sz -- nr bytes to copy.
+ */
+ void* (*TextureMemCpy)( void *to, const void *from, size_t sz );
+
+ /**
+ * Called by glAreTextureResident().
+ */
+ GLboolean (*IsTextureResident)( GLcontext *ctx,
+ struct gl_texture_object *t );
+
+ /**
+ * Called by glPrioritizeTextures().
+ */
+ void (*PrioritizeTexture)( GLcontext *ctx, struct gl_texture_object *t,
+ GLclampf priority );
+
+ /**
+ * Called by glActiveTextureARB() to set current texture unit.
+ */
+ void (*ActiveTexture)( GLcontext *ctx, GLuint texUnitNumber );
+
+ /**
+ * Called when the texture's color lookup table is changed.
+ *
+ * If \p tObj is NULL then the shared texture palette
+ * gl_texture_object::Palette is to be updated.
+ */
+ void (*UpdateTexturePalette)( GLcontext *ctx,
+ struct gl_texture_object *tObj );
+ /*@}*/
+
+
+ /**
+ * \name Imaging functionality
+ */
+ /*@{*/
+ void (*CopyColorTable)( GLcontext *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width );
+
+ void (*CopyColorSubTable)( GLcontext *ctx,
+ GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width );
+
+ void (*CopyConvolutionFilter1D)( GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width );
+
+ void (*CopyConvolutionFilter2D)( GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+ /*@}*/
+
+
+ /**
+ * \name Vertex/fragment program functions
+ */
+ /*@{*/
+ /** Bind a vertex/fragment program */
+ void (*BindProgram)(GLcontext *ctx, GLenum target, struct gl_program *prog);
+ /** Allocate a new program */
+ struct gl_program * (*NewProgram)(GLcontext *ctx, GLenum target, GLuint id);
+ /** Delete a program */
+ void (*DeleteProgram)(GLcontext *ctx, struct gl_program *prog);
+ /** Notify driver that a program string has been specified. */
+ void (*ProgramStringNotify)(GLcontext *ctx, GLenum target,
+ struct gl_program *prog);
+
+ /** Query if program can be loaded onto hardware */
+ GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target,
+ struct gl_program *prog);
+
+ /*@}*/
+
+
+ /**
+ * \name State-changing functions.
+ *
+ * \note drawing functions are above.
+ *
+ * These functions are called by their corresponding OpenGL API functions.
+ * They are \e also called by the gl_PopAttrib() function!!!
+ * May add more functions like these to the device driver in the future.
+ */
+ /*@{*/
+ /** Specify the alpha test function */
+ void (*AlphaFunc)(GLcontext *ctx, GLenum func, GLfloat ref);
+ /** Set the blend color */
+ void (*BlendColor)(GLcontext *ctx, const GLfloat color[4]);
+ /** Set the blend equation */
+ void (*BlendEquationSeparate)(GLcontext *ctx, GLenum modeRGB, GLenum modeA);
+ /** Specify pixel arithmetic */
+ void (*BlendFuncSeparate)(GLcontext *ctx,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA);
+ /** Specify clear values for the color buffers */
+ void (*ClearColor)(GLcontext *ctx, const GLfloat color[4]);
+ /** Specify the clear value for the depth buffer */
+ void (*ClearDepth)(GLcontext *ctx, GLclampd d);
+ /** Specify the clear value for the color index buffers */
+ void (*ClearIndex)(GLcontext *ctx, GLuint index);
+ /** Specify the clear value for the stencil buffer */
+ void (*ClearStencil)(GLcontext *ctx, GLint s);
+ /** Specify a plane against which all geometry is clipped */
+ void (*ClipPlane)(GLcontext *ctx, GLenum plane, const GLfloat *equation );
+ /** Enable and disable writing of frame buffer color components */
+ void (*ColorMask)(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask );
+ /** Cause a material color to track the current color */
+ void (*ColorMaterial)(GLcontext *ctx, GLenum face, GLenum mode);
+ /** Specify whether front- or back-facing facets can be culled */
+ void (*CullFace)(GLcontext *ctx, GLenum mode);
+ /** Define front- and back-facing polygons */
+ void (*FrontFace)(GLcontext *ctx, GLenum mode);
+ /** Specify the value used for depth buffer comparisons */
+ void (*DepthFunc)(GLcontext *ctx, GLenum func);
+ /** Enable or disable writing into the depth buffer */
+ void (*DepthMask)(GLcontext *ctx, GLboolean flag);
+ /** Specify mapping of depth values from NDC to window coordinates */
+ void (*DepthRange)(GLcontext *ctx, GLclampd nearval, GLclampd farval);
+ /** Specify the current buffer for writing */
+ void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
+ /** Specify the buffers for writing for fragment programs*/
+ void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
+ /** Enable or disable server-side gl capabilities */
+ void (*Enable)(GLcontext *ctx, GLenum cap, GLboolean state);
+ /** Specify fog parameters */
+ void (*Fogfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+ /** Specify implementation-specific hints */
+ void (*Hint)(GLcontext *ctx, GLenum target, GLenum mode);
+ /** Control the writing of individual bits in the color index buffers */
+ void (*IndexMask)(GLcontext *ctx, GLuint mask);
+ /** Set light source parameters.
+ * Note: for GL_POSITION and GL_SPOT_DIRECTION, params will have already
+ * been transformed to eye-space.
+ */
+ void (*Lightfv)(GLcontext *ctx, GLenum light,
+ GLenum pname, const GLfloat *params );
+ /** Set the lighting model parameters */
+ void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+ /** Specify the line stipple pattern */
+ void (*LineStipple)(GLcontext *ctx, GLint factor, GLushort pattern );
+ /** Specify the width of rasterized lines */
+ void (*LineWidth)(GLcontext *ctx, GLfloat width);
+ /** Specify a logical pixel operation for color index rendering */
+ void (*LogicOpcode)(GLcontext *ctx, GLenum opcode);
+ void (*PointParameterfv)(GLcontext *ctx, GLenum pname,
+ const GLfloat *params);
+ /** Specify the diameter of rasterized points */
+ void (*PointSize)(GLcontext *ctx, GLfloat size);
+ /** Select a polygon rasterization mode */
+ void (*PolygonMode)(GLcontext *ctx, GLenum face, GLenum mode);
+ /** Set the scale and units used to calculate depth values */
+ void (*PolygonOffset)(GLcontext *ctx, GLfloat factor, GLfloat units);
+ /** Set the polygon stippling pattern */
+ void (*PolygonStipple)(GLcontext *ctx, const GLubyte *mask );
+ /* Specifies the current buffer for reading */
+ void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
+ /** Set rasterization mode */
+ void (*RenderMode)(GLcontext *ctx, GLenum mode );
+ /** Define the scissor box */
+ void (*Scissor)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h);
+ /** Select flat or smooth shading */
+ void (*ShadeModel)(GLcontext *ctx, GLenum mode);
+ /** OpenGL 2.0 two-sided StencilFunc */
+ void (*StencilFuncSeparate)(GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask);
+ /** OpenGL 2.0 two-sided StencilMask */
+ void (*StencilMaskSeparate)(GLcontext *ctx, GLenum face, GLuint mask);
+ /** OpenGL 2.0 two-sided StencilOp */
+ void (*StencilOpSeparate)(GLcontext *ctx, GLenum face, GLenum fail,
+ GLenum zfail, GLenum zpass);
+ /** Control the generation of texture coordinates */
+ void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
+ const GLfloat *params);
+ /** Set texture environment parameters */
+ void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *param);
+ /** Set texture parameters */
+ void (*TexParameter)(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params);
+ void (*TextureMatrix)(GLcontext *ctx, GLuint unit, const GLmatrix *mat);
+ /** Set the viewport */
+ void (*Viewport)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h);
+ /*@}*/
+
+
+ /**
+ * \name Vertex array functions
+ *
+ * Called by the corresponding OpenGL functions.
+ */
+ /*@{*/
+ void (*VertexPointer)(GLcontext *ctx, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*NormalPointer)(GLcontext *ctx, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*ColorPointer)(GLcontext *ctx, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*FogCoordPointer)(GLcontext *ctx, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*IndexPointer)(GLcontext *ctx, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*SecondaryColorPointer)(GLcontext *ctx, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*TexCoordPointer)(GLcontext *ctx, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+ void (*EdgeFlagPointer)(GLcontext *ctx, GLsizei stride, const GLvoid *ptr);
+ void (*VertexAttribPointer)(GLcontext *ctx, GLuint index, GLint size,
+ GLenum type, GLsizei stride, const GLvoid *ptr);
+ void (*LockArraysEXT)( GLcontext *ctx, GLint first, GLsizei count );
+ void (*UnlockArraysEXT)( GLcontext *ctx );
+ /*@}*/
+
+
+ /**
+ * \name State-query functions
+ *
+ * Return GL_TRUE if query was completed, GL_FALSE otherwise.
+ */
+ /*@{*/
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetBooleanv)(GLcontext *ctx, GLenum pname, GLboolean *result);
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetDoublev)(GLcontext *ctx, GLenum pname, GLdouble *result);
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetFloatv)(GLcontext *ctx, GLenum pname, GLfloat *result);
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetIntegerv)(GLcontext *ctx, GLenum pname, GLint *result);
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetInteger64v)(GLcontext *ctx, GLenum pname, GLint64 *result);
+ /** Return the value or values of a selected parameter */
+ GLboolean (*GetPointerv)(GLcontext *ctx, GLenum pname, GLvoid **result);
+ /*@}*/
+
+
+ /**
+ * \name Vertex/pixel buffer object functions
+ */
+#if FEATURE_ARB_vertex_buffer_object
+ /*@{*/
+ void (*BindBuffer)( GLcontext *ctx, GLenum target,
+ struct gl_buffer_object *obj );
+
+ struct gl_buffer_object * (*NewBufferObject)( GLcontext *ctx, GLuint buffer,
+ GLenum target );
+
+ void (*DeleteBuffer)( GLcontext *ctx, struct gl_buffer_object *obj );
+
+ GLboolean (*BufferData)( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+ const GLvoid *data, GLenum usage,
+ struct gl_buffer_object *obj );
+
+ void (*BufferSubData)( GLcontext *ctx, GLenum target, GLintptrARB offset,
+ GLsizeiptrARB size, const GLvoid *data,
+ struct gl_buffer_object *obj );
+
+ void (*GetBufferSubData)( GLcontext *ctx, GLenum target,
+ GLintptrARB offset, GLsizeiptrARB size,
+ GLvoid *data, struct gl_buffer_object *obj );
+
+ void * (*MapBuffer)( GLcontext *ctx, GLenum target, GLenum access,
+ struct gl_buffer_object *obj );
+
+ void (*CopyBufferSubData)( GLcontext *ctx,
+ struct gl_buffer_object *src,
+ struct gl_buffer_object *dst,
+ GLintptr readOffset, GLintptr writeOffset,
+ GLsizeiptr size );
+
+ /* May return NULL if MESA_MAP_NOWAIT_BIT is set in access:
+ */
+ void * (*MapBufferRange)( GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length, GLbitfield access,
+ struct gl_buffer_object *obj);
+
+ void (*FlushMappedBufferRange) (GLcontext *ctx, GLenum target,
+ GLintptr offset, GLsizeiptr length,
+ struct gl_buffer_object *obj);
+
+ GLboolean (*UnmapBuffer)( GLcontext *ctx, GLenum target,
+ struct gl_buffer_object *obj );
+ /*@}*/
+#endif
+
+ /**
+ * \name Functions for GL_EXT_framebuffer_object
+ */
+#if FEATURE_EXT_framebuffer_object
+ /*@{*/
+ struct gl_framebuffer * (*NewFramebuffer)(GLcontext *ctx, GLuint name);
+ struct gl_renderbuffer * (*NewRenderbuffer)(GLcontext *ctx, GLuint name);
+ void (*BindFramebuffer)(GLcontext *ctx, GLenum target,
+ struct gl_framebuffer *fb, struct gl_framebuffer *fbread);
+ void (*FramebufferRenderbuffer)(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLenum attachment,
+ struct gl_renderbuffer *rb);
+ void (*RenderTexture)(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att);
+ void (*FinishRenderTexture)(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att);
+ void (*ValidateFramebuffer)(GLcontext *ctx,
+ struct gl_framebuffer *fb);
+ /*@}*/
+#endif
+#if FEATURE_EXT_framebuffer_blit
+ void (*BlitFramebuffer)(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+#endif
+
+ /**
+ * \name Query objects
+ */
+ /*@{*/
+ struct gl_query_object * (*NewQueryObject)(GLcontext *ctx, GLuint id);
+ void (*DeleteQuery)(GLcontext *ctx, struct gl_query_object *q);
+ void (*BeginQuery)(GLcontext *ctx, struct gl_query_object *q);
+ void (*EndQuery)(GLcontext *ctx, struct gl_query_object *q);
+ void (*CheckQuery)(GLcontext *ctx, struct gl_query_object *q);
+ void (*WaitQuery)(GLcontext *ctx, struct gl_query_object *q);
+ /*@}*/
+
+
+ /**
+ * \name Vertex Array objects
+ */
+ /*@{*/
+ struct gl_array_object * (*NewArrayObject)(GLcontext *ctx, GLuint id);
+ void (*DeleteArrayObject)(GLcontext *ctx, struct gl_array_object *obj);
+ void (*BindArrayObject)(GLcontext *ctx, struct gl_array_object *obj);
+ /*@}*/
+
+ /**
+ * \name GLSL-related functions (ARB extensions and OpenGL 2.x)
+ */
+ /*@{*/
+ void (*AttachShader)(GLcontext *ctx, GLuint program, GLuint shader);
+ void (*BindAttribLocation)(GLcontext *ctx, GLuint program, GLuint index,
+ const GLcharARB *name);
+ void (*CompileShader)(GLcontext *ctx, GLuint shader);
+ GLuint (*CreateShader)(GLcontext *ctx, GLenum type);
+ GLuint (*CreateProgram)(GLcontext *ctx);
+ void (*DeleteProgram2)(GLcontext *ctx, GLuint program);
+ void (*DeleteShader)(GLcontext *ctx, GLuint shader);
+ void (*DetachShader)(GLcontext *ctx, GLuint program, GLuint shader);
+ void (*GetActiveAttrib)(GLcontext *ctx, GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei * length, GLint * size,
+ GLenum * type, GLcharARB * name);
+ void (*GetActiveUniform)(GLcontext *ctx, GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei *length, GLint *size,
+ GLenum *type, GLcharARB *name);
+ void (*GetAttachedShaders)(GLcontext *ctx, GLuint program, GLsizei maxCount,
+ GLsizei *count, GLuint *obj);
+ GLint (*GetAttribLocation)(GLcontext *ctx, GLuint program,
+ const GLcharARB *name);
+ GLuint (*GetHandle)(GLcontext *ctx, GLenum pname);
+ void (*GetProgramiv)(GLcontext *ctx, GLuint program,
+ GLenum pname, GLint *params);
+ void (*GetProgramInfoLog)(GLcontext *ctx, GLuint program, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog);
+ void (*GetShaderiv)(GLcontext *ctx, GLuint shader,
+ GLenum pname, GLint *params);
+ void (*GetShaderInfoLog)(GLcontext *ctx, GLuint shader, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog);
+ void (*GetShaderSource)(GLcontext *ctx, GLuint shader, GLsizei maxLength,
+ GLsizei *length, GLcharARB *sourceOut);
+ void (*GetUniformfv)(GLcontext *ctx, GLuint program, GLint location,
+ GLfloat *params);
+ void (*GetUniformiv)(GLcontext *ctx, GLuint program, GLint location,
+ GLint *params);
+ GLint (*GetUniformLocation)(GLcontext *ctx, GLuint program,
+ const GLcharARB *name);
+ GLboolean (*IsProgram)(GLcontext *ctx, GLuint name);
+ GLboolean (*IsShader)(GLcontext *ctx, GLuint name);
+ void (*LinkProgram)(GLcontext *ctx, GLuint program);
+ void (*ShaderSource)(GLcontext *ctx, GLuint shader, const GLchar *source);
+ void (*Uniform)(GLcontext *ctx, GLint location, GLsizei count,
+ const GLvoid *values, GLenum type);
+ void (*UniformMatrix)(GLcontext *ctx, GLint cols, GLint rows,
+ GLint location, GLsizei count,
+ GLboolean transpose, const GLfloat *values);
+ void (*UseProgram)(GLcontext *ctx, GLuint program);
+ void (*ValidateProgram)(GLcontext *ctx, GLuint program);
+ /* XXX many more to come */
+ /*@}*/
+
+
+ /**
+ * \name Support for multiple T&L engines
+ */
+ /*@{*/
+
+ /**
+ * Bitmask of state changes that require the current T&L module to be
+ * validated, using ValidateTnlModule() below.
+ */
+ GLuint NeedValidate;
+
+ /**
+ * Validate the current T&L module.
+ *
+ * This is called directly after UpdateState() when a state change that has
+ * occurred matches the dd_function_table::NeedValidate bitmask above. This
+ * ensures all computed values are up to date, thus allowing the driver to
+ * decide if the current T&L module needs to be swapped out.
+ *
+ * This must be non-NULL if a driver installs a custom T&L module and sets
+ * the dd_function_table::NeedValidate bitmask, but may be NULL otherwise.
+ */
+ void (*ValidateTnlModule)( GLcontext *ctx, GLuint new_state );
+
+
+#define PRIM_OUTSIDE_BEGIN_END (GL_POLYGON+1)
+#define PRIM_INSIDE_UNKNOWN_PRIM (GL_POLYGON+2)
+#define PRIM_UNKNOWN (GL_POLYGON+3)
+
+ /**
+ * Set by the driver-supplied T&L engine.
+ *
+ * Set to PRIM_OUTSIDE_BEGIN_END when outside glBegin()/glEnd().
+ */
+ GLuint CurrentExecPrimitive;
+
+ /**
+ * Current state of an in-progress compilation.
+ *
+ * May take on any of the additional values PRIM_OUTSIDE_BEGIN_END,
+ * PRIM_INSIDE_UNKNOWN_PRIM or PRIM_UNKNOWN defined above.
+ */
+ GLuint CurrentSavePrimitive;
+
+
+#define FLUSH_STORED_VERTICES 0x1
+#define FLUSH_UPDATE_CURRENT 0x2
+ /**
+ * Set by the driver-supplied T&L engine whenever vertices are buffered
+ * between glBegin()/glEnd() objects or __GLcontextRec::Current is not
+ * updated.
+ *
+ * The dd_function_table::FlushVertices call below may be used to resolve
+ * these conditions.
+ */
+ GLuint NeedFlush;
+ GLuint SaveNeedFlush;
+
+
+ /* Called prior to any of the GLvertexformat functions being
+ * called. Paired with Driver.FlushVertices().
+ */
+ void (*BeginVertices)( GLcontext *ctx );
+
+ /**
+ * If inside glBegin()/glEnd(), it should ASSERT(0). Otherwise, if
+ * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered
+ * vertices, if FLUSH_UPDATE_CURRENT bit is set updates
+ * __GLcontextRec::Current and gl_light_attrib::Material
+ *
+ * Note that the default T&L engine never clears the
+ * FLUSH_UPDATE_CURRENT bit, even after performing the update.
+ */
+ void (*FlushVertices)( GLcontext *ctx, GLuint flags );
+ void (*SaveFlushVertices)( GLcontext *ctx );
+
+ /**
+ * Give the driver the opportunity to hook in its own vtxfmt for
+ * compiling optimized display lists. This is called on each valid
+ * glBegin() during list compilation.
+ */
+ GLboolean (*NotifySaveBegin)( GLcontext *ctx, GLenum mode );
+
+ /**
+ * Notify driver that the special derived value _NeedEyeCoords has
+ * changed.
+ */
+ void (*LightingSpaceChange)( GLcontext *ctx );
+
+ /**
+ * Called by glNewList().
+ *
+ * Let the T&L component know what is going on with display lists
+ * in time to make changes to dispatch tables, etc.
+ */
+ void (*NewList)( GLcontext *ctx, GLuint list, GLenum mode );
+ /**
+ * Called by glEndList().
+ *
+ * \sa dd_function_table::NewList.
+ */
+ void (*EndList)( GLcontext *ctx );
+
+ /**
+ * Called by glCallList(s).
+ *
+ * Notify the T&L component before and after calling a display list.
+ */
+ void (*BeginCallList)( GLcontext *ctx,
+ struct gl_display_list *dlist );
+ /**
+ * Called by glEndCallList().
+ *
+ * \sa dd_function_table::BeginCallList.
+ */
+ void (*EndCallList)( GLcontext *ctx );
+
+
+#if FEATURE_ARB_sync
+ /**
+ * \name GL_ARB_sync interfaces
+ */
+ /*@{*/
+ struct gl_sync_object * (*NewSyncObject)(GLcontext *, GLenum);
+ void (*FenceSync)(GLcontext *, struct gl_sync_object *, GLenum, GLbitfield);
+ void (*DeleteSyncObject)(GLcontext *, struct gl_sync_object *);
+ void (*CheckSync)(GLcontext *, struct gl_sync_object *);
+ void (*ClientWaitSync)(GLcontext *, struct gl_sync_object *,
+ GLbitfield, GLuint64);
+ void (*ServerWaitSync)(GLcontext *, struct gl_sync_object *,
+ GLbitfield, GLuint64);
+ /*@}*/
+#endif
+};
+
+
+/**
+ * Transform/Clip/Lighting interface
+ *
+ * Drivers present a reduced set of the functions possible in
+ * glBegin()/glEnd() objects. Core mesa provides translation stubs for the
+ * remaining functions to map down to these entry points.
+ *
+ * These are the initial values to be installed into dispatch by
+ * mesa. If the T&L driver wants to modify the dispatch table
+ * while installed, it must do so itself. It would be possible for
+ * the vertexformat to install it's own initial values for these
+ * functions, but this way there is an obvious list of what is
+ * expected of the driver.
+ *
+ * If the driver wants to hook in entry points other than those
+ * listed, it must restore them to their original values in
+ * the disable() callback, below.
+ */
+typedef struct {
+ /**
+ * \name Vertex
+ */
+ /*@{*/
+ void (GLAPIENTRYP ArrayElement)( GLint ); /* NOTE */
+ void (GLAPIENTRYP Color3f)( GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP Color3fv)( const GLfloat * );
+ void (GLAPIENTRYP Color4f)( GLfloat, GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP Color4fv)( const GLfloat * );
+ void (GLAPIENTRYP EdgeFlag)( GLboolean );
+ void (GLAPIENTRYP EvalCoord1f)( GLfloat ); /* NOTE */
+ void (GLAPIENTRYP EvalCoord1fv)( const GLfloat * ); /* NOTE */
+ void (GLAPIENTRYP EvalCoord2f)( GLfloat, GLfloat ); /* NOTE */
+ void (GLAPIENTRYP EvalCoord2fv)( const GLfloat * ); /* NOTE */
+ void (GLAPIENTRYP EvalPoint1)( GLint ); /* NOTE */
+ void (GLAPIENTRYP EvalPoint2)( GLint, GLint ); /* NOTE */
+ void (GLAPIENTRYP FogCoordfEXT)( GLfloat );
+ void (GLAPIENTRYP FogCoordfvEXT)( const GLfloat * );
+ void (GLAPIENTRYP Indexf)( GLfloat );
+ void (GLAPIENTRYP Indexfv)( const GLfloat * );
+ void (GLAPIENTRYP Materialfv)( GLenum face, GLenum pname, const GLfloat * ); /* NOTE */
+ void (GLAPIENTRYP MultiTexCoord1fARB)( GLenum, GLfloat );
+ void (GLAPIENTRYP MultiTexCoord1fvARB)( GLenum, const GLfloat * );
+ void (GLAPIENTRYP MultiTexCoord2fARB)( GLenum, GLfloat, GLfloat );
+ void (GLAPIENTRYP MultiTexCoord2fvARB)( GLenum, const GLfloat * );
+ void (GLAPIENTRYP MultiTexCoord3fARB)( GLenum, GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP MultiTexCoord3fvARB)( GLenum, const GLfloat * );
+ void (GLAPIENTRYP MultiTexCoord4fARB)( GLenum, GLfloat, GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP MultiTexCoord4fvARB)( GLenum, const GLfloat * );
+ void (GLAPIENTRYP Normal3f)( GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP Normal3fv)( const GLfloat * );
+ void (GLAPIENTRYP SecondaryColor3fEXT)( GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP SecondaryColor3fvEXT)( const GLfloat * );
+ void (GLAPIENTRYP TexCoord1f)( GLfloat );
+ void (GLAPIENTRYP TexCoord1fv)( const GLfloat * );
+ void (GLAPIENTRYP TexCoord2f)( GLfloat, GLfloat );
+ void (GLAPIENTRYP TexCoord2fv)( const GLfloat * );
+ void (GLAPIENTRYP TexCoord3f)( GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP TexCoord3fv)( const GLfloat * );
+ void (GLAPIENTRYP TexCoord4f)( GLfloat, GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP TexCoord4fv)( const GLfloat * );
+ void (GLAPIENTRYP Vertex2f)( GLfloat, GLfloat );
+ void (GLAPIENTRYP Vertex2fv)( const GLfloat * );
+ void (GLAPIENTRYP Vertex3f)( GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP Vertex3fv)( const GLfloat * );
+ void (GLAPIENTRYP Vertex4f)( GLfloat, GLfloat, GLfloat, GLfloat );
+ void (GLAPIENTRYP Vertex4fv)( const GLfloat * );
+ void (GLAPIENTRYP CallList)( GLuint ); /* NOTE */
+ void (GLAPIENTRYP CallLists)( GLsizei, GLenum, const GLvoid * ); /* NOTE */
+ void (GLAPIENTRYP Begin)( GLenum );
+ void (GLAPIENTRYP End)( void );
+ /* GL_NV_vertex_program */
+ void (GLAPIENTRYP VertexAttrib1fNV)( GLuint index, GLfloat x );
+ void (GLAPIENTRYP VertexAttrib1fvNV)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y );
+ void (GLAPIENTRYP VertexAttrib2fvNV)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z );
+ void (GLAPIENTRYP VertexAttrib3fvNV)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+ void (GLAPIENTRYP VertexAttrib4fvNV)( GLuint index, const GLfloat *v );
+#if FEATURE_ARB_vertex_program
+ void (GLAPIENTRYP VertexAttrib1fARB)( GLuint index, GLfloat x );
+ void (GLAPIENTRYP VertexAttrib1fvARB)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib2fARB)( GLuint index, GLfloat x, GLfloat y );
+ void (GLAPIENTRYP VertexAttrib2fvARB)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib3fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z );
+ void (GLAPIENTRYP VertexAttrib3fvARB)( GLuint index, const GLfloat *v );
+ void (GLAPIENTRYP VertexAttrib4fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+ void (GLAPIENTRYP VertexAttrib4fvARB)( GLuint index, const GLfloat *v );
+#endif
+ /*@}*/
+
+ /*
+ */
+ void (GLAPIENTRYP Rectf)( GLfloat, GLfloat, GLfloat, GLfloat );
+
+ /**
+ * \name Array
+ */
+ /*@{*/
+ void (GLAPIENTRYP DrawArrays)( GLenum mode, GLint start, GLsizei count );
+ void (GLAPIENTRYP DrawElements)( GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices );
+ void (GLAPIENTRYP DrawRangeElements)( GLenum mode, GLuint start,
+ GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices );
+ void (GLAPIENTRYP MultiDrawElementsEXT)( GLenum mode, const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount);
+ /*@}*/
+
+ /**
+ * \name Eval
+ *
+ * If you don't support eval, fallback to the default vertex format
+ * on receiving an eval call and use the pipeline mechanism to
+ * provide partial T&L acceleration.
+ *
+ * Mesa will provide a set of helper functions to do eval within
+ * accelerated vertex formats, eventually...
+ */
+ /*@{*/
+ void (GLAPIENTRYP EvalMesh1)( GLenum mode, GLint i1, GLint i2 );
+ void (GLAPIENTRYP EvalMesh2)( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 );
+ /*@}*/
+
+} GLvertexformat;
+
+
+#endif /* DD_INCLUDED */
diff --git a/mesalib/src/mesa/main/debug.c b/mesalib/src/mesa/main/debug.c
new file mode 100644
index 000000000..8492c8561
--- /dev/null
+++ b/mesalib/src/mesa/main/debug.c
@@ -0,0 +1,440 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "mtypes.h"
+#include "attrib.h"
+#include "colormac.h"
+#include "context.h"
+#include "hash.h"
+#include "imports.h"
+#include "debug.h"
+#include "get.h"
+#include "pixelstore.h"
+#include "readpix.h"
+#include "texgetimage.h"
+#include "texobj.h"
+#include "texformat.h"
+
+
+/**
+ * Primitive names
+ */
+const char *_mesa_prim_name[GL_POLYGON+4] = {
+ "GL_POINTS",
+ "GL_LINES",
+ "GL_LINE_LOOP",
+ "GL_LINE_STRIP",
+ "GL_TRIANGLES",
+ "GL_TRIANGLE_STRIP",
+ "GL_TRIANGLE_FAN",
+ "GL_QUADS",
+ "GL_QUAD_STRIP",
+ "GL_POLYGON",
+ "outside begin/end",
+ "inside unkown primitive",
+ "unknown state"
+};
+
+void
+_mesa_print_state( const char *msg, GLuint state )
+{
+ _mesa_debug(NULL,
+ "%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,
+ state,
+ (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "",
+ (state & _NEW_PROJECTION) ? "ctx->Projection, " : "",
+ (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "",
+ (state & _NEW_COLOR_MATRIX) ? "ctx->ColorMatrix, " : "",
+ (state & _NEW_ACCUM) ? "ctx->Accum, " : "",
+ (state & _NEW_COLOR) ? "ctx->Color, " : "",
+ (state & _NEW_DEPTH) ? "ctx->Depth, " : "",
+ (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "",
+ (state & _NEW_FOG) ? "ctx->Fog, " : "",
+ (state & _NEW_HINT) ? "ctx->Hint, " : "",
+ (state & _NEW_LIGHT) ? "ctx->Light, " : "",
+ (state & _NEW_LINE) ? "ctx->Line, " : "",
+ (state & _NEW_PIXEL) ? "ctx->Pixel, " : "",
+ (state & _NEW_POINT) ? "ctx->Point, " : "",
+ (state & _NEW_POLYGON) ? "ctx->Polygon, " : "",
+ (state & _NEW_POLYGONSTIPPLE) ? "ctx->PolygonStipple, " : "",
+ (state & _NEW_SCISSOR) ? "ctx->Scissor, " : "",
+ (state & _NEW_TEXTURE) ? "ctx->Texture, " : "",
+ (state & _NEW_TRANSFORM) ? "ctx->Transform, " : "",
+ (state & _NEW_VIEWPORT) ? "ctx->Viewport, " : "",
+ (state & _NEW_PACKUNPACK) ? "ctx->Pack/Unpack, " : "",
+ (state & _NEW_ARRAY) ? "ctx->Array, " : "",
+ (state & _NEW_RENDERMODE) ? "ctx->RenderMode, " : "",
+ (state & _NEW_BUFFERS) ? "ctx->Visual, ctx->DrawBuffer,, " : "");
+}
+
+
+
+void
+_mesa_print_tri_caps( const char *name, GLuint flags )
+{
+ _mesa_debug(NULL,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ name,
+ flags,
+ (flags & DD_FLATSHADE) ? "flat-shade, " : "",
+ (flags & DD_SEPARATE_SPECULAR) ? "separate-specular, " : "",
+ (flags & DD_TRI_LIGHT_TWOSIDE) ? "tri-light-twoside, " : "",
+ (flags & DD_TRI_TWOSTENCIL) ? "tri-twostencil, " : "",
+ (flags & DD_TRI_UNFILLED) ? "tri-unfilled, " : "",
+ (flags & DD_TRI_STIPPLE) ? "tri-stipple, " : "",
+ (flags & DD_TRI_OFFSET) ? "tri-offset, " : "",
+ (flags & DD_TRI_SMOOTH) ? "tri-smooth, " : "",
+ (flags & DD_LINE_SMOOTH) ? "line-smooth, " : "",
+ (flags & DD_LINE_STIPPLE) ? "line-stipple, " : "",
+ (flags & DD_LINE_WIDTH) ? "line-wide, " : "",
+ (flags & DD_POINT_SMOOTH) ? "point-smooth, " : "",
+ (flags & DD_POINT_SIZE) ? "point-size, " : "",
+ (flags & DD_POINT_ATTEN) ? "point-atten, " : "",
+ (flags & DD_TRI_CULL_FRONT_BACK) ? "cull-all, " : ""
+ );
+}
+
+
+/**
+ * Print information about this Mesa version and build options.
+ */
+void _mesa_print_info( void )
+{
+ _mesa_debug(NULL, "Mesa GL_VERSION = %s\n",
+ (char *) _mesa_GetString(GL_VERSION));
+ _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n",
+ (char *) _mesa_GetString(GL_RENDERER));
+ _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n",
+ (char *) _mesa_GetString(GL_VENDOR));
+ _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n",
+ (char *) _mesa_GetString(GL_EXTENSIONS));
+#if defined(THREADS)
+ _mesa_debug(NULL, "Mesa thread-safe: YES\n");
+#else
+ _mesa_debug(NULL, "Mesa thread-safe: NO\n");
+#endif
+#if defined(USE_X86_ASM)
+ _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
+#else
+ _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
+#endif
+#if defined(USE_SPARC_ASM)
+ _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
+#else
+ _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
+#endif
+}
+
+
+/**
+ * Set the debugging flags.
+ *
+ * \param debug debug string
+ *
+ * If compiled with debugging support then search for keywords in \p debug and
+ * enables the verbose debug output of the respective feature.
+ */
+static void add_debug_flags( const char *debug )
+{
+#ifdef DEBUG
+ struct debug_option {
+ const char *name;
+ GLbitfield flag;
+ };
+ static const struct debug_option debug_opt[] = {
+ { "varray", VERBOSE_VARRAY },
+ { "tex", VERBOSE_TEXTURE },
+ { "imm", VERBOSE_IMMEDIATE },
+ { "pipe", VERBOSE_PIPELINE },
+ { "driver", VERBOSE_DRIVER },
+ { "state", VERBOSE_STATE },
+ { "api", VERBOSE_API },
+ { "list", VERBOSE_DISPLAY_LIST },
+ { "lighting", VERBOSE_LIGHTING },
+ { "disassem", VERBOSE_DISASSEM }
+ };
+ GLuint i;
+
+ MESA_VERBOSE = 0x0;
+ for (i = 0; i < Elements(debug_opt); i++) {
+ if (_mesa_strstr(debug, debug_opt[i].name))
+ MESA_VERBOSE |= debug_opt[i].flag;
+ }
+
+ /* Debug flag:
+ */
+ if (_mesa_strstr(debug, "flush"))
+ MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH;
+
+#if defined(_FPU_GETCW) && defined(_FPU_SETCW)
+ if (_mesa_strstr(debug, "fpexceptions")) {
+ /* raise FP exceptions */
+ fpu_control_t mask;
+ _FPU_GETCW(mask);
+ mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
+ | _FPU_MASK_OM | _FPU_MASK_UM);
+ _FPU_SETCW(mask);
+ }
+#endif
+
+#else
+ (void) debug;
+#endif
+}
+
+
+void
+_mesa_init_debug( GLcontext *ctx )
+{
+ char *c;
+
+ /* Dither disable */
+ ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
+ if (ctx->NoDither) {
+ if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n");
+ }
+ ctx->Color.DitherFlag = GL_FALSE;
+ }
+
+ c = _mesa_getenv("MESA_DEBUG");
+ if (c)
+ add_debug_flags(c);
+
+ c = _mesa_getenv("MESA_VERBOSE");
+ if (c)
+ add_debug_flags(c);
+}
+
+
+/*
+ * Write ppm file
+ */
+static void
+write_ppm(const char *filename, const GLubyte *buffer, int width, int height,
+ int comps, int rcomp, int gcomp, int bcomp, GLboolean invert)
+{
+ FILE *f = fopen( filename, "w" );
+ if (f) {
+ int x, y;
+ const GLubyte *ptr = buffer;
+ fprintf(f,"P6\n");
+ fprintf(f,"# ppm-file created by osdemo.c\n");
+ fprintf(f,"%i %i\n", width,height);
+ fprintf(f,"255\n");
+ fclose(f);
+ f = fopen( filename, "ab" ); /* reopen in binary append mode */
+ for (y=0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ int yy = invert ? (height - 1 - y) : y;
+ int i = (yy * width + x) * comps;
+ fputc(ptr[i+rcomp], f); /* write red */
+ fputc(ptr[i+gcomp], f); /* write green */
+ fputc(ptr[i+bcomp], f); /* write blue */
+ }
+ }
+ fclose(f);
+ }
+}
+
+
+/**
+ * Write level[0] image to a ppm file.
+ */
+static void
+write_texture_image(struct gl_texture_object *texObj, GLuint face, GLuint level)
+{
+ struct gl_texture_image *img = texObj->Image[face][level];
+ if (img) {
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_pixelstore_attrib store;
+ GLubyte *buffer;
+ char s[100];
+
+ buffer = (GLubyte *) _mesa_malloc(img->Width * img->Height
+ * img->Depth * 4);
+
+ store = ctx->Pack; /* save */
+ ctx->Pack = ctx->DefaultPacking;
+
+ ctx->Driver.GetTexImage(ctx, texObj->Target, level,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer, texObj, img);
+
+ /* make filename */
+ _mesa_sprintf(s, "/tmp/teximage%u.ppm", texObj->Name);
+
+ _mesa_printf(" Writing image level %u to %s\n", level, s);
+ write_ppm(s, buffer, img->Width, img->Height, 4, 0, 1, 2, GL_FALSE);
+
+ ctx->Pack = store; /* restore */
+
+ _mesa_free(buffer);
+ }
+}
+
+
+static GLboolean DumpImages;
+
+
+static void
+dump_texture_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_texture_object *texObj = (struct gl_texture_object *) data;
+ int i;
+ GLboolean written = GL_FALSE;
+ (void) userData;
+
+ _mesa_printf("Texture %u\n", texObj->Name);
+ _mesa_printf(" Target 0x%x\n", texObj->Target);
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ struct gl_texture_image *texImg = texObj->Image[0][i];
+ if (texImg) {
+ _mesa_printf(" Image %u: %d x %d x %d, format %u at %p\n", i,
+ texImg->Width, texImg->Height, texImg->Depth,
+ texImg->TexFormat->MesaFormat, texImg->Data);
+ if (DumpImages && !written) {
+ GLuint face = 0;
+ write_texture_image(texObj, face, i);
+ written = GL_TRUE;
+ }
+ }
+ }
+}
+
+
+/**
+ * Print basic info about all texture objext to stdout.
+ * If dumpImages is true, write PPM of level[0] image to a file.
+ */
+void
+_mesa_dump_textures(GLboolean dumpImages)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DumpImages = dumpImages;
+ _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
+}
+
+
+void
+_mesa_dump_color_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLubyte *buf;
+
+ buf = (GLubyte *) _mesa_malloc(w * h * 4);
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+ _mesa_printf("ReadBuffer %p 0x%x DrawBuffer %p 0x%x\n",
+ ctx->ReadBuffer->_ColorReadBuffer,
+ ctx->ReadBuffer->ColorReadBuffer,
+ ctx->DrawBuffer->_ColorDrawBuffers[0],
+ ctx->DrawBuffer->ColorDrawBuffer[0]);
+ _mesa_printf("Writing %d x %d color buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf, w, h, 4, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+}
+
+
+void
+_mesa_dump_depth_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLuint *buf;
+ GLubyte *buf2;
+ GLuint i;
+
+ buf = (GLuint *) _mesa_malloc(w * h * 4); /* 4 bpp */
+ buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buf);
+
+ /* spread 24 bits of Z across R, G, B */
+ for (i = 0; i < w * h; i++) {
+ buf2[i*3+0] = (buf[i] >> 24) & 0xff;
+ buf2[i*3+1] = (buf[i] >> 16) & 0xff;
+ buf2[i*3+2] = (buf[i] >> 8) & 0xff;
+ }
+
+ _mesa_printf("Writing %d x %d depth buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+ _mesa_free(buf2);
+}
+
+
+void
+_mesa_dump_stencil_buffer(const char *filename)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint w = ctx->DrawBuffer->Width;
+ const GLuint h = ctx->DrawBuffer->Height;
+ GLubyte *buf;
+ GLubyte *buf2;
+ GLuint i;
+
+ buf = (GLubyte *) _mesa_malloc(w * h); /* 1 bpp */
+ buf2 = (GLubyte *) _mesa_malloc(w * h * 3); /* 3 bpp */
+
+ _mesa_PushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ _mesa_PixelStorei(GL_PACK_ALIGNMENT, 1);
+ _mesa_PixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
+
+ _mesa_ReadPixels(0, 0, w, h, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
+
+ for (i = 0; i < w * h; i++) {
+ buf2[i*3+0] = buf[i];
+ buf2[i*3+1] = (buf[i] & 127) * 2;
+ buf2[i*3+2] = (buf[i] - 128) * 2;
+ }
+
+ _mesa_printf("Writing %d x %d stencil buffer to %s\n", w, h, filename);
+ write_ppm(filename, buf2, w, h, 3, 0, 1, 2, GL_TRUE);
+
+ _mesa_PopClientAttrib();
+
+ _mesa_free(buf);
+ _mesa_free(buf2);
+}
diff --git a/mesalib/src/mesa/main/debug.h b/mesalib/src/mesa/main/debug.h
new file mode 100644
index 000000000..bb384c432
--- /dev/null
+++ b/mesalib/src/mesa/main/debug.h
@@ -0,0 +1,72 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file debug.h
+ * Debugging functions.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#if _HAVE_FULL_GL
+
+extern void _mesa_print_tri_caps( const char *name, GLuint flags );
+extern void _mesa_print_enable_flags( const char *msg, GLuint flags );
+extern void _mesa_print_state( const char *msg, GLuint state );
+extern void _mesa_print_info( void );
+extern void _mesa_init_debug( GLcontext *ctx );
+
+#else
+
+/** No-op */
+#define _mesa_print_state( m, s ) ((void)0)
+
+/** No-op */
+#define _mesa_print_info() ((void)0)
+
+/** No-op */
+#define _mesa_init_debug( c ) ((void)0)
+
+#endif
+
+extern void
+_mesa_dump_textures(GLboolean dumpImages);
+
+extern void
+_mesa_dump_color_buffer(const char *filename);
+
+extern void
+_mesa_dump_depth_buffer(const char *filename);
+
+extern void
+_mesa_dump_stencil_buffer(const char *filename);
+
+#endif
diff --git a/mesalib/src/mesa/main/depth.c b/mesalib/src/mesa/main/depth.c
new file mode 100644
index 000000000..91c036ef9
--- /dev/null
+++ b/mesalib/src/mesa/main/depth.c
@@ -0,0 +1,162 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "depth.h"
+#include "enums.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+/**********************************************************************/
+/***** API Functions *****/
+/**********************************************************************/
+
+
+
+void GLAPIENTRY
+_mesa_ClearDepth( GLclampd depth )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ depth = CLAMP( depth, 0.0, 1.0 );
+
+ if (ctx->Depth.Clear == depth)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Clear = depth;
+ if (ctx->Driver.ClearDepth)
+ (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear );
+}
+
+
+
+void GLAPIENTRY
+_mesa_DepthFunc( GLenum func )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func));
+
+ switch (func) {
+ 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:
+ case GL_NEVER:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glDepth.Func" );
+ return;
+ }
+
+ if (ctx->Depth.Func == func)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Func = func;
+
+ if (ctx->Driver.DepthFunc)
+ ctx->Driver.DepthFunc( ctx, func );
+}
+
+
+
+void GLAPIENTRY
+_mesa_DepthMask( GLboolean flag )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "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)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Mask = flag;
+
+ if (ctx->Driver.DepthMask)
+ ctx->Driver.DepthMask( ctx, flag );
+}
+
+
+
+/**
+ * Specified by the GL_EXT_depth_bounds_test extension.
+ */
+void GLAPIENTRY
+_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (zmin > zmax) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)");
+ return;
+ }
+
+ zmin = CLAMP(zmin, 0.0, 1.0);
+ zmax = CLAMP(zmax, 0.0, 1.0);
+
+ if (ctx->Depth.BoundsMin == zmin && ctx->Depth.BoundsMax == zmax)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.BoundsMin = (GLfloat) zmin;
+ ctx->Depth.BoundsMax = (GLfloat) zmax;
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+
+/**
+ * Initialize the depth buffer attribute group in the given context.
+ */
+void
+_mesa_init_depth(GLcontext *ctx)
+{
+ ctx->Depth.Test = GL_FALSE;
+ ctx->Depth.Clear = 1.0;
+ ctx->Depth.Func = GL_LESS;
+ ctx->Depth.Mask = GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/depth.h b/mesalib/src/mesa/main/depth.h
new file mode 100644
index 000000000..dcc0b4637
--- /dev/null
+++ b/mesalib/src/mesa/main/depth.h
@@ -0,0 +1,62 @@
+/**
+ * \file depth.h
+ * Depth buffer operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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 "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_ClearDepth( GLclampd depth );
+
+extern void GLAPIENTRY
+_mesa_DepthFunc( GLenum func );
+
+extern void GLAPIENTRY
+_mesa_DepthMask( GLboolean flag );
+
+extern void GLAPIENTRY
+_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax );
+
+extern void
+_mesa_init_depth( GLcontext * ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_depth( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/depthstencil.c b/mesalib/src/mesa/main/depthstencil.c
new file mode 100644
index 000000000..7be2aacaf
--- /dev/null
+++ b/mesalib/src/mesa/main/depthstencil.c
@@ -0,0 +1,655 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "fbobject.h"
+#include "mtypes.h"
+#include "depthstencil.h"
+#include "renderbuffer.h"
+
+
+/**
+ * Adaptor/wrappers for GL_DEPTH_STENCIL renderbuffers.
+ *
+ * The problem with a GL_DEPTH_STENCIL renderbuffer is that sometimes we
+ * want to treat it as a stencil buffer, other times we want to treat it
+ * as a depth/z buffer and still other times when we want to treat it as
+ * a combined Z+stencil buffer! That implies we need three different sets
+ * of Get/Put functions.
+ *
+ * We solve this by wrapping the Z24_S8 renderbuffer with depth and stencil
+ * adaptors, each with the right kind of depth/stencil Get/Put functions.
+ */
+
+
+static void *
+nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
+{
+ (void) ctx;
+ (void) rb;
+ (void) x;
+ (void) y;
+ return NULL;
+}
+
+
+/**
+ * Delete a depth or stencil wrapper renderbuffer.
+ */
+static void
+delete_wrapper(struct gl_renderbuffer *rb)
+{
+ ASSERT(rb->_ActualFormat == GL_DEPTH_COMPONENT24 ||
+ rb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
+ _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
+ _mesa_free(rb);
+}
+
+
+/**
+ * Realloc storage for wrapper.
+ */
+static GLboolean
+alloc_wrapper_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ /* just pass this on to the wrapped renderbuffer */
+ struct gl_renderbuffer *dsrb = rb->Wrapped;
+ GLboolean retVal;
+
+ (void) internalFormat;
+
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+
+ retVal = dsrb->AllocStorage(ctx, dsrb, dsrb->InternalFormat, width, height);
+ if (retVal) {
+ rb->Width = width;
+ rb->Height = height;
+ }
+ return retVal;
+}
+
+
+
+
+/*======================================================================
+ * Depth wrapper around depth/stencil renderbuffer
+ */
+
+static void
+get_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ GLuint *dst = (GLuint *) values;
+ const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (!src) {
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ src = temp;
+ }
+ for (i = 0; i < count; i++) {
+ dst[i] = src[i] >> 8;
+ }
+}
+
+static void
+get_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ GLuint *dst = (GLuint *) values;
+ ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ ASSERT(count <= MAX_WIDTH);
+ /* don't bother trying direct access */
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ dst[i] = temp[i] >> 8;
+ }
+}
+
+static void
+put_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ const GLuint *src = (const GLuint *) values;
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dst) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = (src[i] << 8) | (dst[i] & 0xff);
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (src[i] << 8) | (temp[i] & 0xff);
+ }
+ }
+ dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_mono_row_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ const GLuint shiftedVal = *((GLuint *) value) << 8;
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dst) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = shiftedVal | (dst[i] & 0xff);
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = shiftedVal | (temp[i] & 0xff);
+ }
+ }
+ dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ const GLuint *src = (const GLuint *) values;
+ ASSERT(z24rb->DataType == GL_UNSIGNED_INT);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
+ *dst = (src[i] << 8) | (*dst & 0xff);
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (src[i] << 8) | (temp[i] & 0xff);
+ }
+ }
+ dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_mono_values_z24(GLcontext *ctx, struct gl_renderbuffer *z24rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = z24rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ const GLuint shiftedVal = *((GLuint *) value) << 8;
+ /* get, modify, put */
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = shiftedVal | (temp[i] & 0xff);
+ }
+ }
+ dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
+}
+
+
+/**
+ * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
+ * a depth renderbuffer.
+ * \return new depth renderbuffer
+ */
+struct gl_renderbuffer *
+_mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
+ struct gl_renderbuffer *dsrb)
+{
+ struct gl_renderbuffer *z24rb;
+
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+
+ z24rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!z24rb)
+ return NULL;
+
+ z24rb->Wrapped = dsrb;
+ z24rb->Name = dsrb->Name;
+ z24rb->RefCount = 1;
+ z24rb->Width = dsrb->Width;
+ z24rb->Height = dsrb->Height;
+ z24rb->InternalFormat = GL_DEPTH_COMPONENT24;
+ z24rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+ z24rb->_BaseFormat = GL_DEPTH_COMPONENT;
+ z24rb->DataType = GL_UNSIGNED_INT;
+ z24rb->DepthBits = 24;
+ z24rb->Data = NULL;
+ z24rb->Delete = delete_wrapper;
+ z24rb->AllocStorage = alloc_wrapper_storage;
+ z24rb->GetPointer = nop_get_pointer;
+ z24rb->GetRow = get_row_z24;
+ z24rb->GetValues = get_values_z24;
+ z24rb->PutRow = put_row_z24;
+ z24rb->PutRowRGB = NULL;
+ z24rb->PutMonoRow = put_mono_row_z24;
+ z24rb->PutValues = put_values_z24;
+ z24rb->PutMonoValues = put_mono_values_z24;
+
+ return z24rb;
+}
+
+
+/*======================================================================
+ * Stencil wrapper around depth/stencil renderbuffer
+ */
+
+static void
+get_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ GLubyte *dst = (GLubyte *) values;
+ const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (!src) {
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ src = temp;
+ }
+ for (i = 0; i < count; i++) {
+ dst[i] = src[i] & 0xff;
+ }
+}
+
+static void
+get_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ GLubyte *dst = (GLubyte *) values;
+ ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ ASSERT(count <= MAX_WIDTH);
+ /* don't bother trying direct access */
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ dst[i] = temp[i] & 0xff;
+ }
+}
+
+static void
+put_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ const GLubyte *src = (const GLubyte *) values;
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dst) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = (dst[i] & 0xffffff00) | src[i];
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (temp[i] & 0xffffff00) | src[i];
+ }
+ }
+ dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_mono_row_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ const GLubyte val = *((GLubyte *) value);
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y);
+ ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dst) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = (dst[i] & 0xffffff00) | val;
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetRow(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (temp[i] & 0xffffff00) | val;
+ }
+ }
+ dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ const GLubyte *src = (const GLubyte *) values;
+ ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (dsrb->GetPointer(ctx, dsrb, 0, 0)) {
+ /* direct access */
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]);
+ *dst = (*dst & 0xffffff00) | src[i];
+ }
+ }
+ }
+ else {
+ /* get, modify, put */
+ GLuint temp[MAX_WIDTH], i;
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (temp[i] & 0xffffff00) | src[i];
+ }
+ }
+ dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
+ }
+}
+
+static void
+put_mono_values_s8(GLcontext *ctx, struct gl_renderbuffer *s8rb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ struct gl_renderbuffer *dsrb = s8rb->Wrapped;
+ GLuint temp[MAX_WIDTH], i;
+ const GLubyte val = *((GLubyte *) value);
+ /* get, modify, put */
+ dsrb->GetValues(ctx, dsrb, count, x, y, temp);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ temp[i] = (temp[i] & 0xffffff) | val;
+ }
+ }
+ dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask);
+}
+
+
+/**
+ * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like
+ * a stencil renderbuffer.
+ * \return new stencil renderbuffer
+ */
+struct gl_renderbuffer *
+_mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx, struct gl_renderbuffer *dsrb)
+{
+ struct gl_renderbuffer *s8rb;
+
+ ASSERT(dsrb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+
+ s8rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!s8rb)
+ return NULL;
+
+ s8rb->Wrapped = dsrb;
+ s8rb->Name = dsrb->Name;
+ s8rb->RefCount = 1;
+ s8rb->Width = dsrb->Width;
+ s8rb->Height = dsrb->Height;
+ s8rb->InternalFormat = GL_STENCIL_INDEX8_EXT;
+ s8rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
+ s8rb->_BaseFormat = GL_STENCIL_INDEX;
+ s8rb->DataType = GL_UNSIGNED_BYTE;
+ s8rb->StencilBits = 8;
+ s8rb->Data = NULL;
+ s8rb->Delete = delete_wrapper;
+ s8rb->AllocStorage = alloc_wrapper_storage;
+ s8rb->GetPointer = nop_get_pointer;
+ s8rb->GetRow = get_row_s8;
+ s8rb->GetValues = get_values_s8;
+ s8rb->PutRow = put_row_s8;
+ s8rb->PutRowRGB = NULL;
+ s8rb->PutMonoRow = put_mono_row_s8;
+ s8rb->PutValues = put_values_s8;
+ s8rb->PutMonoValues = put_mono_values_s8;
+
+ return s8rb;
+}
+
+
+
+/**
+ ** The following functions are useful for hardware drivers that only
+ ** implement combined depth/stencil buffers.
+ ** The GL_EXT_framebuffer_object extension allows indepedent depth and
+ ** stencil buffers to be used in any combination.
+ ** Therefore, we sometimes have to merge separate depth and stencil
+ ** renderbuffers into a single depth+stencil renderbuffer. And sometimes
+ ** we have to split combined depth+stencil renderbuffers into separate
+ ** renderbuffers.
+ **/
+
+
+/**
+ * Extract stencil values from the combined depth/stencil renderbuffer, storing
+ * the values into a separate stencil renderbuffer.
+ * \param dsRb the source depth/stencil renderbuffer
+ * \param stencilRb the destination stencil renderbuffer
+ * (either 8-bit or 32-bit)
+ */
+void
+_mesa_extract_stencil(GLcontext *ctx,
+ struct gl_renderbuffer *dsRb,
+ struct gl_renderbuffer *stencilRb)
+{
+ GLuint row, width, height;
+
+ ASSERT(dsRb);
+ ASSERT(stencilRb);
+
+ ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT ||
+ stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
+ ASSERT(dsRb->Width == stencilRb->Width);
+ ASSERT(dsRb->Height == stencilRb->Height);
+
+ width = dsRb->Width;
+ height = dsRb->Height;
+
+ for (row = 0; row < height; row++) {
+ GLuint depthStencil[MAX_WIDTH];
+ dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
+ if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
+ /* 8bpp stencil */
+ GLubyte stencil[MAX_WIDTH];
+ GLuint i;
+ for (i = 0; i < width; i++) {
+ stencil[i] = depthStencil[i] & 0xff;
+ }
+ stencilRb->PutRow(ctx, stencilRb, width, 0, row, stencil, NULL);
+ }
+ else {
+ /* 32bpp stencil */
+ /* the 24 depth bits will be ignored */
+ ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ stencilRb->PutRow(ctx, stencilRb, width, 0, row, depthStencil, NULL);
+ }
+ }
+}
+
+
+/**
+ * Copy stencil values from a stencil renderbuffer into a combined
+ * depth/stencil renderbuffer.
+ * \param dsRb the destination depth/stencil renderbuffer
+ * \param stencilRb the source stencil buffer (either 8-bit or 32-bit)
+ */
+void
+_mesa_insert_stencil(GLcontext *ctx,
+ struct gl_renderbuffer *dsRb,
+ struct gl_renderbuffer *stencilRb)
+{
+ GLuint row, width, height;
+
+ ASSERT(dsRb);
+ ASSERT(stencilRb);
+
+ ASSERT(dsRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(dsRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT ||
+ stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
+
+ ASSERT(dsRb->Width == stencilRb->Width);
+ ASSERT(dsRb->Height == stencilRb->Height);
+
+ width = dsRb->Width;
+ height = dsRb->Height;
+
+ for (row = 0; row < height; row++) {
+ GLuint depthStencil[MAX_WIDTH];
+
+ dsRb->GetRow(ctx, dsRb, width, 0, row, depthStencil);
+
+ if (stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {
+ /* 8bpp stencil */
+ GLubyte stencil[MAX_WIDTH];
+ GLuint i;
+ stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
+ for (i = 0; i < width; i++) {
+ depthStencil[i] = (depthStencil[i] & 0xffffff00) | stencil[i];
+ }
+ }
+ else {
+ /* 32bpp stencil buffer */
+ GLuint stencil[MAX_WIDTH], i;
+ ASSERT(stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+ ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ stencilRb->GetRow(ctx, stencilRb, width, 0, row, stencil);
+ for (i = 0; i < width; i++) {
+ depthStencil[i]
+ = (depthStencil[i] & 0xffffff00) | (stencil[i] & 0xff);
+ }
+ }
+
+ dsRb->PutRow(ctx, dsRb, width, 0, row, depthStencil, NULL);
+ }
+}
+
+
+/**
+ * Convert the stencil buffer from 8bpp to 32bpp depth/stencil.
+ * \param stencilRb the stencil renderbuffer to promote
+ */
+void
+_mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb)
+{
+ const GLsizei width = stencilRb->Width;
+ const GLsizei height = stencilRb->Height;
+ GLubyte *data;
+ GLint i, j, k;
+
+ ASSERT(stencilRb->_ActualFormat == GL_STENCIL_INDEX8_EXT);
+ ASSERT(stencilRb->Data);
+
+ data = (GLubyte *) stencilRb->Data;
+ stencilRb->Data = NULL;
+ stencilRb->AllocStorage(ctx, stencilRb, GL_DEPTH24_STENCIL8_EXT,
+ width, height);
+
+ ASSERT(stencilRb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+
+ k = 0;
+ for (i = 0; i < height; i++) {
+ GLuint depthStencil[MAX_WIDTH];
+ for (j = 0; j < width; j++) {
+ depthStencil[j] = data[k++];
+ }
+ stencilRb->PutRow(ctx, stencilRb, width, 0, i, depthStencil, NULL);
+ }
+ _mesa_free(data);
+
+ stencilRb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
+}
diff --git a/mesalib/src/mesa/main/depthstencil.h b/mesalib/src/mesa/main/depthstencil.h
new file mode 100644
index 000000000..3dde081f5
--- /dev/null
+++ b/mesalib/src/mesa/main/depthstencil.h
@@ -0,0 +1,56 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 DEPTHSTENCIL_H
+#define DEPTHSTENCIL_H
+
+
+extern struct gl_renderbuffer *
+_mesa_new_z24_renderbuffer_wrapper(GLcontext *ctx,
+ struct gl_renderbuffer *dsrb);
+
+
+extern struct gl_renderbuffer *
+_mesa_new_s8_renderbuffer_wrapper(GLcontext *ctx,
+ struct gl_renderbuffer *dsrb);
+
+
+extern void
+_mesa_extract_stencil(GLcontext *ctx,
+ struct gl_renderbuffer *dsRb,
+ struct gl_renderbuffer *stencilRb);
+
+
+extern void
+_mesa_insert_stencil(GLcontext *ctx,
+ struct gl_renderbuffer *dsRb,
+ struct gl_renderbuffer *stencilRb);
+
+
+extern void
+_mesa_promote_stencil(GLcontext *ctx, struct gl_renderbuffer *stencilRb);
+
+
+#endif /* DEPTHSTENCIL_H */
diff --git a/mesalib/src/mesa/main/descrip.mms b/mesalib/src/mesa/main/descrip.mms
new file mode 100644
index 000000000..e49ec65d4
--- /dev/null
+++ b/mesalib/src/mesa/main/descrip.mms
@@ -0,0 +1,258 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 29 September 2008
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define shader [-.shader]
+ define glapi [-.glapi]
+ define main [-.main]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.glapi],[-.shader]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES =accum.c \
+ api_arrayelt.c \
+ api_exec.c \
+ api_loopback.c \
+ api_noop.c \
+ api_validate.c \
+ attrib.c \
+ arrayobj.c \
+ blend.c \
+ bufferobj.c \
+ buffers.c \
+ clear.c \
+ clip.c \
+ colortab.c \
+ context.c \
+ convolve.c \
+ debug.c \
+ depth.c \
+ depthstencil.c \
+ dispatch.c \
+ dlist.c \
+ drawpix.c \
+ enable.c \
+ enums.c \
+ eval.c \
+ execmem.c \
+ extensions.c \
+ fbobject.c \
+ feedback.c \
+ ffvertex_prog.c \
+ fog.c \
+ framebuffer.c \
+ get.c \
+ getstring.c \
+ hash.c \
+ hint.c \
+ histogram.c \
+ image.c \
+ imports.c \
+ light.c \
+ lines.c \
+ matrix.c \
+ mipmap.c \
+ mm.c \
+ multisample.c \
+ pixel.c \
+ pixelstore.c \
+ points.c \
+ polygon.c \
+ rastpos.c \
+ rbadaptors.c \
+ readpix.c \
+ renderbuffer.c \
+ scissor.c \
+ shaders.c \
+ state.c \
+ stencil.c \
+ texcompress.c \
+ texcompress_fxt1.c \
+ texcompress_s3tc.c \
+ texenv.c \
+ texenvprogram.c \
+ texformat.c \
+ texgen.c \
+ teximage.c \
+ texobj.c \
+ texparam.c \
+ texrender.c \
+ texstate.c \
+ texstore.c \
+ varray.c \
+ vtxfmt.c \
+ queryobj.c \
+ rbadaptors.c
+
+OBJECTS=accum.obj,\
+api_arrayelt.obj,\
+api_exec.obj,\
+api_loopback.obj,\
+api_noop.obj,\
+api_validate.obj,\
+arrayobj.obj,\
+attrib.obj,\
+blend.obj,\
+bufferobj.obj,\
+buffers.obj,\
+clear.obj,\
+clip.obj,\
+colortab.obj,\
+context.obj,\
+convolve.obj,\
+debug.obj,\
+depth.obj,\
+depthstencil.obj,\
+dispatch.obj,\
+dlist.obj,\
+drawpix.obj,\
+enable.obj,\
+enums.obj,\
+eval.obj,\
+execmem.obj,\
+extensions.obj,\
+fbobject.obj,\
+feedback.obj,\
+ffvertex_prog.obj,\
+fog.obj,\
+framebuffer.obj,\
+get.obj,\
+getstring.obj,\
+hash.obj,\
+hint.obj,\
+histogram.obj,\
+image.obj,\
+imports.obj,\
+light.obj,\
+lines.obj,\
+matrix.obj,\
+mipmap.obj,\
+mm.obj,\
+multisample.obj,\
+pixel.obj,\
+pixelstore.obj,\
+points.obj,\
+polygon.obj,\
+rastpos.obj,\
+readpix.obj,\
+renderbuffer.obj,\
+scissor.obj,\
+shaders.obj,\
+state.obj,\
+stencil.obj,\
+texcompress.obj,\
+texcompress_fxt1.obj,\
+texcompress_s3tc.obj,\
+texenv.obj,\
+texenvprogram.obj,\
+texformat.obj,\
+texgen.obj,\
+teximage.obj,\
+texobj.obj,\
+texparam.obj,\
+texrender.obj,\
+texstate.obj,\
+texstore.obj,\
+varray.obj,\
+vtxfmt.obj,\
+queryobj.obj,\
+rbadaptors.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ $(MAKELIB) $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+accum.obj : accum.c
+api_arrayelt.obj : api_arrayelt.c
+api_loopback.obj : api_loopback.c
+api_noop.obj : api_noop.c
+api_validate.obj : api_validate.c
+arrayobj.obj : arrayobj.c
+attrib.obj : attrib.c
+blend.obj : blend.c
+bufferobj.obj : bufferobj.c
+buffers.obj : buffers.c
+clip.obj : clip.c
+colortab.obj : colortab.c
+context.obj : context.c
+convolve.obj : convolve.c
+debug.obj : debug.c
+depth.obj : depth.c
+depthstencil.obj : depthstencil.c
+dispatch.obj : dispatch.c
+dlist.obj : dlist.c
+drawpix.obj : drawpix.c
+enable.obj : enable.c
+enums.obj : enums.c
+eval.obj : eval.c
+execmem.obj : execmem.c
+extensions.obj : extensions.c
+fbobject.obj : fbobject.c
+feedback.obj : feedback.c
+fog.obj : fog.c
+framebuffer.obj : framebuffer.c
+get.obj : get.c
+getstring.obj : getstring.c
+hash.obj : hash.c
+hint.obj : hint.c
+histogram.obj : histogram.c
+image.obj : image.c
+imports.obj : imports.c vsnprintf.c
+light.obj : light.c
+lines.obj : lines.c
+matrix.obj : matrix.c
+mipmap.obj : mipmap.c
+mm.obj : mm.c
+pixel.obj : pixel.c
+points.obj : points.c
+polygon.obj : polygon.c
+rastpos.obj : rastpos.c
+rbadaptors.obj : rbadaptors.c
+renderbuffer.obj : renderbuffer.c
+state.obj : state.c
+stencil.obj : stencil.c
+texcompress.obj : texcompress.c
+texcompress_fxt1.obj : texcompress_fxt1.c
+ cc$(CFLAGS)/warn=(disable=SHIFTCOUNT) texcompress_fxt1.c
+texcompress_s3tc.obj : texcompress_s3tc.c
+texenvprogram.obj : texenvprogram.c
+texformat.obj : texformat.c
+teximage.obj : teximage.c
+texobj.obj : texobj.c
+texrender.obj : texrender.c
+texstate.obj : texstate.c
+texstore.obj : texstore.c
+varray.obj : varray.c
+vtxfmt.obj : vtxfmt.c
+shaders.obj : shaders.c
+queryobj.obj : queryobj.c
+rbadaptors.obj : rbadaptors.c
+clear.obj : clear.c
+multisample.obj : multisample.c
+scissor.obj : scissor.c
+texenv.obj : texenv.c
+texgen.obj : texgen.c
+texparam.obj : texparam.c
+readpix.obj : readpix.c
+ffvertex_prog.obj : ffvertex_prog.c
+api_exec.obj : api_exec.c
+pixelstore.obj : pixelstore.c
diff --git a/mesalib/src/mesa/main/dispatch.c b/mesalib/src/mesa/main/dispatch.c
new file mode 100644
index 000000000..bf1a01378
--- /dev/null
+++ b/mesalib/src/mesa/main/dispatch.c
@@ -0,0 +1,96 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+
+/**
+ * \file dispatch.c
+ *
+ * This file generates all the gl* function entrypoints. This code is not
+ * used if optimized assembly stubs are available (e.g., using x86/glapi_x86.S
+ * on IA32 or sparc/glapi_sparc.S on SPARC).
+ *
+ * \note
+ * This file is also used to build the client-side libGL that loads DRI-based
+ * device drivers. At build-time it is symlinked to src/glx/x11.
+ *
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+#ifndef GLX_USE_APPLEGL
+
+#include "main/glheader.h"
+#include "main/compiler.h"
+#include "glapi/glapi.h"
+#include "glapi/glapitable.h"
+#include "glapi/glthread.h"
+
+
+#if !(defined(USE_X86_ASM) || defined(USE_X86_64_ASM) || defined(USE_SPARC_ASM))
+
+#if defined(WIN32)
+#define KEYWORD1 GLAPI
+#else
+#define KEYWORD1 PUBLIC
+#endif
+
+#define KEYWORD2 GLAPIENTRY
+
+#if defined(USE_MGL_NAMESPACE)
+#define NAME(func) mgl##func
+#else
+#define NAME(func) gl##func
+#endif
+
+#if 0 /* Use this to log GL calls to stdout (for DEBUG only!) */
+
+#define F stdout
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ fprintf MESSAGE; \
+ CALL_ ## FUNC(GET_DISPATCH(), ARGS);
+
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ fprintf MESSAGE; \
+ return CALL_ ## FUNC(GET_DISPATCH(), ARGS);
+
+#else
+
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ CALL_ ## FUNC(GET_DISPATCH(), ARGS);
+
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ return CALL_ ## FUNC(GET_DISPATCH(), ARGS);
+
+#endif /* logging */
+
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#include "glapi/dispatch.h"
+#include "glapi/glapitemp.h"
+
+#endif /* USE_X86_ASM */
+
+#endif /* !GLX_USE_APPLEGL */
diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c
new file mode 100644
index 000000000..b53c1733f
--- /dev/null
+++ b/mesalib/src/mesa/main/dlist.c
@@ -0,0 +1,9402 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file dlist.c
+ * Display lists management functions.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+#include "api_loopback.h"
+#include "config.h"
+#include "mfeatures.h"
+#include "attrib.h"
+#include "blend.h"
+#include "buffers.h"
+#if FEATURE_ARB_vertex_buffer_object
+#include "bufferobj.h"
+#endif
+#include "arrayobj.h"
+#include "clip.h"
+#include "colortab.h"
+#include "context.h"
+#include "convolve.h"
+#include "depth.h"
+#include "dlist.h"
+#include "enable.h"
+#include "enums.h"
+#include "eval.h"
+#include "extensions.h"
+#include "feedback.h"
+#include "framebuffer.h"
+#include "get.h"
+#include "glapi/glapi.h"
+#include "hash.h"
+#include "histogram.h"
+#include "image.h"
+#include "light.h"
+#include "lines.h"
+#include "dlist.h"
+#include "macros.h"
+#include "matrix.h"
+#include "pixel.h"
+#include "points.h"
+#include "polygon.h"
+#include "queryobj.h"
+#include "state.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "mtypes.h"
+#include "varray.h"
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+#include "shader/arbprogram.h"
+#include "shader/program.h"
+#endif
+#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
+#include "shader/nvprogram.h"
+#include "shader/program.h"
+#endif
+#if FEATURE_ATI_fragment_shader
+#include "shader/atifragshader.h"
+#endif
+
+#include "math/m_matrix.h"
+
+#include "glapi/dispatch.h"
+
+
+/**
+ * Flush vertices.
+ *
+ * \param ctx GL context.
+ *
+ * Checks if dd_function_table::SaveNeedFlush is marked to flush
+ * stored (save) vertices, and calls
+ * dd_function_table::SaveFlushVertices if so.
+ */
+#define SAVE_FLUSH_VERTICES(ctx) \
+do { \
+ if (ctx->Driver.SaveNeedFlush) \
+ ctx->Driver.SaveFlushVertices(ctx); \
+} while (0)
+
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair, with return value.
+ *
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval) \
+do { \
+ if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \
+ ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \
+ return retval; \
+ } \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair.
+ *
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx) \
+do { \
+ if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \
+ ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \
+ return; \
+ } \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices.
+ *
+ * \param ctx GL context.
+ */
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx) \
+do { \
+ ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); \
+ SAVE_FLUSH_VERTICES(ctx); \
+} while (0)
+
+/**
+ * Macro to assert that the API call was made outside the
+ * glBegin()/glEnd() pair and flush the vertices, with return value.
+ *
+ * \param ctx GL context.
+ * \param retval value to return value in case the assertion fails.
+ */
+#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)\
+do { \
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval); \
+ SAVE_FLUSH_VERTICES(ctx); \
+} while (0)
+
+
+
+/**
+ * Display list opcodes.
+ *
+ * The fact that these identifiers are assigned consecutive
+ * integer values starting at 0 is very important, see InstSize array usage)
+ */
+typedef enum
+{
+ OPCODE_INVALID = -1, /* Force signed enum */
+ OPCODE_ACCUM,
+ OPCODE_ALPHA_FUNC,
+ OPCODE_BIND_TEXTURE,
+ OPCODE_BITMAP,
+ OPCODE_BLEND_COLOR,
+ OPCODE_BLEND_EQUATION,
+ OPCODE_BLEND_EQUATION_SEPARATE,
+ 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_TABLE_PARAMETER_FV,
+ OPCODE_COLOR_TABLE_PARAMETER_IV,
+ OPCODE_COLOR_SUB_TABLE,
+ OPCODE_CONVOLUTION_FILTER_1D,
+ OPCODE_CONVOLUTION_FILTER_2D,
+ OPCODE_CONVOLUTION_PARAMETER_I,
+ OPCODE_CONVOLUTION_PARAMETER_IV,
+ OPCODE_CONVOLUTION_PARAMETER_F,
+ OPCODE_CONVOLUTION_PARAMETER_FV,
+ OPCODE_COPY_COLOR_SUB_TABLE,
+ OPCODE_COPY_COLOR_TABLE,
+ OPCODE_COPY_PIXELS,
+ OPCODE_COPY_TEX_IMAGE1D,
+ OPCODE_COPY_TEX_IMAGE2D,
+ 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_EVALMESH1,
+ OPCODE_EVALMESH2,
+ OPCODE_FOG,
+ OPCODE_FRONT_FACE,
+ OPCODE_FRUSTUM,
+ OPCODE_HINT,
+ OPCODE_HISTOGRAM,
+ 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_MIN_MAX,
+ 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_READ_BUFFER,
+ OPCODE_RESET_HISTOGRAM,
+ OPCODE_RESET_MIN_MAX,
+ OPCODE_ROTATE,
+ 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,
+ /* GL_ARB_texture_compression */
+ OPCODE_COMPRESSED_TEX_IMAGE_1D,
+ OPCODE_COMPRESSED_TEX_IMAGE_2D,
+ OPCODE_COMPRESSED_TEX_IMAGE_3D,
+ OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D,
+ OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D,
+ OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D,
+ /* GL_ARB_multisample */
+ OPCODE_SAMPLE_COVERAGE,
+ /* GL_ARB_window_pos */
+ OPCODE_WINDOW_POS_ARB,
+ /* GL_NV_vertex_program */
+ OPCODE_BIND_PROGRAM_NV,
+ OPCODE_EXECUTE_PROGRAM_NV,
+ OPCODE_REQUEST_RESIDENT_PROGRAMS_NV,
+ OPCODE_LOAD_PROGRAM_NV,
+ OPCODE_TRACK_MATRIX_NV,
+ /* GL_NV_fragment_program */
+ OPCODE_PROGRAM_LOCAL_PARAMETER_ARB,
+ OPCODE_PROGRAM_NAMED_PARAMETER_NV,
+ /* GL_EXT_stencil_two_side */
+ OPCODE_ACTIVE_STENCIL_FACE_EXT,
+ /* GL_EXT_depth_bounds_test */
+ OPCODE_DEPTH_BOUNDS_EXT,
+ /* GL_ARB_vertex/fragment_program */
+ OPCODE_PROGRAM_STRING_ARB,
+ OPCODE_PROGRAM_ENV_PARAMETER_ARB,
+ /* GL_ARB_occlusion_query */
+ OPCODE_BEGIN_QUERY_ARB,
+ OPCODE_END_QUERY_ARB,
+ /* GL_ARB_draw_buffers */
+ OPCODE_DRAW_BUFFERS_ARB,
+ /* GL_ATI_fragment_shader */
+ OPCODE_TEX_BUMP_PARAMETER_ATI,
+ /* GL_ATI_fragment_shader */
+ OPCODE_BIND_FRAGMENT_SHADER_ATI,
+ OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
+ /* OpenGL 2.0 */
+ OPCODE_STENCIL_FUNC_SEPARATE,
+ OPCODE_STENCIL_OP_SEPARATE,
+ OPCODE_STENCIL_MASK_SEPARATE,
+
+ /* GL_ARB_shader_objects */
+ OPCODE_USE_PROGRAM,
+ OPCODE_UNIFORM_1F,
+ OPCODE_UNIFORM_2F,
+ OPCODE_UNIFORM_3F,
+ OPCODE_UNIFORM_4F,
+ OPCODE_UNIFORM_1FV,
+ OPCODE_UNIFORM_2FV,
+ OPCODE_UNIFORM_3FV,
+ OPCODE_UNIFORM_4FV,
+ OPCODE_UNIFORM_1I,
+ OPCODE_UNIFORM_2I,
+ OPCODE_UNIFORM_3I,
+ OPCODE_UNIFORM_4I,
+ OPCODE_UNIFORM_1IV,
+ OPCODE_UNIFORM_2IV,
+ OPCODE_UNIFORM_3IV,
+ OPCODE_UNIFORM_4IV,
+ OPCODE_UNIFORM_MATRIX22,
+ OPCODE_UNIFORM_MATRIX33,
+ OPCODE_UNIFORM_MATRIX44,
+ OPCODE_UNIFORM_MATRIX23,
+ OPCODE_UNIFORM_MATRIX32,
+ OPCODE_UNIFORM_MATRIX24,
+ OPCODE_UNIFORM_MATRIX42,
+ OPCODE_UNIFORM_MATRIX34,
+ OPCODE_UNIFORM_MATRIX43,
+
+ /* GL_EXT_framebuffer_blit */
+ OPCODE_BLIT_FRAMEBUFFER,
+
+ /* Vertex attributes -- fallback for when optimized display
+ * list build isn't active.
+ */
+ OPCODE_ATTR_1F_NV,
+ OPCODE_ATTR_2F_NV,
+ OPCODE_ATTR_3F_NV,
+ OPCODE_ATTR_4F_NV,
+ OPCODE_ATTR_1F_ARB,
+ OPCODE_ATTR_2F_ARB,
+ OPCODE_ATTR_3F_ARB,
+ OPCODE_ATTR_4F_ARB,
+ OPCODE_MATERIAL,
+ OPCODE_BEGIN,
+ OPCODE_END,
+ OPCODE_RECTF,
+ OPCODE_EVAL_C1,
+ OPCODE_EVAL_C2,
+ OPCODE_EVAL_P1,
+ OPCODE_EVAL_P2,
+
+ /* GL_EXT_provoking_vertex */
+ OPCODE_PROVOKING_VERTEX,
+
+ /* The following three are meta instructions */
+ OPCODE_ERROR, /* raise compiled-in error */
+ OPCODE_CONTINUE,
+ OPCODE_END_OF_LIST,
+ OPCODE_EXT_0
+} OpCode;
+
+
+
+/**
+ * Display list node.
+ *
+ * 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.
+ *
+ * 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 data types.
+ */
+union gl_dlist_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 */
+};
+
+
+typedef union gl_dlist_node Node;
+
+
+/**
+ * How many nodes to allocate at a time.
+ *
+ * \note Reduced now that we hold vertices etc. elsewhere.
+ */
+#define BLOCK_SIZE 256
+
+
+
+/**
+ * Number of nodes of storage needed for each instruction.
+ * Sizes for dynamically allocated opcodes are stored in the context struct.
+ */
+static GLuint InstSize[OPCODE_END_OF_LIST + 1];
+
+void mesa_print_display_list(GLuint list);
+
+
+/**********************************************************************/
+/***** Private *****/
+/**********************************************************************/
+
+
+/**
+ * Make an empty display list. This is used by glGenLists() to
+ * reserve display list IDs.
+ */
+static struct gl_display_list *
+make_list(GLuint name, GLuint count)
+{
+ struct gl_display_list *dlist = CALLOC_STRUCT(gl_display_list);
+ dlist->Name = name;
+ dlist->Head = (Node *) _mesa_malloc(sizeof(Node) * count);
+ dlist->Head[0].opcode = OPCODE_END_OF_LIST;
+ return dlist;
+}
+
+
+/**
+ * Lookup function to just encapsulate casting.
+ */
+static INLINE struct gl_display_list *
+lookup_list(GLcontext *ctx, GLuint list)
+{
+ return (struct gl_display_list *)
+ _mesa_HashLookup(ctx->Shared->DisplayList, list);
+}
+
+
+
+/**
+ * Delete the named display list, but don't remove from hash table.
+ * \param dlist - display list pointer
+ */
+void
+_mesa_delete_list(GLcontext *ctx, struct gl_display_list *dlist)
+{
+ Node *n, *block;
+ GLboolean done;
+
+ n = block = dlist->Head;
+
+ done = block ? GL_FALSE : GL_TRUE;
+ while (!done) {
+
+ /* check for extension opcodes first */
+
+ GLint i = (GLint) n[0].opcode - (GLint) OPCODE_EXT_0;
+ if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) {
+ ctx->ListExt.Opcode[i].Destroy(ctx, &n[1]);
+ n += ctx->ListExt.Opcode[i].Size;
+ }
+ else {
+ switch (n[0].opcode) {
+ /* for some commands, we need to free malloc'd memory */
+ case OPCODE_MAP1:
+ _mesa_free(n[6].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_MAP2:
+ _mesa_free(n[10].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_DRAW_PIXELS:
+ _mesa_free(n[5].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_BITMAP:
+ _mesa_free(n[7].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COLOR_TABLE:
+ _mesa_free(n[6].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COLOR_SUB_TABLE:
+ _mesa_free(n[6].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_CONVOLUTION_FILTER_1D:
+ _mesa_free(n[6].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_CONVOLUTION_FILTER_2D:
+ _mesa_free(n[7].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_POLYGON_STIPPLE:
+ _mesa_free(n[1].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_IMAGE1D:
+ _mesa_free(n[8].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_IMAGE2D:
+ _mesa_free(n[9].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_IMAGE3D:
+ _mesa_free(n[10].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_SUB_IMAGE1D:
+ _mesa_free(n[7].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_SUB_IMAGE2D:
+ _mesa_free(n[9].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_SUB_IMAGE3D:
+ _mesa_free(n[11].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_1D:
+ _mesa_free(n[7].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_2D:
+ _mesa_free(n[8].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_3D:
+ _mesa_free(n[9].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D:
+ _mesa_free(n[7].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D:
+ _mesa_free(n[9].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D:
+ _mesa_free(n[11].data);
+ n += InstSize[n[0].opcode];
+ break;
+#if FEATURE_NV_vertex_program
+ case OPCODE_LOAD_PROGRAM_NV:
+ _mesa_free(n[4].data); /* program string */
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_REQUEST_RESIDENT_PROGRAMS_NV:
+ _mesa_free(n[2].data); /* array of program ids */
+ n += InstSize[n[0].opcode];
+ break;
+#endif
+#if FEATURE_NV_fragment_program
+ case OPCODE_PROGRAM_NAMED_PARAMETER_NV:
+ _mesa_free(n[3].data); /* parameter name */
+ n += InstSize[n[0].opcode];
+ break;
+#endif
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ case OPCODE_PROGRAM_STRING_ARB:
+ _mesa_free(n[4].data); /* program string */
+ n += InstSize[n[0].opcode];
+ break;
+#endif
+ case OPCODE_UNIFORM_1FV:
+ case OPCODE_UNIFORM_2FV:
+ case OPCODE_UNIFORM_3FV:
+ case OPCODE_UNIFORM_4FV:
+ case OPCODE_UNIFORM_1IV:
+ case OPCODE_UNIFORM_2IV:
+ case OPCODE_UNIFORM_3IV:
+ case OPCODE_UNIFORM_4IV:
+ _mesa_free(n[3].data);
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_UNIFORM_MATRIX22:
+ case OPCODE_UNIFORM_MATRIX33:
+ case OPCODE_UNIFORM_MATRIX44:
+ case OPCODE_UNIFORM_MATRIX24:
+ case OPCODE_UNIFORM_MATRIX42:
+ case OPCODE_UNIFORM_MATRIX23:
+ case OPCODE_UNIFORM_MATRIX32:
+ case OPCODE_UNIFORM_MATRIX34:
+ case OPCODE_UNIFORM_MATRIX43:
+ _mesa_free(n[4].data);
+ n += InstSize[n[0].opcode];
+ break;
+
+ case OPCODE_CONTINUE:
+ n = (Node *) n[1].next;
+ _mesa_free(block);
+ block = n;
+ break;
+ case OPCODE_END_OF_LIST:
+ _mesa_free(block);
+ done = GL_TRUE;
+ break;
+ default:
+ /* Most frequent case */
+ n += InstSize[n[0].opcode];
+ break;
+ }
+ }
+ }
+
+ _mesa_free(dlist);
+}
+
+
+/**
+ * Destroy a display list and remove from hash table.
+ * \param list - display list number
+ */
+static void
+destroy_list(GLcontext *ctx, GLuint list)
+{
+ struct gl_display_list *dlist;
+
+ if (list == 0)
+ return;
+
+ dlist = lookup_list(ctx, list);
+ if (!dlist)
+ return;
+
+ _mesa_delete_list(ctx, dlist);
+ _mesa_HashRemove(ctx->Shared->DisplayList, list);
+}
+
+
+/*
+ * Translate the nth element of list from <type> to GLint.
+ */
+static GLint
+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 (GLint) bptr[n];
+ case GL_UNSIGNED_BYTE:
+ ubptr = (GLubyte *) list;
+ return (GLint) ubptr[n];
+ case GL_SHORT:
+ sptr = (GLshort *) list;
+ return (GLint) sptr[n];
+ case GL_UNSIGNED_SHORT:
+ usptr = (GLushort *) list;
+ return (GLint) usptr[n];
+ case GL_INT:
+ iptr = (GLint *) list;
+ return iptr[n];
+ case GL_UNSIGNED_INT:
+ uiptr = (GLuint *) list;
+ return (GLint) uiptr[n];
+ case GL_FLOAT:
+ fptr = (GLfloat *) list;
+ return (GLint) FLOORF(fptr[n]);
+ case GL_2_BYTES:
+ ubptr = ((GLubyte *) list) + 2 * n;
+ return (GLint) ubptr[0] * 256
+ + (GLint) ubptr[1];
+ case GL_3_BYTES:
+ ubptr = ((GLubyte *) list) + 3 * n;
+ return (GLint) ubptr[0] * 65536
+ + (GLint) ubptr[1] * 256
+ + (GLint) ubptr[2];
+ case GL_4_BYTES:
+ ubptr = ((GLubyte *) list) + 4 * n;
+ return (GLint) ubptr[0] * 16777216
+ + (GLint) ubptr[1] * 65536
+ + (GLint) ubptr[2] * 256
+ + (GLint) ubptr[3];
+ default:
+ return 0;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Public *****/
+/**********************************************************************/
+
+/**
+ * Wrapper for _mesa_unpack_image() that handles pixel buffer objects.
+ * If we run out of memory, GL_OUT_OF_MEMORY will be recorded.
+ */
+static GLvoid *
+unpack_image(GLcontext *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *unpack)
+{
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* no PBO */
+ GLvoid *image = _mesa_unpack_image(dimensions, width, height, depth,
+ format, type, pixels, unpack);
+ if (pixels && !image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
+ }
+ return image;
+ }
+ else if (_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+ format, type, pixels)) {
+ const GLubyte *map, *src;
+ GLvoid *image;
+
+ map = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, unpack->BufferObj);
+ if (!map) {
+ /* unable to map src buffer! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO");
+ return NULL;
+ }
+
+ src = ADD_POINTERS(map, pixels);
+ image = _mesa_unpack_image(dimensions, width, height, depth,
+ format, type, src, unpack);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
+ }
+ return image;
+ }
+ /* bad access! */
+ return NULL;
+}
+
+
+/**
+ * Allocate space for a display list instruction.
+ * \param opcode the instruction opcode (OPCODE_* value)
+ * \param bytes instruction size in bytes, not counting opcode.
+ * \return pointer to the usable data area (not including the internal
+ * opcode).
+ */
+void *
+_mesa_alloc_instruction(GLcontext *ctx, GLuint opcode, GLuint bytes)
+{
+ const GLuint numNodes = 1 + (bytes + sizeof(Node) - 1) / sizeof(Node);
+ Node *n;
+
+ if (opcode < (GLuint) OPCODE_EXT_0) {
+ if (InstSize[opcode] == 0) {
+ /* save instruction size now */
+ InstSize[opcode] = numNodes;
+ }
+ else {
+ /* make sure instruction size agrees */
+ ASSERT(numNodes == InstSize[opcode]);
+ }
+ }
+
+ if (ctx->ListState.CurrentPos + numNodes + 2 > BLOCK_SIZE) {
+ /* This block is full. Allocate a new block and chain to it */
+ Node *newblock;
+ n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
+ n[0].opcode = OPCODE_CONTINUE;
+ newblock = (Node *) _mesa_malloc(sizeof(Node) * BLOCK_SIZE);
+ if (!newblock) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Building display list");
+ return NULL;
+ }
+ n[1].next = (Node *) newblock;
+ ctx->ListState.CurrentBlock = newblock;
+ ctx->ListState.CurrentPos = 0;
+ }
+
+ n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
+ ctx->ListState.CurrentPos += numNodes;
+
+ n[0].opcode = (OpCode) opcode;
+
+ return (void *) (n + 1); /* return ptr to node following opcode */
+}
+
+
+/**
+ * This function allows modules and drivers to get their own opcodes
+ * for extending display list functionality.
+ * \param ctx the rendering context
+ * \param size number of bytes for storing the new display list command
+ * \param execute function to execute the new display list command
+ * \param destroy function to destroy the new display list command
+ * \param print function to print the new display list command
+ * \return the new opcode number or -1 if error
+ */
+GLint
+_mesa_alloc_opcode(GLcontext *ctx,
+ GLuint size,
+ void (*execute) (GLcontext *, void *),
+ void (*destroy) (GLcontext *, void *),
+ void (*print) (GLcontext *, void *))
+{
+ if (ctx->ListExt.NumOpcodes < MAX_DLIST_EXT_OPCODES) {
+ const GLuint i = ctx->ListExt.NumOpcodes++;
+ ctx->ListExt.Opcode[i].Size =
+ 1 + (size + sizeof(Node) - 1) / sizeof(Node);
+ ctx->ListExt.Opcode[i].Execute = execute;
+ ctx->ListExt.Opcode[i].Destroy = destroy;
+ ctx->ListExt.Opcode[i].Print = print;
+ return i + OPCODE_EXT_0;
+ }
+ return -1;
+}
+
+
+
+/**
+ * Allocate display list instruction. Returns Node ptr to where the opcode
+ * is stored.
+ * - nParams is the number of function parameters
+ * - return value a pointer to sizeof(Node) before the actual
+ * usable data area.
+ */
+#define ALLOC_INSTRUCTION(CTX, OPCODE, NPARAMS) \
+ ((Node *)_mesa_alloc_instruction(CTX, OPCODE, (NPARAMS)*sizeof(Node)) - 1)
+
+
+
+/*
+ * Display List compilation functions
+ */
+static void GLAPIENTRY
+save_Accum(GLenum op, GLfloat value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ACCUM, 2);
+ if (n) {
+ n[1].e = op;
+ n[2].f = value;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Accum(ctx->Exec, (op, value));
+ }
+}
+
+
+static void GLAPIENTRY
+save_AlphaFunc(GLenum func, GLclampf ref)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ALPHA_FUNC, 2);
+ if (n) {
+ n[1].e = func;
+ n[2].f = (GLfloat) ref;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_AlphaFunc(ctx->Exec, (func, ref));
+ }
+}
+
+
+static void GLAPIENTRY
+save_BindTexture(GLenum target, GLuint texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BIND_TEXTURE, 2);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = texture;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BindTexture(ctx->Exec, (target, texture));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Bitmap(GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove, const GLubyte * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BITMAP, 7);
+ if (n) {
+ 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 = _mesa_unpack_bitmap(width, height, pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Bitmap(ctx->Exec, (width, height,
+ xorig, yorig, xmove, ymove, pixels));
+ }
+}
+
+
+static void GLAPIENTRY
+save_BlendEquation(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BLEND_EQUATION, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BlendEquation(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_BlendEquationSeparateEXT(GLenum modeRGB, GLenum modeA)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BLEND_EQUATION_SEPARATE, 2);
+ if (n) {
+ n[1].e = modeRGB;
+ n[2].e = modeA;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BlendEquationSeparateEXT(ctx->Exec, (modeRGB, modeA));
+ }
+}
+
+
+static void GLAPIENTRY
+save_BlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_BlendFuncSeparateEXT(ctx->Exec,
+ (sfactorRGB, dfactorRGB, sfactorA, dfactorA));
+ }
+}
+
+
+static void GLAPIENTRY
+save_BlendFunc(GLenum srcfactor, GLenum dstfactor)
+{
+ save_BlendFuncSeparateEXT(srcfactor, dstfactor, srcfactor, dstfactor);
+}
+
+
+static void GLAPIENTRY
+save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_BlendColor(ctx->Exec, (red, green, blue, alpha));
+ }
+}
+
+static void invalidate_saved_current_state( GLcontext *ctx )
+{
+ GLint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ ctx->ListState.ActiveAttribSize[i] = 0;
+
+ for (i = 0; i < MAT_ATTRIB_MAX; i++)
+ ctx->ListState.ActiveMaterialSize[i] = 0;
+
+ memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+}
+
+void GLAPIENTRY
+_mesa_save_CallList(GLuint list)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CALL_LIST, 1);
+ if (n) {
+ n[1].ui = list;
+ }
+
+ /* After this, we don't know what state we're in. Invalidate all
+ * cached information previously gathered:
+ */
+ invalidate_saved_current_state( ctx );
+
+ if (ctx->ExecuteFlag) {
+ _mesa_CallList(list);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_save_CallLists(GLsizei num, GLenum type, const GLvoid * lists)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ GLboolean typeErrorFlag;
+
+ SAVE_FLUSH_VERTICES(ctx);
+
+ 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_2_BYTES:
+ case GL_3_BYTES:
+ case GL_4_BYTES:
+ typeErrorFlag = GL_FALSE;
+ break;
+ default:
+ typeErrorFlag = GL_TRUE;
+ }
+
+ for (i = 0; i < num; i++) {
+ GLint list = translate_id(i, type, lists);
+ Node *n = ALLOC_INSTRUCTION(ctx, OPCODE_CALL_LIST_OFFSET, 2);
+ if (n) {
+ n[1].i = list;
+ n[2].b = typeErrorFlag;
+ }
+ }
+
+ /* After this, we don't know what state we're in. Invalidate all
+ * cached information previously gathered:
+ */
+ invalidate_saved_current_state( ctx );
+
+ if (ctx->ExecuteFlag) {
+ CALL_CallLists(ctx->Exec, (num, type, lists));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Clear(GLbitfield mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CLEAR, 1);
+ if (n) {
+ n[1].bf = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Clear(ctx->Exec, (mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_ClearAccum(ctx->Exec, (red, green, blue, alpha));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_ClearColor(ctx->Exec, (red, green, blue, alpha));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClearDepth(GLclampd depth)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CLEAR_DEPTH, 1);
+ if (n) {
+ n[1].f = (GLfloat) depth;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ClearDepth(ctx->Exec, (depth));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClearIndex(GLfloat c)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CLEAR_INDEX, 1);
+ if (n) {
+ n[1].f = c;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ClearIndex(ctx->Exec, (c));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClearStencil(GLint s)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CLEAR_STENCIL, 1);
+ if (n) {
+ n[1].i = s;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ClearStencil(ctx->Exec, (s));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ClipPlane(GLenum plane, const GLdouble * equ)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CLIP_PLANE, 5);
+ if (n) {
+ n[1].e = plane;
+ n[2].f = (GLfloat) equ[0];
+ n[3].f = (GLfloat) equ[1];
+ n[4].f = (GLfloat) equ[2];
+ n[5].f = (GLfloat) equ[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ClipPlane(ctx->Exec, (plane, equ));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_ColorMask(GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_ColorMask(ctx->Exec, (red, green, blue, alpha));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ColorMaterial(GLenum face, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_MATERIAL, 2);
+ if (n) {
+ n[1].e = face;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ColorMaterial(ctx->Exec, (face, mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ColorTable(GLenum target, GLenum internalFormat,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid * table)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (_mesa_is_proxy_texture(target)) {
+ /* execute immediately */
+ CALL_ColorTable(ctx->Exec, (target, internalFormat, width,
+ format, type, table));
+ }
+ else {
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_TABLE, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalFormat;
+ n[3].i = width;
+ n[4].e = format;
+ n[5].e = type;
+ n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, table,
+ &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ColorTable(ctx->Exec, (target, internalFormat, width,
+ format, type, table));
+ }
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_ColorTableParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_TABLE_PARAMETER_FV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].f = params[0];
+ if (pname == GL_COLOR_TABLE_SGI ||
+ pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
+ pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI ||
+ pname == GL_TEXTURE_COLOR_TABLE_SGI) {
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_ColorTableParameterfv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_TABLE_PARAMETER_IV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].i = params[0];
+ if (pname == GL_COLOR_TABLE_SGI ||
+ pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
+ pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI ||
+ pname == GL_TEXTURE_COLOR_TABLE_SGI) {
+ n[4].i = params[1];
+ n[5].i = params[2];
+ n[6].i = params[3];
+ }
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_ColorTableParameteriv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_ColorSubTable(GLenum target, GLsizei start, GLsizei count,
+ GLenum format, GLenum type, const GLvoid * table)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COLOR_SUB_TABLE, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].i = start;
+ n[3].i = count;
+ n[4].e = format;
+ n[5].e = type;
+ n[6].data = unpack_image(ctx, 1, count, 1, 1, format, type, table,
+ &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ColorSubTable(ctx->Exec,
+ (target, start, count, format, type, table));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyColorSubTable(GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COPY_COLOR_SUB_TABLE, 5);
+ if (n) {
+ n[1].e = target;
+ n[2].i = start;
+ n[3].i = x;
+ n[4].i = y;
+ n[5].i = width;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CopyColorSubTable(ctx->Exec, (target, start, x, y, width));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyColorTable(GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COPY_COLOR_TABLE, 5);
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalformat;
+ n[3].i = x;
+ n[4].i = y;
+ n[5].i = width;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CopyColorTable(ctx->Exec, (target, internalformat, x, y, width));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width,
+ GLenum format, GLenum type, const GLvoid * filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_1D, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalFormat;
+ n[3].i = width;
+ n[4].e = format;
+ n[5].e = type;
+ n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, filter,
+ &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionFilter1D(ctx->Exec, (target, internalFormat, width,
+ format, type, filter));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionFilter2D(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid * filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_FILTER_2D, 7);
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalFormat;
+ n[3].i = width;
+ n[4].i = height;
+ n[5].e = format;
+ n[6].e = type;
+ n[7].data = unpack_image(ctx, 2, width, height, 1, format, type, filter,
+ &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionFilter2D(ctx->Exec,
+ (target, internalFormat, width, height, format,
+ type, filter));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_PARAMETER_I, 3);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].i = param;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionParameteri(ctx->Exec, (target, pname, param));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_PARAMETER_IV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].i = params[0];
+ if (pname == GL_CONVOLUTION_BORDER_COLOR ||
+ pname == GL_CONVOLUTION_FILTER_SCALE ||
+ pname == GL_CONVOLUTION_FILTER_BIAS) {
+ n[4].i = params[1];
+ n[5].i = params[2];
+ n[6].i = params[3];
+ }
+ else {
+ n[4].i = n[5].i = n[6].i = 0;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionParameteriv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_PARAMETER_F, 3);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].f = param;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionParameterf(ctx->Exec, (target, pname, param));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ConvolutionParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CONVOLUTION_PARAMETER_FV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].f = params[0];
+ if (pname == GL_CONVOLUTION_BORDER_COLOR ||
+ pname == GL_CONVOLUTION_FILTER_SCALE ||
+ pname == GL_CONVOLUTION_FILTER_BIAS) {
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ else {
+ n[4].f = n[5].f = n[6].f = 0.0F;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ConvolutionParameterfv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyPixels(ctx->Exec, (x, y, width, height, type));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_CopyTexImage1D(GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLint border)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyTexImage1D(ctx->Exec, (target, level, internalformat,
+ x, y, width, border));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyTexImage2D(GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y, GLsizei width,
+ GLsizei height, GLint border)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyTexImage2D(ctx->Exec, (target, level, internalformat,
+ x, y, width, height, border));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_CopyTexSubImage1D(GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyTexSubImage1D(ctx->Exec,
+ (target, level, xoffset, x, y, width));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyTexSubImage2D(GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLint height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyTexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
+ x, y, width, height));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CopyTexSubImage3D(GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLint height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_CopyTexSubImage3D(ctx->Exec, (target, level,
+ xoffset, yoffset, zoffset,
+ x, y, width, height));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CullFace(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_CULL_FACE, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CullFace(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_DepthFunc(GLenum func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DEPTH_FUNC, 1);
+ if (n) {
+ n[1].e = func;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DepthFunc(ctx->Exec, (func));
+ }
+}
+
+
+static void GLAPIENTRY
+save_DepthMask(GLboolean mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DEPTH_MASK, 1);
+ if (n) {
+ n[1].b = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DepthMask(ctx->Exec, (mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_DepthRange(GLclampd nearval, GLclampd farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DEPTH_RANGE, 2);
+ if (n) {
+ n[1].f = (GLfloat) nearval;
+ n[2].f = (GLfloat) farval;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DepthRange(ctx->Exec, (nearval, farval));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Disable(GLenum cap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DISABLE, 1);
+ if (n) {
+ n[1].e = cap;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Disable(ctx->Exec, (cap));
+ }
+}
+
+
+static void GLAPIENTRY
+save_DrawBuffer(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DRAW_BUFFER, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawBuffer(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_DrawPixels(GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DRAW_PIXELS, 5);
+ if (n) {
+ n[1].i = width;
+ n[2].i = height;
+ n[3].e = format;
+ n[4].e = type;
+ n[5].data = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_Enable(GLenum cap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ENABLE, 1);
+ if (n) {
+ n[1].e = cap;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Enable(ctx->Exec, (cap));
+ }
+}
+
+
+
+static void GLAPIENTRY
+_mesa_save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EVALMESH1, 3);
+ if (n) {
+ n[1].e = mode;
+ n[2].i = i1;
+ n[3].i = i2;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EvalMesh1(ctx->Exec, (mode, i1, i2));
+ }
+}
+
+
+static void GLAPIENTRY
+_mesa_save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_EvalMesh2(ctx->Exec, (mode, i1, i2, j1, j2));
+ }
+}
+
+
+
+
+static void GLAPIENTRY
+save_Fogfv(GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_Fogfv(ctx->Exec, (pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Fogf(GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_Fogfv(pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_Fogiv(GLenum pname, const GLint *params)
+{
+ GLfloat p[4];
+ switch (pname) {
+ case GL_FOG_MODE:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_INDEX:
+ p[0] = (GLfloat) *params;
+ break;
+ case GL_FOG_COLOR:
+ p[0] = INT_TO_FLOAT(params[0]);
+ p[1] = INT_TO_FLOAT(params[1]);
+ p[2] = INT_TO_FLOAT(params[2]);
+ p[3] = INT_TO_FLOAT(params[3]);
+ break;
+ default:
+ /* Error will be caught later in gl_Fogfv */
+ ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ save_Fogfv(pname, p);
+}
+
+
+static void GLAPIENTRY
+save_Fogi(GLenum pname, GLint param)
+{
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_Fogiv(pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_FrontFace(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_FRONT_FACE, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_FrontFace(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Frustum(GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_FRUSTUM, 6);
+ if (n) {
+ n[1].f = (GLfloat) left;
+ n[2].f = (GLfloat) right;
+ n[3].f = (GLfloat) bottom;
+ n[4].f = (GLfloat) top;
+ n[5].f = (GLfloat) nearval;
+ n[6].f = (GLfloat) farval;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Frustum(ctx->Exec, (left, right, bottom, top, nearval, farval));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Hint(GLenum target, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_HINT, 2);
+ if (n) {
+ n[1].e = target;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Hint(ctx->Exec, (target, mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Histogram(GLenum target, GLsizei width, GLenum internalFormat,
+ GLboolean sink)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_HISTOGRAM, 4);
+ if (n) {
+ n[1].e = target;
+ n[2].i = width;
+ n[3].e = internalFormat;
+ n[4].b = sink;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Histogram(ctx->Exec, (target, width, internalFormat, sink));
+ }
+}
+
+
+static void GLAPIENTRY
+save_IndexMask(GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_INDEX_MASK, 1);
+ if (n) {
+ n[1].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_IndexMask(ctx->Exec, (mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_InitNames(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_INIT_NAMES, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_InitNames(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_Lightfv(GLenum light, GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LIGHT, 6);
+ if (n) {
+ GLint i, nParams;
+ n[1].e = light;
+ n[2].e = pname;
+ switch (pname) {
+ case GL_AMBIENT:
+ nParams = 4;
+ break;
+ case GL_DIFFUSE:
+ nParams = 4;
+ break;
+ case GL_SPECULAR:
+ nParams = 4;
+ break;
+ case GL_POSITION:
+ nParams = 4;
+ break;
+ case GL_SPOT_DIRECTION:
+ nParams = 3;
+ break;
+ case GL_SPOT_EXPONENT:
+ nParams = 1;
+ break;
+ case GL_SPOT_CUTOFF:
+ nParams = 1;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ nParams = 1;
+ break;
+ case GL_LINEAR_ATTENUATION:
+ nParams = 1;
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ nParams = 1;
+ break;
+ default:
+ nParams = 0;
+ }
+ for (i = 0; i < nParams; i++) {
+ n[3 + i].f = params[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Lightfv(ctx->Exec, (light, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Lightf(GLenum light, GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_Lightfv(light, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_Lightiv(GLenum light, GLenum pname, const GLint *params)
+{
+ GLfloat fparam[4];
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ fparam[0] = INT_TO_FLOAT(params[0]);
+ fparam[1] = INT_TO_FLOAT(params[1]);
+ fparam[2] = INT_TO_FLOAT(params[2]);
+ fparam[3] = INT_TO_FLOAT(params[3]);
+ break;
+ case GL_POSITION:
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = (GLfloat) params[1];
+ fparam[2] = (GLfloat) params[2];
+ fparam[3] = (GLfloat) params[3];
+ break;
+ case GL_SPOT_DIRECTION:
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = (GLfloat) params[1];
+ fparam[2] = (GLfloat) params[2];
+ break;
+ case GL_SPOT_EXPONENT:
+ case GL_SPOT_CUTOFF:
+ case GL_CONSTANT_ATTENUATION:
+ case GL_LINEAR_ATTENUATION:
+ case GL_QUADRATIC_ATTENUATION:
+ fparam[0] = (GLfloat) params[0];
+ break;
+ default:
+ /* error will be caught later in gl_Lightfv */
+ ;
+ }
+ save_Lightfv(light, pname, fparam);
+}
+
+
+static void GLAPIENTRY
+save_Lighti(GLenum light, GLenum pname, GLint param)
+{
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_Lightiv(light, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_LightModelfv(GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_LightModelfv(ctx->Exec, (pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_LightModelf(GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_LightModelfv(pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_LightModeliv(GLenum pname, const GLint *params)
+{
+ GLfloat fparam[4];
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ fparam[0] = INT_TO_FLOAT(params[0]);
+ fparam[1] = INT_TO_FLOAT(params[1]);
+ fparam[2] = INT_TO_FLOAT(params[2]);
+ fparam[3] = INT_TO_FLOAT(params[3]);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ fparam[0] = (GLfloat) params[0];
+ break;
+ default:
+ /* Error will be caught later in gl_LightModelfv */
+ ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ save_LightModelfv(pname, fparam);
+}
+
+
+static void GLAPIENTRY
+save_LightModeli(GLenum pname, GLint param)
+{
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_LightModeliv(pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_LineStipple(GLint factor, GLushort pattern)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LINE_STIPPLE, 2);
+ if (n) {
+ n[1].i = factor;
+ n[2].us = pattern;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_LineStipple(ctx->Exec, (factor, pattern));
+ }
+}
+
+
+static void GLAPIENTRY
+save_LineWidth(GLfloat width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LINE_WIDTH, 1);
+ if (n) {
+ n[1].f = width;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_LineWidth(ctx->Exec, (width));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ListBase(GLuint base)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LIST_BASE, 1);
+ if (n) {
+ n[1].ui = base;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ListBase(ctx->Exec, (base));
+ }
+}
+
+
+static void GLAPIENTRY
+save_LoadIdentity(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_LOAD_IDENTITY, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_LoadIdentity(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_LoadMatrixf(const GLfloat * m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_LoadMatrixf(ctx->Exec, (m));
+ }
+}
+
+
+static void GLAPIENTRY
+save_LoadMatrixd(const GLdouble * m)
+{
+ GLfloat f[16];
+ GLint i;
+ for (i = 0; i < 16; i++) {
+ f[i] = (GLfloat) m[i];
+ }
+ save_LoadMatrixf(f);
+}
+
+
+static void GLAPIENTRY
+save_LoadName(GLuint name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LOAD_NAME, 1);
+ if (n) {
+ n[1].ui = name;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_LoadName(ctx->Exec, (name));
+ }
+}
+
+
+static void GLAPIENTRY
+save_LogicOp(GLenum opcode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LOGIC_OP, 1);
+ if (n) {
+ n[1].e = opcode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_LogicOp(ctx->Exec, (opcode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride,
+ GLint order, const GLdouble * points)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MAP1, 6);
+ if (n) {
+ GLfloat *pnts = _mesa_copy_map_points1d(target, stride, order, points);
+ n[1].e = target;
+ n[2].f = (GLfloat) u1;
+ n[3].f = (GLfloat) u2;
+ n[4].i = _mesa_evaluator_components(target); /* stride */
+ n[5].i = order;
+ n[6].data = (void *) pnts;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Map1d(ctx->Exec, (target, u1, u2, stride, order, points));
+ }
+}
+
+static void GLAPIENTRY
+save_Map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat * points)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MAP1, 6);
+ if (n) {
+ GLfloat *pnts = _mesa_copy_map_points1f(target, stride, order, points);
+ n[1].e = target;
+ n[2].f = u1;
+ n[3].f = u2;
+ n[4].i = _mesa_evaluator_components(target); /* stride */
+ n[5].i = order;
+ n[6].data = (void *) pnts;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Map1f(ctx->Exec, (target, u1, u2, stride, order, points));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Map2d(GLenum target,
+ GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
+ const GLdouble * points)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MAP2, 10);
+ if (n) {
+ GLfloat *pnts = _mesa_copy_map_points2d(target, ustride, uorder,
+ vstride, vorder, points);
+ n[1].e = target;
+ n[2].f = (GLfloat) u1;
+ n[3].f = (GLfloat) u2;
+ n[4].f = (GLfloat) v1;
+ n[5].f = (GLfloat) v2;
+ /* XXX verify these strides are correct */
+ n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride */
+ n[7].i = _mesa_evaluator_components(target); /*vstride */
+ n[8].i = uorder;
+ n[9].i = vorder;
+ n[10].data = (void *) pnts;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Map2d(ctx->Exec, (target,
+ u1, u2, ustride, uorder,
+ v1, v2, vstride, vorder, points));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Map2f(GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat * points)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MAP2, 10);
+ if (n) {
+ GLfloat *pnts = _mesa_copy_map_points2f(target, ustride, uorder,
+ vstride, vorder, points);
+ n[1].e = target;
+ n[2].f = u1;
+ n[3].f = u2;
+ n[4].f = v1;
+ n[5].f = v2;
+ /* XXX verify these strides are correct */
+ n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride */
+ n[7].i = _mesa_evaluator_components(target); /*vstride */
+ n[8].i = uorder;
+ n[9].i = vorder;
+ n[10].data = (void *) pnts;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder,
+ v1, v2, vstride, vorder, points));
+ }
+}
+
+
+static void GLAPIENTRY
+save_MapGrid1f(GLint un, GLfloat u1, GLfloat u2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MAPGRID1, 3);
+ if (n) {
+ n[1].i = un;
+ n[2].f = u1;
+ n[3].f = u2;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_MapGrid1f(ctx->Exec, (un, u1, u2));
+ }
+}
+
+
+static void GLAPIENTRY
+save_MapGrid1d(GLint un, GLdouble u1, GLdouble u2)
+{
+ save_MapGrid1f(un, (GLfloat) u1, (GLfloat) u2);
+}
+
+
+static void GLAPIENTRY
+save_MapGrid2f(GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_MapGrid2f(ctx->Exec, (un, u1, u2, vn, v1, v2));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_MapGrid2d(GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2)
+{
+ save_MapGrid2f(un, (GLfloat) u1, (GLfloat) u2,
+ vn, (GLfloat) v1, (GLfloat) v2);
+}
+
+
+static void GLAPIENTRY
+save_MatrixMode(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MATRIX_MODE, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_MatrixMode(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Minmax(GLenum target, GLenum internalFormat, GLboolean sink)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MIN_MAX, 3);
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalFormat;
+ n[3].b = sink;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Minmax(ctx->Exec, (target, internalFormat, sink));
+ }
+}
+
+
+static void GLAPIENTRY
+save_MultMatrixf(const GLfloat * m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_MultMatrixf(ctx->Exec, (m));
+ }
+}
+
+
+static void GLAPIENTRY
+save_MultMatrixd(const GLdouble * m)
+{
+ GLfloat f[16];
+ GLint i;
+ for (i = 0; i < 16; i++) {
+ f[i] = (GLfloat) m[i];
+ }
+ save_MultMatrixf(f);
+}
+
+
+static void GLAPIENTRY
+save_NewList(GLuint name, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* It's an error to call this function while building a display list */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
+ (void) name;
+ (void) mode;
+}
+
+
+
+static void GLAPIENTRY
+save_Ortho(GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ORTHO, 6);
+ if (n) {
+ n[1].f = (GLfloat) left;
+ n[2].f = (GLfloat) right;
+ n[3].f = (GLfloat) bottom;
+ n[4].f = (GLfloat) top;
+ n[5].f = (GLfloat) nearval;
+ n[6].f = (GLfloat) farval;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Ortho(ctx->Exec, (left, right, bottom, top, nearval, farval));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PixelMapfv(GLenum map, GLint mapsize, const GLfloat *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PIXEL_MAP, 3);
+ if (n) {
+ n[1].e = map;
+ n[2].i = mapsize;
+ n[3].data = (void *) _mesa_malloc(mapsize * sizeof(GLfloat));
+ MEMCPY(n[3].data, (void *) values, mapsize * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PixelMapfv(ctx->Exec, (map, mapsize, values));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PixelMapuiv(GLenum map, GLint mapsize, const GLuint *values)
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GLint i;
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = UINT_TO_FLOAT(values[i]);
+ }
+ }
+ save_PixelMapfv(map, mapsize, fvalues);
+}
+
+
+static void GLAPIENTRY
+save_PixelMapusv(GLenum map, GLint mapsize, const GLushort *values)
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GLint i;
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = USHORT_TO_FLOAT(values[i]);
+ }
+ }
+ save_PixelMapfv(map, mapsize, fvalues);
+}
+
+
+static void GLAPIENTRY
+save_PixelTransferf(GLenum pname, GLfloat param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PIXEL_TRANSFER, 2);
+ if (n) {
+ n[1].e = pname;
+ n[2].f = param;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PixelTransferf(ctx->Exec, (pname, param));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PixelTransferi(GLenum pname, GLint param)
+{
+ save_PixelTransferf(pname, (GLfloat) param);
+}
+
+
+static void GLAPIENTRY
+save_PixelZoom(GLfloat xfactor, GLfloat yfactor)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PIXEL_ZOOM, 2);
+ if (n) {
+ n[1].f = xfactor;
+ n[2].f = yfactor;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PixelZoom(ctx->Exec, (xfactor, yfactor));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PointParameterfvEXT(GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_PointParameterfvEXT(ctx->Exec, (pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PointParameterfEXT(GLenum pname, GLfloat param)
+{
+ GLfloat parray[3];
+ parray[0] = param;
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
+}
+
+static void GLAPIENTRY
+save_PointParameteriNV(GLenum pname, GLint param)
+{
+ GLfloat parray[3];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
+}
+
+static void GLAPIENTRY
+save_PointParameterivNV(GLenum pname, const GLint * param)
+{
+ GLfloat parray[3];
+ parray[0] = (GLfloat) param[0];
+ parray[1] = parray[2] = 0.0F;
+ save_PointParameterfvEXT(pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_PointSize(GLfloat size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_POINT_SIZE, 1);
+ if (n) {
+ n[1].f = size;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PointSize(ctx->Exec, (size));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PolygonMode(GLenum face, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_POLYGON_MODE, 2);
+ if (n) {
+ n[1].e = face;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PolygonMode(ctx->Exec, (face, mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PolygonStipple(const GLubyte * pattern)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_POLYGON_STIPPLE, 1);
+ if (n) {
+ n[1].data = unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP,
+ pattern, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PolygonStipple(ctx->Exec, ((GLubyte *) pattern));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PolygonOffset(GLfloat factor, GLfloat units)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_POLYGON_OFFSET, 2);
+ if (n) {
+ n[1].f = factor;
+ n[2].f = units;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PolygonOffset(ctx->Exec, (factor, units));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PolygonOffsetEXT(GLfloat factor, GLfloat bias)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* XXX mult by DepthMaxF here??? */
+ save_PolygonOffset(factor, ctx->DrawBuffer->_DepthMaxF * bias);
+}
+
+
+static void GLAPIENTRY
+save_PopAttrib(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_POP_ATTRIB, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_PopAttrib(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_PopMatrix(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_POP_MATRIX, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_PopMatrix(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_PopName(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_POP_NAME, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_PopName(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_PrioritizeTextures(GLsizei num, const GLuint * textures,
+ const GLclampf * priorities)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ 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) {
+ CALL_PrioritizeTextures(ctx->Exec, (num, textures, priorities));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PushAttrib(GLbitfield mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PUSH_ATTRIB, 1);
+ if (n) {
+ n[1].bf = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PushAttrib(ctx->Exec, (mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_PushMatrix(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_PUSH_MATRIX, 0);
+ if (ctx->ExecuteFlag) {
+ CALL_PushMatrix(ctx->Exec, ());
+ }
+}
+
+
+static void GLAPIENTRY
+save_PushName(GLuint name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PUSH_NAME, 1);
+ if (n) {
+ n[1].ui = name;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PushName(ctx->Exec, (name));
+ }
+}
+
+
+static void GLAPIENTRY
+save_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_RasterPos4f(ctx->Exec, (x, y, z, w));
+ }
+}
+
+static void GLAPIENTRY
+save_RasterPos2d(GLdouble x, GLdouble y)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2f(GLfloat x, GLfloat y)
+{
+ save_RasterPos4f(x, y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2i(GLint x, GLint y)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2s(GLshort x, GLshort y)
+{
+ save_RasterPos4f(x, y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_RasterPos4f(x, y, z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3i(GLint x, GLint y, GLint z)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3s(GLshort x, GLshort y, GLshort z)
+{
+ save_RasterPos4f(x, y, z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+save_RasterPos4i(GLint x, GLint y, GLint z, GLint w)
+{
+ save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+save_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ save_RasterPos4f(x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_RasterPos2dv(const GLdouble * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2fv(const GLfloat * v)
+{
+ save_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2iv(const GLint * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos2sv(const GLshort * v)
+{
+ save_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3dv(const GLdouble * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3fv(const GLfloat * v)
+{
+ save_RasterPos4f(v[0], v[1], v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3iv(const GLint * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos3sv(const GLshort * v)
+{
+ save_RasterPos4f(v[0], v[1], v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_RasterPos4dv(const GLdouble * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+save_RasterPos4fv(const GLfloat * v)
+{
+ save_RasterPos4f(v[0], v[1], v[2], v[3]);
+}
+
+static void GLAPIENTRY
+save_RasterPos4iv(const GLint * v)
+{
+ save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+save_RasterPos4sv(const GLshort * v)
+{
+ save_RasterPos4f(v[0], v[1], v[2], v[3]);
+}
+
+
+static void GLAPIENTRY
+save_PassThrough(GLfloat token)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PASSTHROUGH, 1);
+ if (n) {
+ n[1].f = token;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_PassThrough(ctx->Exec, (token));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ReadBuffer(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_READ_BUFFER, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ReadBuffer(ctx->Exec, (mode));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ResetHistogram(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_RESET_HISTOGRAM, 1);
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ResetHistogram(ctx->Exec, (target));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ResetMinmax(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_RESET_MIN_MAX, 1);
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ResetMinmax(ctx->Exec, (target));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ROTATE, 4);
+ if (n) {
+ n[1].f = angle;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Rotatef(ctx->Exec, (angle, x, y, z));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
+{
+ save_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+
+static void GLAPIENTRY
+save_Scalef(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_SCALE, 3);
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Scalef(ctx->Exec, (x, y, z));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Scaled(GLdouble x, GLdouble y, GLdouble z)
+{
+ save_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+
+static void GLAPIENTRY
+save_Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_Scissor(ctx->Exec, (x, y, width, height));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ShadeModel(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);
+
+ if (ctx->ExecuteFlag) {
+ CALL_ShadeModel(ctx->Exec, (mode));
+ }
+
+ if (ctx->ListState.Current.ShadeModel == mode)
+ return;
+
+ SAVE_FLUSH_VERTICES(ctx);
+
+ /* Only save the value if we know the statechange will take effect:
+ */
+ if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
+ ctx->ListState.Current.ShadeModel = mode;
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_SHADE_MODEL, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_StencilFunc(ctx->Exec, (func, ref, mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilMask(GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_MASK, 1);
+ if (n) {
+ n[1].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_StencilMask(ctx->Exec, (mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_StencilOp(ctx->Exec, (fail, zfail, zpass));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
+ if (n) {
+ n[1].e = face;
+ n[2].e = func;
+ n[3].i = ref;
+ n[4].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_StencilFuncSeparate(ctx->Exec, (face, func, ref, mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, GLint ref,
+ GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ /* GL_FRONT */
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
+ if (n) {
+ n[1].e = GL_FRONT;
+ n[2].e = frontfunc;
+ n[3].i = ref;
+ n[4].ui = mask;
+ }
+ /* GL_BACK */
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
+ if (n) {
+ n[1].e = GL_BACK;
+ n[2].e = backfunc;
+ n[3].i = ref;
+ n[4].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_StencilFuncSeparate(ctx->Exec, (GL_FRONT, frontfunc, ref, mask));
+ CALL_StencilFuncSeparate(ctx->Exec, (GL_BACK, backfunc, ref, mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilMaskSeparate(GLenum face, GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_MASK_SEPARATE, 2);
+ if (n) {
+ n[1].e = face;
+ n[2].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_StencilMaskSeparate(ctx->Exec, (face, mask));
+ }
+}
+
+
+static void GLAPIENTRY
+save_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_OP_SEPARATE, 4);
+ if (n) {
+ n[1].e = face;
+ n[2].e = fail;
+ n[3].e = zfail;
+ n[4].e = zpass;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_StencilOpSeparate(ctx->Exec, (face, fail, zfail, zpass));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TEXENV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ else {
+ n[3].f = params[0];
+ n[4].f = n[5].f = n[6].f = 0.0F;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexEnvfv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexEnvf(GLenum target, GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexEnvfv(target, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_TexEnvi(GLenum target, GLenum pname, GLint param)
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) param;
+ p[1] = p[2] = p[3] = 0.0;
+ save_TexEnvfv(target, pname, p);
+}
+
+
+static void GLAPIENTRY
+save_TexEnviv(GLenum target, GLenum pname, const GLint * param)
+{
+ GLfloat p[4];
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ p[0] = INT_TO_FLOAT(param[0]);
+ p[1] = INT_TO_FLOAT(param[1]);
+ p[2] = INT_TO_FLOAT(param[2]);
+ p[3] = INT_TO_FLOAT(param[3]);
+ }
+ else {
+ p[0] = (GLfloat) param[0];
+ p[1] = p[2] = p[3] = 0.0F;
+ }
+ save_TexEnvfv(target, pname, p);
+}
+
+
+static void GLAPIENTRY
+save_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_TexGenfv(ctx->Exec, (coord, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexGeniv(GLenum coord, GLenum pname, const GLint *params)
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) params[0];
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ save_TexGenfv(coord, pname, p);
+}
+
+
+static void GLAPIENTRY
+save_TexGend(GLenum coord, GLenum pname, GLdouble param)
+{
+ GLfloat parray[4];
+ parray[0] = (GLfloat) param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexGenfv(coord, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_TexGendv(GLenum coord, GLenum pname, const GLdouble *params)
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) params[0];
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ save_TexGenfv(coord, pname, p);
+}
+
+
+static void GLAPIENTRY
+save_TexGenf(GLenum coord, GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexGenfv(coord, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_TexGeni(GLenum coord, GLenum pname, GLint param)
+{
+ GLint parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0;
+ save_TexGeniv(coord, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_TexParameterfv(ctx->Exec, (target, pname, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ GLfloat parray[4];
+ parray[0] = param;
+ parray[1] = parray[2] = parray[3] = 0.0F;
+ save_TexParameterfv(target, pname, parray);
+}
+
+
+static void GLAPIENTRY
+save_TexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ GLfloat fparam[4];
+ fparam[0] = (GLfloat) param;
+ fparam[1] = fparam[2] = fparam[3] = 0.0;
+ save_TexParameterfv(target, pname, fparam);
+}
+
+
+static void GLAPIENTRY
+save_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GLfloat fparam[4];
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = fparam[2] = fparam[3] = 0.0;
+ save_TexParameterfv(target, pname, fparam);
+}
+
+
+static void GLAPIENTRY
+save_TexImage1D(GLenum target,
+ GLint level, GLint components,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_1D) {
+ /* don't compile, execute immediately */
+ CALL_TexImage1D(ctx->Exec, (target, level, components, width,
+ border, format, type, pixels));
+ }
+ else {
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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 = unpack_image(ctx, 1, width, 1, 1, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexImage1D(ctx->Exec, (target, level, components, width,
+ border, format, type, pixels));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexImage2D(GLenum target,
+ GLint level, GLint components,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_2D) {
+ /* don't compile, execute immediately */
+ CALL_TexImage2D(ctx->Exec, (target, level, components, width,
+ height, border, format, type, pixels));
+ }
+ else {
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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 = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexImage2D(ctx->Exec, (target, level, components, width,
+ height, border, format, type, pixels));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexImage3D(GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_3D) {
+ /* don't compile, execute immediately */
+ CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width,
+ height, depth, border, format, type,
+ pixels));
+ }
+ else {
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_IMAGE3D, 10);
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = (GLint) internalFormat;
+ 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 = unpack_image(ctx, 3, width, height, depth, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width,
+ height, depth, border, format, type,
+ pixels));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexSubImage1D(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ 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 = unpack_image(ctx, 1, width, 1, 1, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexSubImage1D(ctx->Exec, (target, level, xoffset, width,
+ format, type, pixels));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexSubImage2D(GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ 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 = unpack_image(ctx, 2, width, height, 1, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
+ width, height, format, type, pixels));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TexSubImage3D(GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ 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 = unpack_image(ctx, 3, width, height, depth, format, type,
+ pixels, &ctx->Unpack);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexSubImage3D(ctx->Exec, (target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth, format, type,
+ pixels));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Translatef(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TRANSLATE, 3);
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Translatef(ctx->Exec, (x, y, z));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Translated(GLdouble x, GLdouble y, GLdouble z)
+{
+ save_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+
+
+static void GLAPIENTRY
+save_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_Viewport(ctx->Exec, (x, y, width, height));
+ }
+}
+
+
+static void GLAPIENTRY
+save_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ 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) {
+ CALL_WindowPos4fMESA(ctx->Exec, (x, y, z, w));
+ }
+}
+
+static void GLAPIENTRY
+save_WindowPos2dMESA(GLdouble x, GLdouble y)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2fMESA(GLfloat x, GLfloat y)
+{
+ save_WindowPos4fMESA(x, y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2iMESA(GLint x, GLint y)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2sMESA(GLshort x, GLshort y)
+{
+ save_WindowPos4fMESA(x, y, 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_WindowPos4fMESA(x, y, z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3iMESA(GLint x, GLint y, GLint z)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3sMESA(GLshort x, GLshort y, GLshort z)
+{
+ save_WindowPos4fMESA(x, y, z, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+save_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w)
+{
+ save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+static void GLAPIENTRY
+save_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ save_WindowPos4fMESA(x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_WindowPos2dvMESA(const GLdouble * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2fvMESA(const GLfloat * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2ivMESA(const GLint * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos2svMESA(const GLshort * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3dvMESA(const GLdouble * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3fvMESA(const GLfloat * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3ivMESA(const GLint * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos3svMESA(const GLshort * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F);
+}
+
+static void GLAPIENTRY
+save_WindowPos4dvMESA(const GLdouble * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+save_WindowPos4fvMESA(const GLfloat * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], v[2], v[3]);
+}
+
+static void GLAPIENTRY
+save_WindowPos4ivMESA(const GLint * v)
+{
+ save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+static void GLAPIENTRY
+save_WindowPos4svMESA(const GLshort * v)
+{
+ save_WindowPos4fMESA(v[0], v[1], v[2], v[3]);
+}
+
+
+
+/* GL_ARB_multitexture */
+static void GLAPIENTRY
+save_ActiveTextureARB(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ACTIVE_TEXTURE, 1);
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ActiveTextureARB(ctx->Exec, (target));
+ }
+}
+
+
+/* GL_ARB_transpose_matrix */
+
+static void GLAPIENTRY
+save_LoadTransposeMatrixdARB(const GLdouble m[16])
+{
+ GLfloat tm[16];
+ _math_transposefd(tm, m);
+ save_LoadMatrixf(tm);
+}
+
+
+static void GLAPIENTRY
+save_LoadTransposeMatrixfARB(const GLfloat m[16])
+{
+ GLfloat tm[16];
+ _math_transposef(tm, m);
+ save_LoadMatrixf(tm);
+}
+
+
+static void GLAPIENTRY
+save_MultTransposeMatrixdARB(const GLdouble m[16])
+{
+ GLfloat tm[16];
+ _math_transposefd(tm, m);
+ save_MultMatrixf(tm);
+}
+
+
+static void GLAPIENTRY
+save_MultTransposeMatrixfARB(const GLfloat m[16])
+{
+ GLfloat tm[16];
+ _math_transposef(tm, m);
+ save_MultMatrixf(tm);
+}
+
+
+/* GL_ARB_texture_compression */
+static void GLAPIENTRY
+save_CompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_1D) {
+ /* don't compile, execute immediately */
+ CALL_CompressedTexImage1DARB(ctx->Exec, (target, level, internalFormat,
+ width, border, imageSize,
+ data));
+ }
+ else {
+ Node *n;
+ GLvoid *image;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, 7);
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].e = internalFormat;
+ n[4].i = (GLint) width;
+ n[5].i = border;
+ n[6].i = imageSize;
+ n[7].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexImage1DARB(ctx->Exec,
+ (target, level, internalFormat, width,
+ border, imageSize, data));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_CompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_2D) {
+ /* don't compile, execute immediately */
+ CALL_CompressedTexImage2DARB(ctx->Exec, (target, level, internalFormat,
+ width, height, border,
+ imageSize, data));
+ }
+ else {
+ Node *n;
+ GLvoid *image;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, 8);
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].e = internalFormat;
+ n[4].i = (GLint) width;
+ n[5].i = (GLint) height;
+ n[6].i = border;
+ n[7].i = imageSize;
+ n[8].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexImage2DARB(ctx->Exec,
+ (target, level, internalFormat, width,
+ height, border, imageSize, data));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_CompressedTexImage3DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (target == GL_PROXY_TEXTURE_3D) {
+ /* don't compile, execute immediately */
+ CALL_CompressedTexImage3DARB(ctx->Exec, (target, level, internalFormat,
+ width, height, depth, border,
+ imageSize, data));
+ }
+ else {
+ Node *n;
+ GLvoid *image;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, 9);
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].e = internalFormat;
+ n[4].i = (GLint) width;
+ n[5].i = (GLint) height;
+ n[6].i = (GLint) depth;
+ n[7].i = border;
+ n[8].i = imageSize;
+ n[9].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexImage3DARB(ctx->Exec,
+ (target, level, internalFormat, width,
+ height, depth, border, imageSize,
+ data));
+ }
+ }
+}
+
+
+static void GLAPIENTRY
+save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid * data)
+{
+ Node *n;
+ GLvoid *image;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage1DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, 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].i = imageSize;
+ n[7].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexSubImage1DARB(ctx->Exec, (target, level, xoffset,
+ width, format, imageSize,
+ data));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid * data)
+{
+ Node *n;
+ GLvoid *image;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, 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].i = imageSize;
+ n[9].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexSubImage2DARB(ctx->Exec,
+ (target, level, xoffset, yoffset, width,
+ height, format, imageSize, data));
+ }
+}
+
+
+static void GLAPIENTRY
+save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum format,
+ GLsizei imageSize, const GLvoid * data)
+{
+ Node *n;
+ GLvoid *image;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* make copy of image */
+ image = _mesa_malloc(imageSize);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3DARB");
+ return;
+ }
+ MEMCPY(image, data, imageSize);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, 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].i = imageSize;
+ n[11].data = image;
+ }
+ else if (image) {
+ _mesa_free(image);
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_CompressedTexSubImage3DARB(ctx->Exec,
+ (target, level, xoffset, yoffset,
+ zoffset, width, height, depth, format,
+ imageSize, data));
+ }
+}
+
+
+/* GL_ARB_multisample */
+static void GLAPIENTRY
+save_SampleCoverageARB(GLclampf value, GLboolean invert)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_SAMPLE_COVERAGE, 2);
+ if (n) {
+ n[1].f = value;
+ n[2].b = invert;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_SampleCoverageARB(ctx->Exec, (value, invert));
+ }
+}
+
+
+/*
+ * GL_NV_vertex_program
+ */
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+static void GLAPIENTRY
+save_BindProgramNV(GLenum target, GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BIND_PROGRAM_NV, 2);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = id;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BindProgramNV(ctx->Exec, (target, id));
+ }
+}
+
+static void GLAPIENTRY
+save_ProgramEnvParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = x;
+ n[4].f = y;
+ n[5].f = z;
+ n[6].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramEnvParameter4fARB(ctx->Exec, (target, index, x, y, z, w));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
+{
+ save_ProgramEnvParameter4fARB(target, index, params[0], params[1],
+ params[2], params[3]);
+}
+
+
+static void GLAPIENTRY
+save_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat * params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (count > 0) {
+ GLint i;
+ const GLfloat * p = params;
+
+ for (i = 0 ; i < count ; i++) {
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = p[0];
+ n[4].f = p[1];
+ n[5].f = p[2];
+ n[6].f = p[3];
+ p += 4;
+ }
+ }
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramEnvParameters4fvEXT(ctx->Exec, (target, index, count, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramEnvParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ save_ProgramEnvParameter4fARB(target, index,
+ (GLfloat) x,
+ (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+
+static void GLAPIENTRY
+save_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
+{
+ save_ProgramEnvParameter4fARB(target, index,
+ (GLfloat) params[0],
+ (GLfloat) params[1],
+ (GLfloat) params[2], (GLfloat) params[3]);
+}
+
+#endif /* FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program || FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_vertex_program
+static void GLAPIENTRY
+save_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EXECUTE_PROGRAM_NV, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = id;
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ExecuteProgramNV(ctx->Exec, (target, id, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramParameters4dvNV(GLenum target, GLuint index,
+ GLuint num, const GLdouble *params)
+{
+ GLuint i;
+ for (i = 0; i < num; i++) {
+ save_ProgramEnvParameter4dvARB(target, index + i, params + 4 * i);
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramParameters4fvNV(GLenum target, GLuint index,
+ GLuint num, const GLfloat *params)
+{
+ GLuint i;
+ for (i = 0; i < num; i++) {
+ save_ProgramEnvParameter4fvARB(target, index + i, params + 4 * i);
+ }
+}
+
+
+static void GLAPIENTRY
+save_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
+ const GLubyte * program)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_LOAD_PROGRAM_NV, 4);
+ if (n) {
+ GLubyte *programCopy = (GLubyte *) _mesa_malloc(len);
+ if (!programCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ _mesa_memcpy(programCopy, program, len);
+ n[1].e = target;
+ n[2].ui = id;
+ n[3].i = len;
+ n[4].data = programCopy;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_LoadProgramNV(ctx->Exec, (target, id, len, program));
+ }
+}
+
+
+static void GLAPIENTRY
+save_RequestResidentProgramsNV(GLsizei num, const GLuint * ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TRACK_MATRIX_NV, 2);
+ if (n) {
+ GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint));
+ if (!idCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV");
+ return;
+ }
+ _mesa_memcpy(idCopy, ids, num * sizeof(GLuint));
+ n[1].i = num;
+ n[2].data = idCopy;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_RequestResidentProgramsNV(ctx->Exec, (num, ids));
+ }
+}
+
+
+static void GLAPIENTRY
+save_TrackMatrixNV(GLenum target, GLuint address,
+ GLenum matrix, GLenum transform)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TRACK_MATRIX_NV, 4);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = address;
+ n[3].e = matrix;
+ n[4].e = transform;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TrackMatrixNV(ctx->Exec, (target, address, matrix, transform));
+ }
+}
+#endif /* FEATURE_NV_vertex_program */
+
+
+/*
+ * GL_NV_fragment_program
+ */
+#if FEATURE_NV_fragment_program
+static void GLAPIENTRY
+save_ProgramLocalParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = x;
+ n[4].f = y;
+ n[5].f = z;
+ n[6].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramLocalParameter4fARB(ctx->Exec, (target, index, x, y, z, w));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramLocalParameter4fvARB(ctx->Exec, (target, index, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (count > 0) {
+ GLint i;
+ const GLfloat * p = params;
+
+ for (i = 0 ; i < count ; i++) {
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = p[0];
+ n[4].f = p[1];
+ n[5].f = p[2];
+ n[6].f = p[3];
+ p += 4;
+ }
+ }
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramLocalParameters4fvEXT(ctx->Exec, (target, index, count, params));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramLocalParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y,
+ GLdouble z, GLdouble w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = (GLfloat) x;
+ n[4].f = (GLfloat) y;
+ n[5].f = (GLfloat) z;
+ n[6].f = (GLfloat) w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramLocalParameter4dARB(ctx->Exec, (target, index, x, y, z, w));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = index;
+ n[3].f = (GLfloat) params[0];
+ n[4].f = (GLfloat) params[1];
+ n[5].f = (GLfloat) params[2];
+ n[6].f = (GLfloat) params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramLocalParameter4dvARB(ctx->Exec, (target, index, params));
+ }
+}
+
+static void GLAPIENTRY
+save_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte * name,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_NAMED_PARAMETER_NV, 6);
+ if (n) {
+ GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len);
+ if (!nameCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV");
+ return;
+ }
+ _mesa_memcpy(nameCopy, name, len);
+ n[1].ui = id;
+ n[2].i = len;
+ n[3].data = nameCopy;
+ n[4].f = x;
+ n[5].f = y;
+ n[6].f = z;
+ n[7].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramNamedParameter4fNV(ctx->Exec, (id, len, name, x, y, z, w));
+ }
+}
+
+
+static void GLAPIENTRY
+save_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte * name,
+ const float v[])
+{
+ save_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
+}
+
+
+static void GLAPIENTRY
+save_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte * name,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ save_ProgramNamedParameter4fNV(id, len, name, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
+}
+
+
+static void GLAPIENTRY
+save_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte * name,
+ const double v[])
+{
+ save_ProgramNamedParameter4fNV(id, len, name, (GLfloat) v[0],
+ (GLfloat) v[1], (GLfloat) v[2],
+ (GLfloat) v[3]);
+}
+
+#endif /* FEATURE_NV_fragment_program */
+
+
+
+/* GL_EXT_stencil_two_side */
+static void GLAPIENTRY
+save_ActiveStencilFaceEXT(GLenum face)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ACTIVE_STENCIL_FACE_EXT, 1);
+ if (n) {
+ n[1].e = face;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ActiveStencilFaceEXT(ctx->Exec, (face));
+ }
+}
+
+
+/* GL_EXT_depth_bounds_test */
+static void GLAPIENTRY
+save_DepthBoundsEXT(GLclampd zmin, GLclampd zmax)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DEPTH_BOUNDS_EXT, 2);
+ if (n) {
+ n[1].f = (GLfloat) zmin;
+ n[2].f = (GLfloat) zmax;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DepthBoundsEXT(ctx->Exec, (zmin, zmax));
+ }
+}
+
+
+
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+
+static void GLAPIENTRY
+save_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
+ const GLvoid * string)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROGRAM_STRING_ARB, 4);
+ if (n) {
+ GLubyte *programCopy = (GLubyte *) _mesa_malloc(len);
+ if (!programCopy) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return;
+ }
+ _mesa_memcpy(programCopy, string, len);
+ n[1].e = target;
+ n[2].e = format;
+ n[3].i = len;
+ n[4].data = programCopy;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_ProgramStringARB(ctx->Exec, (target, format, len, string));
+ }
+}
+
+#endif /* FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program */
+
+
+#if FEATURE_ARB_occlusion_query
+
+static void GLAPIENTRY
+save_BeginQueryARB(GLenum target, GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BEGIN_QUERY_ARB, 2);
+ if (n) {
+ n[1].e = target;
+ n[2].ui = id;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BeginQueryARB(ctx->Exec, (target, id));
+ }
+}
+
+
+static void GLAPIENTRY
+save_EndQueryARB(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_END_QUERY_ARB, 1);
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EndQueryARB(ctx->Exec, (target));
+ }
+}
+
+#endif /* FEATURE_ARB_occlusion_query */
+
+
+static void GLAPIENTRY
+save_DrawBuffersARB(GLsizei count, const GLenum * buffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_DRAW_BUFFERS_ARB, 1 + MAX_DRAW_BUFFERS);
+ if (n) {
+ GLint i;
+ n[1].i = count;
+ if (count > MAX_DRAW_BUFFERS)
+ count = MAX_DRAW_BUFFERS;
+ for (i = 0; i < count; i++) {
+ n[2 + i].e = buffers[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_DrawBuffersARB(ctx->Exec, (count, buffers));
+ }
+}
+
+static void GLAPIENTRY
+save_TexBumpParameterfvATI(GLenum pname, const GLfloat *param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_BUMP_PARAMETER_ATI, 5);
+ if (n) {
+ n[1].ui = pname;
+ n[2].f = param[0];
+ n[3].f = param[1];
+ n[4].f = param[2];
+ n[5].f = param[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_TexBumpParameterfvATI(ctx->Exec, (pname, param));
+ }
+}
+
+static void GLAPIENTRY
+save_TexBumpParameterivATI(GLenum pname, const GLint *param)
+{
+ GLfloat p[4];
+ p[0] = INT_TO_FLOAT(param[0]);
+ p[1] = INT_TO_FLOAT(param[1]);
+ p[2] = INT_TO_FLOAT(param[2]);
+ p[3] = INT_TO_FLOAT(param[3]);
+ save_TexBumpParameterfvATI(pname, p);
+}
+
+#if FEATURE_ATI_fragment_shader
+static void GLAPIENTRY
+save_BindFragmentShaderATI(GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BIND_FRAGMENT_SHADER_ATI, 1);
+ if (n) {
+ n[1].ui = id;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BindFragmentShaderATI(ctx->Exec, (id));
+ }
+}
+
+static void GLAPIENTRY
+save_SetFragmentShaderConstantATI(GLuint dst, const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI, 5);
+ if (n) {
+ n[1].ui = dst;
+ n[2].f = value[0];
+ n[3].f = value[1];
+ n[4].f = value[2];
+ n[5].f = value[3];
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_SetFragmentShaderConstantATI(ctx->Exec, (dst, value));
+ }
+}
+#endif
+
+static void
+save_Attr1fNV(GLenum attr, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_1F_NV, 2);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 1;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib1fNV(ctx->Exec, (attr, x));
+ }
+}
+
+static void
+save_Attr2fNV(GLenum attr, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_2F_NV, 3);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 2;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib2fNV(ctx->Exec, (attr, x, y));
+ }
+}
+
+static void
+save_Attr3fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_3F_NV, 4);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 3;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib3fNV(ctx->Exec, (attr, x, y, z));
+ }
+}
+
+static void
+save_Attr4fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_4F_NV, 5);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ n[5].f = w;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 4;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib4fNV(ctx->Exec, (attr, x, y, z, w));
+ }
+}
+
+
+static void
+save_Attr1fARB(GLenum attr, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_1F_ARB, 2);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 1;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib1fARB(ctx->Exec, (attr, x));
+ }
+}
+
+static void
+save_Attr2fARB(GLenum attr, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_2F_ARB, 3);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 2;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib2fARB(ctx->Exec, (attr, x, y));
+ }
+}
+
+static void
+save_Attr3fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_3F_ARB, 4);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 3;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib3fARB(ctx->Exec, (attr, x, y, z));
+ }
+}
+
+static void
+save_Attr4fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_ATTR_4F_ARB, 5);
+ if (n) {
+ n[1].e = attr;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ n[5].f = w;
+ }
+
+ ASSERT(attr < MAX_VERTEX_GENERIC_ATTRIBS);
+ ctx->ListState.ActiveAttribSize[attr] = 4;
+ ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
+
+ if (ctx->ExecuteFlag) {
+ CALL_VertexAttrib4fARB(ctx->Exec, (attr, x, y, z, w));
+ }
+}
+
+
+static void GLAPIENTRY
+save_EvalCoord1f(GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EVAL_C1, 1);
+ if (n) {
+ n[1].f = x;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EvalCoord1f(ctx->Exec, (x));
+ }
+}
+
+static void GLAPIENTRY
+save_EvalCoord1fv(const GLfloat * v)
+{
+ save_EvalCoord1f(v[0]);
+}
+
+static void GLAPIENTRY
+save_EvalCoord2f(GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EVAL_C2, 2);
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EvalCoord2f(ctx->Exec, (x, y));
+ }
+}
+
+static void GLAPIENTRY
+save_EvalCoord2fv(const GLfloat * v)
+{
+ save_EvalCoord2f(v[0], v[1]);
+}
+
+
+static void GLAPIENTRY
+save_EvalPoint1(GLint x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EVAL_P1, 1);
+ if (n) {
+ n[1].i = x;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EvalPoint1(ctx->Exec, (x));
+ }
+}
+
+static void GLAPIENTRY
+save_EvalPoint2(GLint x, GLint y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_EVAL_P2, 2);
+ if (n) {
+ n[1].i = x;
+ n[2].i = y;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_EvalPoint2(ctx->Exec, (x, y));
+ }
+}
+
+static void GLAPIENTRY
+save_Indexf(GLfloat x)
+{
+ save_Attr1fNV(VERT_ATTRIB_COLOR_INDEX, x);
+}
+
+static void GLAPIENTRY
+save_Indexfv(const GLfloat * v)
+{
+ save_Attr1fNV(VERT_ATTRIB_COLOR_INDEX, v[0]);
+}
+
+static void GLAPIENTRY
+save_EdgeFlag(GLboolean x)
+{
+ save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? (GLfloat)1.0 : (GLfloat)0.0);
+}
+
+static INLINE GLboolean compare4fv( const GLfloat *a,
+ const GLfloat *b,
+ GLuint count )
+{
+ return memcmp( a, b, count * sizeof(GLfloat) ) == 0;
+}
+
+
+static void GLAPIENTRY
+save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ int args, i;
+ GLuint bitmask;
+
+ switch (face) {
+ case GL_BACK:
+ case GL_FRONT:
+ case GL_FRONT_AND_BACK:
+ break;
+ default:
+ _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(face)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_EMISSION:
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ case GL_AMBIENT_AND_DIFFUSE:
+ args = 4;
+ break;
+ case GL_SHININESS:
+ args = 1;
+ break;
+ case GL_COLOR_INDEXES:
+ args = 3;
+ break;
+ default:
+ _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)");
+ return;
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_Materialfv(ctx->Exec, (face, pname, param));
+ }
+
+ bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
+
+ /* Try to eliminate redundant statechanges. Because it is legal to
+ * call glMaterial even inside begin/end calls, don't need to worry
+ * about ctx->Driver.CurrentSavePrimitive here.
+ */
+ for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+ if (bitmask & (1 << i)) {
+ if (ctx->ListState.ActiveMaterialSize[i] == args &&
+ compare4fv(ctx->ListState.CurrentMaterial[i], param, args)) {
+ bitmask &= ~(1 << i);
+ }
+ else {
+ ctx->ListState.ActiveMaterialSize[i] = args;
+ COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param);
+ }
+ }
+ }
+
+ /* If this call has effect, return early:
+ */
+ if (bitmask == 0)
+ return;
+
+ SAVE_FLUSH_VERTICES(ctx);
+
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6);
+ if (n) {
+ n[1].e = face;
+ n[2].e = pname;
+ for (i = 0; i < args; i++)
+ n[3 + i].f = param[i];
+ }
+}
+
+static void GLAPIENTRY
+save_Begin(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ GLboolean error = GL_FALSE;
+
+ if ( /*mode < GL_POINTS || */ mode > GL_POLYGON) {
+ _mesa_compile_error(ctx, GL_INVALID_ENUM, "Begin (mode)");
+ error = GL_TRUE;
+ }
+ else if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN) {
+ /* Typically the first begin. This may raise an error on
+ * playback, depending on whether CallList is issued from inside
+ * a begin/end or not.
+ */
+ ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
+ }
+ else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END) {
+ ctx->Driver.CurrentSavePrimitive = mode;
+ }
+ else {
+ _mesa_compile_error(ctx, GL_INVALID_OPERATION, "recursive begin");
+ error = GL_TRUE;
+ }
+
+ if (!error) {
+ /* Give the driver an opportunity to hook in an optimized
+ * display list compiler.
+ */
+ if (ctx->Driver.NotifySaveBegin(ctx, mode))
+ return;
+
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BEGIN, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ }
+
+ if (ctx->ExecuteFlag) {
+ CALL_Begin(ctx->Exec, (mode));
+ }
+}
+
+static void GLAPIENTRY
+save_End(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ SAVE_FLUSH_VERTICES(ctx);
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_END, 0);
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ if (ctx->ExecuteFlag) {
+ CALL_End(ctx->Exec, ());
+ }
+}
+
+static void GLAPIENTRY
+save_Rectf(GLfloat a, GLfloat b, GLfloat c, GLfloat d)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ SAVE_FLUSH_VERTICES(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_RECTF, 4);
+ if (n) {
+ n[1].f = a;
+ n[2].f = b;
+ n[3].f = c;
+ n[4].f = d;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Rectf(ctx->Exec, (a, b, c, d));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Vertex2f(GLfloat x, GLfloat y)
+{
+ save_Attr2fNV(VERT_ATTRIB_POS, x, y);
+}
+
+static void GLAPIENTRY
+save_Vertex2fv(const GLfloat * v)
+{
+ save_Attr2fNV(VERT_ATTRIB_POS, v[0], v[1]);
+}
+
+static void GLAPIENTRY
+save_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_Attr3fNV(VERT_ATTRIB_POS, x, y, z);
+}
+
+static void GLAPIENTRY
+save_Vertex3fv(const GLfloat * v)
+{
+ save_Attr3fNV(VERT_ATTRIB_POS, v[0], v[1], v[2]);
+}
+
+static void GLAPIENTRY
+save_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ save_Attr4fNV(VERT_ATTRIB_POS, x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_Vertex4fv(const GLfloat * v)
+{
+ save_Attr4fNV(VERT_ATTRIB_POS, v[0], v[1], v[2], v[3]);
+}
+
+static void GLAPIENTRY
+save_TexCoord1f(GLfloat x)
+{
+ save_Attr1fNV(VERT_ATTRIB_TEX0, x);
+}
+
+static void GLAPIENTRY
+save_TexCoord1fv(const GLfloat * v)
+{
+ save_Attr1fNV(VERT_ATTRIB_TEX0, v[0]);
+}
+
+static void GLAPIENTRY
+save_TexCoord2f(GLfloat x, GLfloat y)
+{
+ save_Attr2fNV(VERT_ATTRIB_TEX0, x, y);
+}
+
+static void GLAPIENTRY
+save_TexCoord2fv(const GLfloat * v)
+{
+ save_Attr2fNV(VERT_ATTRIB_TEX0, v[0], v[1]);
+}
+
+static void GLAPIENTRY
+save_TexCoord3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_Attr3fNV(VERT_ATTRIB_TEX0, x, y, z);
+}
+
+static void GLAPIENTRY
+save_TexCoord3fv(const GLfloat * v)
+{
+ save_Attr3fNV(VERT_ATTRIB_TEX0, v[0], v[1], v[2]);
+}
+
+static void GLAPIENTRY
+save_TexCoord4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ save_Attr4fNV(VERT_ATTRIB_TEX0, x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_TexCoord4fv(const GLfloat * v)
+{
+ save_Attr4fNV(VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3]);
+}
+
+static void GLAPIENTRY
+save_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_Attr3fNV(VERT_ATTRIB_NORMAL, x, y, z);
+}
+
+static void GLAPIENTRY
+save_Normal3fv(const GLfloat * v)
+{
+ save_Attr3fNV(VERT_ATTRIB_NORMAL, v[0], v[1], v[2]);
+}
+
+static void GLAPIENTRY
+save_FogCoordfEXT(GLfloat x)
+{
+ save_Attr1fNV(VERT_ATTRIB_FOG, x);
+}
+
+static void GLAPIENTRY
+save_FogCoordfvEXT(const GLfloat * v)
+{
+ save_Attr1fNV(VERT_ATTRIB_FOG, v[0]);
+}
+
+static void GLAPIENTRY
+save_Color3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_Attr3fNV(VERT_ATTRIB_COLOR0, x, y, z);
+}
+
+static void GLAPIENTRY
+save_Color3fv(const GLfloat * v)
+{
+ save_Attr3fNV(VERT_ATTRIB_COLOR0, v[0], v[1], v[2]);
+}
+
+static void GLAPIENTRY
+save_Color4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ save_Attr4fNV(VERT_ATTRIB_COLOR0, x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_Color4fv(const GLfloat * v)
+{
+ save_Attr4fNV(VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3]);
+}
+
+static void GLAPIENTRY
+save_SecondaryColor3fEXT(GLfloat x, GLfloat y, GLfloat z)
+{
+ save_Attr3fNV(VERT_ATTRIB_COLOR1, x, y, z);
+}
+
+static void GLAPIENTRY
+save_SecondaryColor3fvEXT(const GLfloat * v)
+{
+ save_Attr3fNV(VERT_ATTRIB_COLOR1, v[0], v[1], v[2]);
+}
+
+
+/* Just call the respective ATTR for texcoord
+ */
+static void GLAPIENTRY
+save_MultiTexCoord1f(GLenum target, GLfloat x)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr1fNV(attr, x);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord1fv(GLenum target, const GLfloat * v)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr1fNV(attr, v[0]);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord2f(GLenum target, GLfloat x, GLfloat y)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr2fNV(attr, x, y);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord2fv(GLenum target, const GLfloat * v)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr2fNV(attr, v[0], v[1]);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord3f(GLenum target, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr3fNV(attr, x, y, z);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord3fv(GLenum target, const GLfloat * v)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr3fNV(attr, v[0], v[1], v[2]);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord4f(GLenum target, GLfloat x, GLfloat y,
+ GLfloat z, GLfloat w)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr4fNV(attr, x, y, z, w);
+}
+
+static void GLAPIENTRY
+save_MultiTexCoord4fv(GLenum target, const GLfloat * v)
+{
+ GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
+ save_Attr4fNV(attr, v[0], v[1], v[2], v[3]);
+}
+
+
+/**
+ * Record a GL_INVALID_VALUE error when a invalid vertex attribute
+ * index is found.
+ */
+static void
+index_error(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_VALUE, "VertexAttribf(index)");
+}
+
+
+/* First level for NV_vertex_program:
+ *
+ * Check for errors at compile time?.
+ */
+static void GLAPIENTRY
+save_VertexAttrib1fNV(GLuint index, GLfloat x)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr1fNV(index, x);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib1fvNV(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr1fNV(index, v[0]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib2fNV(GLuint index, GLfloat x, GLfloat y)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr2fNV(index, x, y);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib2fvNV(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr2fNV(index, v[0], v[1]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib3fNV(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr3fNV(index, x, y, z);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib3fvNV(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr3fNV(index, v[0], v[1], v[2]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib4fNV(GLuint index, GLfloat x, GLfloat y,
+ GLfloat z, GLfloat w)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr4fNV(index, x, y, z, w);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib4fvNV(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_NV_VERTEX_PROGRAM_INPUTS)
+ save_Attr4fNV(index, v[0], v[1], v[2], v[3]);
+ else
+ index_error();
+}
+
+
+
+
+static void GLAPIENTRY
+save_VertexAttrib1fARB(GLuint index, GLfloat x)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr1fARB(index, x);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib1fvARB(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr1fARB(index, v[0]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr2fARB(index, x, y);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib2fvARB(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr2fARB(index, v[0], v[1]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr3fARB(index, x, y, z);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib3fvARB(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr3fARB(index, v[0], v[1], v[2]);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat w)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr4fARB(index, x, y, z, w);
+ else
+ index_error();
+}
+
+static void GLAPIENTRY
+save_VertexAttrib4fvARB(GLuint index, const GLfloat * v)
+{
+ if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ save_Attr4fARB(index, v[0], v[1], v[2], v[3]);
+ else
+ index_error();
+}
+
+
+/* GL_ARB_shader_objects, GL_ARB_vertex/fragment_shader */
+
+static void GLAPIENTRY
+exec_BindAttribLocationARB(GLuint program, GLuint index, const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_BindAttribLocationARB(ctx->Exec, (program, index, name));
+}
+
+static GLint GLAPIENTRY
+exec_GetAttribLocationARB(GLuint program, const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_GetAttribLocationARB(ctx->Exec, (program, name));
+}
+/* XXX more shader functions needed here */
+
+
+
+#if FEATURE_EXT_framebuffer_blit
+static void GLAPIENTRY
+save_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_BLIT_FRAMEBUFFER, 10);
+ if (n) {
+ n[1].i = srcX0;
+ n[2].i = srcY0;
+ n[3].i = srcX1;
+ n[4].i = srcY1;
+ n[5].i = dstX0;
+ n[6].i = dstY0;
+ n[7].i = dstX1;
+ n[8].i = dstY1;
+ n[9].i = mask;
+ n[10].e = filter;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_BlitFramebufferEXT(ctx->Exec, (srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter));
+ }
+}
+#endif
+
+
+/** GL_EXT_provoking_vertex */
+static void GLAPIENTRY
+save_ProvokingVertexEXT(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_PROVOKING_VERTEX, 1);
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ /*CALL_ProvokingVertexEXT(ctx->Exec, (mode));*/
+ _mesa_ProvokingVertexEXT(mode);
+ }
+}
+
+
+/* aka UseProgram() */
+static void GLAPIENTRY
+save_UseProgramObjectARB(GLhandleARB program)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_USE_PROGRAM, 1);
+ if (n) {
+ n[1].ui = program;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UseProgramObjectARB(ctx->Exec, (program));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Uniform1fARB(GLint location, GLfloat x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_1F, 2);
+ if (n) {
+ n[1].i = location;
+ n[2].f = x;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform1fARB(ctx->Exec, (location, x));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Uniform2fARB(GLint location, GLfloat x, GLfloat y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_2F, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].f = x;
+ n[3].f = y;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform2fARB(ctx->Exec, (location, x, y));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Uniform3fARB(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_3F, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform3fARB(ctx->Exec, (location, x, y, z));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Uniform4fARB(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_4F, 5);
+ if (n) {
+ n[1].i = location;
+ n[2].f = x;
+ n[3].f = y;
+ n[4].f = z;
+ n[5].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform4fARB(ctx->Exec, (location, x, y, z, w));
+ }
+}
+
+
+/** Return copy of memory */
+static void *
+memdup(const void *src, GLsizei bytes)
+{
+ void *b = bytes >= 0 ? _mesa_malloc(bytes) : NULL;
+ if (b)
+ _mesa_memcpy(b, src, bytes);
+ return b;
+}
+
+
+static void GLAPIENTRY
+save_Uniform1fvARB(GLint location, GLsizei count, const GLfloat *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_1FV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 1 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform1fvARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform2fvARB(GLint location, GLsizei count, const GLfloat *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_2FV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 2 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform2fvARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform3fvARB(GLint location, GLsizei count, const GLfloat *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_3FV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 3 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform3fvARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform4fvARB(GLint location, GLsizei count, const GLfloat *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_4FV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 4 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform4fvARB(ctx->Exec, (location, count, v));
+ }
+}
+
+
+static void GLAPIENTRY
+save_Uniform1iARB(GLint location, GLint x)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_1I, 2);
+ if (n) {
+ n[1].i = location;
+ n[2].i = x;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform1iARB(ctx->Exec, (location, x));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform2iARB(GLint location, GLint x, GLint y)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_2I, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = x;
+ n[3].i = y;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform2iARB(ctx->Exec, (location, x, y));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform3iARB(GLint location, GLint x, GLint y, GLint z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_3I, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = x;
+ n[3].i = y;
+ n[4].i = z;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform3iARB(ctx->Exec, (location, x, y, z));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform4iARB(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_4I, 5);
+ if (n) {
+ n[1].i = location;
+ n[2].i = x;
+ n[3].i = y;
+ n[4].i = z;
+ n[5].i = w;
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform4iARB(ctx->Exec, (location, x, y, z, w));
+ }
+}
+
+
+
+static void GLAPIENTRY
+save_Uniform1ivARB(GLint location, GLsizei count, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_1IV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 1 * sizeof(GLint));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform1ivARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform2ivARB(GLint location, GLsizei count, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_2IV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 2 * sizeof(GLint));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform2ivARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform3ivARB(GLint location, GLsizei count, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_3IV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 3 * sizeof(GLint));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform3ivARB(ctx->Exec, (location, count, v));
+ }
+}
+
+static void GLAPIENTRY
+save_Uniform4ivARB(GLint location, GLsizei count, const GLint *v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_4IV, 3);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].data = memdup(v, count * 4 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_Uniform4ivARB(ctx->Exec, (location, count, v));
+ }
+}
+
+
+static void GLAPIENTRY
+save_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX22, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 2 * 2 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix2fvARB(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+static void GLAPIENTRY
+save_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX33, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 3 * 3 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix3fvARB(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+static void GLAPIENTRY
+save_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX44, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 4 * 4 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix4fvARB(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+
+static void GLAPIENTRY
+save_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX23, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 2 * 3 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix2x3fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+static void GLAPIENTRY
+save_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX32, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 3 * 2 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix3x2fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+
+static void GLAPIENTRY
+save_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX24, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 2 * 4 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix2x4fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+static void GLAPIENTRY
+save_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX42, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 4 * 2 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix4x2fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+
+static void GLAPIENTRY
+save_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX34, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 3 * 4 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix3x4fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+static void GLAPIENTRY
+save_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *m)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ Node *n;
+ ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+ n = ALLOC_INSTRUCTION(ctx, OPCODE_UNIFORM_MATRIX43, 4);
+ if (n) {
+ n[1].i = location;
+ n[2].i = count;
+ n[3].b = transpose;
+ n[4].data = memdup(m, count * 4 * 3 * sizeof(GLfloat));
+ }
+ if (ctx->ExecuteFlag) {
+ CALL_UniformMatrix4x3fv(ctx->Exec, (location, count, transpose, m));
+ }
+}
+
+
+
+/**
+ * Save an error-generating command into display list.
+ *
+ * KW: Will appear in the list before the vertex buffer containing the
+ * command that provoked the error. I don't see this as a problem.
+ */
+static void
+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;
+ }
+}
+
+
+/**
+ * Compile an error into current display list.
+ */
+void
+_mesa_compile_error(GLcontext *ctx, GLenum error, const char *s)
+{
+ if (ctx->CompileFlag)
+ save_error(ctx, error, s);
+ if (ctx->ExecuteFlag)
+ _mesa_error(ctx, error, s);
+}
+
+
+/**
+ * Test if ID names a display list.
+ */
+static GLboolean
+islist(GLcontext *ctx, GLuint list)
+{
+ if (list > 0 && lookup_list(ctx, list)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/**********************************************************************/
+/* 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.
+ * \param list - display list number
+ */
+static void
+execute_list(GLcontext *ctx, GLuint list)
+{
+ struct gl_display_list *dlist;
+ Node *n;
+ GLboolean done;
+
+ if (list == 0 || !islist(ctx, list))
+ return;
+
+ if (ctx->ListState.CallDepth == MAX_LIST_NESTING) {
+ /* raise an error? */
+ return;
+ }
+
+ dlist = lookup_list(ctx, list);
+ if (!dlist)
+ return;
+
+ ctx->ListState.CallDepth++;
+
+ if (ctx->Driver.BeginCallList)
+ ctx->Driver.BeginCallList(ctx, dlist);
+
+ n = dlist->Head;
+
+ done = GL_FALSE;
+ while (!done) {
+ OpCode opcode = n[0].opcode;
+ int i = (int) n[0].opcode - (int) OPCODE_EXT_0;
+
+ if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) {
+ /* this is a driver-extended opcode */
+ ctx->ListExt.Opcode[i].Execute(ctx, &n[1]);
+ n += ctx->ListExt.Opcode[i].Size;
+ }
+ else {
+ switch (opcode) {
+ case OPCODE_ERROR:
+ _mesa_error(ctx, n[1].e, (const char *) n[2].data);
+ break;
+ case OPCODE_ACCUM:
+ CALL_Accum(ctx->Exec, (n[1].e, n[2].f));
+ break;
+ case OPCODE_ALPHA_FUNC:
+ CALL_AlphaFunc(ctx->Exec, (n[1].e, n[2].f));
+ break;
+ case OPCODE_BIND_TEXTURE:
+ CALL_BindTexture(ctx->Exec, (n[1].e, n[2].ui));
+ break;
+ case OPCODE_BITMAP:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_Bitmap(ctx->Exec, ((GLsizei) n[1].i, (GLsizei) n[2].i,
+ n[3].f, n[4].f, n[5].f, n[6].f,
+ (const GLubyte *) n[7].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_BLEND_COLOR:
+ CALL_BlendColor(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_BLEND_EQUATION:
+ CALL_BlendEquation(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_BLEND_EQUATION_SEPARATE:
+ CALL_BlendEquationSeparateEXT(ctx->Exec, (n[1].e, n[2].e));
+ break;
+ case OPCODE_BLEND_FUNC_SEPARATE:
+ CALL_BlendFuncSeparateEXT(ctx->Exec,
+ (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->ListState.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 (n[2].b) {
+ /* user specified a bad data type at compile time */
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)");
+ }
+ else if (ctx->ListState.CallDepth < MAX_LIST_NESTING) {
+ GLuint list = (GLuint) (ctx->List.ListBase + n[1].i);
+ execute_list(ctx, list);
+ }
+ break;
+ case OPCODE_CLEAR:
+ CALL_Clear(ctx->Exec, (n[1].bf));
+ break;
+ case OPCODE_CLEAR_COLOR:
+ CALL_ClearColor(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_CLEAR_ACCUM:
+ CALL_ClearAccum(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_CLEAR_DEPTH:
+ CALL_ClearDepth(ctx->Exec, ((GLclampd) n[1].f));
+ break;
+ case OPCODE_CLEAR_INDEX:
+ CALL_ClearIndex(ctx->Exec, ((GLfloat) n[1].ui));
+ break;
+ case OPCODE_CLEAR_STENCIL:
+ CALL_ClearStencil(ctx->Exec, (n[1].i));
+ break;
+ case OPCODE_CLIP_PLANE:
+ {
+ GLdouble eq[4];
+ eq[0] = n[2].f;
+ eq[1] = n[3].f;
+ eq[2] = n[4].f;
+ eq[3] = n[5].f;
+ CALL_ClipPlane(ctx->Exec, (n[1].e, eq));
+ }
+ break;
+ case OPCODE_COLOR_MASK:
+ CALL_ColorMask(ctx->Exec, (n[1].b, n[2].b, n[3].b, n[4].b));
+ break;
+ case OPCODE_COLOR_MATERIAL:
+ CALL_ColorMaterial(ctx->Exec, (n[1].e, n[2].e));
+ break;
+ case OPCODE_COLOR_TABLE:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_ColorTable(ctx->Exec, (n[1].e, n[2].e, n[3].i, n[4].e,
+ n[5].e, n[6].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_COLOR_TABLE_PARAMETER_FV:
+ {
+ GLfloat params[4];
+ params[0] = n[3].f;
+ params[1] = n[4].f;
+ params[2] = n[5].f;
+ params[3] = n[6].f;
+ CALL_ColorTableParameterfv(ctx->Exec,
+ (n[1].e, n[2].e, params));
+ }
+ break;
+ case OPCODE_COLOR_TABLE_PARAMETER_IV:
+ {
+ GLint params[4];
+ params[0] = n[3].i;
+ params[1] = n[4].i;
+ params[2] = n[5].i;
+ params[3] = n[6].i;
+ CALL_ColorTableParameteriv(ctx->Exec,
+ (n[1].e, n[2].e, params));
+ }
+ break;
+ case OPCODE_COLOR_SUB_TABLE:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_ColorSubTable(ctx->Exec, (n[1].e, n[2].i, n[3].i,
+ n[4].e, n[5].e, n[6].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_CONVOLUTION_FILTER_1D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_ConvolutionFilter1D(ctx->Exec, (n[1].e, n[2].i, n[3].i,
+ n[4].e, n[5].e,
+ n[6].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_CONVOLUTION_FILTER_2D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_ConvolutionFilter2D(ctx->Exec, (n[1].e, n[2].i, n[3].i,
+ n[4].i, n[5].e, n[6].e,
+ n[7].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_CONVOLUTION_PARAMETER_I:
+ CALL_ConvolutionParameteri(ctx->Exec, (n[1].e, n[2].e, n[3].i));
+ break;
+ case OPCODE_CONVOLUTION_PARAMETER_IV:
+ {
+ GLint params[4];
+ params[0] = n[3].i;
+ params[1] = n[4].i;
+ params[2] = n[5].i;
+ params[3] = n[6].i;
+ CALL_ConvolutionParameteriv(ctx->Exec,
+ (n[1].e, n[2].e, params));
+ }
+ break;
+ case OPCODE_CONVOLUTION_PARAMETER_F:
+ CALL_ConvolutionParameterf(ctx->Exec, (n[1].e, n[2].e, n[3].f));
+ break;
+ case OPCODE_CONVOLUTION_PARAMETER_FV:
+ {
+ GLfloat params[4];
+ params[0] = n[3].f;
+ params[1] = n[4].f;
+ params[2] = n[5].f;
+ params[3] = n[6].f;
+ CALL_ConvolutionParameterfv(ctx->Exec,
+ (n[1].e, n[2].e, params));
+ }
+ break;
+ case OPCODE_COPY_COLOR_SUB_TABLE:
+ CALL_CopyColorSubTable(ctx->Exec, (n[1].e, n[2].i,
+ n[3].i, n[4].i, n[5].i));
+ break;
+ case OPCODE_COPY_COLOR_TABLE:
+ CALL_CopyColorSubTable(ctx->Exec, (n[1].e, n[2].i,
+ n[3].i, n[4].i, n[5].i));
+ break;
+ case OPCODE_COPY_PIXELS:
+ CALL_CopyPixels(ctx->Exec, (n[1].i, n[2].i,
+ (GLsizei) n[3].i, (GLsizei) n[4].i,
+ n[5].e));
+ break;
+ case OPCODE_COPY_TEX_IMAGE1D:
+ CALL_CopyTexImage1D(ctx->Exec, (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:
+ CALL_CopyTexImage2D(ctx->Exec, (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:
+ CALL_CopyTexSubImage1D(ctx->Exec, (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:
+ CALL_CopyTexSubImage2D(ctx->Exec, (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:
+ CALL_CopyTexSubImage3D(ctx->Exec, (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:
+ CALL_CullFace(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_DEPTH_FUNC:
+ CALL_DepthFunc(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_DEPTH_MASK:
+ CALL_DepthMask(ctx->Exec, (n[1].b));
+ break;
+ case OPCODE_DEPTH_RANGE:
+ CALL_DepthRange(ctx->Exec,
+ ((GLclampd) n[1].f, (GLclampd) n[2].f));
+ break;
+ case OPCODE_DISABLE:
+ CALL_Disable(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_DRAW_BUFFER:
+ CALL_DrawBuffer(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_DRAW_PIXELS:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_DrawPixels(ctx->Exec, (n[1].i, n[2].i, n[3].e, n[4].e,
+ n[5].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_ENABLE:
+ CALL_Enable(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_EVALMESH1:
+ CALL_EvalMesh1(ctx->Exec, (n[1].e, n[2].i, n[3].i));
+ break;
+ case OPCODE_EVALMESH2:
+ CALL_EvalMesh2(ctx->Exec,
+ (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;
+ CALL_Fogfv(ctx->Exec, (n[1].e, p));
+ }
+ break;
+ case OPCODE_FRONT_FACE:
+ CALL_FrontFace(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_FRUSTUM:
+ CALL_Frustum(ctx->Exec,
+ (n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f));
+ break;
+ case OPCODE_HINT:
+ CALL_Hint(ctx->Exec, (n[1].e, n[2].e));
+ break;
+ case OPCODE_HISTOGRAM:
+ CALL_Histogram(ctx->Exec, (n[1].e, n[2].i, n[3].e, n[4].b));
+ break;
+ case OPCODE_INDEX_MASK:
+ CALL_IndexMask(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_INIT_NAMES:
+ CALL_InitNames(ctx->Exec, ());
+ 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;
+ CALL_Lightfv(ctx->Exec, (n[1].e, n[2].e, p));
+ }
+ 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;
+ CALL_LightModelfv(ctx->Exec, (n[1].e, p));
+ }
+ break;
+ case OPCODE_LINE_STIPPLE:
+ CALL_LineStipple(ctx->Exec, (n[1].i, n[2].us));
+ break;
+ case OPCODE_LINE_WIDTH:
+ CALL_LineWidth(ctx->Exec, (n[1].f));
+ break;
+ case OPCODE_LIST_BASE:
+ CALL_ListBase(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_LOAD_IDENTITY:
+ CALL_LoadIdentity(ctx->Exec, ());
+ break;
+ case OPCODE_LOAD_MATRIX:
+ if (sizeof(Node) == sizeof(GLfloat)) {
+ CALL_LoadMatrixf(ctx->Exec, (&n[1].f));
+ }
+ else {
+ GLfloat m[16];
+ GLuint i;
+ for (i = 0; i < 16; i++) {
+ m[i] = n[1 + i].f;
+ }
+ CALL_LoadMatrixf(ctx->Exec, (m));
+ }
+ break;
+ case OPCODE_LOAD_NAME:
+ CALL_LoadName(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_LOGIC_OP:
+ CALL_LogicOp(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_MAP1:
+ {
+ GLenum target = n[1].e;
+ GLint ustride = _mesa_evaluator_components(target);
+ GLint uorder = n[5].i;
+ GLfloat u1 = n[2].f;
+ GLfloat u2 = n[3].f;
+ CALL_Map1f(ctx->Exec, (target, u1, u2, ustride, uorder,
+ (GLfloat *) n[6].data));
+ }
+ break;
+ case OPCODE_MAP2:
+ {
+ GLenum target = n[1].e;
+ GLfloat u1 = n[2].f;
+ GLfloat u2 = n[3].f;
+ GLfloat v1 = n[4].f;
+ GLfloat v2 = n[5].f;
+ GLint ustride = n[6].i;
+ GLint vstride = n[7].i;
+ GLint uorder = n[8].i;
+ GLint vorder = n[9].i;
+ CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder,
+ v1, v2, vstride, vorder,
+ (GLfloat *) n[10].data));
+ }
+ break;
+ case OPCODE_MAPGRID1:
+ CALL_MapGrid1f(ctx->Exec, (n[1].i, n[2].f, n[3].f));
+ break;
+ case OPCODE_MAPGRID2:
+ CALL_MapGrid2f(ctx->Exec,
+ (n[1].i, n[2].f, n[3].f, n[4].i, n[5].f, n[6].f));
+ break;
+ case OPCODE_MATRIX_MODE:
+ CALL_MatrixMode(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_MIN_MAX:
+ CALL_Minmax(ctx->Exec, (n[1].e, n[2].e, n[3].b));
+ break;
+ case OPCODE_MULT_MATRIX:
+ if (sizeof(Node) == sizeof(GLfloat)) {
+ CALL_MultMatrixf(ctx->Exec, (&n[1].f));
+ }
+ else {
+ GLfloat m[16];
+ GLuint i;
+ for (i = 0; i < 16; i++) {
+ m[i] = n[1 + i].f;
+ }
+ CALL_MultMatrixf(ctx->Exec, (m));
+ }
+ break;
+ case OPCODE_ORTHO:
+ CALL_Ortho(ctx->Exec,
+ (n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f));
+ break;
+ case OPCODE_PASSTHROUGH:
+ CALL_PassThrough(ctx->Exec, (n[1].f));
+ break;
+ case OPCODE_PIXEL_MAP:
+ CALL_PixelMapfv(ctx->Exec,
+ (n[1].e, n[2].i, (GLfloat *) n[3].data));
+ break;
+ case OPCODE_PIXEL_TRANSFER:
+ CALL_PixelTransferf(ctx->Exec, (n[1].e, n[2].f));
+ break;
+ case OPCODE_PIXEL_ZOOM:
+ CALL_PixelZoom(ctx->Exec, (n[1].f, n[2].f));
+ break;
+ case OPCODE_POINT_SIZE:
+ CALL_PointSize(ctx->Exec, (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;
+ CALL_PointParameterfvEXT(ctx->Exec, (n[1].e, params));
+ }
+ break;
+ case OPCODE_POLYGON_MODE:
+ CALL_PolygonMode(ctx->Exec, (n[1].e, n[2].e));
+ break;
+ case OPCODE_POLYGON_STIPPLE:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_PolygonStipple(ctx->Exec, ((GLubyte *) n[1].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_POLYGON_OFFSET:
+ CALL_PolygonOffset(ctx->Exec, (n[1].f, n[2].f));
+ break;
+ case OPCODE_POP_ATTRIB:
+ CALL_PopAttrib(ctx->Exec, ());
+ break;
+ case OPCODE_POP_MATRIX:
+ CALL_PopMatrix(ctx->Exec, ());
+ break;
+ case OPCODE_POP_NAME:
+ CALL_PopName(ctx->Exec, ());
+ break;
+ case OPCODE_PRIORITIZE_TEXTURE:
+ CALL_PrioritizeTextures(ctx->Exec, (1, &n[1].ui, &n[2].f));
+ break;
+ case OPCODE_PUSH_ATTRIB:
+ CALL_PushAttrib(ctx->Exec, (n[1].bf));
+ break;
+ case OPCODE_PUSH_MATRIX:
+ CALL_PushMatrix(ctx->Exec, ());
+ break;
+ case OPCODE_PUSH_NAME:
+ CALL_PushName(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_RASTER_POS:
+ CALL_RasterPos4f(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_READ_BUFFER:
+ CALL_ReadBuffer(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_RESET_HISTOGRAM:
+ CALL_ResetHistogram(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_RESET_MIN_MAX:
+ CALL_ResetMinmax(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_ROTATE:
+ CALL_Rotatef(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_SCALE:
+ CALL_Scalef(ctx->Exec, (n[1].f, n[2].f, n[3].f));
+ break;
+ case OPCODE_SCISSOR:
+ CALL_Scissor(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));
+ break;
+ case OPCODE_SHADE_MODEL:
+ CALL_ShadeModel(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_PROVOKING_VERTEX:
+ CALL_ProvokingVertexEXT(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_STENCIL_FUNC:
+ CALL_StencilFunc(ctx->Exec, (n[1].e, n[2].i, n[3].ui));
+ break;
+ case OPCODE_STENCIL_MASK:
+ CALL_StencilMask(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_STENCIL_OP:
+ CALL_StencilOp(ctx->Exec, (n[1].e, n[2].e, n[3].e));
+ break;
+ case OPCODE_STENCIL_FUNC_SEPARATE:
+ CALL_StencilFuncSeparate(ctx->Exec,
+ (n[1].e, n[2].e, n[3].i, n[4].ui));
+ break;
+ case OPCODE_STENCIL_MASK_SEPARATE:
+ CALL_StencilMaskSeparate(ctx->Exec, (n[1].e, n[2].ui));
+ break;
+ case OPCODE_STENCIL_OP_SEPARATE:
+ CALL_StencilOpSeparate(ctx->Exec,
+ (n[1].e, n[2].e, n[3].e, n[4].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;
+ CALL_TexEnvfv(ctx->Exec, (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;
+ CALL_TexGenfv(ctx->Exec, (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;
+ CALL_TexParameterfv(ctx->Exec, (n[1].e, n[2].e, params));
+ }
+ break;
+ case OPCODE_TEX_IMAGE1D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexImage1D(ctx->Exec, (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 */
+ n[8].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TEX_IMAGE2D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexImage2D(ctx->Exec, (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 */
+ n[9].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TEX_IMAGE3D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexImage3D(ctx->Exec, (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 */
+ n[10].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TEX_SUB_IMAGE1D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexSubImage1D(ctx->Exec, (n[1].e, n[2].i, n[3].i,
+ n[4].i, n[5].e,
+ n[6].e, n[7].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TEX_SUB_IMAGE2D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexSubImage2D(ctx->Exec, (n[1].e, n[2].i, n[3].i,
+ n[4].i, n[5].e,
+ n[6].i, n[7].e, n[8].e,
+ n[9].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TEX_SUB_IMAGE3D:
+ {
+ const struct gl_pixelstore_attrib save = ctx->Unpack;
+ ctx->Unpack = ctx->DefaultPacking;
+ CALL_TexSubImage3D(ctx->Exec, (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,
+ n[11].data));
+ ctx->Unpack = save; /* restore */
+ }
+ break;
+ case OPCODE_TRANSLATE:
+ CALL_Translatef(ctx->Exec, (n[1].f, n[2].f, n[3].f));
+ break;
+ case OPCODE_VIEWPORT:
+ CALL_Viewport(ctx->Exec, (n[1].i, n[2].i,
+ (GLsizei) n[3].i, (GLsizei) n[4].i));
+ break;
+ case OPCODE_WINDOW_POS:
+ CALL_WindowPos4fMESA(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_ACTIVE_TEXTURE: /* GL_ARB_multitexture */
+ CALL_ActiveTextureARB(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_1D: /* GL_ARB_texture_compression */
+ CALL_CompressedTexImage1DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e,
+ n[4].i, n[5].i, n[6].i,
+ n[7].data));
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_2D: /* GL_ARB_texture_compression */
+ CALL_CompressedTexImage2DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e,
+ n[4].i, n[5].i, n[6].i,
+ n[7].i, n[8].data));
+ break;
+ case OPCODE_COMPRESSED_TEX_IMAGE_3D: /* GL_ARB_texture_compression */
+ CALL_CompressedTexImage3DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e,
+ n[4].i, n[5].i, n[6].i,
+ n[7].i, n[8].i,
+ n[9].data));
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: /* GL_ARB_texture_compress */
+ CALL_CompressedTexSubImage1DARB(ctx->Exec,
+ (n[1].e, n[2].i, n[3].i, n[4].i,
+ n[5].e, n[6].i, n[7].data));
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: /* GL_ARB_texture_compress */
+ CALL_CompressedTexSubImage2DARB(ctx->Exec,
+ (n[1].e, n[2].i, n[3].i, n[4].i,
+ n[5].i, n[6].i, n[7].e, n[8].i,
+ n[9].data));
+ break;
+ case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: /* GL_ARB_texture_compress */
+ CALL_CompressedTexSubImage3DARB(ctx->Exec,
+ (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].i, n[11].data));
+ break;
+ case OPCODE_SAMPLE_COVERAGE: /* GL_ARB_multisample */
+ CALL_SampleCoverageARB(ctx->Exec, (n[1].f, n[2].b));
+ break;
+ case OPCODE_WINDOW_POS_ARB: /* GL_ARB_window_pos */
+ CALL_WindowPos3fMESA(ctx->Exec, (n[1].f, n[2].f, n[3].f));
+ break;
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ case OPCODE_BIND_PROGRAM_NV: /* GL_NV_vertex_program */
+ CALL_BindProgramNV(ctx->Exec, (n[1].e, n[2].ui));
+ break;
+#endif
+#if FEATURE_NV_vertex_program
+ case OPCODE_EXECUTE_PROGRAM_NV:
+ {
+ GLfloat v[4];
+ v[0] = n[3].f;
+ v[1] = n[4].f;
+ v[2] = n[5].f;
+ v[3] = n[6].f;
+ CALL_ExecuteProgramNV(ctx->Exec, (n[1].e, n[2].ui, v));
+ }
+ break;
+ case OPCODE_REQUEST_RESIDENT_PROGRAMS_NV:
+ CALL_RequestResidentProgramsNV(ctx->Exec, (n[1].ui,
+ (GLuint *) n[2].data));
+ break;
+ case OPCODE_LOAD_PROGRAM_NV:
+ CALL_LoadProgramNV(ctx->Exec, (n[1].e, n[2].ui, n[3].i,
+ (const GLubyte *) n[4].data));
+ break;
+ case OPCODE_TRACK_MATRIX_NV:
+ CALL_TrackMatrixNV(ctx->Exec, (n[1].e, n[2].ui, n[3].e, n[4].e));
+ break;
+#endif
+
+#if FEATURE_NV_fragment_program
+ case OPCODE_PROGRAM_LOCAL_PARAMETER_ARB:
+ CALL_ProgramLocalParameter4fARB(ctx->Exec,
+ (n[1].e, n[2].ui, n[3].f, n[4].f,
+ n[5].f, n[6].f));
+ break;
+ case OPCODE_PROGRAM_NAMED_PARAMETER_NV:
+ CALL_ProgramNamedParameter4fNV(ctx->Exec, (n[1].ui, n[2].i,
+ (const GLubyte *) n[3].
+ data, n[4].f, n[5].f,
+ n[6].f, n[7].f));
+ break;
+#endif
+
+ case OPCODE_ACTIVE_STENCIL_FACE_EXT:
+ CALL_ActiveStencilFaceEXT(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_DEPTH_BOUNDS_EXT:
+ CALL_DepthBoundsEXT(ctx->Exec, (n[1].f, n[2].f));
+ break;
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ case OPCODE_PROGRAM_STRING_ARB:
+ CALL_ProgramStringARB(ctx->Exec,
+ (n[1].e, n[2].e, n[3].i, n[4].data));
+ break;
+#endif
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program || FEATURE_NV_vertex_program
+ case OPCODE_PROGRAM_ENV_PARAMETER_ARB:
+ CALL_ProgramEnvParameter4fARB(ctx->Exec, (n[1].e, n[2].ui, n[3].f,
+ n[4].f, n[5].f,
+ n[6].f));
+ break;
+#endif
+#if FEATURE_ARB_occlusion_query
+ case OPCODE_BEGIN_QUERY_ARB:
+ CALL_BeginQueryARB(ctx->Exec, (n[1].e, n[2].ui));
+ break;
+ case OPCODE_END_QUERY_ARB:
+ CALL_EndQueryARB(ctx->Exec, (n[1].e));
+ break;
+#endif
+ case OPCODE_DRAW_BUFFERS_ARB:
+ {
+ GLenum buffers[MAX_DRAW_BUFFERS];
+ GLint i, count = MIN2(n[1].i, MAX_DRAW_BUFFERS);
+ for (i = 0; i < count; i++)
+ buffers[i] = n[2 + i].e;
+ CALL_DrawBuffersARB(ctx->Exec, (n[1].i, buffers));
+ }
+ break;
+#if FEATURE_EXT_framebuffer_blit
+ case OPCODE_BLIT_FRAMEBUFFER:
+ CALL_BlitFramebufferEXT(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i,
+ n[5].i, n[6].i, n[7].i, n[8].i,
+ n[9].i, n[10].e));
+ break;
+#endif
+
+ case OPCODE_USE_PROGRAM:
+ CALL_UseProgramObjectARB(ctx->Exec, (n[1].ui));
+ break;
+ case OPCODE_UNIFORM_1F:
+ CALL_Uniform1fARB(ctx->Exec, (n[1].i, n[2].f));
+ break;
+ case OPCODE_UNIFORM_2F:
+ CALL_Uniform2fARB(ctx->Exec, (n[1].i, n[2].f, n[3].f));
+ break;
+ case OPCODE_UNIFORM_3F:
+ CALL_Uniform3fARB(ctx->Exec, (n[1].i, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_UNIFORM_4F:
+ CALL_Uniform4fARB(ctx->Exec,
+ (n[1].i, n[2].f, n[3].f, n[4].f, n[5].f));
+ break;
+ case OPCODE_UNIFORM_1FV:
+ CALL_Uniform1fvARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_2FV:
+ CALL_Uniform2fvARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_3FV:
+ CALL_Uniform3fvARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_4FV:
+ CALL_Uniform4fvARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_1I:
+ CALL_Uniform1iARB(ctx->Exec, (n[1].i, n[2].i));
+ break;
+ case OPCODE_UNIFORM_2I:
+ CALL_Uniform2iARB(ctx->Exec, (n[1].i, n[2].i, n[3].i));
+ break;
+ case OPCODE_UNIFORM_3I:
+ CALL_Uniform3iARB(ctx->Exec, (n[1].i, n[2].i, n[3].i, n[4].i));
+ break;
+ case OPCODE_UNIFORM_4I:
+ CALL_Uniform4iARB(ctx->Exec,
+ (n[1].i, n[2].i, n[3].i, n[4].i, n[5].i));
+ break;
+ case OPCODE_UNIFORM_1IV:
+ CALL_Uniform1ivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_2IV:
+ CALL_Uniform2ivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_3IV:
+ CALL_Uniform3ivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+ case OPCODE_UNIFORM_4IV:
+ CALL_Uniform4ivARB(ctx->Exec, (n[1].i, n[2].i, n[3].data));
+ break;
+
+ case OPCODE_UNIFORM_MATRIX22:
+ CALL_UniformMatrix2fvARB(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX33:
+ CALL_UniformMatrix3fvARB(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX44:
+ CALL_UniformMatrix4fvARB(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX23:
+ CALL_UniformMatrix2x3fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX32:
+ CALL_UniformMatrix3x2fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX24:
+ CALL_UniformMatrix2x4fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX42:
+ CALL_UniformMatrix4x2fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX34:
+ CALL_UniformMatrix3x4fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+ case OPCODE_UNIFORM_MATRIX43:
+ CALL_UniformMatrix4x3fv(ctx->Exec,
+ (n[1].i, n[2].i, n[3].b, n[4].data));
+ break;
+
+ case OPCODE_TEX_BUMP_PARAMETER_ATI:
+ {
+ GLfloat values[4];
+ GLuint i, pname = n[1].ui;
+
+ for (i = 0; i < 4; i++)
+ values[i] = n[1 + i].f;
+ CALL_TexBumpParameterfvATI(ctx->Exec, (pname, values));
+ }
+ break;
+#if FEATURE_ATI_fragment_shader
+ case OPCODE_BIND_FRAGMENT_SHADER_ATI:
+ CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i));
+ break;
+ case OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI:
+ {
+ GLfloat values[4];
+ GLuint i, dst = n[1].ui;
+
+ for (i = 0; i < 4; i++)
+ values[i] = n[1 + i].f;
+ CALL_SetFragmentShaderConstantATI(ctx->Exec, (dst, values));
+ }
+ break;
+#endif
+ case OPCODE_ATTR_1F_NV:
+ CALL_VertexAttrib1fNV(ctx->Exec, (n[1].e, n[2].f));
+ break;
+ case OPCODE_ATTR_2F_NV:
+ /* Really shouldn't have to do this - the Node structure
+ * is convenient, but it would be better to store the data
+ * packed appropriately so that it can be sent directly
+ * on. With x86_64 becoming common, this will start to
+ * matter more.
+ */
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib2fvNV(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib2fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f));
+ break;
+ case OPCODE_ATTR_3F_NV:
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib3fvNV(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib3fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f,
+ n[4].f));
+ break;
+ case OPCODE_ATTR_4F_NV:
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib4fvNV(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib4fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f,
+ n[4].f, n[5].f));
+ break;
+ case OPCODE_ATTR_1F_ARB:
+ CALL_VertexAttrib1fARB(ctx->Exec, (n[1].e, n[2].f));
+ break;
+ case OPCODE_ATTR_2F_ARB:
+ /* Really shouldn't have to do this - the Node structure
+ * is convenient, but it would be better to store the data
+ * packed appropriately so that it can be sent directly
+ * on. With x86_64 becoming common, this will start to
+ * matter more.
+ */
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib2fvARB(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib2fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f));
+ break;
+ case OPCODE_ATTR_3F_ARB:
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib3fvARB(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib3fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f,
+ n[4].f));
+ break;
+ case OPCODE_ATTR_4F_ARB:
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_VertexAttrib4fvARB(ctx->Exec, (n[1].e, &n[2].f));
+ else
+ CALL_VertexAttrib4fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f,
+ n[4].f, n[5].f));
+ break;
+ case OPCODE_MATERIAL:
+ if (sizeof(Node) == sizeof(GLfloat))
+ CALL_Materialfv(ctx->Exec, (n[1].e, n[2].e, &n[3].f));
+ else {
+ GLfloat f[4];
+ f[0] = n[3].f;
+ f[1] = n[4].f;
+ f[2] = n[5].f;
+ f[3] = n[6].f;
+ CALL_Materialfv(ctx->Exec, (n[1].e, n[2].e, f));
+ }
+ break;
+ case OPCODE_BEGIN:
+ CALL_Begin(ctx->Exec, (n[1].e));
+ break;
+ case OPCODE_END:
+ CALL_End(ctx->Exec, ());
+ break;
+ case OPCODE_RECTF:
+ CALL_Rectf(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f));
+ break;
+ case OPCODE_EVAL_C1:
+ CALL_EvalCoord1f(ctx->Exec, (n[1].f));
+ break;
+ case OPCODE_EVAL_C2:
+ CALL_EvalCoord2f(ctx->Exec, (n[1].f, n[2].f));
+ break;
+ case OPCODE_EVAL_P1:
+ CALL_EvalPoint1(ctx->Exec, (n[1].i));
+ break;
+ case OPCODE_EVAL_P2:
+ CALL_EvalPoint2(ctx->Exec, (n[1].i, n[2].i));
+ break;
+
+ case OPCODE_CONTINUE:
+ n = (Node *) n[1].next;
+ break;
+ case OPCODE_END_OF_LIST:
+ done = GL_TRUE;
+ break;
+ default:
+ {
+ char msg[1000];
+ _mesa_sprintf(msg, "Error in execute_list: opcode=%d",
+ (int) opcode);
+ _mesa_problem(ctx, msg);
+ }
+ done = GL_TRUE;
+ }
+
+ /* increment n to point to next compiled command */
+ if (opcode != OPCODE_CONTINUE) {
+ n += InstSize[opcode];
+ }
+ }
+ }
+
+ if (ctx->Driver.EndCallList)
+ ctx->Driver.EndCallList(ctx);
+
+ ctx->ListState.CallDepth--;
+}
+
+
+
+/**********************************************************************/
+/* GL functions */
+/**********************************************************************/
+
+/**
+ * Test if a display list number is valid.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsList(GLuint list)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0); /* must be called before assert */
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+ return islist(ctx, list);
+}
+
+
+/**
+ * Delete a sequence of consecutive display lists.
+ */
+void GLAPIENTRY
+_mesa_DeleteLists(GLuint list, GLsizei range)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint i;
+ FLUSH_VERTICES(ctx, 0); /* must be called before assert */
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (range < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteLists");
+ return;
+ }
+ for (i = list; i < list + range; i++) {
+ destroy_list(ctx, i);
+ }
+}
+
+
+/**
+ * Return a display list number, n, such that lists n through n+range-1
+ * are free.
+ */
+GLuint GLAPIENTRY
+_mesa_GenLists(GLsizei range)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint base;
+ FLUSH_VERTICES(ctx, 0); /* must be called before assert */
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ if (range < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenLists");
+ return 0;
+ }
+ if (range == 0) {
+ return 0;
+ }
+
+ /*
+ * Make this an atomic operation
+ */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range);
+ if (base) {
+ /* reserve the list IDs by with empty/dummy lists */
+ GLint i;
+ for (i = 0; i < range; i++) {
+ _mesa_HashInsert(ctx->Shared->DisplayList, base + i,
+ make_list(base + i, 1));
+ }
+ }
+
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ return base;
+}
+
+
+/**
+ * Begin a new display list.
+ */
+void GLAPIENTRY
+_mesa_NewList(GLuint name, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ FLUSH_CURRENT(ctx, 0); /* must be called before assert */
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glNewList %u %s\n", name,
+ _mesa_lookup_enum_by_nr(mode));
+
+ if (name == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glNewList");
+ return;
+ }
+
+ if (mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glNewList");
+ return;
+ }
+
+ if (ctx->ListState.CurrentList) {
+ /* already compiling a display list */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
+ return;
+ }
+
+ ctx->CompileFlag = GL_TRUE;
+ ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE);
+
+ /* Reset acumulated list state:
+ */
+ invalidate_saved_current_state( ctx );
+
+ /* Allocate new display list */
+ ctx->ListState.CurrentList = make_list(name, BLOCK_SIZE);
+ ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->Head;
+ ctx->ListState.CurrentPos = 0;
+
+ ctx->Driver.NewList(ctx, name, mode);
+
+ ctx->CurrentDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentDispatch);
+}
+
+
+/**
+ * End definition of current display list.
+ */
+void GLAPIENTRY
+_mesa_EndList(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ SAVE_FLUSH_VERTICES(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glEndList\n");
+
+ /* Check that a list is under construction */
+ if (!ctx->ListState.CurrentList) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndList");
+ return;
+ }
+
+ /* Call before emitting END_OF_LIST, in case the driver wants to
+ * emit opcodes itself.
+ */
+ ctx->Driver.EndList(ctx);
+
+ (void) ALLOC_INSTRUCTION(ctx, OPCODE_END_OF_LIST, 0);
+
+ /* Destroy old list, if any */
+ destroy_list(ctx, ctx->ListState.CurrentList->Name);
+
+ /* Install the new list */
+ _mesa_HashInsert(ctx->Shared->DisplayList,
+ ctx->ListState.CurrentList->Name,
+ ctx->ListState.CurrentList);
+
+
+ if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
+ mesa_print_display_list(ctx->ListState.CurrentList->Name);
+
+ ctx->ListState.CurrentList = NULL;
+ ctx->ExecuteFlag = GL_TRUE;
+ ctx->CompileFlag = GL_FALSE;
+
+ ctx->CurrentDispatch = ctx->Exec;
+ _glapi_set_dispatch(ctx->CurrentDispatch);
+}
+
+
+void GLAPIENTRY
+_mesa_CallList(GLuint list)
+{
+ GLboolean save_compile_flag;
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_CURRENT(ctx, 0);
+ /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */
+ /* execute the display list, and restore the CompileFlag. */
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCallList %d\n", list);
+
+ if (list == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCallList(list==0)");
+ return;
+ }
+
+/* mesa_print_display_list( list ); */
+
+ save_compile_flag = ctx->CompileFlag;
+ if (save_compile_flag) {
+ ctx->CompileFlag = GL_FALSE;
+ }
+
+ execute_list(ctx, list);
+ ctx->CompileFlag = save_compile_flag;
+
+ /* also restore API function pointers to point to "save" versions */
+ if (save_compile_flag) {
+ ctx->CurrentDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentDispatch);
+ }
+}
+
+
+/**
+ * Execute glCallLists: call multiple display lists.
+ */
+void GLAPIENTRY
+_mesa_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ GLboolean save_compile_flag;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCallLists %d\n", n);
+
+ 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_2_BYTES:
+ case GL_3_BYTES:
+ case GL_4_BYTES:
+ /* OK */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)");
+ return;
+ }
+
+ /* Save the CompileFlag status, turn it off, execute display list,
+ * and restore the CompileFlag.
+ */
+ save_compile_flag = ctx->CompileFlag;
+ ctx->CompileFlag = GL_FALSE;
+
+ for (i = 0; i < n; i++) {
+ GLuint list = (GLuint) (ctx->List.ListBase + translate_id(i, type, lists));
+ execute_list(ctx, list);
+ }
+
+ ctx->CompileFlag = save_compile_flag;
+
+ /* also restore API function pointers to point to "save" versions */
+ if (save_compile_flag) {
+ ctx->CurrentDispatch = ctx->Save;
+ _glapi_set_dispatch(ctx->CurrentDispatch);
+ }
+}
+
+
+/**
+ * Set the offset added to list numbers in glCallLists.
+ */
+void GLAPIENTRY
+_mesa_ListBase(GLuint base)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0); /* must be called before assert */
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ctx->List.ListBase = base;
+}
+
+
+/* Can no longer assume ctx->Exec->Func is equal to _mesa_Func.
+ */
+static void GLAPIENTRY
+exec_Finish(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_Finish(ctx->Exec, ());
+}
+
+static void GLAPIENTRY
+exec_Flush(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_Flush(ctx->Exec, ());
+}
+
+static void GLAPIENTRY
+exec_GetBooleanv(GLenum pname, GLboolean *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetBooleanv(ctx->Exec, (pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetClipPlane(GLenum plane, GLdouble * equation)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetClipPlane(ctx->Exec, (plane, equation));
+}
+
+static void GLAPIENTRY
+exec_GetDoublev(GLenum pname, GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetDoublev(ctx->Exec, (pname, params));
+}
+
+static GLenum GLAPIENTRY
+exec_GetError(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_GetError(ctx->Exec, ());
+}
+
+static void GLAPIENTRY
+exec_GetFloatv(GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetFloatv(ctx->Exec, (pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetIntegerv(GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetIntegerv(ctx->Exec, (pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetLightfv(GLenum light, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetLightfv(ctx->Exec, (light, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetLightiv(GLenum light, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetLightiv(ctx->Exec, (light, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetMapdv(GLenum target, GLenum query, GLdouble * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMapdv(ctx->Exec, (target, query, v));
+}
+
+static void GLAPIENTRY
+exec_GetMapfv(GLenum target, GLenum query, GLfloat * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMapfv(ctx->Exec, (target, query, v));
+}
+
+static void GLAPIENTRY
+exec_GetMapiv(GLenum target, GLenum query, GLint * v)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMapiv(ctx->Exec, (target, query, v));
+}
+
+static void GLAPIENTRY
+exec_GetMaterialfv(GLenum face, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMaterialfv(ctx->Exec, (face, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetMaterialiv(GLenum face, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMaterialiv(ctx->Exec, (face, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetPixelMapfv(GLenum map, GLfloat *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetPixelMapfv(ctx->Exec, (map, values));
+}
+
+static void GLAPIENTRY
+exec_GetPixelMapuiv(GLenum map, GLuint *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetPixelMapuiv(ctx->Exec, (map, values));
+}
+
+static void GLAPIENTRY
+exec_GetPixelMapusv(GLenum map, GLushort *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetPixelMapusv(ctx->Exec, (map, values));
+}
+
+static void GLAPIENTRY
+exec_GetPolygonStipple(GLubyte * dest)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetPolygonStipple(ctx->Exec, (dest));
+}
+
+static const GLubyte *GLAPIENTRY
+exec_GetString(GLenum name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_GetString(ctx->Exec, (name));
+}
+
+static void GLAPIENTRY
+exec_GetTexEnvfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexEnvfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexEnviv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexEnviv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexGendv(GLenum coord, GLenum pname, GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexGendv(ctx->Exec, (coord, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexGenfv(GLenum coord, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexGenfv(ctx->Exec, (coord, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexGeniv(GLenum coord, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexGeniv(ctx->Exec, (coord, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexImage(GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexImage(ctx->Exec, (target, level, format, type, pixels));
+}
+
+static void GLAPIENTRY
+exec_GetTexLevelParameterfv(GLenum target, GLint level,
+ GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexLevelParameterfv(ctx->Exec, (target, level, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexLevelParameteriv(GLenum target, GLint level,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexLevelParameteriv(ctx->Exec, (target, level, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexParameterfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetTexParameteriv(ctx->Exec, (target, pname, params));
+}
+
+static GLboolean GLAPIENTRY
+exec_IsEnabled(GLenum cap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_IsEnabled(ctx->Exec, (cap));
+}
+
+static void GLAPIENTRY
+exec_PixelStoref(GLenum pname, GLfloat param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_PixelStoref(ctx->Exec, (pname, param));
+}
+
+static void GLAPIENTRY
+exec_PixelStorei(GLenum pname, GLint param)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_PixelStorei(ctx->Exec, (pname, param));
+}
+
+static void GLAPIENTRY
+exec_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid * pixels)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_ReadPixels(ctx->Exec, (x, y, width, height, format, type, pixels));
+}
+
+static GLint GLAPIENTRY
+exec_RenderMode(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_RenderMode(ctx->Exec, (mode));
+}
+
+static void GLAPIENTRY
+exec_FeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_FeedbackBuffer(ctx->Exec, (size, type, buffer));
+}
+
+static void GLAPIENTRY
+exec_SelectBuffer(GLsizei size, GLuint * buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_SelectBuffer(ctx->Exec, (size, buffer));
+}
+
+static GLboolean GLAPIENTRY
+exec_AreTexturesResident(GLsizei n, const GLuint * texName,
+ GLboolean * residences)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_AreTexturesResident(ctx->Exec, (n, texName, residences));
+}
+
+static void GLAPIENTRY
+exec_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_ColorPointer(ctx->Exec, (size, type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_DeleteTextures(GLsizei n, const GLuint * texName)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_DeleteTextures(ctx->Exec, (n, texName));
+}
+
+static void GLAPIENTRY
+exec_DisableClientState(GLenum cap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_DisableClientState(ctx->Exec, (cap));
+}
+
+static void GLAPIENTRY
+exec_EdgeFlagPointer(GLsizei stride, const GLvoid * vptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_EdgeFlagPointer(ctx->Exec, (stride, vptr));
+}
+
+static void GLAPIENTRY
+exec_EnableClientState(GLenum cap)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_EnableClientState(ctx->Exec, (cap));
+}
+
+static void GLAPIENTRY
+exec_GenTextures(GLsizei n, GLuint * texName)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GenTextures(ctx->Exec, (n, texName));
+}
+
+static void GLAPIENTRY
+exec_GetPointerv(GLenum pname, GLvoid **params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetPointerv(ctx->Exec, (pname, params));
+}
+
+static void GLAPIENTRY
+exec_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_IndexPointer(ctx->Exec, (type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid * pointer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_InterleavedArrays(ctx->Exec, (format, stride, pointer));
+}
+
+static GLboolean GLAPIENTRY
+exec_IsTexture(GLuint texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ return CALL_IsTexture(ctx->Exec, (texture));
+}
+
+static void GLAPIENTRY
+exec_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_NormalPointer(ctx->Exec, (type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_PopClientAttrib(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_PopClientAttrib(ctx->Exec, ());
+}
+
+static void GLAPIENTRY
+exec_PushClientAttrib(GLbitfield mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_PushClientAttrib(ctx->Exec, (mask));
+}
+
+static void GLAPIENTRY
+exec_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_TexCoordPointer(ctx->Exec, (size, type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetCompressedTexImageARB(ctx->Exec, (target, level, img));
+}
+
+static void GLAPIENTRY
+exec_VertexPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_VertexPointer(ctx->Exec, (size, type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_CopyConvolutionFilter1D(ctx->Exec,
+ (target, internalFormat, x, y, width));
+}
+
+static void GLAPIENTRY
+exec_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_CopyConvolutionFilter2D(ctx->Exec,
+ (target, internalFormat, x, y, width,
+ height));
+}
+
+static void GLAPIENTRY
+exec_GetColorTable(GLenum target, GLenum format, GLenum type, GLvoid * data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetColorTable(ctx->Exec, (target, format, type, data));
+}
+
+static void GLAPIENTRY
+exec_GetColorTableParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetColorTableParameterfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetColorTableParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetColorTableParameteriv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid * image)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetConvolutionFilter(ctx->Exec, (target, format, type, image));
+}
+
+static void GLAPIENTRY
+exec_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetConvolutionParameterfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetConvolutionParameteriv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetHistogram(GLenum target, GLboolean reset, GLenum format,
+ GLenum type, GLvoid *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetHistogram(ctx->Exec, (target, reset, format, type, values));
+}
+
+static void GLAPIENTRY
+exec_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetHistogramParameterfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetHistogramParameteriv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetMinmax(GLenum target, GLboolean reset, GLenum format,
+ GLenum type, GLvoid *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMinmax(ctx->Exec, (target, reset, format, type, values));
+}
+
+static void GLAPIENTRY
+exec_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMinmaxParameterfv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetMinmaxParameteriv(ctx->Exec, (target, pname, params));
+}
+
+static void GLAPIENTRY
+exec_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
+ GLvoid *row, GLvoid *column, GLvoid *span)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_GetSeparableFilter(ctx->Exec,
+ (target, format, type, row, column, span));
+}
+
+static void GLAPIENTRY
+exec_SeparableFilter2D(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid *row, const GLvoid *column)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_SeparableFilter2D(ctx->Exec,
+ (target, internalFormat, width, height, format,
+ type, row, column));
+}
+
+static void GLAPIENTRY
+exec_ColorPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_ColorPointerEXT(ctx->Exec, (size, type, stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_EdgeFlagPointerEXT(ctx->Exec, (stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_IndexPointerEXT(ctx->Exec, (type, stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_NormalPointerEXT(ctx->Exec, (type, stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_TexCoordPointerEXT(ctx->Exec, (size, type, stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_VertexPointerEXT(ctx->Exec, (size, type, stride, count, ptr));
+}
+
+static void GLAPIENTRY
+exec_LockArraysEXT(GLint first, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_LockArraysEXT(ctx->Exec, (first, count));
+}
+
+static void GLAPIENTRY
+exec_UnlockArraysEXT(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_UnlockArraysEXT(ctx->Exec, ());
+}
+
+static void GLAPIENTRY
+exec_ClientActiveTextureARB(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_ClientActiveTextureARB(ctx->Exec, (target));
+}
+
+static void GLAPIENTRY
+exec_SecondaryColorPointerEXT(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_SecondaryColorPointerEXT(ctx->Exec, (size, type, stride, ptr));
+}
+
+static void GLAPIENTRY
+exec_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_FogCoordPointerEXT(ctx->Exec, (type, stride, ptr));
+}
+
+/* GL_EXT_multi_draw_arrays */
+static void GLAPIENTRY
+exec_MultiDrawArraysEXT(GLenum mode, GLint * first,
+ GLsizei * count, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_MultiDrawArraysEXT(ctx->Exec, (mode, first, count, primcount));
+}
+
+/* GL_IBM_multimode_draw_arrays */
+static void GLAPIENTRY
+exec_MultiModeDrawArraysIBM(const GLenum * mode, const GLint * first,
+ const GLsizei * count, GLsizei primcount,
+ GLint modestride)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_MultiModeDrawArraysIBM(ctx->Exec,
+ (mode, first, count, primcount, modestride));
+}
+
+/* GL_IBM_multimode_draw_arrays */
+static void GLAPIENTRY
+exec_MultiModeDrawElementsIBM(const GLenum * mode,
+ const GLsizei * count,
+ GLenum type,
+ const GLvoid * const *indices,
+ GLsizei primcount, GLint modestride)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, 0);
+ CALL_MultiModeDrawElementsIBM(ctx->Exec,
+ (mode, count, type, indices, primcount,
+ modestride));
+}
+
+
+
+/**
+ * Setup the given dispatch table to point to Mesa's display list
+ * building functions.
+ *
+ * This does not include any of the tnl functions - they are
+ * initialized from _mesa_init_api_defaults and from the active vtxfmt
+ * struct.
+ */
+void
+_mesa_init_dlist_table(struct _glapi_table *table)
+{
+ _mesa_loopback_init_api_table(table);
+
+ /* GL 1.0 */
+ SET_Accum(table, save_Accum);
+ SET_AlphaFunc(table, save_AlphaFunc);
+ SET_Bitmap(table, save_Bitmap);
+ SET_BlendFunc(table, save_BlendFunc);
+ SET_CallList(table, _mesa_save_CallList);
+ SET_CallLists(table, _mesa_save_CallLists);
+ SET_Clear(table, save_Clear);
+ SET_ClearAccum(table, save_ClearAccum);
+ SET_ClearColor(table, save_ClearColor);
+ SET_ClearDepth(table, save_ClearDepth);
+ SET_ClearIndex(table, save_ClearIndex);
+ SET_ClearStencil(table, save_ClearStencil);
+ SET_ClipPlane(table, save_ClipPlane);
+ SET_ColorMask(table, save_ColorMask);
+ SET_ColorMaterial(table, save_ColorMaterial);
+ SET_CopyPixels(table, save_CopyPixels);
+ SET_CullFace(table, save_CullFace);
+ SET_DeleteLists(table, _mesa_DeleteLists);
+ SET_DepthFunc(table, save_DepthFunc);
+ SET_DepthMask(table, save_DepthMask);
+ SET_DepthRange(table, save_DepthRange);
+ SET_Disable(table, save_Disable);
+ SET_DrawBuffer(table, save_DrawBuffer);
+ SET_DrawPixels(table, save_DrawPixels);
+ SET_Enable(table, save_Enable);
+ SET_EndList(table, _mesa_EndList);
+ SET_EvalMesh1(table, _mesa_save_EvalMesh1);
+ SET_EvalMesh2(table, _mesa_save_EvalMesh2);
+ SET_Finish(table, exec_Finish);
+ SET_Flush(table, exec_Flush);
+ SET_Fogf(table, save_Fogf);
+ SET_Fogfv(table, save_Fogfv);
+ SET_Fogi(table, save_Fogi);
+ SET_Fogiv(table, save_Fogiv);
+ SET_FrontFace(table, save_FrontFace);
+ SET_Frustum(table, save_Frustum);
+ SET_GenLists(table, _mesa_GenLists);
+ SET_GetBooleanv(table, exec_GetBooleanv);
+ SET_GetClipPlane(table, exec_GetClipPlane);
+ SET_GetDoublev(table, exec_GetDoublev);
+ SET_GetError(table, exec_GetError);
+ SET_GetFloatv(table, exec_GetFloatv);
+ SET_GetIntegerv(table, exec_GetIntegerv);
+ SET_GetLightfv(table, exec_GetLightfv);
+ SET_GetLightiv(table, exec_GetLightiv);
+ SET_GetMapdv(table, exec_GetMapdv);
+ SET_GetMapfv(table, exec_GetMapfv);
+ SET_GetMapiv(table, exec_GetMapiv);
+ SET_GetMaterialfv(table, exec_GetMaterialfv);
+ SET_GetMaterialiv(table, exec_GetMaterialiv);
+ SET_GetPixelMapfv(table, exec_GetPixelMapfv);
+ SET_GetPixelMapuiv(table, exec_GetPixelMapuiv);
+ SET_GetPixelMapusv(table, exec_GetPixelMapusv);
+ SET_GetPolygonStipple(table, exec_GetPolygonStipple);
+ SET_GetString(table, exec_GetString);
+ SET_GetTexEnvfv(table, exec_GetTexEnvfv);
+ SET_GetTexEnviv(table, exec_GetTexEnviv);
+ SET_GetTexGendv(table, exec_GetTexGendv);
+ SET_GetTexGenfv(table, exec_GetTexGenfv);
+ SET_GetTexGeniv(table, exec_GetTexGeniv);
+ SET_GetTexImage(table, exec_GetTexImage);
+ SET_GetTexLevelParameterfv(table, exec_GetTexLevelParameterfv);
+ SET_GetTexLevelParameteriv(table, exec_GetTexLevelParameteriv);
+ SET_GetTexParameterfv(table, exec_GetTexParameterfv);
+ SET_GetTexParameteriv(table, exec_GetTexParameteriv);
+ SET_Hint(table, save_Hint);
+ SET_IndexMask(table, save_IndexMask);
+ SET_InitNames(table, save_InitNames);
+ SET_IsEnabled(table, exec_IsEnabled);
+ SET_IsList(table, _mesa_IsList);
+ SET_LightModelf(table, save_LightModelf);
+ SET_LightModelfv(table, save_LightModelfv);
+ SET_LightModeli(table, save_LightModeli);
+ SET_LightModeliv(table, save_LightModeliv);
+ SET_Lightf(table, save_Lightf);
+ SET_Lightfv(table, save_Lightfv);
+ SET_Lighti(table, save_Lighti);
+ SET_Lightiv(table, save_Lightiv);
+ SET_LineStipple(table, save_LineStipple);
+ SET_LineWidth(table, save_LineWidth);
+ SET_ListBase(table, save_ListBase);
+ SET_LoadIdentity(table, save_LoadIdentity);
+ SET_LoadMatrixd(table, save_LoadMatrixd);
+ SET_LoadMatrixf(table, save_LoadMatrixf);
+ SET_LoadName(table, save_LoadName);
+ SET_LogicOp(table, save_LogicOp);
+ SET_Map1d(table, save_Map1d);
+ SET_Map1f(table, save_Map1f);
+ SET_Map2d(table, save_Map2d);
+ SET_Map2f(table, save_Map2f);
+ SET_MapGrid1d(table, save_MapGrid1d);
+ SET_MapGrid1f(table, save_MapGrid1f);
+ SET_MapGrid2d(table, save_MapGrid2d);
+ SET_MapGrid2f(table, save_MapGrid2f);
+ SET_MatrixMode(table, save_MatrixMode);
+ SET_MultMatrixd(table, save_MultMatrixd);
+ SET_MultMatrixf(table, save_MultMatrixf);
+ SET_NewList(table, save_NewList);
+ SET_Ortho(table, save_Ortho);
+ SET_PassThrough(table, save_PassThrough);
+ SET_PixelMapfv(table, save_PixelMapfv);
+ SET_PixelMapuiv(table, save_PixelMapuiv);
+ SET_PixelMapusv(table, save_PixelMapusv);
+ SET_PixelStoref(table, exec_PixelStoref);
+ SET_PixelStorei(table, exec_PixelStorei);
+ SET_PixelTransferf(table, save_PixelTransferf);
+ SET_PixelTransferi(table, save_PixelTransferi);
+ SET_PixelZoom(table, save_PixelZoom);
+ SET_PointSize(table, save_PointSize);
+ SET_PolygonMode(table, save_PolygonMode);
+ SET_PolygonOffset(table, save_PolygonOffset);
+ SET_PolygonStipple(table, save_PolygonStipple);
+ SET_PopAttrib(table, save_PopAttrib);
+ SET_PopMatrix(table, save_PopMatrix);
+ SET_PopName(table, save_PopName);
+ SET_PushAttrib(table, save_PushAttrib);
+ SET_PushMatrix(table, save_PushMatrix);
+ SET_PushName(table, save_PushName);
+ SET_RasterPos2d(table, save_RasterPos2d);
+ SET_RasterPos2dv(table, save_RasterPos2dv);
+ SET_RasterPos2f(table, save_RasterPos2f);
+ SET_RasterPos2fv(table, save_RasterPos2fv);
+ SET_RasterPos2i(table, save_RasterPos2i);
+ SET_RasterPos2iv(table, save_RasterPos2iv);
+ SET_RasterPos2s(table, save_RasterPos2s);
+ SET_RasterPos2sv(table, save_RasterPos2sv);
+ SET_RasterPos3d(table, save_RasterPos3d);
+ SET_RasterPos3dv(table, save_RasterPos3dv);
+ SET_RasterPos3f(table, save_RasterPos3f);
+ SET_RasterPos3fv(table, save_RasterPos3fv);
+ SET_RasterPos3i(table, save_RasterPos3i);
+ SET_RasterPos3iv(table, save_RasterPos3iv);
+ SET_RasterPos3s(table, save_RasterPos3s);
+ SET_RasterPos3sv(table, save_RasterPos3sv);
+ SET_RasterPos4d(table, save_RasterPos4d);
+ SET_RasterPos4dv(table, save_RasterPos4dv);
+ SET_RasterPos4f(table, save_RasterPos4f);
+ SET_RasterPos4fv(table, save_RasterPos4fv);
+ SET_RasterPos4i(table, save_RasterPos4i);
+ SET_RasterPos4iv(table, save_RasterPos4iv);
+ SET_RasterPos4s(table, save_RasterPos4s);
+ SET_RasterPos4sv(table, save_RasterPos4sv);
+ SET_ReadBuffer(table, save_ReadBuffer);
+ SET_ReadPixels(table, exec_ReadPixels);
+ SET_RenderMode(table, exec_RenderMode);
+ SET_Rotated(table, save_Rotated);
+ SET_Rotatef(table, save_Rotatef);
+ SET_Scaled(table, save_Scaled);
+ SET_Scalef(table, save_Scalef);
+ SET_Scissor(table, save_Scissor);
+ SET_FeedbackBuffer(table, exec_FeedbackBuffer);
+ SET_SelectBuffer(table, exec_SelectBuffer);
+ SET_ShadeModel(table, save_ShadeModel);
+ SET_StencilFunc(table, save_StencilFunc);
+ SET_StencilMask(table, save_StencilMask);
+ SET_StencilOp(table, save_StencilOp);
+ SET_TexEnvf(table, save_TexEnvf);
+ SET_TexEnvfv(table, save_TexEnvfv);
+ SET_TexEnvi(table, save_TexEnvi);
+ SET_TexEnviv(table, save_TexEnviv);
+ SET_TexGend(table, save_TexGend);
+ SET_TexGendv(table, save_TexGendv);
+ SET_TexGenf(table, save_TexGenf);
+ SET_TexGenfv(table, save_TexGenfv);
+ SET_TexGeni(table, save_TexGeni);
+ SET_TexGeniv(table, save_TexGeniv);
+ SET_TexImage1D(table, save_TexImage1D);
+ SET_TexImage2D(table, save_TexImage2D);
+ SET_TexParameterf(table, save_TexParameterf);
+ SET_TexParameterfv(table, save_TexParameterfv);
+ SET_TexParameteri(table, save_TexParameteri);
+ SET_TexParameteriv(table, save_TexParameteriv);
+ SET_Translated(table, save_Translated);
+ SET_Translatef(table, save_Translatef);
+ SET_Viewport(table, save_Viewport);
+
+ /* GL 1.1 */
+ SET_AreTexturesResident(table, exec_AreTexturesResident);
+ SET_BindTexture(table, save_BindTexture);
+ SET_ColorPointer(table, exec_ColorPointer);
+ SET_CopyTexImage1D(table, save_CopyTexImage1D);
+ SET_CopyTexImage2D(table, save_CopyTexImage2D);
+ SET_CopyTexSubImage1D(table, save_CopyTexSubImage1D);
+ SET_CopyTexSubImage2D(table, save_CopyTexSubImage2D);
+ SET_DeleteTextures(table, exec_DeleteTextures);
+ SET_DisableClientState(table, exec_DisableClientState);
+ SET_EdgeFlagPointer(table, exec_EdgeFlagPointer);
+ SET_EnableClientState(table, exec_EnableClientState);
+ SET_GenTextures(table, exec_GenTextures);
+ SET_GetPointerv(table, exec_GetPointerv);
+ SET_IndexPointer(table, exec_IndexPointer);
+ SET_InterleavedArrays(table, exec_InterleavedArrays);
+ SET_IsTexture(table, exec_IsTexture);
+ SET_NormalPointer(table, exec_NormalPointer);
+ SET_PopClientAttrib(table, exec_PopClientAttrib);
+ SET_PrioritizeTextures(table, save_PrioritizeTextures);
+ SET_PushClientAttrib(table, exec_PushClientAttrib);
+ SET_TexCoordPointer(table, exec_TexCoordPointer);
+ SET_TexSubImage1D(table, save_TexSubImage1D);
+ SET_TexSubImage2D(table, save_TexSubImage2D);
+ SET_VertexPointer(table, exec_VertexPointer);
+
+ /* GL 1.2 */
+ SET_CopyTexSubImage3D(table, save_CopyTexSubImage3D);
+ SET_TexImage3D(table, save_TexImage3D);
+ SET_TexSubImage3D(table, save_TexSubImage3D);
+
+ /* GL 2.0 */
+ SET_StencilFuncSeparate(table, save_StencilFuncSeparate);
+ SET_StencilMaskSeparate(table, save_StencilMaskSeparate);
+ SET_StencilOpSeparate(table, save_StencilOpSeparate);
+
+ /* ATI_separate_stencil */
+ SET_StencilFuncSeparateATI(table, save_StencilFuncSeparateATI);
+
+ /* GL_ARB_imaging */
+ /* Not all are supported */
+ SET_BlendColor(table, save_BlendColor);
+ SET_BlendEquation(table, save_BlendEquation);
+ SET_ColorSubTable(table, save_ColorSubTable);
+ SET_ColorTable(table, save_ColorTable);
+ SET_ColorTableParameterfv(table, save_ColorTableParameterfv);
+ SET_ColorTableParameteriv(table, save_ColorTableParameteriv);
+ SET_ConvolutionFilter1D(table, save_ConvolutionFilter1D);
+ SET_ConvolutionFilter2D(table, save_ConvolutionFilter2D);
+ SET_ConvolutionParameterf(table, save_ConvolutionParameterf);
+ SET_ConvolutionParameterfv(table, save_ConvolutionParameterfv);
+ SET_ConvolutionParameteri(table, save_ConvolutionParameteri);
+ SET_ConvolutionParameteriv(table, save_ConvolutionParameteriv);
+ SET_CopyColorSubTable(table, save_CopyColorSubTable);
+ SET_CopyColorTable(table, save_CopyColorTable);
+ SET_CopyConvolutionFilter1D(table, exec_CopyConvolutionFilter1D);
+ SET_CopyConvolutionFilter2D(table, exec_CopyConvolutionFilter2D);
+ SET_GetColorTable(table, exec_GetColorTable);
+ SET_GetColorTableParameterfv(table, exec_GetColorTableParameterfv);
+ SET_GetColorTableParameteriv(table, exec_GetColorTableParameteriv);
+ SET_GetConvolutionFilter(table, exec_GetConvolutionFilter);
+ SET_GetConvolutionParameterfv(table, exec_GetConvolutionParameterfv);
+ SET_GetConvolutionParameteriv(table, exec_GetConvolutionParameteriv);
+ SET_GetHistogram(table, exec_GetHistogram);
+ SET_GetHistogramParameterfv(table, exec_GetHistogramParameterfv);
+ SET_GetHistogramParameteriv(table, exec_GetHistogramParameteriv);
+ SET_GetMinmax(table, exec_GetMinmax);
+ SET_GetMinmaxParameterfv(table, exec_GetMinmaxParameterfv);
+ SET_GetMinmaxParameteriv(table, exec_GetMinmaxParameteriv);
+ SET_GetSeparableFilter(table, exec_GetSeparableFilter);
+ SET_Histogram(table, save_Histogram);
+ SET_Minmax(table, save_Minmax);
+ SET_ResetHistogram(table, save_ResetHistogram);
+ SET_ResetMinmax(table, save_ResetMinmax);
+ SET_SeparableFilter2D(table, exec_SeparableFilter2D);
+
+ /* 2. GL_EXT_blend_color */
+#if 0
+ SET_BlendColorEXT(table, save_BlendColorEXT);
+#endif
+
+ /* 3. GL_EXT_polygon_offset */
+ SET_PolygonOffsetEXT(table, save_PolygonOffsetEXT);
+
+ /* 6. GL_EXT_texture3d */
+#if 0
+ SET_CopyTexSubImage3DEXT(table, save_CopyTexSubImage3D);
+ SET_TexImage3DEXT(table, save_TexImage3DEXT);
+ SET_TexSubImage3DEXT(table, save_TexSubImage3D);
+#endif
+
+ /* 14. GL_SGI_color_table */
+#if 0
+ SET_ColorTableSGI(table, save_ColorTable);
+ SET_ColorSubTableSGI(table, save_ColorSubTable);
+ SET_GetColorTableSGI(table, exec_GetColorTable);
+ SET_GetColorTableParameterfvSGI(table, exec_GetColorTableParameterfv);
+ SET_GetColorTableParameterivSGI(table, exec_GetColorTableParameteriv);
+#endif
+
+ /* 30. GL_EXT_vertex_array */
+ SET_ColorPointerEXT(table, exec_ColorPointerEXT);
+ SET_EdgeFlagPointerEXT(table, exec_EdgeFlagPointerEXT);
+ SET_IndexPointerEXT(table, exec_IndexPointerEXT);
+ SET_NormalPointerEXT(table, exec_NormalPointerEXT);
+ SET_TexCoordPointerEXT(table, exec_TexCoordPointerEXT);
+ SET_VertexPointerEXT(table, exec_VertexPointerEXT);
+
+ /* 37. GL_EXT_blend_minmax */
+#if 0
+ SET_BlendEquationEXT(table, save_BlendEquationEXT);
+#endif
+
+ /* 54. GL_EXT_point_parameters */
+ SET_PointParameterfEXT(table, save_PointParameterfEXT);
+ SET_PointParameterfvEXT(table, save_PointParameterfvEXT);
+
+ /* 97. GL_EXT_compiled_vertex_array */
+ SET_LockArraysEXT(table, exec_LockArraysEXT);
+ SET_UnlockArraysEXT(table, exec_UnlockArraysEXT);
+
+ /* 145. GL_EXT_secondary_color */
+ SET_SecondaryColorPointerEXT(table, exec_SecondaryColorPointerEXT);
+
+ /* 148. GL_EXT_multi_draw_arrays */
+ SET_MultiDrawArraysEXT(table, exec_MultiDrawArraysEXT);
+
+ /* 149. GL_EXT_fog_coord */
+ SET_FogCoordPointerEXT(table, exec_FogCoordPointerEXT);
+
+ /* 173. GL_EXT_blend_func_separate */
+ SET_BlendFuncSeparateEXT(table, save_BlendFuncSeparateEXT);
+
+ /* 196. GL_MESA_resize_buffers */
+ SET_ResizeBuffersMESA(table, _mesa_ResizeBuffersMESA);
+
+ /* 197. GL_MESA_window_pos */
+ SET_WindowPos2dMESA(table, save_WindowPos2dMESA);
+ SET_WindowPos2dvMESA(table, save_WindowPos2dvMESA);
+ SET_WindowPos2fMESA(table, save_WindowPos2fMESA);
+ SET_WindowPos2fvMESA(table, save_WindowPos2fvMESA);
+ SET_WindowPos2iMESA(table, save_WindowPos2iMESA);
+ SET_WindowPos2ivMESA(table, save_WindowPos2ivMESA);
+ SET_WindowPos2sMESA(table, save_WindowPos2sMESA);
+ SET_WindowPos2svMESA(table, save_WindowPos2svMESA);
+ SET_WindowPos3dMESA(table, save_WindowPos3dMESA);
+ SET_WindowPos3dvMESA(table, save_WindowPos3dvMESA);
+ SET_WindowPos3fMESA(table, save_WindowPos3fMESA);
+ SET_WindowPos3fvMESA(table, save_WindowPos3fvMESA);
+ SET_WindowPos3iMESA(table, save_WindowPos3iMESA);
+ SET_WindowPos3ivMESA(table, save_WindowPos3ivMESA);
+ SET_WindowPos3sMESA(table, save_WindowPos3sMESA);
+ SET_WindowPos3svMESA(table, save_WindowPos3svMESA);
+ SET_WindowPos4dMESA(table, save_WindowPos4dMESA);
+ SET_WindowPos4dvMESA(table, save_WindowPos4dvMESA);
+ SET_WindowPos4fMESA(table, save_WindowPos4fMESA);
+ SET_WindowPos4fvMESA(table, save_WindowPos4fvMESA);
+ SET_WindowPos4iMESA(table, save_WindowPos4iMESA);
+ SET_WindowPos4ivMESA(table, save_WindowPos4ivMESA);
+ SET_WindowPos4sMESA(table, save_WindowPos4sMESA);
+ SET_WindowPos4svMESA(table, save_WindowPos4svMESA);
+
+ /* 200. GL_IBM_multimode_draw_arrays */
+ SET_MultiModeDrawArraysIBM(table, exec_MultiModeDrawArraysIBM);
+ SET_MultiModeDrawElementsIBM(table, exec_MultiModeDrawElementsIBM);
+
+#if FEATURE_NV_vertex_program
+ /* 233. GL_NV_vertex_program */
+ /* The following commands DO NOT go into display lists:
+ * AreProgramsResidentNV, IsProgramNV, GenProgramsNV, DeleteProgramsNV,
+ * VertexAttribPointerNV, GetProgram*, GetVertexAttrib*
+ */
+ SET_BindProgramNV(table, save_BindProgramNV);
+ SET_DeleteProgramsNV(table, _mesa_DeletePrograms);
+ SET_ExecuteProgramNV(table, save_ExecuteProgramNV);
+ SET_GenProgramsNV(table, _mesa_GenPrograms);
+ SET_AreProgramsResidentNV(table, _mesa_AreProgramsResidentNV);
+ SET_RequestResidentProgramsNV(table, save_RequestResidentProgramsNV);
+ SET_GetProgramParameterfvNV(table, _mesa_GetProgramParameterfvNV);
+ SET_GetProgramParameterdvNV(table, _mesa_GetProgramParameterdvNV);
+ SET_GetProgramivNV(table, _mesa_GetProgramivNV);
+ SET_GetProgramStringNV(table, _mesa_GetProgramStringNV);
+ SET_GetTrackMatrixivNV(table, _mesa_GetTrackMatrixivNV);
+ SET_GetVertexAttribdvNV(table, _mesa_GetVertexAttribdvNV);
+ SET_GetVertexAttribfvNV(table, _mesa_GetVertexAttribfvNV);
+ SET_GetVertexAttribivNV(table, _mesa_GetVertexAttribivNV);
+ SET_GetVertexAttribPointervNV(table, _mesa_GetVertexAttribPointervNV);
+ SET_IsProgramNV(table, _mesa_IsProgramARB);
+ SET_LoadProgramNV(table, save_LoadProgramNV);
+ SET_ProgramEnvParameter4dARB(table, save_ProgramEnvParameter4dARB);
+ SET_ProgramEnvParameter4dvARB(table, save_ProgramEnvParameter4dvARB);
+ SET_ProgramEnvParameter4fARB(table, save_ProgramEnvParameter4fARB);
+ SET_ProgramEnvParameter4fvARB(table, save_ProgramEnvParameter4fvARB);
+ SET_ProgramParameters4dvNV(table, save_ProgramParameters4dvNV);
+ SET_ProgramParameters4fvNV(table, save_ProgramParameters4fvNV);
+ SET_TrackMatrixNV(table, save_TrackMatrixNV);
+ SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV);
+#endif
+
+ /* 244. GL_ATI_envmap_bumpmap */
+ SET_TexBumpParameterivATI(table, save_TexBumpParameterivATI);
+ SET_TexBumpParameterfvATI(table, save_TexBumpParameterfvATI);
+
+ /* 245. GL_ATI_fragment_shader */
+#if FEATURE_ATI_fragment_shader
+ SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI);
+ SET_SetFragmentShaderConstantATI(table, save_SetFragmentShaderConstantATI);
+#endif
+
+ /* 282. GL_NV_fragment_program */
+#if FEATURE_NV_fragment_program
+ SET_ProgramNamedParameter4fNV(table, save_ProgramNamedParameter4fNV);
+ SET_ProgramNamedParameter4dNV(table, save_ProgramNamedParameter4dNV);
+ SET_ProgramNamedParameter4fvNV(table, save_ProgramNamedParameter4fvNV);
+ SET_ProgramNamedParameter4dvNV(table, save_ProgramNamedParameter4dvNV);
+ SET_GetProgramNamedParameterfvNV(table,
+ _mesa_GetProgramNamedParameterfvNV);
+ SET_GetProgramNamedParameterdvNV(table,
+ _mesa_GetProgramNamedParameterdvNV);
+ SET_ProgramLocalParameter4dARB(table, save_ProgramLocalParameter4dARB);
+ SET_ProgramLocalParameter4dvARB(table, save_ProgramLocalParameter4dvARB);
+ SET_ProgramLocalParameter4fARB(table, save_ProgramLocalParameter4fARB);
+ SET_ProgramLocalParameter4fvARB(table, save_ProgramLocalParameter4fvARB);
+ SET_GetProgramLocalParameterdvARB(table,
+ _mesa_GetProgramLocalParameterdvARB);
+ SET_GetProgramLocalParameterfvARB(table,
+ _mesa_GetProgramLocalParameterfvARB);
+#endif
+
+ /* 262. GL_NV_point_sprite */
+ SET_PointParameteriNV(table, save_PointParameteriNV);
+ SET_PointParameterivNV(table, save_PointParameterivNV);
+
+ /* 268. GL_EXT_stencil_two_side */
+ SET_ActiveStencilFaceEXT(table, save_ActiveStencilFaceEXT);
+
+ /* 273. GL_APPLE_vertex_array_object */
+ SET_BindVertexArrayAPPLE(table, _mesa_BindVertexArrayAPPLE);
+ SET_DeleteVertexArraysAPPLE(table, _mesa_DeleteVertexArraysAPPLE);
+ SET_GenVertexArraysAPPLE(table, _mesa_GenVertexArraysAPPLE);
+ SET_IsVertexArrayAPPLE(table, _mesa_IsVertexArrayAPPLE);
+
+ /* ???. GL_EXT_depth_bounds_test */
+ SET_DepthBoundsEXT(table, save_DepthBoundsEXT);
+
+ /* ARB 1. GL_ARB_multitexture */
+ SET_ActiveTextureARB(table, save_ActiveTextureARB);
+ SET_ClientActiveTextureARB(table, exec_ClientActiveTextureARB);
+
+ /* ARB 3. GL_ARB_transpose_matrix */
+ SET_LoadTransposeMatrixdARB(table, save_LoadTransposeMatrixdARB);
+ SET_LoadTransposeMatrixfARB(table, save_LoadTransposeMatrixfARB);
+ SET_MultTransposeMatrixdARB(table, save_MultTransposeMatrixdARB);
+ SET_MultTransposeMatrixfARB(table, save_MultTransposeMatrixfARB);
+
+ /* ARB 5. GL_ARB_multisample */
+ SET_SampleCoverageARB(table, save_SampleCoverageARB);
+
+ /* ARB 12. GL_ARB_texture_compression */
+ SET_CompressedTexImage3DARB(table, save_CompressedTexImage3DARB);
+ SET_CompressedTexImage2DARB(table, save_CompressedTexImage2DARB);
+ SET_CompressedTexImage1DARB(table, save_CompressedTexImage1DARB);
+ SET_CompressedTexSubImage3DARB(table, save_CompressedTexSubImage3DARB);
+ SET_CompressedTexSubImage2DARB(table, save_CompressedTexSubImage2DARB);
+ SET_CompressedTexSubImage1DARB(table, save_CompressedTexSubImage1DARB);
+ SET_GetCompressedTexImageARB(table, exec_GetCompressedTexImageARB);
+
+ /* ARB 14. GL_ARB_point_parameters */
+ /* aliased with EXT_point_parameters functions */
+
+ /* ARB 25. GL_ARB_window_pos */
+ /* aliased with MESA_window_pos functions */
+
+ /* ARB 26. GL_ARB_vertex_program */
+ /* ARB 27. GL_ARB_fragment_program */
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ /* glVertexAttrib* functions alias the NV ones, handled elsewhere */
+ SET_VertexAttribPointerARB(table, _mesa_VertexAttribPointerARB);
+ SET_EnableVertexAttribArrayARB(table, _mesa_EnableVertexAttribArrayARB);
+ SET_DisableVertexAttribArrayARB(table, _mesa_DisableVertexAttribArrayARB);
+ SET_ProgramStringARB(table, save_ProgramStringARB);
+ SET_BindProgramNV(table, save_BindProgramNV);
+ SET_DeleteProgramsNV(table, _mesa_DeletePrograms);
+ SET_GenProgramsNV(table, _mesa_GenPrograms);
+ SET_IsProgramNV(table, _mesa_IsProgramARB);
+ SET_GetVertexAttribdvNV(table, _mesa_GetVertexAttribdvNV);
+ SET_GetVertexAttribfvNV(table, _mesa_GetVertexAttribfvNV);
+ SET_GetVertexAttribivNV(table, _mesa_GetVertexAttribivNV);
+ SET_GetVertexAttribPointervNV(table, _mesa_GetVertexAttribPointervNV);
+ SET_ProgramEnvParameter4dARB(table, save_ProgramEnvParameter4dARB);
+ SET_ProgramEnvParameter4dvARB(table, save_ProgramEnvParameter4dvARB);
+ SET_ProgramEnvParameter4fARB(table, save_ProgramEnvParameter4fARB);
+ SET_ProgramEnvParameter4fvARB(table, save_ProgramEnvParameter4fvARB);
+ SET_ProgramLocalParameter4dARB(table, save_ProgramLocalParameter4dARB);
+ SET_ProgramLocalParameter4dvARB(table, save_ProgramLocalParameter4dvARB);
+ SET_ProgramLocalParameter4fARB(table, save_ProgramLocalParameter4fARB);
+ SET_ProgramLocalParameter4fvARB(table, save_ProgramLocalParameter4fvARB);
+ SET_GetProgramEnvParameterdvARB(table, _mesa_GetProgramEnvParameterdvARB);
+ SET_GetProgramEnvParameterfvARB(table, _mesa_GetProgramEnvParameterfvARB);
+ SET_GetProgramLocalParameterdvARB(table,
+ _mesa_GetProgramLocalParameterdvARB);
+ SET_GetProgramLocalParameterfvARB(table,
+ _mesa_GetProgramLocalParameterfvARB);
+ SET_GetProgramivARB(table, _mesa_GetProgramivARB);
+ SET_GetProgramStringARB(table, _mesa_GetProgramStringARB);
+#endif
+
+ /* ARB 28. GL_ARB_vertex_buffer_object */
+#if FEATURE_ARB_vertex_buffer_object
+ /* None of the extension's functions get compiled */
+ SET_BindBufferARB(table, _mesa_BindBufferARB);
+ SET_BufferDataARB(table, _mesa_BufferDataARB);
+ SET_BufferSubDataARB(table, _mesa_BufferSubDataARB);
+ SET_DeleteBuffersARB(table, _mesa_DeleteBuffersARB);
+ SET_GenBuffersARB(table, _mesa_GenBuffersARB);
+ SET_GetBufferParameterivARB(table, _mesa_GetBufferParameterivARB);
+ SET_GetBufferPointervARB(table, _mesa_GetBufferPointervARB);
+ SET_GetBufferSubDataARB(table, _mesa_GetBufferSubDataARB);
+ SET_IsBufferARB(table, _mesa_IsBufferARB);
+ SET_MapBufferARB(table, _mesa_MapBufferARB);
+ SET_UnmapBufferARB(table, _mesa_UnmapBufferARB);
+#endif
+
+#if FEATURE_ARB_occlusion_query
+ SET_BeginQueryARB(table, save_BeginQueryARB);
+ SET_EndQueryARB(table, save_EndQueryARB);
+ SET_GenQueriesARB(table, _mesa_GenQueriesARB);
+ SET_DeleteQueriesARB(table, _mesa_DeleteQueriesARB);
+ SET_IsQueryARB(table, _mesa_IsQueryARB);
+ SET_GetQueryivARB(table, _mesa_GetQueryivARB);
+ SET_GetQueryObjectivARB(table, _mesa_GetQueryObjectivARB);
+ SET_GetQueryObjectuivARB(table, _mesa_GetQueryObjectuivARB);
+#endif
+ SET_DrawBuffersARB(table, save_DrawBuffersARB);
+
+#if FEATURE_EXT_framebuffer_blit
+ SET_BlitFramebufferEXT(table, save_BlitFramebufferEXT);
+#endif
+
+ /* GL_ARB_shader_objects */
+ SET_UseProgramObjectARB(table, save_UseProgramObjectARB);
+ SET_Uniform1fARB(table, save_Uniform1fARB);
+ SET_Uniform2fARB(table, save_Uniform2fARB);
+ SET_Uniform3fARB(table, save_Uniform3fARB);
+ SET_Uniform4fARB(table, save_Uniform4fARB);
+ SET_Uniform1fvARB(table, save_Uniform1fvARB);
+ SET_Uniform2fvARB(table, save_Uniform2fvARB);
+ SET_Uniform3fvARB(table, save_Uniform3fvARB);
+ SET_Uniform4fvARB(table, save_Uniform4fvARB);
+ SET_Uniform1iARB(table, save_Uniform1iARB);
+ SET_Uniform2iARB(table, save_Uniform2iARB);
+ SET_Uniform3iARB(table, save_Uniform3iARB);
+ SET_Uniform4iARB(table, save_Uniform4iARB);
+ SET_Uniform1ivARB(table, save_Uniform1ivARB);
+ SET_Uniform2ivARB(table, save_Uniform2ivARB);
+ SET_Uniform3ivARB(table, save_Uniform3ivARB);
+ SET_Uniform4ivARB(table, save_Uniform4ivARB);
+ SET_UniformMatrix2fvARB(table, save_UniformMatrix2fvARB);
+ SET_UniformMatrix3fvARB(table, save_UniformMatrix3fvARB);
+ SET_UniformMatrix4fvARB(table, save_UniformMatrix4fvARB);
+ SET_UniformMatrix2x3fv(table, save_UniformMatrix2x3fv);
+ SET_UniformMatrix3x2fv(table, save_UniformMatrix3x2fv);
+ SET_UniformMatrix2x4fv(table, save_UniformMatrix2x4fv);
+ SET_UniformMatrix4x2fv(table, save_UniformMatrix4x2fv);
+ SET_UniformMatrix3x4fv(table, save_UniformMatrix3x4fv);
+ SET_UniformMatrix4x3fv(table, save_UniformMatrix4x3fv);
+
+ /* ARB 30/31/32. GL_ARB_shader_objects, GL_ARB_vertex/fragment_shader */
+ SET_BindAttribLocationARB(table, exec_BindAttribLocationARB);
+ SET_GetAttribLocationARB(table, exec_GetAttribLocationARB);
+ /* XXX additional functions need to be implemented here! */
+
+ /* 299. GL_EXT_blend_equation_separate */
+ SET_BlendEquationSeparateEXT(table, save_BlendEquationSeparateEXT);
+
+ /* GL_EXT_gpu_program_parmaeters */
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ SET_ProgramEnvParameters4fvEXT(table, save_ProgramEnvParameters4fvEXT);
+ SET_ProgramLocalParameters4fvEXT(table, save_ProgramLocalParameters4fvEXT);
+#endif
+
+ /* ARB 50. GL_ARB_map_buffer_range */
+#if FEATURE_ARB_map_buffer_range
+ SET_MapBufferRange(table, _mesa_MapBufferRange); /* no dlist save */
+ SET_FlushMappedBufferRange(table, _mesa_FlushMappedBufferRange); /* no dl */
+#endif
+
+ /* ARB 59. GL_ARB_copy_buffer */
+ SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */
+
+ /* 364. GL_EXT_provoking_vertex */
+ SET_ProvokingVertexEXT(table, save_ProvokingVertexEXT);
+}
+
+
+
+static const char *
+enum_string(GLenum k)
+{
+ return _mesa_lookup_enum_by_nr(k);
+}
+
+
+/**
+ * Print the commands in a display list. For debugging only.
+ * TODO: many commands aren't handled yet.
+ */
+static void GLAPIENTRY
+print_list(GLcontext *ctx, GLuint list)
+{
+ struct gl_display_list *dlist;
+ Node *n;
+ GLboolean done;
+
+ if (!islist(ctx, list)) {
+ _mesa_printf("%u is not a display list ID\n", list);
+ return;
+ }
+
+ dlist = lookup_list(ctx, list);
+ if (!dlist)
+ return;
+
+ n = dlist->Head;
+
+ _mesa_printf("START-LIST %u, address %p\n", list, (void *) n);
+
+ done = n ? GL_FALSE : GL_TRUE;
+ while (!done) {
+ OpCode opcode = n[0].opcode;
+ GLint i = (GLint) n[0].opcode - (GLint) OPCODE_EXT_0;
+
+ if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) {
+ /* this is a driver-extended opcode */
+ ctx->ListExt.Opcode[i].Print(ctx, &n[1]);
+ n += ctx->ListExt.Opcode[i].Size;
+ }
+ else {
+ switch (opcode) {
+ case OPCODE_ACCUM:
+ _mesa_printf("Accum %s %g\n", enum_string(n[1].e), n[2].f);
+ break;
+ case OPCODE_BITMAP:
+ _mesa_printf("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:
+ _mesa_printf("CallList %d\n", (int) n[1].ui);
+ break;
+ case OPCODE_CALL_LIST_OFFSET:
+ _mesa_printf("CallList %d + offset %u = %u\n", (int) n[1].ui,
+ ctx->List.ListBase, ctx->List.ListBase + n[1].ui);
+ break;
+ case OPCODE_COLOR_TABLE_PARAMETER_FV:
+ _mesa_printf("ColorTableParameterfv %s %s %f %f %f %f\n",
+ enum_string(n[1].e), enum_string(n[2].e),
+ n[3].f, n[4].f, n[5].f, n[6].f);
+ break;
+ case OPCODE_COLOR_TABLE_PARAMETER_IV:
+ _mesa_printf("ColorTableParameteriv %s %s %d %d %d %d\n",
+ enum_string(n[1].e), enum_string(n[2].e),
+ n[3].i, n[4].i, n[5].i, n[6].i);
+ break;
+ case OPCODE_DISABLE:
+ _mesa_printf("Disable %s\n", enum_string(n[1].e));
+ break;
+ case OPCODE_ENABLE:
+ _mesa_printf("Enable %s\n", enum_string(n[1].e));
+ break;
+ case OPCODE_FRUSTUM:
+ _mesa_printf("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:
+ _mesa_printf("LineStipple %d %x\n", n[1].i, (int) n[2].us);
+ break;
+ case OPCODE_LOAD_IDENTITY:
+ _mesa_printf("LoadIdentity\n");
+ break;
+ case OPCODE_LOAD_MATRIX:
+ _mesa_printf("LoadMatrix\n");
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[1].f, n[5].f, n[9].f, n[13].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[2].f, n[6].f, n[10].f, n[14].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[3].f, n[7].f, n[11].f, n[15].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[4].f, n[8].f, n[12].f, n[16].f);
+ break;
+ case OPCODE_MULT_MATRIX:
+ _mesa_printf("MultMatrix (or Rotate)\n");
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[1].f, n[5].f, n[9].f, n[13].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[2].f, n[6].f, n[10].f, n[14].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[3].f, n[7].f, n[11].f, n[15].f);
+ _mesa_printf(" %8f %8f %8f %8f\n",
+ n[4].f, n[8].f, n[12].f, n[16].f);
+ break;
+ case OPCODE_ORTHO:
+ _mesa_printf("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:
+ _mesa_printf("PopAttrib\n");
+ break;
+ case OPCODE_POP_MATRIX:
+ _mesa_printf("PopMatrix\n");
+ break;
+ case OPCODE_POP_NAME:
+ _mesa_printf("PopName\n");
+ break;
+ case OPCODE_PUSH_ATTRIB:
+ _mesa_printf("PushAttrib %x\n", n[1].bf);
+ break;
+ case OPCODE_PUSH_MATRIX:
+ _mesa_printf("PushMatrix\n");
+ break;
+ case OPCODE_PUSH_NAME:
+ _mesa_printf("PushName %d\n", (int) n[1].ui);
+ break;
+ case OPCODE_RASTER_POS:
+ _mesa_printf("RasterPos %g %g %g %g\n",
+ n[1].f, n[2].f, n[3].f, n[4].f);
+ break;
+ case OPCODE_ROTATE:
+ _mesa_printf("Rotate %g %g %g %g\n",
+ n[1].f, n[2].f, n[3].f, n[4].f);
+ break;
+ case OPCODE_SCALE:
+ _mesa_printf("Scale %g %g %g\n", n[1].f, n[2].f, n[3].f);
+ break;
+ case OPCODE_TRANSLATE:
+ _mesa_printf("Translate %g %g %g\n", n[1].f, n[2].f, n[3].f);
+ break;
+ case OPCODE_BIND_TEXTURE:
+ _mesa_printf("BindTexture %s %d\n",
+ _mesa_lookup_enum_by_nr(n[1].ui), n[2].ui);
+ break;
+ case OPCODE_SHADE_MODEL:
+ _mesa_printf("ShadeModel %s\n", _mesa_lookup_enum_by_nr(n[1].ui));
+ break;
+ case OPCODE_MAP1:
+ _mesa_printf("Map1 %s %.3f %.3f %d %d\n",
+ _mesa_lookup_enum_by_nr(n[1].ui),
+ n[2].f, n[3].f, n[4].i, n[5].i);
+ break;
+ case OPCODE_MAP2:
+ _mesa_printf("Map2 %s %.3f %.3f %.3f %.3f %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(n[1].ui),
+ n[2].f, n[3].f, n[4].f, n[5].f,
+ n[6].i, n[7].i, n[8].i, n[9].i);
+ break;
+ case OPCODE_MAPGRID1:
+ _mesa_printf("MapGrid1 %d %.3f %.3f\n", n[1].i, n[2].f, n[3].f);
+ break;
+ case OPCODE_MAPGRID2:
+ _mesa_printf("MapGrid2 %d %.3f %.3f, %d %.3f %.3f\n",
+ n[1].i, n[2].f, n[3].f, n[4].i, n[5].f, n[6].f);
+ break;
+ case OPCODE_EVALMESH1:
+ _mesa_printf("EvalMesh1 %d %d\n", n[1].i, n[2].i);
+ break;
+ case OPCODE_EVALMESH2:
+ _mesa_printf("EvalMesh2 %d %d %d %d\n",
+ n[1].i, n[2].i, n[3].i, n[4].i);
+ break;
+
+ case OPCODE_ATTR_1F_NV:
+ _mesa_printf("ATTR_1F_NV attr %d: %f\n", n[1].i, n[2].f);
+ break;
+ case OPCODE_ATTR_2F_NV:
+ _mesa_printf("ATTR_2F_NV attr %d: %f %f\n",
+ n[1].i, n[2].f, n[3].f);
+ break;
+ case OPCODE_ATTR_3F_NV:
+ _mesa_printf("ATTR_3F_NV attr %d: %f %f %f\n",
+ n[1].i, n[2].f, n[3].f, n[4].f);
+ break;
+ case OPCODE_ATTR_4F_NV:
+ _mesa_printf("ATTR_4F_NV attr %d: %f %f %f %f\n",
+ n[1].i, n[2].f, n[3].f, n[4].f, n[5].f);
+ break;
+ case OPCODE_ATTR_1F_ARB:
+ _mesa_printf("ATTR_1F_ARB attr %d: %f\n", n[1].i, n[2].f);
+ break;
+ case OPCODE_ATTR_2F_ARB:
+ _mesa_printf("ATTR_2F_ARB attr %d: %f %f\n",
+ n[1].i, n[2].f, n[3].f);
+ break;
+ case OPCODE_ATTR_3F_ARB:
+ _mesa_printf("ATTR_3F_ARB attr %d: %f %f %f\n",
+ n[1].i, n[2].f, n[3].f, n[4].f);
+ break;
+ case OPCODE_ATTR_4F_ARB:
+ _mesa_printf("ATTR_4F_ARB attr %d: %f %f %f %f\n",
+ n[1].i, n[2].f, n[3].f, n[4].f, n[5].f);
+ break;
+
+ case OPCODE_MATERIAL:
+ _mesa_printf("MATERIAL %x %x: %f %f %f %f\n",
+ n[1].i, n[2].i, n[3].f, n[4].f, n[5].f, n[6].f);
+ break;
+ case OPCODE_BEGIN:
+ _mesa_printf("BEGIN %x\n", n[1].i);
+ break;
+ case OPCODE_END:
+ _mesa_printf("END\n");
+ break;
+ case OPCODE_RECTF:
+ _mesa_printf("RECTF %f %f %f %f\n", n[1].f, n[2].f, n[3].f,
+ n[4].f);
+ break;
+ case OPCODE_EVAL_C1:
+ _mesa_printf("EVAL_C1 %f\n", n[1].f);
+ break;
+ case OPCODE_EVAL_C2:
+ _mesa_printf("EVAL_C2 %f %f\n", n[1].f, n[2].f);
+ break;
+ case OPCODE_EVAL_P1:
+ _mesa_printf("EVAL_P1 %d\n", n[1].i);
+ break;
+ case OPCODE_EVAL_P2:
+ _mesa_printf("EVAL_P2 %d %d\n", n[1].i, n[2].i);
+ break;
+
+ case OPCODE_PROVOKING_VERTEX:
+ _mesa_printf("ProvokingVertex %s\n",
+ _mesa_lookup_enum_by_nr(n[1].ui));
+ break;
+
+ /*
+ * meta opcodes/commands
+ */
+ case OPCODE_ERROR:
+ _mesa_printf("Error: %s %s\n",
+ enum_string(n[1].e), (const char *) n[2].data);
+ break;
+ case OPCODE_CONTINUE:
+ _mesa_printf("DISPLAY-LIST-CONTINUE\n");
+ n = (Node *) n[1].next;
+ break;
+ case OPCODE_END_OF_LIST:
+ _mesa_printf("END-LIST %u\n", list);
+ done = GL_TRUE;
+ break;
+ default:
+ if (opcode < 0 || opcode > OPCODE_END_OF_LIST) {
+ _mesa_printf
+ ("ERROR IN DISPLAY LIST: opcode = %d, address = %p\n",
+ opcode, (void *) n);
+ return;
+ }
+ else {
+ _mesa_printf("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_CURRENT_CONTEXT(ctx);
+ print_list(ctx, list);
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+void
+_mesa_save_vtxfmt_init(GLvertexformat * vfmt)
+{
+ vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ vfmt->Begin = save_Begin;
+ vfmt->CallList = _mesa_save_CallList;
+ vfmt->CallLists = _mesa_save_CallLists;
+ vfmt->Color3f = save_Color3f;
+ vfmt->Color3fv = save_Color3fv;
+ vfmt->Color4f = save_Color4f;
+ vfmt->Color4fv = save_Color4fv;
+ vfmt->EdgeFlag = save_EdgeFlag;
+ vfmt->End = save_End;
+ vfmt->EvalCoord1f = save_EvalCoord1f;
+ vfmt->EvalCoord1fv = save_EvalCoord1fv;
+ vfmt->EvalCoord2f = save_EvalCoord2f;
+ vfmt->EvalCoord2fv = save_EvalCoord2fv;
+ vfmt->EvalPoint1 = save_EvalPoint1;
+ vfmt->EvalPoint2 = save_EvalPoint2;
+ vfmt->FogCoordfEXT = save_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = save_FogCoordfvEXT;
+ vfmt->Indexf = save_Indexf;
+ vfmt->Indexfv = save_Indexfv;
+ vfmt->Materialfv = save_Materialfv;
+ vfmt->MultiTexCoord1fARB = save_MultiTexCoord1f;
+ vfmt->MultiTexCoord1fvARB = save_MultiTexCoord1fv;
+ vfmt->MultiTexCoord2fARB = save_MultiTexCoord2f;
+ vfmt->MultiTexCoord2fvARB = save_MultiTexCoord2fv;
+ vfmt->MultiTexCoord3fARB = save_MultiTexCoord3f;
+ vfmt->MultiTexCoord3fvARB = save_MultiTexCoord3fv;
+ vfmt->MultiTexCoord4fARB = save_MultiTexCoord4f;
+ vfmt->MultiTexCoord4fvARB = save_MultiTexCoord4fv;
+ vfmt->Normal3f = save_Normal3f;
+ vfmt->Normal3fv = save_Normal3fv;
+ vfmt->SecondaryColor3fEXT = save_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = save_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = save_TexCoord1f;
+ vfmt->TexCoord1fv = save_TexCoord1fv;
+ vfmt->TexCoord2f = save_TexCoord2f;
+ vfmt->TexCoord2fv = save_TexCoord2fv;
+ vfmt->TexCoord3f = save_TexCoord3f;
+ vfmt->TexCoord3fv = save_TexCoord3fv;
+ vfmt->TexCoord4f = save_TexCoord4f;
+ vfmt->TexCoord4fv = save_TexCoord4fv;
+ vfmt->Vertex2f = save_Vertex2f;
+ vfmt->Vertex2fv = save_Vertex2fv;
+ vfmt->Vertex3f = save_Vertex3f;
+ vfmt->Vertex3fv = save_Vertex3fv;
+ vfmt->Vertex4f = save_Vertex4f;
+ vfmt->Vertex4fv = save_Vertex4fv;
+ vfmt->VertexAttrib1fNV = save_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = save_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = save_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = save_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = save_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = save_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = save_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = save_VertexAttrib4fvNV;
+ vfmt->VertexAttrib1fARB = save_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = save_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = save_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = save_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = save_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = save_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = save_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = save_VertexAttrib4fvARB;
+
+ vfmt->EvalMesh1 = _mesa_save_EvalMesh1;
+ vfmt->EvalMesh2 = _mesa_save_EvalMesh2;
+ vfmt->Rectf = save_Rectf;
+
+ /* The driver is required to implement these as
+ * 1) They can probably do a better job.
+ * 2) A lot of new mechanisms would have to be added to this module
+ * to support it. That code would probably never get used,
+ * because of (1).
+ */
+#if 0
+ vfmt->DrawArrays = 0;
+ vfmt->DrawElements = 0;
+ vfmt->DrawRangeElements = 0;
+ vfmt->MultiDrawElemementsEXT = 0;
+#endif
+}
+
+
+/**
+ * Initialize display list state for given context.
+ */
+void
+_mesa_init_display_list(GLcontext *ctx)
+{
+ static GLboolean tableInitialized = GL_FALSE;
+
+ /* zero-out the instruction size table, just once */
+ if (!tableInitialized) {
+ _mesa_bzero(InstSize, sizeof(InstSize));
+ tableInitialized = GL_TRUE;
+ }
+
+ /* Display list */
+ ctx->ListState.CallDepth = 0;
+ ctx->ExecuteFlag = GL_TRUE;
+ ctx->CompileFlag = GL_FALSE;
+ ctx->ListState.CurrentBlock = NULL;
+ ctx->ListState.CurrentPos = 0;
+
+ /* Display List group */
+ ctx->List.ListBase = 0;
+
+ _mesa_save_vtxfmt_init(&ctx->ListState.ListVtxfmt);
+}
diff --git a/mesalib/src/mesa/main/dlist.h b/mesalib/src/mesa/main/dlist.h
new file mode 100644
index 000000000..ab7ec2c8d
--- /dev/null
+++ b/mesalib/src/mesa/main/dlist.h
@@ -0,0 +1,96 @@
+/**
+ * \file dlist.h
+ * Display lists management.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+
+extern void
+_mesa_delete_list(GLcontext *ctx, struct gl_display_list *dlist);
+
+extern void GLAPIENTRY _mesa_CallList( GLuint list );
+
+extern void GLAPIENTRY _mesa_CallLists( GLsizei n, GLenum type, const GLvoid *lists );
+
+extern void GLAPIENTRY _mesa_DeleteLists( GLuint list, GLsizei range );
+
+extern void GLAPIENTRY _mesa_EndList( void );
+
+extern GLuint GLAPIENTRY _mesa_GenLists( GLsizei range );
+
+extern GLboolean GLAPIENTRY _mesa_IsList( GLuint list );
+
+extern void GLAPIENTRY _mesa_ListBase( GLuint base );
+
+extern void GLAPIENTRY _mesa_NewList( GLuint list, GLenum mode );
+
+extern void GLAPIENTRY _mesa_save_CallLists( GLsizei n, GLenum type, const GLvoid *lists );
+
+extern void GLAPIENTRY _mesa_save_CallList( GLuint list );
+
+
+
+extern void _mesa_init_dlist_table( struct _glapi_table *table );
+
+extern void _mesa_compile_error( GLcontext *ctx, GLenum error, const char *s );
+
+
+extern void *_mesa_alloc_instruction(GLcontext *ctx, GLuint opcode, GLuint sz);
+
+extern GLint _mesa_alloc_opcode( GLcontext *ctx, GLuint sz,
+ void (*execute)( GLcontext *, void * ),
+ void (*destroy)( GLcontext *, void * ),
+ void (*print)( GLcontext *, void * ) );
+
+extern void _mesa_init_display_list( GLcontext * ctx );
+
+extern void _mesa_save_vtxfmt_init( GLvertexformat *vfmt );
+
+
+#else
+
+/** No-op */
+#define _mesa_init_dlist_table(t,ts) ((void)0)
+
+/** No-op */
+#define _mesa_init_display_list(c) ((void)0)
+
+/** No-op */
+#define _mesa_save_vtxfmt_init(v) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/dlopen.c b/mesalib/src/mesa/main/dlopen.c
new file mode 100644
index 000000000..414cfad8e
--- /dev/null
+++ b/mesalib/src/mesa/main/dlopen.c
@@ -0,0 +1,101 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * Wrapper functions for dlopen(), dlsym(), dlclose().
+ * Note that the #ifdef tests for various environments should be expanded.
+ */
+
+
+#include "compiler.h"
+#include "dlopen.h"
+
+#if defined(_GNU_SOURCE) && !defined(__MINGW32__)
+#include <dlfcn.h>
+#endif
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+
+/**
+ * Wrapper for dlopen().
+ * Note that 'flags' isn't used at this time.
+ */
+void *
+_mesa_dlopen(const char *libname, int flags)
+{
+#if defined(_GNU_SOURCE)
+ flags = RTLD_LAZY | RTLD_GLOBAL; /* Overriding flags at this time */
+ return dlopen(libname, flags);
+#elif defined(__MINGW32__)
+ return LoadLibraryA(libname);
+#else
+ return NULL;
+#endif
+}
+
+
+/**
+ * Wrapper for dlsym() that does a cast to a generic function type,
+ * rather than a void *. This reduces the number of warnings that are
+ * generated.
+ */
+GenericFunc
+_mesa_dlsym(void *handle, const char *fname)
+{
+#if defined(__DJGPP__)
+ /* need '_' prefix on symbol names */
+ char fname2[1000];
+ fname2[0] = '_';
+ _mesa_strncpy(fname2 + 1, fname, 998);
+ fname2[999] = 0;
+ return (GenericFunc) dlsym(handle, fname2);
+#elif defined(_GNU_SOURCE)
+ return (GenericFunc) dlsym(handle, fname);
+#elif defined(__MINGW32__)
+ return (GenericFunc) GetProcAddress(handle, fname);
+#else
+ return (GenericFunc) NULL;
+#endif
+}
+
+
+/**
+ * Wrapper for dlclose().
+ */
+void
+_mesa_dlclose(void *handle)
+{
+#if defined(_GNU_SOURCE)
+ dlclose(handle);
+#elif defined(__MINGW32__)
+ FreeLibrary(handle);
+#else
+ (void) handle;
+#endif
+}
+
+
+
diff --git a/mesalib/src/mesa/main/dlopen.h b/mesalib/src/mesa/main/dlopen.h
new file mode 100644
index 000000000..9895a2254
--- /dev/null
+++ b/mesalib/src/mesa/main/dlopen.h
@@ -0,0 +1,42 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2008 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 DLOPEN_H
+#define DLOPEN_H
+
+
+typedef void (*GenericFunc)(void);
+
+
+extern void *
+_mesa_dlopen(const char *libname, int flags);
+
+extern GenericFunc
+_mesa_dlsym(void *handle, const char *fname);
+
+extern void
+_mesa_dlclose(void *handle);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/drawpix.c b/mesalib/src/mesa/main/drawpix.c
new file mode 100644
index 000000000..aef658564
--- /dev/null
+++ b/mesalib/src/mesa/main/drawpix.c
@@ -0,0 +1,311 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "drawpix.h"
+#include "enums.h"
+#include "feedback.h"
+#include "framebuffer.h"
+#include "image.h"
+#include "readpix.h"
+#include "state.h"
+
+
+
+/**
+ * If a fragment program is enabled, check that it's valid.
+ * \return GL_TRUE if valid, GL_FALSE otherwise
+ */
+static GLboolean
+valid_fragment_program(GLcontext *ctx)
+{
+ return !(ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled);
+}
+
+
+#if _HAVE_FULL_GL
+
+/*
+ * Execute glDrawPixels
+ */
+void GLAPIENTRY
+_mesa_DrawPixels( GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
+ return;
+ }
+
+ /* We're not using the current vertex program, and the driver may install
+ * it's own.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (!valid_fragment_program(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels (invalid fragment program)");
+ goto end;
+ }
+
+ if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) {
+ /* the error was already recorded */
+ goto end;
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glDrawPixels(incomplete framebuffer)" );
+ goto end;
+ }
+
+ if (!ctx->Current.RasterPosValid) {
+ goto end; /* no-op, not an error */
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ if (width > 0 && height > 0) {
+ /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
+ GLint x = IROUND(ctx->Current.RasterPos[0]);
+ GLint y = IROUND(ctx->Current.RasterPos[1]);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(invalid PBO access)");
+ goto end;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(PBO is mapped)");
+ goto end;
+ }
+ }
+
+ ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
+ &ctx->Unpack, pixels);
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ /* Feedback the current raster pos info */
+ FLUSH_CURRENT( ctx, 0 );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterIndex,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLenum type )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
+ return;
+ }
+
+ /* Note: more detailed 'type' checking is done by the
+ * _mesa_source/dest_buffer_exists() calls below. That's where we
+ * check if the stencil buffer exists, etc.
+ */
+ if (type != GL_COLOR &&
+ type != GL_DEPTH &&
+ type != GL_STENCIL &&
+ type != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ /* We're not using the current vertex program, and the driver may install
+ * it's own.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (!valid_fragment_program(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyPixels (invalid fragment program)");
+ goto end;
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+ ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyPixels(incomplete framebuffer)" );
+ goto end;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, type) ||
+ !_mesa_dest_buffer_exists(ctx, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyPixels(missing source or dest buffer)");
+ goto end;
+ }
+
+ if (!ctx->Current.RasterPosValid || width ==0 || height == 0) {
+ goto end; /* no-op, not an error */
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ /* Round to satisfy conformance tests (matches SGI's OpenGL) */
+ if (width > 0 && height > 0) {
+ GLint destx = IROUND(ctx->Current.RasterPos[0]);
+ GLint desty = IROUND(ctx->Current.RasterPos[1]);
+ ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
+ type );
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ FLUSH_CURRENT( ctx, 0 );
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterIndex,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+
+end:
+ _mesa_set_vp_override(ctx, GL_FALSE);
+}
+
+#endif /* _HAVE_FULL_GL */
+
+
+
+void GLAPIENTRY
+_mesa_Bitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
+ return;
+ }
+
+ if (!ctx->Current.RasterPosValid) {
+ return; /* do nothing */
+ }
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ if (!valid_fragment_program(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap (invalid fragment program)");
+ return;
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glBitmap(incomplete framebuffer)");
+ return;
+ }
+
+ if (ctx->RenderMode == GL_RENDER) {
+ /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
+ if (width > 0 && height > 0) {
+ const GLfloat epsilon = 0.0001F;
+ GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+ GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
+
+ if (ctx->Unpack.BufferObj->Name) {
+ /* unpack from PBO */
+ if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+ GL_COLOR_INDEX, GL_BITMAP,
+ (GLvoid *) bitmap)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(invalid PBO access)");
+ return;
+ }
+ if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBitmap(PBO is mapped)");
+ return;
+ }
+ }
+
+ ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+ }
+ }
+#if _HAVE_FULL_GL
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ FLUSH_CURRENT(ctx, 0);
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
+ _mesa_feedback_vertex( ctx,
+ ctx->Current.RasterPos,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterIndex,
+ ctx->Current.RasterTexCoords[0] );
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */
+ }
+#endif
+
+ /* update raster position */
+ ctx->Current.RasterPos[0] += xmove;
+ ctx->Current.RasterPos[1] += ymove;
+}
diff --git a/mesalib/src/mesa/main/drawpix.h b/mesalib/src/mesa/main/drawpix.h
new file mode 100644
index 000000000..6177adad6
--- /dev/null
+++ b/mesalib/src/mesa/main/drawpix.h
@@ -0,0 +1,49 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_DrawPixels( GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLenum type );
+
+
+extern void GLAPIENTRY
+_mesa_Bitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
new file mode 100644
index 000000000..4a00440ab
--- /dev/null
+++ b/mesalib/src/mesa/main/enable.c
@@ -0,0 +1,1407 @@
+/**
+ * \file enable.c
+ * Enable/disable/query GL capabilities.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "context.h"
+#include "enable.h"
+#include "light.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "math/m_matrix.h"
+#include "api_arrayelt.h"
+
+
+
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)", \
+ state ? "Enable" : "Disable", CAP); \
+ return; \
+ }
+
+
+/**
+ * Helper to enable/disable client-side state.
+ */
+static void
+client_state(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ GLuint flag;
+ GLboolean *var;
+
+ switch (cap) {
+ case GL_VERTEX_ARRAY:
+ var = &ctx->Array.ArrayObj->Vertex.Enabled;
+ flag = _NEW_ARRAY_VERTEX;
+ break;
+ case GL_NORMAL_ARRAY:
+ var = &ctx->Array.ArrayObj->Normal.Enabled;
+ flag = _NEW_ARRAY_NORMAL;
+ break;
+ case GL_COLOR_ARRAY:
+ var = &ctx->Array.ArrayObj->Color.Enabled;
+ flag = _NEW_ARRAY_COLOR0;
+ break;
+ case GL_INDEX_ARRAY:
+ var = &ctx->Array.ArrayObj->Index.Enabled;
+ flag = _NEW_ARRAY_INDEX;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ var = &ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled;
+ flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture);
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ var = &ctx->Array.ArrayObj->EdgeFlag.Enabled;
+ flag = _NEW_ARRAY_EDGEFLAG;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ var = &ctx->Array.ArrayObj->FogCoord.Enabled;
+ flag = _NEW_ARRAY_FOGCOORD;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ var = &ctx->Array.ArrayObj->SecondaryColor.Enabled;
+ flag = _NEW_ARRAY_COLOR1;
+ break;
+
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ var = &ctx->Array.ArrayObj->PointSize.Enabled;
+ flag = _NEW_ARRAY_POINT_SIZE;
+ break;
+#endif
+
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ var = &ctx->Array.ArrayObj->VertexAttrib[n].Enabled;
+ flag = _NEW_ARRAY_ATTRIB(n);
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM,
+ "glEnable/DisableClientState(0x%x)", cap);
+ return;
+ }
+
+ if (*var == state)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.NewState |= flag;
+
+ _ae_invalidate_state(ctx, _NEW_ARRAY);
+
+ *var = state;
+
+ if (state)
+ ctx->Array.ArrayObj->_Enabled |= flag;
+ else
+ ctx->Array.ArrayObj->_Enabled &= ~flag;
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+}
+
+
+/**
+ * Enable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_EnableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_DisableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_FALSE );
+}
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)", \
+ state ? "Enable" : "Disable", CAP); \
+ return; \
+ }
+
+#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)", \
+ state ? "Enable" : "Disable", CAP); \
+ return; \
+ }
+
+
+
+/**
+ * Return pointer to current texture unit for setting/getting coordinate
+ * state.
+ * Note that we'll set GL_INVALID_OPERATION if the active texture unit is
+ * higher than the number of supported coordinate units. And we'll return NULL.
+ */
+static struct gl_texture_unit *
+get_texcoord_unit(GLcontext *ctx)
+{
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)");
+ return NULL;
+ }
+ else {
+ return &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ }
+}
+
+
+/**
+ * Helper function to enable or disable a texture target.
+ * \param bit one of the TEXTURE_x_BIT values
+ * \return GL_TRUE if state is changing or GL_FALSE if no change
+ */
+static GLboolean
+enable_texture(GLcontext *ctx, GLboolean state, GLbitfield texBit)
+{
+ const GLuint curr = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
+ const GLbitfield newenabled = state
+ ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
+
+ if (texUnit->Enabled == newenabled)
+ return GL_FALSE;
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Enabled = newenabled;
+ return GL_TRUE;
+}
+
+
+/**
+ * Helper function to enable or disable state.
+ *
+ * \param ctx GL context.
+ * \param cap the state to enable/disable
+ * \param state whether to enable or disable the specified capability.
+ *
+ * Updates the current context and flushes the vertices as needed. For
+ * capabilities associated with extensions it verifies that those extensions
+ * are effectivly present before updating. Notifies the driver via
+ * dd_function_table::Enable.
+ */
+void
+_mesa_set_enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "%s %s (newstate is %x)\n",
+ state ? "glEnable" : "glDisable",
+ _mesa_lookup_enum_by_nr(cap),
+ ctx->NewState);
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (ctx->Color.AlphaEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.AlphaEnabled = state;
+ break;
+ case GL_AUTO_NORMAL:
+ if (ctx->Eval.AutoNormal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.AutoNormal = state;
+ break;
+ case GL_BLEND:
+ if (ctx->Color.BlendEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.BlendEnabled = state;
+ break;
+#if FEATURE_userclip
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ {
+ const GLuint p = cap - GL_CLIP_PLANE0;
+
+ if ((ctx->Transform.ClipPlanesEnabled & (1 << p)) == ((GLuint) state << p))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+
+ if (state) {
+ ctx->Transform.ClipPlanesEnabled |= (1 << p);
+
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+ /* This derived state also calculated in clip.c and
+ * from _mesa_update_state() on changes to EyeUserPlane
+ * and ctx->ProjectionMatrix respectively.
+ */
+ _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrixStack.Top->inv );
+ }
+ else {
+ ctx->Transform.ClipPlanesEnabled &= ~(1 << p);
+ }
+ }
+ break;
+#endif
+ case GL_COLOR_MATERIAL:
+ if (ctx->Light.ColorMaterialEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ FLUSH_CURRENT(ctx, 0);
+ ctx->Light.ColorMaterialEnabled = state;
+ if (state) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ }
+ break;
+ case GL_CULL_FACE:
+ if (ctx->Polygon.CullFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.CullFlag = state;
+ break;
+ case GL_CULL_VERTEX_EXT:
+ CHECK_EXTENSION(EXT_cull_vertex, cap);
+ if (ctx->Transform.CullVertexFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.CullVertexFlag = state;
+ break;
+ case GL_DEPTH_TEST:
+ if (ctx->Depth.Test == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Test = state;
+ break;
+ case GL_DITHER:
+ if (ctx->NoDither) {
+ state = GL_FALSE; /* MESA_NO_DITHER env var */
+ }
+ if (ctx->Color.DitherFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.DitherFlag = state;
+ break;
+ case GL_FOG:
+ if (ctx->Fog.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Enabled = state;
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXTENSION(EXT_histogram, cap);
+ if (ctx->Pixel.HistogramEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.HistogramEnabled = state;
+ break;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Light[cap-GL_LIGHT0].Enabled = state;
+ if (state) {
+ insert_at_tail(&ctx->Light.EnabledList,
+ &ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ else {
+ remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ break;
+ case GL_LIGHTING:
+ if (ctx->Light.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Enabled = state;
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+ ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+ else
+ ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
+ break;
+ case GL_LINE_SMOOTH:
+ if (ctx->Line.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_SMOOTH;
+ break;
+ case GL_LINE_STIPPLE:
+ if (ctx->Line.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_STIPPLE;
+ break;
+ case GL_INDEX_LOGIC_OP:
+ if (ctx->Color.IndexLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.IndexLogicOpEnabled = state;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ if (ctx->Color.ColorLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.ColorLogicOpEnabled = state;
+ break;
+ case GL_MAP1_COLOR_4:
+ if (ctx->Eval.Map1Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Color4 = state;
+ break;
+ case GL_MAP1_INDEX:
+ if (ctx->Eval.Map1Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Index = state;
+ break;
+ case GL_MAP1_NORMAL:
+ if (ctx->Eval.Map1Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Normal = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ if (ctx->Eval.Map1TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord1 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ if (ctx->Eval.Map1TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord2 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ if (ctx->Eval.Map1TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord3 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ if (ctx->Eval.Map1TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord4 = state;
+ break;
+ case GL_MAP1_VERTEX_3:
+ if (ctx->Eval.Map1Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex3 = state;
+ break;
+ case GL_MAP1_VERTEX_4:
+ if (ctx->Eval.Map1Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex4 = state;
+ break;
+ case GL_MAP2_COLOR_4:
+ if (ctx->Eval.Map2Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Color4 = state;
+ break;
+ case GL_MAP2_INDEX:
+ if (ctx->Eval.Map2Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Index = state;
+ break;
+ case GL_MAP2_NORMAL:
+ if (ctx->Eval.Map2Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Normal = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ if (ctx->Eval.Map2TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord1 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ if (ctx->Eval.Map2TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord2 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ if (ctx->Eval.Map2TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord3 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ if (ctx->Eval.Map2TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord4 = state;
+ break;
+ case GL_MAP2_VERTEX_3:
+ if (ctx->Eval.Map2Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex3 = state;
+ break;
+ case GL_MAP2_VERTEX_4:
+ if (ctx->Eval.Map2Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex4 = state;
+ break;
+ case GL_MINMAX:
+ if (ctx->Pixel.MinMaxEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.MinMaxEnabled = state;
+ break;
+ case GL_NORMALIZE:
+ if (ctx->Transform.Normalize == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.Normalize = state;
+ break;
+ case GL_POINT_SMOOTH:
+ if (ctx->Point.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_POINT_SMOOTH;
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (ctx->Polygon.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_SMOOTH;
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (ctx->Polygon.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_STIPPLE;
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ if (ctx->Polygon.OffsetPoint == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetPoint = state;
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ if (ctx->Polygon.OffsetLine == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetLine = state;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ if (ctx->Polygon.OffsetFill == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetFill = state;
+ break;
+ case GL_RESCALE_NORMAL_EXT:
+ if (ctx->Transform.RescaleNormals == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RescaleNormals = state;
+ break;
+ case GL_SCISSOR_TEST:
+ if (ctx->Scissor.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.Enabled = state;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ if (ctx->Texture.SharedPalette == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ ctx->Texture.SharedPalette = state;
+ break;
+ case GL_STENCIL_TEST:
+ if (ctx->Stencil.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Enabled = state;
+ break;
+ case GL_TEXTURE_1D:
+ if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_2D:
+ if (!enable_texture(ctx, state, TEXTURE_2D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_3D:
+ if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_GEN_Q:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~Q_BIT;
+ if (state)
+ newenabled |= Q_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_R:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~R_BIT;
+ if (state)
+ newenabled |= R_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_S:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~S_BIT;
+ if (state)
+ newenabled |= S_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_T:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled = texUnit->TexGenEnabled & ~T_BIT;
+ if (state)
+ newenabled |= T_BIT;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_INDEX_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_EDGE_FLAG_ARRAY:
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ case GL_POINT_SIZE_ARRAY_OES:
+ client_state( ctx, cap, state );
+ return;
+
+ /* GL_SGI_color_table */
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table, cap);
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION] == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION] = state;
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table, cap);
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION] == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION] = state;
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table, cap);
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX] == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX] = state;
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_texture_color_table, cap);
+ if (ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled = state;
+ break;
+
+ /* GL_EXT_convolution */
+ case GL_CONVOLUTION_1D:
+ CHECK_EXTENSION(EXT_convolution, cap);
+ if (ctx->Pixel.Convolution1DEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.Convolution1DEnabled = state;
+ break;
+ case GL_CONVOLUTION_2D:
+ CHECK_EXTENSION(EXT_convolution, cap);
+ if (ctx->Pixel.Convolution2DEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.Convolution2DEnabled = state;
+ break;
+ case GL_SEPARABLE_2D:
+ CHECK_EXTENSION(EXT_convolution, cap);
+ if (ctx->Pixel.Separable2DEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.Separable2DEnabled = state;
+ break;
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map, cap);
+ if (!enable_texture(ctx, state, TEXTURE_CUBE_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program, cap);
+ if (ctx->Fog.ColorSumEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.ColorSumEnabled = state;
+ break;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ if (ctx->Multisample.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.Enabled = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ if (ctx->Multisample.SampleAlphaToCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToCoverage = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ if (ctx->Multisample.SampleAlphaToOne == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToOne = state;
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ if (ctx->Multisample.SampleCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverage = state;
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ if (ctx->Multisample.SampleCoverageInvert == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverageInvert = state;
+ break;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip, cap);
+ if (ctx->Transform.RasterPositionUnclipped == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RasterPositionUnclipped = state;
+ break;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap);
+ if (ctx->Point.PointSprite == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.PointSprite = state;
+ break;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.Enabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.PointSizeEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.PointSizeEnabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.TwoSideEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.TwoSideEnabled = state;
+ break;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Attrib[map] = state;
+ }
+ break;
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Attrib[map] = state;
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle, cap);
+ if (!enable_texture(ctx, state, TEXTURE_RECT_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side, cap);
+ if (ctx->Stencil.TestTwoSide == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.TestTwoSide = state;
+ if (state) {
+ ctx->Stencil._BackFace = 2;
+ ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
+ } else {
+ ctx->Stencil._BackFace = 1;
+ ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
+ }
+ break;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXTENSION(ARB_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test, cap);
+ if (ctx->Depth.BoundsTest == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.BoundsTest = state;
+ break;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader, cap);
+ if (ctx->ATIFragmentShader.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->ATIFragmentShader.Enabled = state;
+ break;
+#endif
+
+ /* GL_MESA_texture_array */
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map, cap);
+ ctx->Texture.CubeMapSeamless = state;
+ break;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(0x%x)", state ? "glEnable" : "glDisable", cap);
+ return;
+ }
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+}
+
+
+/**
+ * Enable GL capability. Called by glEnable()
+ * \param cap state to enable.
+ */
+void GLAPIENTRY
+_mesa_Enable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability. Called by glDisable()
+ * \param cap state to disable.
+ */
+void GLAPIENTRY
+_mesa_Disable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_FALSE );
+}
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME) \
+ if (!ctx->Extensions.EXTNAME) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled"); \
+ return GL_FALSE; \
+ }
+
+#undef CHECK_EXTENSION2
+#define CHECK_EXTENSION2(EXT1, EXT2) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled"); \
+ return GL_FALSE; \
+ }
+
+
+/**
+ * Helper function to determine whether a texture target is enabled.
+ */
+static GLboolean
+is_texture_enabled(GLcontext *ctx, GLbitfield bit)
+{
+ const struct gl_texture_unit *const texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE;
+}
+
+
+/**
+ * Return simple enable/disable state.
+ *
+ * \param cap state variable to query.
+ *
+ * Returns the state of the specified capability from the current GL context.
+ * For the capabilities associated with extensions verifies that those
+ * extensions are effectively present before reporting.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsEnabled( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ 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.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1;
+ 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:
+ return is_texture_enabled(ctx, TEXTURE_1D_BIT);
+ case GL_TEXTURE_2D:
+ return is_texture_enabled(ctx, TEXTURE_2D_BIT);
+ case GL_TEXTURE_3D:
+ return is_texture_enabled(ctx, TEXTURE_3D_BIT);
+ case GL_TEXTURE_GEN_Q:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_R:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_S:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+ case GL_TEXTURE_GEN_T:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ return (ctx->Array.ArrayObj->Vertex.Enabled != 0);
+ case GL_NORMAL_ARRAY:
+ return (ctx->Array.ArrayObj->Normal.Enabled != 0);
+ case GL_COLOR_ARRAY:
+ return (ctx->Array.ArrayObj->Color.Enabled != 0);
+ case GL_INDEX_ARRAY:
+ return (ctx->Array.ArrayObj->Index.Enabled != 0);
+ case GL_TEXTURE_COORD_ARRAY:
+ return (ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled != 0);
+ case GL_EDGE_FLAG_ARRAY:
+ return (ctx->Array.ArrayObj->EdgeFlag.Enabled != 0);
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_fog_coord);
+ return (ctx->Array.ArrayObj->FogCoord.Enabled != 0);
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_secondary_color);
+ return (ctx->Array.ArrayObj->SecondaryColor.Enabled != 0);
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ return (ctx->Array.ArrayObj->PointSize.Enabled != 0);
+#endif
+
+ /* GL_EXT_histogram */
+ case GL_HISTOGRAM:
+ CHECK_EXTENSION(EXT_histogram);
+ return ctx->Pixel.HistogramEnabled;
+ case GL_MINMAX:
+ CHECK_EXTENSION(EXT_histogram);
+ return ctx->Pixel.MinMaxEnabled;
+
+ /* GL_SGI_color_table */
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table);
+ return ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION];
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table);
+ return ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION];
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_color_table);
+ return ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX];
+
+ /* GL_SGI_texture_color_table */
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXTENSION(SGI_texture_color_table);
+ return ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled;
+
+ /* GL_EXT_convolution */
+ case GL_CONVOLUTION_1D:
+ CHECK_EXTENSION(EXT_convolution);
+ return ctx->Pixel.Convolution1DEnabled;
+ case GL_CONVOLUTION_2D:
+ CHECK_EXTENSION(EXT_convolution);
+ return ctx->Pixel.Convolution2DEnabled;
+ case GL_SEPARABLE_2D:
+ CHECK_EXTENSION(EXT_convolution);
+ return ctx->Pixel.Separable2DEnabled;
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map);
+ return is_texture_enabled(ctx, TEXTURE_CUBE_BIT);
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program);
+ return ctx->Fog.ColorSumEnabled;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ return ctx->Multisample.Enabled;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ return ctx->Multisample.SampleAlphaToCoverage;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ return ctx->Multisample.SampleAlphaToOne;
+ case GL_SAMPLE_COVERAGE_ARB:
+ return ctx->Multisample.SampleCoverage;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ return ctx->Multisample.SampleCoverageInvert;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip);
+ return ctx->Transform.RasterPositionUnclipped;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite)
+ return ctx->Point.PointSprite;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.Enabled;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.PointSizeEnabled;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.TwoSideEnabled;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0);
+ }
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map1Attrib[map];
+ }
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map2Attrib[map];
+ }
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program);
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle);
+ return is_texture_enabled(ctx, TEXTURE_RECT_BIT);
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side);
+ return ctx->Stencil.TestTwoSide;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test);
+ return ctx->Depth.BoundsTest;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader);
+ return ctx->ATIFragmentShader.Enabled;
+#endif /* FEATURE_ATI_fragment_shader */
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map);
+ return ctx->Texture.CubeMapSeamless;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
+ return GL_FALSE;
+ }
+}
diff --git a/mesalib/src/mesa/main/enable.h b/mesalib/src/mesa/main/enable.h
new file mode 100644
index 000000000..25c90b027
--- /dev/null
+++ b/mesalib/src/mesa/main/enable.h
@@ -0,0 +1,57 @@
+/**
+ * \file enable.h
+ * Enable/disable/query GL capabilities.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef ENABLE_H
+#define ENABLE_H
+
+
+#include "mtypes.h"
+
+
+extern void
+_mesa_set_enable( GLcontext* ctx, GLenum cap, GLboolean state );
+
+extern void GLAPIENTRY
+_mesa_Disable( GLenum cap );
+
+extern void GLAPIENTRY
+_mesa_Enable( GLenum cap );
+
+extern GLboolean GLAPIENTRY
+_mesa_IsEnabled( GLenum cap );
+
+extern void GLAPIENTRY
+_mesa_EnableClientState( GLenum cap );
+
+extern void GLAPIENTRY
+_mesa_DisableClientState( GLenum cap );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/enums.c b/mesalib/src/mesa/main/enums.c
new file mode 100644
index 000000000..9f650dadd
--- /dev/null
+++ b/mesalib/src/mesa/main/enums.c
@@ -0,0 +1,5201 @@
+/* DO NOT EDIT - This file generated automatically by gl_enums.py (from Mesa) script */
+
+/*
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "glheader.h"
+#include "mfeatures.h"
+#include "enums.h"
+#include "imports.h"
+
+typedef struct {
+ size_t offset;
+ int n;
+} enum_elt;
+
+LONGSTRING static const char enum_string_table[] =
+ "GL_2D\0"
+ "GL_2_BYTES\0"
+ "GL_3D\0"
+ "GL_3D_COLOR\0"
+ "GL_3D_COLOR_TEXTURE\0"
+ "GL_3_BYTES\0"
+ "GL_4D_COLOR_TEXTURE\0"
+ "GL_4_BYTES\0"
+ "GL_ACCUM\0"
+ "GL_ACCUM_ALPHA_BITS\0"
+ "GL_ACCUM_BLUE_BITS\0"
+ "GL_ACCUM_BUFFER_BIT\0"
+ "GL_ACCUM_CLEAR_VALUE\0"
+ "GL_ACCUM_GREEN_BITS\0"
+ "GL_ACCUM_RED_BITS\0"
+ "GL_ACTIVE_ATTRIBUTES\0"
+ "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH\0"
+ "GL_ACTIVE_STENCIL_FACE_EXT\0"
+ "GL_ACTIVE_TEXTURE\0"
+ "GL_ACTIVE_TEXTURE_ARB\0"
+ "GL_ACTIVE_UNIFORMS\0"
+ "GL_ACTIVE_UNIFORM_MAX_LENGTH\0"
+ "GL_ACTIVE_VERTEX_UNITS_ARB\0"
+ "GL_ADD\0"
+ "GL_ADD_SIGNED\0"
+ "GL_ADD_SIGNED_ARB\0"
+ "GL_ADD_SIGNED_EXT\0"
+ "GL_ALIASED_LINE_WIDTH_RANGE\0"
+ "GL_ALIASED_POINT_SIZE_RANGE\0"
+ "GL_ALL_ATTRIB_BITS\0"
+ "GL_ALL_CLIENT_ATTRIB_BITS\0"
+ "GL_ALPHA\0"
+ "GL_ALPHA12\0"
+ "GL_ALPHA12_EXT\0"
+ "GL_ALPHA16\0"
+ "GL_ALPHA16_EXT\0"
+ "GL_ALPHA4\0"
+ "GL_ALPHA4_EXT\0"
+ "GL_ALPHA8\0"
+ "GL_ALPHA8_EXT\0"
+ "GL_ALPHA_BIAS\0"
+ "GL_ALPHA_BITS\0"
+ "GL_ALPHA_SCALE\0"
+ "GL_ALPHA_TEST\0"
+ "GL_ALPHA_TEST_FUNC\0"
+ "GL_ALPHA_TEST_REF\0"
+ "GL_ALREADY_SIGNALED\0"
+ "GL_ALWAYS\0"
+ "GL_AMBIENT\0"
+ "GL_AMBIENT_AND_DIFFUSE\0"
+ "GL_AND\0"
+ "GL_AND_INVERTED\0"
+ "GL_AND_REVERSE\0"
+ "GL_ARRAY_BUFFER\0"
+ "GL_ARRAY_BUFFER_BINDING\0"
+ "GL_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_ATTACHED_SHADERS\0"
+ "GL_ATTRIB_ARRAY_POINTER_NV\0"
+ "GL_ATTRIB_ARRAY_SIZE_NV\0"
+ "GL_ATTRIB_ARRAY_STRIDE_NV\0"
+ "GL_ATTRIB_ARRAY_TYPE_NV\0"
+ "GL_ATTRIB_STACK_DEPTH\0"
+ "GL_AUTO_NORMAL\0"
+ "GL_AUX0\0"
+ "GL_AUX1\0"
+ "GL_AUX2\0"
+ "GL_AUX3\0"
+ "GL_AUX_BUFFERS\0"
+ "GL_BACK\0"
+ "GL_BACK_LEFT\0"
+ "GL_BACK_RIGHT\0"
+ "GL_BGR\0"
+ "GL_BGRA\0"
+ "GL_BITMAP\0"
+ "GL_BITMAP_TOKEN\0"
+ "GL_BLEND\0"
+ "GL_BLEND_COLOR\0"
+ "GL_BLEND_COLOR_EXT\0"
+ "GL_BLEND_DST\0"
+ "GL_BLEND_DST_ALPHA\0"
+ "GL_BLEND_DST_RGB\0"
+ "GL_BLEND_EQUATION\0"
+ "GL_BLEND_EQUATION_ALPHA\0"
+ "GL_BLEND_EQUATION_ALPHA_EXT\0"
+ "GL_BLEND_EQUATION_EXT\0"
+ "GL_BLEND_EQUATION_RGB\0"
+ "GL_BLEND_EQUATION_RGB_EXT\0"
+ "GL_BLEND_SRC\0"
+ "GL_BLEND_SRC_ALPHA\0"
+ "GL_BLEND_SRC_RGB\0"
+ "GL_BLUE\0"
+ "GL_BLUE_BIAS\0"
+ "GL_BLUE_BITS\0"
+ "GL_BLUE_SCALE\0"
+ "GL_BOOL\0"
+ "GL_BOOL_ARB\0"
+ "GL_BOOL_VEC2\0"
+ "GL_BOOL_VEC2_ARB\0"
+ "GL_BOOL_VEC3\0"
+ "GL_BOOL_VEC3_ARB\0"
+ "GL_BOOL_VEC4\0"
+ "GL_BOOL_VEC4_ARB\0"
+ "GL_BUFFER_ACCESS\0"
+ "GL_BUFFER_ACCESS_ARB\0"
+ "GL_BUFFER_FLUSHING_UNMAP_APPLE\0"
+ "GL_BUFFER_MAPPED\0"
+ "GL_BUFFER_MAPPED_ARB\0"
+ "GL_BUFFER_MAP_POINTER\0"
+ "GL_BUFFER_MAP_POINTER_ARB\0"
+ "GL_BUFFER_SERIALIZED_MODIFY_APPLE\0"
+ "GL_BUFFER_SIZE\0"
+ "GL_BUFFER_SIZE_ARB\0"
+ "GL_BUFFER_USAGE\0"
+ "GL_BUFFER_USAGE_ARB\0"
+ "GL_BUMP_ENVMAP_ATI\0"
+ "GL_BUMP_NUM_TEX_UNITS_ATI\0"
+ "GL_BUMP_ROT_MATRIX_ATI\0"
+ "GL_BUMP_ROT_MATRIX_SIZE_ATI\0"
+ "GL_BUMP_TARGET_ATI\0"
+ "GL_BUMP_TEX_UNITS_ATI\0"
+ "GL_BYTE\0"
+ "GL_C3F_V3F\0"
+ "GL_C4F_N3F_V3F\0"
+ "GL_C4UB_V2F\0"
+ "GL_C4UB_V3F\0"
+ "GL_CCW\0"
+ "GL_CLAMP\0"
+ "GL_CLAMP_TO_BORDER\0"
+ "GL_CLAMP_TO_BORDER_ARB\0"
+ "GL_CLAMP_TO_BORDER_SGIS\0"
+ "GL_CLAMP_TO_EDGE\0"
+ "GL_CLAMP_TO_EDGE_SGIS\0"
+ "GL_CLEAR\0"
+ "GL_CLIENT_ACTIVE_TEXTURE\0"
+ "GL_CLIENT_ACTIVE_TEXTURE_ARB\0"
+ "GL_CLIENT_ALL_ATTRIB_BITS\0"
+ "GL_CLIENT_ATTRIB_STACK_DEPTH\0"
+ "GL_CLIENT_PIXEL_STORE_BIT\0"
+ "GL_CLIENT_VERTEX_ARRAY_BIT\0"
+ "GL_CLIP_PLANE0\0"
+ "GL_CLIP_PLANE1\0"
+ "GL_CLIP_PLANE2\0"
+ "GL_CLIP_PLANE3\0"
+ "GL_CLIP_PLANE4\0"
+ "GL_CLIP_PLANE5\0"
+ "GL_CLIP_VOLUME_CLIPPING_HINT_EXT\0"
+ "GL_COEFF\0"
+ "GL_COLOR\0"
+ "GL_COLOR_ARRAY\0"
+ "GL_COLOR_ARRAY_BUFFER_BINDING\0"
+ "GL_COLOR_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_COLOR_ARRAY_POINTER\0"
+ "GL_COLOR_ARRAY_SIZE\0"
+ "GL_COLOR_ARRAY_STRIDE\0"
+ "GL_COLOR_ARRAY_TYPE\0"
+ "GL_COLOR_ATTACHMENT0\0"
+ "GL_COLOR_ATTACHMENT0_EXT\0"
+ "GL_COLOR_ATTACHMENT1\0"
+ "GL_COLOR_ATTACHMENT10\0"
+ "GL_COLOR_ATTACHMENT10_EXT\0"
+ "GL_COLOR_ATTACHMENT11\0"
+ "GL_COLOR_ATTACHMENT11_EXT\0"
+ "GL_COLOR_ATTACHMENT12\0"
+ "GL_COLOR_ATTACHMENT12_EXT\0"
+ "GL_COLOR_ATTACHMENT13\0"
+ "GL_COLOR_ATTACHMENT13_EXT\0"
+ "GL_COLOR_ATTACHMENT14\0"
+ "GL_COLOR_ATTACHMENT14_EXT\0"
+ "GL_COLOR_ATTACHMENT15\0"
+ "GL_COLOR_ATTACHMENT15_EXT\0"
+ "GL_COLOR_ATTACHMENT1_EXT\0"
+ "GL_COLOR_ATTACHMENT2\0"
+ "GL_COLOR_ATTACHMENT2_EXT\0"
+ "GL_COLOR_ATTACHMENT3\0"
+ "GL_COLOR_ATTACHMENT3_EXT\0"
+ "GL_COLOR_ATTACHMENT4\0"
+ "GL_COLOR_ATTACHMENT4_EXT\0"
+ "GL_COLOR_ATTACHMENT5\0"
+ "GL_COLOR_ATTACHMENT5_EXT\0"
+ "GL_COLOR_ATTACHMENT6\0"
+ "GL_COLOR_ATTACHMENT6_EXT\0"
+ "GL_COLOR_ATTACHMENT7\0"
+ "GL_COLOR_ATTACHMENT7_EXT\0"
+ "GL_COLOR_ATTACHMENT8\0"
+ "GL_COLOR_ATTACHMENT8_EXT\0"
+ "GL_COLOR_ATTACHMENT9\0"
+ "GL_COLOR_ATTACHMENT9_EXT\0"
+ "GL_COLOR_BUFFER_BIT\0"
+ "GL_COLOR_CLEAR_VALUE\0"
+ "GL_COLOR_INDEX\0"
+ "GL_COLOR_INDEXES\0"
+ "GL_COLOR_LOGIC_OP\0"
+ "GL_COLOR_MATERIAL\0"
+ "GL_COLOR_MATERIAL_FACE\0"
+ "GL_COLOR_MATERIAL_PARAMETER\0"
+ "GL_COLOR_MATRIX\0"
+ "GL_COLOR_MATRIX_SGI\0"
+ "GL_COLOR_MATRIX_STACK_DEPTH\0"
+ "GL_COLOR_MATRIX_STACK_DEPTH_SGI\0"
+ "GL_COLOR_SUM\0"
+ "GL_COLOR_SUM_ARB\0"
+ "GL_COLOR_TABLE\0"
+ "GL_COLOR_TABLE_ALPHA_SIZE\0"
+ "GL_COLOR_TABLE_ALPHA_SIZE_EXT\0"
+ "GL_COLOR_TABLE_ALPHA_SIZE_SGI\0"
+ "GL_COLOR_TABLE_BIAS\0"
+ "GL_COLOR_TABLE_BIAS_SGI\0"
+ "GL_COLOR_TABLE_BLUE_SIZE\0"
+ "GL_COLOR_TABLE_BLUE_SIZE_EXT\0"
+ "GL_COLOR_TABLE_BLUE_SIZE_SGI\0"
+ "GL_COLOR_TABLE_FORMAT\0"
+ "GL_COLOR_TABLE_FORMAT_EXT\0"
+ "GL_COLOR_TABLE_FORMAT_SGI\0"
+ "GL_COLOR_TABLE_GREEN_SIZE\0"
+ "GL_COLOR_TABLE_GREEN_SIZE_EXT\0"
+ "GL_COLOR_TABLE_GREEN_SIZE_SGI\0"
+ "GL_COLOR_TABLE_INTENSITY_SIZE\0"
+ "GL_COLOR_TABLE_INTENSITY_SIZE_EXT\0"
+ "GL_COLOR_TABLE_INTENSITY_SIZE_SGI\0"
+ "GL_COLOR_TABLE_LUMINANCE_SIZE\0"
+ "GL_COLOR_TABLE_LUMINANCE_SIZE_EXT\0"
+ "GL_COLOR_TABLE_LUMINANCE_SIZE_SGI\0"
+ "GL_COLOR_TABLE_RED_SIZE\0"
+ "GL_COLOR_TABLE_RED_SIZE_EXT\0"
+ "GL_COLOR_TABLE_RED_SIZE_SGI\0"
+ "GL_COLOR_TABLE_SCALE\0"
+ "GL_COLOR_TABLE_SCALE_SGI\0"
+ "GL_COLOR_TABLE_WIDTH\0"
+ "GL_COLOR_TABLE_WIDTH_EXT\0"
+ "GL_COLOR_TABLE_WIDTH_SGI\0"
+ "GL_COLOR_WRITEMASK\0"
+ "GL_COMBINE\0"
+ "GL_COMBINE4\0"
+ "GL_COMBINE_ALPHA\0"
+ "GL_COMBINE_ALPHA_ARB\0"
+ "GL_COMBINE_ALPHA_EXT\0"
+ "GL_COMBINE_ARB\0"
+ "GL_COMBINE_EXT\0"
+ "GL_COMBINE_RGB\0"
+ "GL_COMBINE_RGB_ARB\0"
+ "GL_COMBINE_RGB_EXT\0"
+ "GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT\0"
+ "GL_COMPARE_R_TO_TEXTURE\0"
+ "GL_COMPARE_R_TO_TEXTURE_ARB\0"
+ "GL_COMPILE\0"
+ "GL_COMPILE_AND_EXECUTE\0"
+ "GL_COMPILE_STATUS\0"
+ "GL_COMPRESSED_ALPHA\0"
+ "GL_COMPRESSED_ALPHA_ARB\0"
+ "GL_COMPRESSED_INTENSITY\0"
+ "GL_COMPRESSED_INTENSITY_ARB\0"
+ "GL_COMPRESSED_LUMINANCE\0"
+ "GL_COMPRESSED_LUMINANCE_ALPHA\0"
+ "GL_COMPRESSED_LUMINANCE_ALPHA_ARB\0"
+ "GL_COMPRESSED_LUMINANCE_ARB\0"
+ "GL_COMPRESSED_RGB\0"
+ "GL_COMPRESSED_RGBA\0"
+ "GL_COMPRESSED_RGBA_ARB\0"
+ "GL_COMPRESSED_RGBA_FXT1_3DFX\0"
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT\0"
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT\0"
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT\0"
+ "GL_COMPRESSED_RGB_ARB\0"
+ "GL_COMPRESSED_RGB_FXT1_3DFX\0"
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT\0"
+ "GL_COMPRESSED_SLUMINANCE\0"
+ "GL_COMPRESSED_SLUMINANCE_ALPHA\0"
+ "GL_COMPRESSED_SRGB\0"
+ "GL_COMPRESSED_SRGB_ALPHA\0"
+ "GL_COMPRESSED_TEXTURE_FORMATS\0"
+ "GL_CONDITION_SATISFIED\0"
+ "GL_CONSTANT\0"
+ "GL_CONSTANT_ALPHA\0"
+ "GL_CONSTANT_ALPHA_EXT\0"
+ "GL_CONSTANT_ARB\0"
+ "GL_CONSTANT_ATTENUATION\0"
+ "GL_CONSTANT_BORDER_HP\0"
+ "GL_CONSTANT_COLOR\0"
+ "GL_CONSTANT_COLOR_EXT\0"
+ "GL_CONSTANT_EXT\0"
+ "GL_CONVOLUTION_1D\0"
+ "GL_CONVOLUTION_2D\0"
+ "GL_CONVOLUTION_BORDER_COLOR\0"
+ "GL_CONVOLUTION_BORDER_COLOR_HP\0"
+ "GL_CONVOLUTION_BORDER_MODE\0"
+ "GL_CONVOLUTION_BORDER_MODE_EXT\0"
+ "GL_CONVOLUTION_FILTER_BIAS\0"
+ "GL_CONVOLUTION_FILTER_BIAS_EXT\0"
+ "GL_CONVOLUTION_FILTER_SCALE\0"
+ "GL_CONVOLUTION_FILTER_SCALE_EXT\0"
+ "GL_CONVOLUTION_FORMAT\0"
+ "GL_CONVOLUTION_FORMAT_EXT\0"
+ "GL_CONVOLUTION_HEIGHT\0"
+ "GL_CONVOLUTION_HEIGHT_EXT\0"
+ "GL_CONVOLUTION_WIDTH\0"
+ "GL_CONVOLUTION_WIDTH_EXT\0"
+ "GL_COORD_REPLACE\0"
+ "GL_COORD_REPLACE_ARB\0"
+ "GL_COORD_REPLACE_NV\0"
+ "GL_COPY\0"
+ "GL_COPY_INVERTED\0"
+ "GL_COPY_PIXEL_TOKEN\0"
+ "GL_COPY_READ_BUFFER\0"
+ "GL_COPY_WRITE_BUFFER\0"
+ "GL_CULL_FACE\0"
+ "GL_CULL_FACE_MODE\0"
+ "GL_CULL_VERTEX_EXT\0"
+ "GL_CULL_VERTEX_EYE_POSITION_EXT\0"
+ "GL_CULL_VERTEX_OBJECT_POSITION_EXT\0"
+ "GL_CURRENT_ATTRIB_NV\0"
+ "GL_CURRENT_BIT\0"
+ "GL_CURRENT_COLOR\0"
+ "GL_CURRENT_FOG_COORD\0"
+ "GL_CURRENT_FOG_COORDINATE\0"
+ "GL_CURRENT_INDEX\0"
+ "GL_CURRENT_MATRIX_ARB\0"
+ "GL_CURRENT_MATRIX_INDEX_ARB\0"
+ "GL_CURRENT_MATRIX_NV\0"
+ "GL_CURRENT_MATRIX_STACK_DEPTH_ARB\0"
+ "GL_CURRENT_MATRIX_STACK_DEPTH_NV\0"
+ "GL_CURRENT_NORMAL\0"
+ "GL_CURRENT_PALETTE_MATRIX_ARB\0"
+ "GL_CURRENT_PROGRAM\0"
+ "GL_CURRENT_QUERY\0"
+ "GL_CURRENT_QUERY_ARB\0"
+ "GL_CURRENT_RASTER_COLOR\0"
+ "GL_CURRENT_RASTER_DISTANCE\0"
+ "GL_CURRENT_RASTER_INDEX\0"
+ "GL_CURRENT_RASTER_POSITION\0"
+ "GL_CURRENT_RASTER_POSITION_VALID\0"
+ "GL_CURRENT_RASTER_SECONDARY_COLOR\0"
+ "GL_CURRENT_RASTER_TEXTURE_COORDS\0"
+ "GL_CURRENT_SECONDARY_COLOR\0"
+ "GL_CURRENT_TEXTURE_COORDS\0"
+ "GL_CURRENT_VERTEX_ATTRIB\0"
+ "GL_CURRENT_VERTEX_ATTRIB_ARB\0"
+ "GL_CURRENT_WEIGHT_ARB\0"
+ "GL_CW\0"
+ "GL_DEBUG_ASSERT_MESA\0"
+ "GL_DEBUG_OBJECT_MESA\0"
+ "GL_DEBUG_PRINT_MESA\0"
+ "GL_DECAL\0"
+ "GL_DECR\0"
+ "GL_DECR_WRAP\0"
+ "GL_DECR_WRAP_EXT\0"
+ "GL_DELETE_STATUS\0"
+ "GL_DEPTH\0"
+ "GL_DEPTH24_STENCIL8\0"
+ "GL_DEPTH_ATTACHMENT\0"
+ "GL_DEPTH_ATTACHMENT_EXT\0"
+ "GL_DEPTH_BIAS\0"
+ "GL_DEPTH_BITS\0"
+ "GL_DEPTH_BOUNDS_EXT\0"
+ "GL_DEPTH_BOUNDS_TEST_EXT\0"
+ "GL_DEPTH_BUFFER_BIT\0"
+ "GL_DEPTH_CLAMP_NV\0"
+ "GL_DEPTH_CLEAR_VALUE\0"
+ "GL_DEPTH_COMPONENT\0"
+ "GL_DEPTH_COMPONENT16\0"
+ "GL_DEPTH_COMPONENT16_ARB\0"
+ "GL_DEPTH_COMPONENT16_SGIX\0"
+ "GL_DEPTH_COMPONENT24\0"
+ "GL_DEPTH_COMPONENT24_ARB\0"
+ "GL_DEPTH_COMPONENT24_SGIX\0"
+ "GL_DEPTH_COMPONENT32\0"
+ "GL_DEPTH_COMPONENT32_ARB\0"
+ "GL_DEPTH_COMPONENT32_SGIX\0"
+ "GL_DEPTH_FUNC\0"
+ "GL_DEPTH_RANGE\0"
+ "GL_DEPTH_SCALE\0"
+ "GL_DEPTH_STENCIL\0"
+ "GL_DEPTH_STENCIL_ATTACHMENT\0"
+ "GL_DEPTH_STENCIL_NV\0"
+ "GL_DEPTH_STENCIL_TO_BGRA_NV\0"
+ "GL_DEPTH_STENCIL_TO_RGBA_NV\0"
+ "GL_DEPTH_TEST\0"
+ "GL_DEPTH_TEXTURE_MODE\0"
+ "GL_DEPTH_TEXTURE_MODE_ARB\0"
+ "GL_DEPTH_WRITEMASK\0"
+ "GL_DIFFUSE\0"
+ "GL_DITHER\0"
+ "GL_DOMAIN\0"
+ "GL_DONT_CARE\0"
+ "GL_DOT3_RGB\0"
+ "GL_DOT3_RGBA\0"
+ "GL_DOT3_RGBA_ARB\0"
+ "GL_DOT3_RGBA_EXT\0"
+ "GL_DOT3_RGB_ARB\0"
+ "GL_DOT3_RGB_EXT\0"
+ "GL_DOUBLE\0"
+ "GL_DOUBLEBUFFER\0"
+ "GL_DRAW_BUFFER\0"
+ "GL_DRAW_BUFFER0\0"
+ "GL_DRAW_BUFFER0_ARB\0"
+ "GL_DRAW_BUFFER0_ATI\0"
+ "GL_DRAW_BUFFER1\0"
+ "GL_DRAW_BUFFER10\0"
+ "GL_DRAW_BUFFER10_ARB\0"
+ "GL_DRAW_BUFFER10_ATI\0"
+ "GL_DRAW_BUFFER11\0"
+ "GL_DRAW_BUFFER11_ARB\0"
+ "GL_DRAW_BUFFER11_ATI\0"
+ "GL_DRAW_BUFFER12\0"
+ "GL_DRAW_BUFFER12_ARB\0"
+ "GL_DRAW_BUFFER12_ATI\0"
+ "GL_DRAW_BUFFER13\0"
+ "GL_DRAW_BUFFER13_ARB\0"
+ "GL_DRAW_BUFFER13_ATI\0"
+ "GL_DRAW_BUFFER14\0"
+ "GL_DRAW_BUFFER14_ARB\0"
+ "GL_DRAW_BUFFER14_ATI\0"
+ "GL_DRAW_BUFFER15\0"
+ "GL_DRAW_BUFFER15_ARB\0"
+ "GL_DRAW_BUFFER15_ATI\0"
+ "GL_DRAW_BUFFER1_ARB\0"
+ "GL_DRAW_BUFFER1_ATI\0"
+ "GL_DRAW_BUFFER2\0"
+ "GL_DRAW_BUFFER2_ARB\0"
+ "GL_DRAW_BUFFER2_ATI\0"
+ "GL_DRAW_BUFFER3\0"
+ "GL_DRAW_BUFFER3_ARB\0"
+ "GL_DRAW_BUFFER3_ATI\0"
+ "GL_DRAW_BUFFER4\0"
+ "GL_DRAW_BUFFER4_ARB\0"
+ "GL_DRAW_BUFFER4_ATI\0"
+ "GL_DRAW_BUFFER5\0"
+ "GL_DRAW_BUFFER5_ARB\0"
+ "GL_DRAW_BUFFER5_ATI\0"
+ "GL_DRAW_BUFFER6\0"
+ "GL_DRAW_BUFFER6_ARB\0"
+ "GL_DRAW_BUFFER6_ATI\0"
+ "GL_DRAW_BUFFER7\0"
+ "GL_DRAW_BUFFER7_ARB\0"
+ "GL_DRAW_BUFFER7_ATI\0"
+ "GL_DRAW_BUFFER8\0"
+ "GL_DRAW_BUFFER8_ARB\0"
+ "GL_DRAW_BUFFER8_ATI\0"
+ "GL_DRAW_BUFFER9\0"
+ "GL_DRAW_BUFFER9_ARB\0"
+ "GL_DRAW_BUFFER9_ATI\0"
+ "GL_DRAW_FRAMEBUFFER\0"
+ "GL_DRAW_FRAMEBUFFER_BINDING_EXT\0"
+ "GL_DRAW_FRAMEBUFFER_EXT\0"
+ "GL_DRAW_PIXEL_TOKEN\0"
+ "GL_DST_ALPHA\0"
+ "GL_DST_COLOR\0"
+ "GL_DU8DV8_ATI\0"
+ "GL_DUDV_ATI\0"
+ "GL_DYNAMIC_COPY\0"
+ "GL_DYNAMIC_COPY_ARB\0"
+ "GL_DYNAMIC_DRAW\0"
+ "GL_DYNAMIC_DRAW_ARB\0"
+ "GL_DYNAMIC_READ\0"
+ "GL_DYNAMIC_READ_ARB\0"
+ "GL_EDGE_FLAG\0"
+ "GL_EDGE_FLAG_ARRAY\0"
+ "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING\0"
+ "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_EDGE_FLAG_ARRAY_POINTER\0"
+ "GL_EDGE_FLAG_ARRAY_STRIDE\0"
+ "GL_ELEMENT_ARRAY_BUFFER\0"
+ "GL_ELEMENT_ARRAY_BUFFER_BINDING\0"
+ "GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_EMISSION\0"
+ "GL_ENABLE_BIT\0"
+ "GL_EQUAL\0"
+ "GL_EQUIV\0"
+ "GL_EVAL_BIT\0"
+ "GL_EXP\0"
+ "GL_EXP2\0"
+ "GL_EXTENSIONS\0"
+ "GL_EYE_LINEAR\0"
+ "GL_EYE_PLANE\0"
+ "GL_EYE_PLANE_ABSOLUTE_NV\0"
+ "GL_EYE_RADIAL_NV\0"
+ "GL_FALSE\0"
+ "GL_FASTEST\0"
+ "GL_FEEDBACK\0"
+ "GL_FEEDBACK_BUFFER_POINTER\0"
+ "GL_FEEDBACK_BUFFER_SIZE\0"
+ "GL_FEEDBACK_BUFFER_TYPE\0"
+ "GL_FILL\0"
+ "GL_FIRST_VERTEX_CONVENTION_EXT\0"
+ "GL_FLAT\0"
+ "GL_FLOAT\0"
+ "GL_FLOAT_MAT2\0"
+ "GL_FLOAT_MAT2_ARB\0"
+ "GL_FLOAT_MAT2x3\0"
+ "GL_FLOAT_MAT2x4\0"
+ "GL_FLOAT_MAT3\0"
+ "GL_FLOAT_MAT3_ARB\0"
+ "GL_FLOAT_MAT3x2\0"
+ "GL_FLOAT_MAT3x4\0"
+ "GL_FLOAT_MAT4\0"
+ "GL_FLOAT_MAT4_ARB\0"
+ "GL_FLOAT_MAT4x2\0"
+ "GL_FLOAT_MAT4x3\0"
+ "GL_FLOAT_VEC2\0"
+ "GL_FLOAT_VEC2_ARB\0"
+ "GL_FLOAT_VEC3\0"
+ "GL_FLOAT_VEC3_ARB\0"
+ "GL_FLOAT_VEC4\0"
+ "GL_FLOAT_VEC4_ARB\0"
+ "GL_FOG\0"
+ "GL_FOG_BIT\0"
+ "GL_FOG_COLOR\0"
+ "GL_FOG_COORD\0"
+ "GL_FOG_COORDINATE\0"
+ "GL_FOG_COORDINATE_ARRAY\0"
+ "GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING\0"
+ "GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_FOG_COORDINATE_ARRAY_POINTER\0"
+ "GL_FOG_COORDINATE_ARRAY_STRIDE\0"
+ "GL_FOG_COORDINATE_ARRAY_TYPE\0"
+ "GL_FOG_COORDINATE_SOURCE\0"
+ "GL_FOG_COORD_ARRAY\0"
+ "GL_FOG_COORD_ARRAY_BUFFER_BINDING\0"
+ "GL_FOG_COORD_ARRAY_POINTER\0"
+ "GL_FOG_COORD_ARRAY_STRIDE\0"
+ "GL_FOG_COORD_ARRAY_TYPE\0"
+ "GL_FOG_COORD_SRC\0"
+ "GL_FOG_DENSITY\0"
+ "GL_FOG_DISTANCE_MODE_NV\0"
+ "GL_FOG_END\0"
+ "GL_FOG_HINT\0"
+ "GL_FOG_INDEX\0"
+ "GL_FOG_MODE\0"
+ "GL_FOG_OFFSET_SGIX\0"
+ "GL_FOG_OFFSET_VALUE_SGIX\0"
+ "GL_FOG_START\0"
+ "GL_FRAGMENT_DEPTH\0"
+ "GL_FRAGMENT_PROGRAM_ARB\0"
+ "GL_FRAGMENT_SHADER\0"
+ "GL_FRAGMENT_SHADER_ARB\0"
+ "GL_FRAGMENT_SHADER_DERIVATIVE_HINT\0"
+ "GL_FRAMEBUFFER\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL\0"
+ "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT\0"
+ "GL_FRAMEBUFFER_BINDING_EXT\0"
+ "GL_FRAMEBUFFER_COMPLETE\0"
+ "GL_FRAMEBUFFER_COMPLETE_EXT\0"
+ "GL_FRAMEBUFFER_DEFAULT\0"
+ "GL_FRAMEBUFFER_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\0"
+ "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\0"
+ "GL_FRAMEBUFFER_STATUS_ERROR_EXT\0"
+ "GL_FRAMEBUFFER_UNDEFINED\0"
+ "GL_FRAMEBUFFER_UNSUPPORTED\0"
+ "GL_FRAMEBUFFER_UNSUPPORTED_EXT\0"
+ "GL_FRONT\0"
+ "GL_FRONT_AND_BACK\0"
+ "GL_FRONT_FACE\0"
+ "GL_FRONT_LEFT\0"
+ "GL_FRONT_RIGHT\0"
+ "GL_FUNC_ADD\0"
+ "GL_FUNC_ADD_EXT\0"
+ "GL_FUNC_REVERSE_SUBTRACT\0"
+ "GL_FUNC_REVERSE_SUBTRACT_EXT\0"
+ "GL_FUNC_SUBTRACT\0"
+ "GL_FUNC_SUBTRACT_EXT\0"
+ "GL_GENERATE_MIPMAP\0"
+ "GL_GENERATE_MIPMAP_HINT\0"
+ "GL_GENERATE_MIPMAP_HINT_SGIS\0"
+ "GL_GENERATE_MIPMAP_SGIS\0"
+ "GL_GEQUAL\0"
+ "GL_GREATER\0"
+ "GL_GREEN\0"
+ "GL_GREEN_BIAS\0"
+ "GL_GREEN_BITS\0"
+ "GL_GREEN_SCALE\0"
+ "GL_HINT_BIT\0"
+ "GL_HISTOGRAM\0"
+ "GL_HISTOGRAM_ALPHA_SIZE\0"
+ "GL_HISTOGRAM_ALPHA_SIZE_EXT\0"
+ "GL_HISTOGRAM_BLUE_SIZE\0"
+ "GL_HISTOGRAM_BLUE_SIZE_EXT\0"
+ "GL_HISTOGRAM_EXT\0"
+ "GL_HISTOGRAM_FORMAT\0"
+ "GL_HISTOGRAM_FORMAT_EXT\0"
+ "GL_HISTOGRAM_GREEN_SIZE\0"
+ "GL_HISTOGRAM_GREEN_SIZE_EXT\0"
+ "GL_HISTOGRAM_LUMINANCE_SIZE\0"
+ "GL_HISTOGRAM_LUMINANCE_SIZE_EXT\0"
+ "GL_HISTOGRAM_RED_SIZE\0"
+ "GL_HISTOGRAM_RED_SIZE_EXT\0"
+ "GL_HISTOGRAM_SINK\0"
+ "GL_HISTOGRAM_SINK_EXT\0"
+ "GL_HISTOGRAM_WIDTH\0"
+ "GL_HISTOGRAM_WIDTH_EXT\0"
+ "GL_IDENTITY_NV\0"
+ "GL_IGNORE_BORDER_HP\0"
+ "GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES\0"
+ "GL_IMPLEMENTATION_COLOR_READ_TYPE_OES\0"
+ "GL_INCR\0"
+ "GL_INCR_WRAP\0"
+ "GL_INCR_WRAP_EXT\0"
+ "GL_INDEX\0"
+ "GL_INDEX_ARRAY\0"
+ "GL_INDEX_ARRAY_BUFFER_BINDING\0"
+ "GL_INDEX_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_INDEX_ARRAY_POINTER\0"
+ "GL_INDEX_ARRAY_STRIDE\0"
+ "GL_INDEX_ARRAY_TYPE\0"
+ "GL_INDEX_BITS\0"
+ "GL_INDEX_CLEAR_VALUE\0"
+ "GL_INDEX_LOGIC_OP\0"
+ "GL_INDEX_MODE\0"
+ "GL_INDEX_OFFSET\0"
+ "GL_INDEX_SHIFT\0"
+ "GL_INDEX_WRITEMASK\0"
+ "GL_INFO_LOG_LENGTH\0"
+ "GL_INT\0"
+ "GL_INTENSITY\0"
+ "GL_INTENSITY12\0"
+ "GL_INTENSITY12_EXT\0"
+ "GL_INTENSITY16\0"
+ "GL_INTENSITY16_EXT\0"
+ "GL_INTENSITY4\0"
+ "GL_INTENSITY4_EXT\0"
+ "GL_INTENSITY8\0"
+ "GL_INTENSITY8_EXT\0"
+ "GL_INTENSITY_EXT\0"
+ "GL_INTERPOLATE\0"
+ "GL_INTERPOLATE_ARB\0"
+ "GL_INTERPOLATE_EXT\0"
+ "GL_INT_VEC2\0"
+ "GL_INT_VEC2_ARB\0"
+ "GL_INT_VEC3\0"
+ "GL_INT_VEC3_ARB\0"
+ "GL_INT_VEC4\0"
+ "GL_INT_VEC4_ARB\0"
+ "GL_INVALID_ENUM\0"
+ "GL_INVALID_FRAMEBUFFER_OPERATION\0"
+ "GL_INVALID_FRAMEBUFFER_OPERATION_EXT\0"
+ "GL_INVALID_OPERATION\0"
+ "GL_INVALID_VALUE\0"
+ "GL_INVERSE_NV\0"
+ "GL_INVERSE_TRANSPOSE_NV\0"
+ "GL_INVERT\0"
+ "GL_KEEP\0"
+ "GL_LAST_VERTEX_CONVENTION_EXT\0"
+ "GL_LEFT\0"
+ "GL_LEQUAL\0"
+ "GL_LESS\0"
+ "GL_LIGHT0\0"
+ "GL_LIGHT1\0"
+ "GL_LIGHT2\0"
+ "GL_LIGHT3\0"
+ "GL_LIGHT4\0"
+ "GL_LIGHT5\0"
+ "GL_LIGHT6\0"
+ "GL_LIGHT7\0"
+ "GL_LIGHTING\0"
+ "GL_LIGHTING_BIT\0"
+ "GL_LIGHT_MODEL_AMBIENT\0"
+ "GL_LIGHT_MODEL_COLOR_CONTROL\0"
+ "GL_LIGHT_MODEL_COLOR_CONTROL_EXT\0"
+ "GL_LIGHT_MODEL_LOCAL_VIEWER\0"
+ "GL_LIGHT_MODEL_TWO_SIDE\0"
+ "GL_LINE\0"
+ "GL_LINEAR\0"
+ "GL_LINEAR_ATTENUATION\0"
+ "GL_LINEAR_CLIPMAP_LINEAR_SGIX\0"
+ "GL_LINEAR_CLIPMAP_NEAREST_SGIX\0"
+ "GL_LINEAR_MIPMAP_LINEAR\0"
+ "GL_LINEAR_MIPMAP_NEAREST\0"
+ "GL_LINES\0"
+ "GL_LINE_BIT\0"
+ "GL_LINE_LOOP\0"
+ "GL_LINE_RESET_TOKEN\0"
+ "GL_LINE_SMOOTH\0"
+ "GL_LINE_SMOOTH_HINT\0"
+ "GL_LINE_STIPPLE\0"
+ "GL_LINE_STIPPLE_PATTERN\0"
+ "GL_LINE_STIPPLE_REPEAT\0"
+ "GL_LINE_STRIP\0"
+ "GL_LINE_TOKEN\0"
+ "GL_LINE_WIDTH\0"
+ "GL_LINE_WIDTH_GRANULARITY\0"
+ "GL_LINE_WIDTH_RANGE\0"
+ "GL_LINK_STATUS\0"
+ "GL_LIST_BASE\0"
+ "GL_LIST_BIT\0"
+ "GL_LIST_INDEX\0"
+ "GL_LIST_MODE\0"
+ "GL_LOAD\0"
+ "GL_LOGIC_OP\0"
+ "GL_LOGIC_OP_MODE\0"
+ "GL_LOWER_LEFT\0"
+ "GL_LUMINANCE\0"
+ "GL_LUMINANCE12\0"
+ "GL_LUMINANCE12_ALPHA12\0"
+ "GL_LUMINANCE12_ALPHA12_EXT\0"
+ "GL_LUMINANCE12_ALPHA4\0"
+ "GL_LUMINANCE12_ALPHA4_EXT\0"
+ "GL_LUMINANCE12_EXT\0"
+ "GL_LUMINANCE16\0"
+ "GL_LUMINANCE16_ALPHA16\0"
+ "GL_LUMINANCE16_ALPHA16_EXT\0"
+ "GL_LUMINANCE16_EXT\0"
+ "GL_LUMINANCE4\0"
+ "GL_LUMINANCE4_ALPHA4\0"
+ "GL_LUMINANCE4_ALPHA4_EXT\0"
+ "GL_LUMINANCE4_EXT\0"
+ "GL_LUMINANCE6_ALPHA2\0"
+ "GL_LUMINANCE6_ALPHA2_EXT\0"
+ "GL_LUMINANCE8\0"
+ "GL_LUMINANCE8_ALPHA8\0"
+ "GL_LUMINANCE8_ALPHA8_EXT\0"
+ "GL_LUMINANCE8_EXT\0"
+ "GL_LUMINANCE_ALPHA\0"
+ "GL_MAP1_COLOR_4\0"
+ "GL_MAP1_GRID_DOMAIN\0"
+ "GL_MAP1_GRID_SEGMENTS\0"
+ "GL_MAP1_INDEX\0"
+ "GL_MAP1_NORMAL\0"
+ "GL_MAP1_TEXTURE_COORD_1\0"
+ "GL_MAP1_TEXTURE_COORD_2\0"
+ "GL_MAP1_TEXTURE_COORD_3\0"
+ "GL_MAP1_TEXTURE_COORD_4\0"
+ "GL_MAP1_VERTEX_3\0"
+ "GL_MAP1_VERTEX_4\0"
+ "GL_MAP1_VERTEX_ATTRIB0_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB10_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB11_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB12_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB13_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB14_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB15_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB1_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB2_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB3_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB4_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB5_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB6_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB7_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB8_4_NV\0"
+ "GL_MAP1_VERTEX_ATTRIB9_4_NV\0"
+ "GL_MAP2_COLOR_4\0"
+ "GL_MAP2_GRID_DOMAIN\0"
+ "GL_MAP2_GRID_SEGMENTS\0"
+ "GL_MAP2_INDEX\0"
+ "GL_MAP2_NORMAL\0"
+ "GL_MAP2_TEXTURE_COORD_1\0"
+ "GL_MAP2_TEXTURE_COORD_2\0"
+ "GL_MAP2_TEXTURE_COORD_3\0"
+ "GL_MAP2_TEXTURE_COORD_4\0"
+ "GL_MAP2_VERTEX_3\0"
+ "GL_MAP2_VERTEX_4\0"
+ "GL_MAP2_VERTEX_ATTRIB0_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB10_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB11_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB12_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB13_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB14_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB15_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB1_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB2_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB3_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB4_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB5_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB6_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB7_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB8_4_NV\0"
+ "GL_MAP2_VERTEX_ATTRIB9_4_NV\0"
+ "GL_MAP_COLOR\0"
+ "GL_MAP_FLUSH_EXPLICIT_BIT\0"
+ "GL_MAP_INVALIDATE_BUFFER_BIT\0"
+ "GL_MAP_INVALIDATE_RANGE_BIT\0"
+ "GL_MAP_READ_BIT\0"
+ "GL_MAP_STENCIL\0"
+ "GL_MAP_UNSYNCHRONIZED_BIT\0"
+ "GL_MAP_WRITE_BIT\0"
+ "GL_MATRIX0_ARB\0"
+ "GL_MATRIX0_NV\0"
+ "GL_MATRIX10_ARB\0"
+ "GL_MATRIX11_ARB\0"
+ "GL_MATRIX12_ARB\0"
+ "GL_MATRIX13_ARB\0"
+ "GL_MATRIX14_ARB\0"
+ "GL_MATRIX15_ARB\0"
+ "GL_MATRIX16_ARB\0"
+ "GL_MATRIX17_ARB\0"
+ "GL_MATRIX18_ARB\0"
+ "GL_MATRIX19_ARB\0"
+ "GL_MATRIX1_ARB\0"
+ "GL_MATRIX1_NV\0"
+ "GL_MATRIX20_ARB\0"
+ "GL_MATRIX21_ARB\0"
+ "GL_MATRIX22_ARB\0"
+ "GL_MATRIX23_ARB\0"
+ "GL_MATRIX24_ARB\0"
+ "GL_MATRIX25_ARB\0"
+ "GL_MATRIX26_ARB\0"
+ "GL_MATRIX27_ARB\0"
+ "GL_MATRIX28_ARB\0"
+ "GL_MATRIX29_ARB\0"
+ "GL_MATRIX2_ARB\0"
+ "GL_MATRIX2_NV\0"
+ "GL_MATRIX30_ARB\0"
+ "GL_MATRIX31_ARB\0"
+ "GL_MATRIX3_ARB\0"
+ "GL_MATRIX3_NV\0"
+ "GL_MATRIX4_ARB\0"
+ "GL_MATRIX4_NV\0"
+ "GL_MATRIX5_ARB\0"
+ "GL_MATRIX5_NV\0"
+ "GL_MATRIX6_ARB\0"
+ "GL_MATRIX6_NV\0"
+ "GL_MATRIX7_ARB\0"
+ "GL_MATRIX7_NV\0"
+ "GL_MATRIX8_ARB\0"
+ "GL_MATRIX9_ARB\0"
+ "GL_MATRIX_INDEX_ARRAY_ARB\0"
+ "GL_MATRIX_INDEX_ARRAY_POINTER_ARB\0"
+ "GL_MATRIX_INDEX_ARRAY_SIZE_ARB\0"
+ "GL_MATRIX_INDEX_ARRAY_STRIDE_ARB\0"
+ "GL_MATRIX_INDEX_ARRAY_TYPE_ARB\0"
+ "GL_MATRIX_MODE\0"
+ "GL_MATRIX_PALETTE_ARB\0"
+ "GL_MAX\0"
+ "GL_MAX_3D_TEXTURE_SIZE\0"
+ "GL_MAX_ARRAY_TEXTURE_LAYERS_EXT\0"
+ "GL_MAX_ATTRIB_STACK_DEPTH\0"
+ "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH\0"
+ "GL_MAX_CLIPMAP_DEPTH_SGIX\0"
+ "GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX\0"
+ "GL_MAX_CLIP_PLANES\0"
+ "GL_MAX_COLOR_ATTACHMENTS_EXT\0"
+ "GL_MAX_COLOR_MATRIX_STACK_DEPTH\0"
+ "GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI\0"
+ "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS\0"
+ "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB\0"
+ "GL_MAX_CONVOLUTION_HEIGHT\0"
+ "GL_MAX_CONVOLUTION_HEIGHT_EXT\0"
+ "GL_MAX_CONVOLUTION_WIDTH\0"
+ "GL_MAX_CONVOLUTION_WIDTH_EXT\0"
+ "GL_MAX_CUBE_MAP_TEXTURE_SIZE\0"
+ "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB\0"
+ "GL_MAX_DRAW_BUFFERS\0"
+ "GL_MAX_DRAW_BUFFERS_ARB\0"
+ "GL_MAX_DRAW_BUFFERS_ATI\0"
+ "GL_MAX_ELEMENTS_INDICES\0"
+ "GL_MAX_ELEMENTS_VERTICES\0"
+ "GL_MAX_EVAL_ORDER\0"
+ "GL_MAX_EXT\0"
+ "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS\0"
+ "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB\0"
+ "GL_MAX_LIGHTS\0"
+ "GL_MAX_LIST_NESTING\0"
+ "GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB\0"
+ "GL_MAX_MODELVIEW_STACK_DEPTH\0"
+ "GL_MAX_NAME_STACK_DEPTH\0"
+ "GL_MAX_PALETTE_MATRICES_ARB\0"
+ "GL_MAX_PIXEL_MAP_TABLE\0"
+ "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB\0"
+ "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROGRAM_ATTRIBS_ARB\0"
+ "GL_MAX_PROGRAM_CALL_DEPTH_NV\0"
+ "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB\0"
+ "GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV\0"
+ "GL_MAX_PROGRAM_IF_DEPTH_NV\0"
+ "GL_MAX_PROGRAM_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB\0"
+ "GL_MAX_PROGRAM_LOOP_COUNT_NV\0"
+ "GL_MAX_PROGRAM_LOOP_DEPTH_NV\0"
+ "GL_MAX_PROGRAM_MATRICES_ARB\0"
+ "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB\0"
+ "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROGRAM_PARAMETERS_ARB\0"
+ "GL_MAX_PROGRAM_TEMPORARIES_ARB\0"
+ "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB\0"
+ "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB\0"
+ "GL_MAX_PROJECTION_STACK_DEPTH\0"
+ "GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB\0"
+ "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV\0"
+ "GL_MAX_RENDERBUFFER_SIZE_EXT\0"
+ "GL_MAX_SAMPLES\0"
+ "GL_MAX_SERVER_WAIT_TIMEOUT\0"
+ "GL_MAX_SHININESS_NV\0"
+ "GL_MAX_SPOT_EXPONENT_NV\0"
+ "GL_MAX_TEXTURE_COORDS\0"
+ "GL_MAX_TEXTURE_COORDS_ARB\0"
+ "GL_MAX_TEXTURE_IMAGE_UNITS\0"
+ "GL_MAX_TEXTURE_IMAGE_UNITS_ARB\0"
+ "GL_MAX_TEXTURE_LOD_BIAS\0"
+ "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT\0"
+ "GL_MAX_TEXTURE_SIZE\0"
+ "GL_MAX_TEXTURE_STACK_DEPTH\0"
+ "GL_MAX_TEXTURE_UNITS\0"
+ "GL_MAX_TEXTURE_UNITS_ARB\0"
+ "GL_MAX_TRACK_MATRICES_NV\0"
+ "GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV\0"
+ "GL_MAX_VARYING_FLOATS\0"
+ "GL_MAX_VARYING_FLOATS_ARB\0"
+ "GL_MAX_VERTEX_ATTRIBS\0"
+ "GL_MAX_VERTEX_ATTRIBS_ARB\0"
+ "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS\0"
+ "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB\0"
+ "GL_MAX_VERTEX_UNIFORM_COMPONENTS\0"
+ "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB\0"
+ "GL_MAX_VERTEX_UNITS_ARB\0"
+ "GL_MAX_VIEWPORT_DIMS\0"
+ "GL_MIN\0"
+ "GL_MINMAX\0"
+ "GL_MINMAX_EXT\0"
+ "GL_MINMAX_FORMAT\0"
+ "GL_MINMAX_FORMAT_EXT\0"
+ "GL_MINMAX_SINK\0"
+ "GL_MINMAX_SINK_EXT\0"
+ "GL_MIN_EXT\0"
+ "GL_MIRRORED_REPEAT\0"
+ "GL_MIRRORED_REPEAT_ARB\0"
+ "GL_MIRRORED_REPEAT_IBM\0"
+ "GL_MIRROR_CLAMP_ATI\0"
+ "GL_MIRROR_CLAMP_EXT\0"
+ "GL_MIRROR_CLAMP_TO_BORDER_EXT\0"
+ "GL_MIRROR_CLAMP_TO_EDGE_ATI\0"
+ "GL_MIRROR_CLAMP_TO_EDGE_EXT\0"
+ "GL_MODELVIEW\0"
+ "GL_MODELVIEW0_ARB\0"
+ "GL_MODELVIEW10_ARB\0"
+ "GL_MODELVIEW11_ARB\0"
+ "GL_MODELVIEW12_ARB\0"
+ "GL_MODELVIEW13_ARB\0"
+ "GL_MODELVIEW14_ARB\0"
+ "GL_MODELVIEW15_ARB\0"
+ "GL_MODELVIEW16_ARB\0"
+ "GL_MODELVIEW17_ARB\0"
+ "GL_MODELVIEW18_ARB\0"
+ "GL_MODELVIEW19_ARB\0"
+ "GL_MODELVIEW1_ARB\0"
+ "GL_MODELVIEW20_ARB\0"
+ "GL_MODELVIEW21_ARB\0"
+ "GL_MODELVIEW22_ARB\0"
+ "GL_MODELVIEW23_ARB\0"
+ "GL_MODELVIEW24_ARB\0"
+ "GL_MODELVIEW25_ARB\0"
+ "GL_MODELVIEW26_ARB\0"
+ "GL_MODELVIEW27_ARB\0"
+ "GL_MODELVIEW28_ARB\0"
+ "GL_MODELVIEW29_ARB\0"
+ "GL_MODELVIEW2_ARB\0"
+ "GL_MODELVIEW30_ARB\0"
+ "GL_MODELVIEW31_ARB\0"
+ "GL_MODELVIEW3_ARB\0"
+ "GL_MODELVIEW4_ARB\0"
+ "GL_MODELVIEW5_ARB\0"
+ "GL_MODELVIEW6_ARB\0"
+ "GL_MODELVIEW7_ARB\0"
+ "GL_MODELVIEW8_ARB\0"
+ "GL_MODELVIEW9_ARB\0"
+ "GL_MODELVIEW_MATRIX\0"
+ "GL_MODELVIEW_PROJECTION_NV\0"
+ "GL_MODELVIEW_STACK_DEPTH\0"
+ "GL_MODULATE\0"
+ "GL_MODULATE_ADD_ATI\0"
+ "GL_MODULATE_SIGNED_ADD_ATI\0"
+ "GL_MODULATE_SUBTRACT_ATI\0"
+ "GL_MULT\0"
+ "GL_MULTISAMPLE\0"
+ "GL_MULTISAMPLE_3DFX\0"
+ "GL_MULTISAMPLE_ARB\0"
+ "GL_MULTISAMPLE_BIT\0"
+ "GL_MULTISAMPLE_BIT_3DFX\0"
+ "GL_MULTISAMPLE_BIT_ARB\0"
+ "GL_MULTISAMPLE_FILTER_HINT_NV\0"
+ "GL_N3F_V3F\0"
+ "GL_NAME_STACK_DEPTH\0"
+ "GL_NAND\0"
+ "GL_NEAREST\0"
+ "GL_NEAREST_CLIPMAP_LINEAR_SGIX\0"
+ "GL_NEAREST_CLIPMAP_NEAREST_SGIX\0"
+ "GL_NEAREST_MIPMAP_LINEAR\0"
+ "GL_NEAREST_MIPMAP_NEAREST\0"
+ "GL_NEVER\0"
+ "GL_NICEST\0"
+ "GL_NONE\0"
+ "GL_NOOP\0"
+ "GL_NOR\0"
+ "GL_NORMALIZE\0"
+ "GL_NORMAL_ARRAY\0"
+ "GL_NORMAL_ARRAY_BUFFER_BINDING\0"
+ "GL_NORMAL_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_NORMAL_ARRAY_POINTER\0"
+ "GL_NORMAL_ARRAY_STRIDE\0"
+ "GL_NORMAL_ARRAY_TYPE\0"
+ "GL_NORMAL_MAP\0"
+ "GL_NORMAL_MAP_ARB\0"
+ "GL_NORMAL_MAP_NV\0"
+ "GL_NOTEQUAL\0"
+ "GL_NO_ERROR\0"
+ "GL_NUM_COMPRESSED_TEXTURE_FORMATS\0"
+ "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB\0"
+ "GL_OBJECT_ACTIVE_ATTRIBUTES_ARB\0"
+ "GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB\0"
+ "GL_OBJECT_ACTIVE_UNIFORMS_ARB\0"
+ "GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB\0"
+ "GL_OBJECT_ATTACHED_OBJECTS_ARB\0"
+ "GL_OBJECT_COMPILE_STATUS_ARB\0"
+ "GL_OBJECT_DELETE_STATUS_ARB\0"
+ "GL_OBJECT_INFO_LOG_LENGTH_ARB\0"
+ "GL_OBJECT_LINEAR\0"
+ "GL_OBJECT_LINK_STATUS_ARB\0"
+ "GL_OBJECT_PLANE\0"
+ "GL_OBJECT_SHADER_SOURCE_LENGTH_ARB\0"
+ "GL_OBJECT_SUBTYPE_ARB\0"
+ "GL_OBJECT_TYPE\0"
+ "GL_OBJECT_TYPE_ARB\0"
+ "GL_OBJECT_VALIDATE_STATUS_ARB\0"
+ "GL_OCCLUSION_TEST_HP\0"
+ "GL_OCCLUSION_TEST_RESULT_HP\0"
+ "GL_ONE\0"
+ "GL_ONE_MINUS_CONSTANT_ALPHA\0"
+ "GL_ONE_MINUS_CONSTANT_ALPHA_EXT\0"
+ "GL_ONE_MINUS_CONSTANT_COLOR\0"
+ "GL_ONE_MINUS_CONSTANT_COLOR_EXT\0"
+ "GL_ONE_MINUS_DST_ALPHA\0"
+ "GL_ONE_MINUS_DST_COLOR\0"
+ "GL_ONE_MINUS_SRC_ALPHA\0"
+ "GL_ONE_MINUS_SRC_COLOR\0"
+ "GL_OPERAND0_ALPHA\0"
+ "GL_OPERAND0_ALPHA_ARB\0"
+ "GL_OPERAND0_ALPHA_EXT\0"
+ "GL_OPERAND0_RGB\0"
+ "GL_OPERAND0_RGB_ARB\0"
+ "GL_OPERAND0_RGB_EXT\0"
+ "GL_OPERAND1_ALPHA\0"
+ "GL_OPERAND1_ALPHA_ARB\0"
+ "GL_OPERAND1_ALPHA_EXT\0"
+ "GL_OPERAND1_RGB\0"
+ "GL_OPERAND1_RGB_ARB\0"
+ "GL_OPERAND1_RGB_EXT\0"
+ "GL_OPERAND2_ALPHA\0"
+ "GL_OPERAND2_ALPHA_ARB\0"
+ "GL_OPERAND2_ALPHA_EXT\0"
+ "GL_OPERAND2_RGB\0"
+ "GL_OPERAND2_RGB_ARB\0"
+ "GL_OPERAND2_RGB_EXT\0"
+ "GL_OPERAND3_ALPHA_NV\0"
+ "GL_OPERAND3_RGB_NV\0"
+ "GL_OR\0"
+ "GL_ORDER\0"
+ "GL_OR_INVERTED\0"
+ "GL_OR_REVERSE\0"
+ "GL_OUT_OF_MEMORY\0"
+ "GL_PACK_ALIGNMENT\0"
+ "GL_PACK_IMAGE_HEIGHT\0"
+ "GL_PACK_INVERT_MESA\0"
+ "GL_PACK_LSB_FIRST\0"
+ "GL_PACK_ROW_LENGTH\0"
+ "GL_PACK_SKIP_IMAGES\0"
+ "GL_PACK_SKIP_PIXELS\0"
+ "GL_PACK_SKIP_ROWS\0"
+ "GL_PACK_SWAP_BYTES\0"
+ "GL_PALETTE4_R5_G6_B5_OES\0"
+ "GL_PALETTE4_RGB5_A1_OES\0"
+ "GL_PALETTE4_RGB8_OES\0"
+ "GL_PALETTE4_RGBA4_OES\0"
+ "GL_PALETTE4_RGBA8_OES\0"
+ "GL_PALETTE8_R5_G6_B5_OES\0"
+ "GL_PALETTE8_RGB5_A1_OES\0"
+ "GL_PALETTE8_RGB8_OES\0"
+ "GL_PALETTE8_RGBA4_OES\0"
+ "GL_PALETTE8_RGBA8_OES\0"
+ "GL_PASS_THROUGH_TOKEN\0"
+ "GL_PERSPECTIVE_CORRECTION_HINT\0"
+ "GL_PIXEL_MAP_A_TO_A\0"
+ "GL_PIXEL_MAP_A_TO_A_SIZE\0"
+ "GL_PIXEL_MAP_B_TO_B\0"
+ "GL_PIXEL_MAP_B_TO_B_SIZE\0"
+ "GL_PIXEL_MAP_G_TO_G\0"
+ "GL_PIXEL_MAP_G_TO_G_SIZE\0"
+ "GL_PIXEL_MAP_I_TO_A\0"
+ "GL_PIXEL_MAP_I_TO_A_SIZE\0"
+ "GL_PIXEL_MAP_I_TO_B\0"
+ "GL_PIXEL_MAP_I_TO_B_SIZE\0"
+ "GL_PIXEL_MAP_I_TO_G\0"
+ "GL_PIXEL_MAP_I_TO_G_SIZE\0"
+ "GL_PIXEL_MAP_I_TO_I\0"
+ "GL_PIXEL_MAP_I_TO_I_SIZE\0"
+ "GL_PIXEL_MAP_I_TO_R\0"
+ "GL_PIXEL_MAP_I_TO_R_SIZE\0"
+ "GL_PIXEL_MAP_R_TO_R\0"
+ "GL_PIXEL_MAP_R_TO_R_SIZE\0"
+ "GL_PIXEL_MAP_S_TO_S\0"
+ "GL_PIXEL_MAP_S_TO_S_SIZE\0"
+ "GL_PIXEL_MODE_BIT\0"
+ "GL_PIXEL_PACK_BUFFER\0"
+ "GL_PIXEL_PACK_BUFFER_BINDING\0"
+ "GL_PIXEL_PACK_BUFFER_BINDING_EXT\0"
+ "GL_PIXEL_PACK_BUFFER_EXT\0"
+ "GL_PIXEL_UNPACK_BUFFER\0"
+ "GL_PIXEL_UNPACK_BUFFER_BINDING\0"
+ "GL_PIXEL_UNPACK_BUFFER_BINDING_EXT\0"
+ "GL_PIXEL_UNPACK_BUFFER_EXT\0"
+ "GL_POINT\0"
+ "GL_POINTS\0"
+ "GL_POINT_BIT\0"
+ "GL_POINT_DISTANCE_ATTENUATION\0"
+ "GL_POINT_DISTANCE_ATTENUATION_ARB\0"
+ "GL_POINT_DISTANCE_ATTENUATION_EXT\0"
+ "GL_POINT_DISTANCE_ATTENUATION_SGIS\0"
+ "GL_POINT_FADE_THRESHOLD_SIZE\0"
+ "GL_POINT_FADE_THRESHOLD_SIZE_ARB\0"
+ "GL_POINT_FADE_THRESHOLD_SIZE_EXT\0"
+ "GL_POINT_FADE_THRESHOLD_SIZE_SGIS\0"
+ "GL_POINT_SIZE\0"
+ "GL_POINT_SIZE_GRANULARITY\0"
+ "GL_POINT_SIZE_MAX\0"
+ "GL_POINT_SIZE_MAX_ARB\0"
+ "GL_POINT_SIZE_MAX_EXT\0"
+ "GL_POINT_SIZE_MAX_SGIS\0"
+ "GL_POINT_SIZE_MIN\0"
+ "GL_POINT_SIZE_MIN_ARB\0"
+ "GL_POINT_SIZE_MIN_EXT\0"
+ "GL_POINT_SIZE_MIN_SGIS\0"
+ "GL_POINT_SIZE_RANGE\0"
+ "GL_POINT_SMOOTH\0"
+ "GL_POINT_SMOOTH_HINT\0"
+ "GL_POINT_SPRITE\0"
+ "GL_POINT_SPRITE_ARB\0"
+ "GL_POINT_SPRITE_COORD_ORIGIN\0"
+ "GL_POINT_SPRITE_NV\0"
+ "GL_POINT_SPRITE_R_MODE_NV\0"
+ "GL_POINT_TOKEN\0"
+ "GL_POLYGON\0"
+ "GL_POLYGON_BIT\0"
+ "GL_POLYGON_MODE\0"
+ "GL_POLYGON_OFFSET_BIAS\0"
+ "GL_POLYGON_OFFSET_FACTOR\0"
+ "GL_POLYGON_OFFSET_FILL\0"
+ "GL_POLYGON_OFFSET_LINE\0"
+ "GL_POLYGON_OFFSET_POINT\0"
+ "GL_POLYGON_OFFSET_UNITS\0"
+ "GL_POLYGON_SMOOTH\0"
+ "GL_POLYGON_SMOOTH_HINT\0"
+ "GL_POLYGON_STIPPLE\0"
+ "GL_POLYGON_STIPPLE_BIT\0"
+ "GL_POLYGON_TOKEN\0"
+ "GL_POSITION\0"
+ "GL_POST_COLOR_MATRIX_ALPHA_BIAS\0"
+ "GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI\0"
+ "GL_POST_COLOR_MATRIX_ALPHA_SCALE\0"
+ "GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI\0"
+ "GL_POST_COLOR_MATRIX_BLUE_BIAS\0"
+ "GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI\0"
+ "GL_POST_COLOR_MATRIX_BLUE_SCALE\0"
+ "GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI\0"
+ "GL_POST_COLOR_MATRIX_COLOR_TABLE\0"
+ "GL_POST_COLOR_MATRIX_GREEN_BIAS\0"
+ "GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI\0"
+ "GL_POST_COLOR_MATRIX_GREEN_SCALE\0"
+ "GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI\0"
+ "GL_POST_COLOR_MATRIX_RED_BIAS\0"
+ "GL_POST_COLOR_MATRIX_RED_BIAS_SGI\0"
+ "GL_POST_COLOR_MATRIX_RED_SCALE\0"
+ "GL_POST_COLOR_MATRIX_RED_SCALE_SGI\0"
+ "GL_POST_CONVOLUTION_ALPHA_BIAS\0"
+ "GL_POST_CONVOLUTION_ALPHA_BIAS_EXT\0"
+ "GL_POST_CONVOLUTION_ALPHA_SCALE\0"
+ "GL_POST_CONVOLUTION_ALPHA_SCALE_EXT\0"
+ "GL_POST_CONVOLUTION_BLUE_BIAS\0"
+ "GL_POST_CONVOLUTION_BLUE_BIAS_EXT\0"
+ "GL_POST_CONVOLUTION_BLUE_SCALE\0"
+ "GL_POST_CONVOLUTION_BLUE_SCALE_EXT\0"
+ "GL_POST_CONVOLUTION_COLOR_TABLE\0"
+ "GL_POST_CONVOLUTION_GREEN_BIAS\0"
+ "GL_POST_CONVOLUTION_GREEN_BIAS_EXT\0"
+ "GL_POST_CONVOLUTION_GREEN_SCALE\0"
+ "GL_POST_CONVOLUTION_GREEN_SCALE_EXT\0"
+ "GL_POST_CONVOLUTION_RED_BIAS\0"
+ "GL_POST_CONVOLUTION_RED_BIAS_EXT\0"
+ "GL_POST_CONVOLUTION_RED_SCALE\0"
+ "GL_POST_CONVOLUTION_RED_SCALE_EXT\0"
+ "GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX\0"
+ "GL_POST_TEXTURE_FILTER_BIAS_SGIX\0"
+ "GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX\0"
+ "GL_POST_TEXTURE_FILTER_SCALE_SGIX\0"
+ "GL_PREVIOUS\0"
+ "GL_PREVIOUS_ARB\0"
+ "GL_PREVIOUS_EXT\0"
+ "GL_PRIMARY_COLOR\0"
+ "GL_PRIMARY_COLOR_ARB\0"
+ "GL_PRIMARY_COLOR_EXT\0"
+ "GL_PROGRAM_ADDRESS_REGISTERS_ARB\0"
+ "GL_PROGRAM_ALU_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_ATTRIBS_ARB\0"
+ "GL_PROGRAM_BINDING_ARB\0"
+ "GL_PROGRAM_ERROR_POSITION_ARB\0"
+ "GL_PROGRAM_ERROR_POSITION_NV\0"
+ "GL_PROGRAM_ERROR_STRING_ARB\0"
+ "GL_PROGRAM_FORMAT_ARB\0"
+ "GL_PROGRAM_FORMAT_ASCII_ARB\0"
+ "GL_PROGRAM_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_LENGTH_ARB\0"
+ "GL_PROGRAM_LENGTH_NV\0"
+ "GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB\0"
+ "GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_NATIVE_ATTRIBS_ARB\0"
+ "GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_NATIVE_PARAMETERS_ARB\0"
+ "GL_PROGRAM_NATIVE_TEMPORARIES_ARB\0"
+ "GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB\0"
+ "GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_OBJECT_ARB\0"
+ "GL_PROGRAM_PARAMETERS_ARB\0"
+ "GL_PROGRAM_PARAMETER_NV\0"
+ "GL_PROGRAM_RESIDENT_NV\0"
+ "GL_PROGRAM_STRING_ARB\0"
+ "GL_PROGRAM_STRING_NV\0"
+ "GL_PROGRAM_TARGET_NV\0"
+ "GL_PROGRAM_TEMPORARIES_ARB\0"
+ "GL_PROGRAM_TEX_INDIRECTIONS_ARB\0"
+ "GL_PROGRAM_TEX_INSTRUCTIONS_ARB\0"
+ "GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB\0"
+ "GL_PROJECTION\0"
+ "GL_PROJECTION_MATRIX\0"
+ "GL_PROJECTION_STACK_DEPTH\0"
+ "GL_PROVOKING_VERTEX_EXT\0"
+ "GL_PROXY_COLOR_TABLE\0"
+ "GL_PROXY_HISTOGRAM\0"
+ "GL_PROXY_HISTOGRAM_EXT\0"
+ "GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE\0"
+ "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE\0"
+ "GL_PROXY_TEXTURE_1D\0"
+ "GL_PROXY_TEXTURE_1D_ARRAY_EXT\0"
+ "GL_PROXY_TEXTURE_1D_EXT\0"
+ "GL_PROXY_TEXTURE_2D\0"
+ "GL_PROXY_TEXTURE_2D_ARRAY_EXT\0"
+ "GL_PROXY_TEXTURE_2D_EXT\0"
+ "GL_PROXY_TEXTURE_3D\0"
+ "GL_PROXY_TEXTURE_COLOR_TABLE_SGI\0"
+ "GL_PROXY_TEXTURE_CUBE_MAP\0"
+ "GL_PROXY_TEXTURE_CUBE_MAP_ARB\0"
+ "GL_PROXY_TEXTURE_RECTANGLE_ARB\0"
+ "GL_PROXY_TEXTURE_RECTANGLE_NV\0"
+ "GL_Q\0"
+ "GL_QUADRATIC_ATTENUATION\0"
+ "GL_QUADS\0"
+ "GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT\0"
+ "GL_QUAD_MESH_SUN\0"
+ "GL_QUAD_STRIP\0"
+ "GL_QUERY_COUNTER_BITS\0"
+ "GL_QUERY_COUNTER_BITS_ARB\0"
+ "GL_QUERY_RESULT\0"
+ "GL_QUERY_RESULT_ARB\0"
+ "GL_QUERY_RESULT_AVAILABLE\0"
+ "GL_QUERY_RESULT_AVAILABLE_ARB\0"
+ "GL_R\0"
+ "GL_R3_G3_B2\0"
+ "GL_RASTER_POSITION_UNCLIPPED_IBM\0"
+ "GL_READ_BUFFER\0"
+ "GL_READ_FRAMEBUFFER\0"
+ "GL_READ_FRAMEBUFFER_BINDING_EXT\0"
+ "GL_READ_FRAMEBUFFER_EXT\0"
+ "GL_READ_ONLY\0"
+ "GL_READ_ONLY_ARB\0"
+ "GL_READ_WRITE\0"
+ "GL_READ_WRITE_ARB\0"
+ "GL_RED\0"
+ "GL_REDUCE\0"
+ "GL_REDUCE_EXT\0"
+ "GL_RED_BIAS\0"
+ "GL_RED_BITS\0"
+ "GL_RED_SCALE\0"
+ "GL_REFLECTION_MAP\0"
+ "GL_REFLECTION_MAP_ARB\0"
+ "GL_REFLECTION_MAP_NV\0"
+ "GL_RENDER\0"
+ "GL_RENDERBUFFER\0"
+ "GL_RENDERBUFFER_ALPHA_SIZE\0"
+ "GL_RENDERBUFFER_BINDING_EXT\0"
+ "GL_RENDERBUFFER_BLUE_SIZE\0"
+ "GL_RENDERBUFFER_DEPTH_SIZE\0"
+ "GL_RENDERBUFFER_EXT\0"
+ "GL_RENDERBUFFER_GREEN_SIZE\0"
+ "GL_RENDERBUFFER_HEIGHT\0"
+ "GL_RENDERBUFFER_HEIGHT_EXT\0"
+ "GL_RENDERBUFFER_INTERNAL_FORMAT\0"
+ "GL_RENDERBUFFER_INTERNAL_FORMAT_EXT\0"
+ "GL_RENDERBUFFER_RED_SIZE\0"
+ "GL_RENDERBUFFER_SAMPLES\0"
+ "GL_RENDERBUFFER_STENCIL_SIZE\0"
+ "GL_RENDERBUFFER_WIDTH\0"
+ "GL_RENDERBUFFER_WIDTH_EXT\0"
+ "GL_RENDERER\0"
+ "GL_RENDER_MODE\0"
+ "GL_REPEAT\0"
+ "GL_REPLACE\0"
+ "GL_REPLACE_EXT\0"
+ "GL_REPLICATE_BORDER_HP\0"
+ "GL_RESCALE_NORMAL\0"
+ "GL_RESCALE_NORMAL_EXT\0"
+ "GL_RETURN\0"
+ "GL_RGB\0"
+ "GL_RGB10\0"
+ "GL_RGB10_A2\0"
+ "GL_RGB10_A2_EXT\0"
+ "GL_RGB10_EXT\0"
+ "GL_RGB12\0"
+ "GL_RGB12_EXT\0"
+ "GL_RGB16\0"
+ "GL_RGB16_EXT\0"
+ "GL_RGB2_EXT\0"
+ "GL_RGB4\0"
+ "GL_RGB4_EXT\0"
+ "GL_RGB4_S3TC\0"
+ "GL_RGB5\0"
+ "GL_RGB5_A1\0"
+ "GL_RGB5_A1_EXT\0"
+ "GL_RGB5_EXT\0"
+ "GL_RGB8\0"
+ "GL_RGB8_EXT\0"
+ "GL_RGBA\0"
+ "GL_RGBA12\0"
+ "GL_RGBA12_EXT\0"
+ "GL_RGBA16\0"
+ "GL_RGBA16_EXT\0"
+ "GL_RGBA2\0"
+ "GL_RGBA2_EXT\0"
+ "GL_RGBA4\0"
+ "GL_RGBA4_DXT5_S3TC\0"
+ "GL_RGBA4_EXT\0"
+ "GL_RGBA4_S3TC\0"
+ "GL_RGBA8\0"
+ "GL_RGBA8_EXT\0"
+ "GL_RGBA8_SNORM\0"
+ "GL_RGBA_DXT5_S3TC\0"
+ "GL_RGBA_MODE\0"
+ "GL_RGBA_S3TC\0"
+ "GL_RGBA_SNORM\0"
+ "GL_RGB_S3TC\0"
+ "GL_RGB_SCALE\0"
+ "GL_RGB_SCALE_ARB\0"
+ "GL_RGB_SCALE_EXT\0"
+ "GL_RIGHT\0"
+ "GL_S\0"
+ "GL_SAMPLER_1D\0"
+ "GL_SAMPLER_1D_SHADOW\0"
+ "GL_SAMPLER_2D\0"
+ "GL_SAMPLER_2D_SHADOW\0"
+ "GL_SAMPLER_3D\0"
+ "GL_SAMPLER_CUBE\0"
+ "GL_SAMPLES\0"
+ "GL_SAMPLES_3DFX\0"
+ "GL_SAMPLES_ARB\0"
+ "GL_SAMPLES_PASSED\0"
+ "GL_SAMPLES_PASSED_ARB\0"
+ "GL_SAMPLE_ALPHA_TO_COVERAGE\0"
+ "GL_SAMPLE_ALPHA_TO_COVERAGE_ARB\0"
+ "GL_SAMPLE_ALPHA_TO_ONE\0"
+ "GL_SAMPLE_ALPHA_TO_ONE_ARB\0"
+ "GL_SAMPLE_BUFFERS\0"
+ "GL_SAMPLE_BUFFERS_3DFX\0"
+ "GL_SAMPLE_BUFFERS_ARB\0"
+ "GL_SAMPLE_COVERAGE\0"
+ "GL_SAMPLE_COVERAGE_ARB\0"
+ "GL_SAMPLE_COVERAGE_INVERT\0"
+ "GL_SAMPLE_COVERAGE_INVERT_ARB\0"
+ "GL_SAMPLE_COVERAGE_VALUE\0"
+ "GL_SAMPLE_COVERAGE_VALUE_ARB\0"
+ "GL_SCISSOR_BIT\0"
+ "GL_SCISSOR_BOX\0"
+ "GL_SCISSOR_TEST\0"
+ "GL_SECONDARY_COLOR_ARRAY\0"
+ "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING\0"
+ "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_SECONDARY_COLOR_ARRAY_POINTER\0"
+ "GL_SECONDARY_COLOR_ARRAY_SIZE\0"
+ "GL_SECONDARY_COLOR_ARRAY_STRIDE\0"
+ "GL_SECONDARY_COLOR_ARRAY_TYPE\0"
+ "GL_SELECT\0"
+ "GL_SELECTION_BUFFER_POINTER\0"
+ "GL_SELECTION_BUFFER_SIZE\0"
+ "GL_SEPARABLE_2D\0"
+ "GL_SEPARATE_SPECULAR_COLOR\0"
+ "GL_SEPARATE_SPECULAR_COLOR_EXT\0"
+ "GL_SET\0"
+ "GL_SHADER_OBJECT_ARB\0"
+ "GL_SHADER_SOURCE_LENGTH\0"
+ "GL_SHADER_TYPE\0"
+ "GL_SHADE_MODEL\0"
+ "GL_SHADING_LANGUAGE_VERSION\0"
+ "GL_SHADOW_AMBIENT_SGIX\0"
+ "GL_SHARED_TEXTURE_PALETTE_EXT\0"
+ "GL_SHININESS\0"
+ "GL_SHORT\0"
+ "GL_SIGNALED\0"
+ "GL_SIGNED_NORMALIZED\0"
+ "GL_SINGLE_COLOR\0"
+ "GL_SINGLE_COLOR_EXT\0"
+ "GL_SLICE_ACCUM_SUN\0"
+ "GL_SLUMINANCE\0"
+ "GL_SLUMINANCE8\0"
+ "GL_SLUMINANCE8_ALPHA8\0"
+ "GL_SLUMINANCE_ALPHA\0"
+ "GL_SMOOTH\0"
+ "GL_SMOOTH_LINE_WIDTH_GRANULARITY\0"
+ "GL_SMOOTH_LINE_WIDTH_RANGE\0"
+ "GL_SMOOTH_POINT_SIZE_GRANULARITY\0"
+ "GL_SMOOTH_POINT_SIZE_RANGE\0"
+ "GL_SOURCE0_ALPHA\0"
+ "GL_SOURCE0_ALPHA_ARB\0"
+ "GL_SOURCE0_ALPHA_EXT\0"
+ "GL_SOURCE0_RGB\0"
+ "GL_SOURCE0_RGB_ARB\0"
+ "GL_SOURCE0_RGB_EXT\0"
+ "GL_SOURCE1_ALPHA\0"
+ "GL_SOURCE1_ALPHA_ARB\0"
+ "GL_SOURCE1_ALPHA_EXT\0"
+ "GL_SOURCE1_RGB\0"
+ "GL_SOURCE1_RGB_ARB\0"
+ "GL_SOURCE1_RGB_EXT\0"
+ "GL_SOURCE2_ALPHA\0"
+ "GL_SOURCE2_ALPHA_ARB\0"
+ "GL_SOURCE2_ALPHA_EXT\0"
+ "GL_SOURCE2_RGB\0"
+ "GL_SOURCE2_RGB_ARB\0"
+ "GL_SOURCE2_RGB_EXT\0"
+ "GL_SOURCE3_ALPHA_NV\0"
+ "GL_SOURCE3_RGB_NV\0"
+ "GL_SPECULAR\0"
+ "GL_SPHERE_MAP\0"
+ "GL_SPOT_CUTOFF\0"
+ "GL_SPOT_DIRECTION\0"
+ "GL_SPOT_EXPONENT\0"
+ "GL_SRC0_ALPHA\0"
+ "GL_SRC0_RGB\0"
+ "GL_SRC1_ALPHA\0"
+ "GL_SRC1_RGB\0"
+ "GL_SRC2_ALPHA\0"
+ "GL_SRC2_RGB\0"
+ "GL_SRC_ALPHA\0"
+ "GL_SRC_ALPHA_SATURATE\0"
+ "GL_SRC_COLOR\0"
+ "GL_SRGB\0"
+ "GL_SRGB8\0"
+ "GL_SRGB8_ALPHA8\0"
+ "GL_SRGB_ALPHA\0"
+ "GL_STACK_OVERFLOW\0"
+ "GL_STACK_UNDERFLOW\0"
+ "GL_STATIC_COPY\0"
+ "GL_STATIC_COPY_ARB\0"
+ "GL_STATIC_DRAW\0"
+ "GL_STATIC_DRAW_ARB\0"
+ "GL_STATIC_READ\0"
+ "GL_STATIC_READ_ARB\0"
+ "GL_STENCIL\0"
+ "GL_STENCIL_ATTACHMENT\0"
+ "GL_STENCIL_ATTACHMENT_EXT\0"
+ "GL_STENCIL_BACK_FAIL\0"
+ "GL_STENCIL_BACK_FAIL_ATI\0"
+ "GL_STENCIL_BACK_FUNC\0"
+ "GL_STENCIL_BACK_FUNC_ATI\0"
+ "GL_STENCIL_BACK_PASS_DEPTH_FAIL\0"
+ "GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI\0"
+ "GL_STENCIL_BACK_PASS_DEPTH_PASS\0"
+ "GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI\0"
+ "GL_STENCIL_BACK_REF\0"
+ "GL_STENCIL_BACK_VALUE_MASK\0"
+ "GL_STENCIL_BACK_WRITEMASK\0"
+ "GL_STENCIL_BITS\0"
+ "GL_STENCIL_BUFFER_BIT\0"
+ "GL_STENCIL_CLEAR_VALUE\0"
+ "GL_STENCIL_FAIL\0"
+ "GL_STENCIL_FUNC\0"
+ "GL_STENCIL_INDEX\0"
+ "GL_STENCIL_INDEX16_EXT\0"
+ "GL_STENCIL_INDEX1_EXT\0"
+ "GL_STENCIL_INDEX4_EXT\0"
+ "GL_STENCIL_INDEX8_EXT\0"
+ "GL_STENCIL_INDEX_EXT\0"
+ "GL_STENCIL_PASS_DEPTH_FAIL\0"
+ "GL_STENCIL_PASS_DEPTH_PASS\0"
+ "GL_STENCIL_REF\0"
+ "GL_STENCIL_TEST\0"
+ "GL_STENCIL_TEST_TWO_SIDE_EXT\0"
+ "GL_STENCIL_VALUE_MASK\0"
+ "GL_STENCIL_WRITEMASK\0"
+ "GL_STEREO\0"
+ "GL_STORAGE_CACHED_APPLE\0"
+ "GL_STORAGE_PRIVATE_APPLE\0"
+ "GL_STORAGE_SHARED_APPLE\0"
+ "GL_STREAM_COPY\0"
+ "GL_STREAM_COPY_ARB\0"
+ "GL_STREAM_DRAW\0"
+ "GL_STREAM_DRAW_ARB\0"
+ "GL_STREAM_READ\0"
+ "GL_STREAM_READ_ARB\0"
+ "GL_SUBPIXEL_BITS\0"
+ "GL_SUBTRACT\0"
+ "GL_SUBTRACT_ARB\0"
+ "GL_SYNC_CONDITION\0"
+ "GL_SYNC_FENCE\0"
+ "GL_SYNC_FLAGS\0"
+ "GL_SYNC_FLUSH_COMMANDS_BIT\0"
+ "GL_SYNC_GPU_COMMANDS_COMPLETE\0"
+ "GL_SYNC_STATUS\0"
+ "GL_T\0"
+ "GL_T2F_C3F_V3F\0"
+ "GL_T2F_C4F_N3F_V3F\0"
+ "GL_T2F_C4UB_V3F\0"
+ "GL_T2F_N3F_V3F\0"
+ "GL_T2F_V3F\0"
+ "GL_T4F_C4F_N3F_V4F\0"
+ "GL_T4F_V4F\0"
+ "GL_TABLE_TOO_LARGE_EXT\0"
+ "GL_TEXTURE\0"
+ "GL_TEXTURE0\0"
+ "GL_TEXTURE0_ARB\0"
+ "GL_TEXTURE1\0"
+ "GL_TEXTURE10\0"
+ "GL_TEXTURE10_ARB\0"
+ "GL_TEXTURE11\0"
+ "GL_TEXTURE11_ARB\0"
+ "GL_TEXTURE12\0"
+ "GL_TEXTURE12_ARB\0"
+ "GL_TEXTURE13\0"
+ "GL_TEXTURE13_ARB\0"
+ "GL_TEXTURE14\0"
+ "GL_TEXTURE14_ARB\0"
+ "GL_TEXTURE15\0"
+ "GL_TEXTURE15_ARB\0"
+ "GL_TEXTURE16\0"
+ "GL_TEXTURE16_ARB\0"
+ "GL_TEXTURE17\0"
+ "GL_TEXTURE17_ARB\0"
+ "GL_TEXTURE18\0"
+ "GL_TEXTURE18_ARB\0"
+ "GL_TEXTURE19\0"
+ "GL_TEXTURE19_ARB\0"
+ "GL_TEXTURE1_ARB\0"
+ "GL_TEXTURE2\0"
+ "GL_TEXTURE20\0"
+ "GL_TEXTURE20_ARB\0"
+ "GL_TEXTURE21\0"
+ "GL_TEXTURE21_ARB\0"
+ "GL_TEXTURE22\0"
+ "GL_TEXTURE22_ARB\0"
+ "GL_TEXTURE23\0"
+ "GL_TEXTURE23_ARB\0"
+ "GL_TEXTURE24\0"
+ "GL_TEXTURE24_ARB\0"
+ "GL_TEXTURE25\0"
+ "GL_TEXTURE25_ARB\0"
+ "GL_TEXTURE26\0"
+ "GL_TEXTURE26_ARB\0"
+ "GL_TEXTURE27\0"
+ "GL_TEXTURE27_ARB\0"
+ "GL_TEXTURE28\0"
+ "GL_TEXTURE28_ARB\0"
+ "GL_TEXTURE29\0"
+ "GL_TEXTURE29_ARB\0"
+ "GL_TEXTURE2_ARB\0"
+ "GL_TEXTURE3\0"
+ "GL_TEXTURE30\0"
+ "GL_TEXTURE30_ARB\0"
+ "GL_TEXTURE31\0"
+ "GL_TEXTURE31_ARB\0"
+ "GL_TEXTURE3_ARB\0"
+ "GL_TEXTURE4\0"
+ "GL_TEXTURE4_ARB\0"
+ "GL_TEXTURE5\0"
+ "GL_TEXTURE5_ARB\0"
+ "GL_TEXTURE6\0"
+ "GL_TEXTURE6_ARB\0"
+ "GL_TEXTURE7\0"
+ "GL_TEXTURE7_ARB\0"
+ "GL_TEXTURE8\0"
+ "GL_TEXTURE8_ARB\0"
+ "GL_TEXTURE9\0"
+ "GL_TEXTURE9_ARB\0"
+ "GL_TEXTURE_1D\0"
+ "GL_TEXTURE_1D_ARRAY_EXT\0"
+ "GL_TEXTURE_2D\0"
+ "GL_TEXTURE_2D_ARRAY_EXT\0"
+ "GL_TEXTURE_3D\0"
+ "GL_TEXTURE_ALPHA_SIZE\0"
+ "GL_TEXTURE_ALPHA_SIZE_EXT\0"
+ "GL_TEXTURE_BASE_LEVEL\0"
+ "GL_TEXTURE_BINDING_1D\0"
+ "GL_TEXTURE_BINDING_1D_ARRAY_EXT\0"
+ "GL_TEXTURE_BINDING_2D\0"
+ "GL_TEXTURE_BINDING_2D_ARRAY_EXT\0"
+ "GL_TEXTURE_BINDING_3D\0"
+ "GL_TEXTURE_BINDING_CUBE_MAP\0"
+ "GL_TEXTURE_BINDING_CUBE_MAP_ARB\0"
+ "GL_TEXTURE_BINDING_RECTANGLE_ARB\0"
+ "GL_TEXTURE_BINDING_RECTANGLE_NV\0"
+ "GL_TEXTURE_BIT\0"
+ "GL_TEXTURE_BLUE_SIZE\0"
+ "GL_TEXTURE_BLUE_SIZE_EXT\0"
+ "GL_TEXTURE_BORDER\0"
+ "GL_TEXTURE_BORDER_COLOR\0"
+ "GL_TEXTURE_CLIPMAP_CENTER_SGIX\0"
+ "GL_TEXTURE_CLIPMAP_DEPTH_SGIX\0"
+ "GL_TEXTURE_CLIPMAP_FRAME_SGIX\0"
+ "GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX\0"
+ "GL_TEXTURE_CLIPMAP_OFFSET_SGIX\0"
+ "GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX\0"
+ "GL_TEXTURE_COLOR_TABLE_SGI\0"
+ "GL_TEXTURE_COLOR_WRITEMASK_SGIS\0"
+ "GL_TEXTURE_COMPARE_FAIL_VALUE_ARB\0"
+ "GL_TEXTURE_COMPARE_FUNC\0"
+ "GL_TEXTURE_COMPARE_FUNC_ARB\0"
+ "GL_TEXTURE_COMPARE_MODE\0"
+ "GL_TEXTURE_COMPARE_MODE_ARB\0"
+ "GL_TEXTURE_COMPARE_OPERATOR_SGIX\0"
+ "GL_TEXTURE_COMPARE_SGIX\0"
+ "GL_TEXTURE_COMPONENTS\0"
+ "GL_TEXTURE_COMPRESSED\0"
+ "GL_TEXTURE_COMPRESSED_ARB\0"
+ "GL_TEXTURE_COMPRESSED_FORMATS_ARB\0"
+ "GL_TEXTURE_COMPRESSED_IMAGE_SIZE\0"
+ "GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB\0"
+ "GL_TEXTURE_COMPRESSION_HINT\0"
+ "GL_TEXTURE_COMPRESSION_HINT_ARB\0"
+ "GL_TEXTURE_COORD_ARRAY\0"
+ "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING\0"
+ "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_TEXTURE_COORD_ARRAY_POINTER\0"
+ "GL_TEXTURE_COORD_ARRAY_SIZE\0"
+ "GL_TEXTURE_COORD_ARRAY_STRIDE\0"
+ "GL_TEXTURE_COORD_ARRAY_TYPE\0"
+ "GL_TEXTURE_CUBE_MAP\0"
+ "GL_TEXTURE_CUBE_MAP_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_X\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z\0"
+ "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_X\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_Y\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_Z\0"
+ "GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\0"
+ "GL_TEXTURE_CUBE_MAP_SEAMLESS\0"
+ "GL_TEXTURE_DEPTH\0"
+ "GL_TEXTURE_DEPTH_SIZE\0"
+ "GL_TEXTURE_DEPTH_SIZE_ARB\0"
+ "GL_TEXTURE_ENV\0"
+ "GL_TEXTURE_ENV_COLOR\0"
+ "GL_TEXTURE_ENV_MODE\0"
+ "GL_TEXTURE_FILTER_CONTROL\0"
+ "GL_TEXTURE_GEN_MODE\0"
+ "GL_TEXTURE_GEN_Q\0"
+ "GL_TEXTURE_GEN_R\0"
+ "GL_TEXTURE_GEN_S\0"
+ "GL_TEXTURE_GEN_T\0"
+ "GL_TEXTURE_GEQUAL_R_SGIX\0"
+ "GL_TEXTURE_GREEN_SIZE\0"
+ "GL_TEXTURE_GREEN_SIZE_EXT\0"
+ "GL_TEXTURE_HEIGHT\0"
+ "GL_TEXTURE_INDEX_SIZE_EXT\0"
+ "GL_TEXTURE_INTENSITY_SIZE\0"
+ "GL_TEXTURE_INTENSITY_SIZE_EXT\0"
+ "GL_TEXTURE_INTERNAL_FORMAT\0"
+ "GL_TEXTURE_LEQUAL_R_SGIX\0"
+ "GL_TEXTURE_LOD_BIAS\0"
+ "GL_TEXTURE_LOD_BIAS_EXT\0"
+ "GL_TEXTURE_LOD_BIAS_R_SGIX\0"
+ "GL_TEXTURE_LOD_BIAS_S_SGIX\0"
+ "GL_TEXTURE_LOD_BIAS_T_SGIX\0"
+ "GL_TEXTURE_LUMINANCE_SIZE\0"
+ "GL_TEXTURE_LUMINANCE_SIZE_EXT\0"
+ "GL_TEXTURE_MAG_FILTER\0"
+ "GL_TEXTURE_MATRIX\0"
+ "GL_TEXTURE_MAX_ANISOTROPY_EXT\0"
+ "GL_TEXTURE_MAX_CLAMP_R_SGIX\0"
+ "GL_TEXTURE_MAX_CLAMP_S_SGIX\0"
+ "GL_TEXTURE_MAX_CLAMP_T_SGIX\0"
+ "GL_TEXTURE_MAX_LEVEL\0"
+ "GL_TEXTURE_MAX_LOD\0"
+ "GL_TEXTURE_MIN_FILTER\0"
+ "GL_TEXTURE_MIN_LOD\0"
+ "GL_TEXTURE_PRIORITY\0"
+ "GL_TEXTURE_RANGE_LENGTH_APPLE\0"
+ "GL_TEXTURE_RANGE_POINTER_APPLE\0"
+ "GL_TEXTURE_RECTANGLE_ARB\0"
+ "GL_TEXTURE_RECTANGLE_NV\0"
+ "GL_TEXTURE_RED_SIZE\0"
+ "GL_TEXTURE_RED_SIZE_EXT\0"
+ "GL_TEXTURE_RESIDENT\0"
+ "GL_TEXTURE_STACK_DEPTH\0"
+ "GL_TEXTURE_STENCIL_SIZE\0"
+ "GL_TEXTURE_STORAGE_HINT_APPLE\0"
+ "GL_TEXTURE_TOO_LARGE_EXT\0"
+ "GL_TEXTURE_UNSIGNED_REMAP_MODE_NV\0"
+ "GL_TEXTURE_WIDTH\0"
+ "GL_TEXTURE_WRAP_R\0"
+ "GL_TEXTURE_WRAP_S\0"
+ "GL_TEXTURE_WRAP_T\0"
+ "GL_TIMEOUT_EXPIRED\0"
+ "GL_TIMEOUT_IGNORED\0"
+ "GL_TIME_ELAPSED_EXT\0"
+ "GL_TRACK_MATRIX_NV\0"
+ "GL_TRACK_MATRIX_TRANSFORM_NV\0"
+ "GL_TRANSFORM_BIT\0"
+ "GL_TRANSPOSE_COLOR_MATRIX\0"
+ "GL_TRANSPOSE_COLOR_MATRIX_ARB\0"
+ "GL_TRANSPOSE_CURRENT_MATRIX_ARB\0"
+ "GL_TRANSPOSE_MODELVIEW_MATRIX\0"
+ "GL_TRANSPOSE_MODELVIEW_MATRIX_ARB\0"
+ "GL_TRANSPOSE_NV\0"
+ "GL_TRANSPOSE_PROJECTION_MATRIX\0"
+ "GL_TRANSPOSE_PROJECTION_MATRIX_ARB\0"
+ "GL_TRANSPOSE_TEXTURE_MATRIX\0"
+ "GL_TRANSPOSE_TEXTURE_MATRIX_ARB\0"
+ "GL_TRIANGLES\0"
+ "GL_TRIANGLE_FAN\0"
+ "GL_TRIANGLE_MESH_SUN\0"
+ "GL_TRIANGLE_STRIP\0"
+ "GL_TRUE\0"
+ "GL_UNPACK_ALIGNMENT\0"
+ "GL_UNPACK_IMAGE_HEIGHT\0"
+ "GL_UNPACK_LSB_FIRST\0"
+ "GL_UNPACK_ROW_LENGTH\0"
+ "GL_UNPACK_SKIP_IMAGES\0"
+ "GL_UNPACK_SKIP_PIXELS\0"
+ "GL_UNPACK_SKIP_ROWS\0"
+ "GL_UNPACK_SWAP_BYTES\0"
+ "GL_UNSIGNALED\0"
+ "GL_UNSIGNED_BYTE\0"
+ "GL_UNSIGNED_BYTE_2_3_3_REV\0"
+ "GL_UNSIGNED_BYTE_3_3_2\0"
+ "GL_UNSIGNED_INT\0"
+ "GL_UNSIGNED_INT_10_10_10_2\0"
+ "GL_UNSIGNED_INT_24_8\0"
+ "GL_UNSIGNED_INT_24_8_NV\0"
+ "GL_UNSIGNED_INT_2_10_10_10_REV\0"
+ "GL_UNSIGNED_INT_8_8_8_8\0"
+ "GL_UNSIGNED_INT_8_8_8_8_REV\0"
+ "GL_UNSIGNED_NORMALIZED\0"
+ "GL_UNSIGNED_SHORT\0"
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV\0"
+ "GL_UNSIGNED_SHORT_4_4_4_4\0"
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV\0"
+ "GL_UNSIGNED_SHORT_5_5_5_1\0"
+ "GL_UNSIGNED_SHORT_5_6_5\0"
+ "GL_UNSIGNED_SHORT_5_6_5_REV\0"
+ "GL_UNSIGNED_SHORT_8_8_APPLE\0"
+ "GL_UNSIGNED_SHORT_8_8_MESA\0"
+ "GL_UNSIGNED_SHORT_8_8_REV_APPLE\0"
+ "GL_UNSIGNED_SHORT_8_8_REV_MESA\0"
+ "GL_UPPER_LEFT\0"
+ "GL_V2F\0"
+ "GL_V3F\0"
+ "GL_VALIDATE_STATUS\0"
+ "GL_VENDOR\0"
+ "GL_VERSION\0"
+ "GL_VERTEX_ARRAY\0"
+ "GL_VERTEX_ARRAY_BINDING\0"
+ "GL_VERTEX_ARRAY_BINDING_APPLE\0"
+ "GL_VERTEX_ARRAY_BUFFER_BINDING\0"
+ "GL_VERTEX_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_VERTEX_ARRAY_POINTER\0"
+ "GL_VERTEX_ARRAY_SIZE\0"
+ "GL_VERTEX_ARRAY_STRIDE\0"
+ "GL_VERTEX_ARRAY_TYPE\0"
+ "GL_VERTEX_ATTRIB_ARRAY0_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY10_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY11_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY12_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY13_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY14_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY15_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY1_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY2_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY3_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY4_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY5_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY6_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY7_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY8_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY9_NV\0"
+ "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING\0"
+ "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_ENABLED\0"
+ "GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED\0"
+ "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_POINTER\0"
+ "GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_SIZE\0"
+ "GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_STRIDE\0"
+ "GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB\0"
+ "GL_VERTEX_ATTRIB_ARRAY_TYPE\0"
+ "GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB\0"
+ "GL_VERTEX_BLEND_ARB\0"
+ "GL_VERTEX_PROGRAM_ARB\0"
+ "GL_VERTEX_PROGRAM_BINDING_NV\0"
+ "GL_VERTEX_PROGRAM_NV\0"
+ "GL_VERTEX_PROGRAM_POINT_SIZE\0"
+ "GL_VERTEX_PROGRAM_POINT_SIZE_ARB\0"
+ "GL_VERTEX_PROGRAM_POINT_SIZE_NV\0"
+ "GL_VERTEX_PROGRAM_TWO_SIDE\0"
+ "GL_VERTEX_PROGRAM_TWO_SIDE_ARB\0"
+ "GL_VERTEX_PROGRAM_TWO_SIDE_NV\0"
+ "GL_VERTEX_SHADER\0"
+ "GL_VERTEX_SHADER_ARB\0"
+ "GL_VERTEX_STATE_PROGRAM_NV\0"
+ "GL_VIEWPORT\0"
+ "GL_VIEWPORT_BIT\0"
+ "GL_WAIT_FAILED\0"
+ "GL_WEIGHT_ARRAY_ARB\0"
+ "GL_WEIGHT_ARRAY_BUFFER_BINDING\0"
+ "GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB\0"
+ "GL_WEIGHT_ARRAY_POINTER_ARB\0"
+ "GL_WEIGHT_ARRAY_SIZE_ARB\0"
+ "GL_WEIGHT_ARRAY_STRIDE_ARB\0"
+ "GL_WEIGHT_ARRAY_TYPE_ARB\0"
+ "GL_WEIGHT_SUM_UNITY_ARB\0"
+ "GL_WRAP_BORDER_SUN\0"
+ "GL_WRITE_ONLY\0"
+ "GL_WRITE_ONLY_ARB\0"
+ "GL_XOR\0"
+ "GL_YCBCR_422_APPLE\0"
+ "GL_YCBCR_MESA\0"
+ "GL_ZERO\0"
+ "GL_ZOOM_X\0"
+ "GL_ZOOM_Y\0"
+ ;
+
+static const enum_elt all_enums[1857] =
+{
+ { 0, 0x00000600 }, /* GL_2D */
+ { 6, 0x00001407 }, /* GL_2_BYTES */
+ { 17, 0x00000601 }, /* GL_3D */
+ { 23, 0x00000602 }, /* GL_3D_COLOR */
+ { 35, 0x00000603 }, /* GL_3D_COLOR_TEXTURE */
+ { 55, 0x00001408 }, /* GL_3_BYTES */
+ { 66, 0x00000604 }, /* GL_4D_COLOR_TEXTURE */
+ { 86, 0x00001409 }, /* GL_4_BYTES */
+ { 97, 0x00000100 }, /* GL_ACCUM */
+ { 106, 0x00000D5B }, /* GL_ACCUM_ALPHA_BITS */
+ { 126, 0x00000D5A }, /* GL_ACCUM_BLUE_BITS */
+ { 145, 0x00000200 }, /* GL_ACCUM_BUFFER_BIT */
+ { 165, 0x00000B80 }, /* GL_ACCUM_CLEAR_VALUE */
+ { 186, 0x00000D59 }, /* GL_ACCUM_GREEN_BITS */
+ { 206, 0x00000D58 }, /* GL_ACCUM_RED_BITS */
+ { 224, 0x00008B89 }, /* GL_ACTIVE_ATTRIBUTES */
+ { 245, 0x00008B8A }, /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */
+ { 276, 0x00008911 }, /* GL_ACTIVE_STENCIL_FACE_EXT */
+ { 303, 0x000084E0 }, /* GL_ACTIVE_TEXTURE */
+ { 321, 0x000084E0 }, /* GL_ACTIVE_TEXTURE_ARB */
+ { 343, 0x00008B86 }, /* GL_ACTIVE_UNIFORMS */
+ { 362, 0x00008B87 }, /* GL_ACTIVE_UNIFORM_MAX_LENGTH */
+ { 391, 0x000086A5 }, /* GL_ACTIVE_VERTEX_UNITS_ARB */
+ { 418, 0x00000104 }, /* GL_ADD */
+ { 425, 0x00008574 }, /* GL_ADD_SIGNED */
+ { 439, 0x00008574 }, /* GL_ADD_SIGNED_ARB */
+ { 457, 0x00008574 }, /* GL_ADD_SIGNED_EXT */
+ { 475, 0x0000846E }, /* GL_ALIASED_LINE_WIDTH_RANGE */
+ { 503, 0x0000846D }, /* GL_ALIASED_POINT_SIZE_RANGE */
+ { 531, 0x000FFFFF }, /* GL_ALL_ATTRIB_BITS */
+ { 550, 0xFFFFFFFF }, /* GL_ALL_CLIENT_ATTRIB_BITS */
+ { 576, 0x00001906 }, /* GL_ALPHA */
+ { 585, 0x0000803D }, /* GL_ALPHA12 */
+ { 596, 0x0000803D }, /* GL_ALPHA12_EXT */
+ { 611, 0x0000803E }, /* GL_ALPHA16 */
+ { 622, 0x0000803E }, /* GL_ALPHA16_EXT */
+ { 637, 0x0000803B }, /* GL_ALPHA4 */
+ { 647, 0x0000803B }, /* GL_ALPHA4_EXT */
+ { 661, 0x0000803C }, /* GL_ALPHA8 */
+ { 671, 0x0000803C }, /* GL_ALPHA8_EXT */
+ { 685, 0x00000D1D }, /* GL_ALPHA_BIAS */
+ { 699, 0x00000D55 }, /* GL_ALPHA_BITS */
+ { 713, 0x00000D1C }, /* GL_ALPHA_SCALE */
+ { 728, 0x00000BC0 }, /* GL_ALPHA_TEST */
+ { 742, 0x00000BC1 }, /* GL_ALPHA_TEST_FUNC */
+ { 761, 0x00000BC2 }, /* GL_ALPHA_TEST_REF */
+ { 779, 0x0000911A }, /* GL_ALREADY_SIGNALED */
+ { 799, 0x00000207 }, /* GL_ALWAYS */
+ { 809, 0x00001200 }, /* GL_AMBIENT */
+ { 820, 0x00001602 }, /* GL_AMBIENT_AND_DIFFUSE */
+ { 843, 0x00001501 }, /* GL_AND */
+ { 850, 0x00001504 }, /* GL_AND_INVERTED */
+ { 866, 0x00001502 }, /* GL_AND_REVERSE */
+ { 881, 0x00008892 }, /* GL_ARRAY_BUFFER */
+ { 897, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING */
+ { 921, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING_ARB */
+ { 949, 0x00008B85 }, /* GL_ATTACHED_SHADERS */
+ { 969, 0x00008645 }, /* GL_ATTRIB_ARRAY_POINTER_NV */
+ { 996, 0x00008623 }, /* GL_ATTRIB_ARRAY_SIZE_NV */
+ { 1020, 0x00008624 }, /* GL_ATTRIB_ARRAY_STRIDE_NV */
+ { 1046, 0x00008625 }, /* GL_ATTRIB_ARRAY_TYPE_NV */
+ { 1070, 0x00000BB0 }, /* GL_ATTRIB_STACK_DEPTH */
+ { 1092, 0x00000D80 }, /* GL_AUTO_NORMAL */
+ { 1107, 0x00000409 }, /* GL_AUX0 */
+ { 1115, 0x0000040A }, /* GL_AUX1 */
+ { 1123, 0x0000040B }, /* GL_AUX2 */
+ { 1131, 0x0000040C }, /* GL_AUX3 */
+ { 1139, 0x00000C00 }, /* GL_AUX_BUFFERS */
+ { 1154, 0x00000405 }, /* GL_BACK */
+ { 1162, 0x00000402 }, /* GL_BACK_LEFT */
+ { 1175, 0x00000403 }, /* GL_BACK_RIGHT */
+ { 1189, 0x000080E0 }, /* GL_BGR */
+ { 1196, 0x000080E1 }, /* GL_BGRA */
+ { 1204, 0x00001A00 }, /* GL_BITMAP */
+ { 1214, 0x00000704 }, /* GL_BITMAP_TOKEN */
+ { 1230, 0x00000BE2 }, /* GL_BLEND */
+ { 1239, 0x00008005 }, /* GL_BLEND_COLOR */
+ { 1254, 0x00008005 }, /* GL_BLEND_COLOR_EXT */
+ { 1273, 0x00000BE0 }, /* GL_BLEND_DST */
+ { 1286, 0x000080CA }, /* GL_BLEND_DST_ALPHA */
+ { 1305, 0x000080C8 }, /* GL_BLEND_DST_RGB */
+ { 1322, 0x00008009 }, /* GL_BLEND_EQUATION */
+ { 1340, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA */
+ { 1364, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA_EXT */
+ { 1392, 0x00008009 }, /* GL_BLEND_EQUATION_EXT */
+ { 1414, 0x00008009 }, /* GL_BLEND_EQUATION_RGB */
+ { 1436, 0x00008009 }, /* GL_BLEND_EQUATION_RGB_EXT */
+ { 1462, 0x00000BE1 }, /* GL_BLEND_SRC */
+ { 1475, 0x000080CB }, /* GL_BLEND_SRC_ALPHA */
+ { 1494, 0x000080C9 }, /* GL_BLEND_SRC_RGB */
+ { 1511, 0x00001905 }, /* GL_BLUE */
+ { 1519, 0x00000D1B }, /* GL_BLUE_BIAS */
+ { 1532, 0x00000D54 }, /* GL_BLUE_BITS */
+ { 1545, 0x00000D1A }, /* GL_BLUE_SCALE */
+ { 1559, 0x00008B56 }, /* GL_BOOL */
+ { 1567, 0x00008B56 }, /* GL_BOOL_ARB */
+ { 1579, 0x00008B57 }, /* GL_BOOL_VEC2 */
+ { 1592, 0x00008B57 }, /* GL_BOOL_VEC2_ARB */
+ { 1609, 0x00008B58 }, /* GL_BOOL_VEC3 */
+ { 1622, 0x00008B58 }, /* GL_BOOL_VEC3_ARB */
+ { 1639, 0x00008B59 }, /* GL_BOOL_VEC4 */
+ { 1652, 0x00008B59 }, /* GL_BOOL_VEC4_ARB */
+ { 1669, 0x000088BB }, /* GL_BUFFER_ACCESS */
+ { 1686, 0x000088BB }, /* GL_BUFFER_ACCESS_ARB */
+ { 1707, 0x00008A13 }, /* GL_BUFFER_FLUSHING_UNMAP_APPLE */
+ { 1738, 0x000088BC }, /* GL_BUFFER_MAPPED */
+ { 1755, 0x000088BC }, /* GL_BUFFER_MAPPED_ARB */
+ { 1776, 0x000088BD }, /* GL_BUFFER_MAP_POINTER */
+ { 1798, 0x000088BD }, /* GL_BUFFER_MAP_POINTER_ARB */
+ { 1824, 0x00008A12 }, /* GL_BUFFER_SERIALIZED_MODIFY_APPLE */
+ { 1858, 0x00008764 }, /* GL_BUFFER_SIZE */
+ { 1873, 0x00008764 }, /* GL_BUFFER_SIZE_ARB */
+ { 1892, 0x00008765 }, /* GL_BUFFER_USAGE */
+ { 1908, 0x00008765 }, /* GL_BUFFER_USAGE_ARB */
+ { 1928, 0x0000877B }, /* GL_BUMP_ENVMAP_ATI */
+ { 1947, 0x00008777 }, /* GL_BUMP_NUM_TEX_UNITS_ATI */
+ { 1973, 0x00008775 }, /* GL_BUMP_ROT_MATRIX_ATI */
+ { 1996, 0x00008776 }, /* GL_BUMP_ROT_MATRIX_SIZE_ATI */
+ { 2024, 0x0000877C }, /* GL_BUMP_TARGET_ATI */
+ { 2043, 0x00008778 }, /* GL_BUMP_TEX_UNITS_ATI */
+ { 2065, 0x00001400 }, /* GL_BYTE */
+ { 2073, 0x00002A24 }, /* GL_C3F_V3F */
+ { 2084, 0x00002A26 }, /* GL_C4F_N3F_V3F */
+ { 2099, 0x00002A22 }, /* GL_C4UB_V2F */
+ { 2111, 0x00002A23 }, /* GL_C4UB_V3F */
+ { 2123, 0x00000901 }, /* GL_CCW */
+ { 2130, 0x00002900 }, /* GL_CLAMP */
+ { 2139, 0x0000812D }, /* GL_CLAMP_TO_BORDER */
+ { 2158, 0x0000812D }, /* GL_CLAMP_TO_BORDER_ARB */
+ { 2181, 0x0000812D }, /* GL_CLAMP_TO_BORDER_SGIS */
+ { 2205, 0x0000812F }, /* GL_CLAMP_TO_EDGE */
+ { 2222, 0x0000812F }, /* GL_CLAMP_TO_EDGE_SGIS */
+ { 2244, 0x00001500 }, /* GL_CLEAR */
+ { 2253, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE */
+ { 2278, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE_ARB */
+ { 2307, 0xFFFFFFFF }, /* GL_CLIENT_ALL_ATTRIB_BITS */
+ { 2333, 0x00000BB1 }, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
+ { 2362, 0x00000001 }, /* GL_CLIENT_PIXEL_STORE_BIT */
+ { 2388, 0x00000002 }, /* GL_CLIENT_VERTEX_ARRAY_BIT */
+ { 2415, 0x00003000 }, /* GL_CLIP_PLANE0 */
+ { 2430, 0x00003001 }, /* GL_CLIP_PLANE1 */
+ { 2445, 0x00003002 }, /* GL_CLIP_PLANE2 */
+ { 2460, 0x00003003 }, /* GL_CLIP_PLANE3 */
+ { 2475, 0x00003004 }, /* GL_CLIP_PLANE4 */
+ { 2490, 0x00003005 }, /* GL_CLIP_PLANE5 */
+ { 2505, 0x000080F0 }, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
+ { 2538, 0x00000A00 }, /* GL_COEFF */
+ { 2547, 0x00001800 }, /* GL_COLOR */
+ { 2556, 0x00008076 }, /* GL_COLOR_ARRAY */
+ { 2571, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING */
+ { 2601, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING_ARB */
+ { 2635, 0x00008090 }, /* GL_COLOR_ARRAY_POINTER */
+ { 2658, 0x00008081 }, /* GL_COLOR_ARRAY_SIZE */
+ { 2678, 0x00008083 }, /* GL_COLOR_ARRAY_STRIDE */
+ { 2700, 0x00008082 }, /* GL_COLOR_ARRAY_TYPE */
+ { 2720, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0 */
+ { 2741, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0_EXT */
+ { 2766, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1 */
+ { 2787, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10 */
+ { 2809, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10_EXT */
+ { 2835, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11 */
+ { 2857, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11_EXT */
+ { 2883, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12 */
+ { 2905, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12_EXT */
+ { 2931, 0x00008CED }, /* GL_COLOR_ATTACHMENT13 */
+ { 2953, 0x00008CED }, /* GL_COLOR_ATTACHMENT13_EXT */
+ { 2979, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14 */
+ { 3001, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14_EXT */
+ { 3027, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15 */
+ { 3049, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15_EXT */
+ { 3075, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1_EXT */
+ { 3100, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2 */
+ { 3121, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2_EXT */
+ { 3146, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3 */
+ { 3167, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3_EXT */
+ { 3192, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4 */
+ { 3213, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4_EXT */
+ { 3238, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5 */
+ { 3259, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5_EXT */
+ { 3284, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6 */
+ { 3305, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6_EXT */
+ { 3330, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7 */
+ { 3351, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7_EXT */
+ { 3376, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8 */
+ { 3397, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8_EXT */
+ { 3422, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9 */
+ { 3443, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9_EXT */
+ { 3468, 0x00004000 }, /* GL_COLOR_BUFFER_BIT */
+ { 3488, 0x00000C22 }, /* GL_COLOR_CLEAR_VALUE */
+ { 3509, 0x00001900 }, /* GL_COLOR_INDEX */
+ { 3524, 0x00001603 }, /* GL_COLOR_INDEXES */
+ { 3541, 0x00000BF2 }, /* GL_COLOR_LOGIC_OP */
+ { 3559, 0x00000B57 }, /* GL_COLOR_MATERIAL */
+ { 3577, 0x00000B55 }, /* GL_COLOR_MATERIAL_FACE */
+ { 3600, 0x00000B56 }, /* GL_COLOR_MATERIAL_PARAMETER */
+ { 3628, 0x000080B1 }, /* GL_COLOR_MATRIX */
+ { 3644, 0x000080B1 }, /* GL_COLOR_MATRIX_SGI */
+ { 3664, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH */
+ { 3692, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH_SGI */
+ { 3724, 0x00008458 }, /* GL_COLOR_SUM */
+ { 3737, 0x00008458 }, /* GL_COLOR_SUM_ARB */
+ { 3754, 0x000080D0 }, /* GL_COLOR_TABLE */
+ { 3769, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE */
+ { 3795, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_EXT */
+ { 3825, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_SGI */
+ { 3855, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS */
+ { 3875, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS_SGI */
+ { 3899, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE */
+ { 3924, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_EXT */
+ { 3953, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_SGI */
+ { 3982, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT */
+ { 4004, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_EXT */
+ { 4030, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_SGI */
+ { 4056, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE */
+ { 4082, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_EXT */
+ { 4112, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_SGI */
+ { 4142, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE */
+ { 4172, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_EXT */
+ { 4206, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_SGI */
+ { 4240, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
+ { 4270, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_EXT */
+ { 4304, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_SGI */
+ { 4338, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE */
+ { 4362, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_EXT */
+ { 4390, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_SGI */
+ { 4418, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE */
+ { 4439, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE_SGI */
+ { 4464, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH */
+ { 4485, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_EXT */
+ { 4510, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_SGI */
+ { 4535, 0x00000C23 }, /* GL_COLOR_WRITEMASK */
+ { 4554, 0x00008570 }, /* GL_COMBINE */
+ { 4565, 0x00008503 }, /* GL_COMBINE4 */
+ { 4577, 0x00008572 }, /* GL_COMBINE_ALPHA */
+ { 4594, 0x00008572 }, /* GL_COMBINE_ALPHA_ARB */
+ { 4615, 0x00008572 }, /* GL_COMBINE_ALPHA_EXT */
+ { 4636, 0x00008570 }, /* GL_COMBINE_ARB */
+ { 4651, 0x00008570 }, /* GL_COMBINE_EXT */
+ { 4666, 0x00008571 }, /* GL_COMBINE_RGB */
+ { 4681, 0x00008571 }, /* GL_COMBINE_RGB_ARB */
+ { 4700, 0x00008571 }, /* GL_COMBINE_RGB_EXT */
+ { 4719, 0x0000884E }, /* GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT */
+ { 4755, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE */
+ { 4779, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE_ARB */
+ { 4807, 0x00001300 }, /* GL_COMPILE */
+ { 4818, 0x00001301 }, /* GL_COMPILE_AND_EXECUTE */
+ { 4841, 0x00008B81 }, /* GL_COMPILE_STATUS */
+ { 4859, 0x000084E9 }, /* GL_COMPRESSED_ALPHA */
+ { 4879, 0x000084E9 }, /* GL_COMPRESSED_ALPHA_ARB */
+ { 4903, 0x000084EC }, /* GL_COMPRESSED_INTENSITY */
+ { 4927, 0x000084EC }, /* GL_COMPRESSED_INTENSITY_ARB */
+ { 4955, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE */
+ { 4979, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA */
+ { 5009, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA_ARB */
+ { 5043, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE_ARB */
+ { 5071, 0x000084ED }, /* GL_COMPRESSED_RGB */
+ { 5089, 0x000084EE }, /* GL_COMPRESSED_RGBA */
+ { 5108, 0x000084EE }, /* GL_COMPRESSED_RGBA_ARB */
+ { 5131, 0x000086B1 }, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
+ { 5160, 0x000083F1 }, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
+ { 5193, 0x000083F2 }, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
+ { 5226, 0x000083F3 }, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
+ { 5259, 0x000084ED }, /* GL_COMPRESSED_RGB_ARB */
+ { 5281, 0x000086B0 }, /* GL_COMPRESSED_RGB_FXT1_3DFX */
+ { 5309, 0x000083F0 }, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
+ { 5341, 0x00008C4A }, /* GL_COMPRESSED_SLUMINANCE */
+ { 5366, 0x00008C4B }, /* GL_COMPRESSED_SLUMINANCE_ALPHA */
+ { 5397, 0x00008C48 }, /* GL_COMPRESSED_SRGB */
+ { 5416, 0x00008C49 }, /* GL_COMPRESSED_SRGB_ALPHA */
+ { 5441, 0x000086A3 }, /* GL_COMPRESSED_TEXTURE_FORMATS */
+ { 5471, 0x0000911C }, /* GL_CONDITION_SATISFIED */
+ { 5494, 0x00008576 }, /* GL_CONSTANT */
+ { 5506, 0x00008003 }, /* GL_CONSTANT_ALPHA */
+ { 5524, 0x00008003 }, /* GL_CONSTANT_ALPHA_EXT */
+ { 5546, 0x00008576 }, /* GL_CONSTANT_ARB */
+ { 5562, 0x00001207 }, /* GL_CONSTANT_ATTENUATION */
+ { 5586, 0x00008151 }, /* GL_CONSTANT_BORDER_HP */
+ { 5608, 0x00008001 }, /* GL_CONSTANT_COLOR */
+ { 5626, 0x00008001 }, /* GL_CONSTANT_COLOR_EXT */
+ { 5648, 0x00008576 }, /* GL_CONSTANT_EXT */
+ { 5664, 0x00008010 }, /* GL_CONVOLUTION_1D */
+ { 5682, 0x00008011 }, /* GL_CONVOLUTION_2D */
+ { 5700, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR */
+ { 5728, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR_HP */
+ { 5759, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE */
+ { 5786, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE_EXT */
+ { 5817, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS */
+ { 5844, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS_EXT */
+ { 5875, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE */
+ { 5903, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE_EXT */
+ { 5935, 0x00008017 }, /* GL_CONVOLUTION_FORMAT */
+ { 5957, 0x00008017 }, /* GL_CONVOLUTION_FORMAT_EXT */
+ { 5983, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT */
+ { 6005, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT_EXT */
+ { 6031, 0x00008018 }, /* GL_CONVOLUTION_WIDTH */
+ { 6052, 0x00008018 }, /* GL_CONVOLUTION_WIDTH_EXT */
+ { 6077, 0x00008862 }, /* GL_COORD_REPLACE */
+ { 6094, 0x00008862 }, /* GL_COORD_REPLACE_ARB */
+ { 6115, 0x00008862 }, /* GL_COORD_REPLACE_NV */
+ { 6135, 0x00001503 }, /* GL_COPY */
+ { 6143, 0x0000150C }, /* GL_COPY_INVERTED */
+ { 6160, 0x00000706 }, /* GL_COPY_PIXEL_TOKEN */
+ { 6180, 0x00008F36 }, /* GL_COPY_READ_BUFFER */
+ { 6200, 0x00008F37 }, /* GL_COPY_WRITE_BUFFER */
+ { 6221, 0x00000B44 }, /* GL_CULL_FACE */
+ { 6234, 0x00000B45 }, /* GL_CULL_FACE_MODE */
+ { 6252, 0x000081AA }, /* GL_CULL_VERTEX_EXT */
+ { 6271, 0x000081AC }, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
+ { 6303, 0x000081AB }, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
+ { 6338, 0x00008626 }, /* GL_CURRENT_ATTRIB_NV */
+ { 6359, 0x00000001 }, /* GL_CURRENT_BIT */
+ { 6374, 0x00000B00 }, /* GL_CURRENT_COLOR */
+ { 6391, 0x00008453 }, /* GL_CURRENT_FOG_COORD */
+ { 6412, 0x00008453 }, /* GL_CURRENT_FOG_COORDINATE */
+ { 6438, 0x00000B01 }, /* GL_CURRENT_INDEX */
+ { 6455, 0x00008641 }, /* GL_CURRENT_MATRIX_ARB */
+ { 6477, 0x00008845 }, /* GL_CURRENT_MATRIX_INDEX_ARB */
+ { 6505, 0x00008641 }, /* GL_CURRENT_MATRIX_NV */
+ { 6526, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
+ { 6560, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_NV */
+ { 6593, 0x00000B02 }, /* GL_CURRENT_NORMAL */
+ { 6611, 0x00008843 }, /* GL_CURRENT_PALETTE_MATRIX_ARB */
+ { 6641, 0x00008B8D }, /* GL_CURRENT_PROGRAM */
+ { 6660, 0x00008865 }, /* GL_CURRENT_QUERY */
+ { 6677, 0x00008865 }, /* GL_CURRENT_QUERY_ARB */
+ { 6698, 0x00000B04 }, /* GL_CURRENT_RASTER_COLOR */
+ { 6722, 0x00000B09 }, /* GL_CURRENT_RASTER_DISTANCE */
+ { 6749, 0x00000B05 }, /* GL_CURRENT_RASTER_INDEX */
+ { 6773, 0x00000B07 }, /* GL_CURRENT_RASTER_POSITION */
+ { 6800, 0x00000B08 }, /* GL_CURRENT_RASTER_POSITION_VALID */
+ { 6833, 0x0000845F }, /* GL_CURRENT_RASTER_SECONDARY_COLOR */
+ { 6867, 0x00000B06 }, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
+ { 6900, 0x00008459 }, /* GL_CURRENT_SECONDARY_COLOR */
+ { 6927, 0x00000B03 }, /* GL_CURRENT_TEXTURE_COORDS */
+ { 6953, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB */
+ { 6978, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB_ARB */
+ { 7007, 0x000086A8 }, /* GL_CURRENT_WEIGHT_ARB */
+ { 7029, 0x00000900 }, /* GL_CW */
+ { 7035, 0x0000875B }, /* GL_DEBUG_ASSERT_MESA */
+ { 7056, 0x00008759 }, /* GL_DEBUG_OBJECT_MESA */
+ { 7077, 0x0000875A }, /* GL_DEBUG_PRINT_MESA */
+ { 7097, 0x00002101 }, /* GL_DECAL */
+ { 7106, 0x00001E03 }, /* GL_DECR */
+ { 7114, 0x00008508 }, /* GL_DECR_WRAP */
+ { 7127, 0x00008508 }, /* GL_DECR_WRAP_EXT */
+ { 7144, 0x00008B80 }, /* GL_DELETE_STATUS */
+ { 7161, 0x00001801 }, /* GL_DEPTH */
+ { 7170, 0x000088F0 }, /* GL_DEPTH24_STENCIL8 */
+ { 7190, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT */
+ { 7210, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT_EXT */
+ { 7234, 0x00000D1F }, /* GL_DEPTH_BIAS */
+ { 7248, 0x00000D56 }, /* GL_DEPTH_BITS */
+ { 7262, 0x00008891 }, /* GL_DEPTH_BOUNDS_EXT */
+ { 7282, 0x00008890 }, /* GL_DEPTH_BOUNDS_TEST_EXT */
+ { 7307, 0x00000100 }, /* GL_DEPTH_BUFFER_BIT */
+ { 7327, 0x0000864F }, /* GL_DEPTH_CLAMP_NV */
+ { 7345, 0x00000B73 }, /* GL_DEPTH_CLEAR_VALUE */
+ { 7366, 0x00001902 }, /* GL_DEPTH_COMPONENT */
+ { 7385, 0x000081A5 }, /* GL_DEPTH_COMPONENT16 */
+ { 7406, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_ARB */
+ { 7431, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_SGIX */
+ { 7457, 0x000081A6 }, /* GL_DEPTH_COMPONENT24 */
+ { 7478, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_ARB */
+ { 7503, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_SGIX */
+ { 7529, 0x000081A7 }, /* GL_DEPTH_COMPONENT32 */
+ { 7550, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_ARB */
+ { 7575, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_SGIX */
+ { 7601, 0x00000B74 }, /* GL_DEPTH_FUNC */
+ { 7615, 0x00000B70 }, /* GL_DEPTH_RANGE */
+ { 7630, 0x00000D1E }, /* GL_DEPTH_SCALE */
+ { 7645, 0x000084F9 }, /* GL_DEPTH_STENCIL */
+ { 7662, 0x0000821A }, /* GL_DEPTH_STENCIL_ATTACHMENT */
+ { 7690, 0x000084F9 }, /* GL_DEPTH_STENCIL_NV */
+ { 7710, 0x0000886F }, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
+ { 7738, 0x0000886E }, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
+ { 7766, 0x00000B71 }, /* GL_DEPTH_TEST */
+ { 7780, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE */
+ { 7802, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE_ARB */
+ { 7828, 0x00000B72 }, /* GL_DEPTH_WRITEMASK */
+ { 7847, 0x00001201 }, /* GL_DIFFUSE */
+ { 7858, 0x00000BD0 }, /* GL_DITHER */
+ { 7868, 0x00000A02 }, /* GL_DOMAIN */
+ { 7878, 0x00001100 }, /* GL_DONT_CARE */
+ { 7891, 0x000086AE }, /* GL_DOT3_RGB */
+ { 7903, 0x000086AF }, /* GL_DOT3_RGBA */
+ { 7916, 0x000086AF }, /* GL_DOT3_RGBA_ARB */
+ { 7933, 0x00008741 }, /* GL_DOT3_RGBA_EXT */
+ { 7950, 0x000086AE }, /* GL_DOT3_RGB_ARB */
+ { 7966, 0x00008740 }, /* GL_DOT3_RGB_EXT */
+ { 7982, 0x0000140A }, /* GL_DOUBLE */
+ { 7992, 0x00000C32 }, /* GL_DOUBLEBUFFER */
+ { 8008, 0x00000C01 }, /* GL_DRAW_BUFFER */
+ { 8023, 0x00008825 }, /* GL_DRAW_BUFFER0 */
+ { 8039, 0x00008825 }, /* GL_DRAW_BUFFER0_ARB */
+ { 8059, 0x00008825 }, /* GL_DRAW_BUFFER0_ATI */
+ { 8079, 0x00008826 }, /* GL_DRAW_BUFFER1 */
+ { 8095, 0x0000882F }, /* GL_DRAW_BUFFER10 */
+ { 8112, 0x0000882F }, /* GL_DRAW_BUFFER10_ARB */
+ { 8133, 0x0000882F }, /* GL_DRAW_BUFFER10_ATI */
+ { 8154, 0x00008830 }, /* GL_DRAW_BUFFER11 */
+ { 8171, 0x00008830 }, /* GL_DRAW_BUFFER11_ARB */
+ { 8192, 0x00008830 }, /* GL_DRAW_BUFFER11_ATI */
+ { 8213, 0x00008831 }, /* GL_DRAW_BUFFER12 */
+ { 8230, 0x00008831 }, /* GL_DRAW_BUFFER12_ARB */
+ { 8251, 0x00008831 }, /* GL_DRAW_BUFFER12_ATI */
+ { 8272, 0x00008832 }, /* GL_DRAW_BUFFER13 */
+ { 8289, 0x00008832 }, /* GL_DRAW_BUFFER13_ARB */
+ { 8310, 0x00008832 }, /* GL_DRAW_BUFFER13_ATI */
+ { 8331, 0x00008833 }, /* GL_DRAW_BUFFER14 */
+ { 8348, 0x00008833 }, /* GL_DRAW_BUFFER14_ARB */
+ { 8369, 0x00008833 }, /* GL_DRAW_BUFFER14_ATI */
+ { 8390, 0x00008834 }, /* GL_DRAW_BUFFER15 */
+ { 8407, 0x00008834 }, /* GL_DRAW_BUFFER15_ARB */
+ { 8428, 0x00008834 }, /* GL_DRAW_BUFFER15_ATI */
+ { 8449, 0x00008826 }, /* GL_DRAW_BUFFER1_ARB */
+ { 8469, 0x00008826 }, /* GL_DRAW_BUFFER1_ATI */
+ { 8489, 0x00008827 }, /* GL_DRAW_BUFFER2 */
+ { 8505, 0x00008827 }, /* GL_DRAW_BUFFER2_ARB */
+ { 8525, 0x00008827 }, /* GL_DRAW_BUFFER2_ATI */
+ { 8545, 0x00008828 }, /* GL_DRAW_BUFFER3 */
+ { 8561, 0x00008828 }, /* GL_DRAW_BUFFER3_ARB */
+ { 8581, 0x00008828 }, /* GL_DRAW_BUFFER3_ATI */
+ { 8601, 0x00008829 }, /* GL_DRAW_BUFFER4 */
+ { 8617, 0x00008829 }, /* GL_DRAW_BUFFER4_ARB */
+ { 8637, 0x00008829 }, /* GL_DRAW_BUFFER4_ATI */
+ { 8657, 0x0000882A }, /* GL_DRAW_BUFFER5 */
+ { 8673, 0x0000882A }, /* GL_DRAW_BUFFER5_ARB */
+ { 8693, 0x0000882A }, /* GL_DRAW_BUFFER5_ATI */
+ { 8713, 0x0000882B }, /* GL_DRAW_BUFFER6 */
+ { 8729, 0x0000882B }, /* GL_DRAW_BUFFER6_ARB */
+ { 8749, 0x0000882B }, /* GL_DRAW_BUFFER6_ATI */
+ { 8769, 0x0000882C }, /* GL_DRAW_BUFFER7 */
+ { 8785, 0x0000882C }, /* GL_DRAW_BUFFER7_ARB */
+ { 8805, 0x0000882C }, /* GL_DRAW_BUFFER7_ATI */
+ { 8825, 0x0000882D }, /* GL_DRAW_BUFFER8 */
+ { 8841, 0x0000882D }, /* GL_DRAW_BUFFER8_ARB */
+ { 8861, 0x0000882D }, /* GL_DRAW_BUFFER8_ATI */
+ { 8881, 0x0000882E }, /* GL_DRAW_BUFFER9 */
+ { 8897, 0x0000882E }, /* GL_DRAW_BUFFER9_ARB */
+ { 8917, 0x0000882E }, /* GL_DRAW_BUFFER9_ATI */
+ { 8937, 0x00008CA9 }, /* GL_DRAW_FRAMEBUFFER */
+ { 8957, 0x00008CA6 }, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
+ { 8989, 0x00008CA9 }, /* GL_DRAW_FRAMEBUFFER_EXT */
+ { 9013, 0x00000705 }, /* GL_DRAW_PIXEL_TOKEN */
+ { 9033, 0x00000304 }, /* GL_DST_ALPHA */
+ { 9046, 0x00000306 }, /* GL_DST_COLOR */
+ { 9059, 0x0000877A }, /* GL_DU8DV8_ATI */
+ { 9073, 0x00008779 }, /* GL_DUDV_ATI */
+ { 9085, 0x000088EA }, /* GL_DYNAMIC_COPY */
+ { 9101, 0x000088EA }, /* GL_DYNAMIC_COPY_ARB */
+ { 9121, 0x000088E8 }, /* GL_DYNAMIC_DRAW */
+ { 9137, 0x000088E8 }, /* GL_DYNAMIC_DRAW_ARB */
+ { 9157, 0x000088E9 }, /* GL_DYNAMIC_READ */
+ { 9173, 0x000088E9 }, /* GL_DYNAMIC_READ_ARB */
+ { 9193, 0x00000B43 }, /* GL_EDGE_FLAG */
+ { 9206, 0x00008079 }, /* GL_EDGE_FLAG_ARRAY */
+ { 9225, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
+ { 9259, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB */
+ { 9297, 0x00008093 }, /* GL_EDGE_FLAG_ARRAY_POINTER */
+ { 9324, 0x0000808C }, /* GL_EDGE_FLAG_ARRAY_STRIDE */
+ { 9350, 0x00008893 }, /* GL_ELEMENT_ARRAY_BUFFER */
+ { 9374, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
+ { 9406, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB */
+ { 9442, 0x00001600 }, /* GL_EMISSION */
+ { 9454, 0x00002000 }, /* GL_ENABLE_BIT */
+ { 9468, 0x00000202 }, /* GL_EQUAL */
+ { 9477, 0x00001509 }, /* GL_EQUIV */
+ { 9486, 0x00010000 }, /* GL_EVAL_BIT */
+ { 9498, 0x00000800 }, /* GL_EXP */
+ { 9505, 0x00000801 }, /* GL_EXP2 */
+ { 9513, 0x00001F03 }, /* GL_EXTENSIONS */
+ { 9527, 0x00002400 }, /* GL_EYE_LINEAR */
+ { 9541, 0x00002502 }, /* GL_EYE_PLANE */
+ { 9554, 0x0000855C }, /* GL_EYE_PLANE_ABSOLUTE_NV */
+ { 9579, 0x0000855B }, /* GL_EYE_RADIAL_NV */
+ { 9596, 0x00000000 }, /* GL_FALSE */
+ { 9605, 0x00001101 }, /* GL_FASTEST */
+ { 9616, 0x00001C01 }, /* GL_FEEDBACK */
+ { 9628, 0x00000DF0 }, /* GL_FEEDBACK_BUFFER_POINTER */
+ { 9655, 0x00000DF1 }, /* GL_FEEDBACK_BUFFER_SIZE */
+ { 9679, 0x00000DF2 }, /* GL_FEEDBACK_BUFFER_TYPE */
+ { 9703, 0x00001B02 }, /* GL_FILL */
+ { 9711, 0x00008E4D }, /* GL_FIRST_VERTEX_CONVENTION_EXT */
+ { 9742, 0x00001D00 }, /* GL_FLAT */
+ { 9750, 0x00001406 }, /* GL_FLOAT */
+ { 9759, 0x00008B5A }, /* GL_FLOAT_MAT2 */
+ { 9773, 0x00008B5A }, /* GL_FLOAT_MAT2_ARB */
+ { 9791, 0x00008B65 }, /* GL_FLOAT_MAT2x3 */
+ { 9807, 0x00008B66 }, /* GL_FLOAT_MAT2x4 */
+ { 9823, 0x00008B5B }, /* GL_FLOAT_MAT3 */
+ { 9837, 0x00008B5B }, /* GL_FLOAT_MAT3_ARB */
+ { 9855, 0x00008B67 }, /* GL_FLOAT_MAT3x2 */
+ { 9871, 0x00008B68 }, /* GL_FLOAT_MAT3x4 */
+ { 9887, 0x00008B5C }, /* GL_FLOAT_MAT4 */
+ { 9901, 0x00008B5C }, /* GL_FLOAT_MAT4_ARB */
+ { 9919, 0x00008B69 }, /* GL_FLOAT_MAT4x2 */
+ { 9935, 0x00008B6A }, /* GL_FLOAT_MAT4x3 */
+ { 9951, 0x00008B50 }, /* GL_FLOAT_VEC2 */
+ { 9965, 0x00008B50 }, /* GL_FLOAT_VEC2_ARB */
+ { 9983, 0x00008B51 }, /* GL_FLOAT_VEC3 */
+ { 9997, 0x00008B51 }, /* GL_FLOAT_VEC3_ARB */
+ { 10015, 0x00008B52 }, /* GL_FLOAT_VEC4 */
+ { 10029, 0x00008B52 }, /* GL_FLOAT_VEC4_ARB */
+ { 10047, 0x00000B60 }, /* GL_FOG */
+ { 10054, 0x00000080 }, /* GL_FOG_BIT */
+ { 10065, 0x00000B66 }, /* GL_FOG_COLOR */
+ { 10078, 0x00008451 }, /* GL_FOG_COORD */
+ { 10091, 0x00008451 }, /* GL_FOG_COORDINATE */
+ { 10109, 0x00008457 }, /* GL_FOG_COORDINATE_ARRAY */
+ { 10133, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
+ { 10172, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB */
+ { 10215, 0x00008456 }, /* GL_FOG_COORDINATE_ARRAY_POINTER */
+ { 10247, 0x00008455 }, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
+ { 10278, 0x00008454 }, /* GL_FOG_COORDINATE_ARRAY_TYPE */
+ { 10307, 0x00008450 }, /* GL_FOG_COORDINATE_SOURCE */
+ { 10332, 0x00008457 }, /* GL_FOG_COORD_ARRAY */
+ { 10351, 0x0000889D }, /* GL_FOG_COORD_ARRAY_BUFFER_BINDING */
+ { 10385, 0x00008456 }, /* GL_FOG_COORD_ARRAY_POINTER */
+ { 10412, 0x00008455 }, /* GL_FOG_COORD_ARRAY_STRIDE */
+ { 10438, 0x00008454 }, /* GL_FOG_COORD_ARRAY_TYPE */
+ { 10462, 0x00008450 }, /* GL_FOG_COORD_SRC */
+ { 10479, 0x00000B62 }, /* GL_FOG_DENSITY */
+ { 10494, 0x0000855A }, /* GL_FOG_DISTANCE_MODE_NV */
+ { 10518, 0x00000B64 }, /* GL_FOG_END */
+ { 10529, 0x00000C54 }, /* GL_FOG_HINT */
+ { 10541, 0x00000B61 }, /* GL_FOG_INDEX */
+ { 10554, 0x00000B65 }, /* GL_FOG_MODE */
+ { 10566, 0x00008198 }, /* GL_FOG_OFFSET_SGIX */
+ { 10585, 0x00008199 }, /* GL_FOG_OFFSET_VALUE_SGIX */
+ { 10610, 0x00000B63 }, /* GL_FOG_START */
+ { 10623, 0x00008452 }, /* GL_FRAGMENT_DEPTH */
+ { 10641, 0x00008804 }, /* GL_FRAGMENT_PROGRAM_ARB */
+ { 10665, 0x00008B30 }, /* GL_FRAGMENT_SHADER */
+ { 10684, 0x00008B30 }, /* GL_FRAGMENT_SHADER_ARB */
+ { 10707, 0x00008B8B }, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
+ { 10742, 0x00008D40 }, /* GL_FRAMEBUFFER */
+ { 10757, 0x00008215 }, /* GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */
+ { 10794, 0x00008214 }, /* GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */
+ { 10830, 0x00008210 }, /* GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */
+ { 10871, 0x00008211 }, /* GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */
+ { 10912, 0x00008216 }, /* GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */
+ { 10949, 0x00008213 }, /* GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */
+ { 10986, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */
+ { 11024, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */
+ { 11066, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */
+ { 11104, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */
+ { 11146, 0x00008212 }, /* GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */
+ { 11181, 0x00008217 }, /* GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */
+ { 11220, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */
+ { 11269, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */
+ { 11317, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */
+ { 11369, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+ { 11409, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT */
+ { 11453, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */
+ { 11493, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */
+ { 11537, 0x00008CA6 }, /* GL_FRAMEBUFFER_BINDING_EXT */
+ { 11564, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE */
+ { 11588, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE_EXT */
+ { 11616, 0x00008218 }, /* GL_FRAMEBUFFER_DEFAULT */
+ { 11639, 0x00008D40 }, /* GL_FRAMEBUFFER_EXT */
+ { 11658, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */
+ { 11695, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */
+ { 11736, 0x00008CD9 }, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
+ { 11777, 0x00008CDB }, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
+ { 11819, 0x00008CD8 }, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
+ { 11870, 0x00008CDA }, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
+ { 11908, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */
+ { 11953, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */
+ { 12002, 0x00008D56 }, /* GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */
+ { 12040, 0x00008CDC }, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
+ { 12082, 0x00008CDE }, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
+ { 12114, 0x00008219 }, /* GL_FRAMEBUFFER_UNDEFINED */
+ { 12139, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED */
+ { 12166, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */
+ { 12197, 0x00000404 }, /* GL_FRONT */
+ { 12206, 0x00000408 }, /* GL_FRONT_AND_BACK */
+ { 12224, 0x00000B46 }, /* GL_FRONT_FACE */
+ { 12238, 0x00000400 }, /* GL_FRONT_LEFT */
+ { 12252, 0x00000401 }, /* GL_FRONT_RIGHT */
+ { 12267, 0x00008006 }, /* GL_FUNC_ADD */
+ { 12279, 0x00008006 }, /* GL_FUNC_ADD_EXT */
+ { 12295, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT */
+ { 12320, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT_EXT */
+ { 12349, 0x0000800A }, /* GL_FUNC_SUBTRACT */
+ { 12366, 0x0000800A }, /* GL_FUNC_SUBTRACT_EXT */
+ { 12387, 0x00008191 }, /* GL_GENERATE_MIPMAP */
+ { 12406, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT */
+ { 12430, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT_SGIS */
+ { 12459, 0x00008191 }, /* GL_GENERATE_MIPMAP_SGIS */
+ { 12483, 0x00000206 }, /* GL_GEQUAL */
+ { 12493, 0x00000204 }, /* GL_GREATER */
+ { 12504, 0x00001904 }, /* GL_GREEN */
+ { 12513, 0x00000D19 }, /* GL_GREEN_BIAS */
+ { 12527, 0x00000D53 }, /* GL_GREEN_BITS */
+ { 12541, 0x00000D18 }, /* GL_GREEN_SCALE */
+ { 12556, 0x00008000 }, /* GL_HINT_BIT */
+ { 12568, 0x00008024 }, /* GL_HISTOGRAM */
+ { 12581, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE */
+ { 12605, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE_EXT */
+ { 12633, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE */
+ { 12656, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE_EXT */
+ { 12683, 0x00008024 }, /* GL_HISTOGRAM_EXT */
+ { 12700, 0x00008027 }, /* GL_HISTOGRAM_FORMAT */
+ { 12720, 0x00008027 }, /* GL_HISTOGRAM_FORMAT_EXT */
+ { 12744, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE */
+ { 12768, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE_EXT */
+ { 12796, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE */
+ { 12824, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE_EXT */
+ { 12856, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE */
+ { 12878, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE_EXT */
+ { 12904, 0x0000802D }, /* GL_HISTOGRAM_SINK */
+ { 12922, 0x0000802D }, /* GL_HISTOGRAM_SINK_EXT */
+ { 12944, 0x00008026 }, /* GL_HISTOGRAM_WIDTH */
+ { 12963, 0x00008026 }, /* GL_HISTOGRAM_WIDTH_EXT */
+ { 12986, 0x0000862A }, /* GL_IDENTITY_NV */
+ { 13001, 0x00008150 }, /* GL_IGNORE_BORDER_HP */
+ { 13021, 0x00008B9B }, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
+ { 13061, 0x00008B9A }, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
+ { 13099, 0x00001E02 }, /* GL_INCR */
+ { 13107, 0x00008507 }, /* GL_INCR_WRAP */
+ { 13120, 0x00008507 }, /* GL_INCR_WRAP_EXT */
+ { 13137, 0x00008222 }, /* GL_INDEX */
+ { 13146, 0x00008077 }, /* GL_INDEX_ARRAY */
+ { 13161, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING */
+ { 13191, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING_ARB */
+ { 13225, 0x00008091 }, /* GL_INDEX_ARRAY_POINTER */
+ { 13248, 0x00008086 }, /* GL_INDEX_ARRAY_STRIDE */
+ { 13270, 0x00008085 }, /* GL_INDEX_ARRAY_TYPE */
+ { 13290, 0x00000D51 }, /* GL_INDEX_BITS */
+ { 13304, 0x00000C20 }, /* GL_INDEX_CLEAR_VALUE */
+ { 13325, 0x00000BF1 }, /* GL_INDEX_LOGIC_OP */
+ { 13343, 0x00000C30 }, /* GL_INDEX_MODE */
+ { 13357, 0x00000D13 }, /* GL_INDEX_OFFSET */
+ { 13373, 0x00000D12 }, /* GL_INDEX_SHIFT */
+ { 13388, 0x00000C21 }, /* GL_INDEX_WRITEMASK */
+ { 13407, 0x00008B84 }, /* GL_INFO_LOG_LENGTH */
+ { 13426, 0x00001404 }, /* GL_INT */
+ { 13433, 0x00008049 }, /* GL_INTENSITY */
+ { 13446, 0x0000804C }, /* GL_INTENSITY12 */
+ { 13461, 0x0000804C }, /* GL_INTENSITY12_EXT */
+ { 13480, 0x0000804D }, /* GL_INTENSITY16 */
+ { 13495, 0x0000804D }, /* GL_INTENSITY16_EXT */
+ { 13514, 0x0000804A }, /* GL_INTENSITY4 */
+ { 13528, 0x0000804A }, /* GL_INTENSITY4_EXT */
+ { 13546, 0x0000804B }, /* GL_INTENSITY8 */
+ { 13560, 0x0000804B }, /* GL_INTENSITY8_EXT */
+ { 13578, 0x00008049 }, /* GL_INTENSITY_EXT */
+ { 13595, 0x00008575 }, /* GL_INTERPOLATE */
+ { 13610, 0x00008575 }, /* GL_INTERPOLATE_ARB */
+ { 13629, 0x00008575 }, /* GL_INTERPOLATE_EXT */
+ { 13648, 0x00008B53 }, /* GL_INT_VEC2 */
+ { 13660, 0x00008B53 }, /* GL_INT_VEC2_ARB */
+ { 13676, 0x00008B54 }, /* GL_INT_VEC3 */
+ { 13688, 0x00008B54 }, /* GL_INT_VEC3_ARB */
+ { 13704, 0x00008B55 }, /* GL_INT_VEC4 */
+ { 13716, 0x00008B55 }, /* GL_INT_VEC4_ARB */
+ { 13732, 0x00000500 }, /* GL_INVALID_ENUM */
+ { 13748, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION */
+ { 13781, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */
+ { 13818, 0x00000502 }, /* GL_INVALID_OPERATION */
+ { 13839, 0x00000501 }, /* GL_INVALID_VALUE */
+ { 13856, 0x0000862B }, /* GL_INVERSE_NV */
+ { 13870, 0x0000862D }, /* GL_INVERSE_TRANSPOSE_NV */
+ { 13894, 0x0000150A }, /* GL_INVERT */
+ { 13904, 0x00001E00 }, /* GL_KEEP */
+ { 13912, 0x00008E4E }, /* GL_LAST_VERTEX_CONVENTION_EXT */
+ { 13942, 0x00000406 }, /* GL_LEFT */
+ { 13950, 0x00000203 }, /* GL_LEQUAL */
+ { 13960, 0x00000201 }, /* GL_LESS */
+ { 13968, 0x00004000 }, /* GL_LIGHT0 */
+ { 13978, 0x00004001 }, /* GL_LIGHT1 */
+ { 13988, 0x00004002 }, /* GL_LIGHT2 */
+ { 13998, 0x00004003 }, /* GL_LIGHT3 */
+ { 14008, 0x00004004 }, /* GL_LIGHT4 */
+ { 14018, 0x00004005 }, /* GL_LIGHT5 */
+ { 14028, 0x00004006 }, /* GL_LIGHT6 */
+ { 14038, 0x00004007 }, /* GL_LIGHT7 */
+ { 14048, 0x00000B50 }, /* GL_LIGHTING */
+ { 14060, 0x00000040 }, /* GL_LIGHTING_BIT */
+ { 14076, 0x00000B53 }, /* GL_LIGHT_MODEL_AMBIENT */
+ { 14099, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL */
+ { 14128, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL_EXT */
+ { 14161, 0x00000B51 }, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
+ { 14189, 0x00000B52 }, /* GL_LIGHT_MODEL_TWO_SIDE */
+ { 14213, 0x00001B01 }, /* GL_LINE */
+ { 14221, 0x00002601 }, /* GL_LINEAR */
+ { 14231, 0x00001208 }, /* GL_LINEAR_ATTENUATION */
+ { 14253, 0x00008170 }, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
+ { 14283, 0x0000844F }, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
+ { 14314, 0x00002703 }, /* GL_LINEAR_MIPMAP_LINEAR */
+ { 14338, 0x00002701 }, /* GL_LINEAR_MIPMAP_NEAREST */
+ { 14363, 0x00000001 }, /* GL_LINES */
+ { 14372, 0x00000004 }, /* GL_LINE_BIT */
+ { 14384, 0x00000002 }, /* GL_LINE_LOOP */
+ { 14397, 0x00000707 }, /* GL_LINE_RESET_TOKEN */
+ { 14417, 0x00000B20 }, /* GL_LINE_SMOOTH */
+ { 14432, 0x00000C52 }, /* GL_LINE_SMOOTH_HINT */
+ { 14452, 0x00000B24 }, /* GL_LINE_STIPPLE */
+ { 14468, 0x00000B25 }, /* GL_LINE_STIPPLE_PATTERN */
+ { 14492, 0x00000B26 }, /* GL_LINE_STIPPLE_REPEAT */
+ { 14515, 0x00000003 }, /* GL_LINE_STRIP */
+ { 14529, 0x00000702 }, /* GL_LINE_TOKEN */
+ { 14543, 0x00000B21 }, /* GL_LINE_WIDTH */
+ { 14557, 0x00000B23 }, /* GL_LINE_WIDTH_GRANULARITY */
+ { 14583, 0x00000B22 }, /* GL_LINE_WIDTH_RANGE */
+ { 14603, 0x00008B82 }, /* GL_LINK_STATUS */
+ { 14618, 0x00000B32 }, /* GL_LIST_BASE */
+ { 14631, 0x00020000 }, /* GL_LIST_BIT */
+ { 14643, 0x00000B33 }, /* GL_LIST_INDEX */
+ { 14657, 0x00000B30 }, /* GL_LIST_MODE */
+ { 14670, 0x00000101 }, /* GL_LOAD */
+ { 14678, 0x00000BF1 }, /* GL_LOGIC_OP */
+ { 14690, 0x00000BF0 }, /* GL_LOGIC_OP_MODE */
+ { 14707, 0x00008CA1 }, /* GL_LOWER_LEFT */
+ { 14721, 0x00001909 }, /* GL_LUMINANCE */
+ { 14734, 0x00008041 }, /* GL_LUMINANCE12 */
+ { 14749, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12 */
+ { 14772, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12_EXT */
+ { 14799, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4 */
+ { 14821, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4_EXT */
+ { 14847, 0x00008041 }, /* GL_LUMINANCE12_EXT */
+ { 14866, 0x00008042 }, /* GL_LUMINANCE16 */
+ { 14881, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16 */
+ { 14904, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16_EXT */
+ { 14931, 0x00008042 }, /* GL_LUMINANCE16_EXT */
+ { 14950, 0x0000803F }, /* GL_LUMINANCE4 */
+ { 14964, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4 */
+ { 14985, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4_EXT */
+ { 15010, 0x0000803F }, /* GL_LUMINANCE4_EXT */
+ { 15028, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2 */
+ { 15049, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2_EXT */
+ { 15074, 0x00008040 }, /* GL_LUMINANCE8 */
+ { 15088, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8 */
+ { 15109, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8_EXT */
+ { 15134, 0x00008040 }, /* GL_LUMINANCE8_EXT */
+ { 15152, 0x0000190A }, /* GL_LUMINANCE_ALPHA */
+ { 15171, 0x00000D90 }, /* GL_MAP1_COLOR_4 */
+ { 15187, 0x00000DD0 }, /* GL_MAP1_GRID_DOMAIN */
+ { 15207, 0x00000DD1 }, /* GL_MAP1_GRID_SEGMENTS */
+ { 15229, 0x00000D91 }, /* GL_MAP1_INDEX */
+ { 15243, 0x00000D92 }, /* GL_MAP1_NORMAL */
+ { 15258, 0x00000D93 }, /* GL_MAP1_TEXTURE_COORD_1 */
+ { 15282, 0x00000D94 }, /* GL_MAP1_TEXTURE_COORD_2 */
+ { 15306, 0x00000D95 }, /* GL_MAP1_TEXTURE_COORD_3 */
+ { 15330, 0x00000D96 }, /* GL_MAP1_TEXTURE_COORD_4 */
+ { 15354, 0x00000D97 }, /* GL_MAP1_VERTEX_3 */
+ { 15371, 0x00000D98 }, /* GL_MAP1_VERTEX_4 */
+ { 15388, 0x00008660 }, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
+ { 15416, 0x0000866A }, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
+ { 15445, 0x0000866B }, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
+ { 15474, 0x0000866C }, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
+ { 15503, 0x0000866D }, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
+ { 15532, 0x0000866E }, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
+ { 15561, 0x0000866F }, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
+ { 15590, 0x00008661 }, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
+ { 15618, 0x00008662 }, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
+ { 15646, 0x00008663 }, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
+ { 15674, 0x00008664 }, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
+ { 15702, 0x00008665 }, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
+ { 15730, 0x00008666 }, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
+ { 15758, 0x00008667 }, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
+ { 15786, 0x00008668 }, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
+ { 15814, 0x00008669 }, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
+ { 15842, 0x00000DB0 }, /* GL_MAP2_COLOR_4 */
+ { 15858, 0x00000DD2 }, /* GL_MAP2_GRID_DOMAIN */
+ { 15878, 0x00000DD3 }, /* GL_MAP2_GRID_SEGMENTS */
+ { 15900, 0x00000DB1 }, /* GL_MAP2_INDEX */
+ { 15914, 0x00000DB2 }, /* GL_MAP2_NORMAL */
+ { 15929, 0x00000DB3 }, /* GL_MAP2_TEXTURE_COORD_1 */
+ { 15953, 0x00000DB4 }, /* GL_MAP2_TEXTURE_COORD_2 */
+ { 15977, 0x00000DB5 }, /* GL_MAP2_TEXTURE_COORD_3 */
+ { 16001, 0x00000DB6 }, /* GL_MAP2_TEXTURE_COORD_4 */
+ { 16025, 0x00000DB7 }, /* GL_MAP2_VERTEX_3 */
+ { 16042, 0x00000DB8 }, /* GL_MAP2_VERTEX_4 */
+ { 16059, 0x00008670 }, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
+ { 16087, 0x0000867A }, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
+ { 16116, 0x0000867B }, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
+ { 16145, 0x0000867C }, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
+ { 16174, 0x0000867D }, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
+ { 16203, 0x0000867E }, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
+ { 16232, 0x0000867F }, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
+ { 16261, 0x00008671 }, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
+ { 16289, 0x00008672 }, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
+ { 16317, 0x00008673 }, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
+ { 16345, 0x00008674 }, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
+ { 16373, 0x00008675 }, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
+ { 16401, 0x00008676 }, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
+ { 16429, 0x00008677 }, /* GL_MAP2_VERTEX_ATTRIB7_4_NV */
+ { 16457, 0x00008678 }, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
+ { 16485, 0x00008679 }, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
+ { 16513, 0x00000D10 }, /* GL_MAP_COLOR */
+ { 16526, 0x00000010 }, /* GL_MAP_FLUSH_EXPLICIT_BIT */
+ { 16552, 0x00000008 }, /* GL_MAP_INVALIDATE_BUFFER_BIT */
+ { 16581, 0x00000004 }, /* GL_MAP_INVALIDATE_RANGE_BIT */
+ { 16609, 0x00000001 }, /* GL_MAP_READ_BIT */
+ { 16625, 0x00000D11 }, /* GL_MAP_STENCIL */
+ { 16640, 0x00000020 }, /* GL_MAP_UNSYNCHRONIZED_BIT */
+ { 16666, 0x00000002 }, /* GL_MAP_WRITE_BIT */
+ { 16683, 0x000088C0 }, /* GL_MATRIX0_ARB */
+ { 16698, 0x00008630 }, /* GL_MATRIX0_NV */
+ { 16712, 0x000088CA }, /* GL_MATRIX10_ARB */
+ { 16728, 0x000088CB }, /* GL_MATRIX11_ARB */
+ { 16744, 0x000088CC }, /* GL_MATRIX12_ARB */
+ { 16760, 0x000088CD }, /* GL_MATRIX13_ARB */
+ { 16776, 0x000088CE }, /* GL_MATRIX14_ARB */
+ { 16792, 0x000088CF }, /* GL_MATRIX15_ARB */
+ { 16808, 0x000088D0 }, /* GL_MATRIX16_ARB */
+ { 16824, 0x000088D1 }, /* GL_MATRIX17_ARB */
+ { 16840, 0x000088D2 }, /* GL_MATRIX18_ARB */
+ { 16856, 0x000088D3 }, /* GL_MATRIX19_ARB */
+ { 16872, 0x000088C1 }, /* GL_MATRIX1_ARB */
+ { 16887, 0x00008631 }, /* GL_MATRIX1_NV */
+ { 16901, 0x000088D4 }, /* GL_MATRIX20_ARB */
+ { 16917, 0x000088D5 }, /* GL_MATRIX21_ARB */
+ { 16933, 0x000088D6 }, /* GL_MATRIX22_ARB */
+ { 16949, 0x000088D7 }, /* GL_MATRIX23_ARB */
+ { 16965, 0x000088D8 }, /* GL_MATRIX24_ARB */
+ { 16981, 0x000088D9 }, /* GL_MATRIX25_ARB */
+ { 16997, 0x000088DA }, /* GL_MATRIX26_ARB */
+ { 17013, 0x000088DB }, /* GL_MATRIX27_ARB */
+ { 17029, 0x000088DC }, /* GL_MATRIX28_ARB */
+ { 17045, 0x000088DD }, /* GL_MATRIX29_ARB */
+ { 17061, 0x000088C2 }, /* GL_MATRIX2_ARB */
+ { 17076, 0x00008632 }, /* GL_MATRIX2_NV */
+ { 17090, 0x000088DE }, /* GL_MATRIX30_ARB */
+ { 17106, 0x000088DF }, /* GL_MATRIX31_ARB */
+ { 17122, 0x000088C3 }, /* GL_MATRIX3_ARB */
+ { 17137, 0x00008633 }, /* GL_MATRIX3_NV */
+ { 17151, 0x000088C4 }, /* GL_MATRIX4_ARB */
+ { 17166, 0x00008634 }, /* GL_MATRIX4_NV */
+ { 17180, 0x000088C5 }, /* GL_MATRIX5_ARB */
+ { 17195, 0x00008635 }, /* GL_MATRIX5_NV */
+ { 17209, 0x000088C6 }, /* GL_MATRIX6_ARB */
+ { 17224, 0x00008636 }, /* GL_MATRIX6_NV */
+ { 17238, 0x000088C7 }, /* GL_MATRIX7_ARB */
+ { 17253, 0x00008637 }, /* GL_MATRIX7_NV */
+ { 17267, 0x000088C8 }, /* GL_MATRIX8_ARB */
+ { 17282, 0x000088C9 }, /* GL_MATRIX9_ARB */
+ { 17297, 0x00008844 }, /* GL_MATRIX_INDEX_ARRAY_ARB */
+ { 17323, 0x00008849 }, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
+ { 17357, 0x00008846 }, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
+ { 17388, 0x00008848 }, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
+ { 17421, 0x00008847 }, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
+ { 17452, 0x00000BA0 }, /* GL_MATRIX_MODE */
+ { 17467, 0x00008840 }, /* GL_MATRIX_PALETTE_ARB */
+ { 17489, 0x00008008 }, /* GL_MAX */
+ { 17496, 0x00008073 }, /* GL_MAX_3D_TEXTURE_SIZE */
+ { 17519, 0x000088FF }, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
+ { 17551, 0x00000D35 }, /* GL_MAX_ATTRIB_STACK_DEPTH */
+ { 17577, 0x00000D3B }, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
+ { 17610, 0x00008177 }, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
+ { 17636, 0x00008178 }, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ { 17670, 0x00000D32 }, /* GL_MAX_CLIP_PLANES */
+ { 17689, 0x00008CDF }, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
+ { 17718, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
+ { 17750, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI */
+ { 17786, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
+ { 17822, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB */
+ { 17862, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT */
+ { 17888, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT_EXT */
+ { 17918, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH */
+ { 17943, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH_EXT */
+ { 17972, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
+ { 18001, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB */
+ { 18034, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS */
+ { 18054, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ARB */
+ { 18078, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ATI */
+ { 18102, 0x000080E9 }, /* GL_MAX_ELEMENTS_INDICES */
+ { 18126, 0x000080E8 }, /* GL_MAX_ELEMENTS_VERTICES */
+ { 18151, 0x00000D30 }, /* GL_MAX_EVAL_ORDER */
+ { 18169, 0x00008008 }, /* GL_MAX_EXT */
+ { 18180, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
+ { 18215, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB */
+ { 18254, 0x00000D31 }, /* GL_MAX_LIGHTS */
+ { 18268, 0x00000B31 }, /* GL_MAX_LIST_NESTING */
+ { 18288, 0x00008841 }, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
+ { 18326, 0x00000D36 }, /* GL_MAX_MODELVIEW_STACK_DEPTH */
+ { 18355, 0x00000D37 }, /* GL_MAX_NAME_STACK_DEPTH */
+ { 18379, 0x00008842 }, /* GL_MAX_PALETTE_MATRICES_ARB */
+ { 18407, 0x00000D34 }, /* GL_MAX_PIXEL_MAP_TABLE */
+ { 18430, 0x000088B1 }, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
+ { 18467, 0x0000880B }, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ { 18503, 0x000088AD }, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
+ { 18530, 0x000088F5 }, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
+ { 18559, 0x000088B5 }, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
+ { 18593, 0x000088F4 }, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */
+ { 18629, 0x000088F6 }, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
+ { 18656, 0x000088A1 }, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
+ { 18688, 0x000088B4 }, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
+ { 18724, 0x000088F8 }, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
+ { 18753, 0x000088F7 }, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
+ { 18782, 0x0000862F }, /* GL_MAX_PROGRAM_MATRICES_ARB */
+ { 18810, 0x0000862E }, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
+ { 18848, 0x000088B3 }, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ { 18892, 0x0000880E }, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ { 18935, 0x000088AF }, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
+ { 18969, 0x000088A3 }, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ { 19008, 0x000088AB }, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
+ { 19045, 0x000088A7 }, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ { 19083, 0x00008810 }, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ { 19126, 0x0000880F }, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ { 19169, 0x000088A9 }, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
+ { 19199, 0x000088A5 }, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
+ { 19230, 0x0000880D }, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
+ { 19266, 0x0000880C }, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ { 19302, 0x00000D38 }, /* GL_MAX_PROJECTION_STACK_DEPTH */
+ { 19332, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
+ { 19366, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_NV */
+ { 19399, 0x000084E8 }, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
+ { 19428, 0x00008D57 }, /* GL_MAX_SAMPLES */
+ { 19443, 0x00009111 }, /* GL_MAX_SERVER_WAIT_TIMEOUT */
+ { 19470, 0x00008504 }, /* GL_MAX_SHININESS_NV */
+ { 19490, 0x00008505 }, /* GL_MAX_SPOT_EXPONENT_NV */
+ { 19514, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS */
+ { 19536, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS_ARB */
+ { 19562, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS */
+ { 19589, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS_ARB */
+ { 19620, 0x000084FD }, /* GL_MAX_TEXTURE_LOD_BIAS */
+ { 19644, 0x000084FF }, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
+ { 19678, 0x00000D33 }, /* GL_MAX_TEXTURE_SIZE */
+ { 19698, 0x00000D39 }, /* GL_MAX_TEXTURE_STACK_DEPTH */
+ { 19725, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS */
+ { 19746, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS_ARB */
+ { 19771, 0x0000862F }, /* GL_MAX_TRACK_MATRICES_NV */
+ { 19796, 0x0000862E }, /* GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */
+ { 19831, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS */
+ { 19853, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS_ARB */
+ { 19879, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS */
+ { 19901, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS_ARB */
+ { 19927, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
+ { 19961, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */
+ { 19999, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
+ { 20032, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB */
+ { 20069, 0x000086A4 }, /* GL_MAX_VERTEX_UNITS_ARB */
+ { 20093, 0x00000D3A }, /* GL_MAX_VIEWPORT_DIMS */
+ { 20114, 0x00008007 }, /* GL_MIN */
+ { 20121, 0x0000802E }, /* GL_MINMAX */
+ { 20131, 0x0000802E }, /* GL_MINMAX_EXT */
+ { 20145, 0x0000802F }, /* GL_MINMAX_FORMAT */
+ { 20162, 0x0000802F }, /* GL_MINMAX_FORMAT_EXT */
+ { 20183, 0x00008030 }, /* GL_MINMAX_SINK */
+ { 20198, 0x00008030 }, /* GL_MINMAX_SINK_EXT */
+ { 20217, 0x00008007 }, /* GL_MIN_EXT */
+ { 20228, 0x00008370 }, /* GL_MIRRORED_REPEAT */
+ { 20247, 0x00008370 }, /* GL_MIRRORED_REPEAT_ARB */
+ { 20270, 0x00008370 }, /* GL_MIRRORED_REPEAT_IBM */
+ { 20293, 0x00008742 }, /* GL_MIRROR_CLAMP_ATI */
+ { 20313, 0x00008742 }, /* GL_MIRROR_CLAMP_EXT */
+ { 20333, 0x00008912 }, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
+ { 20363, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_ATI */
+ { 20391, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
+ { 20419, 0x00001700 }, /* GL_MODELVIEW */
+ { 20432, 0x00001700 }, /* GL_MODELVIEW0_ARB */
+ { 20450, 0x0000872A }, /* GL_MODELVIEW10_ARB */
+ { 20469, 0x0000872B }, /* GL_MODELVIEW11_ARB */
+ { 20488, 0x0000872C }, /* GL_MODELVIEW12_ARB */
+ { 20507, 0x0000872D }, /* GL_MODELVIEW13_ARB */
+ { 20526, 0x0000872E }, /* GL_MODELVIEW14_ARB */
+ { 20545, 0x0000872F }, /* GL_MODELVIEW15_ARB */
+ { 20564, 0x00008730 }, /* GL_MODELVIEW16_ARB */
+ { 20583, 0x00008731 }, /* GL_MODELVIEW17_ARB */
+ { 20602, 0x00008732 }, /* GL_MODELVIEW18_ARB */
+ { 20621, 0x00008733 }, /* GL_MODELVIEW19_ARB */
+ { 20640, 0x0000850A }, /* GL_MODELVIEW1_ARB */
+ { 20658, 0x00008734 }, /* GL_MODELVIEW20_ARB */
+ { 20677, 0x00008735 }, /* GL_MODELVIEW21_ARB */
+ { 20696, 0x00008736 }, /* GL_MODELVIEW22_ARB */
+ { 20715, 0x00008737 }, /* GL_MODELVIEW23_ARB */
+ { 20734, 0x00008738 }, /* GL_MODELVIEW24_ARB */
+ { 20753, 0x00008739 }, /* GL_MODELVIEW25_ARB */
+ { 20772, 0x0000873A }, /* GL_MODELVIEW26_ARB */
+ { 20791, 0x0000873B }, /* GL_MODELVIEW27_ARB */
+ { 20810, 0x0000873C }, /* GL_MODELVIEW28_ARB */
+ { 20829, 0x0000873D }, /* GL_MODELVIEW29_ARB */
+ { 20848, 0x00008722 }, /* GL_MODELVIEW2_ARB */
+ { 20866, 0x0000873E }, /* GL_MODELVIEW30_ARB */
+ { 20885, 0x0000873F }, /* GL_MODELVIEW31_ARB */
+ { 20904, 0x00008723 }, /* GL_MODELVIEW3_ARB */
+ { 20922, 0x00008724 }, /* GL_MODELVIEW4_ARB */
+ { 20940, 0x00008725 }, /* GL_MODELVIEW5_ARB */
+ { 20958, 0x00008726 }, /* GL_MODELVIEW6_ARB */
+ { 20976, 0x00008727 }, /* GL_MODELVIEW7_ARB */
+ { 20994, 0x00008728 }, /* GL_MODELVIEW8_ARB */
+ { 21012, 0x00008729 }, /* GL_MODELVIEW9_ARB */
+ { 21030, 0x00000BA6 }, /* GL_MODELVIEW_MATRIX */
+ { 21050, 0x00008629 }, /* GL_MODELVIEW_PROJECTION_NV */
+ { 21077, 0x00000BA3 }, /* GL_MODELVIEW_STACK_DEPTH */
+ { 21102, 0x00002100 }, /* GL_MODULATE */
+ { 21114, 0x00008744 }, /* GL_MODULATE_ADD_ATI */
+ { 21134, 0x00008745 }, /* GL_MODULATE_SIGNED_ADD_ATI */
+ { 21161, 0x00008746 }, /* GL_MODULATE_SUBTRACT_ATI */
+ { 21186, 0x00000103 }, /* GL_MULT */
+ { 21194, 0x0000809D }, /* GL_MULTISAMPLE */
+ { 21209, 0x000086B2 }, /* GL_MULTISAMPLE_3DFX */
+ { 21229, 0x0000809D }, /* GL_MULTISAMPLE_ARB */
+ { 21248, 0x20000000 }, /* GL_MULTISAMPLE_BIT */
+ { 21267, 0x20000000 }, /* GL_MULTISAMPLE_BIT_3DFX */
+ { 21291, 0x20000000 }, /* GL_MULTISAMPLE_BIT_ARB */
+ { 21314, 0x00008534 }, /* GL_MULTISAMPLE_FILTER_HINT_NV */
+ { 21344, 0x00002A25 }, /* GL_N3F_V3F */
+ { 21355, 0x00000D70 }, /* GL_NAME_STACK_DEPTH */
+ { 21375, 0x0000150E }, /* GL_NAND */
+ { 21383, 0x00002600 }, /* GL_NEAREST */
+ { 21394, 0x0000844E }, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
+ { 21425, 0x0000844D }, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
+ { 21457, 0x00002702 }, /* GL_NEAREST_MIPMAP_LINEAR */
+ { 21482, 0x00002700 }, /* GL_NEAREST_MIPMAP_NEAREST */
+ { 21508, 0x00000200 }, /* GL_NEVER */
+ { 21517, 0x00001102 }, /* GL_NICEST */
+ { 21527, 0x00000000 }, /* GL_NONE */
+ { 21535, 0x00001505 }, /* GL_NOOP */
+ { 21543, 0x00001508 }, /* GL_NOR */
+ { 21550, 0x00000BA1 }, /* GL_NORMALIZE */
+ { 21563, 0x00008075 }, /* GL_NORMAL_ARRAY */
+ { 21579, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
+ { 21610, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING_ARB */
+ { 21645, 0x0000808F }, /* GL_NORMAL_ARRAY_POINTER */
+ { 21669, 0x0000807F }, /* GL_NORMAL_ARRAY_STRIDE */
+ { 21692, 0x0000807E }, /* GL_NORMAL_ARRAY_TYPE */
+ { 21713, 0x00008511 }, /* GL_NORMAL_MAP */
+ { 21727, 0x00008511 }, /* GL_NORMAL_MAP_ARB */
+ { 21745, 0x00008511 }, /* GL_NORMAL_MAP_NV */
+ { 21762, 0x00000205 }, /* GL_NOTEQUAL */
+ { 21774, 0x00000000 }, /* GL_NO_ERROR */
+ { 21786, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
+ { 21820, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB */
+ { 21858, 0x00008B89 }, /* GL_OBJECT_ACTIVE_ATTRIBUTES_ARB */
+ { 21890, 0x00008B8A }, /* GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB */
+ { 21932, 0x00008B86 }, /* GL_OBJECT_ACTIVE_UNIFORMS_ARB */
+ { 21962, 0x00008B87 }, /* GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB */
+ { 22002, 0x00008B85 }, /* GL_OBJECT_ATTACHED_OBJECTS_ARB */
+ { 22033, 0x00008B81 }, /* GL_OBJECT_COMPILE_STATUS_ARB */
+ { 22062, 0x00008B80 }, /* GL_OBJECT_DELETE_STATUS_ARB */
+ { 22090, 0x00008B84 }, /* GL_OBJECT_INFO_LOG_LENGTH_ARB */
+ { 22120, 0x00002401 }, /* GL_OBJECT_LINEAR */
+ { 22137, 0x00008B82 }, /* GL_OBJECT_LINK_STATUS_ARB */
+ { 22163, 0x00002501 }, /* GL_OBJECT_PLANE */
+ { 22179, 0x00008B88 }, /* GL_OBJECT_SHADER_SOURCE_LENGTH_ARB */
+ { 22214, 0x00008B4F }, /* GL_OBJECT_SUBTYPE_ARB */
+ { 22236, 0x00009112 }, /* GL_OBJECT_TYPE */
+ { 22251, 0x00008B4E }, /* GL_OBJECT_TYPE_ARB */
+ { 22270, 0x00008B83 }, /* GL_OBJECT_VALIDATE_STATUS_ARB */
+ { 22300, 0x00008165 }, /* GL_OCCLUSION_TEST_HP */
+ { 22321, 0x00008166 }, /* GL_OCCLUSION_TEST_RESULT_HP */
+ { 22349, 0x00000001 }, /* GL_ONE */
+ { 22356, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA */
+ { 22384, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA_EXT */
+ { 22416, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR */
+ { 22444, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR_EXT */
+ { 22476, 0x00000305 }, /* GL_ONE_MINUS_DST_ALPHA */
+ { 22499, 0x00000307 }, /* GL_ONE_MINUS_DST_COLOR */
+ { 22522, 0x00000303 }, /* GL_ONE_MINUS_SRC_ALPHA */
+ { 22545, 0x00000301 }, /* GL_ONE_MINUS_SRC_COLOR */
+ { 22568, 0x00008598 }, /* GL_OPERAND0_ALPHA */
+ { 22586, 0x00008598 }, /* GL_OPERAND0_ALPHA_ARB */
+ { 22608, 0x00008598 }, /* GL_OPERAND0_ALPHA_EXT */
+ { 22630, 0x00008590 }, /* GL_OPERAND0_RGB */
+ { 22646, 0x00008590 }, /* GL_OPERAND0_RGB_ARB */
+ { 22666, 0x00008590 }, /* GL_OPERAND0_RGB_EXT */
+ { 22686, 0x00008599 }, /* GL_OPERAND1_ALPHA */
+ { 22704, 0x00008599 }, /* GL_OPERAND1_ALPHA_ARB */
+ { 22726, 0x00008599 }, /* GL_OPERAND1_ALPHA_EXT */
+ { 22748, 0x00008591 }, /* GL_OPERAND1_RGB */
+ { 22764, 0x00008591 }, /* GL_OPERAND1_RGB_ARB */
+ { 22784, 0x00008591 }, /* GL_OPERAND1_RGB_EXT */
+ { 22804, 0x0000859A }, /* GL_OPERAND2_ALPHA */
+ { 22822, 0x0000859A }, /* GL_OPERAND2_ALPHA_ARB */
+ { 22844, 0x0000859A }, /* GL_OPERAND2_ALPHA_EXT */
+ { 22866, 0x00008592 }, /* GL_OPERAND2_RGB */
+ { 22882, 0x00008592 }, /* GL_OPERAND2_RGB_ARB */
+ { 22902, 0x00008592 }, /* GL_OPERAND2_RGB_EXT */
+ { 22922, 0x0000859B }, /* GL_OPERAND3_ALPHA_NV */
+ { 22943, 0x00008593 }, /* GL_OPERAND3_RGB_NV */
+ { 22962, 0x00001507 }, /* GL_OR */
+ { 22968, 0x00000A01 }, /* GL_ORDER */
+ { 22977, 0x0000150D }, /* GL_OR_INVERTED */
+ { 22992, 0x0000150B }, /* GL_OR_REVERSE */
+ { 23006, 0x00000505 }, /* GL_OUT_OF_MEMORY */
+ { 23023, 0x00000D05 }, /* GL_PACK_ALIGNMENT */
+ { 23041, 0x0000806C }, /* GL_PACK_IMAGE_HEIGHT */
+ { 23062, 0x00008758 }, /* GL_PACK_INVERT_MESA */
+ { 23082, 0x00000D01 }, /* GL_PACK_LSB_FIRST */
+ { 23100, 0x00000D02 }, /* GL_PACK_ROW_LENGTH */
+ { 23119, 0x0000806B }, /* GL_PACK_SKIP_IMAGES */
+ { 23139, 0x00000D04 }, /* GL_PACK_SKIP_PIXELS */
+ { 23159, 0x00000D03 }, /* GL_PACK_SKIP_ROWS */
+ { 23177, 0x00000D00 }, /* GL_PACK_SWAP_BYTES */
+ { 23196, 0x00008B92 }, /* GL_PALETTE4_R5_G6_B5_OES */
+ { 23221, 0x00008B94 }, /* GL_PALETTE4_RGB5_A1_OES */
+ { 23245, 0x00008B90 }, /* GL_PALETTE4_RGB8_OES */
+ { 23266, 0x00008B93 }, /* GL_PALETTE4_RGBA4_OES */
+ { 23288, 0x00008B91 }, /* GL_PALETTE4_RGBA8_OES */
+ { 23310, 0x00008B97 }, /* GL_PALETTE8_R5_G6_B5_OES */
+ { 23335, 0x00008B99 }, /* GL_PALETTE8_RGB5_A1_OES */
+ { 23359, 0x00008B95 }, /* GL_PALETTE8_RGB8_OES */
+ { 23380, 0x00008B98 }, /* GL_PALETTE8_RGBA4_OES */
+ { 23402, 0x00008B96 }, /* GL_PALETTE8_RGBA8_OES */
+ { 23424, 0x00000700 }, /* GL_PASS_THROUGH_TOKEN */
+ { 23446, 0x00000C50 }, /* GL_PERSPECTIVE_CORRECTION_HINT */
+ { 23477, 0x00000C79 }, /* GL_PIXEL_MAP_A_TO_A */
+ { 23497, 0x00000CB9 }, /* GL_PIXEL_MAP_A_TO_A_SIZE */
+ { 23522, 0x00000C78 }, /* GL_PIXEL_MAP_B_TO_B */
+ { 23542, 0x00000CB8 }, /* GL_PIXEL_MAP_B_TO_B_SIZE */
+ { 23567, 0x00000C77 }, /* GL_PIXEL_MAP_G_TO_G */
+ { 23587, 0x00000CB7 }, /* GL_PIXEL_MAP_G_TO_G_SIZE */
+ { 23612, 0x00000C75 }, /* GL_PIXEL_MAP_I_TO_A */
+ { 23632, 0x00000CB5 }, /* GL_PIXEL_MAP_I_TO_A_SIZE */
+ { 23657, 0x00000C74 }, /* GL_PIXEL_MAP_I_TO_B */
+ { 23677, 0x00000CB4 }, /* GL_PIXEL_MAP_I_TO_B_SIZE */
+ { 23702, 0x00000C73 }, /* GL_PIXEL_MAP_I_TO_G */
+ { 23722, 0x00000CB3 }, /* GL_PIXEL_MAP_I_TO_G_SIZE */
+ { 23747, 0x00000C70 }, /* GL_PIXEL_MAP_I_TO_I */
+ { 23767, 0x00000CB0 }, /* GL_PIXEL_MAP_I_TO_I_SIZE */
+ { 23792, 0x00000C72 }, /* GL_PIXEL_MAP_I_TO_R */
+ { 23812, 0x00000CB2 }, /* GL_PIXEL_MAP_I_TO_R_SIZE */
+ { 23837, 0x00000C76 }, /* GL_PIXEL_MAP_R_TO_R */
+ { 23857, 0x00000CB6 }, /* GL_PIXEL_MAP_R_TO_R_SIZE */
+ { 23882, 0x00000C71 }, /* GL_PIXEL_MAP_S_TO_S */
+ { 23902, 0x00000CB1 }, /* GL_PIXEL_MAP_S_TO_S_SIZE */
+ { 23927, 0x00000020 }, /* GL_PIXEL_MODE_BIT */
+ { 23945, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER */
+ { 23966, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING */
+ { 23995, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING_EXT */
+ { 24028, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER_EXT */
+ { 24053, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER */
+ { 24076, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING */
+ { 24107, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING_EXT */
+ { 24142, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER_EXT */
+ { 24169, 0x00001B00 }, /* GL_POINT */
+ { 24178, 0x00000000 }, /* GL_POINTS */
+ { 24188, 0x00000002 }, /* GL_POINT_BIT */
+ { 24201, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION */
+ { 24231, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_ARB */
+ { 24265, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_EXT */
+ { 24299, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_SGIS */
+ { 24334, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE */
+ { 24363, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_ARB */
+ { 24396, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_EXT */
+ { 24429, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_SGIS */
+ { 24463, 0x00000B11 }, /* GL_POINT_SIZE */
+ { 24477, 0x00000B13 }, /* GL_POINT_SIZE_GRANULARITY */
+ { 24503, 0x00008127 }, /* GL_POINT_SIZE_MAX */
+ { 24521, 0x00008127 }, /* GL_POINT_SIZE_MAX_ARB */
+ { 24543, 0x00008127 }, /* GL_POINT_SIZE_MAX_EXT */
+ { 24565, 0x00008127 }, /* GL_POINT_SIZE_MAX_SGIS */
+ { 24588, 0x00008126 }, /* GL_POINT_SIZE_MIN */
+ { 24606, 0x00008126 }, /* GL_POINT_SIZE_MIN_ARB */
+ { 24628, 0x00008126 }, /* GL_POINT_SIZE_MIN_EXT */
+ { 24650, 0x00008126 }, /* GL_POINT_SIZE_MIN_SGIS */
+ { 24673, 0x00000B12 }, /* GL_POINT_SIZE_RANGE */
+ { 24693, 0x00000B10 }, /* GL_POINT_SMOOTH */
+ { 24709, 0x00000C51 }, /* GL_POINT_SMOOTH_HINT */
+ { 24730, 0x00008861 }, /* GL_POINT_SPRITE */
+ { 24746, 0x00008861 }, /* GL_POINT_SPRITE_ARB */
+ { 24766, 0x00008CA0 }, /* GL_POINT_SPRITE_COORD_ORIGIN */
+ { 24795, 0x00008861 }, /* GL_POINT_SPRITE_NV */
+ { 24814, 0x00008863 }, /* GL_POINT_SPRITE_R_MODE_NV */
+ { 24840, 0x00000701 }, /* GL_POINT_TOKEN */
+ { 24855, 0x00000009 }, /* GL_POLYGON */
+ { 24866, 0x00000008 }, /* GL_POLYGON_BIT */
+ { 24881, 0x00000B40 }, /* GL_POLYGON_MODE */
+ { 24897, 0x00008039 }, /* GL_POLYGON_OFFSET_BIAS */
+ { 24920, 0x00008038 }, /* GL_POLYGON_OFFSET_FACTOR */
+ { 24945, 0x00008037 }, /* GL_POLYGON_OFFSET_FILL */
+ { 24968, 0x00002A02 }, /* GL_POLYGON_OFFSET_LINE */
+ { 24991, 0x00002A01 }, /* GL_POLYGON_OFFSET_POINT */
+ { 25015, 0x00002A00 }, /* GL_POLYGON_OFFSET_UNITS */
+ { 25039, 0x00000B41 }, /* GL_POLYGON_SMOOTH */
+ { 25057, 0x00000C53 }, /* GL_POLYGON_SMOOTH_HINT */
+ { 25080, 0x00000B42 }, /* GL_POLYGON_STIPPLE */
+ { 25099, 0x00000010 }, /* GL_POLYGON_STIPPLE_BIT */
+ { 25122, 0x00000703 }, /* GL_POLYGON_TOKEN */
+ { 25139, 0x00001203 }, /* GL_POSITION */
+ { 25151, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
+ { 25183, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI */
+ { 25219, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
+ { 25252, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI */
+ { 25289, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
+ { 25320, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI */
+ { 25355, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
+ { 25387, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI */
+ { 25423, 0x000080D2 }, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
+ { 25456, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
+ { 25488, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI */
+ { 25524, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
+ { 25557, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI */
+ { 25594, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS */
+ { 25624, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS_SGI */
+ { 25658, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE */
+ { 25689, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE_SGI */
+ { 25724, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
+ { 25755, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS_EXT */
+ { 25790, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
+ { 25822, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE_EXT */
+ { 25858, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS */
+ { 25888, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS_EXT */
+ { 25922, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE */
+ { 25953, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE_EXT */
+ { 25988, 0x000080D1 }, /* GL_POST_CONVOLUTION_COLOR_TABLE */
+ { 26020, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS */
+ { 26051, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS_EXT */
+ { 26086, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE */
+ { 26118, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE_EXT */
+ { 26154, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS */
+ { 26183, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS_EXT */
+ { 26216, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE */
+ { 26246, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE_EXT */
+ { 26280, 0x0000817B }, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
+ { 26319, 0x00008179 }, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
+ { 26352, 0x0000817C }, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
+ { 26392, 0x0000817A }, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
+ { 26426, 0x00008578 }, /* GL_PREVIOUS */
+ { 26438, 0x00008578 }, /* GL_PREVIOUS_ARB */
+ { 26454, 0x00008578 }, /* GL_PREVIOUS_EXT */
+ { 26470, 0x00008577 }, /* GL_PRIMARY_COLOR */
+ { 26487, 0x00008577 }, /* GL_PRIMARY_COLOR_ARB */
+ { 26508, 0x00008577 }, /* GL_PRIMARY_COLOR_EXT */
+ { 26529, 0x000088B0 }, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
+ { 26562, 0x00008805 }, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ { 26594, 0x000088AC }, /* GL_PROGRAM_ATTRIBS_ARB */
+ { 26617, 0x00008677 }, /* GL_PROGRAM_BINDING_ARB */
+ { 26640, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_ARB */
+ { 26670, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_NV */
+ { 26699, 0x00008874 }, /* GL_PROGRAM_ERROR_STRING_ARB */
+ { 26727, 0x00008876 }, /* GL_PROGRAM_FORMAT_ARB */
+ { 26749, 0x00008875 }, /* GL_PROGRAM_FORMAT_ASCII_ARB */
+ { 26777, 0x000088A0 }, /* GL_PROGRAM_INSTRUCTIONS_ARB */
+ { 26805, 0x00008627 }, /* GL_PROGRAM_LENGTH_ARB */
+ { 26827, 0x00008627 }, /* GL_PROGRAM_LENGTH_NV */
+ { 26848, 0x000088B2 }, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ { 26888, 0x00008808 }, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ { 26927, 0x000088AE }, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
+ { 26957, 0x000088A2 }, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ { 26992, 0x000088AA }, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
+ { 27025, 0x000088A6 }, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ { 27059, 0x0000880A }, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ { 27098, 0x00008809 }, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ { 27137, 0x00008B40 }, /* GL_PROGRAM_OBJECT_ARB */
+ { 27159, 0x000088A8 }, /* GL_PROGRAM_PARAMETERS_ARB */
+ { 27185, 0x00008644 }, /* GL_PROGRAM_PARAMETER_NV */
+ { 27209, 0x00008647 }, /* GL_PROGRAM_RESIDENT_NV */
+ { 27232, 0x00008628 }, /* GL_PROGRAM_STRING_ARB */
+ { 27254, 0x00008628 }, /* GL_PROGRAM_STRING_NV */
+ { 27275, 0x00008646 }, /* GL_PROGRAM_TARGET_NV */
+ { 27296, 0x000088A4 }, /* GL_PROGRAM_TEMPORARIES_ARB */
+ { 27323, 0x00008807 }, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
+ { 27355, 0x00008806 }, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ { 27387, 0x000088B6 }, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
+ { 27422, 0x00001701 }, /* GL_PROJECTION */
+ { 27436, 0x00000BA7 }, /* GL_PROJECTION_MATRIX */
+ { 27457, 0x00000BA4 }, /* GL_PROJECTION_STACK_DEPTH */
+ { 27483, 0x00008E4F }, /* GL_PROVOKING_VERTEX_EXT */
+ { 27507, 0x000080D3 }, /* GL_PROXY_COLOR_TABLE */
+ { 27528, 0x00008025 }, /* GL_PROXY_HISTOGRAM */
+ { 27547, 0x00008025 }, /* GL_PROXY_HISTOGRAM_EXT */
+ { 27570, 0x000080D5 }, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
+ { 27609, 0x000080D4 }, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
+ { 27647, 0x00008063 }, /* GL_PROXY_TEXTURE_1D */
+ { 27667, 0x00008C19 }, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
+ { 27697, 0x00008063 }, /* GL_PROXY_TEXTURE_1D_EXT */
+ { 27721, 0x00008064 }, /* GL_PROXY_TEXTURE_2D */
+ { 27741, 0x00008C1B }, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
+ { 27771, 0x00008064 }, /* GL_PROXY_TEXTURE_2D_EXT */
+ { 27795, 0x00008070 }, /* GL_PROXY_TEXTURE_3D */
+ { 27815, 0x000080BD }, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
+ { 27848, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP */
+ { 27874, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP_ARB */
+ { 27904, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
+ { 27935, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_NV */
+ { 27965, 0x00002003 }, /* GL_Q */
+ { 27970, 0x00001209 }, /* GL_QUADRATIC_ATTENUATION */
+ { 27995, 0x00000007 }, /* GL_QUADS */
+ { 28004, 0x00008E4C }, /* GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT */
+ { 28052, 0x00008614 }, /* GL_QUAD_MESH_SUN */
+ { 28069, 0x00000008 }, /* GL_QUAD_STRIP */
+ { 28083, 0x00008864 }, /* GL_QUERY_COUNTER_BITS */
+ { 28105, 0x00008864 }, /* GL_QUERY_COUNTER_BITS_ARB */
+ { 28131, 0x00008866 }, /* GL_QUERY_RESULT */
+ { 28147, 0x00008866 }, /* GL_QUERY_RESULT_ARB */
+ { 28167, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE */
+ { 28193, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE_ARB */
+ { 28223, 0x00002002 }, /* GL_R */
+ { 28228, 0x00002A10 }, /* GL_R3_G3_B2 */
+ { 28240, 0x00019262 }, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
+ { 28273, 0x00000C02 }, /* GL_READ_BUFFER */
+ { 28288, 0x00008CA8 }, /* GL_READ_FRAMEBUFFER */
+ { 28308, 0x00008CAA }, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
+ { 28340, 0x00008CA8 }, /* GL_READ_FRAMEBUFFER_EXT */
+ { 28364, 0x000088B8 }, /* GL_READ_ONLY */
+ { 28377, 0x000088B8 }, /* GL_READ_ONLY_ARB */
+ { 28394, 0x000088BA }, /* GL_READ_WRITE */
+ { 28408, 0x000088BA }, /* GL_READ_WRITE_ARB */
+ { 28426, 0x00001903 }, /* GL_RED */
+ { 28433, 0x00008016 }, /* GL_REDUCE */
+ { 28443, 0x00008016 }, /* GL_REDUCE_EXT */
+ { 28457, 0x00000D15 }, /* GL_RED_BIAS */
+ { 28469, 0x00000D52 }, /* GL_RED_BITS */
+ { 28481, 0x00000D14 }, /* GL_RED_SCALE */
+ { 28494, 0x00008512 }, /* GL_REFLECTION_MAP */
+ { 28512, 0x00008512 }, /* GL_REFLECTION_MAP_ARB */
+ { 28534, 0x00008512 }, /* GL_REFLECTION_MAP_NV */
+ { 28555, 0x00001C00 }, /* GL_RENDER */
+ { 28565, 0x00008D41 }, /* GL_RENDERBUFFER */
+ { 28581, 0x00008D53 }, /* GL_RENDERBUFFER_ALPHA_SIZE */
+ { 28608, 0x00008CA7 }, /* GL_RENDERBUFFER_BINDING_EXT */
+ { 28636, 0x00008D52 }, /* GL_RENDERBUFFER_BLUE_SIZE */
+ { 28662, 0x00008D54 }, /* GL_RENDERBUFFER_DEPTH_SIZE */
+ { 28689, 0x00008D41 }, /* GL_RENDERBUFFER_EXT */
+ { 28709, 0x00008D51 }, /* GL_RENDERBUFFER_GREEN_SIZE */
+ { 28736, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT */
+ { 28759, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT_EXT */
+ { 28786, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT */
+ { 28818, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */
+ { 28854, 0x00008D50 }, /* GL_RENDERBUFFER_RED_SIZE */
+ { 28879, 0x00008CAB }, /* GL_RENDERBUFFER_SAMPLES */
+ { 28903, 0x00008D55 }, /* GL_RENDERBUFFER_STENCIL_SIZE */
+ { 28932, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH */
+ { 28954, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH_EXT */
+ { 28980, 0x00001F01 }, /* GL_RENDERER */
+ { 28992, 0x00000C40 }, /* GL_RENDER_MODE */
+ { 29007, 0x00002901 }, /* GL_REPEAT */
+ { 29017, 0x00001E01 }, /* GL_REPLACE */
+ { 29028, 0x00008062 }, /* GL_REPLACE_EXT */
+ { 29043, 0x00008153 }, /* GL_REPLICATE_BORDER_HP */
+ { 29066, 0x0000803A }, /* GL_RESCALE_NORMAL */
+ { 29084, 0x0000803A }, /* GL_RESCALE_NORMAL_EXT */
+ { 29106, 0x00000102 }, /* GL_RETURN */
+ { 29116, 0x00001907 }, /* GL_RGB */
+ { 29123, 0x00008052 }, /* GL_RGB10 */
+ { 29132, 0x00008059 }, /* GL_RGB10_A2 */
+ { 29144, 0x00008059 }, /* GL_RGB10_A2_EXT */
+ { 29160, 0x00008052 }, /* GL_RGB10_EXT */
+ { 29173, 0x00008053 }, /* GL_RGB12 */
+ { 29182, 0x00008053 }, /* GL_RGB12_EXT */
+ { 29195, 0x00008054 }, /* GL_RGB16 */
+ { 29204, 0x00008054 }, /* GL_RGB16_EXT */
+ { 29217, 0x0000804E }, /* GL_RGB2_EXT */
+ { 29229, 0x0000804F }, /* GL_RGB4 */
+ { 29237, 0x0000804F }, /* GL_RGB4_EXT */
+ { 29249, 0x000083A1 }, /* GL_RGB4_S3TC */
+ { 29262, 0x00008050 }, /* GL_RGB5 */
+ { 29270, 0x00008057 }, /* GL_RGB5_A1 */
+ { 29281, 0x00008057 }, /* GL_RGB5_A1_EXT */
+ { 29296, 0x00008050 }, /* GL_RGB5_EXT */
+ { 29308, 0x00008051 }, /* GL_RGB8 */
+ { 29316, 0x00008051 }, /* GL_RGB8_EXT */
+ { 29328, 0x00001908 }, /* GL_RGBA */
+ { 29336, 0x0000805A }, /* GL_RGBA12 */
+ { 29346, 0x0000805A }, /* GL_RGBA12_EXT */
+ { 29360, 0x0000805B }, /* GL_RGBA16 */
+ { 29370, 0x0000805B }, /* GL_RGBA16_EXT */
+ { 29384, 0x00008055 }, /* GL_RGBA2 */
+ { 29393, 0x00008055 }, /* GL_RGBA2_EXT */
+ { 29406, 0x00008056 }, /* GL_RGBA4 */
+ { 29415, 0x000083A5 }, /* GL_RGBA4_DXT5_S3TC */
+ { 29434, 0x00008056 }, /* GL_RGBA4_EXT */
+ { 29447, 0x000083A3 }, /* GL_RGBA4_S3TC */
+ { 29461, 0x00008058 }, /* GL_RGBA8 */
+ { 29470, 0x00008058 }, /* GL_RGBA8_EXT */
+ { 29483, 0x00008F97 }, /* GL_RGBA8_SNORM */
+ { 29498, 0x000083A4 }, /* GL_RGBA_DXT5_S3TC */
+ { 29516, 0x00000C31 }, /* GL_RGBA_MODE */
+ { 29529, 0x000083A2 }, /* GL_RGBA_S3TC */
+ { 29542, 0x00008F93 }, /* GL_RGBA_SNORM */
+ { 29556, 0x000083A0 }, /* GL_RGB_S3TC */
+ { 29568, 0x00008573 }, /* GL_RGB_SCALE */
+ { 29581, 0x00008573 }, /* GL_RGB_SCALE_ARB */
+ { 29598, 0x00008573 }, /* GL_RGB_SCALE_EXT */
+ { 29615, 0x00000407 }, /* GL_RIGHT */
+ { 29624, 0x00002000 }, /* GL_S */
+ { 29629, 0x00008B5D }, /* GL_SAMPLER_1D */
+ { 29643, 0x00008B61 }, /* GL_SAMPLER_1D_SHADOW */
+ { 29664, 0x00008B5E }, /* GL_SAMPLER_2D */
+ { 29678, 0x00008B62 }, /* GL_SAMPLER_2D_SHADOW */
+ { 29699, 0x00008B5F }, /* GL_SAMPLER_3D */
+ { 29713, 0x00008B60 }, /* GL_SAMPLER_CUBE */
+ { 29729, 0x000080A9 }, /* GL_SAMPLES */
+ { 29740, 0x000086B4 }, /* GL_SAMPLES_3DFX */
+ { 29756, 0x000080A9 }, /* GL_SAMPLES_ARB */
+ { 29771, 0x00008914 }, /* GL_SAMPLES_PASSED */
+ { 29789, 0x00008914 }, /* GL_SAMPLES_PASSED_ARB */
+ { 29811, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
+ { 29839, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE_ARB */
+ { 29871, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE */
+ { 29894, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE_ARB */
+ { 29921, 0x000080A8 }, /* GL_SAMPLE_BUFFERS */
+ { 29939, 0x000086B3 }, /* GL_SAMPLE_BUFFERS_3DFX */
+ { 29962, 0x000080A8 }, /* GL_SAMPLE_BUFFERS_ARB */
+ { 29984, 0x000080A0 }, /* GL_SAMPLE_COVERAGE */
+ { 30003, 0x000080A0 }, /* GL_SAMPLE_COVERAGE_ARB */
+ { 30026, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT */
+ { 30052, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT_ARB */
+ { 30082, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE */
+ { 30107, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE_ARB */
+ { 30136, 0x00080000 }, /* GL_SCISSOR_BIT */
+ { 30151, 0x00000C10 }, /* GL_SCISSOR_BOX */
+ { 30166, 0x00000C11 }, /* GL_SCISSOR_TEST */
+ { 30182, 0x0000845E }, /* GL_SECONDARY_COLOR_ARRAY */
+ { 30207, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
+ { 30247, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB */
+ { 30291, 0x0000845D }, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
+ { 30324, 0x0000845A }, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
+ { 30354, 0x0000845C }, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
+ { 30386, 0x0000845B }, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
+ { 30416, 0x00001C02 }, /* GL_SELECT */
+ { 30426, 0x00000DF3 }, /* GL_SELECTION_BUFFER_POINTER */
+ { 30454, 0x00000DF4 }, /* GL_SELECTION_BUFFER_SIZE */
+ { 30479, 0x00008012 }, /* GL_SEPARABLE_2D */
+ { 30495, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR */
+ { 30522, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR_EXT */
+ { 30553, 0x0000150F }, /* GL_SET */
+ { 30560, 0x00008B48 }, /* GL_SHADER_OBJECT_ARB */
+ { 30581, 0x00008B88 }, /* GL_SHADER_SOURCE_LENGTH */
+ { 30605, 0x00008B4F }, /* GL_SHADER_TYPE */
+ { 30620, 0x00000B54 }, /* GL_SHADE_MODEL */
+ { 30635, 0x00008B8C }, /* GL_SHADING_LANGUAGE_VERSION */
+ { 30663, 0x000080BF }, /* GL_SHADOW_AMBIENT_SGIX */
+ { 30686, 0x000081FB }, /* GL_SHARED_TEXTURE_PALETTE_EXT */
+ { 30716, 0x00001601 }, /* GL_SHININESS */
+ { 30729, 0x00001402 }, /* GL_SHORT */
+ { 30738, 0x00009119 }, /* GL_SIGNALED */
+ { 30750, 0x00008F9C }, /* GL_SIGNED_NORMALIZED */
+ { 30771, 0x000081F9 }, /* GL_SINGLE_COLOR */
+ { 30787, 0x000081F9 }, /* GL_SINGLE_COLOR_EXT */
+ { 30807, 0x000085CC }, /* GL_SLICE_ACCUM_SUN */
+ { 30826, 0x00008C46 }, /* GL_SLUMINANCE */
+ { 30840, 0x00008C47 }, /* GL_SLUMINANCE8 */
+ { 30855, 0x00008C45 }, /* GL_SLUMINANCE8_ALPHA8 */
+ { 30877, 0x00008C44 }, /* GL_SLUMINANCE_ALPHA */
+ { 30897, 0x00001D01 }, /* GL_SMOOTH */
+ { 30907, 0x00000B23 }, /* GL_SMOOTH_LINE_WIDTH_GRANULARITY */
+ { 30940, 0x00000B22 }, /* GL_SMOOTH_LINE_WIDTH_RANGE */
+ { 30967, 0x00000B13 }, /* GL_SMOOTH_POINT_SIZE_GRANULARITY */
+ { 31000, 0x00000B12 }, /* GL_SMOOTH_POINT_SIZE_RANGE */
+ { 31027, 0x00008588 }, /* GL_SOURCE0_ALPHA */
+ { 31044, 0x00008588 }, /* GL_SOURCE0_ALPHA_ARB */
+ { 31065, 0x00008588 }, /* GL_SOURCE0_ALPHA_EXT */
+ { 31086, 0x00008580 }, /* GL_SOURCE0_RGB */
+ { 31101, 0x00008580 }, /* GL_SOURCE0_RGB_ARB */
+ { 31120, 0x00008580 }, /* GL_SOURCE0_RGB_EXT */
+ { 31139, 0x00008589 }, /* GL_SOURCE1_ALPHA */
+ { 31156, 0x00008589 }, /* GL_SOURCE1_ALPHA_ARB */
+ { 31177, 0x00008589 }, /* GL_SOURCE1_ALPHA_EXT */
+ { 31198, 0x00008581 }, /* GL_SOURCE1_RGB */
+ { 31213, 0x00008581 }, /* GL_SOURCE1_RGB_ARB */
+ { 31232, 0x00008581 }, /* GL_SOURCE1_RGB_EXT */
+ { 31251, 0x0000858A }, /* GL_SOURCE2_ALPHA */
+ { 31268, 0x0000858A }, /* GL_SOURCE2_ALPHA_ARB */
+ { 31289, 0x0000858A }, /* GL_SOURCE2_ALPHA_EXT */
+ { 31310, 0x00008582 }, /* GL_SOURCE2_RGB */
+ { 31325, 0x00008582 }, /* GL_SOURCE2_RGB_ARB */
+ { 31344, 0x00008582 }, /* GL_SOURCE2_RGB_EXT */
+ { 31363, 0x0000858B }, /* GL_SOURCE3_ALPHA_NV */
+ { 31383, 0x00008583 }, /* GL_SOURCE3_RGB_NV */
+ { 31401, 0x00001202 }, /* GL_SPECULAR */
+ { 31413, 0x00002402 }, /* GL_SPHERE_MAP */
+ { 31427, 0x00001206 }, /* GL_SPOT_CUTOFF */
+ { 31442, 0x00001204 }, /* GL_SPOT_DIRECTION */
+ { 31460, 0x00001205 }, /* GL_SPOT_EXPONENT */
+ { 31477, 0x00008588 }, /* GL_SRC0_ALPHA */
+ { 31491, 0x00008580 }, /* GL_SRC0_RGB */
+ { 31503, 0x00008589 }, /* GL_SRC1_ALPHA */
+ { 31517, 0x00008581 }, /* GL_SRC1_RGB */
+ { 31529, 0x0000858A }, /* GL_SRC2_ALPHA */
+ { 31543, 0x00008582 }, /* GL_SRC2_RGB */
+ { 31555, 0x00000302 }, /* GL_SRC_ALPHA */
+ { 31568, 0x00000308 }, /* GL_SRC_ALPHA_SATURATE */
+ { 31590, 0x00000300 }, /* GL_SRC_COLOR */
+ { 31603, 0x00008C40 }, /* GL_SRGB */
+ { 31611, 0x00008C41 }, /* GL_SRGB8 */
+ { 31620, 0x00008C43 }, /* GL_SRGB8_ALPHA8 */
+ { 31636, 0x00008C42 }, /* GL_SRGB_ALPHA */
+ { 31650, 0x00000503 }, /* GL_STACK_OVERFLOW */
+ { 31668, 0x00000504 }, /* GL_STACK_UNDERFLOW */
+ { 31687, 0x000088E6 }, /* GL_STATIC_COPY */
+ { 31702, 0x000088E6 }, /* GL_STATIC_COPY_ARB */
+ { 31721, 0x000088E4 }, /* GL_STATIC_DRAW */
+ { 31736, 0x000088E4 }, /* GL_STATIC_DRAW_ARB */
+ { 31755, 0x000088E5 }, /* GL_STATIC_READ */
+ { 31770, 0x000088E5 }, /* GL_STATIC_READ_ARB */
+ { 31789, 0x00001802 }, /* GL_STENCIL */
+ { 31800, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT */
+ { 31822, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT_EXT */
+ { 31848, 0x00008801 }, /* GL_STENCIL_BACK_FAIL */
+ { 31869, 0x00008801 }, /* GL_STENCIL_BACK_FAIL_ATI */
+ { 31894, 0x00008800 }, /* GL_STENCIL_BACK_FUNC */
+ { 31915, 0x00008800 }, /* GL_STENCIL_BACK_FUNC_ATI */
+ { 31940, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
+ { 31972, 0x00008802 }, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI */
+ { 32008, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
+ { 32040, 0x00008803 }, /* GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI */
+ { 32076, 0x00008CA3 }, /* GL_STENCIL_BACK_REF */
+ { 32096, 0x00008CA4 }, /* GL_STENCIL_BACK_VALUE_MASK */
+ { 32123, 0x00008CA5 }, /* GL_STENCIL_BACK_WRITEMASK */
+ { 32149, 0x00000D57 }, /* GL_STENCIL_BITS */
+ { 32165, 0x00000400 }, /* GL_STENCIL_BUFFER_BIT */
+ { 32187, 0x00000B91 }, /* GL_STENCIL_CLEAR_VALUE */
+ { 32210, 0x00000B94 }, /* GL_STENCIL_FAIL */
+ { 32226, 0x00000B92 }, /* GL_STENCIL_FUNC */
+ { 32242, 0x00001901 }, /* GL_STENCIL_INDEX */
+ { 32259, 0x00008D49 }, /* GL_STENCIL_INDEX16_EXT */
+ { 32282, 0x00008D46 }, /* GL_STENCIL_INDEX1_EXT */
+ { 32304, 0x00008D47 }, /* GL_STENCIL_INDEX4_EXT */
+ { 32326, 0x00008D48 }, /* GL_STENCIL_INDEX8_EXT */
+ { 32348, 0x00008D45 }, /* GL_STENCIL_INDEX_EXT */
+ { 32369, 0x00000B95 }, /* GL_STENCIL_PASS_DEPTH_FAIL */
+ { 32396, 0x00000B96 }, /* GL_STENCIL_PASS_DEPTH_PASS */
+ { 32423, 0x00000B97 }, /* GL_STENCIL_REF */
+ { 32438, 0x00000B90 }, /* GL_STENCIL_TEST */
+ { 32454, 0x00008910 }, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
+ { 32483, 0x00000B93 }, /* GL_STENCIL_VALUE_MASK */
+ { 32505, 0x00000B98 }, /* GL_STENCIL_WRITEMASK */
+ { 32526, 0x00000C33 }, /* GL_STEREO */
+ { 32536, 0x000085BE }, /* GL_STORAGE_CACHED_APPLE */
+ { 32560, 0x000085BD }, /* GL_STORAGE_PRIVATE_APPLE */
+ { 32585, 0x000085BF }, /* GL_STORAGE_SHARED_APPLE */
+ { 32609, 0x000088E2 }, /* GL_STREAM_COPY */
+ { 32624, 0x000088E2 }, /* GL_STREAM_COPY_ARB */
+ { 32643, 0x000088E0 }, /* GL_STREAM_DRAW */
+ { 32658, 0x000088E0 }, /* GL_STREAM_DRAW_ARB */
+ { 32677, 0x000088E1 }, /* GL_STREAM_READ */
+ { 32692, 0x000088E1 }, /* GL_STREAM_READ_ARB */
+ { 32711, 0x00000D50 }, /* GL_SUBPIXEL_BITS */
+ { 32728, 0x000084E7 }, /* GL_SUBTRACT */
+ { 32740, 0x000084E7 }, /* GL_SUBTRACT_ARB */
+ { 32756, 0x00009113 }, /* GL_SYNC_CONDITION */
+ { 32774, 0x00009116 }, /* GL_SYNC_FENCE */
+ { 32788, 0x00009115 }, /* GL_SYNC_FLAGS */
+ { 32802, 0x00000001 }, /* GL_SYNC_FLUSH_COMMANDS_BIT */
+ { 32829, 0x00009117 }, /* GL_SYNC_GPU_COMMANDS_COMPLETE */
+ { 32859, 0x00009114 }, /* GL_SYNC_STATUS */
+ { 32874, 0x00002001 }, /* GL_T */
+ { 32879, 0x00002A2A }, /* GL_T2F_C3F_V3F */
+ { 32894, 0x00002A2C }, /* GL_T2F_C4F_N3F_V3F */
+ { 32913, 0x00002A29 }, /* GL_T2F_C4UB_V3F */
+ { 32929, 0x00002A2B }, /* GL_T2F_N3F_V3F */
+ { 32944, 0x00002A27 }, /* GL_T2F_V3F */
+ { 32955, 0x00002A2D }, /* GL_T4F_C4F_N3F_V4F */
+ { 32974, 0x00002A28 }, /* GL_T4F_V4F */
+ { 32985, 0x00008031 }, /* GL_TABLE_TOO_LARGE_EXT */
+ { 33008, 0x00001702 }, /* GL_TEXTURE */
+ { 33019, 0x000084C0 }, /* GL_TEXTURE0 */
+ { 33031, 0x000084C0 }, /* GL_TEXTURE0_ARB */
+ { 33047, 0x000084C1 }, /* GL_TEXTURE1 */
+ { 33059, 0x000084CA }, /* GL_TEXTURE10 */
+ { 33072, 0x000084CA }, /* GL_TEXTURE10_ARB */
+ { 33089, 0x000084CB }, /* GL_TEXTURE11 */
+ { 33102, 0x000084CB }, /* GL_TEXTURE11_ARB */
+ { 33119, 0x000084CC }, /* GL_TEXTURE12 */
+ { 33132, 0x000084CC }, /* GL_TEXTURE12_ARB */
+ { 33149, 0x000084CD }, /* GL_TEXTURE13 */
+ { 33162, 0x000084CD }, /* GL_TEXTURE13_ARB */
+ { 33179, 0x000084CE }, /* GL_TEXTURE14 */
+ { 33192, 0x000084CE }, /* GL_TEXTURE14_ARB */
+ { 33209, 0x000084CF }, /* GL_TEXTURE15 */
+ { 33222, 0x000084CF }, /* GL_TEXTURE15_ARB */
+ { 33239, 0x000084D0 }, /* GL_TEXTURE16 */
+ { 33252, 0x000084D0 }, /* GL_TEXTURE16_ARB */
+ { 33269, 0x000084D1 }, /* GL_TEXTURE17 */
+ { 33282, 0x000084D1 }, /* GL_TEXTURE17_ARB */
+ { 33299, 0x000084D2 }, /* GL_TEXTURE18 */
+ { 33312, 0x000084D2 }, /* GL_TEXTURE18_ARB */
+ { 33329, 0x000084D3 }, /* GL_TEXTURE19 */
+ { 33342, 0x000084D3 }, /* GL_TEXTURE19_ARB */
+ { 33359, 0x000084C1 }, /* GL_TEXTURE1_ARB */
+ { 33375, 0x000084C2 }, /* GL_TEXTURE2 */
+ { 33387, 0x000084D4 }, /* GL_TEXTURE20 */
+ { 33400, 0x000084D4 }, /* GL_TEXTURE20_ARB */
+ { 33417, 0x000084D5 }, /* GL_TEXTURE21 */
+ { 33430, 0x000084D5 }, /* GL_TEXTURE21_ARB */
+ { 33447, 0x000084D6 }, /* GL_TEXTURE22 */
+ { 33460, 0x000084D6 }, /* GL_TEXTURE22_ARB */
+ { 33477, 0x000084D7 }, /* GL_TEXTURE23 */
+ { 33490, 0x000084D7 }, /* GL_TEXTURE23_ARB */
+ { 33507, 0x000084D8 }, /* GL_TEXTURE24 */
+ { 33520, 0x000084D8 }, /* GL_TEXTURE24_ARB */
+ { 33537, 0x000084D9 }, /* GL_TEXTURE25 */
+ { 33550, 0x000084D9 }, /* GL_TEXTURE25_ARB */
+ { 33567, 0x000084DA }, /* GL_TEXTURE26 */
+ { 33580, 0x000084DA }, /* GL_TEXTURE26_ARB */
+ { 33597, 0x000084DB }, /* GL_TEXTURE27 */
+ { 33610, 0x000084DB }, /* GL_TEXTURE27_ARB */
+ { 33627, 0x000084DC }, /* GL_TEXTURE28 */
+ { 33640, 0x000084DC }, /* GL_TEXTURE28_ARB */
+ { 33657, 0x000084DD }, /* GL_TEXTURE29 */
+ { 33670, 0x000084DD }, /* GL_TEXTURE29_ARB */
+ { 33687, 0x000084C2 }, /* GL_TEXTURE2_ARB */
+ { 33703, 0x000084C3 }, /* GL_TEXTURE3 */
+ { 33715, 0x000084DE }, /* GL_TEXTURE30 */
+ { 33728, 0x000084DE }, /* GL_TEXTURE30_ARB */
+ { 33745, 0x000084DF }, /* GL_TEXTURE31 */
+ { 33758, 0x000084DF }, /* GL_TEXTURE31_ARB */
+ { 33775, 0x000084C3 }, /* GL_TEXTURE3_ARB */
+ { 33791, 0x000084C4 }, /* GL_TEXTURE4 */
+ { 33803, 0x000084C4 }, /* GL_TEXTURE4_ARB */
+ { 33819, 0x000084C5 }, /* GL_TEXTURE5 */
+ { 33831, 0x000084C5 }, /* GL_TEXTURE5_ARB */
+ { 33847, 0x000084C6 }, /* GL_TEXTURE6 */
+ { 33859, 0x000084C6 }, /* GL_TEXTURE6_ARB */
+ { 33875, 0x000084C7 }, /* GL_TEXTURE7 */
+ { 33887, 0x000084C7 }, /* GL_TEXTURE7_ARB */
+ { 33903, 0x000084C8 }, /* GL_TEXTURE8 */
+ { 33915, 0x000084C8 }, /* GL_TEXTURE8_ARB */
+ { 33931, 0x000084C9 }, /* GL_TEXTURE9 */
+ { 33943, 0x000084C9 }, /* GL_TEXTURE9_ARB */
+ { 33959, 0x00000DE0 }, /* GL_TEXTURE_1D */
+ { 33973, 0x00008C18 }, /* GL_TEXTURE_1D_ARRAY_EXT */
+ { 33997, 0x00000DE1 }, /* GL_TEXTURE_2D */
+ { 34011, 0x00008C1A }, /* GL_TEXTURE_2D_ARRAY_EXT */
+ { 34035, 0x0000806F }, /* GL_TEXTURE_3D */
+ { 34049, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE */
+ { 34071, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE_EXT */
+ { 34097, 0x0000813C }, /* GL_TEXTURE_BASE_LEVEL */
+ { 34119, 0x00008068 }, /* GL_TEXTURE_BINDING_1D */
+ { 34141, 0x00008C1C }, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
+ { 34173, 0x00008069 }, /* GL_TEXTURE_BINDING_2D */
+ { 34195, 0x00008C1D }, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
+ { 34227, 0x0000806A }, /* GL_TEXTURE_BINDING_3D */
+ { 34249, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP */
+ { 34277, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP_ARB */
+ { 34309, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
+ { 34342, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_NV */
+ { 34374, 0x00040000 }, /* GL_TEXTURE_BIT */
+ { 34389, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE */
+ { 34410, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE_EXT */
+ { 34435, 0x00001005 }, /* GL_TEXTURE_BORDER */
+ { 34453, 0x00001004 }, /* GL_TEXTURE_BORDER_COLOR */
+ { 34477, 0x00008171 }, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
+ { 34508, 0x00008176 }, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
+ { 34538, 0x00008172 }, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
+ { 34568, 0x00008175 }, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
+ { 34603, 0x00008173 }, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
+ { 34634, 0x00008174 }, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ { 34672, 0x000080BC }, /* GL_TEXTURE_COLOR_TABLE_SGI */
+ { 34699, 0x000081EF }, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
+ { 34731, 0x000080BF }, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
+ { 34765, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC */
+ { 34789, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC_ARB */
+ { 34817, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE */
+ { 34841, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE_ARB */
+ { 34869, 0x0000819B }, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
+ { 34902, 0x0000819A }, /* GL_TEXTURE_COMPARE_SGIX */
+ { 34926, 0x00001003 }, /* GL_TEXTURE_COMPONENTS */
+ { 34948, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED */
+ { 34970, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED_ARB */
+ { 34996, 0x000086A3 }, /* GL_TEXTURE_COMPRESSED_FORMATS_ARB */
+ { 35030, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
+ { 35063, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB */
+ { 35100, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT */
+ { 35128, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT_ARB */
+ { 35160, 0x00008078 }, /* GL_TEXTURE_COORD_ARRAY */
+ { 35183, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
+ { 35221, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB */
+ { 35263, 0x00008092 }, /* GL_TEXTURE_COORD_ARRAY_POINTER */
+ { 35294, 0x00008088 }, /* GL_TEXTURE_COORD_ARRAY_SIZE */
+ { 35322, 0x0000808A }, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
+ { 35352, 0x00008089 }, /* GL_TEXTURE_COORD_ARRAY_TYPE */
+ { 35380, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP */
+ { 35400, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP_ARB */
+ { 35424, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
+ { 35455, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB */
+ { 35490, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
+ { 35521, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB */
+ { 35556, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
+ { 35587, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB */
+ { 35622, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
+ { 35653, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB */
+ { 35688, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
+ { 35719, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB */
+ { 35754, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
+ { 35785, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB */
+ { 35820, 0x000088F4 }, /* GL_TEXTURE_CUBE_MAP_SEAMLESS */
+ { 35849, 0x00008071 }, /* GL_TEXTURE_DEPTH */
+ { 35866, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE */
+ { 35888, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE_ARB */
+ { 35914, 0x00002300 }, /* GL_TEXTURE_ENV */
+ { 35929, 0x00002201 }, /* GL_TEXTURE_ENV_COLOR */
+ { 35950, 0x00002200 }, /* GL_TEXTURE_ENV_MODE */
+ { 35970, 0x00008500 }, /* GL_TEXTURE_FILTER_CONTROL */
+ { 35996, 0x00002500 }, /* GL_TEXTURE_GEN_MODE */
+ { 36016, 0x00000C63 }, /* GL_TEXTURE_GEN_Q */
+ { 36033, 0x00000C62 }, /* GL_TEXTURE_GEN_R */
+ { 36050, 0x00000C60 }, /* GL_TEXTURE_GEN_S */
+ { 36067, 0x00000C61 }, /* GL_TEXTURE_GEN_T */
+ { 36084, 0x0000819D }, /* GL_TEXTURE_GEQUAL_R_SGIX */
+ { 36109, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE */
+ { 36131, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE_EXT */
+ { 36157, 0x00001001 }, /* GL_TEXTURE_HEIGHT */
+ { 36175, 0x000080ED }, /* GL_TEXTURE_INDEX_SIZE_EXT */
+ { 36201, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE */
+ { 36227, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE_EXT */
+ { 36257, 0x00001003 }, /* GL_TEXTURE_INTERNAL_FORMAT */
+ { 36284, 0x0000819C }, /* GL_TEXTURE_LEQUAL_R_SGIX */
+ { 36309, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS */
+ { 36329, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS_EXT */
+ { 36353, 0x00008190 }, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
+ { 36380, 0x0000818E }, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
+ { 36407, 0x0000818F }, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
+ { 36434, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE */
+ { 36460, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE_EXT */
+ { 36490, 0x00002800 }, /* GL_TEXTURE_MAG_FILTER */
+ { 36512, 0x00000BA8 }, /* GL_TEXTURE_MATRIX */
+ { 36530, 0x000084FE }, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
+ { 36560, 0x0000836B }, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
+ { 36588, 0x00008369 }, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
+ { 36616, 0x0000836A }, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
+ { 36644, 0x0000813D }, /* GL_TEXTURE_MAX_LEVEL */
+ { 36665, 0x0000813B }, /* GL_TEXTURE_MAX_LOD */
+ { 36684, 0x00002801 }, /* GL_TEXTURE_MIN_FILTER */
+ { 36706, 0x0000813A }, /* GL_TEXTURE_MIN_LOD */
+ { 36725, 0x00008066 }, /* GL_TEXTURE_PRIORITY */
+ { 36745, 0x000085B7 }, /* GL_TEXTURE_RANGE_LENGTH_APPLE */
+ { 36775, 0x000085B8 }, /* GL_TEXTURE_RANGE_POINTER_APPLE */
+ { 36806, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_ARB */
+ { 36831, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_NV */
+ { 36855, 0x0000805C }, /* GL_TEXTURE_RED_SIZE */
+ { 36875, 0x0000805C }, /* GL_TEXTURE_RED_SIZE_EXT */
+ { 36899, 0x00008067 }, /* GL_TEXTURE_RESIDENT */
+ { 36919, 0x00000BA5 }, /* GL_TEXTURE_STACK_DEPTH */
+ { 36942, 0x000088F1 }, /* GL_TEXTURE_STENCIL_SIZE */
+ { 36966, 0x000085BC }, /* GL_TEXTURE_STORAGE_HINT_APPLE */
+ { 36996, 0x00008065 }, /* GL_TEXTURE_TOO_LARGE_EXT */
+ { 37021, 0x0000888F }, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
+ { 37055, 0x00001000 }, /* GL_TEXTURE_WIDTH */
+ { 37072, 0x00008072 }, /* GL_TEXTURE_WRAP_R */
+ { 37090, 0x00002802 }, /* GL_TEXTURE_WRAP_S */
+ { 37108, 0x00002803 }, /* GL_TEXTURE_WRAP_T */
+ { 37126, 0x0000911B }, /* GL_TIMEOUT_EXPIRED */
+ { 37145, 0xFFFFFFFFFFFFFFFF }, /* GL_TIMEOUT_IGNORED */
+ { 37164, 0x000088BF }, /* GL_TIME_ELAPSED_EXT */
+ { 37184, 0x00008648 }, /* GL_TRACK_MATRIX_NV */
+ { 37203, 0x00008649 }, /* GL_TRACK_MATRIX_TRANSFORM_NV */
+ { 37232, 0x00001000 }, /* GL_TRANSFORM_BIT */
+ { 37249, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX */
+ { 37275, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX_ARB */
+ { 37305, 0x000088B7 }, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
+ { 37337, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
+ { 37367, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX_ARB */
+ { 37401, 0x0000862C }, /* GL_TRANSPOSE_NV */
+ { 37417, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX */
+ { 37448, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX_ARB */
+ { 37483, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX */
+ { 37511, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX_ARB */
+ { 37543, 0x00000004 }, /* GL_TRIANGLES */
+ { 37556, 0x00000006 }, /* GL_TRIANGLE_FAN */
+ { 37572, 0x00008615 }, /* GL_TRIANGLE_MESH_SUN */
+ { 37593, 0x00000005 }, /* GL_TRIANGLE_STRIP */
+ { 37611, 0x00000001 }, /* GL_TRUE */
+ { 37619, 0x00000CF5 }, /* GL_UNPACK_ALIGNMENT */
+ { 37639, 0x0000806E }, /* GL_UNPACK_IMAGE_HEIGHT */
+ { 37662, 0x00000CF1 }, /* GL_UNPACK_LSB_FIRST */
+ { 37682, 0x00000CF2 }, /* GL_UNPACK_ROW_LENGTH */
+ { 37703, 0x0000806D }, /* GL_UNPACK_SKIP_IMAGES */
+ { 37725, 0x00000CF4 }, /* GL_UNPACK_SKIP_PIXELS */
+ { 37747, 0x00000CF3 }, /* GL_UNPACK_SKIP_ROWS */
+ { 37767, 0x00000CF0 }, /* GL_UNPACK_SWAP_BYTES */
+ { 37788, 0x00009118 }, /* GL_UNSIGNALED */
+ { 37802, 0x00001401 }, /* GL_UNSIGNED_BYTE */
+ { 37819, 0x00008362 }, /* GL_UNSIGNED_BYTE_2_3_3_REV */
+ { 37846, 0x00008032 }, /* GL_UNSIGNED_BYTE_3_3_2 */
+ { 37869, 0x00001405 }, /* GL_UNSIGNED_INT */
+ { 37885, 0x00008036 }, /* GL_UNSIGNED_INT_10_10_10_2 */
+ { 37912, 0x000084FA }, /* GL_UNSIGNED_INT_24_8 */
+ { 37933, 0x000084FA }, /* GL_UNSIGNED_INT_24_8_NV */
+ { 37957, 0x00008368 }, /* GL_UNSIGNED_INT_2_10_10_10_REV */
+ { 37988, 0x00008035 }, /* GL_UNSIGNED_INT_8_8_8_8 */
+ { 38012, 0x00008367 }, /* GL_UNSIGNED_INT_8_8_8_8_REV */
+ { 38040, 0x00008C17 }, /* GL_UNSIGNED_NORMALIZED */
+ { 38063, 0x00001403 }, /* GL_UNSIGNED_SHORT */
+ { 38081, 0x00008366 }, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
+ { 38111, 0x00008033 }, /* GL_UNSIGNED_SHORT_4_4_4_4 */
+ { 38137, 0x00008365 }, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
+ { 38167, 0x00008034 }, /* GL_UNSIGNED_SHORT_5_5_5_1 */
+ { 38193, 0x00008363 }, /* GL_UNSIGNED_SHORT_5_6_5 */
+ { 38217, 0x00008364 }, /* GL_UNSIGNED_SHORT_5_6_5_REV */
+ { 38245, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_APPLE */
+ { 38273, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_MESA */
+ { 38300, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
+ { 38332, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_MESA */
+ { 38363, 0x00008CA2 }, /* GL_UPPER_LEFT */
+ { 38377, 0x00002A20 }, /* GL_V2F */
+ { 38384, 0x00002A21 }, /* GL_V3F */
+ { 38391, 0x00008B83 }, /* GL_VALIDATE_STATUS */
+ { 38410, 0x00001F00 }, /* GL_VENDOR */
+ { 38420, 0x00001F02 }, /* GL_VERSION */
+ { 38431, 0x00008074 }, /* GL_VERTEX_ARRAY */
+ { 38447, 0x000085B5 }, /* GL_VERTEX_ARRAY_BINDING */
+ { 38471, 0x000085B5 }, /* GL_VERTEX_ARRAY_BINDING_APPLE */
+ { 38501, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
+ { 38532, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING_ARB */
+ { 38567, 0x0000808E }, /* GL_VERTEX_ARRAY_POINTER */
+ { 38591, 0x0000807A }, /* GL_VERTEX_ARRAY_SIZE */
+ { 38612, 0x0000807C }, /* GL_VERTEX_ARRAY_STRIDE */
+ { 38635, 0x0000807B }, /* GL_VERTEX_ARRAY_TYPE */
+ { 38656, 0x00008650 }, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
+ { 38683, 0x0000865A }, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
+ { 38711, 0x0000865B }, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
+ { 38739, 0x0000865C }, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
+ { 38767, 0x0000865D }, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
+ { 38795, 0x0000865E }, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
+ { 38823, 0x0000865F }, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
+ { 38851, 0x00008651 }, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
+ { 38878, 0x00008652 }, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
+ { 38905, 0x00008653 }, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
+ { 38932, 0x00008654 }, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
+ { 38959, 0x00008655 }, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
+ { 38986, 0x00008656 }, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
+ { 39013, 0x00008657 }, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
+ { 39040, 0x00008658 }, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
+ { 39067, 0x00008659 }, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
+ { 39094, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
+ { 39132, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB */
+ { 39174, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
+ { 39205, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB */
+ { 39240, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
+ { 39274, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB */
+ { 39312, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
+ { 39343, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB */
+ { 39378, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
+ { 39406, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB */
+ { 39438, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
+ { 39468, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB */
+ { 39502, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
+ { 39530, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB */
+ { 39562, 0x000086A7 }, /* GL_VERTEX_BLEND_ARB */
+ { 39582, 0x00008620 }, /* GL_VERTEX_PROGRAM_ARB */
+ { 39604, 0x0000864A }, /* GL_VERTEX_PROGRAM_BINDING_NV */
+ { 39633, 0x00008620 }, /* GL_VERTEX_PROGRAM_NV */
+ { 39654, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE */
+ { 39683, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_ARB */
+ { 39716, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_NV */
+ { 39748, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE */
+ { 39775, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_ARB */
+ { 39806, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_NV */
+ { 39836, 0x00008B31 }, /* GL_VERTEX_SHADER */
+ { 39853, 0x00008B31 }, /* GL_VERTEX_SHADER_ARB */
+ { 39874, 0x00008621 }, /* GL_VERTEX_STATE_PROGRAM_NV */
+ { 39901, 0x00000BA2 }, /* GL_VIEWPORT */
+ { 39913, 0x00000800 }, /* GL_VIEWPORT_BIT */
+ { 39929, 0x0000911D }, /* GL_WAIT_FAILED */
+ { 39944, 0x000086AD }, /* GL_WEIGHT_ARRAY_ARB */
+ { 39964, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
+ { 39995, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB */
+ { 40030, 0x000086AC }, /* GL_WEIGHT_ARRAY_POINTER_ARB */
+ { 40058, 0x000086AB }, /* GL_WEIGHT_ARRAY_SIZE_ARB */
+ { 40083, 0x000086AA }, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
+ { 40110, 0x000086A9 }, /* GL_WEIGHT_ARRAY_TYPE_ARB */
+ { 40135, 0x000086A6 }, /* GL_WEIGHT_SUM_UNITY_ARB */
+ { 40159, 0x000081D4 }, /* GL_WRAP_BORDER_SUN */
+ { 40178, 0x000088B9 }, /* GL_WRITE_ONLY */
+ { 40192, 0x000088B9 }, /* GL_WRITE_ONLY_ARB */
+ { 40210, 0x00001506 }, /* GL_XOR */
+ { 40217, 0x000085B9 }, /* GL_YCBCR_422_APPLE */
+ { 40236, 0x00008757 }, /* GL_YCBCR_MESA */
+ { 40250, 0x00000000 }, /* GL_ZERO */
+ { 40258, 0x00000D16 }, /* GL_ZOOM_X */
+ { 40268, 0x00000D17 }, /* GL_ZOOM_Y */
+};
+
+static const unsigned reduced_enums[1347] =
+{
+ 475, /* GL_FALSE */
+ 691, /* GL_LINES */
+ 693, /* GL_LINE_LOOP */
+ 700, /* GL_LINE_STRIP */
+ 1743, /* GL_TRIANGLES */
+ 1746, /* GL_TRIANGLE_STRIP */
+ 1744, /* GL_TRIANGLE_FAN */
+ 1271, /* GL_QUADS */
+ 1274, /* GL_QUAD_STRIP */
+ 1158, /* GL_POLYGON */
+ 1170, /* GL_POLYGON_STIPPLE_BIT */
+ 1119, /* GL_PIXEL_MODE_BIT */
+ 678, /* GL_LIGHTING_BIT */
+ 504, /* GL_FOG_BIT */
+ 8, /* GL_ACCUM */
+ 710, /* GL_LOAD */
+ 1326, /* GL_RETURN */
+ 991, /* GL_MULT */
+ 23, /* GL_ADD */
+ 1007, /* GL_NEVER */
+ 668, /* GL_LESS */
+ 465, /* GL_EQUAL */
+ 667, /* GL_LEQUAL */
+ 590, /* GL_GREATER */
+ 1022, /* GL_NOTEQUAL */
+ 589, /* GL_GEQUAL */
+ 47, /* GL_ALWAYS */
+ 1467, /* GL_SRC_COLOR */
+ 1052, /* GL_ONE_MINUS_SRC_COLOR */
+ 1465, /* GL_SRC_ALPHA */
+ 1051, /* GL_ONE_MINUS_SRC_ALPHA */
+ 444, /* GL_DST_ALPHA */
+ 1049, /* GL_ONE_MINUS_DST_ALPHA */
+ 445, /* GL_DST_COLOR */
+ 1050, /* GL_ONE_MINUS_DST_COLOR */
+ 1466, /* GL_SRC_ALPHA_SATURATE */
+ 577, /* GL_FRONT_LEFT */
+ 578, /* GL_FRONT_RIGHT */
+ 69, /* GL_BACK_LEFT */
+ 70, /* GL_BACK_RIGHT */
+ 574, /* GL_FRONT */
+ 68, /* GL_BACK */
+ 666, /* GL_LEFT */
+ 1368, /* GL_RIGHT */
+ 575, /* GL_FRONT_AND_BACK */
+ 63, /* GL_AUX0 */
+ 64, /* GL_AUX1 */
+ 65, /* GL_AUX2 */
+ 66, /* GL_AUX3 */
+ 656, /* GL_INVALID_ENUM */
+ 660, /* GL_INVALID_VALUE */
+ 659, /* GL_INVALID_OPERATION */
+ 1472, /* GL_STACK_OVERFLOW */
+ 1473, /* GL_STACK_UNDERFLOW */
+ 1077, /* GL_OUT_OF_MEMORY */
+ 657, /* GL_INVALID_FRAMEBUFFER_OPERATION */
+ 0, /* GL_2D */
+ 2, /* GL_3D */
+ 3, /* GL_3D_COLOR */
+ 4, /* GL_3D_COLOR_TEXTURE */
+ 6, /* GL_4D_COLOR_TEXTURE */
+ 1097, /* GL_PASS_THROUGH_TOKEN */
+ 1157, /* GL_POINT_TOKEN */
+ 701, /* GL_LINE_TOKEN */
+ 1171, /* GL_POLYGON_TOKEN */
+ 74, /* GL_BITMAP_TOKEN */
+ 443, /* GL_DRAW_PIXEL_TOKEN */
+ 301, /* GL_COPY_PIXEL_TOKEN */
+ 694, /* GL_LINE_RESET_TOKEN */
+ 468, /* GL_EXP */
+ 469, /* GL_EXP2 */
+ 337, /* GL_CW */
+ 125, /* GL_CCW */
+ 146, /* GL_COEFF */
+ 1074, /* GL_ORDER */
+ 381, /* GL_DOMAIN */
+ 311, /* GL_CURRENT_COLOR */
+ 314, /* GL_CURRENT_INDEX */
+ 320, /* GL_CURRENT_NORMAL */
+ 333, /* GL_CURRENT_TEXTURE_COORDS */
+ 325, /* GL_CURRENT_RASTER_COLOR */
+ 327, /* GL_CURRENT_RASTER_INDEX */
+ 331, /* GL_CURRENT_RASTER_TEXTURE_COORDS */
+ 328, /* GL_CURRENT_RASTER_POSITION */
+ 329, /* GL_CURRENT_RASTER_POSITION_VALID */
+ 326, /* GL_CURRENT_RASTER_DISTANCE */
+ 1150, /* GL_POINT_SMOOTH */
+ 1139, /* GL_POINT_SIZE */
+ 1149, /* GL_POINT_SIZE_RANGE */
+ 1140, /* GL_POINT_SIZE_GRANULARITY */
+ 695, /* GL_LINE_SMOOTH */
+ 702, /* GL_LINE_WIDTH */
+ 704, /* GL_LINE_WIDTH_RANGE */
+ 703, /* GL_LINE_WIDTH_GRANULARITY */
+ 697, /* GL_LINE_STIPPLE */
+ 698, /* GL_LINE_STIPPLE_PATTERN */
+ 699, /* GL_LINE_STIPPLE_REPEAT */
+ 709, /* GL_LIST_MODE */
+ 874, /* GL_MAX_LIST_NESTING */
+ 706, /* GL_LIST_BASE */
+ 708, /* GL_LIST_INDEX */
+ 1160, /* GL_POLYGON_MODE */
+ 1167, /* GL_POLYGON_SMOOTH */
+ 1169, /* GL_POLYGON_STIPPLE */
+ 454, /* GL_EDGE_FLAG */
+ 304, /* GL_CULL_FACE */
+ 305, /* GL_CULL_FACE_MODE */
+ 576, /* GL_FRONT_FACE */
+ 677, /* GL_LIGHTING */
+ 682, /* GL_LIGHT_MODEL_LOCAL_VIEWER */
+ 683, /* GL_LIGHT_MODEL_TWO_SIDE */
+ 679, /* GL_LIGHT_MODEL_AMBIENT */
+ 1414, /* GL_SHADE_MODEL */
+ 193, /* GL_COLOR_MATERIAL_FACE */
+ 194, /* GL_COLOR_MATERIAL_PARAMETER */
+ 192, /* GL_COLOR_MATERIAL */
+ 503, /* GL_FOG */
+ 525, /* GL_FOG_INDEX */
+ 521, /* GL_FOG_DENSITY */
+ 529, /* GL_FOG_START */
+ 523, /* GL_FOG_END */
+ 526, /* GL_FOG_MODE */
+ 505, /* GL_FOG_COLOR */
+ 368, /* GL_DEPTH_RANGE */
+ 375, /* GL_DEPTH_TEST */
+ 378, /* GL_DEPTH_WRITEMASK */
+ 356, /* GL_DEPTH_CLEAR_VALUE */
+ 367, /* GL_DEPTH_FUNC */
+ 12, /* GL_ACCUM_CLEAR_VALUE */
+ 1508, /* GL_STENCIL_TEST */
+ 1496, /* GL_STENCIL_CLEAR_VALUE */
+ 1498, /* GL_STENCIL_FUNC */
+ 1510, /* GL_STENCIL_VALUE_MASK */
+ 1497, /* GL_STENCIL_FAIL */
+ 1505, /* GL_STENCIL_PASS_DEPTH_FAIL */
+ 1506, /* GL_STENCIL_PASS_DEPTH_PASS */
+ 1507, /* GL_STENCIL_REF */
+ 1511, /* GL_STENCIL_WRITEMASK */
+ 843, /* GL_MATRIX_MODE */
+ 1012, /* GL_NORMALIZE */
+ 1837, /* GL_VIEWPORT */
+ 986, /* GL_MODELVIEW_STACK_DEPTH */
+ 1250, /* GL_PROJECTION_STACK_DEPTH */
+ 1718, /* GL_TEXTURE_STACK_DEPTH */
+ 984, /* GL_MODELVIEW_MATRIX */
+ 1249, /* GL_PROJECTION_MATRIX */
+ 1701, /* GL_TEXTURE_MATRIX */
+ 61, /* GL_ATTRIB_STACK_DEPTH */
+ 136, /* GL_CLIENT_ATTRIB_STACK_DEPTH */
+ 43, /* GL_ALPHA_TEST */
+ 44, /* GL_ALPHA_TEST_FUNC */
+ 45, /* GL_ALPHA_TEST_REF */
+ 380, /* GL_DITHER */
+ 78, /* GL_BLEND_DST */
+ 87, /* GL_BLEND_SRC */
+ 75, /* GL_BLEND */
+ 712, /* GL_LOGIC_OP_MODE */
+ 630, /* GL_INDEX_LOGIC_OP */
+ 191, /* GL_COLOR_LOGIC_OP */
+ 67, /* GL_AUX_BUFFERS */
+ 391, /* GL_DRAW_BUFFER */
+ 1284, /* GL_READ_BUFFER */
+ 1395, /* GL_SCISSOR_BOX */
+ 1396, /* GL_SCISSOR_TEST */
+ 629, /* GL_INDEX_CLEAR_VALUE */
+ 634, /* GL_INDEX_WRITEMASK */
+ 188, /* GL_COLOR_CLEAR_VALUE */
+ 230, /* GL_COLOR_WRITEMASK */
+ 631, /* GL_INDEX_MODE */
+ 1361, /* GL_RGBA_MODE */
+ 390, /* GL_DOUBLEBUFFER */
+ 1512, /* GL_STEREO */
+ 1319, /* GL_RENDER_MODE */
+ 1098, /* GL_PERSPECTIVE_CORRECTION_HINT */
+ 1151, /* GL_POINT_SMOOTH_HINT */
+ 696, /* GL_LINE_SMOOTH_HINT */
+ 1168, /* GL_POLYGON_SMOOTH_HINT */
+ 524, /* GL_FOG_HINT */
+ 1682, /* GL_TEXTURE_GEN_S */
+ 1683, /* GL_TEXTURE_GEN_T */
+ 1681, /* GL_TEXTURE_GEN_R */
+ 1680, /* GL_TEXTURE_GEN_Q */
+ 1111, /* GL_PIXEL_MAP_I_TO_I */
+ 1117, /* GL_PIXEL_MAP_S_TO_S */
+ 1113, /* GL_PIXEL_MAP_I_TO_R */
+ 1109, /* GL_PIXEL_MAP_I_TO_G */
+ 1107, /* GL_PIXEL_MAP_I_TO_B */
+ 1105, /* GL_PIXEL_MAP_I_TO_A */
+ 1115, /* GL_PIXEL_MAP_R_TO_R */
+ 1103, /* GL_PIXEL_MAP_G_TO_G */
+ 1101, /* GL_PIXEL_MAP_B_TO_B */
+ 1099, /* GL_PIXEL_MAP_A_TO_A */
+ 1112, /* GL_PIXEL_MAP_I_TO_I_SIZE */
+ 1118, /* GL_PIXEL_MAP_S_TO_S_SIZE */
+ 1114, /* GL_PIXEL_MAP_I_TO_R_SIZE */
+ 1110, /* GL_PIXEL_MAP_I_TO_G_SIZE */
+ 1108, /* GL_PIXEL_MAP_I_TO_B_SIZE */
+ 1106, /* GL_PIXEL_MAP_I_TO_A_SIZE */
+ 1116, /* GL_PIXEL_MAP_R_TO_R_SIZE */
+ 1104, /* GL_PIXEL_MAP_G_TO_G_SIZE */
+ 1102, /* GL_PIXEL_MAP_B_TO_B_SIZE */
+ 1100, /* GL_PIXEL_MAP_A_TO_A_SIZE */
+ 1755, /* GL_UNPACK_SWAP_BYTES */
+ 1750, /* GL_UNPACK_LSB_FIRST */
+ 1751, /* GL_UNPACK_ROW_LENGTH */
+ 1754, /* GL_UNPACK_SKIP_ROWS */
+ 1753, /* GL_UNPACK_SKIP_PIXELS */
+ 1748, /* GL_UNPACK_ALIGNMENT */
+ 1086, /* GL_PACK_SWAP_BYTES */
+ 1081, /* GL_PACK_LSB_FIRST */
+ 1082, /* GL_PACK_ROW_LENGTH */
+ 1085, /* GL_PACK_SKIP_ROWS */
+ 1084, /* GL_PACK_SKIP_PIXELS */
+ 1078, /* GL_PACK_ALIGNMENT */
+ 790, /* GL_MAP_COLOR */
+ 795, /* GL_MAP_STENCIL */
+ 633, /* GL_INDEX_SHIFT */
+ 632, /* GL_INDEX_OFFSET */
+ 1297, /* GL_RED_SCALE */
+ 1295, /* GL_RED_BIAS */
+ 1855, /* GL_ZOOM_X */
+ 1856, /* GL_ZOOM_Y */
+ 594, /* GL_GREEN_SCALE */
+ 592, /* GL_GREEN_BIAS */
+ 93, /* GL_BLUE_SCALE */
+ 91, /* GL_BLUE_BIAS */
+ 42, /* GL_ALPHA_SCALE */
+ 40, /* GL_ALPHA_BIAS */
+ 369, /* GL_DEPTH_SCALE */
+ 350, /* GL_DEPTH_BIAS */
+ 869, /* GL_MAX_EVAL_ORDER */
+ 873, /* GL_MAX_LIGHTS */
+ 852, /* GL_MAX_CLIP_PLANES */
+ 919, /* GL_MAX_TEXTURE_SIZE */
+ 879, /* GL_MAX_PIXEL_MAP_TABLE */
+ 848, /* GL_MAX_ATTRIB_STACK_DEPTH */
+ 876, /* GL_MAX_MODELVIEW_STACK_DEPTH */
+ 877, /* GL_MAX_NAME_STACK_DEPTH */
+ 905, /* GL_MAX_PROJECTION_STACK_DEPTH */
+ 920, /* GL_MAX_TEXTURE_STACK_DEPTH */
+ 934, /* GL_MAX_VIEWPORT_DIMS */
+ 849, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */
+ 1522, /* GL_SUBPIXEL_BITS */
+ 628, /* GL_INDEX_BITS */
+ 1296, /* GL_RED_BITS */
+ 593, /* GL_GREEN_BITS */
+ 92, /* GL_BLUE_BITS */
+ 41, /* GL_ALPHA_BITS */
+ 351, /* GL_DEPTH_BITS */
+ 1494, /* GL_STENCIL_BITS */
+ 14, /* GL_ACCUM_RED_BITS */
+ 13, /* GL_ACCUM_GREEN_BITS */
+ 10, /* GL_ACCUM_BLUE_BITS */
+ 9, /* GL_ACCUM_ALPHA_BITS */
+ 1000, /* GL_NAME_STACK_DEPTH */
+ 62, /* GL_AUTO_NORMAL */
+ 736, /* GL_MAP1_COLOR_4 */
+ 739, /* GL_MAP1_INDEX */
+ 740, /* GL_MAP1_NORMAL */
+ 741, /* GL_MAP1_TEXTURE_COORD_1 */
+ 742, /* GL_MAP1_TEXTURE_COORD_2 */
+ 743, /* GL_MAP1_TEXTURE_COORD_3 */
+ 744, /* GL_MAP1_TEXTURE_COORD_4 */
+ 745, /* GL_MAP1_VERTEX_3 */
+ 746, /* GL_MAP1_VERTEX_4 */
+ 763, /* GL_MAP2_COLOR_4 */
+ 766, /* GL_MAP2_INDEX */
+ 767, /* GL_MAP2_NORMAL */
+ 768, /* GL_MAP2_TEXTURE_COORD_1 */
+ 769, /* GL_MAP2_TEXTURE_COORD_2 */
+ 770, /* GL_MAP2_TEXTURE_COORD_3 */
+ 771, /* GL_MAP2_TEXTURE_COORD_4 */
+ 772, /* GL_MAP2_VERTEX_3 */
+ 773, /* GL_MAP2_VERTEX_4 */
+ 737, /* GL_MAP1_GRID_DOMAIN */
+ 738, /* GL_MAP1_GRID_SEGMENTS */
+ 764, /* GL_MAP2_GRID_DOMAIN */
+ 765, /* GL_MAP2_GRID_SEGMENTS */
+ 1605, /* GL_TEXTURE_1D */
+ 1607, /* GL_TEXTURE_2D */
+ 478, /* GL_FEEDBACK_BUFFER_POINTER */
+ 479, /* GL_FEEDBACK_BUFFER_SIZE */
+ 480, /* GL_FEEDBACK_BUFFER_TYPE */
+ 1405, /* GL_SELECTION_BUFFER_POINTER */
+ 1406, /* GL_SELECTION_BUFFER_SIZE */
+ 1723, /* GL_TEXTURE_WIDTH */
+ 1687, /* GL_TEXTURE_HEIGHT */
+ 1642, /* GL_TEXTURE_COMPONENTS */
+ 1626, /* GL_TEXTURE_BORDER_COLOR */
+ 1625, /* GL_TEXTURE_BORDER */
+ 382, /* GL_DONT_CARE */
+ 476, /* GL_FASTEST */
+ 1008, /* GL_NICEST */
+ 48, /* GL_AMBIENT */
+ 379, /* GL_DIFFUSE */
+ 1454, /* GL_SPECULAR */
+ 1172, /* GL_POSITION */
+ 1457, /* GL_SPOT_DIRECTION */
+ 1458, /* GL_SPOT_EXPONENT */
+ 1456, /* GL_SPOT_CUTOFF */
+ 275, /* GL_CONSTANT_ATTENUATION */
+ 686, /* GL_LINEAR_ATTENUATION */
+ 1270, /* GL_QUADRATIC_ATTENUATION */
+ 244, /* GL_COMPILE */
+ 245, /* GL_COMPILE_AND_EXECUTE */
+ 120, /* GL_BYTE */
+ 1757, /* GL_UNSIGNED_BYTE */
+ 1419, /* GL_SHORT */
+ 1768, /* GL_UNSIGNED_SHORT */
+ 636, /* GL_INT */
+ 1760, /* GL_UNSIGNED_INT */
+ 484, /* GL_FLOAT */
+ 1, /* GL_2_BYTES */
+ 5, /* GL_3_BYTES */
+ 7, /* GL_4_BYTES */
+ 389, /* GL_DOUBLE */
+ 132, /* GL_CLEAR */
+ 50, /* GL_AND */
+ 52, /* GL_AND_REVERSE */
+ 299, /* GL_COPY */
+ 51, /* GL_AND_INVERTED */
+ 1010, /* GL_NOOP */
+ 1851, /* GL_XOR */
+ 1073, /* GL_OR */
+ 1011, /* GL_NOR */
+ 466, /* GL_EQUIV */
+ 663, /* GL_INVERT */
+ 1076, /* GL_OR_REVERSE */
+ 300, /* GL_COPY_INVERTED */
+ 1075, /* GL_OR_INVERTED */
+ 1001, /* GL_NAND */
+ 1410, /* GL_SET */
+ 463, /* GL_EMISSION */
+ 1418, /* GL_SHININESS */
+ 49, /* GL_AMBIENT_AND_DIFFUSE */
+ 190, /* GL_COLOR_INDEXES */
+ 951, /* GL_MODELVIEW */
+ 1248, /* GL_PROJECTION */
+ 1540, /* GL_TEXTURE */
+ 147, /* GL_COLOR */
+ 346, /* GL_DEPTH */
+ 1480, /* GL_STENCIL */
+ 189, /* GL_COLOR_INDEX */
+ 1499, /* GL_STENCIL_INDEX */
+ 357, /* GL_DEPTH_COMPONENT */
+ 1292, /* GL_RED */
+ 591, /* GL_GREEN */
+ 90, /* GL_BLUE */
+ 31, /* GL_ALPHA */
+ 1327, /* GL_RGB */
+ 1346, /* GL_RGBA */
+ 714, /* GL_LUMINANCE */
+ 735, /* GL_LUMINANCE_ALPHA */
+ 73, /* GL_BITMAP */
+ 1128, /* GL_POINT */
+ 684, /* GL_LINE */
+ 481, /* GL_FILL */
+ 1301, /* GL_RENDER */
+ 477, /* GL_FEEDBACK */
+ 1404, /* GL_SELECT */
+ 483, /* GL_FLAT */
+ 1429, /* GL_SMOOTH */
+ 664, /* GL_KEEP */
+ 1321, /* GL_REPLACE */
+ 618, /* GL_INCR */
+ 342, /* GL_DECR */
+ 1783, /* GL_VENDOR */
+ 1318, /* GL_RENDERER */
+ 1784, /* GL_VERSION */
+ 470, /* GL_EXTENSIONS */
+ 1369, /* GL_S */
+ 1531, /* GL_T */
+ 1281, /* GL_R */
+ 1269, /* GL_Q */
+ 987, /* GL_MODULATE */
+ 341, /* GL_DECAL */
+ 1677, /* GL_TEXTURE_ENV_MODE */
+ 1676, /* GL_TEXTURE_ENV_COLOR */
+ 1675, /* GL_TEXTURE_ENV */
+ 471, /* GL_EYE_LINEAR */
+ 1034, /* GL_OBJECT_LINEAR */
+ 1455, /* GL_SPHERE_MAP */
+ 1679, /* GL_TEXTURE_GEN_MODE */
+ 1036, /* GL_OBJECT_PLANE */
+ 472, /* GL_EYE_PLANE */
+ 1002, /* GL_NEAREST */
+ 685, /* GL_LINEAR */
+ 1006, /* GL_NEAREST_MIPMAP_NEAREST */
+ 690, /* GL_LINEAR_MIPMAP_NEAREST */
+ 1005, /* GL_NEAREST_MIPMAP_LINEAR */
+ 689, /* GL_LINEAR_MIPMAP_LINEAR */
+ 1700, /* GL_TEXTURE_MAG_FILTER */
+ 1708, /* GL_TEXTURE_MIN_FILTER */
+ 1725, /* GL_TEXTURE_WRAP_S */
+ 1726, /* GL_TEXTURE_WRAP_T */
+ 126, /* GL_CLAMP */
+ 1320, /* GL_REPEAT */
+ 1166, /* GL_POLYGON_OFFSET_UNITS */
+ 1165, /* GL_POLYGON_OFFSET_POINT */
+ 1164, /* GL_POLYGON_OFFSET_LINE */
+ 1282, /* GL_R3_G3_B2 */
+ 1780, /* GL_V2F */
+ 1781, /* GL_V3F */
+ 123, /* GL_C4UB_V2F */
+ 124, /* GL_C4UB_V3F */
+ 121, /* GL_C3F_V3F */
+ 999, /* GL_N3F_V3F */
+ 122, /* GL_C4F_N3F_V3F */
+ 1536, /* GL_T2F_V3F */
+ 1538, /* GL_T4F_V4F */
+ 1534, /* GL_T2F_C4UB_V3F */
+ 1532, /* GL_T2F_C3F_V3F */
+ 1535, /* GL_T2F_N3F_V3F */
+ 1533, /* GL_T2F_C4F_N3F_V3F */
+ 1537, /* GL_T4F_C4F_N3F_V4F */
+ 139, /* GL_CLIP_PLANE0 */
+ 140, /* GL_CLIP_PLANE1 */
+ 141, /* GL_CLIP_PLANE2 */
+ 142, /* GL_CLIP_PLANE3 */
+ 143, /* GL_CLIP_PLANE4 */
+ 144, /* GL_CLIP_PLANE5 */
+ 669, /* GL_LIGHT0 */
+ 670, /* GL_LIGHT1 */
+ 671, /* GL_LIGHT2 */
+ 672, /* GL_LIGHT3 */
+ 673, /* GL_LIGHT4 */
+ 674, /* GL_LIGHT5 */
+ 675, /* GL_LIGHT6 */
+ 676, /* GL_LIGHT7 */
+ 595, /* GL_HINT_BIT */
+ 277, /* GL_CONSTANT_COLOR */
+ 1047, /* GL_ONE_MINUS_CONSTANT_COLOR */
+ 272, /* GL_CONSTANT_ALPHA */
+ 1045, /* GL_ONE_MINUS_CONSTANT_ALPHA */
+ 76, /* GL_BLEND_COLOR */
+ 579, /* GL_FUNC_ADD */
+ 935, /* GL_MIN */
+ 845, /* GL_MAX */
+ 81, /* GL_BLEND_EQUATION */
+ 583, /* GL_FUNC_SUBTRACT */
+ 581, /* GL_FUNC_REVERSE_SUBTRACT */
+ 280, /* GL_CONVOLUTION_1D */
+ 281, /* GL_CONVOLUTION_2D */
+ 1407, /* GL_SEPARABLE_2D */
+ 284, /* GL_CONVOLUTION_BORDER_MODE */
+ 288, /* GL_CONVOLUTION_FILTER_SCALE */
+ 286, /* GL_CONVOLUTION_FILTER_BIAS */
+ 1293, /* GL_REDUCE */
+ 290, /* GL_CONVOLUTION_FORMAT */
+ 294, /* GL_CONVOLUTION_WIDTH */
+ 292, /* GL_CONVOLUTION_HEIGHT */
+ 860, /* GL_MAX_CONVOLUTION_WIDTH */
+ 858, /* GL_MAX_CONVOLUTION_HEIGHT */
+ 1205, /* GL_POST_CONVOLUTION_RED_SCALE */
+ 1201, /* GL_POST_CONVOLUTION_GREEN_SCALE */
+ 1196, /* GL_POST_CONVOLUTION_BLUE_SCALE */
+ 1192, /* GL_POST_CONVOLUTION_ALPHA_SCALE */
+ 1203, /* GL_POST_CONVOLUTION_RED_BIAS */
+ 1199, /* GL_POST_CONVOLUTION_GREEN_BIAS */
+ 1194, /* GL_POST_CONVOLUTION_BLUE_BIAS */
+ 1190, /* GL_POST_CONVOLUTION_ALPHA_BIAS */
+ 596, /* GL_HISTOGRAM */
+ 1253, /* GL_PROXY_HISTOGRAM */
+ 612, /* GL_HISTOGRAM_WIDTH */
+ 602, /* GL_HISTOGRAM_FORMAT */
+ 608, /* GL_HISTOGRAM_RED_SIZE */
+ 604, /* GL_HISTOGRAM_GREEN_SIZE */
+ 599, /* GL_HISTOGRAM_BLUE_SIZE */
+ 597, /* GL_HISTOGRAM_ALPHA_SIZE */
+ 606, /* GL_HISTOGRAM_LUMINANCE_SIZE */
+ 610, /* GL_HISTOGRAM_SINK */
+ 936, /* GL_MINMAX */
+ 938, /* GL_MINMAX_FORMAT */
+ 940, /* GL_MINMAX_SINK */
+ 1539, /* GL_TABLE_TOO_LARGE_EXT */
+ 1759, /* GL_UNSIGNED_BYTE_3_3_2 */
+ 1770, /* GL_UNSIGNED_SHORT_4_4_4_4 */
+ 1772, /* GL_UNSIGNED_SHORT_5_5_5_1 */
+ 1765, /* GL_UNSIGNED_INT_8_8_8_8 */
+ 1761, /* GL_UNSIGNED_INT_10_10_10_2 */
+ 1163, /* GL_POLYGON_OFFSET_FILL */
+ 1162, /* GL_POLYGON_OFFSET_FACTOR */
+ 1161, /* GL_POLYGON_OFFSET_BIAS */
+ 1324, /* GL_RESCALE_NORMAL */
+ 36, /* GL_ALPHA4 */
+ 38, /* GL_ALPHA8 */
+ 32, /* GL_ALPHA12 */
+ 34, /* GL_ALPHA16 */
+ 725, /* GL_LUMINANCE4 */
+ 731, /* GL_LUMINANCE8 */
+ 715, /* GL_LUMINANCE12 */
+ 721, /* GL_LUMINANCE16 */
+ 726, /* GL_LUMINANCE4_ALPHA4 */
+ 729, /* GL_LUMINANCE6_ALPHA2 */
+ 732, /* GL_LUMINANCE8_ALPHA8 */
+ 718, /* GL_LUMINANCE12_ALPHA4 */
+ 716, /* GL_LUMINANCE12_ALPHA12 */
+ 722, /* GL_LUMINANCE16_ALPHA16 */
+ 637, /* GL_INTENSITY */
+ 642, /* GL_INTENSITY4 */
+ 644, /* GL_INTENSITY8 */
+ 638, /* GL_INTENSITY12 */
+ 640, /* GL_INTENSITY16 */
+ 1336, /* GL_RGB2_EXT */
+ 1337, /* GL_RGB4 */
+ 1340, /* GL_RGB5 */
+ 1344, /* GL_RGB8 */
+ 1328, /* GL_RGB10 */
+ 1332, /* GL_RGB12 */
+ 1334, /* GL_RGB16 */
+ 1351, /* GL_RGBA2 */
+ 1353, /* GL_RGBA4 */
+ 1341, /* GL_RGB5_A1 */
+ 1357, /* GL_RGBA8 */
+ 1329, /* GL_RGB10_A2 */
+ 1347, /* GL_RGBA12 */
+ 1349, /* GL_RGBA16 */
+ 1715, /* GL_TEXTURE_RED_SIZE */
+ 1685, /* GL_TEXTURE_GREEN_SIZE */
+ 1623, /* GL_TEXTURE_BLUE_SIZE */
+ 1610, /* GL_TEXTURE_ALPHA_SIZE */
+ 1698, /* GL_TEXTURE_LUMINANCE_SIZE */
+ 1689, /* GL_TEXTURE_INTENSITY_SIZE */
+ 1322, /* GL_REPLACE_EXT */
+ 1257, /* GL_PROXY_TEXTURE_1D */
+ 1260, /* GL_PROXY_TEXTURE_2D */
+ 1721, /* GL_TEXTURE_TOO_LARGE_EXT */
+ 1710, /* GL_TEXTURE_PRIORITY */
+ 1717, /* GL_TEXTURE_RESIDENT */
+ 1613, /* GL_TEXTURE_BINDING_1D */
+ 1615, /* GL_TEXTURE_BINDING_2D */
+ 1617, /* GL_TEXTURE_BINDING_3D */
+ 1083, /* GL_PACK_SKIP_IMAGES */
+ 1079, /* GL_PACK_IMAGE_HEIGHT */
+ 1752, /* GL_UNPACK_SKIP_IMAGES */
+ 1749, /* GL_UNPACK_IMAGE_HEIGHT */
+ 1609, /* GL_TEXTURE_3D */
+ 1263, /* GL_PROXY_TEXTURE_3D */
+ 1672, /* GL_TEXTURE_DEPTH */
+ 1724, /* GL_TEXTURE_WRAP_R */
+ 846, /* GL_MAX_3D_TEXTURE_SIZE */
+ 1785, /* GL_VERTEX_ARRAY */
+ 1013, /* GL_NORMAL_ARRAY */
+ 148, /* GL_COLOR_ARRAY */
+ 622, /* GL_INDEX_ARRAY */
+ 1650, /* GL_TEXTURE_COORD_ARRAY */
+ 455, /* GL_EDGE_FLAG_ARRAY */
+ 1791, /* GL_VERTEX_ARRAY_SIZE */
+ 1793, /* GL_VERTEX_ARRAY_TYPE */
+ 1792, /* GL_VERTEX_ARRAY_STRIDE */
+ 1018, /* GL_NORMAL_ARRAY_TYPE */
+ 1017, /* GL_NORMAL_ARRAY_STRIDE */
+ 152, /* GL_COLOR_ARRAY_SIZE */
+ 154, /* GL_COLOR_ARRAY_TYPE */
+ 153, /* GL_COLOR_ARRAY_STRIDE */
+ 627, /* GL_INDEX_ARRAY_TYPE */
+ 626, /* GL_INDEX_ARRAY_STRIDE */
+ 1654, /* GL_TEXTURE_COORD_ARRAY_SIZE */
+ 1656, /* GL_TEXTURE_COORD_ARRAY_TYPE */
+ 1655, /* GL_TEXTURE_COORD_ARRAY_STRIDE */
+ 459, /* GL_EDGE_FLAG_ARRAY_STRIDE */
+ 1790, /* GL_VERTEX_ARRAY_POINTER */
+ 1016, /* GL_NORMAL_ARRAY_POINTER */
+ 151, /* GL_COLOR_ARRAY_POINTER */
+ 625, /* GL_INDEX_ARRAY_POINTER */
+ 1653, /* GL_TEXTURE_COORD_ARRAY_POINTER */
+ 458, /* GL_EDGE_FLAG_ARRAY_POINTER */
+ 992, /* GL_MULTISAMPLE */
+ 1381, /* GL_SAMPLE_ALPHA_TO_COVERAGE */
+ 1383, /* GL_SAMPLE_ALPHA_TO_ONE */
+ 1388, /* GL_SAMPLE_COVERAGE */
+ 1385, /* GL_SAMPLE_BUFFERS */
+ 1376, /* GL_SAMPLES */
+ 1392, /* GL_SAMPLE_COVERAGE_VALUE */
+ 1390, /* GL_SAMPLE_COVERAGE_INVERT */
+ 195, /* GL_COLOR_MATRIX */
+ 197, /* GL_COLOR_MATRIX_STACK_DEPTH */
+ 854, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */
+ 1188, /* GL_POST_COLOR_MATRIX_RED_SCALE */
+ 1184, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */
+ 1179, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */
+ 1175, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */
+ 1186, /* GL_POST_COLOR_MATRIX_RED_BIAS */
+ 1182, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */
+ 1177, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */
+ 1173, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */
+ 1633, /* GL_TEXTURE_COLOR_TABLE_SGI */
+ 1264, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */
+ 1635, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
+ 80, /* GL_BLEND_DST_RGB */
+ 89, /* GL_BLEND_SRC_RGB */
+ 79, /* GL_BLEND_DST_ALPHA */
+ 88, /* GL_BLEND_SRC_ALPHA */
+ 201, /* GL_COLOR_TABLE */
+ 1198, /* GL_POST_CONVOLUTION_COLOR_TABLE */
+ 1181, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */
+ 1252, /* GL_PROXY_COLOR_TABLE */
+ 1256, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */
+ 1255, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */
+ 225, /* GL_COLOR_TABLE_SCALE */
+ 205, /* GL_COLOR_TABLE_BIAS */
+ 210, /* GL_COLOR_TABLE_FORMAT */
+ 227, /* GL_COLOR_TABLE_WIDTH */
+ 222, /* GL_COLOR_TABLE_RED_SIZE */
+ 213, /* GL_COLOR_TABLE_GREEN_SIZE */
+ 207, /* GL_COLOR_TABLE_BLUE_SIZE */
+ 202, /* GL_COLOR_TABLE_ALPHA_SIZE */
+ 219, /* GL_COLOR_TABLE_LUMINANCE_SIZE */
+ 216, /* GL_COLOR_TABLE_INTENSITY_SIZE */
+ 71, /* GL_BGR */
+ 72, /* GL_BGRA */
+ 868, /* GL_MAX_ELEMENTS_VERTICES */
+ 867, /* GL_MAX_ELEMENTS_INDICES */
+ 1688, /* GL_TEXTURE_INDEX_SIZE_EXT */
+ 145, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */
+ 1145, /* GL_POINT_SIZE_MIN */
+ 1141, /* GL_POINT_SIZE_MAX */
+ 1135, /* GL_POINT_FADE_THRESHOLD_SIZE */
+ 1131, /* GL_POINT_DISTANCE_ATTENUATION */
+ 127, /* GL_CLAMP_TO_BORDER */
+ 130, /* GL_CLAMP_TO_EDGE */
+ 1709, /* GL_TEXTURE_MIN_LOD */
+ 1707, /* GL_TEXTURE_MAX_LOD */
+ 1612, /* GL_TEXTURE_BASE_LEVEL */
+ 1706, /* GL_TEXTURE_MAX_LEVEL */
+ 615, /* GL_IGNORE_BORDER_HP */
+ 276, /* GL_CONSTANT_BORDER_HP */
+ 1323, /* GL_REPLICATE_BORDER_HP */
+ 282, /* GL_CONVOLUTION_BORDER_COLOR */
+ 1042, /* GL_OCCLUSION_TEST_HP */
+ 1043, /* GL_OCCLUSION_TEST_RESULT_HP */
+ 687, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */
+ 1627, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */
+ 1629, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */
+ 1631, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */
+ 1632, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ 1630, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */
+ 1628, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */
+ 850, /* GL_MAX_CLIPMAP_DEPTH_SGIX */
+ 851, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */
+ 1208, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */
+ 1210, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */
+ 1207, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */
+ 1209, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */
+ 1696, /* GL_TEXTURE_LOD_BIAS_S_SGIX */
+ 1697, /* GL_TEXTURE_LOD_BIAS_T_SGIX */
+ 1695, /* GL_TEXTURE_LOD_BIAS_R_SGIX */
+ 585, /* GL_GENERATE_MIPMAP */
+ 586, /* GL_GENERATE_MIPMAP_HINT */
+ 527, /* GL_FOG_OFFSET_SGIX */
+ 528, /* GL_FOG_OFFSET_VALUE_SGIX */
+ 1641, /* GL_TEXTURE_COMPARE_SGIX */
+ 1640, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */
+ 1692, /* GL_TEXTURE_LEQUAL_R_SGIX */
+ 1684, /* GL_TEXTURE_GEQUAL_R_SGIX */
+ 358, /* GL_DEPTH_COMPONENT16 */
+ 361, /* GL_DEPTH_COMPONENT24 */
+ 364, /* GL_DEPTH_COMPONENT32 */
+ 306, /* GL_CULL_VERTEX_EXT */
+ 308, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */
+ 307, /* GL_CULL_VERTEX_EYE_POSITION_EXT */
+ 1848, /* GL_WRAP_BORDER_SUN */
+ 1634, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */
+ 680, /* GL_LIGHT_MODEL_COLOR_CONTROL */
+ 1422, /* GL_SINGLE_COLOR */
+ 1408, /* GL_SEPARATE_SPECULAR_COLOR */
+ 1417, /* GL_SHARED_TEXTURE_PALETTE_EXT */
+ 538, /* GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING */
+ 539, /* GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE */
+ 546, /* GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE */
+ 541, /* GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE */
+ 537, /* GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE */
+ 536, /* GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE */
+ 540, /* GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE */
+ 547, /* GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE */
+ 558, /* GL_FRAMEBUFFER_DEFAULT */
+ 571, /* GL_FRAMEBUFFER_UNDEFINED */
+ 371, /* GL_DEPTH_STENCIL_ATTACHMENT */
+ 621, /* GL_INDEX */
+ 1758, /* GL_UNSIGNED_BYTE_2_3_3_REV */
+ 1773, /* GL_UNSIGNED_SHORT_5_6_5 */
+ 1774, /* GL_UNSIGNED_SHORT_5_6_5_REV */
+ 1771, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */
+ 1769, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */
+ 1766, /* GL_UNSIGNED_INT_8_8_8_8_REV */
+ 1764, /* GL_UNSIGNED_INT_2_10_10_10_REV */
+ 1704, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */
+ 1705, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */
+ 1703, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */
+ 943, /* GL_MIRRORED_REPEAT */
+ 1364, /* GL_RGB_S3TC */
+ 1339, /* GL_RGB4_S3TC */
+ 1362, /* GL_RGBA_S3TC */
+ 1356, /* GL_RGBA4_S3TC */
+ 1360, /* GL_RGBA_DXT5_S3TC */
+ 1354, /* GL_RGBA4_DXT5_S3TC */
+ 264, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */
+ 259, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */
+ 260, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */
+ 261, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */
+ 1004, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */
+ 1003, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */
+ 688, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */
+ 514, /* GL_FOG_COORDINATE_SOURCE */
+ 506, /* GL_FOG_COORD */
+ 530, /* GL_FRAGMENT_DEPTH */
+ 312, /* GL_CURRENT_FOG_COORD */
+ 513, /* GL_FOG_COORDINATE_ARRAY_TYPE */
+ 512, /* GL_FOG_COORDINATE_ARRAY_STRIDE */
+ 511, /* GL_FOG_COORDINATE_ARRAY_POINTER */
+ 508, /* GL_FOG_COORDINATE_ARRAY */
+ 199, /* GL_COLOR_SUM */
+ 332, /* GL_CURRENT_SECONDARY_COLOR */
+ 1401, /* GL_SECONDARY_COLOR_ARRAY_SIZE */
+ 1403, /* GL_SECONDARY_COLOR_ARRAY_TYPE */
+ 1402, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */
+ 1400, /* GL_SECONDARY_COLOR_ARRAY_POINTER */
+ 1397, /* GL_SECONDARY_COLOR_ARRAY */
+ 330, /* GL_CURRENT_RASTER_SECONDARY_COLOR */
+ 28, /* GL_ALIASED_POINT_SIZE_RANGE */
+ 27, /* GL_ALIASED_LINE_WIDTH_RANGE */
+ 1541, /* GL_TEXTURE0 */
+ 1543, /* GL_TEXTURE1 */
+ 1565, /* GL_TEXTURE2 */
+ 1587, /* GL_TEXTURE3 */
+ 1593, /* GL_TEXTURE4 */
+ 1595, /* GL_TEXTURE5 */
+ 1597, /* GL_TEXTURE6 */
+ 1599, /* GL_TEXTURE7 */
+ 1601, /* GL_TEXTURE8 */
+ 1603, /* GL_TEXTURE9 */
+ 1544, /* GL_TEXTURE10 */
+ 1546, /* GL_TEXTURE11 */
+ 1548, /* GL_TEXTURE12 */
+ 1550, /* GL_TEXTURE13 */
+ 1552, /* GL_TEXTURE14 */
+ 1554, /* GL_TEXTURE15 */
+ 1556, /* GL_TEXTURE16 */
+ 1558, /* GL_TEXTURE17 */
+ 1560, /* GL_TEXTURE18 */
+ 1562, /* GL_TEXTURE19 */
+ 1566, /* GL_TEXTURE20 */
+ 1568, /* GL_TEXTURE21 */
+ 1570, /* GL_TEXTURE22 */
+ 1572, /* GL_TEXTURE23 */
+ 1574, /* GL_TEXTURE24 */
+ 1576, /* GL_TEXTURE25 */
+ 1578, /* GL_TEXTURE26 */
+ 1580, /* GL_TEXTURE27 */
+ 1582, /* GL_TEXTURE28 */
+ 1584, /* GL_TEXTURE29 */
+ 1588, /* GL_TEXTURE30 */
+ 1590, /* GL_TEXTURE31 */
+ 18, /* GL_ACTIVE_TEXTURE */
+ 133, /* GL_CLIENT_ACTIVE_TEXTURE */
+ 921, /* GL_MAX_TEXTURE_UNITS */
+ 1736, /* GL_TRANSPOSE_MODELVIEW_MATRIX */
+ 1739, /* GL_TRANSPOSE_PROJECTION_MATRIX */
+ 1741, /* GL_TRANSPOSE_TEXTURE_MATRIX */
+ 1733, /* GL_TRANSPOSE_COLOR_MATRIX */
+ 1523, /* GL_SUBTRACT */
+ 908, /* GL_MAX_RENDERBUFFER_SIZE_EXT */
+ 247, /* GL_COMPRESSED_ALPHA */
+ 251, /* GL_COMPRESSED_LUMINANCE */
+ 252, /* GL_COMPRESSED_LUMINANCE_ALPHA */
+ 249, /* GL_COMPRESSED_INTENSITY */
+ 255, /* GL_COMPRESSED_RGB */
+ 256, /* GL_COMPRESSED_RGBA */
+ 1648, /* GL_TEXTURE_COMPRESSION_HINT */
+ 1713, /* GL_TEXTURE_RECTANGLE_ARB */
+ 1620, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */
+ 1267, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */
+ 906, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */
+ 370, /* GL_DEPTH_STENCIL */
+ 1762, /* GL_UNSIGNED_INT_24_8 */
+ 917, /* GL_MAX_TEXTURE_LOD_BIAS */
+ 1702, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */
+ 918, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */
+ 1678, /* GL_TEXTURE_FILTER_CONTROL */
+ 1693, /* GL_TEXTURE_LOD_BIAS */
+ 232, /* GL_COMBINE4 */
+ 911, /* GL_MAX_SHININESS_NV */
+ 912, /* GL_MAX_SPOT_EXPONENT_NV */
+ 619, /* GL_INCR_WRAP */
+ 343, /* GL_DECR_WRAP */
+ 963, /* GL_MODELVIEW1_ARB */
+ 1019, /* GL_NORMAL_MAP */
+ 1298, /* GL_REFLECTION_MAP */
+ 1657, /* GL_TEXTURE_CUBE_MAP */
+ 1618, /* GL_TEXTURE_BINDING_CUBE_MAP */
+ 1665, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */
+ 1659, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */
+ 1667, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */
+ 1661, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */
+ 1669, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */
+ 1663, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */
+ 1265, /* GL_PROXY_TEXTURE_CUBE_MAP */
+ 862, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */
+ 998, /* GL_MULTISAMPLE_FILTER_HINT_NV */
+ 522, /* GL_FOG_DISTANCE_MODE_NV */
+ 474, /* GL_EYE_RADIAL_NV */
+ 473, /* GL_EYE_PLANE_ABSOLUTE_NV */
+ 231, /* GL_COMBINE */
+ 238, /* GL_COMBINE_RGB */
+ 233, /* GL_COMBINE_ALPHA */
+ 1365, /* GL_RGB_SCALE */
+ 24, /* GL_ADD_SIGNED */
+ 647, /* GL_INTERPOLATE */
+ 271, /* GL_CONSTANT */
+ 1214, /* GL_PRIMARY_COLOR */
+ 1211, /* GL_PREVIOUS */
+ 1437, /* GL_SOURCE0_RGB */
+ 1443, /* GL_SOURCE1_RGB */
+ 1449, /* GL_SOURCE2_RGB */
+ 1453, /* GL_SOURCE3_RGB_NV */
+ 1434, /* GL_SOURCE0_ALPHA */
+ 1440, /* GL_SOURCE1_ALPHA */
+ 1446, /* GL_SOURCE2_ALPHA */
+ 1452, /* GL_SOURCE3_ALPHA_NV */
+ 1056, /* GL_OPERAND0_RGB */
+ 1062, /* GL_OPERAND1_RGB */
+ 1068, /* GL_OPERAND2_RGB */
+ 1072, /* GL_OPERAND3_RGB_NV */
+ 1053, /* GL_OPERAND0_ALPHA */
+ 1059, /* GL_OPERAND1_ALPHA */
+ 1065, /* GL_OPERAND2_ALPHA */
+ 1071, /* GL_OPERAND3_ALPHA_NV */
+ 1786, /* GL_VERTEX_ARRAY_BINDING */
+ 1711, /* GL_TEXTURE_RANGE_LENGTH_APPLE */
+ 1712, /* GL_TEXTURE_RANGE_POINTER_APPLE */
+ 1852, /* GL_YCBCR_422_APPLE */
+ 1775, /* GL_UNSIGNED_SHORT_8_8_APPLE */
+ 1777, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */
+ 1720, /* GL_TEXTURE_STORAGE_HINT_APPLE */
+ 1514, /* GL_STORAGE_PRIVATE_APPLE */
+ 1513, /* GL_STORAGE_CACHED_APPLE */
+ 1515, /* GL_STORAGE_SHARED_APPLE */
+ 1424, /* GL_SLICE_ACCUM_SUN */
+ 1273, /* GL_QUAD_MESH_SUN */
+ 1745, /* GL_TRIANGLE_MESH_SUN */
+ 1825, /* GL_VERTEX_PROGRAM_ARB */
+ 1836, /* GL_VERTEX_STATE_PROGRAM_NV */
+ 1812, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED */
+ 1818, /* GL_VERTEX_ATTRIB_ARRAY_SIZE */
+ 1820, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE */
+ 1822, /* GL_VERTEX_ATTRIB_ARRAY_TYPE */
+ 334, /* GL_CURRENT_VERTEX_ATTRIB */
+ 1227, /* GL_PROGRAM_LENGTH_ARB */
+ 1241, /* GL_PROGRAM_STRING_ARB */
+ 985, /* GL_MODELVIEW_PROJECTION_NV */
+ 614, /* GL_IDENTITY_NV */
+ 661, /* GL_INVERSE_NV */
+ 1738, /* GL_TRANSPOSE_NV */
+ 662, /* GL_INVERSE_TRANSPOSE_NV */
+ 892, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */
+ 891, /* GL_MAX_PROGRAM_MATRICES_ARB */
+ 799, /* GL_MATRIX0_NV */
+ 811, /* GL_MATRIX1_NV */
+ 823, /* GL_MATRIX2_NV */
+ 827, /* GL_MATRIX3_NV */
+ 829, /* GL_MATRIX4_NV */
+ 831, /* GL_MATRIX5_NV */
+ 833, /* GL_MATRIX6_NV */
+ 835, /* GL_MATRIX7_NV */
+ 318, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */
+ 315, /* GL_CURRENT_MATRIX_ARB */
+ 1828, /* GL_VERTEX_PROGRAM_POINT_SIZE */
+ 1831, /* GL_VERTEX_PROGRAM_TWO_SIDE */
+ 1239, /* GL_PROGRAM_PARAMETER_NV */
+ 1816, /* GL_VERTEX_ATTRIB_ARRAY_POINTER */
+ 1243, /* GL_PROGRAM_TARGET_NV */
+ 1240, /* GL_PROGRAM_RESIDENT_NV */
+ 1730, /* GL_TRACK_MATRIX_NV */
+ 1731, /* GL_TRACK_MATRIX_TRANSFORM_NV */
+ 1826, /* GL_VERTEX_PROGRAM_BINDING_NV */
+ 1221, /* GL_PROGRAM_ERROR_POSITION_ARB */
+ 355, /* GL_DEPTH_CLAMP_NV */
+ 1794, /* GL_VERTEX_ATTRIB_ARRAY0_NV */
+ 1801, /* GL_VERTEX_ATTRIB_ARRAY1_NV */
+ 1802, /* GL_VERTEX_ATTRIB_ARRAY2_NV */
+ 1803, /* GL_VERTEX_ATTRIB_ARRAY3_NV */
+ 1804, /* GL_VERTEX_ATTRIB_ARRAY4_NV */
+ 1805, /* GL_VERTEX_ATTRIB_ARRAY5_NV */
+ 1806, /* GL_VERTEX_ATTRIB_ARRAY6_NV */
+ 1807, /* GL_VERTEX_ATTRIB_ARRAY7_NV */
+ 1808, /* GL_VERTEX_ATTRIB_ARRAY8_NV */
+ 1809, /* GL_VERTEX_ATTRIB_ARRAY9_NV */
+ 1795, /* GL_VERTEX_ATTRIB_ARRAY10_NV */
+ 1796, /* GL_VERTEX_ATTRIB_ARRAY11_NV */
+ 1797, /* GL_VERTEX_ATTRIB_ARRAY12_NV */
+ 1798, /* GL_VERTEX_ATTRIB_ARRAY13_NV */
+ 1799, /* GL_VERTEX_ATTRIB_ARRAY14_NV */
+ 1800, /* GL_VERTEX_ATTRIB_ARRAY15_NV */
+ 747, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */
+ 754, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */
+ 755, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */
+ 756, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */
+ 757, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */
+ 758, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */
+ 759, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */
+ 760, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */
+ 761, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */
+ 762, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */
+ 748, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */
+ 749, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */
+ 750, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */
+ 751, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */
+ 752, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */
+ 753, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */
+ 774, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */
+ 781, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */
+ 782, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */
+ 783, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */
+ 784, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */
+ 785, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */
+ 786, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */
+ 1220, /* GL_PROGRAM_BINDING_ARB */
+ 788, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */
+ 789, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */
+ 775, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */
+ 776, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */
+ 777, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */
+ 778, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */
+ 779, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */
+ 780, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */
+ 1646, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */
+ 1643, /* GL_TEXTURE_COMPRESSED */
+ 1024, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */
+ 269, /* GL_COMPRESSED_TEXTURE_FORMATS */
+ 933, /* GL_MAX_VERTEX_UNITS_ARB */
+ 22, /* GL_ACTIVE_VERTEX_UNITS_ARB */
+ 1847, /* GL_WEIGHT_SUM_UNITY_ARB */
+ 1824, /* GL_VERTEX_BLEND_ARB */
+ 336, /* GL_CURRENT_WEIGHT_ARB */
+ 1846, /* GL_WEIGHT_ARRAY_TYPE_ARB */
+ 1845, /* GL_WEIGHT_ARRAY_STRIDE_ARB */
+ 1844, /* GL_WEIGHT_ARRAY_SIZE_ARB */
+ 1843, /* GL_WEIGHT_ARRAY_POINTER_ARB */
+ 1840, /* GL_WEIGHT_ARRAY_ARB */
+ 383, /* GL_DOT3_RGB */
+ 384, /* GL_DOT3_RGBA */
+ 263, /* GL_COMPRESSED_RGB_FXT1_3DFX */
+ 258, /* GL_COMPRESSED_RGBA_FXT1_3DFX */
+ 993, /* GL_MULTISAMPLE_3DFX */
+ 1386, /* GL_SAMPLE_BUFFERS_3DFX */
+ 1377, /* GL_SAMPLES_3DFX */
+ 974, /* GL_MODELVIEW2_ARB */
+ 977, /* GL_MODELVIEW3_ARB */
+ 978, /* GL_MODELVIEW4_ARB */
+ 979, /* GL_MODELVIEW5_ARB */
+ 980, /* GL_MODELVIEW6_ARB */
+ 981, /* GL_MODELVIEW7_ARB */
+ 982, /* GL_MODELVIEW8_ARB */
+ 983, /* GL_MODELVIEW9_ARB */
+ 953, /* GL_MODELVIEW10_ARB */
+ 954, /* GL_MODELVIEW11_ARB */
+ 955, /* GL_MODELVIEW12_ARB */
+ 956, /* GL_MODELVIEW13_ARB */
+ 957, /* GL_MODELVIEW14_ARB */
+ 958, /* GL_MODELVIEW15_ARB */
+ 959, /* GL_MODELVIEW16_ARB */
+ 960, /* GL_MODELVIEW17_ARB */
+ 961, /* GL_MODELVIEW18_ARB */
+ 962, /* GL_MODELVIEW19_ARB */
+ 964, /* GL_MODELVIEW20_ARB */
+ 965, /* GL_MODELVIEW21_ARB */
+ 966, /* GL_MODELVIEW22_ARB */
+ 967, /* GL_MODELVIEW23_ARB */
+ 968, /* GL_MODELVIEW24_ARB */
+ 969, /* GL_MODELVIEW25_ARB */
+ 970, /* GL_MODELVIEW26_ARB */
+ 971, /* GL_MODELVIEW27_ARB */
+ 972, /* GL_MODELVIEW28_ARB */
+ 973, /* GL_MODELVIEW29_ARB */
+ 975, /* GL_MODELVIEW30_ARB */
+ 976, /* GL_MODELVIEW31_ARB */
+ 388, /* GL_DOT3_RGB_EXT */
+ 386, /* GL_DOT3_RGBA_EXT */
+ 947, /* GL_MIRROR_CLAMP_EXT */
+ 950, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */
+ 988, /* GL_MODULATE_ADD_ATI */
+ 989, /* GL_MODULATE_SIGNED_ADD_ATI */
+ 990, /* GL_MODULATE_SUBTRACT_ATI */
+ 1853, /* GL_YCBCR_MESA */
+ 1080, /* GL_PACK_INVERT_MESA */
+ 339, /* GL_DEBUG_OBJECT_MESA */
+ 340, /* GL_DEBUG_PRINT_MESA */
+ 338, /* GL_DEBUG_ASSERT_MESA */
+ 110, /* GL_BUFFER_SIZE */
+ 112, /* GL_BUFFER_USAGE */
+ 116, /* GL_BUMP_ROT_MATRIX_ATI */
+ 117, /* GL_BUMP_ROT_MATRIX_SIZE_ATI */
+ 115, /* GL_BUMP_NUM_TEX_UNITS_ATI */
+ 119, /* GL_BUMP_TEX_UNITS_ATI */
+ 447, /* GL_DUDV_ATI */
+ 446, /* GL_DU8DV8_ATI */
+ 114, /* GL_BUMP_ENVMAP_ATI */
+ 118, /* GL_BUMP_TARGET_ATI */
+ 1485, /* GL_STENCIL_BACK_FUNC */
+ 1483, /* GL_STENCIL_BACK_FAIL */
+ 1487, /* GL_STENCIL_BACK_PASS_DEPTH_FAIL */
+ 1489, /* GL_STENCIL_BACK_PASS_DEPTH_PASS */
+ 531, /* GL_FRAGMENT_PROGRAM_ARB */
+ 1218, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ 1246, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ 1245, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */
+ 1230, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ 1236, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ 1235, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ 881, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */
+ 904, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */
+ 903, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */
+ 894, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */
+ 900, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */
+ 899, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */
+ 864, /* GL_MAX_DRAW_BUFFERS */
+ 392, /* GL_DRAW_BUFFER0 */
+ 395, /* GL_DRAW_BUFFER1 */
+ 416, /* GL_DRAW_BUFFER2 */
+ 419, /* GL_DRAW_BUFFER3 */
+ 422, /* GL_DRAW_BUFFER4 */
+ 425, /* GL_DRAW_BUFFER5 */
+ 428, /* GL_DRAW_BUFFER6 */
+ 431, /* GL_DRAW_BUFFER7 */
+ 434, /* GL_DRAW_BUFFER8 */
+ 437, /* GL_DRAW_BUFFER9 */
+ 396, /* GL_DRAW_BUFFER10 */
+ 399, /* GL_DRAW_BUFFER11 */
+ 402, /* GL_DRAW_BUFFER12 */
+ 405, /* GL_DRAW_BUFFER13 */
+ 408, /* GL_DRAW_BUFFER14 */
+ 411, /* GL_DRAW_BUFFER15 */
+ 82, /* GL_BLEND_EQUATION_ALPHA */
+ 844, /* GL_MATRIX_PALETTE_ARB */
+ 875, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */
+ 878, /* GL_MAX_PALETTE_MATRICES_ARB */
+ 321, /* GL_CURRENT_PALETTE_MATRIX_ARB */
+ 838, /* GL_MATRIX_INDEX_ARRAY_ARB */
+ 316, /* GL_CURRENT_MATRIX_INDEX_ARB */
+ 840, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */
+ 842, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */
+ 841, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */
+ 839, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */
+ 1673, /* GL_TEXTURE_DEPTH_SIZE */
+ 376, /* GL_DEPTH_TEXTURE_MODE */
+ 1638, /* GL_TEXTURE_COMPARE_MODE */
+ 1636, /* GL_TEXTURE_COMPARE_FUNC */
+ 242, /* GL_COMPARE_R_TO_TEXTURE */
+ 1152, /* GL_POINT_SPRITE */
+ 296, /* GL_COORD_REPLACE */
+ 1156, /* GL_POINT_SPRITE_R_MODE_NV */
+ 1275, /* GL_QUERY_COUNTER_BITS */
+ 323, /* GL_CURRENT_QUERY */
+ 1277, /* GL_QUERY_RESULT */
+ 1279, /* GL_QUERY_RESULT_AVAILABLE */
+ 927, /* GL_MAX_VERTEX_ATTRIBS */
+ 1814, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED */
+ 374, /* GL_DEPTH_STENCIL_TO_RGBA_NV */
+ 373, /* GL_DEPTH_STENCIL_TO_BGRA_NV */
+ 913, /* GL_MAX_TEXTURE_COORDS */
+ 915, /* GL_MAX_TEXTURE_IMAGE_UNITS */
+ 1223, /* GL_PROGRAM_ERROR_STRING_ARB */
+ 1225, /* GL_PROGRAM_FORMAT_ASCII_ARB */
+ 1224, /* GL_PROGRAM_FORMAT_ARB */
+ 1722, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */
+ 353, /* GL_DEPTH_BOUNDS_TEST_EXT */
+ 352, /* GL_DEPTH_BOUNDS_EXT */
+ 53, /* GL_ARRAY_BUFFER */
+ 460, /* GL_ELEMENT_ARRAY_BUFFER */
+ 54, /* GL_ARRAY_BUFFER_BINDING */
+ 461, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */
+ 1788, /* GL_VERTEX_ARRAY_BUFFER_BINDING */
+ 1014, /* GL_NORMAL_ARRAY_BUFFER_BINDING */
+ 149, /* GL_COLOR_ARRAY_BUFFER_BINDING */
+ 623, /* GL_INDEX_ARRAY_BUFFER_BINDING */
+ 1651, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */
+ 456, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */
+ 1398, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */
+ 509, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */
+ 1841, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */
+ 1810, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */
+ 1226, /* GL_PROGRAM_INSTRUCTIONS_ARB */
+ 887, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */
+ 1232, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ 896, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */
+ 1244, /* GL_PROGRAM_TEMPORARIES_ARB */
+ 902, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
+ 1234, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ 898, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */
+ 1238, /* GL_PROGRAM_PARAMETERS_ARB */
+ 901, /* GL_MAX_PROGRAM_PARAMETERS_ARB */
+ 1233, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */
+ 897, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */
+ 1219, /* GL_PROGRAM_ATTRIBS_ARB */
+ 882, /* GL_MAX_PROGRAM_ATTRIBS_ARB */
+ 1231, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */
+ 895, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */
+ 1217, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */
+ 880, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */
+ 1229, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ 893, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */
+ 888, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */
+ 884, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */
+ 1247, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */
+ 1735, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */
+ 1288, /* GL_READ_ONLY */
+ 1849, /* GL_WRITE_ONLY */
+ 1290, /* GL_READ_WRITE */
+ 102, /* GL_BUFFER_ACCESS */
+ 105, /* GL_BUFFER_MAPPED */
+ 107, /* GL_BUFFER_MAP_POINTER */
+ 1729, /* GL_TIME_ELAPSED_EXT */
+ 798, /* GL_MATRIX0_ARB */
+ 810, /* GL_MATRIX1_ARB */
+ 822, /* GL_MATRIX2_ARB */
+ 826, /* GL_MATRIX3_ARB */
+ 828, /* GL_MATRIX4_ARB */
+ 830, /* GL_MATRIX5_ARB */
+ 832, /* GL_MATRIX6_ARB */
+ 834, /* GL_MATRIX7_ARB */
+ 836, /* GL_MATRIX8_ARB */
+ 837, /* GL_MATRIX9_ARB */
+ 800, /* GL_MATRIX10_ARB */
+ 801, /* GL_MATRIX11_ARB */
+ 802, /* GL_MATRIX12_ARB */
+ 803, /* GL_MATRIX13_ARB */
+ 804, /* GL_MATRIX14_ARB */
+ 805, /* GL_MATRIX15_ARB */
+ 806, /* GL_MATRIX16_ARB */
+ 807, /* GL_MATRIX17_ARB */
+ 808, /* GL_MATRIX18_ARB */
+ 809, /* GL_MATRIX19_ARB */
+ 812, /* GL_MATRIX20_ARB */
+ 813, /* GL_MATRIX21_ARB */
+ 814, /* GL_MATRIX22_ARB */
+ 815, /* GL_MATRIX23_ARB */
+ 816, /* GL_MATRIX24_ARB */
+ 817, /* GL_MATRIX25_ARB */
+ 818, /* GL_MATRIX26_ARB */
+ 819, /* GL_MATRIX27_ARB */
+ 820, /* GL_MATRIX28_ARB */
+ 821, /* GL_MATRIX29_ARB */
+ 824, /* GL_MATRIX30_ARB */
+ 825, /* GL_MATRIX31_ARB */
+ 1518, /* GL_STREAM_DRAW */
+ 1520, /* GL_STREAM_READ */
+ 1516, /* GL_STREAM_COPY */
+ 1476, /* GL_STATIC_DRAW */
+ 1478, /* GL_STATIC_READ */
+ 1474, /* GL_STATIC_COPY */
+ 450, /* GL_DYNAMIC_DRAW */
+ 452, /* GL_DYNAMIC_READ */
+ 448, /* GL_DYNAMIC_COPY */
+ 1120, /* GL_PIXEL_PACK_BUFFER */
+ 1124, /* GL_PIXEL_UNPACK_BUFFER */
+ 1121, /* GL_PIXEL_PACK_BUFFER_BINDING */
+ 1125, /* GL_PIXEL_UNPACK_BUFFER_BINDING */
+ 347, /* GL_DEPTH24_STENCIL8 */
+ 1719, /* GL_TEXTURE_STENCIL_SIZE */
+ 1671, /* GL_TEXTURE_CUBE_MAP_SEAMLESS */
+ 883, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */
+ 886, /* GL_MAX_PROGRAM_IF_DEPTH_NV */
+ 890, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */
+ 889, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */
+ 847, /* GL_MAX_ARRAY_TEXTURE_LAYERS_EXT */
+ 1509, /* GL_STENCIL_TEST_TWO_SIDE_EXT */
+ 17, /* GL_ACTIVE_STENCIL_FACE_EXT */
+ 948, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */
+ 1379, /* GL_SAMPLES_PASSED */
+ 109, /* GL_BUFFER_SERIALIZED_MODIFY_APPLE */
+ 104, /* GL_BUFFER_FLUSHING_UNMAP_APPLE */
+ 532, /* GL_FRAGMENT_SHADER */
+ 1834, /* GL_VERTEX_SHADER */
+ 1237, /* GL_PROGRAM_OBJECT_ARB */
+ 1411, /* GL_SHADER_OBJECT_ARB */
+ 871, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS */
+ 931, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS */
+ 925, /* GL_MAX_VARYING_FLOATS */
+ 929, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS */
+ 856, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */
+ 1040, /* GL_OBJECT_TYPE_ARB */
+ 1413, /* GL_SHADER_TYPE */
+ 497, /* GL_FLOAT_VEC2 */
+ 499, /* GL_FLOAT_VEC3 */
+ 501, /* GL_FLOAT_VEC4 */
+ 650, /* GL_INT_VEC2 */
+ 652, /* GL_INT_VEC3 */
+ 654, /* GL_INT_VEC4 */
+ 94, /* GL_BOOL */
+ 96, /* GL_BOOL_VEC2 */
+ 98, /* GL_BOOL_VEC3 */
+ 100, /* GL_BOOL_VEC4 */
+ 485, /* GL_FLOAT_MAT2 */
+ 489, /* GL_FLOAT_MAT3 */
+ 493, /* GL_FLOAT_MAT4 */
+ 1370, /* GL_SAMPLER_1D */
+ 1372, /* GL_SAMPLER_2D */
+ 1374, /* GL_SAMPLER_3D */
+ 1375, /* GL_SAMPLER_CUBE */
+ 1371, /* GL_SAMPLER_1D_SHADOW */
+ 1373, /* GL_SAMPLER_2D_SHADOW */
+ 487, /* GL_FLOAT_MAT2x3 */
+ 488, /* GL_FLOAT_MAT2x4 */
+ 491, /* GL_FLOAT_MAT3x2 */
+ 492, /* GL_FLOAT_MAT3x4 */
+ 495, /* GL_FLOAT_MAT4x2 */
+ 496, /* GL_FLOAT_MAT4x3 */
+ 345, /* GL_DELETE_STATUS */
+ 246, /* GL_COMPILE_STATUS */
+ 705, /* GL_LINK_STATUS */
+ 1782, /* GL_VALIDATE_STATUS */
+ 635, /* GL_INFO_LOG_LENGTH */
+ 56, /* GL_ATTACHED_SHADERS */
+ 20, /* GL_ACTIVE_UNIFORMS */
+ 21, /* GL_ACTIVE_UNIFORM_MAX_LENGTH */
+ 1412, /* GL_SHADER_SOURCE_LENGTH */
+ 15, /* GL_ACTIVE_ATTRIBUTES */
+ 16, /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */
+ 534, /* GL_FRAGMENT_SHADER_DERIVATIVE_HINT */
+ 1415, /* GL_SHADING_LANGUAGE_VERSION */
+ 322, /* GL_CURRENT_PROGRAM */
+ 1089, /* GL_PALETTE4_RGB8_OES */
+ 1091, /* GL_PALETTE4_RGBA8_OES */
+ 1087, /* GL_PALETTE4_R5_G6_B5_OES */
+ 1090, /* GL_PALETTE4_RGBA4_OES */
+ 1088, /* GL_PALETTE4_RGB5_A1_OES */
+ 1094, /* GL_PALETTE8_RGB8_OES */
+ 1096, /* GL_PALETTE8_RGBA8_OES */
+ 1092, /* GL_PALETTE8_R5_G6_B5_OES */
+ 1095, /* GL_PALETTE8_RGBA4_OES */
+ 1093, /* GL_PALETTE8_RGB5_A1_OES */
+ 617, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */
+ 616, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */
+ 1767, /* GL_UNSIGNED_NORMALIZED */
+ 1606, /* GL_TEXTURE_1D_ARRAY_EXT */
+ 1258, /* GL_PROXY_TEXTURE_1D_ARRAY_EXT */
+ 1608, /* GL_TEXTURE_2D_ARRAY_EXT */
+ 1261, /* GL_PROXY_TEXTURE_2D_ARRAY_EXT */
+ 1614, /* GL_TEXTURE_BINDING_1D_ARRAY_EXT */
+ 1616, /* GL_TEXTURE_BINDING_2D_ARRAY_EXT */
+ 1468, /* GL_SRGB */
+ 1469, /* GL_SRGB8 */
+ 1471, /* GL_SRGB_ALPHA */
+ 1470, /* GL_SRGB8_ALPHA8 */
+ 1428, /* GL_SLUMINANCE_ALPHA */
+ 1427, /* GL_SLUMINANCE8_ALPHA8 */
+ 1425, /* GL_SLUMINANCE */
+ 1426, /* GL_SLUMINANCE8 */
+ 267, /* GL_COMPRESSED_SRGB */
+ 268, /* GL_COMPRESSED_SRGB_ALPHA */
+ 265, /* GL_COMPRESSED_SLUMINANCE */
+ 266, /* GL_COMPRESSED_SLUMINANCE_ALPHA */
+ 1154, /* GL_POINT_SPRITE_COORD_ORIGIN */
+ 713, /* GL_LOWER_LEFT */
+ 1779, /* GL_UPPER_LEFT */
+ 1491, /* GL_STENCIL_BACK_REF */
+ 1492, /* GL_STENCIL_BACK_VALUE_MASK */
+ 1493, /* GL_STENCIL_BACK_WRITEMASK */
+ 441, /* GL_DRAW_FRAMEBUFFER_BINDING_EXT */
+ 1304, /* GL_RENDERBUFFER_BINDING_EXT */
+ 1285, /* GL_READ_FRAMEBUFFER */
+ 440, /* GL_DRAW_FRAMEBUFFER */
+ 1286, /* GL_READ_FRAMEBUFFER_BINDING_EXT */
+ 1314, /* GL_RENDERBUFFER_SAMPLES */
+ 544, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE */
+ 542, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME */
+ 553, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL */
+ 549, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE */
+ 551, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */
+ 556, /* GL_FRAMEBUFFER_COMPLETE */
+ 560, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT */
+ 566, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT */
+ 564, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */
+ 562, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */
+ 565, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */
+ 563, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */
+ 569, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */
+ 572, /* GL_FRAMEBUFFER_UNSUPPORTED */
+ 570, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */
+ 853, /* GL_MAX_COLOR_ATTACHMENTS_EXT */
+ 155, /* GL_COLOR_ATTACHMENT0 */
+ 157, /* GL_COLOR_ATTACHMENT1 */
+ 171, /* GL_COLOR_ATTACHMENT2 */
+ 173, /* GL_COLOR_ATTACHMENT3 */
+ 175, /* GL_COLOR_ATTACHMENT4 */
+ 177, /* GL_COLOR_ATTACHMENT5 */
+ 179, /* GL_COLOR_ATTACHMENT6 */
+ 181, /* GL_COLOR_ATTACHMENT7 */
+ 183, /* GL_COLOR_ATTACHMENT8 */
+ 185, /* GL_COLOR_ATTACHMENT9 */
+ 158, /* GL_COLOR_ATTACHMENT10 */
+ 160, /* GL_COLOR_ATTACHMENT11 */
+ 162, /* GL_COLOR_ATTACHMENT12 */
+ 164, /* GL_COLOR_ATTACHMENT13 */
+ 166, /* GL_COLOR_ATTACHMENT14 */
+ 168, /* GL_COLOR_ATTACHMENT15 */
+ 348, /* GL_DEPTH_ATTACHMENT */
+ 1481, /* GL_STENCIL_ATTACHMENT */
+ 535, /* GL_FRAMEBUFFER */
+ 1302, /* GL_RENDERBUFFER */
+ 1316, /* GL_RENDERBUFFER_WIDTH */
+ 1309, /* GL_RENDERBUFFER_HEIGHT */
+ 1311, /* GL_RENDERBUFFER_INTERNAL_FORMAT */
+ 1504, /* GL_STENCIL_INDEX_EXT */
+ 1501, /* GL_STENCIL_INDEX1_EXT */
+ 1502, /* GL_STENCIL_INDEX4_EXT */
+ 1503, /* GL_STENCIL_INDEX8_EXT */
+ 1500, /* GL_STENCIL_INDEX16_EXT */
+ 1313, /* GL_RENDERBUFFER_RED_SIZE */
+ 1308, /* GL_RENDERBUFFER_GREEN_SIZE */
+ 1305, /* GL_RENDERBUFFER_BLUE_SIZE */
+ 1303, /* GL_RENDERBUFFER_ALPHA_SIZE */
+ 1306, /* GL_RENDERBUFFER_DEPTH_SIZE */
+ 1315, /* GL_RENDERBUFFER_STENCIL_SIZE */
+ 568, /* GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE */
+ 909, /* GL_MAX_SAMPLES */
+ 1272, /* GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT */
+ 482, /* GL_FIRST_VERTEX_CONVENTION_EXT */
+ 665, /* GL_LAST_VERTEX_CONVENTION_EXT */
+ 1251, /* GL_PROVOKING_VERTEX_EXT */
+ 302, /* GL_COPY_READ_BUFFER */
+ 303, /* GL_COPY_WRITE_BUFFER */
+ 1363, /* GL_RGBA_SNORM */
+ 1359, /* GL_RGBA8_SNORM */
+ 1421, /* GL_SIGNED_NORMALIZED */
+ 910, /* GL_MAX_SERVER_WAIT_TIMEOUT */
+ 1039, /* GL_OBJECT_TYPE */
+ 1525, /* GL_SYNC_CONDITION */
+ 1530, /* GL_SYNC_STATUS */
+ 1527, /* GL_SYNC_FLAGS */
+ 1526, /* GL_SYNC_FENCE */
+ 1529, /* GL_SYNC_GPU_COMMANDS_COMPLETE */
+ 1756, /* GL_UNSIGNALED */
+ 1420, /* GL_SIGNALED */
+ 46, /* GL_ALREADY_SIGNALED */
+ 1727, /* GL_TIMEOUT_EXPIRED */
+ 270, /* GL_CONDITION_SATISFIED */
+ 1839, /* GL_WAIT_FAILED */
+ 467, /* GL_EVAL_BIT */
+ 1283, /* GL_RASTER_POSITION_UNCLIPPED_IBM */
+ 707, /* GL_LIST_BIT */
+ 1622, /* GL_TEXTURE_BIT */
+ 1394, /* GL_SCISSOR_BIT */
+ 29, /* GL_ALL_ATTRIB_BITS */
+ 995, /* GL_MULTISAMPLE_BIT */
+ 30, /* GL_ALL_CLIENT_ATTRIB_BITS */
+ 1728, /* GL_TIMEOUT_IGNORED */
+};
+
+typedef int (*cfunc)(const void *, const void *);
+
+/**
+ * Compare a key name to an element in the \c all_enums array.
+ *
+ * \c bsearch always passes the key as the first parameter and the pointer
+ * to the array element as the second parameter. We can elimiate some
+ * extra work by taking advantage of that fact.
+ *
+ * \param a Pointer to the desired enum name.
+ * \param b Pointer to an element of the \c all_enums array.
+ */
+static int compar_name( const char *a, const enum_elt *b )
+{
+ return _mesa_strcmp( a, & enum_string_table[ b->offset ] );
+}
+
+/**
+ * Compare a key enum value to an element in the \c all_enums array.
+ *
+ * \c bsearch always passes the key as the first parameter and the pointer
+ * to the array element as the second parameter. We can elimiate some
+ * extra work by taking advantage of that fact.
+ *
+ * \param a Pointer to the desired enum name.
+ * \param b Pointer to an index into the \c all_enums array.
+ */
+static int compar_nr( const int *a, const unsigned *b )
+{
+ return a[0] - all_enums[*b].n;
+}
+
+
+static char token_tmp[20];
+
+const char *_mesa_lookup_enum_by_nr( int nr )
+{
+ unsigned * i;
+
+ i = (unsigned *) _mesa_bsearch(& nr, reduced_enums,
+ Elements(reduced_enums),
+ sizeof(reduced_enums[0]),
+ (cfunc) compar_nr);
+
+ if ( i != NULL ) {
+ return & enum_string_table[ all_enums[ *i ].offset ];
+ }
+ else {
+ /* this is not re-entrant safe, no big deal here */
+ _mesa_sprintf(token_tmp, "0x%x", nr);
+ return token_tmp;
+ }
+}
+
+/* Get the name of an enum given that it is a primitive type. Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr )
+{
+ switch (nr) {
+ case GL_POINTS: return "GL_POINTS";
+ case GL_LINES: return "GL_LINES";
+ case GL_LINE_STRIP: return "GL_LINE_STRIP";
+ case GL_LINE_LOOP: return "GL_LINE_LOOP";
+ case GL_TRIANGLES: return "GL_TRIANGLES";
+ case GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP";
+ case GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN";
+ case GL_QUADS: return "GL_QUADS";
+ case GL_QUAD_STRIP: return "GL_QUAD_STRIP";
+ case GL_POLYGON: return "GL_POLYGON";
+ case GL_POLYGON+1: return "OUTSIDE_BEGIN_END";
+ default: return "<invalid>";
+ }
+}
+
+
+
+int _mesa_lookup_enum_by_name( const char *symbol )
+{
+ enum_elt * f = NULL;
+
+ if ( symbol != NULL ) {
+ f = (enum_elt *) _mesa_bsearch(symbol, all_enums,
+ Elements(all_enums),
+ sizeof( enum_elt ),
+ (cfunc) compar_name);
+ }
+
+ return (f != NULL) ? f->n : -1;
+}
+
+
diff --git a/mesalib/src/mesa/main/enums.h b/mesalib/src/mesa/main/enums.h
new file mode 100644
index 000000000..b5f69001b
--- /dev/null
+++ b/mesalib/src/mesa/main/enums.h
@@ -0,0 +1,61 @@
+/**
+ * \file enums.h
+ * Enumeration name/number lookup functions.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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_
+
+
+#if defined(_HAVE_FULL_GL) && _HAVE_FULL_GL
+
+extern const char *_mesa_lookup_enum_by_nr( int nr );
+
+/* Get the name of an enum given that it is a primitive type. Avoids
+ * GL_FALSE/GL_POINTS ambiguity and others.
+ */
+const char *_mesa_lookup_prim_by_nr( int nr );
+
+extern int _mesa_lookup_enum_by_name( const char *symbol );
+
+#else
+
+/** No-op */
+#define _mesa_lookup_enum_by_name( s ) 0
+
+/** No-op */
+#define _mesa_lookup_enum_by_nr( n ) "unknown"
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/eval.c b/mesalib/src/mesa/main/eval.c
new file mode 100644
index 000000000..3f89f9c1e
--- /dev/null
+++ b/mesalib/src/mesa/main/eval.c
@@ -0,0 +1,962 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * 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!
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "eval.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+/*
+ * Return the number of components per control point for any type of
+ * evaluator. Return 0 if bad target.
+ * See table 5.1 in the OpenGL 1.2 spec.
+ */
+GLuint _mesa_evaluator_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: break;
+ }
+
+ /* XXX need to check for the vertex program extension
+ if (!ctx->Extensions.NV_vertex_program)
+ return 0;
+ */
+
+ if (target >= GL_MAP1_VERTEX_ATTRIB0_4_NV &&
+ target <= GL_MAP1_VERTEX_ATTRIB15_4_NV)
+ return 4;
+
+ if (target >= GL_MAP2_VERTEX_ATTRIB0_4_NV &&
+ target <= GL_MAP2_VERTEX_ATTRIB15_4_NV)
+ return 4;
+
+ return 0;
+}
+
+
+/*
+ * Return pointer to the gl_1d_map struct for the named target.
+ */
+static struct gl_1d_map *
+get_1d_map( GLcontext *ctx, GLenum target )
+{
+ switch (target) {
+ case GL_MAP1_VERTEX_3:
+ return &ctx->EvalMap.Map1Vertex3;
+ case GL_MAP1_VERTEX_4:
+ return &ctx->EvalMap.Map1Vertex4;
+ case GL_MAP1_INDEX:
+ return &ctx->EvalMap.Map1Index;
+ case GL_MAP1_COLOR_4:
+ return &ctx->EvalMap.Map1Color4;
+ case GL_MAP1_NORMAL:
+ return &ctx->EvalMap.Map1Normal;
+ case GL_MAP1_TEXTURE_COORD_1:
+ return &ctx->EvalMap.Map1Texture1;
+ case GL_MAP1_TEXTURE_COORD_2:
+ return &ctx->EvalMap.Map1Texture2;
+ case GL_MAP1_TEXTURE_COORD_3:
+ return &ctx->EvalMap.Map1Texture3;
+ case GL_MAP1_TEXTURE_COORD_4:
+ return &ctx->EvalMap.Map1Texture4;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ if (!ctx->Extensions.NV_vertex_program)
+ return NULL;
+ return &ctx->EvalMap.Map1Attrib[target - GL_MAP1_VERTEX_ATTRIB0_4_NV];
+ default:
+ return NULL;
+ }
+}
+
+
+/*
+ * Return pointer to the gl_2d_map struct for the named target.
+ */
+static struct gl_2d_map *
+get_2d_map( GLcontext *ctx, GLenum target )
+{
+ switch (target) {
+ case GL_MAP2_VERTEX_3:
+ return &ctx->EvalMap.Map2Vertex3;
+ case GL_MAP2_VERTEX_4:
+ return &ctx->EvalMap.Map2Vertex4;
+ case GL_MAP2_INDEX:
+ return &ctx->EvalMap.Map2Index;
+ case GL_MAP2_COLOR_4:
+ return &ctx->EvalMap.Map2Color4;
+ case GL_MAP2_NORMAL:
+ return &ctx->EvalMap.Map2Normal;
+ case GL_MAP2_TEXTURE_COORD_1:
+ return &ctx->EvalMap.Map2Texture1;
+ case GL_MAP2_TEXTURE_COORD_2:
+ return &ctx->EvalMap.Map2Texture2;
+ case GL_MAP2_TEXTURE_COORD_3:
+ return &ctx->EvalMap.Map2Texture3;
+ case GL_MAP2_TEXTURE_COORD_4:
+ return &ctx->EvalMap.Map2Texture4;
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ if (!ctx->Extensions.NV_vertex_program)
+ return NULL;
+ return &ctx->EvalMap.Map2Attrib[target - GL_MAP2_VERTEX_ATTRIB0_4_NV];
+ default:
+ return NULL;
+ }
+}
+
+
+/**********************************************************************/
+/*** Copy and deallocate control points ***/
+/**********************************************************************/
+
+
+/*
+ * Copy 1-parametric evaluator control points from user-specified
+ * memory space to a buffer of contiguous control points.
+ * \param see glMap1f for details
+ * \return pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
+ const GLfloat *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, k, size = _mesa_evaluator_components(target);
+
+ if (!points || !size)
+ 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 *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
+ const GLdouble *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, k, size = _mesa_evaluator_components(target);
+
+ if (!points || !size)
+ 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.
+ *
+ * \param see glMap2f for details
+ * \return pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+GLfloat *_mesa_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 = _mesa_evaluator_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 *_mesa_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 = _mesa_evaluator_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;
+}
+
+
+
+
+/**********************************************************************/
+/*** API entry points ***/
+/**********************************************************************/
+
+
+/*
+ * This does the work of glMap1[fd].
+ */
+static void
+map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
+ GLint uorder, const GLvoid *points, GLenum type )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint k;
+ GLfloat *pnts;
+ struct gl_1d_map *map = NULL;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
+
+ if (u1 == u2) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
+ return;
+ }
+ if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
+ return;
+ }
+ if (!points) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
+ return;
+ }
+
+ k = _mesa_evaluator_components( target );
+ if (k == 0) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
+ }
+
+ if (ustride < k) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
+ return;
+ }
+
+ if (ctx->Texture.CurrentUnit != 0) {
+ /* See OpenGL 1.2.1 spec, section F.2.13 */
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
+ return;
+ }
+
+ map = get_1d_map(ctx, target);
+ if (!map) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
+ return;
+ }
+
+ /* make copy of the control points */
+ if (type == GL_FLOAT)
+ pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
+ else
+ pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
+
+
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ map->Order = uorder;
+ map->u1 = u1;
+ map->u2 = u2;
+ map->du = 1.0F / (u2 - u1);
+ if (map->Points)
+ FREE( map->Points );
+ map->Points = pnts;
+}
+
+
+
+void GLAPIENTRY
+_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat *points )
+{
+ map1(target, u1, u2, stride, order, points, GL_FLOAT);
+}
+
+
+void GLAPIENTRY
+_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
+ GLint order, const GLdouble *points )
+{
+ map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
+}
+
+
+static void
+map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLvoid *points, GLenum type )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint k;
+ GLfloat *pnts;
+ struct gl_2d_map *map = NULL;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
+
+ if (u1==u2) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
+ return;
+ }
+
+ if (v1==v2) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
+ return;
+ }
+
+ if (uorder<1 || uorder>MAX_EVAL_ORDER) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
+ return;
+ }
+
+ if (vorder<1 || vorder>MAX_EVAL_ORDER) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
+ return;
+ }
+
+ k = _mesa_evaluator_components( target );
+ if (k==0) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
+ }
+
+ if (ustride < k) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
+ return;
+ }
+ if (vstride < k) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
+ return;
+ }
+
+ if (ctx->Texture.CurrentUnit != 0) {
+ /* See OpenGL 1.2.1 spec, section F.2.13 */
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
+ return;
+ }
+
+ map = get_2d_map(ctx, target);
+ if (!map) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
+ return;
+ }
+
+ /* make copy of the control points */
+ if (type == GL_FLOAT)
+ pnts = _mesa_copy_map_points2f(target, ustride, uorder,
+ vstride, vorder, (GLfloat*) points);
+ else
+ pnts = _mesa_copy_map_points2d(target, ustride, uorder,
+ vstride, vorder, (GLdouble*) points);
+
+
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ map->Uorder = uorder;
+ map->u1 = u1;
+ map->u2 = u2;
+ map->du = 1.0F / (u2 - u1);
+ map->Vorder = vorder;
+ map->v1 = v1;
+ map->v2 = v2;
+ map->dv = 1.0F / (v2 - v1);
+ if (map->Points)
+ FREE( map->Points );
+ map->Points = pnts;
+}
+
+
+void GLAPIENTRY
+_mesa_Map2f( GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points)
+{
+ map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
+ points, GL_FLOAT);
+}
+
+
+void GLAPIENTRY
+_mesa_Map2d( GLenum target,
+ GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
+ const GLdouble *points )
+{
+ map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
+ (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_1d_map *map1d;
+ struct gl_2d_map *map2d;
+ GLint i, n;
+ GLfloat *data;
+ GLuint comps;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ comps = _mesa_evaluator_components(target);
+ if (!comps) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
+ return;
+ }
+
+ map1d = get_1d_map(ctx, target);
+ map2d = get_2d_map(ctx, target);
+ ASSERT(map1d || map2d);
+
+ switch (query) {
+ case GL_COEFF:
+ if (map1d) {
+ data = map1d->Points;
+ n = map1d->Order * comps;
+ }
+ else {
+ data = map2d->Points;
+ n = map2d->Uorder * map2d->Vorder * comps;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = data[i];
+ }
+ }
+ break;
+ case GL_ORDER:
+ if (map1d) {
+ v[0] = (GLdouble) map1d->Order;
+ }
+ else {
+ v[0] = (GLdouble) map2d->Uorder;
+ v[1] = (GLdouble) map2d->Vorder;
+ }
+ break;
+ case GL_DOMAIN:
+ if (map1d) {
+ v[0] = (GLdouble) map1d->u1;
+ v[1] = (GLdouble) map1d->u2;
+ }
+ else {
+ v[0] = (GLdouble) map2d->u1;
+ v[1] = (GLdouble) map2d->u2;
+ v[2] = (GLdouble) map2d->v1;
+ v[3] = (GLdouble) map2d->v2;
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_1d_map *map1d;
+ struct gl_2d_map *map2d;
+ GLint i, n;
+ GLfloat *data;
+ GLuint comps;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ comps = _mesa_evaluator_components(target);
+ if (!comps) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
+ return;
+ }
+
+ map1d = get_1d_map(ctx, target);
+ map2d = get_2d_map(ctx, target);
+ ASSERT(map1d || map2d);
+
+ switch (query) {
+ case GL_COEFF:
+ if (map1d) {
+ data = map1d->Points;
+ n = map1d->Order * comps;
+ }
+ else {
+ data = map2d->Points;
+ n = map2d->Uorder * map2d->Vorder * comps;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = data[i];
+ }
+ }
+ break;
+ case GL_ORDER:
+ if (map1d) {
+ v[0] = (GLfloat) map1d->Order;
+ }
+ else {
+ v[0] = (GLfloat) map2d->Uorder;
+ v[1] = (GLfloat) map2d->Vorder;
+ }
+ break;
+ case GL_DOMAIN:
+ if (map1d) {
+ v[0] = map1d->u1;
+ v[1] = map1d->u2;
+ }
+ else {
+ v[0] = map2d->u1;
+ v[1] = map2d->u2;
+ v[2] = map2d->v1;
+ v[3] = map2d->v2;
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_1d_map *map1d;
+ struct gl_2d_map *map2d;
+ GLuint i, n;
+ GLfloat *data;
+ GLuint comps;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ comps = _mesa_evaluator_components(target);
+ if (!comps) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
+ return;
+ }
+
+ map1d = get_1d_map(ctx, target);
+ map2d = get_2d_map(ctx, target);
+ ASSERT(map1d || map2d);
+
+ switch (query) {
+ case GL_COEFF:
+ if (map1d) {
+ data = map1d->Points;
+ n = map1d->Order * comps;
+ }
+ else {
+ data = map2d->Points;
+ n = map2d->Uorder * map2d->Vorder * comps;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = IROUND(data[i]);
+ }
+ }
+ break;
+ case GL_ORDER:
+ if (map1d) {
+ v[0] = map1d->Order;
+ }
+ else {
+ v[0] = map2d->Uorder;
+ v[1] = map2d->Vorder;
+ }
+ break;
+ case GL_DOMAIN:
+ if (map1d) {
+ v[0] = IROUND(map1d->u1);
+ v[1] = IROUND(map1d->u2);
+ }
+ else {
+ v[0] = IROUND(map2d->u1);
+ v[1] = IROUND(map2d->u2);
+ v[2] = IROUND(map2d->v1);
+ v[3] = IROUND(map2d->v2);
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (un<1) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
+ return;
+ }
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.MapGrid1un = un;
+ ctx->Eval.MapGrid1u1 = u1;
+ ctx->Eval.MapGrid1u2 = u2;
+ ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
+}
+
+
+void GLAPIENTRY
+_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
+{
+ _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
+}
+
+
+void GLAPIENTRY
+_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (un<1) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
+ return;
+ }
+ if (vn<1) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ 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 GLAPIENTRY
+_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2 )
+{
+ _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
+ vn, (GLfloat) v1, (GLfloat) v2 );
+}
+
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * 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];
+ }
+}
+
+
+/**
+ * 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];
+ }
+}
+
+
+void _mesa_init_eval( GLcontext *ctx )
+{
+ int i;
+
+ /* 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;
+ MEMSET(ctx->Eval.Map1Attrib, 0, sizeof(ctx->Eval.Map1Attrib));
+ 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;
+ MEMSET(ctx->Eval.Map2Attrib, 0, sizeof(ctx->Eval.Map2Attrib));
+ 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 };
+ static GLfloat attrib[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 );
+ for (i = 0; i < 16; i++)
+ init_1d_map( ctx->EvalMap.Map1Attrib + i, 4, attrib );
+
+ 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 );
+ for (i = 0; i < 16; i++)
+ init_2d_map( ctx->EvalMap.Map2Attrib + i, 4, attrib );
+ }
+}
+
+
+void _mesa_free_eval_data( GLcontext *ctx )
+{
+ int i;
+
+ /* 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 );
+ for (i = 0; i < 16; i++)
+ FREE((ctx->EvalMap.Map1Attrib[i].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 );
+ for (i = 0; i < 16; i++)
+ FREE((ctx->EvalMap.Map2Attrib[i].Points));
+}
diff --git a/mesalib/src/mesa/main/eval.h b/mesalib/src/mesa/main/eval.h
new file mode 100644
index 000000000..b3ff0a96f
--- /dev/null
+++ b/mesalib/src/mesa/main/eval.h
@@ -0,0 +1,128 @@
+/**
+ * \file eval.h
+ * Eval operations.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef EVAL_H
+#define EVAL_H
+
+
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void _mesa_init_eval( GLcontext *ctx );
+extern void _mesa_free_eval_data( GLcontext *ctx );
+
+
+extern GLuint _mesa_evaluator_components( GLenum target );
+
+
+extern void gl_free_control_points( GLcontext *ctx,
+ GLenum target, GLfloat *data );
+
+
+extern GLfloat *_mesa_copy_map_points1f( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLfloat *points );
+
+extern GLfloat *_mesa_copy_map_points1d( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLdouble *points );
+
+extern GLfloat *_mesa_copy_map_points2f( GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLfloat *points );
+
+extern GLfloat *_mesa_copy_map_points2d(GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLdouble *points );
+
+
+
+extern void GLAPIENTRY
+_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat *points );
+
+extern void GLAPIENTRY
+_mesa_Map2f( GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points );
+
+extern void GLAPIENTRY
+_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
+ GLint order, const GLdouble *points );
+
+extern void GLAPIENTRY
+_mesa_Map2d( GLenum target,
+ GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
+ const GLdouble *points );
+
+extern void GLAPIENTRY
+_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 );
+
+extern void GLAPIENTRY
+_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 );
+
+extern void GLAPIENTRY
+_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 );
+
+extern void GLAPIENTRY
+_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2 );
+
+extern void GLAPIENTRY
+_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v );
+
+extern void GLAPIENTRY
+_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v );
+
+extern void GLAPIENTRY
+_mesa_GetMapiv( GLenum target, GLenum query, GLint *v );
+
+#else
+
+/** No-op */
+#define _mesa_init_eval( c ) ((void)0)
+
+/** No-op */
+#define _mesa_free_eval_data( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/execmem.c b/mesalib/src/mesa/main/execmem.c
new file mode 100644
index 000000000..57c1e117c
--- /dev/null
+++ b/mesalib/src/mesa/main/execmem.c
@@ -0,0 +1,155 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+
+/**
+ * \file execmem.c
+ * Functions for allocating executable memory.
+ *
+ * \author Keith Whitwell
+ */
+
+
+#include "imports.h"
+#include "glapi/glthread.h"
+
+
+
+#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun)
+
+/*
+ * Allocate a large block of memory which can hold code then dole it out
+ * in pieces by means of the generic memory manager code.
+*/
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include "mm.h"
+
+#ifdef MESA_SELINUX
+#include <selinux/selinux.h>
+#endif
+
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+#define EXEC_HEAP_SIZE (10*1024*1024)
+
+_glthread_DECLARE_STATIC_MUTEX(exec_mutex);
+
+static struct mem_block *exec_heap = NULL;
+static unsigned char *exec_mem = NULL;
+
+
+static int
+init_heap(void)
+{
+#ifdef MESA_SELINUX
+ if (is_selinux_enabled()) {
+ if (!security_get_boolean_active("allow_execmem") ||
+ !security_get_boolean_pending("allow_execmem"))
+ return 0;
+ }
+#endif
+
+ if (!exec_heap)
+ exec_heap = mmInit( 0, EXEC_HEAP_SIZE );
+
+ if (!exec_mem)
+ exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ return (exec_mem != NULL);
+}
+
+
+void *
+_mesa_exec_malloc(GLuint size)
+{
+ struct mem_block *block = NULL;
+ void *addr = NULL;
+
+ _glthread_LOCK_MUTEX(exec_mutex);
+
+ if (!init_heap())
+ goto bail;
+
+ if (exec_heap) {
+ size = (size + 31) & ~31;
+ block = mmAllocMem( exec_heap, size, 32, 0 );
+ }
+
+ if (block)
+ addr = exec_mem + block->ofs;
+ else
+ _mesa_printf("_mesa_exec_malloc failed\n");
+
+bail:
+ _glthread_UNLOCK_MUTEX(exec_mutex);
+
+ return addr;
+}
+
+
+void
+_mesa_exec_free(void *addr)
+{
+ _glthread_LOCK_MUTEX(exec_mutex);
+
+ if (exec_heap) {
+ struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
+
+ if (block)
+ mmFreeMem(block);
+ }
+
+ _glthread_UNLOCK_MUTEX(exec_mutex);
+}
+
+
+#else
+
+/*
+ * Just use regular memory.
+ */
+
+void *
+_mesa_exec_malloc(GLuint size)
+{
+ return _mesa_malloc( size );
+}
+
+
+void
+_mesa_exec_free(void *addr)
+{
+ _mesa_free(addr);
+}
+
+
+#endif
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
new file mode 100644
index 000000000..e3070b154
--- /dev/null
+++ b/mesalib/src/mesa/main/extensions.c
@@ -0,0 +1,675 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "extensions.h"
+#include "simple_list.h"
+#include "mtypes.h"
+
+
+#define F(x) offsetof(struct gl_extensions, x)
+#define ON GL_TRUE
+#define OFF GL_FALSE
+
+
+/*
+ * Note: The GL_MESAX_* extensions are placeholders for future ARB extensions.
+ */
+static const struct {
+ GLboolean enabled;
+ const char *name;
+ int flag_offset;
+} default_extensions[] = {
+ { OFF, "GL_ARB_copy_buffer", F(ARB_copy_buffer) },
+ { OFF, "GL_ARB_depth_texture", F(ARB_depth_texture) },
+ { ON, "GL_ARB_draw_buffers", F(ARB_draw_buffers) },
+ { OFF, "GL_ARB_fragment_program", F(ARB_fragment_program) },
+ { OFF, "GL_ARB_fragment_program_shadow", F(ARB_fragment_program_shadow) },
+ { OFF, "GL_ARB_fragment_shader", F(ARB_fragment_shader) },
+ { OFF, "GL_ARB_framebuffer_object", F(ARB_framebuffer_object) },
+ { OFF, "GL_ARB_half_float_pixel", F(ARB_half_float_pixel) },
+ { OFF, "GL_ARB_imaging", F(ARB_imaging) },
+ { OFF, "GL_ARB_map_buffer_range", F(ARB_map_buffer_range) },
+ { ON, "GL_ARB_multisample", F(ARB_multisample) },
+ { OFF, "GL_ARB_multitexture", F(ARB_multitexture) },
+ { OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) },
+ { OFF, "GL_ARB_pixel_buffer_object", F(EXT_pixel_buffer_object) },
+ { OFF, "GL_ARB_point_parameters", F(EXT_point_parameters) },
+ { OFF, "GL_ARB_point_sprite", F(ARB_point_sprite) },
+ { OFF, "GL_ARB_seamless_cube_map", F(ARB_seamless_cube_map) },
+ { OFF, "GL_ARB_shader_objects", F(ARB_shader_objects) },
+ { OFF, "GL_ARB_shading_language_100", F(ARB_shading_language_100) },
+ { OFF, "GL_ARB_shading_language_120", F(ARB_shading_language_120) },
+ { OFF, "GL_ARB_shadow", F(ARB_shadow) },
+ { OFF, "GL_ARB_shadow_ambient", F(ARB_shadow_ambient) },
+ { OFF, "GL_ARB_sync", F(ARB_sync) },
+ { OFF, "GL_ARB_texture_border_clamp", F(ARB_texture_border_clamp) },
+ { ON, "GL_ARB_texture_compression", F(ARB_texture_compression) },
+ { OFF, "GL_ARB_texture_cube_map", F(ARB_texture_cube_map) },
+ { OFF, "GL_ARB_texture_env_add", F(EXT_texture_env_add) },
+ { OFF, "GL_ARB_texture_env_combine", F(ARB_texture_env_combine) },
+ { OFF, "GL_ARB_texture_env_crossbar", F(ARB_texture_env_crossbar) },
+ { OFF, "GL_ARB_texture_env_dot3", F(ARB_texture_env_dot3) },
+ { OFF, "GL_MESAX_texture_float", F(ARB_texture_float) },
+ { OFF, "GL_ARB_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)},
+ { OFF, "GL_ARB_texture_non_power_of_two", F(ARB_texture_non_power_of_two)},
+ { OFF, "GL_ARB_texture_rectangle", F(NV_texture_rectangle) },
+ { ON, "GL_ARB_transpose_matrix", F(ARB_transpose_matrix) },
+ { OFF, "GL_ARB_vertex_array_bgra", F(EXT_vertex_array_bgra) },
+ { OFF, "GL_ARB_vertex_array_object", F(ARB_vertex_array_object) },
+ { ON, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) },
+ { OFF, "GL_ARB_vertex_program", F(ARB_vertex_program) },
+ { OFF, "GL_ARB_vertex_shader", F(ARB_vertex_shader) },
+ { ON, "GL_ARB_window_pos", F(ARB_window_pos) },
+ { ON, "GL_EXT_abgr", F(EXT_abgr) },
+ { ON, "GL_EXT_bgra", F(EXT_bgra) },
+ { OFF, "GL_EXT_blend_color", F(EXT_blend_color) },
+ { OFF, "GL_EXT_blend_equation_separate", F(EXT_blend_equation_separate) },
+ { OFF, "GL_EXT_blend_func_separate", F(EXT_blend_func_separate) },
+ { OFF, "GL_EXT_blend_logic_op", F(EXT_blend_logic_op) },
+ { OFF, "GL_EXT_blend_minmax", F(EXT_blend_minmax) },
+ { OFF, "GL_EXT_blend_subtract", F(EXT_blend_subtract) },
+ { OFF, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) },
+ { OFF, "GL_EXT_cull_vertex", F(EXT_cull_vertex) },
+ { ON, "GL_EXT_compiled_vertex_array", F(EXT_compiled_vertex_array) },
+ { OFF, "GL_EXT_convolution", F(EXT_convolution) },
+ { ON, "GL_EXT_copy_texture", F(EXT_copy_texture) },
+ { OFF, "GL_EXT_depth_bounds_test", F(EXT_depth_bounds_test) },
+ { ON, "GL_EXT_draw_range_elements", F(EXT_draw_range_elements) },
+ { OFF, "GL_EXT_framebuffer_object", F(EXT_framebuffer_object) },
+ { OFF, "GL_EXT_framebuffer_blit", F(EXT_framebuffer_blit) },
+ { OFF, "GL_EXT_fog_coord", F(EXT_fog_coord) },
+ { OFF, "GL_EXT_gpu_program_parameters", F(EXT_gpu_program_parameters) },
+ { OFF, "GL_EXT_histogram", F(EXT_histogram) },
+ { ON, "GL_EXT_multi_draw_arrays", F(EXT_multi_draw_arrays) },
+ { OFF, "GL_EXT_packed_depth_stencil", F(EXT_packed_depth_stencil) },
+ { ON, "GL_EXT_packed_pixels", F(EXT_packed_pixels) },
+ { OFF, "GL_EXT_paletted_texture", F(EXT_paletted_texture) },
+ { OFF, "GL_EXT_pixel_buffer_object", F(EXT_pixel_buffer_object) },
+ { OFF, "GL_EXT_point_parameters", F(EXT_point_parameters) },
+ { ON, "GL_EXT_polygon_offset", F(EXT_polygon_offset) },
+ { OFF, "GL_EXT_provoking_vertex", F(EXT_provoking_vertex) },
+ { ON, "GL_EXT_rescale_normal", F(EXT_rescale_normal) },
+ { OFF, "GL_EXT_secondary_color", F(EXT_secondary_color) },
+ { ON, "GL_EXT_separate_specular_color", F(EXT_separate_specular_color) },
+ { OFF, "GL_EXT_shadow_funcs", F(EXT_shadow_funcs) },
+ { OFF, "GL_EXT_shared_texture_palette", F(EXT_shared_texture_palette) },
+ { OFF, "GL_EXT_stencil_two_side", F(EXT_stencil_two_side) },
+ { OFF, "GL_EXT_stencil_wrap", F(EXT_stencil_wrap) },
+ { ON, "GL_EXT_subtexture", F(EXT_subtexture) },
+ { ON, "GL_EXT_texture", F(EXT_texture) },
+ { ON, "GL_EXT_texture3D", F(EXT_texture3D) },
+ { OFF, "GL_EXT_texture_compression_s3tc", F(EXT_texture_compression_s3tc) },
+ { ON, "GL_EXT_texture_edge_clamp", F(SGIS_texture_edge_clamp) },
+ { OFF, "GL_EXT_texture_env_add", F(EXT_texture_env_add) },
+ { OFF, "GL_EXT_texture_env_combine", F(EXT_texture_env_combine) },
+ { OFF, "GL_EXT_texture_env_dot3", F(EXT_texture_env_dot3) },
+ { OFF, "GL_EXT_texture_filter_anisotropic", F(EXT_texture_filter_anisotropic) },
+ { OFF, "GL_EXT_texture_lod_bias", F(EXT_texture_lod_bias) },
+ { OFF, "GL_EXT_texture_mirror_clamp", F(EXT_texture_mirror_clamp) },
+ { ON, "GL_EXT_texture_object", F(EXT_texture_object) },
+ { OFF, "GL_EXT_texture_rectangle", F(NV_texture_rectangle) },
+ { OFF, "GL_EXT_texture_sRGB", F(EXT_texture_sRGB) },
+ { OFF, "GL_EXT_texture_swizzle", F(EXT_texture_swizzle) },
+ { OFF, "GL_EXT_timer_query", F(EXT_timer_query) },
+ { ON, "GL_EXT_vertex_array", F(EXT_vertex_array) },
+ { OFF, "GL_EXT_vertex_array_bgra", F(EXT_vertex_array_bgra) },
+ { OFF, "GL_EXT_vertex_array_set", F(EXT_vertex_array_set) },
+ { OFF, "GL_3DFX_texture_compression_FXT1", F(TDFX_texture_compression_FXT1) },
+ { OFF, "GL_APPLE_client_storage", F(APPLE_client_storage) },
+ { ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) },
+ { OFF, "GL_APPLE_vertex_array_object", F(APPLE_vertex_array_object) },
+ { OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) },
+ { OFF, "GL_ATI_envmap_bumpmap", F(ATI_envmap_bumpmap) },
+ { OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)},
+ { OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)},
+ { OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)},
+ { OFF, "GL_ATI_separate_stencil", F(ATI_separate_stencil)},
+ { ON, "GL_IBM_multimode_draw_arrays", F(IBM_multimode_draw_arrays) },
+ { ON, "GL_IBM_rasterpos_clip", F(IBM_rasterpos_clip) },
+ { OFF, "GL_IBM_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)},
+ { OFF, "GL_INGR_blend_func_separate", F(EXT_blend_func_separate) },
+ { OFF, "GL_MESA_pack_invert", F(MESA_pack_invert) },
+ { OFF, "GL_MESA_packed_depth_stencil", F(MESA_packed_depth_stencil) },
+ { OFF, "GL_MESA_resize_buffers", F(MESA_resize_buffers) },
+ { OFF, "GL_MESA_texture_array", F(MESA_texture_array) },
+ { OFF, "GL_MESA_texture_signed_rgba", F(MESA_texture_signed_rgba) },
+ { OFF, "GL_MESA_ycbcr_texture", F(MESA_ycbcr_texture) },
+ { ON, "GL_MESA_window_pos", F(ARB_window_pos) },
+ { OFF, "GL_NV_blend_square", F(NV_blend_square) },
+ { OFF, "GL_NV_fragment_program", F(NV_fragment_program) },
+ { ON, "GL_NV_light_max_exponent", F(NV_light_max_exponent) },
+ { OFF, "GL_NV_point_sprite", F(NV_point_sprite) },
+ { OFF, "GL_NV_texture_env_combine4", F(NV_texture_env_combine4) },
+ { OFF, "GL_NV_texture_rectangle", F(NV_texture_rectangle) },
+ { ON, "GL_NV_texgen_reflection", F(NV_texgen_reflection) },
+ { OFF, "GL_NV_vertex_program", F(NV_vertex_program) },
+ { OFF, "GL_NV_vertex_program1_1", F(NV_vertex_program1_1) },
+ { ON, "GL_OES_read_format", F(OES_read_format) },
+ { OFF, "GL_SGI_color_matrix", F(SGI_color_matrix) },
+ { OFF, "GL_SGI_color_table", F(SGI_color_table) },
+ { OFF, "GL_SGI_texture_color_table", F(SGI_texture_color_table) },
+ { OFF, "GL_SGIS_generate_mipmap", F(SGIS_generate_mipmap) },
+ { OFF, "GL_SGIS_texture_border_clamp", F(ARB_texture_border_clamp) },
+ { ON, "GL_SGIS_texture_edge_clamp", F(SGIS_texture_edge_clamp) },
+ { ON, "GL_SGIS_texture_lod", F(SGIS_texture_lod) },
+ { ON, "GL_SUN_multi_draw_arrays", F(EXT_multi_draw_arrays) },
+ { OFF, "GL_S3_s3tc", F(S3_s3tc) },
+};
+
+
+
+/**
+ * Enable all extensions suitable for a software-only renderer.
+ * This is a convenience function used by the XMesa, OSMesa, GGI drivers, etc.
+ */
+void
+_mesa_enable_sw_extensions(GLcontext *ctx)
+{
+ ctx->Extensions.ARB_copy_buffer = GL_TRUE;
+ ctx->Extensions.ARB_depth_texture = GL_TRUE;
+ /*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
+#if FEATURE_ARB_fragment_program
+ ctx->Extensions.ARB_fragment_program = GL_TRUE;
+ ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE;
+#endif
+#if FEATURE_ARB_fragment_shader
+ ctx->Extensions.ARB_fragment_shader = GL_TRUE;
+#endif
+#if FEATURE_ARB_framebuffer_object
+ ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
+#endif
+ ctx->Extensions.ARB_half_float_pixel = GL_TRUE;
+ ctx->Extensions.ARB_imaging = GL_TRUE;
+ ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
+ ctx->Extensions.ARB_multitexture = GL_TRUE;
+#if FEATURE_ARB_occlusion_query
+ ctx->Extensions.ARB_occlusion_query = GL_TRUE;
+#endif
+ ctx->Extensions.ARB_point_sprite = GL_TRUE;
+#if FEATURE_ARB_shader_objects
+ ctx->Extensions.ARB_shader_objects = GL_TRUE;
+#endif
+#if FEATURE_ARB_shading_language_100
+ ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
+#endif
+#if FEATURE_ARB_shading_language_120
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
+#endif
+ ctx->Extensions.ARB_shadow = GL_TRUE;
+ ctx->Extensions.ARB_shadow_ambient = GL_TRUE;
+ ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
+ ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
+ /*ctx->Extensions.ARB_texture_float = GL_TRUE;*/
+ ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
+ ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
+ ctx->Extensions.ARB_vertex_array_object = GL_TRUE;
+#if FEATURE_ARB_vertex_program
+ ctx->Extensions.ARB_vertex_program = GL_TRUE;
+#endif
+#if FEATURE_ARB_vertex_shader
+ ctx->Extensions.ARB_vertex_shader = GL_TRUE;
+#endif
+#if FEATURE_ARB_vertex_buffer_object
+ /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
+#endif
+#if FEATURE_ARB_sync
+ ctx->Extensions.ARB_sync = GL_TRUE;
+#endif
+ ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
+ ctx->Extensions.ATI_envmap_bumpmap = GL_TRUE;
+#if FEATURE_ATI_fragment_shader
+ ctx->Extensions.ATI_fragment_shader = GL_TRUE;
+#endif
+ ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
+ ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
+ ctx->Extensions.ATI_separate_stencil = GL_TRUE;
+ ctx->Extensions.EXT_blend_color = GL_TRUE;
+ ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
+ ctx->Extensions.EXT_blend_minmax = GL_TRUE;
+ ctx->Extensions.EXT_blend_subtract = GL_TRUE;
+ ctx->Extensions.EXT_convolution = GL_TRUE;
+ ctx->Extensions.EXT_depth_bounds_test = GL_TRUE;
+ ctx->Extensions.EXT_fog_coord = GL_TRUE;
+#if FEATURE_EXT_framebuffer_object
+ ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
+#endif
+#if FEATURE_EXT_framebuffer_blit
+ ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
+#endif
+ ctx->Extensions.EXT_histogram = GL_TRUE;
+ /*ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;*/
+ ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
+ ctx->Extensions.EXT_paletted_texture = GL_TRUE;
+#if FEATURE_EXT_pixel_buffer_object
+ ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
+#endif
+ ctx->Extensions.EXT_point_parameters = GL_TRUE;
+ ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
+ ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
+ ctx->Extensions.EXT_secondary_color = GL_TRUE;
+ ctx->Extensions.EXT_shared_texture_palette = GL_TRUE;
+ ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_add = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
+ ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
+#if FEATURE_EXT_texture_sRGB
+ ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
+#endif
+ ctx->Extensions.EXT_texture_swizzle = GL_TRUE;
+ ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
+ /*ctx->Extensions.IBM_multimode_draw_arrays = GL_TRUE;*/
+ ctx->Extensions.MESA_pack_invert = GL_TRUE;
+ ctx->Extensions.MESA_resize_buffers = GL_TRUE;
+ ctx->Extensions.MESA_texture_array = GL_TRUE;
+ ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
+ ctx->Extensions.NV_blend_square = GL_TRUE;
+ /*ctx->Extensions.NV_light_max_exponent = GL_TRUE;*/
+ ctx->Extensions.NV_point_sprite = GL_TRUE;
+ ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
+ ctx->Extensions.NV_texture_rectangle = GL_TRUE;
+ /*ctx->Extensions.NV_texgen_reflection = GL_TRUE;*/
+#if FEATURE_NV_vertex_program
+ ctx->Extensions.NV_vertex_program = GL_TRUE;
+ ctx->Extensions.NV_vertex_program1_1 = GL_TRUE;
+#endif
+#if FEATURE_NV_fragment_program
+ ctx->Extensions.NV_fragment_program = GL_TRUE;
+#endif
+ ctx->Extensions.SGI_color_matrix = GL_TRUE;
+ ctx->Extensions.SGI_color_table = GL_TRUE;
+ ctx->Extensions.SGI_texture_color_table = GL_TRUE;
+ ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
+ ctx->Extensions.SGIS_texture_edge_clamp = GL_TRUE;
+#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
+ ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
+#endif
+#if FEATURE_texture_fxt1
+ _mesa_enable_extension(ctx, "GL_3DFX_texture_compression_FXT1");
+#endif
+#if FEATURE_texture_s3tc
+ if (ctx->Mesa_DXTn) {
+ _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+ _mesa_enable_extension(ctx, "GL_S3_s3tc");
+ }
+#endif
+}
+
+
+/**
+ * Enable GL_ARB_imaging and all the EXT extensions that are subsets of it.
+ */
+void
+_mesa_enable_imaging_extensions(GLcontext *ctx)
+{
+ ctx->Extensions.ARB_imaging = GL_TRUE;
+ ctx->Extensions.EXT_blend_color = GL_TRUE;
+ ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
+ ctx->Extensions.EXT_blend_minmax = GL_TRUE;
+ ctx->Extensions.EXT_blend_subtract = GL_TRUE;
+ ctx->Extensions.EXT_convolution = GL_TRUE;
+ ctx->Extensions.EXT_histogram = GL_TRUE;
+ ctx->Extensions.SGI_color_matrix = GL_TRUE;
+ ctx->Extensions.SGI_color_table = GL_TRUE;
+}
+
+
+
+/**
+ * Enable all OpenGL 1.3 features and extensions.
+ * A convenience function to be called by drivers.
+ */
+void
+_mesa_enable_1_3_extensions(GLcontext *ctx)
+{
+ /*ctx->Extensions.ARB_multisample = GL_TRUE;*/
+ ctx->Extensions.ARB_multitexture = GL_TRUE;
+ ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
+ /*ctx->Extensions.ARB_texture_compression = GL_TRUE;*/
+ ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
+ ctx->Extensions.EXT_texture_env_add = GL_TRUE;
+ /*ctx->Extensions.ARB_transpose_matrix = GL_TRUE;*/
+}
+
+
+
+/**
+ * Enable all OpenGL 1.4 features and extensions.
+ * A convenience function to be called by drivers.
+ */
+void
+_mesa_enable_1_4_extensions(GLcontext *ctx)
+{
+ ctx->Extensions.ARB_depth_texture = GL_TRUE;
+ ctx->Extensions.ARB_shadow = GL_TRUE;
+ ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
+ ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
+ ctx->Extensions.ARB_window_pos = GL_TRUE;
+ ctx->Extensions.EXT_blend_color = GL_TRUE;
+ ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
+ ctx->Extensions.EXT_blend_minmax = GL_TRUE;
+ ctx->Extensions.EXT_blend_subtract = GL_TRUE;
+ ctx->Extensions.EXT_fog_coord = GL_TRUE;
+ /*ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;*/
+ ctx->Extensions.EXT_point_parameters = GL_TRUE;
+ ctx->Extensions.EXT_secondary_color = GL_TRUE;
+ ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
+ ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
+ ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
+}
+
+
+/**
+ * Enable all OpenGL 1.5 features and extensions.
+ * A convenience function to be called by drivers.
+ */
+void
+_mesa_enable_1_5_extensions(GLcontext *ctx)
+{
+ ctx->Extensions.ARB_occlusion_query = GL_TRUE;
+ /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
+ ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
+}
+
+
+/**
+ * Enable all OpenGL 2.0 features and extensions.
+ * A convenience function to be called by drivers.
+ */
+void
+_mesa_enable_2_0_extensions(GLcontext *ctx)
+{
+ /*ctx->Extensions.ARB_draw_buffers = GL_TRUE;*/
+#if FEATURE_ARB_fragment_shader
+ ctx->Extensions.ARB_fragment_shader = GL_TRUE;
+#endif
+ ctx->Extensions.ARB_point_sprite = GL_TRUE;
+ ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
+ ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
+#if FEATURE_ARB_shader_objects
+ ctx->Extensions.ARB_shader_objects = GL_TRUE;
+#endif
+#if FEATURE_ARB_shading_language_100
+ ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
+#endif
+ ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
+#if FEATURE_ARB_vertex_shader
+ ctx->Extensions.ARB_vertex_shader = GL_TRUE;
+#endif
+}
+
+
+/**
+ * Enable all OpenGL 2.1 features and extensions.
+ * A convenience function to be called by drivers.
+ */
+void
+_mesa_enable_2_1_extensions(GLcontext *ctx)
+{
+#if FEATURE_EXT_pixel_buffer_object
+ ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
+#endif
+#if FEATURE_EXT_texture_sRGB
+ ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
+#endif
+#ifdef FEATURE_ARB_shading_language_120
+ ctx->Extensions.ARB_shading_language_120 = GL_TRUE;
+#endif
+}
+
+
+
+/**
+ * Either enable or disable the named extension.
+ * \return GL_TRUE for success, GL_FALSE if invalid extension name
+ */
+static GLboolean
+set_extension( GLcontext *ctx, const char *name, GLboolean state )
+{
+ GLboolean *base = (GLboolean *) &ctx->Extensions;
+ GLuint i;
+
+ if (ctx->Extensions.String) {
+ /* The string was already queried - can't change it now! */
+ _mesa_problem(ctx, "Trying to enable/disable extension after glGetString(GL_EXTENSIONS): %s", name);
+ return GL_FALSE;
+ }
+
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ if (_mesa_strcmp(default_extensions[i].name, name) == 0) {
+ if (default_extensions[i].flag_offset) {
+ GLboolean *enabled = base + default_extensions[i].flag_offset;
+ *enabled = state;
+ }
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Enable the named extension.
+ * Typically called by drivers.
+ */
+void
+_mesa_enable_extension( GLcontext *ctx, const char *name )
+{
+ if (!set_extension(ctx, name, GL_TRUE))
+ _mesa_problem(ctx, "Trying to enable unknown extension: %s", name);
+}
+
+
+/**
+ * Disable the named extension.
+ * XXX is this really needed???
+ */
+void
+_mesa_disable_extension( GLcontext *ctx, const char *name )
+{
+ if (!set_extension(ctx, name, GL_FALSE))
+ _mesa_problem(ctx, "Trying to disable unknown extension: %s", name);
+}
+
+
+/**
+ * Test if the named extension is enabled in this context.
+ */
+GLboolean
+_mesa_extension_is_enabled( GLcontext *ctx, const char *name )
+{
+ const GLboolean *base = (const GLboolean *) &ctx->Extensions;
+ GLuint i;
+
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ if (_mesa_strcmp(default_extensions[i].name, name) == 0) {
+ if (!default_extensions[i].flag_offset)
+ return GL_TRUE;
+ return *(base + default_extensions[i].flag_offset);
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Append string 'b' onto string 'a'. Free 'a' and return new string.
+ */
+static char *
+append(const char *a, const char *b)
+{
+ const GLuint aLen = a ? _mesa_strlen(a) : 0;
+ const GLuint bLen = b ? _mesa_strlen(b) : 0;
+ char *s = _mesa_calloc(aLen + bLen + 1);
+ if (s) {
+ if (a)
+ _mesa_memcpy(s, a, aLen);
+ if (b)
+ _mesa_memcpy(s + aLen, b, bLen);
+ s[aLen + bLen] = '\0';
+ }
+ if (a)
+ _mesa_free((void *) a);
+ return s;
+}
+
+
+/**
+ * Check the MESA_EXTENSION_OVERRIDE env var.
+ * For extension names that are recognized, turn them on. For extension
+ * names that are recognized and prefixed with '-', turn them off.
+ * Return a string of the unknown/leftover names.
+ */
+static const char *
+get_extension_override( GLcontext *ctx )
+{
+ const char *envExt = _mesa_getenv("MESA_EXTENSION_OVERRIDE");
+ char *extraExt = NULL;
+ char ext[1000];
+ GLuint extLen = 0;
+ GLuint i;
+ GLboolean disableExt = GL_FALSE;
+
+ if (!envExt)
+ return NULL;
+
+ for (i = 0; ; i++) {
+ if (envExt[i] == '\0' || envExt[i] == ' ') {
+ /* terminate/process 'ext' if extLen > 0 */
+ if (extLen > 0) {
+ assert(extLen < sizeof(ext));
+ /* enable extension named by 'ext' */
+ ext[extLen] = 0;
+ if (!set_extension(ctx, ext, !disableExt)) {
+ /* unknown extension name, append it to extraExt */
+ if (extraExt) {
+ extraExt = append(extraExt, " ");
+ }
+ extraExt = append(extraExt, ext);
+ }
+ extLen = 0;
+ disableExt = GL_FALSE;
+ }
+ if (envExt[i] == '\0')
+ break;
+ }
+ else if (envExt[i] == '-') {
+ disableExt = GL_TRUE;
+ }
+ else {
+ /* accumulate this non-space character */
+ ext[extLen++] = envExt[i];
+ }
+ }
+
+ return extraExt;
+}
+
+
+/**
+ * Run through the default_extensions array above and set the
+ * ctx->Extensions.ARB/EXT_* flags accordingly.
+ * To be called during context initialization.
+ */
+void
+_mesa_init_extensions( GLcontext *ctx )
+{
+ GLboolean *base = (GLboolean *) &ctx->Extensions;
+ GLuint i;
+
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ if (default_extensions[i].enabled &&
+ default_extensions[i].flag_offset) {
+ *(base + default_extensions[i].flag_offset) = GL_TRUE;
+ }
+ }
+}
+
+
+/**
+ * Construct the GL_EXTENSIONS string. Called the first time that
+ * glGetString(GL_EXTENSIONS) is called.
+ */
+GLubyte *
+_mesa_make_extension_string( GLcontext *ctx )
+{
+ const GLboolean *base = (const GLboolean *) &ctx->Extensions;
+ const char *extraExt = get_extension_override(ctx);
+ GLuint extStrLen = 0;
+ char *s;
+ GLuint i;
+
+ /* first, compute length of the extension string */
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ if (!default_extensions[i].flag_offset ||
+ *(base + default_extensions[i].flag_offset)) {
+ extStrLen += (GLuint)_mesa_strlen(default_extensions[i].name) + 1;
+ }
+ }
+
+ if (extraExt)
+ extStrLen += _mesa_strlen(extraExt) + 1; /* +1 for space */
+
+ /* allocate the extension string */
+ s = (char *) _mesa_malloc(extStrLen);
+ if (!s)
+ return NULL;
+
+ /* second, build the extension string */
+ extStrLen = 0;
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ if (!default_extensions[i].flag_offset ||
+ *(base + default_extensions[i].flag_offset)) {
+ GLuint len = (GLuint)_mesa_strlen(default_extensions[i].name);
+ _mesa_memcpy(s + extStrLen, default_extensions[i].name, len);
+ extStrLen += len;
+ s[extStrLen] = ' ';
+ extStrLen++;
+ }
+ }
+ ASSERT(extStrLen > 0);
+
+ s[extStrLen - 1] = 0; /* -1 to overwrite trailing the ' ' */
+
+ if (extraExt) {
+ s = append(s, " ");
+ s = append(s, extraExt);
+ }
+
+ return (GLubyte *) s;
+}
diff --git a/mesalib/src/mesa/main/extensions.h b/mesalib/src/mesa/main/extensions.h
new file mode 100644
index 000000000..05ad859a2
--- /dev/null
+++ b/mesalib/src/mesa/main/extensions.h
@@ -0,0 +1,86 @@
+/**
+ * \file extensions.h
+ * Extension handling.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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_
+
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void _mesa_enable_sw_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_1_3_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_1_4_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_1_5_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_2_0_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_2_1_extensions(GLcontext *ctx);
+
+extern void _mesa_enable_extension(GLcontext *ctx, const char *name);
+
+extern void _mesa_disable_extension(GLcontext *ctx, const char *name);
+
+extern GLboolean _mesa_extension_is_enabled(GLcontext *ctx, const char *name);
+
+extern void _mesa_init_extensions(GLcontext *ctx);
+
+extern GLubyte *_mesa_make_extension_string(GLcontext *ctx);
+
+#else
+
+/** No-op */
+#define _mesa_extensions_dtr( ctx ) ((void)0)
+
+/** No-op */
+#define _mesa_extensions_ctr( ctx ) ((void)0)
+
+/** No-op */
+#define _mesa_extensions_get_string( ctx ) "GL_EXT_texture_object"
+
+/** No-op */
+#define _mesa_enable_imaging_extensions( c ) ((void)0)
+
+/** No-op */
+#define _mesa_enable_extension( c, n ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
new file mode 100644
index 000000000..825a23090
--- /dev/null
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -0,0 +1,2103 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/*
+ * GL_EXT/ARB_framebuffer_object extensions
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#include "buffers.h"
+#include "context.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "hash.h"
+#include "macros.h"
+#include "mipmap.h"
+#include "renderbuffer.h"
+#include "state.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "texstore.h"
+
+
+/**
+ * Notes:
+ *
+ * None of the GL_EXT_framebuffer_object functions are compiled into
+ * display lists.
+ */
+
+
+
+/*
+ * When glGenRender/FramebuffersEXT() is called we insert pointers to
+ * these placeholder objects into the hash table.
+ * Later, when the object ID is first bound, we replace the placeholder
+ * with the real frame/renderbuffer.
+ */
+static struct gl_framebuffer DummyFramebuffer;
+static struct gl_renderbuffer DummyRenderbuffer;
+
+
+#define IS_CUBE_FACE(TARGET) \
+ ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
+ (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+
+
+static void
+delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
+{
+ /* no op */
+}
+
+static void
+delete_dummy_framebuffer(struct gl_framebuffer *fb)
+{
+ /* no op */
+}
+
+
+void
+_mesa_init_fbobjects(GLcontext *ctx)
+{
+ DummyFramebuffer.Delete = delete_dummy_framebuffer;
+ DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
+}
+
+
+/**
+ * Helper routine for getting a gl_renderbuffer.
+ */
+struct gl_renderbuffer *
+_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id)
+{
+ struct gl_renderbuffer *rb;
+
+ if (id == 0)
+ return NULL;
+
+ rb = (struct gl_renderbuffer *)
+ _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
+ return rb;
+}
+
+
+/**
+ * Helper routine for getting a gl_framebuffer.
+ */
+struct gl_framebuffer *
+_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id)
+{
+ struct gl_framebuffer *fb;
+
+ if (id == 0)
+ return NULL;
+
+ fb = (struct gl_framebuffer *)
+ _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
+ return fb;
+}
+
+
+/**
+ * Mark the given framebuffer as invalid. This will force the
+ * test for framebuffer completeness to be done before the framebuffer
+ * is used.
+ */
+static void
+invalidate_framebuffer(struct gl_framebuffer *fb)
+{
+ fb->_Status = 0; /* "indeterminate" */
+}
+
+
+/**
+ * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
+ * gl_renderbuffer_attachment object.
+ * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
+ * the depth buffer attachment point.
+ */
+struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment)
+{
+ GLuint i;
+
+ switch (attachment) {
+ case GL_COLOR_ATTACHMENT0_EXT:
+ case GL_COLOR_ATTACHMENT1_EXT:
+ case GL_COLOR_ATTACHMENT2_EXT:
+ case GL_COLOR_ATTACHMENT3_EXT:
+ case GL_COLOR_ATTACHMENT4_EXT:
+ case GL_COLOR_ATTACHMENT5_EXT:
+ case GL_COLOR_ATTACHMENT6_EXT:
+ case GL_COLOR_ATTACHMENT7_EXT:
+ case GL_COLOR_ATTACHMENT8_EXT:
+ case GL_COLOR_ATTACHMENT9_EXT:
+ case GL_COLOR_ATTACHMENT10_EXT:
+ case GL_COLOR_ATTACHMENT11_EXT:
+ case GL_COLOR_ATTACHMENT12_EXT:
+ case GL_COLOR_ATTACHMENT13_EXT:
+ case GL_COLOR_ATTACHMENT14_EXT:
+ case GL_COLOR_ATTACHMENT15_EXT:
+ i = attachment - GL_COLOR_ATTACHMENT0_EXT;
+ if (i >= ctx->Const.MaxColorAttachments) {
+ return NULL;
+ }
+ return &fb->Attachment[BUFFER_COLOR0 + i];
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ /* fall-through */
+ case GL_DEPTH_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_DEPTH];
+ case GL_STENCIL_ATTACHMENT_EXT:
+ return &fb->Attachment[BUFFER_STENCIL];
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Remove any texture or renderbuffer attached to the given attachment
+ * point. Update reference counts, etc.
+ */
+void
+_mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
+{
+ if (att->Type == GL_TEXTURE) {
+ ASSERT(att->Texture);
+ if (ctx->Driver.FinishRenderTexture) {
+ /* tell driver that we're done rendering to this texture. */
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ }
+ _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
+ ASSERT(!att->Texture);
+ }
+ if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
+ ASSERT(!att->Texture);
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
+ ASSERT(!att->Renderbuffer);
+ }
+ att->Type = GL_NONE;
+ att->Complete = GL_TRUE;
+}
+
+
+/**
+ * Bind a texture object to an attachment point.
+ * The previous binding, if any, will be removed first.
+ */
+void
+_mesa_set_texture_attachment(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_texture_object *texObj,
+ GLenum texTarget, GLuint level, GLuint zoffset)
+{
+ if (att->Texture == texObj) {
+ /* re-attaching same texture */
+ ASSERT(att->Type == GL_TEXTURE);
+ }
+ else {
+ /* new attachment */
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_TEXTURE;
+ assert(!att->Texture);
+ _mesa_reference_texobj(&att->Texture, texObj);
+ }
+
+ /* always update these fields */
+ att->TextureLevel = level;
+ if (IS_CUBE_FACE(texTarget)) {
+ att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ }
+ else {
+ att->CubeMapFace = 0;
+ }
+ att->Zoffset = zoffset;
+ att->Complete = GL_FALSE;
+
+ if (att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
+ ctx->Driver.RenderTexture(ctx, fb, att);
+ }
+
+ invalidate_framebuffer(fb);
+}
+
+
+/**
+ * Bind a renderbuffer to an attachment point.
+ * The previous binding, if any, will be removed first.
+ */
+void
+_mesa_set_renderbuffer_attachment(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_renderbuffer *rb)
+{
+ /* XXX check if re-doing same attachment, exit early */
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_RENDERBUFFER_EXT;
+ att->Texture = NULL; /* just to be safe */
+ att->Complete = GL_FALSE;
+ _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
+}
+
+
+/**
+ * Fallback for ctx->Driver.FramebufferRenderbuffer()
+ * Attach a renderbuffer object to a framebuffer object.
+ */
+void
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment, struct gl_renderbuffer *rb)
+{
+ struct gl_renderbuffer_attachment *att;
+
+ _glthread_LOCK_MUTEX(fb->Mutex);
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ ASSERT(att);
+ if (rb) {
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* do stencil attachment here (depth already done above) */
+ att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
+ assert(att);
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ }
+ }
+ else {
+ _mesa_remove_attachment(ctx, att);
+ }
+
+ invalidate_framebuffer(fb);
+
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+}
+
+
+/**
+ * For debug only.
+ */
+static void
+att_incomplete(const char *msg)
+{
+#if 0
+ _mesa_printf("attachment incomplete: %s\n", msg);
+#else
+ (void) msg;
+#endif
+}
+
+
+/**
+ * Test if an attachment point is complete and update its Complete field.
+ * \param format if GL_COLOR, this is a color attachment point,
+ * if GL_DEPTH, this is a depth component attachment point,
+ * if GL_STENCIL, this is a stencil component attachment point.
+ */
+static void
+test_attachment_completeness(const GLcontext *ctx, GLenum format,
+ struct gl_renderbuffer_attachment *att)
+{
+ assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
+
+ /* assume complete */
+ att->Complete = GL_TRUE;
+
+ /* Look for reasons why the attachment might be incomplete */
+ if (att->Type == GL_TEXTURE) {
+ const struct gl_texture_object *texObj = att->Texture;
+ struct gl_texture_image *texImage;
+
+ if (!texObj) {
+ att_incomplete("no texobj");
+ att->Complete = GL_FALSE;
+ return;
+ }
+
+ texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
+ if (!texImage) {
+ att_incomplete("no teximage");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texImage->Width < 1 || texImage->Height < 1) {
+ att_incomplete("teximage width/height=0");
+ _mesa_printf("texobj = %u\n", texObj->Name);
+ _mesa_printf("level = %d\n", att->TextureLevel);
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
+ att_incomplete("bad z offset");
+ att->Complete = GL_FALSE;
+ return;
+ }
+
+ if (format == GL_COLOR) {
+ if (texImage->TexFormat->BaseFormat != GL_RGB &&
+ texImage->TexFormat->BaseFormat != GL_RGBA) {
+ att_incomplete("bad format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (texImage->TexFormat->TexelBytes == 0) {
+ att_incomplete("compressed internalformat");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ else if (format == GL_DEPTH) {
+ if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
+ texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ att->Complete = GL_FALSE;
+ att_incomplete("bad depth format");
+ return;
+ }
+ }
+ else {
+ ASSERT(format == GL_STENCIL);
+ ASSERT(att->Renderbuffer->StencilBits);
+ if (ctx->Extensions.EXT_packed_depth_stencil &&
+ ctx->Extensions.ARB_depth_texture &&
+ att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* OK */
+ }
+ else {
+ /* no such thing as stencil-only textures */
+ att_incomplete("illegal stencil texture");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ }
+ else if (att->Type == GL_RENDERBUFFER_EXT) {
+ ASSERT(att->Renderbuffer);
+ if (!att->Renderbuffer->InternalFormat ||
+ att->Renderbuffer->Width < 1 ||
+ att->Renderbuffer->Height < 1) {
+ att_incomplete("0x0 renderbuffer");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ if (format == GL_COLOR) {
+ if (att->Renderbuffer->_BaseFormat != GL_RGB &&
+ att->Renderbuffer->_BaseFormat != GL_RGBA) {
+ att_incomplete("bad renderbuffer color format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ ASSERT(att->Renderbuffer->RedBits);
+ ASSERT(att->Renderbuffer->GreenBits);
+ ASSERT(att->Renderbuffer->BlueBits);
+ }
+ else if (format == GL_DEPTH) {
+ if (att->Renderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
+ ASSERT(att->Renderbuffer->DepthBits);
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ ASSERT(att->Renderbuffer->DepthBits);
+ /* OK */
+ }
+ else {
+ att_incomplete("bad renderbuffer depth format");
+ att->Complete = GL_FALSE;
+ return;
+ }
+ }
+ else {
+ assert(format == GL_STENCIL);
+ if (att->Renderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
+ ASSERT(att->Renderbuffer->StencilBits);
+ /* OK */
+ }
+ else if (ctx->Extensions.EXT_packed_depth_stencil &&
+ att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ ASSERT(att->Renderbuffer->StencilBits);
+ /* OK */
+ }
+ else {
+ att->Complete = GL_FALSE;
+ att_incomplete("bad renderbuffer stencil format");
+ return;
+ }
+ }
+ }
+ else {
+ ASSERT(att->Type == GL_NONE);
+ /* complete */
+ return;
+ }
+}
+
+
+/**
+ * Helpful for debugging
+ */
+static void
+fbo_incomplete(const char *msg, int index)
+{
+ (void) msg;
+ (void) index;
+ /*
+ _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
+ */
+}
+
+
+/**
+ * Test if the given framebuffer object is complete and update its
+ * Status field with the results.
+ * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
+ * driver to make hardware-specific validation/completeness checks.
+ * Also update the framebuffer's Width and Height fields if the
+ * framebuffer is complete.
+ */
+void
+_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ GLuint numImages;
+ GLenum intFormat = GL_NONE; /* color buffers' internal format */
+ GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
+ GLint numSamples = -1;
+ GLint i;
+ GLuint j;
+
+ assert(fb->Name != 0);
+
+ numImages = 0;
+ fb->Width = 0;
+ fb->Height = 0;
+
+ /* Start at -2 to more easily loop over all attachment points.
+ * -2: depth buffer
+ * -1: stencil buffer
+ * >=0: color buffer
+ */
+ for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
+ struct gl_renderbuffer_attachment *att;
+ GLenum f;
+
+ /*
+ * XXX for ARB_fbo, only check color buffers that are named by
+ * GL_READ_BUFFER and GL_DRAW_BUFFERi.
+ */
+
+ /* check for attachment completeness
+ */
+ if (i == -2) {
+ att = &fb->Attachment[BUFFER_DEPTH];
+ test_attachment_completeness(ctx, GL_DEPTH, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("depth attachment incomplete", -1);
+ return;
+ }
+ }
+ else if (i == -1) {
+ att = &fb->Attachment[BUFFER_STENCIL];
+ test_attachment_completeness(ctx, GL_STENCIL, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("stencil attachment incomplete", -1);
+ return;
+ }
+ }
+ else {
+ att = &fb->Attachment[BUFFER_COLOR0 + i];
+ test_attachment_completeness(ctx, GL_COLOR, att);
+ if (!att->Complete) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fbo_incomplete("color attachment incomplete", i);
+ return;
+ }
+ }
+
+ /* get width, height, format of the renderbuffer/texture
+ */
+ if (att->Type == GL_TEXTURE) {
+ const struct gl_texture_image *texImg
+ = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ minWidth = MIN2(minWidth, texImg->Width);
+ maxWidth = MAX2(maxWidth, texImg->Width);
+ minHeight = MIN2(minHeight, texImg->Height);
+ maxHeight = MAX2(maxHeight, texImg->Height);
+ f = texImg->_BaseFormat;
+ numImages++;
+ if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT
+ && f != GL_DEPTH_STENCIL_EXT) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ fbo_incomplete("texture attachment incomplete", -1);
+ return;
+ }
+ }
+ else if (att->Type == GL_RENDERBUFFER_EXT) {
+ minWidth = MIN2(minWidth, att->Renderbuffer->Width);
+ maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
+ minHeight = MIN2(minHeight, att->Renderbuffer->Height);
+ maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
+ f = att->Renderbuffer->InternalFormat;
+ numImages++;
+ }
+ else {
+ assert(att->Type == GL_NONE);
+ continue;
+ }
+
+ if (numSamples < 0) {
+ /* first buffer */
+ numSamples = att->Renderbuffer->NumSamples;
+ }
+
+ /* Error-check width, height, format, samples
+ */
+ if (numImages == 1) {
+ /* save format, num samples */
+ if (i >= 0) {
+ intFormat = f;
+ }
+ }
+ else {
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ /* check that width, height, format are same */
+ if (minWidth != maxWidth || minHeight != maxHeight) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
+ fbo_incomplete("width or height mismatch", -1);
+ return;
+ }
+ /* check that all color buffer have same format */
+ if (intFormat != GL_NONE && f != intFormat) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ fbo_incomplete("format mismatch", -1);
+ return;
+ }
+ }
+ if (att->Renderbuffer &&
+ att->Renderbuffer->NumSamples != numSamples) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ fbo_incomplete("inconsistant number of samples", i);
+ return;
+ }
+
+ }
+ }
+
+#ifndef FEATURE_OES_framebuffer_object
+ /* Check that all DrawBuffers are present */
+ for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
+ if (fb->ColorDrawBuffer[j] != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+ fbo_incomplete("missing drawbuffer", j);
+ return;
+ }
+ }
+ }
+
+ /* Check that the ReadBuffer is present */
+ if (fb->ColorReadBuffer != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+ fbo_incomplete("missing readbuffer", -1);
+ return;
+ }
+ }
+#endif
+
+ if (numImages == 0) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
+ fbo_incomplete("no attachments", -1);
+ return;
+ }
+
+ /* Provisionally set status = COMPLETE ... */
+ fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
+
+ /* ... but the driver may say the FB is incomplete.
+ * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
+ * if anything.
+ */
+ if (ctx->Driver.ValidateFramebuffer) {
+ ctx->Driver.ValidateFramebuffer(ctx, fb);
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ fbo_incomplete("driver marked FBO as incomplete", -1);
+ }
+ }
+
+ if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
+ /*
+ * Note that if ARB_framebuffer_object is supported and the attached
+ * renderbuffers/textures are different sizes, the framebuffer
+ * width/height will be set to the smallest width/height.
+ */
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+
+ /* finally, update the visual info for the framebuffer */
+ _mesa_update_framebuffer_visual(fb);
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsRenderbufferEXT(GLuint renderbuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+ if (renderbuffer) {
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (rb != NULL && rb != &DummyRenderbuffer)
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
+{
+ struct gl_renderbuffer *newRb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glBindRenderbufferEXT(target)");
+ return;
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ /* The above doesn't fully flush the drivers in the way that a
+ * glFlush does, but that is required here:
+ */
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx);
+
+
+ if (renderbuffer) {
+ newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (newRb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ newRb = NULL;
+ }
+ else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All RB IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
+ return;
+ }
+
+ if (!newRb) {
+ /* create new renderbuffer object */
+ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
+ if (!newRb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
+ return;
+ }
+ ASSERT(newRb->AllocStorage);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
+ newRb->RefCount = 1; /* referenced by hash table */
+ }
+ }
+ else {
+ newRb = NULL;
+ }
+
+ ASSERT(newRb != &DummyRenderbuffer);
+
+ _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
+}
+
+
+/**
+ * If the given renderbuffer is anywhere attached to the framebuffer, detach
+ * the renderbuffer.
+ * This is used when a renderbuffer object is deleted.
+ * The spec calls for unbinding.
+ */
+static void
+detach_renderbuffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer *rb)
+{
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer == rb) {
+ _mesa_remove_attachment(ctx, &fb->Attachment[i]);
+ }
+ }
+ invalidate_framebuffer(fb);
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ for (i = 0; i < n; i++) {
+ if (renderbuffers[i] > 0) {
+ struct gl_renderbuffer *rb;
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
+ if (rb) {
+ /* check if deleting currently bound renderbuffer object */
+ if (rb == ctx->CurrentRenderbuffer) {
+ /* bind default */
+ ASSERT(rb->RefCount >= 2);
+ _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ }
+
+ if (ctx->DrawBuffer->Name) {
+ detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
+ }
+ if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) {
+ detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
+ }
+
+ /* Remove from hash table immediately, to free the ID.
+ * But the object will not be freed until it's no longer
+ * referenced anywhere else.
+ */
+ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
+
+ if (rb != &DummyRenderbuffer) {
+ /* no longer referenced by hash table */
+ _mesa_reference_renderbuffer(&rb, NULL);
+ }
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
+ return;
+ }
+
+ if (!renderbuffers)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
+
+ for (i = 0; i < n; i++) {
+ GLuint name = first + i;
+ renderbuffers[i] = name;
+ /* insert dummy placeholder into hash table */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+/**
+ * Given an internal format token for a render buffer, return the
+ * corresponding base format.
+ * This is very similar to _mesa_base_tex_format() but the set of valid
+ * internal formats is somewhat different.
+ *
+ * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT
+ * GL_DEPTH_STENCIL_EXT or zero if error.
+ */
+GLenum
+_mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat)
+{
+ switch (internalFormat) {
+ 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 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_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ case GL_STENCIL_INDEX16_EXT:
+ return GL_STENCIL_INDEX;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ if (ctx->Extensions.EXT_packed_depth_stencil)
+ return GL_DEPTH_STENCIL_EXT;
+ else
+ return 0;
+ /* XXX add floating point formats eventually */
+ default:
+ return 0;
+ }
+}
+
+
+/** sentinal value, see below */
+#define NO_SAMPLES 1000
+
+
+/**
+ * Helper function used by _mesa_RenderbufferStorageEXT() and
+ * _mesa_RenderbufferStorageMultisample().
+ * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
+ */
+static void
+renderbuffer_storage(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples)
+{
+ const char *func = samples == NO_SAMPLES ?
+ "glRenderbufferStorage" : "RenderbufferStorageMultisample";
+ struct gl_renderbuffer *rb;
+ GLenum baseFormat;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
+ return;
+ }
+
+ baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
+ if (baseFormat == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
+ return;
+ }
+
+ if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
+ return;
+ }
+
+ if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
+ return;
+ }
+
+ if (samples == NO_SAMPLES) {
+ /* NumSamples == 0 indicates non-multisampling */
+ samples = 0;
+ }
+ else if (samples > ctx->Const.MaxSamples) {
+ /* note: driver may choose to use more samples than what's requested */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, func);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (rb->InternalFormat == internalFormat &&
+ rb->Width == (GLuint) width &&
+ rb->Height == (GLuint) height) {
+ /* no change in allocation needed */
+ return;
+ }
+
+ /* These MUST get set by the AllocStorage func */
+ rb->_ActualFormat = 0;
+ rb->RedBits =
+ rb->GreenBits =
+ rb->BlueBits =
+ rb->AlphaBits =
+ rb->IndexBits =
+ rb->DepthBits =
+ rb->StencilBits = 0;
+ rb->NumSamples = samples;
+
+ /* Now allocate the storage */
+ ASSERT(rb->AllocStorage);
+ if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
+ /* No error - check/set fields now */
+ assert(rb->_ActualFormat);
+ assert(rb->Width == (GLuint) width);
+ assert(rb->Height == (GLuint) height);
+ assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
+ rb->DepthBits || rb->StencilBits || rb->IndexBits);
+ rb->InternalFormat = internalFormat;
+ rb->_BaseFormat = baseFormat;
+ }
+ else {
+ /* Probably ran out of memory - clear the fields */
+ rb->Width = 0;
+ rb->Height = 0;
+ rb->InternalFormat = GL_NONE;
+ rb->_ActualFormat = GL_NONE;
+ rb->_BaseFormat = GL_NONE;
+ rb->RedBits =
+ rb->GreenBits =
+ rb->BlueBits =
+ rb->AlphaBits =
+ rb->IndexBits =
+ rb->DepthBits =
+ rb->StencilBits =
+ rb->NumSamples = 0;
+ }
+
+ /*
+ test_framebuffer_completeness(ctx, fb);
+ */
+ /* XXX if this renderbuffer is attached anywhere, invalidate attachment
+ * points???
+ */
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ /* GL_ARB_fbo says calling this function is equivalent to calling
+ * glRenderbufferStorageMultisample() with samples=0. We pass in
+ * a token value here just for error reporting purposes.
+ */
+ renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
+}
+
+
+void GLAPIENTRY
+_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ renderbuffer_storage(target, internalFormat, width, height, samples);
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetRenderbufferParameterivEXT(target)");
+ return;
+ }
+
+ rb = ctx->CurrentRenderbuffer;
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetRenderbufferParameterivEXT");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ switch (pname) {
+ case GL_RENDERBUFFER_WIDTH_EXT:
+ *params = rb->Width;
+ return;
+ case GL_RENDERBUFFER_HEIGHT_EXT:
+ *params = rb->Height;
+ return;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
+ *params = rb->InternalFormat;
+ return;
+ case GL_RENDERBUFFER_RED_SIZE_EXT:
+ *params = rb->RedBits;
+ break;
+ case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+ *params = rb->GreenBits;
+ break;
+ case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+ *params = rb->BlueBits;
+ break;
+ case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+ *params = rb->AlphaBits;
+ break;
+ case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+ *params = rb->DepthBits;
+ break;
+ case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+ *params = rb->StencilBits;
+ break;
+ case GL_RENDERBUFFER_SAMPLES:
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ *params = rb->NumSamples;
+ break;
+ }
+ /* fallthrough */
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetRenderbufferParameterivEXT(target)");
+ return;
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsFramebufferEXT(GLuint framebuffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+ if (framebuffer) {
+ struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ if (rb != NULL && rb != &DummyFramebuffer)
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+static void
+check_begin_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ GLuint i;
+ ASSERT(ctx->Driver.RenderTexture);
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ struct gl_texture_object *texObj = att->Texture;
+ if (texObj
+ && att->Texture->Image[att->CubeMapFace][att->TextureLevel]) {
+ ctx->Driver.RenderTexture(ctx, fb, att);
+ }
+ }
+}
+
+
+/**
+ * Examine all the framebuffer's attachments to see if any are textures.
+ * If so, call ctx->Driver.FinishRenderTexture() for each texture to
+ * notify the device driver that the texture image may have changed.
+ */
+static void
+check_end_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ if (ctx->Driver.FinishRenderTexture) {
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ if (att->Texture && att->Renderbuffer) {
+ ctx->Driver.FinishRenderTexture(ctx, att);
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
+{
+ struct gl_framebuffer *newFb, *newFbread;
+ GLboolean bindReadBuf, bindDrawBuf;
+ GET_CURRENT_CONTEXT(ctx);
+
+#ifdef DEBUG
+ if (ctx->Extensions.ARB_framebuffer_object) {
+ ASSERT(ctx->Extensions.EXT_framebuffer_object);
+ ASSERT(ctx->Extensions.EXT_framebuffer_blit);
+ }
+#endif
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindFramebufferEXT(unsupported)");
+ return;
+ }
+
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_FALSE;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_FALSE;
+ bindReadBuf = GL_TRUE;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_TRUE;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ if (ctx->Driver.Flush) {
+ ctx->Driver.Flush(ctx);
+ }
+
+ if (framebuffer) {
+ /* Binding a user-created framebuffer object */
+ newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
+ if (newFb == &DummyFramebuffer) {
+ /* ID was reserved, but no real framebuffer object made yet */
+ newFb = NULL;
+ }
+ else if (!newFb && ctx->Extensions.ARB_framebuffer_object) {
+ /* All FBO IDs must be Gen'd */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
+ return;
+ }
+
+ if (!newFb) {
+ /* create new framebuffer object */
+ newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
+ if (!newFb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
+ }
+ newFbread = newFb;
+ }
+ else {
+ /* Binding the window system framebuffer (which was originally set
+ * with MakeCurrent).
+ */
+ newFb = ctx->WinSysDrawBuffer;
+ newFbread = ctx->WinSysReadBuffer;
+ }
+
+ ASSERT(newFb);
+ ASSERT(newFb != &DummyFramebuffer);
+
+ /*
+ * OK, now bind the new Draw/Read framebuffers, if they're changing.
+ */
+
+ if (bindReadBuf) {
+ if (ctx->ReadBuffer == newFbread)
+ bindReadBuf = GL_FALSE; /* no change */
+ else
+ _mesa_reference_framebuffer(&ctx->ReadBuffer, newFbread);
+ }
+
+ if (bindDrawBuf) {
+ /* check if old FB had any texture attachments */
+ if (ctx->DrawBuffer->Name != 0) {
+ check_end_texture_render(ctx, ctx->DrawBuffer);
+ }
+
+ if (ctx->DrawBuffer == newFb)
+ bindDrawBuf = GL_FALSE; /* no change */
+ else
+ _mesa_reference_framebuffer(&ctx->DrawBuffer, newFb);
+
+ if (newFb->Name != 0) {
+ /* check if newly bound framebuffer has any texture attachments */
+ check_begin_texture_render(ctx, newFb);
+ }
+ }
+
+ if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
+ ctx->Driver.BindFramebuffer(ctx, target, newFb, newFbread);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ /* The above doesn't fully flush the drivers in the way that a
+ * glFlush does, but that is required here:
+ */
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx);
+
+ for (i = 0; i < n; i++) {
+ if (framebuffers[i] > 0) {
+ struct gl_framebuffer *fb;
+ fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
+ if (fb) {
+ ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
+
+ /* check if deleting currently bound framebuffer object */
+ if (fb == ctx->DrawBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ }
+ if (fb == ctx->ReadBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
+ }
+
+ /* remove from hash table immediately, to free the ID */
+ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
+
+ if (fb != &DummyFramebuffer) {
+ /* But the object will not be freed until it's no longer
+ * bound in any context.
+ */
+ _mesa_reference_framebuffer(&fb, NULL);
+ }
+ }
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
+ return;
+ }
+
+ if (!framebuffers)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
+
+ for (i = 0; i < n; i++) {
+ GLuint name = first + i;
+ framebuffers[i] = name;
+ /* insert dummy placeholder into hash table */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+
+GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatusEXT(GLenum target)
+{
+ struct gl_framebuffer *buffer;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0;
+ }
+ buffer = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0;
+ }
+ buffer = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ buffer = ctx->DrawBuffer;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
+ }
+
+ if (buffer->Name == 0) {
+ /* The window system / default framebuffer is always complete */
+ return GL_FRAMEBUFFER_COMPLETE_EXT;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ _mesa_test_framebuffer_completeness(ctx, buffer);
+ }
+
+ return buffer->_Status;
+}
+
+
+
+/**
+ * Common code called by glFramebufferTexture1D/2D/3DEXT().
+ */
+static void
+framebuffer_texture(GLcontext *ctx, const char *caller, GLenum target,
+ GLenum attachment, GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
+{
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj = NULL;
+ struct gl_framebuffer *fb;
+ GLboolean error = GL_FALSE;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_READ_FRAMEBUFFER_EXT:
+ error = !ctx->Extensions.EXT_framebuffer_blit;
+ fb = ctx->ReadBuffer;
+ break;
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ error = !ctx->Extensions.EXT_framebuffer_blit;
+ /* fall-through */
+ case GL_FRAMEBUFFER_EXT:
+ fb = ctx->DrawBuffer;
+ break;
+ default:
+ error = GL_TRUE;
+ }
+
+ if (error) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
+ return;
+ }
+
+ ASSERT(fb);
+
+ /* check framebuffer binding */
+ if (fb->Name == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT", caller);
+ return;
+ }
+
+
+ /* The textarget, level, and zoffset parameters are only validated if
+ * texture is non-zero.
+ */
+ if (texture) {
+ GLboolean err = GL_TRUE;
+
+ texObj = _mesa_lookup_texture(ctx, texture);
+ if (texObj != NULL) {
+ if (textarget == 0) {
+ err = (texObj->Target != GL_TEXTURE_3D) &&
+ (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
+ (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
+ }
+ else {
+ err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
+ ? !IS_CUBE_FACE(textarget)
+ : (texObj->Target != textarget);
+ }
+ }
+
+ if (err) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT(texture target mismatch)",
+ caller);
+ return;
+ }
+
+ if (texObj->Target == GL_TEXTURE_3D) {
+ const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (zoffset < 0 || zoffset >= maxSize) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(zoffset)", caller);
+ return;
+ }
+ }
+ else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
+ (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
+ if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(layer)", caller);
+ return;
+ }
+ }
+
+ if ((level < 0) ||
+ (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glFramebufferTexture%sEXT(level)", caller);
+ return;
+ }
+ }
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture%sEXT(attachment)", caller);
+ return;
+ }
+
+ if (texObj && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* the texture format must be depth+stencil */
+ const struct gl_texture_image *texImg;
+ texImg = texObj->Image[0][texObj->BaseLevel];
+ if (!texImg || texImg->_BaseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture%sEXT(texture is not"
+ " DEPTH_STENCIL format)", caller);
+ return;
+ }
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ /* The above doesn't fully flush the drivers in the way that a
+ * glFlush does, but that is required here:
+ */
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx);
+
+ _glthread_LOCK_MUTEX(fb->Mutex);
+ if (texObj) {
+ _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
+ level, zoffset);
+ /* Set the render-to-texture flag. We'll check this flag in
+ * glTexImage() and friends to determine if we need to revalidate
+ * any FBOs that might be rendering into this texture.
+ * This flag never gets cleared since it's non-trivial to determine
+ * when all FBOs might be done rendering to this texture. That's OK
+ * though since it's uncommon to render to a texture then repeatedly
+ * call glTexImage() to change images in the texture.
+ */
+ texObj->_RenderToTexture = GL_TRUE;
+ }
+ else {
+ _mesa_remove_attachment(ctx, att);
+ }
+
+ invalidate_framebuffer(fb);
+
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+}
+
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) && (textarget != GL_TEXTURE_1D)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture1DEXT(textarget)");
+ return;
+ }
+
+ framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
+ level, 0);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) &&
+ (textarget != GL_TEXTURE_2D) &&
+ (textarget != GL_TEXTURE_RECTANGLE_ARB) &&
+ (!IS_CUBE_FACE(textarget))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferTexture2DEXT(textarget=0x%x)", textarget);
+ return;
+ }
+
+ framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
+ level, 0);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferTexture3DEXT(textarget)");
+ return;
+ }
+
+ framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
+ level, zoffset);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
+ level, layer);
+}
+
+
+void GLAPIENTRY
+_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
+ GLenum renderbufferTarget,
+ GLuint renderbuffer)
+{
+ struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *fb;
+ struct gl_renderbuffer *rb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+ fb = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+ fb = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ fb = ctx->DrawBuffer;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+
+ if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(renderbufferTarget)");
+ return;
+ }
+
+ if (fb->Name == 0) {
+ /* Can't attach new renderbuffers to a window system framebuffer */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
+ return;
+ }
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(attachment)");
+ return;
+ }
+
+ if (renderbuffer) {
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbufferEXT(renderbuffer)");
+ return;
+ }
+ }
+ else {
+ /* remove renderbuffer attachment */
+ rb = NULL;
+ }
+
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* make sure the renderbuffer is a depth/stencil format */
+ if (rb->_BaseFormat != GL_DEPTH_STENCIL) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbufferEXT(renderbuffer"
+ " is not DEPTH_STENCIL format)");
+ return;
+ }
+ }
+
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ /* The above doesn't fully flush the drivers in the way that a
+ * glFlush does, but that is required here:
+ */
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx);
+
+ assert(ctx->Driver.FramebufferRenderbuffer);
+ ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
+
+ /* Some subsequent GL commands may depend on the framebuffer's visual
+ * after the binding is updated. Update visual info now.
+ */
+ _mesa_update_framebuffer_visual(fb);
+}
+
+
+void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params)
+{
+ const struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *buffer;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+ buffer = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+ buffer = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ buffer = ctx->DrawBuffer;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+
+ if (buffer->Name == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameterivEXT");
+ return;
+ }
+
+ att = _mesa_get_attachment(ctx, buffer, attachment);
+ if (att == NULL) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(attachment)");
+ return;
+ }
+
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* the depth and stencil attachments must point to the same buffer */
+ const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
+ depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
+ stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
+ if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
+ " attachments differ)");
+ return;
+ }
+ }
+
+ FLUSH_CURRENT(ctx, _NEW_BUFFERS);
+ /* The above doesn't fully flush the drivers in the way that a
+ * glFlush does, but that is required here:
+ */
+ if (ctx->Driver.Flush)
+ ctx->Driver.Flush(ctx);
+
+ switch (pname) {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
+ *params = att->Type;
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
+ if (att->Type == GL_RENDERBUFFER_EXT) {
+ *params = att->Renderbuffer->Name;
+ }
+ else if (att->Type == GL_TEXTURE) {
+ *params = att->Texture->Name;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
+ if (att->Type == GL_TEXTURE) {
+ *params = att->TextureLevel;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
+ if (att->Type == GL_TEXTURE) {
+ if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
+ *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
+ }
+ else {
+ *params = 0;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
+ if (att->Type == GL_TEXTURE) {
+ if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
+ *params = att->Zoffset;
+ }
+ else {
+ *params = 0;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->ColorEncoding;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ return;
+ }
+ else {
+ *params = att->Renderbuffer->ComponentType;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->RedBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->GreenBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->BlueBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->AlphaBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->DepthBits;
+ }
+ return;
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ if (!ctx->Extensions.ARB_framebuffer_object) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ }
+ else {
+ *params = att->Renderbuffer->StencilBits;
+ }
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GenerateMipmapEXT(GLenum target)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ /* OK, legal value */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");
+ return;
+ }
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ int face;
+
+ for (face = 0; face < 6; face++)
+ ctx->Driver.GenerateMipmap(ctx,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
+ texObj);
+ } else {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+#if FEATURE_EXT_framebuffer_blit
+/**
+ * Blit rectangular region, optionally from one framebuffer to another.
+ *
+ * Note, if the src buffer is multisampled and the dest is not, this is
+ * when the samples must be resolved to a single color.
+ */
+void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT);
+ const struct gl_framebuffer *readFb, *drawFb;
+ const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (ctx->NewState) {
+ _mesa_update_state(ctx);
+ }
+
+ readFb = ctx->ReadBuffer;
+ drawFb = ctx->DrawBuffer;
+
+ if (!readFb || !drawFb) {
+ /* This will normally never happen but someday we may want to
+ * support MakeCurrent() with no drawables.
+ */
+ return;
+ }
+
+ /* check for complete framebuffers */
+ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+ readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glBlitFramebufferEXT(incomplete draw/read buffers)");
+ return;
+ }
+
+ if (filter != GL_NEAREST && filter != GL_LINEAR) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
+ return;
+ }
+
+ if (mask & ~legalMaskBits) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+ return;
+ }
+
+ /* depth/stencil must be blitted with nearest filtering */
+ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+ && filter != GL_NEAREST) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
+ return;
+ }
+
+ /* get color read/draw renderbuffers */
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ colorReadRb = readFb->_ColorReadBuffer;
+ colorDrawRb = drawFb->_ColorDrawBuffers[0];
+ }
+ else {
+ colorReadRb = colorDrawRb = NULL;
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ struct gl_renderbuffer *readRb = readFb->_StencilBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer;
+ if (!readRb ||
+ !drawRb ||
+ readRb->StencilBits != drawRb->StencilBits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(stencil buffer size mismatch");
+ return;
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ struct gl_renderbuffer *readRb = readFb->_DepthBuffer;
+ struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer;
+ if (!readRb ||
+ !drawRb ||
+ readRb->DepthBits != drawRb->DepthBits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(depth buffer size mismatch");
+ return;
+ }
+ }
+
+ if (readFb->Visual.samples > 0 &&
+ drawFb->Visual.samples > 0 &&
+ readFb->Visual.samples != drawFb->Visual.samples) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(mismatched samples");
+ return;
+ }
+
+ /* extra checks for multisample copies... */
+ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
+ /* src and dest region sizes must be the same */
+ if (srcX1 - srcX0 != dstX1 - dstX0 ||
+ srcY1 - srcY0 != dstY1 - dstY0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample region sizes");
+ return;
+ }
+
+ /* color formats must match */
+ if (colorReadRb &&
+ colorDrawRb &&
+ colorReadRb->_ActualFormat != colorDrawRb->_ActualFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(bad src/dst multisample pixel formats");
+ return;
+ }
+ }
+
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
+ return;
+ }
+
+ ASSERT(ctx->Driver.BlitFramebuffer);
+ ctx->Driver.BlitFramebuffer(ctx,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
+#endif /* FEATURE_EXT_framebuffer_blit */
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
new file mode 100644
index 000000000..540939407
--- /dev/null
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -0,0 +1,146 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 FBOBJECT_H
+#define FBOBJECT_H
+
+
+extern void
+_mesa_init_fbobjects(GLcontext *ctx);
+
+extern struct gl_renderbuffer *
+_mesa_lookup_renderbuffer(GLcontext *ctx, GLuint id);
+
+extern struct gl_framebuffer *
+_mesa_lookup_framebuffer(GLcontext *ctx, GLuint id);
+
+extern struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment);
+
+
+extern void
+_mesa_remove_attachment(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att);
+
+extern void
+_mesa_set_texture_attachment(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_texture_object *texObj,
+ GLenum texTarget, GLuint level, GLuint zoffset);
+
+extern void
+_mesa_set_renderbuffer_attachment(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_renderbuffer *rb);
+
+extern void
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment, struct gl_renderbuffer *rb);
+
+extern void
+_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb);
+
+extern GLenum
+_mesa_base_fbo_format(GLcontext *ctx, GLenum internalFormat);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsRenderbufferEXT(GLuint renderbuffer);
+
+extern void GLAPIENTRY
+_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer);
+
+extern void GLAPIENTRY
+_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers);
+
+extern void GLAPIENTRY
+_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers);
+
+extern void GLAPIENTRY
+_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname,
+ GLint *params);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsFramebufferEXT(GLuint framebuffer);
+
+extern void GLAPIENTRY
+_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer);
+
+extern void GLAPIENTRY
+_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers);
+
+extern void GLAPIENTRY
+_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers);
+
+extern GLenum GLAPIENTRY
+_mesa_CheckFramebufferStatusEXT(GLenum target);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture, GLint level);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level, GLint zoffset);
+
+extern void GLAPIENTRY
+_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+
+extern void GLAPIENTRY
+_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+extern void GLAPIENTRY
+_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
+ GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GenerateMipmapEXT(GLenum target);
+
+
+extern void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+
+#endif /* FBOBJECT_H */
diff --git a/mesalib/src/mesa/main/feedback.c b/mesalib/src/mesa/main/feedback.c
new file mode 100644
index 000000000..818a80454
--- /dev/null
+++ b/mesalib/src/mesa/main/feedback.c
@@ -0,0 +1,536 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file feedback.c
+ * Selection and feedback modes functions.
+ */
+
+
+#include "glheader.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "feedback.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+
+
+#define FB_3D 0x01
+#define FB_4D 0x02
+#define FB_INDEX 0x04
+#define FB_COLOR 0x08
+#define FB_TEXTURE 0X10
+
+
+
+void GLAPIENTRY
+_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode==GL_FEEDBACK) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
+ return;
+ }
+ if (size<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
+ return;
+ }
+ if (!buffer) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
+ ctx->Feedback.BufferSize = 0;
+ return;
+ }
+
+ switch (type) {
+ case GL_2D:
+ ctx->Feedback._Mask = 0;
+ break;
+ case GL_3D:
+ ctx->Feedback._Mask = FB_3D;
+ break;
+ case GL_3D_COLOR:
+ ctx->Feedback._Mask = (FB_3D |
+ (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX));
+ break;
+ case GL_3D_COLOR_TEXTURE:
+ ctx->Feedback._Mask = (FB_3D |
+ (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) |
+ FB_TEXTURE);
+ break;
+ case GL_4D_COLOR_TEXTURE:
+ ctx->Feedback._Mask = (FB_3D | FB_4D |
+ (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) |
+ FB_TEXTURE);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* Always flush */
+ ctx->Feedback.Type = type;
+ ctx->Feedback.BufferSize = size;
+ ctx->Feedback.Buffer = buffer;
+ ctx->Feedback.Count = 0; /* Becaues of this. */
+}
+
+
+void GLAPIENTRY
+_mesa_PassThrough( GLfloat token )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode==GL_FEEDBACK) {
+ FLUSH_VERTICES(ctx, 0);
+ _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
+ _mesa_feedback_token( ctx, token );
+ }
+}
+
+
+/**
+ * Put a vertex into the feedback buffer.
+ */
+void
+_mesa_feedback_vertex(GLcontext *ctx,
+ const GLfloat win[4],
+ const GLfloat color[4],
+ GLfloat index,
+ const GLfloat texcoord[4])
+{
+ _mesa_feedback_token( ctx, win[0] );
+ _mesa_feedback_token( ctx, win[1] );
+ if (ctx->Feedback._Mask & FB_3D) {
+ _mesa_feedback_token( ctx, win[2] );
+ }
+ if (ctx->Feedback._Mask & FB_4D) {
+ _mesa_feedback_token( ctx, win[3] );
+ }
+ if (ctx->Feedback._Mask & FB_INDEX) {
+ _mesa_feedback_token( ctx, (GLfloat) index );
+ }
+ if (ctx->Feedback._Mask & FB_COLOR) {
+ _mesa_feedback_token( ctx, color[0] );
+ _mesa_feedback_token( ctx, color[1] );
+ _mesa_feedback_token( ctx, color[2] );
+ _mesa_feedback_token( ctx, color[3] );
+ }
+ if (ctx->Feedback._Mask & FB_TEXTURE) {
+ _mesa_feedback_token( ctx, texcoord[0] );
+ _mesa_feedback_token( ctx, texcoord[1] );
+ _mesa_feedback_token( ctx, texcoord[2] );
+ _mesa_feedback_token( ctx, texcoord[3] );
+ }
+}
+
+
+#endif /* _HAVE_FULL_GL */
+
+
+/**********************************************************************/
+/** \name Selection */
+/*@{*/
+
+/**
+ * Establish a buffer for selection mode values.
+ *
+ * \param size buffer size.
+ * \param buffer buffer.
+ *
+ * \sa glSelectBuffer().
+ *
+ * \note this function can't be put in a display list.
+ *
+ * Verifies we're not in selection mode, flushes the vertices and initialize
+ * the fields in __GLcontextRec::Select with the given buffer.
+ */
+void GLAPIENTRY
+_mesa_SelectBuffer( GLsizei size, GLuint *buffer )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode==GL_SELECT) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
+ return; /* KW: added return */
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
+ 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;
+}
+
+
+/**
+ * Write a value of a record into the selection buffer.
+ *
+ * \param ctx GL context.
+ * \param value value.
+ *
+ * Verifies there is free space in the buffer to write the value and
+ * increments the pointer.
+ */
+static INLINE void
+write_record(GLcontext *ctx, GLuint value)
+{
+ if (ctx->Select.BufferCount < ctx->Select.BufferSize) {
+ ctx->Select.Buffer[ctx->Select.BufferCount] = value;
+ }
+ ctx->Select.BufferCount++;
+}
+
+
+/**
+ * Update the hit flag and the maximum and minimum depth values.
+ *
+ * \param ctx GL context.
+ * \param z depth.
+ *
+ * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and
+ * gl_selection::HitMaxZ.
+ */
+void
+_mesa_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;
+ }
+}
+
+
+/**
+ * Write the hit record.
+ *
+ * \param ctx GL context.
+ *
+ * Write the hit record, i.e., the number of names in the stack, the minimum and
+ * maximum depth values and the number of names in the name stack at the time
+ * of the event. Resets the hit flag.
+ *
+ * \sa gl_selection.
+ */
+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;
+}
+
+
+/**
+ * Initialize the name stack.
+ *
+ * Verifies we are in select mode and resets the name stack depth and resets
+ * the hit record data in gl_selection. Marks new render mode in
+ * __GLcontextRec::NewState.
+ */
+void GLAPIENTRY
+_mesa_InitNames( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* 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;
+ ctx->NewState |= _NEW_RENDERMODE;
+}
+
+
+/**
+ * Load the top-most name of the name stack.
+ *
+ * \param name name.
+ *
+ * Verifies we are in selection mode and that the name stack is not empty.
+ * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
+ * and replace the top-most name in the stack.
+ *
+ * sa __GLcontextRec::Select.
+ */
+void GLAPIENTRY
+_mesa_LoadName( GLuint name )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode != GL_SELECT) {
+ return;
+ }
+ if (ctx->Select.NameStackDepth == 0) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
+
+ 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;
+ }
+}
+
+
+/**
+ * Push a name into the name stack.
+ *
+ * \param name name.
+ *
+ * Verifies we are in selection mode and that the name stack is not full.
+ * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
+ * and adds the name to the top of the name stack.
+ *
+ * sa __GLcontextRec::Select.
+ */
+void GLAPIENTRY
+_mesa_PushName( GLuint name )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode != GL_SELECT) {
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) {
+ _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
+ }
+ else
+ ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
+}
+
+
+/**
+ * Pop a name into the name stack.
+ *
+ * Verifies we are in selection mode and that the name stack is not empty.
+ * Flushes vertices. If there is a hit flag writes it (via write_hit_record()),
+ * and removes top-most name in the name stack.
+ *
+ * sa __GLcontextRec::Select.
+ */
+void GLAPIENTRY
+_mesa_PopName( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->RenderMode != GL_SELECT) {
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.NameStackDepth == 0) {
+ _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
+ }
+ else
+ ctx->Select.NameStackDepth--;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Render Mode */
+/*@{*/
+
+/**
+ * Set rasterization mode.
+ *
+ * \param mode rasterization mode.
+ *
+ * \note this function can't be put in a display list.
+ *
+ * \sa glRenderMode().
+ *
+ * Flushes the vertices and do the necessary cleanup according to the previous
+ * rasterization mode, such as writing the hit record or resent the select
+ * buffer index when exiting the select mode. Updates
+ * __GLcontextRec::RenderMode and notifies the driver via the
+ * dd_function_table::RenderMode callback.
+ */
+GLint GLAPIENTRY
+_mesa_RenderMode( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint result;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ FLUSH_VERTICES(ctx, _NEW_RENDERMODE);
+
+ 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
+ _mesa_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;
+#if _HAVE_FULL_GL
+ case GL_FEEDBACK:
+ if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
+ /* overflow */
+ result = -1;
+ }
+ else {
+ result = ctx->Feedback.Count;
+ }
+ ctx->Feedback.Count = 0;
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
+ return 0;
+ }
+
+ switch (mode) {
+ case GL_RENDER:
+ break;
+ case GL_SELECT:
+ if (ctx->Select.BufferSize==0) {
+ /* haven't called glSelectBuffer yet */
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
+ }
+ break;
+#if _HAVE_FULL_GL
+ case GL_FEEDBACK:
+ if (ctx->Feedback.BufferSize==0) {
+ /* haven't called glFeedbackBuffer yet */
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
+ }
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
+ return 0;
+ }
+
+ ctx->RenderMode = mode;
+ if (ctx->Driver.RenderMode)
+ ctx->Driver.RenderMode( ctx, mode );
+
+ return result;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialize context feedback data.
+ */
+void _mesa_init_feedback( GLcontext * ctx )
+{
+ /* 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;
+
+ /* Miscellaneous */
+ ctx->RenderMode = GL_RENDER;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/feedback.h b/mesalib/src/mesa/main/feedback.h
new file mode 100644
index 000000000..72c2acd5e
--- /dev/null
+++ b/mesalib/src/mesa/main/feedback.h
@@ -0,0 +1,83 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "mtypes.h"
+
+
+extern void
+_mesa_init_feedback( GLcontext *ctx );
+
+extern void
+_mesa_feedback_vertex( GLcontext *ctx,
+ const GLfloat win[4],
+ const GLfloat color[4],
+ GLfloat index,
+ const GLfloat texcoord[4] );
+
+
+static INLINE void
+_mesa_feedback_token( GLcontext *ctx, GLfloat token )
+{
+ if (ctx->Feedback.Count < ctx->Feedback.BufferSize) {
+ ctx->Feedback.Buffer[ctx->Feedback.Count] = token;
+ }
+ ctx->Feedback.Count++;
+}
+
+
+extern void
+_mesa_update_hitflag( GLcontext *ctx, GLfloat z );
+
+
+extern void GLAPIENTRY
+_mesa_PassThrough( GLfloat token );
+
+extern void GLAPIENTRY
+_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer );
+
+extern void GLAPIENTRY
+_mesa_SelectBuffer( GLsizei size, GLuint *buffer );
+
+extern void GLAPIENTRY
+_mesa_InitNames( void );
+
+extern void GLAPIENTRY
+_mesa_LoadName( GLuint name );
+
+extern void GLAPIENTRY
+_mesa_PushName( GLuint name );
+
+extern void GLAPIENTRY
+_mesa_PopName( void );
+
+extern GLint GLAPIENTRY
+_mesa_RenderMode( GLenum mode );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
new file mode 100644
index 000000000..356476e35
--- /dev/null
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -0,0 +1,1672 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * \file ffvertex_prog.c
+ *
+ * Create a vertex program to execute the current fixed function T&L pipeline.
+ * \author Keith Whitwell
+ */
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/ffvertex_prog.h"
+#include "shader/program.h"
+#include "shader/prog_cache.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+
+
+/** Max of number of lights and texture coord units */
+#define NUM_UNITS MAX2(MAX_TEXTURE_COORD_UNITS, MAX_LIGHTS)
+
+struct state_key {
+ unsigned light_color_material_mask:12;
+ unsigned light_global_enabled:1;
+ unsigned light_local_viewer:1;
+ unsigned light_twoside:1;
+ unsigned material_shininess_is_zero:1;
+ unsigned need_eye_coords:1;
+ unsigned normalize:1;
+ unsigned rescale_normals:1;
+
+ unsigned fog_source_is_depth:1;
+ unsigned separate_specular:1;
+ unsigned point_attenuated:1;
+ unsigned point_array:1;
+ unsigned texture_enabled_global:1;
+ unsigned fragprog_inputs_read:12;
+
+ unsigned varying_vp_inputs;
+
+ struct {
+ unsigned light_enabled:1;
+ unsigned light_eyepos3_is_zero:1;
+ unsigned light_spotcutoff_is_180:1;
+ unsigned light_attenuated:1;
+ unsigned texunit_really_enabled:1;
+ unsigned texmat_enabled:1;
+ unsigned texgen_enabled:4;
+ unsigned texgen_mode0:4;
+ unsigned texgen_mode1:4;
+ unsigned texgen_mode2:4;
+ unsigned texgen_mode3:4;
+ } unit[NUM_UNITS];
+};
+
+
+#define TXG_NONE 0
+#define TXG_OBJ_LINEAR 1
+#define TXG_EYE_LINEAR 2
+#define TXG_SPHERE_MAP 3
+#define TXG_REFLECTION_MAP 4
+#define TXG_NORMAL_MAP 5
+
+static GLuint translate_texgen( GLboolean enabled, GLenum mode )
+{
+ if (!enabled)
+ return TXG_NONE;
+
+ switch (mode) {
+ case GL_OBJECT_LINEAR: return TXG_OBJ_LINEAR;
+ case GL_EYE_LINEAR: return TXG_EYE_LINEAR;
+ case GL_SPHERE_MAP: return TXG_SPHERE_MAP;
+ case GL_REFLECTION_MAP_NV: return TXG_REFLECTION_MAP;
+ case GL_NORMAL_MAP_NV: return TXG_NORMAL_MAP;
+ default: return TXG_NONE;
+ }
+}
+
+
+
+static GLboolean check_active_shininess( GLcontext *ctx,
+ const struct state_key *key,
+ GLuint side )
+{
+ GLuint bit = 1 << (MAT_ATTRIB_FRONT_SHININESS + side);
+
+ if ((key->varying_vp_inputs & VERT_BIT_COLOR0) &&
+ (key->light_color_material_mask & bit))
+ return GL_TRUE;
+
+ if (key->varying_vp_inputs & (bit << 16))
+ return GL_TRUE;
+
+ if (ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS + side][0] != 0.0F)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+static void make_state_key( GLcontext *ctx, struct state_key *key )
+{
+ const struct gl_fragment_program *fp;
+ GLuint i;
+
+ memset(key, 0, sizeof(struct state_key));
+ fp = ctx->FragmentProgram._Current;
+
+ /* This now relies on texenvprogram.c being active:
+ */
+ assert(fp);
+
+ key->need_eye_coords = ctx->_NeedEyeCoords;
+
+ key->fragprog_inputs_read = fp->Base.InputsRead;
+ key->varying_vp_inputs = ctx->varying_vp_inputs;
+
+ if (ctx->RenderMode == GL_FEEDBACK) {
+ /* make sure the vertprog emits color and tex0 */
+ key->fragprog_inputs_read |= (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
+ }
+
+ key->separate_specular = (ctx->Light.Model.ColorControl ==
+ GL_SEPARATE_SPECULAR_COLOR);
+
+ if (ctx->Light.Enabled) {
+ key->light_global_enabled = 1;
+
+ if (ctx->Light.Model.LocalViewer)
+ key->light_local_viewer = 1;
+
+ if (ctx->Light.Model.TwoSide)
+ key->light_twoside = 1;
+
+ if (ctx->Light.ColorMaterialEnabled) {
+ key->light_color_material_mask = ctx->Light.ColorMaterialBitmask;
+ }
+
+ for (i = 0; i < MAX_LIGHTS; i++) {
+ struct gl_light *light = &ctx->Light.Light[i];
+
+ if (light->Enabled) {
+ key->unit[i].light_enabled = 1;
+
+ if (light->EyePosition[3] == 0.0)
+ key->unit[i].light_eyepos3_is_zero = 1;
+
+ if (light->SpotCutoff == 180.0)
+ key->unit[i].light_spotcutoff_is_180 = 1;
+
+ if (light->ConstantAttenuation != 1.0 ||
+ light->LinearAttenuation != 0.0 ||
+ light->QuadraticAttenuation != 0.0)
+ key->unit[i].light_attenuated = 1;
+ }
+ }
+
+ if (check_active_shininess(ctx, key, 0)) {
+ key->material_shininess_is_zero = 0;
+ }
+ else if (key->light_twoside &&
+ check_active_shininess(ctx, key, 1)) {
+ key->material_shininess_is_zero = 0;
+ }
+ else {
+ key->material_shininess_is_zero = 1;
+ }
+ }
+
+ if (ctx->Transform.Normalize)
+ key->normalize = 1;
+
+ if (ctx->Transform.RescaleNormals)
+ key->rescale_normals = 1;
+
+ if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
+ key->fog_source_is_depth = 1;
+
+ if (ctx->Point._Attenuated)
+ key->point_attenuated = 1;
+
+#if FEATURE_point_size_array
+ if (ctx->Array.ArrayObj->PointSize.Enabled)
+ key->point_array = 1;
+#endif
+
+ if (ctx->Texture._TexGenEnabled ||
+ ctx->Texture._TexMatEnabled ||
+ ctx->Texture._EnabledUnits)
+ key->texture_enabled_global = 1;
+
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->_ReallyEnabled)
+ key->unit[i].texunit_really_enabled = 1;
+
+ if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
+ key->unit[i].texmat_enabled = 1;
+
+ if (texUnit->TexGenEnabled) {
+ key->unit[i].texgen_enabled = 1;
+
+ key->unit[i].texgen_mode0 =
+ translate_texgen( texUnit->TexGenEnabled & (1<<0),
+ texUnit->GenS.Mode );
+ key->unit[i].texgen_mode1 =
+ translate_texgen( texUnit->TexGenEnabled & (1<<1),
+ texUnit->GenT.Mode );
+ key->unit[i].texgen_mode2 =
+ translate_texgen( texUnit->TexGenEnabled & (1<<2),
+ texUnit->GenR.Mode );
+ key->unit[i].texgen_mode3 =
+ translate_texgen( texUnit->TexGenEnabled & (1<<3),
+ texUnit->GenQ.Mode );
+ }
+ }
+}
+
+
+
+/* Very useful debugging tool - produces annotated listing of
+ * generated program with line/function references for each
+ * instruction back into this file:
+ */
+#define DISASSEM 0
+
+
+/* Use uregs to represent registers internally, translate to Mesa's
+ * expected formats on emit.
+ *
+ * NOTE: These are passed by value extensively in this file rather
+ * than as usual by pointer reference. If this disturbs you, try
+ * remembering they are just 32bits in size.
+ *
+ * GCC is smart enough to deal with these dword-sized structures in
+ * much the same way as if I had defined them as dwords and was using
+ * macros to access and set the fields. This is much nicer and easier
+ * to evolve.
+ */
+struct ureg {
+ GLuint file:4;
+ GLint idx:9; /* relative addressing may be negative */
+ /* sizeof(idx) should == sizeof(prog_src_reg::Index) */
+ GLuint negate:1;
+ GLuint swz:12;
+ GLuint pad:6;
+};
+
+
+struct tnl_program {
+ const struct state_key *state;
+ struct gl_vertex_program *program;
+ GLint max_inst; /** number of instructions allocated for program */
+ GLboolean mvp_with_dp4;
+
+ GLuint temp_in_use;
+ GLuint temp_reserved;
+
+ struct ureg eye_position;
+ struct ureg eye_position_z;
+ struct ureg eye_position_normalized;
+ struct ureg transformed_normal;
+ struct ureg identity;
+
+ GLuint materials;
+ GLuint color_materials;
+};
+
+
+static const struct ureg undef = {
+ PROGRAM_UNDEFINED,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+/* Local shorthand:
+ */
+#define X SWIZZLE_X
+#define Y SWIZZLE_Y
+#define Z SWIZZLE_Z
+#define W SWIZZLE_W
+
+
+/* Construct a ureg:
+ */
+static struct ureg make_ureg(GLuint file, GLint idx)
+{
+ struct ureg reg;
+ reg.file = file;
+ reg.idx = idx;
+ reg.negate = 0;
+ reg.swz = SWIZZLE_NOOP;
+ reg.pad = 0;
+ return reg;
+}
+
+
+
+static struct ureg negate( struct ureg reg )
+{
+ reg.negate ^= 1;
+ return reg;
+}
+
+
+static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
+{
+ reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
+ GET_SWZ(reg.swz, y),
+ GET_SWZ(reg.swz, z),
+ GET_SWZ(reg.swz, w));
+ return reg;
+}
+
+
+static struct ureg swizzle1( struct ureg reg, int x )
+{
+ return swizzle(reg, x, x, x, x);
+}
+
+
+static struct ureg get_temp( struct tnl_program *p )
+{
+ int bit = _mesa_ffs( ~p->temp_in_use );
+ if (!bit) {
+ _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
+ _mesa_exit(1);
+ }
+
+ if ((GLuint) bit > p->program->Base.NumTemporaries)
+ p->program->Base.NumTemporaries = bit;
+
+ p->temp_in_use |= 1<<(bit-1);
+ return make_ureg(PROGRAM_TEMPORARY, bit-1);
+}
+
+
+static struct ureg reserve_temp( struct tnl_program *p )
+{
+ struct ureg temp = get_temp( p );
+ p->temp_reserved |= 1<<temp.idx;
+ return temp;
+}
+
+
+static void release_temp( struct tnl_program *p, struct ureg reg )
+{
+ if (reg.file == PROGRAM_TEMPORARY) {
+ p->temp_in_use &= ~(1<<reg.idx);
+ p->temp_in_use |= p->temp_reserved; /* can't release reserved temps */
+ }
+}
+
+static void release_temps( struct tnl_program *p )
+{
+ p->temp_in_use = p->temp_reserved;
+}
+
+
+static struct ureg register_param5(struct tnl_program *p,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4)
+{
+ gl_state_index tokens[STATE_LENGTH];
+ GLint idx;
+ tokens[0] = s0;
+ tokens[1] = s1;
+ tokens[2] = s2;
+ tokens[3] = s3;
+ tokens[4] = s4;
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
+}
+
+
+#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+
+
+
+/**
+ * \param input one of VERT_ATTRIB_x tokens.
+ */
+static struct ureg register_input( struct tnl_program *p, GLuint input )
+{
+ assert(input < 32);
+
+ if (p->state->varying_vp_inputs & (1<<input)) {
+ p->program->Base.InputsRead |= (1<<input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, input );
+ }
+}
+
+
+/**
+ * \param input one of VERT_RESULT_x tokens.
+ */
+static struct ureg register_output( struct tnl_program *p, GLuint output )
+{
+ p->program->Base.OutputsWritten |= (1<<output);
+ return make_ureg(PROGRAM_OUTPUT, output);
+}
+
+
+static struct ureg register_const4f( struct tnl_program *p,
+ GLfloat s0,
+ GLfloat s1,
+ GLfloat s2,
+ GLfloat s3)
+{
+ GLfloat values[4];
+ GLint idx;
+ GLuint swizzle;
+ values[0] = s0;
+ values[1] = s1;
+ values[2] = s2;
+ values[3] = s3;
+ idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
+ &swizzle );
+ ASSERT(swizzle == SWIZZLE_NOOP);
+ return make_ureg(PROGRAM_CONSTANT, idx);
+}
+
+#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
+#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
+#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
+#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
+
+static GLboolean is_undef( struct ureg reg )
+{
+ return reg.file == PROGRAM_UNDEFINED;
+}
+
+
+static struct ureg get_identity_param( struct tnl_program *p )
+{
+ if (is_undef(p->identity))
+ p->identity = register_const4f(p, 0,0,0,1);
+
+ return p->identity;
+}
+
+static void register_matrix_param5( struct tnl_program *p,
+ GLint s0, /* modelview, projection, etc */
+ GLint s1, /* texture matrix number */
+ GLint s2, /* first row */
+ GLint s3, /* last row */
+ GLint s4, /* inverse, transpose, etc */
+ struct ureg *matrix )
+{
+ GLint i;
+
+ /* This is a bit sad as the support is there to pull the whole
+ * matrix out in one go:
+ */
+ for (i = 0; i <= s3 - s2; i++)
+ matrix[i] = register_param5( p, s0, s1, i, i, s4 );
+}
+
+
+static void emit_arg( struct prog_src_register *src,
+ struct ureg reg )
+{
+ src->File = reg.file;
+ src->Index = reg.idx;
+ src->Swizzle = reg.swz;
+ src->Negate = reg.negate ? NEGATE_XYZW : NEGATE_NONE;
+ src->Abs = 0;
+ src->RelAddr = 0;
+ /* Check that bitfield sizes aren't exceeded */
+ ASSERT(src->Index == reg.idx);
+}
+
+
+static void emit_dst( struct prog_dst_register *dst,
+ struct ureg reg, GLuint mask )
+{
+ dst->File = reg.file;
+ dst->Index = reg.idx;
+ /* allow zero as a shorthand for xyzw */
+ dst->WriteMask = mask ? mask : WRITEMASK_XYZW;
+ dst->CondMask = COND_TR; /* always pass cond test */
+ dst->CondSwizzle = SWIZZLE_NOOP;
+ dst->CondSrc = 0;
+ dst->pad = 0;
+ /* Check that bitfield sizes aren't exceeded */
+ ASSERT(dst->Index == reg.idx);
+}
+
+
+static void debug_insn( struct prog_instruction *inst, const char *fn,
+ GLuint line )
+{
+ if (DISASSEM) {
+ static const char *last_fn;
+
+ if (fn != last_fn) {
+ last_fn = fn;
+ _mesa_printf("%s:\n", fn);
+ }
+
+ _mesa_printf("%d:\t", line);
+ _mesa_print_instruction(inst);
+ }
+}
+
+
+static void emit_op3fn(struct tnl_program *p,
+ enum prog_opcode op,
+ struct ureg dest,
+ GLuint mask,
+ struct ureg src0,
+ struct ureg src1,
+ struct ureg src2,
+ const char *fn,
+ GLuint line)
+{
+ GLuint nr;
+ struct prog_instruction *inst;
+
+ assert((GLint) p->program->Base.NumInstructions <= p->max_inst);
+
+ if (p->program->Base.NumInstructions == p->max_inst) {
+ /* need to extend the program's instruction array */
+ struct prog_instruction *newInst;
+
+ /* double the size */
+ p->max_inst *= 2;
+
+ newInst = _mesa_alloc_instructions(p->max_inst);
+ if (!newInst) {
+ _mesa_error(NULL, GL_OUT_OF_MEMORY, "vertex program build");
+ return;
+ }
+
+ _mesa_copy_instructions(newInst,
+ p->program->Base.Instructions,
+ p->program->Base.NumInstructions);
+
+ _mesa_free_instructions(p->program->Base.Instructions,
+ p->program->Base.NumInstructions);
+
+ p->program->Base.Instructions = newInst;
+ }
+
+ nr = p->program->Base.NumInstructions++;
+
+ inst = &p->program->Base.Instructions[nr];
+ inst->Opcode = (enum prog_opcode) op;
+ inst->Data = 0;
+
+ emit_arg( &inst->SrcReg[0], src0 );
+ emit_arg( &inst->SrcReg[1], src1 );
+ emit_arg( &inst->SrcReg[2], src2 );
+
+ emit_dst( &inst->DstReg, dest, mask );
+
+ debug_insn(inst, fn, line);
+}
+
+
+#define emit_op3(p, op, dst, mask, src0, src1, src2) \
+ emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
+
+#define emit_op2(p, op, dst, mask, src0, src1) \
+ emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
+
+#define emit_op1(p, op, dst, mask, src0) \
+ emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
+
+
+static struct ureg make_temp( struct tnl_program *p, struct ureg reg )
+{
+ if (reg.file == PROGRAM_TEMPORARY &&
+ !(p->temp_reserved & (1<<reg.idx)))
+ return reg;
+ else {
+ struct ureg temp = get_temp(p);
+ emit_op1(p, OPCODE_MOV, temp, 0, reg);
+ return temp;
+ }
+}
+
+
+/* Currently no tracking performed of input/output/register size or
+ * active elements. Could be used to reduce these operations, as
+ * could the matrix type.
+ */
+static void emit_matrix_transform_vec4( struct tnl_program *p,
+ struct ureg dest,
+ const struct ureg *mat,
+ struct ureg src)
+{
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_X, src, mat[0]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Y, src, mat[1]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_Z, src, mat[2]);
+ emit_op2(p, OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]);
+}
+
+
+/* This version is much easier to implement if writemasks are not
+ * supported natively on the target or (like SSE), the target doesn't
+ * have a clean/obvious dotproduct implementation.
+ */
+static void emit_transpose_matrix_transform_vec4( struct tnl_program *p,
+ struct ureg dest,
+ const struct ureg *mat,
+ struct ureg src)
+{
+ struct ureg tmp;
+
+ if (dest.file != PROGRAM_TEMPORARY)
+ tmp = get_temp(p);
+ else
+ tmp = dest;
+
+ emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
+ emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
+ emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
+ emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
+
+ if (dest.file != PROGRAM_TEMPORARY)
+ release_temp(p, tmp);
+}
+
+
+static void emit_matrix_transform_vec3( struct tnl_program *p,
+ struct ureg dest,
+ const struct ureg *mat,
+ struct ureg src)
+{
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]);
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]);
+ emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]);
+}
+
+
+static void emit_normalize_vec3( struct tnl_program *p,
+ struct ureg dest,
+ struct ureg src )
+{
+#if 0
+ /* XXX use this when drivers are ready for NRM3 */
+ emit_op1(p, OPCODE_NRM3, dest, WRITEMASK_XYZ, src);
+#else
+ struct ureg tmp = get_temp(p);
+ emit_op2(p, OPCODE_DP3, tmp, WRITEMASK_X, src, src);
+ emit_op1(p, OPCODE_RSQ, tmp, WRITEMASK_X, tmp);
+ emit_op2(p, OPCODE_MUL, dest, 0, src, swizzle1(tmp, X));
+ release_temp(p, tmp);
+#endif
+}
+
+
+static void emit_passthrough( struct tnl_program *p,
+ GLuint input,
+ GLuint output )
+{
+ struct ureg out = register_output(p, output);
+ emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input));
+}
+
+
+static struct ureg get_eye_position( struct tnl_program *p )
+{
+ if (is_undef(p->eye_position)) {
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg modelview[4];
+
+ p->eye_position = reserve_temp(p);
+
+ if (p->mvp_with_dp4) {
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
+ 0, modelview );
+
+ emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
+ }
+ else {
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
+ STATE_MATRIX_TRANSPOSE, modelview );
+
+ emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
+ }
+ }
+
+ return p->eye_position;
+}
+
+
+static struct ureg get_eye_position_z( struct tnl_program *p )
+{
+ if (!is_undef(p->eye_position))
+ return swizzle1(p->eye_position, Z);
+
+ if (is_undef(p->eye_position_z)) {
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg modelview[4];
+
+ p->eye_position_z = reserve_temp(p);
+
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
+ 0, modelview );
+
+ emit_op2(p, OPCODE_DP4, p->eye_position_z, 0, pos, modelview[2]);
+ }
+
+ return p->eye_position_z;
+}
+
+
+static struct ureg get_eye_position_normalized( struct tnl_program *p )
+{
+ if (is_undef(p->eye_position_normalized)) {
+ struct ureg eye = get_eye_position(p);
+ p->eye_position_normalized = reserve_temp(p);
+ emit_normalize_vec3(p, p->eye_position_normalized, eye);
+ }
+
+ return p->eye_position_normalized;
+}
+
+
+static struct ureg get_transformed_normal( struct tnl_program *p )
+{
+ if (is_undef(p->transformed_normal) &&
+ !p->state->need_eye_coords &&
+ !p->state->normalize &&
+ !(p->state->need_eye_coords == p->state->rescale_normals))
+ {
+ p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL );
+ }
+ else if (is_undef(p->transformed_normal))
+ {
+ struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
+ struct ureg mvinv[3];
+ struct ureg transformed_normal = reserve_temp(p);
+
+ if (p->state->need_eye_coords) {
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
+ STATE_MATRIX_INVTRANS, mvinv );
+
+ /* Transform to eye space:
+ */
+ emit_matrix_transform_vec3( p, transformed_normal, mvinv, normal );
+ normal = transformed_normal;
+ }
+
+ /* Normalize/Rescale:
+ */
+ if (p->state->normalize) {
+ emit_normalize_vec3( p, transformed_normal, normal );
+ normal = transformed_normal;
+ }
+ else if (p->state->need_eye_coords == p->state->rescale_normals) {
+ /* This is already adjusted for eye/non-eye rendering:
+ */
+ struct ureg rescale = register_param2(p, STATE_INTERNAL,
+ STATE_NORMAL_SCALE);
+
+ emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal, rescale );
+ normal = transformed_normal;
+ }
+
+ assert(normal.file == PROGRAM_TEMPORARY);
+ p->transformed_normal = normal;
+ }
+
+ return p->transformed_normal;
+}
+
+
+static void build_hpos( struct tnl_program *p )
+{
+ struct ureg pos = register_input( p, VERT_ATTRIB_POS );
+ struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
+ struct ureg mvp[4];
+
+ if (p->mvp_with_dp4) {
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
+ 0, mvp );
+ emit_matrix_transform_vec4( p, hpos, mvp, pos );
+ }
+ else {
+ register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
+ STATE_MATRIX_TRANSPOSE, mvp );
+ emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos );
+ }
+}
+
+
+static GLuint material_attrib( GLuint side, GLuint property )
+{
+ return (property - STATE_AMBIENT) * 2 + side;
+}
+
+
+/**
+ * Get a bitmask of which material values vary on a per-vertex basis.
+ */
+static void set_material_flags( struct tnl_program *p )
+{
+ p->color_materials = 0;
+ p->materials = 0;
+
+ if (p->state->varying_vp_inputs & VERT_BIT_COLOR0) {
+ p->materials =
+ p->color_materials = p->state->light_color_material_mask;
+ }
+
+ p->materials |= (p->state->varying_vp_inputs >> 16);
+}
+
+
+static struct ureg get_material( struct tnl_program *p, GLuint side,
+ GLuint property )
+{
+ GLuint attrib = material_attrib(side, property);
+
+ if (p->color_materials & (1<<attrib))
+ return register_input(p, VERT_ATTRIB_COLOR0);
+ else if (p->materials & (1<<attrib)) {
+ /* Put material values in the GENERIC slots -- they are not used
+ * for anything in fixed function mode.
+ */
+ return register_input( p, attrib + VERT_ATTRIB_GENERIC0 );
+ }
+ else
+ return register_param3( p, STATE_MATERIAL, side, property );
+}
+
+#define SCENE_COLOR_BITS(side) (( MAT_BIT_FRONT_EMISSION | \
+ MAT_BIT_FRONT_AMBIENT | \
+ MAT_BIT_FRONT_DIFFUSE) << (side))
+
+
+/**
+ * Either return a precalculated constant value or emit code to
+ * calculate these values dynamically in the case where material calls
+ * are present between begin/end pairs.
+ *
+ * Probably want to shift this to the program compilation phase - if
+ * we always emitted the calculation here, a smart compiler could
+ * detect that it was constant (given a certain set of inputs), and
+ * lift it out of the main loop. That way the programs created here
+ * would be independent of the vertex_buffer details.
+ */
+static struct ureg get_scenecolor( struct tnl_program *p, GLuint side )
+{
+ if (p->materials & SCENE_COLOR_BITS(side)) {
+ struct ureg lm_ambient = register_param1(p, STATE_LIGHTMODEL_AMBIENT);
+ struct ureg material_emission = get_material(p, side, STATE_EMISSION);
+ struct ureg material_ambient = get_material(p, side, STATE_AMBIENT);
+ struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE);
+ struct ureg tmp = make_temp(p, material_diffuse);
+ emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient,
+ material_ambient, material_emission);
+ return tmp;
+ }
+ else
+ return register_param2( p, STATE_LIGHTMODEL_SCENECOLOR, side );
+}
+
+
+static struct ureg get_lightprod( struct tnl_program *p, GLuint light,
+ GLuint side, GLuint property )
+{
+ GLuint attrib = material_attrib(side, property);
+ if (p->materials & (1<<attrib)) {
+ struct ureg light_value =
+ register_param3(p, STATE_LIGHT, light, property);
+ struct ureg material_value = get_material(p, side, property);
+ struct ureg tmp = get_temp(p);
+ emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value);
+ return tmp;
+ }
+ else
+ return register_param4(p, STATE_LIGHTPROD, light, side, property);
+}
+
+
+static struct ureg calculate_light_attenuation( struct tnl_program *p,
+ GLuint i,
+ struct ureg VPpli,
+ struct ureg dist )
+{
+ struct ureg attenuation = register_param3(p, STATE_LIGHT, i,
+ STATE_ATTENUATION);
+ struct ureg att = get_temp(p);
+
+ /* Calculate spot attenuation:
+ */
+ if (!p->state->unit[i].light_spotcutoff_is_180) {
+ struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_SPOT_DIR_NORMALIZED, i);
+ struct ureg spot = get_temp(p);
+ struct ureg slt = get_temp(p);
+
+ emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm);
+ emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
+ emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
+ emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
+
+ release_temp(p, spot);
+ release_temp(p, slt);
+ }
+
+ /* Calculate distance attenuation:
+ */
+ if (p->state->unit[i].light_attenuated) {
+ /* 1/d,d,d,1/d */
+ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
+ /* 1,d,d*d,1/d */
+ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y));
+ /* 1/dist-atten */
+ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist);
+
+ if (!p->state->unit[i].light_spotcutoff_is_180) {
+ /* dist-atten */
+ emit_op1(p, OPCODE_RCP, dist, 0, dist);
+ /* spot-atten * dist-atten */
+ emit_op2(p, OPCODE_MUL, att, 0, dist, att);
+ }
+ else {
+ /* dist-atten */
+ emit_op1(p, OPCODE_RCP, att, 0, dist);
+ }
+ }
+
+ return att;
+}
+
+
+/**
+ * Compute:
+ * lit.y = MAX(0, dots.x)
+ * lit.z = SLT(0, dots.x)
+ */
+static void emit_degenerate_lit( struct tnl_program *p,
+ struct ureg lit,
+ struct ureg dots )
+{
+ struct ureg id = get_identity_param(p); /* id = {0,0,0,1} */
+
+ /* Note that lit.x & lit.w will not be examined. Note also that
+ * dots.xyzw == dots.xxxx.
+ */
+
+ /* MAX lit, id, dots;
+ */
+ emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots);
+
+ /* result[2] = (in > 0 ? 1 : 0)
+ * SLT lit.z, id.z, dots; # lit.z = (0 < dots.z) ? 1 : 0
+ */
+ emit_op2(p, OPCODE_SLT, lit, WRITEMASK_Z, swizzle1(id,Z), dots);
+}
+
+
+/* Need to add some addtional parameters to allow lighting in object
+ * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
+ * space lighting.
+ */
+static void build_lighting( struct tnl_program *p )
+{
+ const GLboolean twoside = p->state->light_twoside;
+ const GLboolean separate = p->state->separate_specular;
+ GLuint nr_lights = 0, count = 0;
+ struct ureg normal = get_transformed_normal(p);
+ struct ureg lit = get_temp(p);
+ struct ureg dots = get_temp(p);
+ struct ureg _col0 = undef, _col1 = undef;
+ struct ureg _bfc0 = undef, _bfc1 = undef;
+ GLuint i;
+
+ /*
+ * NOTE:
+ * dots.x = dot(normal, VPpli)
+ * dots.y = dot(normal, halfAngle)
+ * dots.z = back.shininess
+ * dots.w = front.shininess
+ */
+
+ for (i = 0; i < MAX_LIGHTS; i++)
+ if (p->state->unit[i].light_enabled)
+ nr_lights++;
+
+ set_material_flags(p);
+
+ {
+ if (!p->state->material_shininess_is_zero) {
+ struct ureg shininess = get_material(p, 0, STATE_SHININESS);
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X));
+ release_temp(p, shininess);
+ }
+
+ _col0 = make_temp(p, get_scenecolor(p, 0));
+ if (separate)
+ _col1 = make_temp(p, get_identity_param(p));
+ else
+ _col1 = _col0;
+ }
+
+ if (twoside) {
+ if (!p->state->material_shininess_is_zero) {
+ /* Note that we negate the back-face specular exponent here.
+ * The negation will be un-done later in the back-face code below.
+ */
+ struct ureg shininess = get_material(p, 1, STATE_SHININESS);
+ emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
+ negate(swizzle1(shininess,X)));
+ release_temp(p, shininess);
+ }
+
+ _bfc0 = make_temp(p, get_scenecolor(p, 1));
+ if (separate)
+ _bfc1 = make_temp(p, get_identity_param(p));
+ else
+ _bfc1 = _bfc0;
+ }
+
+ /* If no lights, still need to emit the scenecolor.
+ */
+ {
+ struct ureg res0 = register_output( p, VERT_RESULT_COL0 );
+ emit_op1(p, OPCODE_MOV, res0, 0, _col0);
+ }
+
+ if (separate) {
+ struct ureg res1 = register_output( p, VERT_RESULT_COL1 );
+ emit_op1(p, OPCODE_MOV, res1, 0, _col1);
+ }
+
+ if (twoside) {
+ struct ureg res0 = register_output( p, VERT_RESULT_BFC0 );
+ emit_op1(p, OPCODE_MOV, res0, 0, _bfc0);
+ }
+
+ if (twoside && separate) {
+ struct ureg res1 = register_output( p, VERT_RESULT_BFC1 );
+ emit_op1(p, OPCODE_MOV, res1, 0, _bfc1);
+ }
+
+ if (nr_lights == 0) {
+ release_temps(p);
+ return;
+ }
+
+ for (i = 0; i < MAX_LIGHTS; i++) {
+ if (p->state->unit[i].light_enabled) {
+ struct ureg half = undef;
+ struct ureg att = undef, VPpli = undef;
+
+ count++;
+
+ if (p->state->unit[i].light_eyepos3_is_zero) {
+ /* Can used precomputed constants in this case.
+ * Attenuation never applies to infinite lights.
+ */
+ VPpli = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_POSITION_NORMALIZED, i);
+
+ if (!p->state->material_shininess_is_zero) {
+ if (p->state->light_local_viewer) {
+ struct ureg eye_hat = get_eye_position_normalized(p);
+ half = get_temp(p);
+ emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+ emit_normalize_vec3(p, half, half);
+ }
+ else {
+ half = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_HALF_VECTOR, i);
+ }
+ }
+ }
+ else {
+ struct ureg Ppli = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_POSITION, i);
+ struct ureg V = get_eye_position(p);
+ struct ureg dist = get_temp(p);
+
+ VPpli = get_temp(p);
+
+ /* Calculate VPpli vector
+ */
+ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
+
+ /* Normalize VPpli. The dist value also used in
+ * attenuation below.
+ */
+ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
+ emit_op1(p, OPCODE_RSQ, dist, 0, dist);
+ emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
+
+ /* Calculate attenuation:
+ */
+ if (!p->state->unit[i].light_spotcutoff_is_180 ||
+ p->state->unit[i].light_attenuated) {
+ att = calculate_light_attenuation(p, i, VPpli, dist);
+ }
+
+ /* Calculate viewer direction, or use infinite viewer:
+ */
+ if (!p->state->material_shininess_is_zero) {
+ half = get_temp(p);
+
+ if (p->state->light_local_viewer) {
+ struct ureg eye_hat = get_eye_position_normalized(p);
+ emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+ }
+ else {
+ struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
+ emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
+ }
+
+ emit_normalize_vec3(p, half, half);
+ }
+
+ release_temp(p, dist);
+ }
+
+ /* Calculate dot products:
+ */
+ if (p->state->material_shininess_is_zero) {
+ emit_op2(p, OPCODE_DP3, dots, 0, normal, VPpli);
+ }
+ else {
+ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
+ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
+ }
+
+ /* Front face lighting:
+ */
+ {
+ struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT);
+ struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE);
+ struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR);
+ struct ureg res0, res1;
+ GLuint mask0, mask1;
+
+ if (count == nr_lights) {
+ if (separate) {
+ mask0 = WRITEMASK_XYZ;
+ mask1 = WRITEMASK_XYZ;
+ res0 = register_output( p, VERT_RESULT_COL0 );
+ res1 = register_output( p, VERT_RESULT_COL1 );
+ }
+ else {
+ mask0 = 0;
+ mask1 = WRITEMASK_XYZ;
+ res0 = _col0;
+ res1 = register_output( p, VERT_RESULT_COL0 );
+ }
+ }
+ else {
+ mask0 = 0;
+ mask1 = 0;
+ res0 = _col0;
+ res1 = _col1;
+ }
+
+ if (!is_undef(att)) {
+ /* light is attenuated by distance */
+ emit_op1(p, OPCODE_LIT, lit, 0, dots);
+ emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
+ emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
+ }
+ else if (!p->state->material_shininess_is_zero) {
+ /* there's a non-zero specular term */
+ emit_op1(p, OPCODE_LIT, lit, 0, dots);
+ emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0);
+ }
+ else {
+ /* no attenutation, no specular */
+ emit_degenerate_lit(p, lit, dots);
+ emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0);
+ }
+
+ emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0);
+ emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1);
+
+ release_temp(p, ambient);
+ release_temp(p, diffuse);
+ release_temp(p, specular);
+ }
+
+ /* Back face lighting:
+ */
+ if (twoside) {
+ struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT);
+ struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE);
+ struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR);
+ struct ureg res0, res1;
+ GLuint mask0, mask1;
+
+ if (count == nr_lights) {
+ if (separate) {
+ mask0 = WRITEMASK_XYZ;
+ mask1 = WRITEMASK_XYZ;
+ res0 = register_output( p, VERT_RESULT_BFC0 );
+ res1 = register_output( p, VERT_RESULT_BFC1 );
+ }
+ else {
+ mask0 = 0;
+ mask1 = WRITEMASK_XYZ;
+ res0 = _bfc0;
+ res1 = register_output( p, VERT_RESULT_BFC0 );
+ }
+ }
+ else {
+ res0 = _bfc0;
+ res1 = _bfc1;
+ mask0 = 0;
+ mask1 = 0;
+ }
+
+ /* For the back face we need to negate the X and Y component
+ * dot products. dots.Z has the negated back-face specular
+ * exponent. We swizzle that into the W position. This
+ * negation makes the back-face specular term positive again.
+ */
+ dots = negate(swizzle(dots,X,Y,W,Z));
+
+ if (!is_undef(att)) {
+ emit_op1(p, OPCODE_LIT, lit, 0, dots);
+ emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
+ emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0);
+ }
+ else if (!p->state->material_shininess_is_zero) {
+ emit_op1(p, OPCODE_LIT, lit, 0, dots);
+ emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/
+ }
+ else {
+ emit_degenerate_lit(p, lit, dots);
+ emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0);
+ }
+
+ emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
+ emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
+ /* restore dots to its original state for subsequent lights
+ * by negating and swizzling again.
+ */
+ dots = negate(swizzle(dots,X,Y,W,Z));
+
+ release_temp(p, ambient);
+ release_temp(p, diffuse);
+ release_temp(p, specular);
+ }
+
+ release_temp(p, half);
+ release_temp(p, VPpli);
+ release_temp(p, att);
+ }
+ }
+
+ release_temps( p );
+}
+
+
+static void build_fog( struct tnl_program *p )
+{
+ struct ureg fog = register_output(p, VERT_RESULT_FOGC);
+ struct ureg input;
+
+ if (p->state->fog_source_is_depth) {
+ input = get_eye_position_z(p);
+ }
+ else {
+ input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X);
+ }
+
+ /* result.fog = {abs(f),0,0,1}; */
+ emit_op1(p, OPCODE_ABS, fog, WRITEMASK_X, input);
+ emit_op1(p, OPCODE_MOV, fog, WRITEMASK_YZW, get_identity_param(p));
+}
+
+
+static void build_reflect_texgen( struct tnl_program *p,
+ struct ureg dest,
+ GLuint writemask )
+{
+ struct ureg normal = get_transformed_normal(p);
+ struct ureg eye_hat = get_eye_position_normalized(p);
+ struct ureg tmp = get_temp(p);
+
+ /* n.u */
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
+ /* 2n.u */
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
+ /* (-2n.u)n + u */
+ emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat);
+
+ release_temp(p, tmp);
+}
+
+
+static void build_sphere_texgen( struct tnl_program *p,
+ struct ureg dest,
+ GLuint writemask )
+{
+ struct ureg normal = get_transformed_normal(p);
+ struct ureg eye_hat = get_eye_position_normalized(p);
+ struct ureg tmp = get_temp(p);
+ struct ureg half = register_scalar_const(p, .5);
+ struct ureg r = get_temp(p);
+ struct ureg inv_m = get_temp(p);
+ struct ureg id = get_identity_param(p);
+
+ /* Could share the above calculations, but it would be
+ * a fairly odd state for someone to set (both sphere and
+ * reflection active for different texture coordinate
+ * components. Of course - if two texture units enable
+ * reflect and/or sphere, things start to tilt in favour
+ * of seperating this out:
+ */
+
+ /* n.u */
+ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat);
+ /* 2n.u */
+ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp);
+ /* (-2n.u)n + u */
+ emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat);
+ /* r + 0,0,1 */
+ emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z));
+ /* rx^2 + ry^2 + (rz+1)^2 */
+ emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp);
+ /* 2/m */
+ emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
+ /* 1/m */
+ emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half);
+ /* r/m + 1/2 */
+ emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half);
+
+ release_temp(p, tmp);
+ release_temp(p, r);
+ release_temp(p, inv_m);
+}
+
+
+static void build_texture_transform( struct tnl_program *p )
+{
+ GLuint i, j;
+
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+
+ if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i)))
+ continue;
+
+ if (p->state->unit[i].texgen_enabled ||
+ p->state->unit[i].texmat_enabled) {
+
+ GLuint texmat_enabled = p->state->unit[i].texmat_enabled;
+ struct ureg out = register_output(p, VERT_RESULT_TEX0 + i);
+ struct ureg out_texgen = undef;
+
+ if (p->state->unit[i].texgen_enabled) {
+ GLuint copy_mask = 0;
+ GLuint sphere_mask = 0;
+ GLuint reflect_mask = 0;
+ GLuint normal_mask = 0;
+ GLuint modes[4];
+
+ if (texmat_enabled)
+ out_texgen = get_temp(p);
+ else
+ out_texgen = out;
+
+ modes[0] = p->state->unit[i].texgen_mode0;
+ modes[1] = p->state->unit[i].texgen_mode1;
+ modes[2] = p->state->unit[i].texgen_mode2;
+ modes[3] = p->state->unit[i].texgen_mode3;
+
+ for (j = 0; j < 4; j++) {
+ switch (modes[j]) {
+ case TXG_OBJ_LINEAR: {
+ struct ureg obj = register_input(p, VERT_ATTRIB_POS);
+ struct ureg plane =
+ register_param3(p, STATE_TEXGEN, i,
+ STATE_TEXGEN_OBJECT_S + j);
+
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ obj, plane );
+ break;
+ }
+ case TXG_EYE_LINEAR: {
+ struct ureg eye = get_eye_position(p);
+ struct ureg plane =
+ register_param3(p, STATE_TEXGEN, i,
+ STATE_TEXGEN_EYE_S + j);
+
+ emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j,
+ eye, plane );
+ break;
+ }
+ case TXG_SPHERE_MAP:
+ sphere_mask |= WRITEMASK_X << j;
+ break;
+ case TXG_REFLECTION_MAP:
+ reflect_mask |= WRITEMASK_X << j;
+ break;
+ case TXG_NORMAL_MAP:
+ normal_mask |= WRITEMASK_X << j;
+ break;
+ case TXG_NONE:
+ copy_mask |= WRITEMASK_X << j;
+ }
+ }
+
+ if (sphere_mask) {
+ build_sphere_texgen(p, out_texgen, sphere_mask);
+ }
+
+ if (reflect_mask) {
+ build_reflect_texgen(p, out_texgen, reflect_mask);
+ }
+
+ if (normal_mask) {
+ struct ureg normal = get_transformed_normal(p);
+ emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
+ }
+
+ if (copy_mask) {
+ struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i);
+ emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in );
+ }
+ }
+
+ if (texmat_enabled) {
+ struct ureg texmat[4];
+ struct ureg in = (!is_undef(out_texgen) ?
+ out_texgen :
+ register_input(p, VERT_ATTRIB_TEX0+i));
+ if (p->mvp_with_dp4) {
+ register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+ 0, texmat );
+ emit_matrix_transform_vec4( p, out, texmat, in );
+ }
+ else {
+ register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+ STATE_MATRIX_TRANSPOSE, texmat );
+ emit_transpose_matrix_transform_vec4( p, out, texmat, in );
+ }
+ }
+
+ release_temps(p);
+ }
+ else {
+ emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i);
+ }
+ }
+}
+
+
+/**
+ * Point size attenuation computation.
+ */
+static void build_atten_pointsize( struct tnl_program *p )
+{
+ struct ureg eye = get_eye_position_z(p);
+ struct ureg state_size = register_param1(p, STATE_POINT_SIZE);
+ struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION);
+ struct ureg out = register_output(p, VERT_RESULT_PSIZ);
+ struct ureg ut = get_temp(p);
+
+ /* dist = |eyez| */
+ emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z));
+ /* p1 + dist * (p2 + dist * p3); */
+ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
+ swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y));
+ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y),
+ ut, swizzle1(state_attenuation, X));
+
+ /* 1 / sqrt(factor) */
+ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut );
+
+#if 0
+ /* out = pointSize / sqrt(factor) */
+ emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size);
+#else
+ /* this is a good place to clamp the point size since there's likely
+ * no hardware registers to clamp point size at rasterization time.
+ */
+ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size);
+ emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y));
+ emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z));
+#endif
+
+ release_temp(p, ut);
+}
+
+
+/**
+ * Pass-though per-vertex point size, from user's point size array.
+ */
+static void build_array_pointsize( struct tnl_program *p )
+{
+ struct ureg in = register_input(p, VERT_ATTRIB_POINT_SIZE);
+ struct ureg out = register_output(p, VERT_RESULT_PSIZ);
+ emit_op1(p, OPCODE_MOV, out, WRITEMASK_X, in);
+}
+
+
+static void build_tnl_program( struct tnl_program *p )
+{
+ /* Emit the program, starting with modelviewproject:
+ */
+ build_hpos(p);
+
+ /* Lighting calculations:
+ */
+ if (p->state->fragprog_inputs_read & (FRAG_BIT_COL0|FRAG_BIT_COL1)) {
+ if (p->state->light_global_enabled)
+ build_lighting(p);
+ else {
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0)
+ emit_passthrough(p, VERT_ATTRIB_COLOR0, VERT_RESULT_COL0);
+
+ if (p->state->fragprog_inputs_read & FRAG_BIT_COL1)
+ emit_passthrough(p, VERT_ATTRIB_COLOR1, VERT_RESULT_COL1);
+ }
+ }
+
+ if (p->state->fragprog_inputs_read & FRAG_BIT_FOGC)
+ build_fog(p);
+
+ if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY)
+ build_texture_transform(p);
+
+ if (p->state->point_attenuated)
+ build_atten_pointsize(p);
+ else if (p->state->point_array)
+ build_array_pointsize(p);
+
+ /* Finish up:
+ */
+ emit_op1(p, OPCODE_END, undef, 0, undef);
+
+ /* Disassemble:
+ */
+ if (DISASSEM) {
+ _mesa_printf ("\n");
+ }
+}
+
+
+static void
+create_new_program( const struct state_key *key,
+ struct gl_vertex_program *program,
+ GLboolean mvp_with_dp4,
+ GLuint max_temps)
+{
+ struct tnl_program p;
+
+ _mesa_memset(&p, 0, sizeof(p));
+ p.state = key;
+ p.program = program;
+ p.eye_position = undef;
+ p.eye_position_z = undef;
+ p.eye_position_normalized = undef;
+ p.transformed_normal = undef;
+ p.identity = undef;
+ p.temp_in_use = 0;
+ p.mvp_with_dp4 = mvp_with_dp4;
+
+ if (max_temps >= sizeof(int) * 8)
+ p.temp_reserved = 0;
+ else
+ p.temp_reserved = ~((1<<max_temps)-1);
+
+ /* Start by allocating 32 instructions.
+ * If we need more, we'll grow the instruction array as needed.
+ */
+ p.max_inst = 32;
+ p.program->Base.Instructions = _mesa_alloc_instructions(p.max_inst);
+ p.program->Base.String = NULL;
+ p.program->Base.NumInstructions =
+ p.program->Base.NumTemporaries =
+ p.program->Base.NumParameters =
+ p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
+ p.program->Base.Parameters = _mesa_new_parameter_list();
+ p.program->Base.InputsRead = 0;
+ p.program->Base.OutputsWritten = 0;
+
+ build_tnl_program( &p );
+}
+
+
+/**
+ * Return a vertex program which implements the current fixed-function
+ * transform/lighting/texgen operations.
+ * XXX move this into core mesa (main/)
+ */
+struct gl_vertex_program *
+_mesa_get_fixed_func_vertex_program(GLcontext *ctx)
+{
+ struct gl_vertex_program *prog;
+ struct state_key key;
+
+ /* Grab all the relevent state and put it in a single structure:
+ */
+ make_state_key(ctx, &key);
+
+ /* Look for an already-prepared program for this state:
+ */
+ prog = (struct gl_vertex_program *)
+ _mesa_search_program_cache(ctx->VertexProgram.Cache, &key, sizeof(key));
+
+ if (!prog) {
+ /* OK, we'll have to build a new one */
+ if (0)
+ _mesa_printf("Build new TNL program\n");
+
+ prog = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+ if (!prog)
+ return NULL;
+
+ create_new_program( &key, prog,
+ ctx->mvp_with_dp4,
+ ctx->Const.VertexProgram.MaxTemps );
+
+#if 0
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB,
+ &prog->Base );
+#endif
+ _mesa_program_cache_insert(ctx, ctx->VertexProgram.Cache,
+ &key, sizeof(key), &prog->Base);
+ }
+
+ return prog;
+}
diff --git a/mesalib/src/mesa/main/ffvertex_prog.h b/mesalib/src/mesa/main/ffvertex_prog.h
new file mode 100644
index 000000000..38dc5fbb8
--- /dev/null
+++ b/mesalib/src/mesa/main/ffvertex_prog.h
@@ -0,0 +1,40 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef FFVERTEX_PROG_H
+#define FFVERTEX_PROG_H
+
+
+#include "main/mtypes.h"
+
+struct gl_vertex_program *
+_mesa_get_fixed_func_vertex_program(GLcontext *ctx);
+
+
+
+#endif /* FFVERTEX_PROG_H */
diff --git a/mesalib/src/mesa/main/fog.c b/mesalib/src/mesa/main/fog.c
new file mode 100644
index 000000000..4323d3db8
--- /dev/null
+++ b/mesalib/src/mesa/main/fog.c
@@ -0,0 +1,188 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "colormac.h"
+#include "context.h"
+#include "fog.h"
+#include "mtypes.h"
+
+
+
+void GLAPIENTRY
+_mesa_Fogf(GLenum pname, GLfloat param)
+{
+ _mesa_Fogfv(pname, &param);
+}
+
+
+void GLAPIENTRY
+_mesa_Fogi(GLenum pname, GLint param )
+{
+ GLfloat fparam = (GLfloat) param;
+ _mesa_Fogfv(pname, &fparam);
+}
+
+
+void GLAPIENTRY
+_mesa_Fogiv(GLenum pname, const GLint *params )
+{
+ GLfloat p[4];
+ switch (pname) {
+ case GL_FOG_MODE:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_INDEX:
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ p[0] = (GLfloat) *params;
+ break;
+ case GL_FOG_COLOR:
+ p[0] = INT_TO_FLOAT( params[0] );
+ p[1] = INT_TO_FLOAT( params[1] );
+ p[2] = INT_TO_FLOAT( params[2] );
+ p[3] = INT_TO_FLOAT( params[3] );
+ break;
+ default:
+ /* Error will be caught later in _mesa_Fogfv */
+ ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ _mesa_Fogfv(pname, p);
+}
+
+
+#define UPDATE_FOG_SCALE(ctx) do {\
+ if (ctx->Fog.End == ctx->Fog.Start)\
+ ctx->Fog._Scale = 1.0f;\
+ else\
+ ctx->Fog._Scale = 1.0f / (ctx->Fog.End - ctx->Fog.Start);\
+ } while(0)
+
+
+void GLAPIENTRY
+_mesa_Fogfv( GLenum pname, const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLenum m;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_FOG_MODE:
+ m = (GLenum) (GLint) *params;
+ switch (m) {
+ case GL_LINEAR:
+ case GL_EXP:
+ case GL_EXP2:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFog" );
+ return;
+ }
+ if (ctx->Fog.Mode == m)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Mode = m;
+ break;
+ case GL_FOG_DENSITY:
+ if (*params<0.0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glFog" );
+ return;
+ }
+ if (ctx->Fog.Density == *params)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Density = *params;
+ break;
+ case GL_FOG_START:
+ if (ctx->Fog.Start == *params)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Start = *params;
+ UPDATE_FOG_SCALE(ctx);
+ break;
+ case GL_FOG_END:
+ if (ctx->Fog.End == *params)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.End = *params;
+ UPDATE_FOG_SCALE(ctx);
+ break;
+ case GL_FOG_INDEX:
+ if (ctx->Fog.Index == *params)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Index = *params;
+ break;
+ case GL_FOG_COLOR:
+ if (TEST_EQ_4V(ctx->Fog.Color, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Color[0] = CLAMP(params[0], 0.0F, 1.0F);
+ ctx->Fog.Color[1] = CLAMP(params[1], 0.0F, 1.0F);
+ ctx->Fog.Color[2] = CLAMP(params[2], 0.0F, 1.0F);
+ ctx->Fog.Color[3] = CLAMP(params[3], 0.0F, 1.0F);
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT: {
+ GLenum p = (GLenum) (GLint) *params;
+ if (!ctx->Extensions.EXT_fog_coord ||
+ (p != GL_FOG_COORDINATE_EXT && p != GL_FRAGMENT_DEPTH_EXT)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glFog");
+ return;
+ }
+ if (ctx->Fog.FogCoordinateSource == p)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.FogCoordinateSource = p;
+ break;
+ }
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFog" );
+ return;
+ }
+
+ if (ctx->Driver.Fogfv) {
+ (*ctx->Driver.Fogfv)( ctx, pname, params );
+ }
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+void _mesa_init_fog( GLcontext * ctx )
+{
+ /* 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;
+ ctx->Fog.ColorSumEnabled = GL_FALSE;
+ ctx->Fog.FogCoordinateSource = GL_FRAGMENT_DEPTH_EXT;
+ ctx->Fog._Scale = 1.0f;
+}
diff --git a/mesalib/src/mesa/main/fog.h b/mesalib/src/mesa/main/fog.h
new file mode 100644
index 000000000..a14d19cdb
--- /dev/null
+++ b/mesalib/src/mesa/main/fog.h
@@ -0,0 +1,66 @@
+/**
+ * \file fog.h
+ * Fog operations.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef FOG_H
+#define FOG_H
+
+
+#include "mtypes.h"
+
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_Fogf(GLenum pname, GLfloat param);
+
+extern void GLAPIENTRY
+_mesa_Fogi(GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_Fogfv(GLenum pname, const GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_Fogiv(GLenum pname, const GLint *params );
+
+extern void _mesa_init_fog( GLcontext * ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_fog( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c
new file mode 100644
index 000000000..dc79b8ca6
--- /dev/null
+++ b/mesalib/src/mesa/main/framebuffer.c
@@ -0,0 +1,961 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * Functions for allocating/managing framebuffers and renderbuffers.
+ * Also, routines for reading/writing renderbuffer data as ubytes,
+ * ushorts, uints, etc.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "buffers.h"
+#include "context.h"
+#include "depthstencil.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "texobj.h"
+
+
+
+/**
+ * Compute/set the _DepthMax field for the given framebuffer.
+ * This value depends on the Z buffer resolution.
+ */
+static void
+compute_depth_max(struct gl_framebuffer *fb)
+{
+ if (fb->Visual.depthBits == 0) {
+ /* Special case. Even if we don't have a depth buffer we need
+ * good values for DepthMax for Z vertex transformation purposes
+ * and for per-fragment fog computation.
+ */
+ fb->_DepthMax = (1 << 16) - 1;
+ }
+ else if (fb->Visual.depthBits < 32) {
+ fb->_DepthMax = (1 << fb->Visual.depthBits) - 1;
+ }
+ else {
+ /* Special case since shift values greater than or equal to the
+ * number of bits in the left hand expression's type are undefined.
+ */
+ fb->_DepthMax = 0xffffffff;
+ }
+ fb->_DepthMaxF = (GLfloat) fb->_DepthMax;
+
+ /* Minimum resolvable depth value, for polygon offset */
+ fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF;
+}
+
+
+/**
+ * Create and initialize a gl_framebuffer object.
+ * This is intended for creating _window_system_ framebuffers, not generic
+ * framebuffer objects ala GL_EXT_framebuffer_object.
+ *
+ * \sa _mesa_new_framebuffer
+ */
+struct gl_framebuffer *
+_mesa_create_framebuffer(const GLvisual *visual)
+{
+ struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);
+ assert(visual);
+ if (fb) {
+ _mesa_initialize_framebuffer(fb, visual);
+ }
+ return fb;
+}
+
+
+/**
+ * Allocate a new gl_framebuffer object.
+ * This is the default function for ctx->Driver.NewFramebuffer().
+ * This is for allocating user-created framebuffers, not window-system
+ * framebuffers!
+ * \sa _mesa_create_framebuffer
+ */
+struct gl_framebuffer *
+_mesa_new_framebuffer(GLcontext *ctx, GLuint name)
+{
+ struct gl_framebuffer *fb;
+ (void) ctx;
+ assert(name != 0);
+ fb = CALLOC_STRUCT(gl_framebuffer);
+ if (fb) {
+ fb->Name = name;
+ fb->RefCount = 1;
+ fb->_NumColorDrawBuffers = 1;
+ fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
+ fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
+ fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
+ fb->_ColorReadBufferIndex = BUFFER_COLOR0;
+ fb->Delete = _mesa_destroy_framebuffer;
+ _glthread_INIT_MUTEX(fb->Mutex);
+ }
+ return fb;
+}
+
+
+/**
+ * Initialize a gl_framebuffer object. Typically used to initialize
+ * window system-created framebuffers, not user-created framebuffers.
+ * \sa _mesa_create_framebuffer
+ */
+void
+_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
+{
+ assert(fb);
+ assert(visual);
+
+ _mesa_bzero(fb, sizeof(struct gl_framebuffer));
+
+ _glthread_INIT_MUTEX(fb->Mutex);
+
+ fb->RefCount = 1;
+
+ /* save the visual */
+ fb->Visual = *visual;
+
+ /* Init read/draw renderbuffer state */
+ if (visual->doubleBufferMode) {
+ fb->_NumColorDrawBuffers = 1;
+ fb->ColorDrawBuffer[0] = GL_BACK;
+ fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;
+ fb->ColorReadBuffer = GL_BACK;
+ fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;
+ }
+ else {
+ fb->_NumColorDrawBuffers = 1;
+ fb->ColorDrawBuffer[0] = GL_FRONT;
+ fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;
+ fb->ColorReadBuffer = GL_FRONT;
+ fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;
+ }
+
+ fb->Delete = _mesa_destroy_framebuffer;
+ fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
+
+ compute_depth_max(fb);
+}
+
+
+/**
+ * Deallocate buffer and everything attached to it.
+ * Typically called via the gl_framebuffer->Delete() method.
+ */
+void
+_mesa_destroy_framebuffer(struct gl_framebuffer *fb)
+{
+ if (fb) {
+ _mesa_free_framebuffer_data(fb);
+ _mesa_free(fb);
+ }
+}
+
+
+/**
+ * Free all the data hanging off the given gl_framebuffer, but don't free
+ * the gl_framebuffer object itself.
+ */
+void
+_mesa_free_framebuffer_data(struct gl_framebuffer *fb)
+{
+ GLuint i;
+
+ assert(fb);
+ assert(fb->RefCount == 0);
+
+ _glthread_DESTROY_MUTEX(fb->Mutex);
+
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
+ if (att->Renderbuffer) {
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ }
+ if (att->Texture) {
+ _mesa_reference_texobj(&att->Texture, NULL);
+ }
+ ASSERT(!att->Renderbuffer);
+ ASSERT(!att->Texture);
+ att->Type = GL_NONE;
+ }
+
+ /* unbind _Depth/_StencilBuffer to decr ref counts */
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);
+}
+
+
+/**
+ * Set *ptr to point to fb, with refcounting and locking.
+ */
+void
+_mesa_reference_framebuffer(struct gl_framebuffer **ptr,
+ struct gl_framebuffer *fb)
+{
+ assert(ptr);
+ if (*ptr == fb) {
+ /* no change */
+ return;
+ }
+
+ if (*ptr) {
+ /* unreference old renderbuffer */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_framebuffer *oldFb = *ptr;
+
+ _glthread_LOCK_MUTEX(oldFb->Mutex);
+ ASSERT(oldFb->RefCount > 0);
+ oldFb->RefCount--;
+ deleteFlag = (oldFb->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldFb->Mutex);
+
+ if (deleteFlag)
+ oldFb->Delete(oldFb);
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (fb) {
+ _glthread_LOCK_MUTEX(fb->Mutex);
+ fb->RefCount++;
+ _glthread_UNLOCK_MUTEX(fb->Mutex);
+ *ptr = fb;
+ }
+}
+
+
+/**
+ * Resize the given framebuffer's renderbuffers to the new width and height.
+ * This should only be used for window-system framebuffers, not
+ * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
+ * This will typically be called via ctx->Driver.ResizeBuffers() or directly
+ * from a device driver.
+ *
+ * \note it's possible for ctx to be null since a window can be resized
+ * without a currently bound rendering context.
+ */
+void
+_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint width, GLuint height)
+{
+ GLuint i;
+
+ /* XXX I think we could check if the size is not changing
+ * and return early.
+ */
+
+ /* For window system framebuffers, Name is zero */
+ assert(fb->Name == 0);
+
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
+ if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {
+ struct gl_renderbuffer *rb = att->Renderbuffer;
+ /* only resize if size is changing */
+ if (rb->Width != width || rb->Height != height) {
+ /* could just as well pass rb->_ActualFormat here */
+ if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
+ ASSERT(rb->Width == width);
+ ASSERT(rb->Height == height);
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
+ /* no return */
+ }
+ }
+ }
+ }
+
+ if (fb->_DepthBuffer) {
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ if (rb->Width != width || rb->Height != height) {
+ if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
+ }
+ }
+ }
+
+ if (fb->_StencilBuffer) {
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ if (rb->Width != width || rb->Height != height) {
+ if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
+ }
+ }
+ }
+
+ fb->Width = width;
+ fb->Height = height;
+
+ if (ctx) {
+ /* update scissor / window bounds */
+ _mesa_update_draw_buffer_bounds(ctx);
+ /* Signal new buffer state so that swrast will update its clipping
+ * info (the CLIP_BIT flag).
+ */
+ ctx->NewState |= _NEW_BUFFERS;
+ }
+}
+
+
+
+/**
+ * XXX THIS IS OBSOLETE - drivers should take care of detecting window
+ * size changes and act accordingly, likely calling _mesa_resize_framebuffer().
+ *
+ * GL_MESA_resize_buffers extension.
+ *
+ * When this function is called, we'll ask the window system how large
+ * the current window is. If it's a new size, we'll call the driver's
+ * ResizeBuffers function. The driver will then resize its color buffers
+ * as needed, and maybe call the swrast's routine for reallocating
+ * swrast-managed depth/stencil/accum/etc buffers.
+ * \note This function should only be called through the GL API, not
+ * from device drivers (as was done in the past).
+ */
+void
+_mesa_resizebuffers( GLcontext *ctx )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glResizeBuffersMESA\n");
+
+ if (!ctx->Driver.GetBufferSize) {
+ return;
+ }
+
+ if (ctx->WinSysDrawBuffer) {
+ GLuint newWidth, newHeight;
+ GLframebuffer *buffer = ctx->WinSysDrawBuffer;
+
+ assert(buffer->Name == 0);
+
+ /* ask device driver for size of output buffer */
+ ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
+
+ /* see if size of device driver's color buffer (window) has changed */
+ if (buffer->Width != newWidth || buffer->Height != newHeight) {
+ if (ctx->Driver.ResizeBuffers)
+ ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
+ }
+ }
+
+ if (ctx->WinSysReadBuffer
+ && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) {
+ GLuint newWidth, newHeight;
+ GLframebuffer *buffer = ctx->WinSysReadBuffer;
+
+ assert(buffer->Name == 0);
+
+ /* ask device driver for size of read buffer */
+ ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );
+
+ /* see if size of device driver's color buffer (window) has changed */
+ if (buffer->Width != newWidth || buffer->Height != newHeight) {
+ if (ctx->Driver.ResizeBuffers)
+ ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
+ }
+ }
+
+ ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
+}
+
+
+/*
+ * XXX THIS IS OBSOLETE
+ */
+void GLAPIENTRY
+_mesa_ResizeBuffersMESA( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->Extensions.MESA_resize_buffers)
+ _mesa_resizebuffers( ctx );
+}
+
+
+
+/**
+ * Examine all the framebuffer's renderbuffers to update the Width/Height
+ * fields of the framebuffer. If we have renderbuffers with different
+ * sizes, set the framebuffer's width and height to the min size.
+ * Note: this is only intended for user-created framebuffers, not
+ * window-system framebuffes.
+ */
+static void
+update_framebuffer_size(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ GLuint minWidth = ~0, minHeight = ~0;
+ GLuint i;
+
+ /* user-created framebuffers only */
+ assert(fb->Name);
+
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
+ const struct gl_renderbuffer *rb = att->Renderbuffer;
+ if (rb) {
+ minWidth = MIN2(minWidth, rb->Width);
+ minHeight = MIN2(minHeight, rb->Height);
+ }
+ }
+
+ if (minWidth != ~0) {
+ fb->Width = minWidth;
+ fb->Height = minHeight;
+ }
+ else {
+ fb->Width = 0;
+ fb->Height = 0;
+ }
+}
+
+
+/**
+ * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields.
+ * These values are computed from the buffer's width and height and
+ * the scissor box, if it's enabled.
+ * \param ctx the GL context.
+ */
+void
+_mesa_update_draw_buffer_bounds(GLcontext *ctx)
+{
+ struct gl_framebuffer *buffer = ctx->DrawBuffer;
+
+ if (!buffer)
+ return;
+
+ if (buffer->Name) {
+ /* user-created framebuffer size depends on the renderbuffers */
+ update_framebuffer_size(ctx, buffer);
+ }
+
+ buffer->_Xmin = 0;
+ buffer->_Ymin = 0;
+ buffer->_Xmax = buffer->Width;
+ buffer->_Ymax = buffer->Height;
+
+ if (ctx->Scissor.Enabled) {
+ if (ctx->Scissor.X > buffer->_Xmin) {
+ buffer->_Xmin = ctx->Scissor.X;
+ }
+ if (ctx->Scissor.Y > buffer->_Ymin) {
+ buffer->_Ymin = ctx->Scissor.Y;
+ }
+ if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {
+ buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;
+ }
+ if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {
+ buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;
+ }
+ /* finally, check for empty region */
+ if (buffer->_Xmin > buffer->_Xmax) {
+ buffer->_Xmin = buffer->_Xmax;
+ }
+ if (buffer->_Ymin > buffer->_Ymax) {
+ buffer->_Ymin = buffer->_Ymax;
+ }
+ }
+
+ ASSERT(buffer->_Xmin <= buffer->_Xmax);
+ ASSERT(buffer->_Ymin <= buffer->_Ymax);
+}
+
+
+/**
+ * The glGet queries of the framebuffer red/green/blue size, stencil size,
+ * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can
+ * change depending on the renderbuffer bindings. This function updates
+ * the given framebuffer's Visual from the current renderbuffer bindings.
+ *
+ * This may apply to user-created framebuffers or window system framebuffers.
+ *
+ * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
+ * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
+ * The former one is used to convert floating point depth values into
+ * integer Z values.
+ */
+void
+_mesa_update_framebuffer_visual(struct gl_framebuffer *fb)
+{
+ GLuint i;
+
+ _mesa_bzero(&fb->Visual, sizeof(fb->Visual));
+ fb->Visual.rgbMode = GL_TRUE; /* assume this */
+
+#if 0 /* this _might_ be needed */
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ /* leave visual fields zero'd */
+ return;
+ }
+#endif
+
+ /* find first RGB or CI renderbuffer */
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ if (fb->Attachment[i].Renderbuffer) {
+ const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
+ if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) {
+ fb->Visual.redBits = rb->RedBits;
+ fb->Visual.greenBits = rb->GreenBits;
+ fb->Visual.blueBits = rb->BlueBits;
+ fb->Visual.alphaBits = rb->AlphaBits;
+ fb->Visual.rgbBits = fb->Visual.redBits
+ + fb->Visual.greenBits + fb->Visual.blueBits;
+ fb->Visual.floatMode = GL_FALSE;
+ fb->Visual.samples = rb->NumSamples;
+ break;
+ }
+ else if (rb->_BaseFormat == GL_COLOR_INDEX) {
+ fb->Visual.indexBits = rb->IndexBits;
+ fb->Visual.rgbMode = GL_FALSE;
+ break;
+ }
+ }
+ }
+
+ if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
+ fb->Visual.haveDepthBuffer = GL_TRUE;
+ fb->Visual.depthBits
+ = fb->Attachment[BUFFER_DEPTH].Renderbuffer->DepthBits;
+ }
+
+ if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
+ fb->Visual.haveStencilBuffer = GL_TRUE;
+ fb->Visual.stencilBits
+ = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits;
+ }
+
+ if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
+ fb->Visual.haveAccumBuffer = GL_TRUE;
+ fb->Visual.accumRedBits
+ = fb->Attachment[BUFFER_ACCUM].Renderbuffer->RedBits;
+ fb->Visual.accumGreenBits
+ = fb->Attachment[BUFFER_ACCUM].Renderbuffer->GreenBits;
+ fb->Visual.accumBlueBits
+ = fb->Attachment[BUFFER_ACCUM].Renderbuffer->BlueBits;
+ fb->Visual.accumAlphaBits
+ = fb->Attachment[BUFFER_ACCUM].Renderbuffer->AlphaBits;
+ }
+
+ compute_depth_max(fb);
+}
+
+
+/**
+ * Update the framebuffer's _DepthBuffer field using the renderbuffer
+ * found at the given attachment index.
+ *
+ * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
+ * create and install a depth wrapper/adaptor.
+ *
+ * \param fb the framebuffer whose _DepthBuffer field to update
+ * \param attIndex indicates the renderbuffer to possibly wrap
+ */
+void
+_mesa_update_depth_buffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLuint attIndex)
+{
+ struct gl_renderbuffer *depthRb;
+
+ /* only one possiblity for now */
+ ASSERT(attIndex == BUFFER_DEPTH);
+
+ depthRb = fb->Attachment[attIndex].Renderbuffer;
+
+ if (depthRb && depthRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
+ /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
+ if (!fb->_DepthBuffer
+ || fb->_DepthBuffer->Wrapped != depthRb
+ || fb->_DepthBuffer->_BaseFormat != GL_DEPTH_COMPONENT) {
+ /* need to update wrapper */
+ struct gl_renderbuffer *wrapper
+ = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
+ ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
+ }
+ }
+ else {
+ /* depthRb may be null */
+ _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
+ }
+}
+
+
+/**
+ * Update the framebuffer's _StencilBuffer field using the renderbuffer
+ * found at the given attachment index.
+ *
+ * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
+ * create and install a stencil wrapper/adaptor.
+ *
+ * \param fb the framebuffer whose _StencilBuffer field to update
+ * \param attIndex indicates the renderbuffer to possibly wrap
+ */
+void
+_mesa_update_stencil_buffer(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ GLuint attIndex)
+{
+ struct gl_renderbuffer *stencilRb;
+
+ ASSERT(attIndex == BUFFER_DEPTH ||
+ attIndex == BUFFER_STENCIL);
+
+ stencilRb = fb->Attachment[attIndex].Renderbuffer;
+
+ if (stencilRb && stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
+ /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
+ if (!fb->_StencilBuffer
+ || fb->_StencilBuffer->Wrapped != stencilRb
+ || fb->_StencilBuffer->_BaseFormat != GL_STENCIL_INDEX) {
+ /* need to update wrapper */
+ struct gl_renderbuffer *wrapper
+ = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
+ ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
+ }
+ }
+ else {
+ /* stencilRb may be null */
+ _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
+ }
+}
+
+
+/*
+ * Example DrawBuffers scenarios:
+ *
+ * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to
+ * "gl_FragColor" or program writes to the "result.color" register:
+ *
+ * fragment color output renderbuffer
+ * --------------------- ---------------
+ * color[0] Front, Back
+ *
+ *
+ * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to
+ * gl_FragData[i] or program writes to result.color[i] registers:
+ *
+ * fragment color output renderbuffer
+ * --------------------- ---------------
+ * color[0] Front
+ * color[1] Aux0
+ * color[3] Aux1
+ *
+ *
+ * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to
+ * gl_FragColor, or fixed function:
+ *
+ * fragment color output renderbuffer
+ * --------------------- ---------------
+ * color[0] Front, Aux0, Aux1
+ *
+ *
+ * In either case, the list of renderbuffers is stored in the
+ * framebuffer->_ColorDrawBuffers[] array and
+ * framebuffer->_NumColorDrawBuffers indicates the number of buffers.
+ * The renderer (like swrast) has to look at the current fragment shader
+ * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine
+ * how to map color outputs to renderbuffers.
+ *
+ * Note that these two calls are equivalent (for fixed function fragment
+ * shading anyway):
+ * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer)
+ * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]);
+ */
+
+
+
+
+/**
+ * Update the (derived) list of color drawing renderbuffer pointers.
+ * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers
+ * writing colors.
+ */
+static void
+update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ GLuint output;
+
+ /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */
+ fb->_ColorDrawBuffers[0] = NULL;
+
+ for (output = 0; output < fb->_NumColorDrawBuffers; output++) {
+ GLint buf = fb->_ColorDrawBufferIndexes[output];
+ if (buf >= 0) {
+ fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer;
+ }
+ else {
+ fb->_ColorDrawBuffers[output] = NULL;
+ }
+ }
+}
+
+
+/**
+ * Update the (derived) color read renderbuffer pointer.
+ * Unlike the DrawBuffer, we can only read from one (or zero) color buffers.
+ */
+static void
+update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ (void) ctx;
+ if (fb->_ColorReadBufferIndex == -1 ||
+ fb->DeletePending ||
+ fb->Width == 0 ||
+ fb->Height == 0) {
+ fb->_ColorReadBuffer = NULL; /* legal! */
+ }
+ else {
+ ASSERT(fb->_ColorReadBufferIndex >= 0);
+ ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT);
+ fb->_ColorReadBuffer
+ = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
+ }
+}
+
+
+/**
+ * Update a gl_framebuffer's derived state.
+ *
+ * Specifically, update these framebuffer fields:
+ * _ColorDrawBuffers
+ * _NumColorDrawBuffers
+ * _ColorReadBuffer
+ * _DepthBuffer
+ * _StencilBuffer
+ *
+ * If the framebuffer is user-created, make sure it's complete.
+ *
+ * The following functions (at least) can effect framebuffer state:
+ * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
+ * glRenderbufferStorageEXT.
+ */
+static void
+update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ if (fb->Name == 0) {
+ /* This is a window-system framebuffer */
+ /* Need to update the FB's GL_DRAW_BUFFER state to match the
+ * context state (GL_READ_BUFFER too).
+ */
+ if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
+ _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers,
+ ctx->Color.DrawBuffer, NULL);
+ }
+ if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) {
+
+ }
+ }
+ else {
+ /* This is a user-created framebuffer.
+ * Completeness only matters for user-created framebuffers.
+ */
+ if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
+ _mesa_test_framebuffer_completeness(ctx, fb);
+ }
+ }
+
+ /* Strictly speaking, we don't need to update the draw-state
+ * if this FB is bound as ctx->ReadBuffer (and conversely, the
+ * read-state if this FB is bound as ctx->DrawBuffer), but no
+ * harm.
+ */
+ update_color_draw_buffers(ctx, fb);
+ update_color_read_buffer(ctx, fb);
+ _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
+ _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
+
+ compute_depth_max(fb);
+}
+
+
+/**
+ * Update state related to the current draw/read framebuffers.
+ */
+void
+_mesa_update_framebuffer(GLcontext *ctx)
+{
+ struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+ struct gl_framebuffer *readFb = ctx->ReadBuffer;
+
+ update_framebuffer(ctx, drawFb);
+ if (readFb != drawFb)
+ update_framebuffer(ctx, readFb);
+}
+
+
+/**
+ * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
+ * glCopyTex[Sub]Image, etc) exists.
+ * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
+ * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
+ * \return GL_TRUE if buffer exists, GL_FALSE otherwise
+ */
+GLboolean
+_mesa_source_buffer_exists(GLcontext *ctx, GLenum format)
+{
+ const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;
+
+ /* If we don't know the framebuffer status, update it now */
+ if (ctx->ReadBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ }
+
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ return GL_FALSE;
+ }
+
+ switch (format) {
+ case GL_COLOR:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ case GL_COLOR_INDEX:
+ if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
+ return GL_FALSE;
+ }
+ ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 ||
+ ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0);
+ break;
+ case GL_DEPTH:
+ case GL_DEPTH_COMPONENT:
+ if (!att[BUFFER_DEPTH].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
+ break;
+ case GL_STENCIL:
+ case GL_STENCIL_INDEX:
+ if (!att[BUFFER_STENCIL].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!att[BUFFER_DEPTH].Renderbuffer ||
+ !att[BUFFER_STENCIL].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
+ ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
+ break;
+ default:
+ _mesa_problem(ctx,
+ "Unexpected format 0x%x in _mesa_source_buffer_exists",
+ format);
+ return GL_FALSE;
+ }
+
+ /* OK */
+ return GL_TRUE;
+}
+
+
+/**
+ * As above, but for drawing operations.
+ * XXX could do some code merging w/ above function.
+ */
+GLboolean
+_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format)
+{
+ const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment;
+
+ /* If we don't know the framebuffer status, update it now */
+ if (ctx->DrawBuffer->_Status == 0) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
+ }
+
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ return GL_FALSE;
+ }
+
+ switch (format) {
+ case GL_COLOR:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ case GL_COLOR_INDEX:
+ /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */
+ /* Could assert that colorbuffer has RedBits > 0 */
+ break;
+ case GL_DEPTH:
+ case GL_DEPTH_COMPONENT:
+ if (!att[BUFFER_DEPTH].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
+ break;
+ case GL_STENCIL:
+ case GL_STENCIL_INDEX:
+ if (!att[BUFFER_STENCIL].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!att[BUFFER_DEPTH].Renderbuffer ||
+ !att[BUFFER_STENCIL].Renderbuffer) {
+ return GL_FALSE;
+ }
+ ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
+ ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
+ break;
+ default:
+ _mesa_problem(ctx,
+ "Unexpected format 0x%x in _mesa_dest_buffer_exists",
+ format);
+ return GL_FALSE;
+ }
+
+ /* OK */
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h
new file mode 100644
index 000000000..45a4703ba
--- /dev/null
+++ b/mesalib/src/mesa/main/framebuffer.h
@@ -0,0 +1,85 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 FRAMEBUFFER_H
+#define FRAMEBUFFER_H
+
+
+extern struct gl_framebuffer *
+_mesa_create_framebuffer(const GLvisual *visual);
+
+extern struct gl_framebuffer *
+_mesa_new_framebuffer(GLcontext *ctx, GLuint name);
+
+extern void
+_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual);
+
+extern void
+_mesa_destroy_framebuffer(struct gl_framebuffer *buffer);
+
+extern void
+_mesa_free_framebuffer_data(struct gl_framebuffer *buffer);
+
+extern void
+_mesa_reference_framebuffer(struct gl_framebuffer **ptr,
+ struct gl_framebuffer *fb);
+
+extern void
+_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint width, GLuint height);
+
+
+extern void
+_mesa_resizebuffers( GLcontext *ctx );
+
+extern void GLAPIENTRY
+_mesa_ResizeBuffersMESA( void );
+
+
+extern void
+_mesa_update_draw_buffer_bounds(GLcontext *ctx);
+
+extern void
+_mesa_update_framebuffer_visual(struct gl_framebuffer *fb);
+
+extern void
+_mesa_update_depth_buffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint attIndex);
+
+extern void
+_mesa_update_stencil_buffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint attIndex);
+
+extern void
+_mesa_update_framebuffer(GLcontext *ctx);
+
+extern GLboolean
+_mesa_source_buffer_exists(GLcontext *ctx, GLenum format);
+
+extern GLboolean
+_mesa_dest_buffer_exists(GLcontext *ctx, GLenum format);
+
+
+#endif /* FRAMEBUFFER_H */
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
new file mode 100644
index 000000000..477ed0103
--- /dev/null
+++ b/mesalib/src/mesa/main/get.c
@@ -0,0 +1,7419 @@
+
+/***
+ *** NOTE!!! DO NOT EDIT THIS FILE!!! IT IS GENERATED BY get_gen.py
+ ***/
+
+#include "glheader.h"
+#include "context.h"
+#include "enable.h"
+#include "extensions.h"
+#include "fbobject.h"
+#include "get.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "state.h"
+#include "texcompress.h"
+
+
+#define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE )
+
+#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+
+#define INT64_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE )
+#define INT64_TO_INT(I) ( (GLint)((I > INT_MAX) ? INT_MAX : ((I < INT_MIN) ? INT_MIN : (I))) )
+
+#define BOOLEAN_TO_INT(B) ( (GLint) (B) )
+#define BOOLEAN_TO_INT64(B) ( (GLint64) (B) )
+#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F )
+
+#define ENUM_TO_INT64(E) ( (GLint64) (E) )
+
+
+/*
+ * Check if named extension is enabled, if not generate error and return.
+ */
+#define CHECK_EXT1(EXT1, FUNC) \
+ if (!ctx->Extensions.EXT1) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \
+ return; \
+ }
+
+/*
+ * Check if either of two extensions is enabled.
+ */
+#define CHECK_EXT2(EXT1, EXT2, FUNC) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \
+ return; \
+ }
+
+/*
+ * Check if either of three extensions is enabled.
+ */
+#define CHECK_EXT3(EXT1, EXT2, EXT3, FUNC) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2 && \
+ !ctx->Extensions.EXT3) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \
+ return; \
+ }
+
+/*
+ * Check if either of four extensions is enabled.
+ */
+#define CHECK_EXT4(EXT1, EXT2, EXT3, EXT4, FUNC) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2 && \
+ !ctx->Extensions.EXT3 && !ctx->Extensions.EXT4) { \
+ _mesa_error(ctx, GL_INVALID_ENUM, FUNC "(0x%x)", (int) pname); \
+ return; \
+ }
+
+
+void GLAPIENTRY
+_mesa_GetBooleanv( GLenum pname, GLboolean *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->Driver.GetBooleanv &&
+ ctx->Driver.GetBooleanv(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumRedBits);
+ break;
+ case GL_ACCUM_GREEN_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumGreenBits);
+ break;
+ case GL_ACCUM_BLUE_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumBlueBits);
+ break;
+ case GL_ACCUM_ALPHA_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumAlphaBits);
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[3]);
+ break;
+ case GL_ALPHA_BIAS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.AlphaBias);
+ break;
+ case GL_ALPHA_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.alphaBits);
+ break;
+ case GL_ALPHA_SCALE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.AlphaScale);
+ break;
+ case GL_ALPHA_TEST:
+ params[0] = ctx->Color.AlphaEnabled;
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Color.AlphaRef);
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ params[0] = ctx->Eval.AutoNormal;
+ break;
+ case GL_AUX_BUFFERS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.numAuxBuffers);
+ break;
+ case GL_BLEND:
+ params[0] = ctx->Color.BlendEnabled;
+ break;
+ case GL_BLEND_DST:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_EXT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_EXT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_EXT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_EXT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendEquationRGB );
+ break;
+ case GL_BLEND_EQUATION_ALPHA_EXT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendEquationA );
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[3]);
+ break;
+ case GL_BLUE_BIAS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.BlueBias);
+ break;
+ case GL_BLUE_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.blueBits);
+ break;
+ case GL_BLUE_SCALE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.BlueScale);
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->ClientAttribStackDepth);
+ break;
+ case GL_CLIP_PLANE0:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 0) & 1;
+ break;
+ case GL_CLIP_PLANE1:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 1) & 1;
+ break;
+ case GL_CLIP_PLANE2:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 2) & 1;
+ break;
+ case GL_CLIP_PLANE3:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 3) & 1;
+ break;
+ case GL_CLIP_PLANE4:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 4) & 1;
+ break;
+ case GL_CLIP_PLANE5:
+ params[0] = (ctx->Transform.ClipPlanesEnabled >> 5) & 1;
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[3]);
+ break;
+ case GL_COLOR_MATERIAL:
+ params[0] = ctx->Light.ColorMaterialEnabled;
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Color.ColorMask[RCOMP] ? 1 : 0);
+ params[1] = INT_TO_BOOLEAN(ctx->Color.ColorMask[GCOMP] ? 1 : 0);
+ params[2] = INT_TO_BOOLEAN(ctx->Color.ColorMask[BCOMP] ? 1 : 0);
+ params[3] = INT_TO_BOOLEAN(ctx->Color.ColorMask[ACOMP] ? 1 : 0);
+ break;
+ case GL_CULL_FACE:
+ params[0] = ctx->Polygon.CullFlag;
+ break;
+ case GL_CULL_FACE_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]);
+ }
+ break;
+ case GL_CURRENT_INDEX:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]);
+ }
+ break;
+ case GL_CURRENT_NORMAL:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]);
+ }
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[3]);
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterDistance);
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterIndex);
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[3]);
+ break;
+ case GL_CURRENT_RASTER_SECONDARY_COLOR:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterSecondaryColor[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterSecondaryColor[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterSecondaryColor[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterSecondaryColor[3]);
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][3]);
+ }
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ params[0] = ctx->Current.RasterPosValid;
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]);
+ }
+ break;
+ case GL_DEPTH_BIAS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.DepthBias);
+ break;
+ case GL_DEPTH_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.depthBits);
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ params[0] = FLOAT_TO_BOOLEAN(((GLfloat) ctx->Depth.Clear));
+ break;
+ case GL_DEPTH_FUNC:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Viewport.Near);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Viewport.Far);
+ break;
+ case GL_DEPTH_SCALE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.DepthScale);
+ break;
+ case GL_DEPTH_TEST:
+ params[0] = ctx->Depth.Test;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ params[0] = ctx->Depth.Mask;
+ break;
+ case GL_DITHER:
+ params[0] = ctx->Color.DitherFlag;
+ break;
+ case GL_DOUBLEBUFFER:
+ params[0] = ctx->DrawBuffer->Visual.doubleBufferMode;
+ break;
+ case GL_DRAW_BUFFER:
+ params[0] = ENUM_TO_BOOLEAN(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_EDGE_FLAG:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = (ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0);
+ }
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->Feedback.BufferSize);
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ params[0] = ctx->Fog.Enabled;
+ break;
+ case GL_FOG_COLOR:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[3]);
+ break;
+ case GL_FOG_DENSITY:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Density);
+ break;
+ case GL_FOG_END:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.End);
+ break;
+ case GL_FOG_HINT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Index);
+ break;
+ case GL_FOG_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Start);
+ break;
+ case GL_FRONT_FACE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.GreenBias);
+ break;
+ case GL_GREEN_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.greenBits);
+ break;
+ case GL_GREEN_SCALE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.GreenScale);
+ break;
+ case GL_INDEX_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.indexBits);
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ params[0] = INT_TO_BOOLEAN(ctx->Color.ClearIndex);
+ break;
+ case GL_INDEX_MODE:
+ params[0] = !ctx->DrawBuffer->Visual.rgbMode;
+ break;
+ case GL_INDEX_OFFSET:
+ params[0] = INT_TO_BOOLEAN(ctx->Pixel.IndexOffset);
+ break;
+ case GL_INDEX_SHIFT:
+ params[0] = INT_TO_BOOLEAN(ctx->Pixel.IndexShift);
+ break;
+ case GL_INDEX_WRITEMASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Color.IndexMask);
+ break;
+ case GL_LIGHT0:
+ params[0] = ctx->Light.Light[0].Enabled;
+ break;
+ case GL_LIGHT1:
+ params[0] = ctx->Light.Light[1].Enabled;
+ break;
+ case GL_LIGHT2:
+ params[0] = ctx->Light.Light[2].Enabled;
+ break;
+ case GL_LIGHT3:
+ params[0] = ctx->Light.Light[3].Enabled;
+ break;
+ case GL_LIGHT4:
+ params[0] = ctx->Light.Light[4].Enabled;
+ break;
+ case GL_LIGHT5:
+ params[0] = ctx->Light.Light[5].Enabled;
+ break;
+ case GL_LIGHT6:
+ params[0] = ctx->Light.Light[6].Enabled;
+ break;
+ case GL_LIGHT7:
+ params[0] = ctx->Light.Light[7].Enabled;
+ break;
+ case GL_LIGHTING:
+ params[0] = ctx->Light.Enabled;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[3]);
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ params[0] = ctx->Light.Model.LocalViewer;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ params[0] = ctx->Light.Model.TwoSide;
+ break;
+ case GL_LINE_SMOOTH:
+ params[0] = ctx->Line.SmoothFlag;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ params[0] = ctx->Line.StippleFlag;
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ params[0] = INT_TO_BOOLEAN(ctx->Line.StipplePattern);
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ params[0] = INT_TO_BOOLEAN(ctx->Line.StippleFactor);
+ break;
+ case GL_LINE_WIDTH:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Line.Width);
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.LineWidthGranularity);
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinLineWidthAA);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxLineWidthAA);
+ break;
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinLineWidth);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxLineWidth);
+ break;
+ case GL_LIST_BASE:
+ params[0] = INT_TO_BOOLEAN(ctx->List.ListBase);
+ break;
+ case GL_LIST_INDEX:
+ params[0] = INT_TO_BOOLEAN((ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0));
+ break;
+ case GL_LIST_MODE:
+ {
+ GLenum mode;
+ if (!ctx->CompileFlag)
+ mode = 0;
+ else if (ctx->ExecuteFlag)
+ mode = GL_COMPILE_AND_EXECUTE;
+ else
+ mode = GL_COMPILE;
+ params[0] = ENUM_TO_BOOLEAN(mode);
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ params[0] = ctx->Color.IndexLogicOpEnabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ params[0] = ctx->Color.ColorLogicOpEnabled;
+ break;
+ case GL_LOGIC_OP_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ params[0] = ctx->Eval.Map1Color4;
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid1u1);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid1u2);
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ params[0] = INT_TO_BOOLEAN(ctx->Eval.MapGrid1un);
+ break;
+ case GL_MAP1_INDEX:
+ params[0] = ctx->Eval.Map1Index;
+ break;
+ case GL_MAP1_NORMAL:
+ params[0] = ctx->Eval.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ params[0] = ctx->Eval.Map1TextureCoord1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ params[0] = ctx->Eval.Map1TextureCoord2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ params[0] = ctx->Eval.Map1TextureCoord3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ params[0] = ctx->Eval.Map1TextureCoord4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ params[0] = ctx->Eval.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ params[0] = ctx->Eval.Map1Vertex4;
+ break;
+ case GL_MAP2_COLOR_4:
+ params[0] = ctx->Eval.Map2Color4;
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2u1);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2u2);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2v1);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2v2);
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = INT_TO_BOOLEAN(ctx->Eval.MapGrid2un);
+ params[1] = INT_TO_BOOLEAN(ctx->Eval.MapGrid2vn);
+ break;
+ case GL_MAP2_INDEX:
+ params[0] = ctx->Eval.Map2Index;
+ break;
+ case GL_MAP2_NORMAL:
+ params[0] = ctx->Eval.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ params[0] = ctx->Eval.Map2TextureCoord1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ params[0] = ctx->Eval.Map2TextureCoord2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ params[0] = ctx->Eval.Map2TextureCoord3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ params[0] = ctx->Eval.Map2TextureCoord4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ params[0] = ctx->Eval.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ params[0] = ctx->Eval.Map2Vertex4;
+ break;
+ case GL_MAP_COLOR:
+ params[0] = ctx->Pixel.MapColorFlag;
+ break;
+ case GL_MAP_STENCIL:
+ params[0] = ctx->Pixel.MapStencilFlag;
+ break;
+ case GL_MATRIX_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_CLIENT_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIP_PLANES:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxClipPlanes);
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayLockSize);
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayLockSize);
+ break;
+ case GL_MAX_EVAL_ORDER:
+ params[0] = INT_TO_BOOLEAN(MAX_EVAL_ORDER);
+ break;
+ case GL_MAX_LIGHTS:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxLights);
+ break;
+ case GL_MAX_LIST_NESTING:
+ params[0] = INT_TO_BOOLEAN(MAX_LIST_NESTING);
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_MODELVIEW_STACK_DEPTH);
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_NAME_STACK_DEPTH);
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ params[0] = INT_TO_BOOLEAN(MAX_PIXEL_MAP_TABLE);
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_PROJECTION_STACK_DEPTH);
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ params[0] = INT_TO_BOOLEAN(1 << (ctx->Const.MaxTextureLevels - 1));
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ params[0] = INT_TO_BOOLEAN(1 << (ctx->Const.Max3DTextureLevels - 1));
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(MAX_TEXTURE_STACK_DEPTH);
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxViewportWidth);
+ params[1] = INT_TO_BOOLEAN(ctx->Const.MaxViewportHeight);
+ break;
+ case GL_MODELVIEW_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->ModelviewMatrixStack.Depth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->Select.NameStackDepth);
+ break;
+ case GL_NORMALIZE:
+ params[0] = ctx->Transform.Normalize;
+ break;
+ case GL_PACK_ALIGNMENT:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.Alignment);
+ break;
+ case GL_PACK_LSB_FIRST:
+ params[0] = ctx->Pack.LsbFirst;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.RowLength);
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipPixels);
+ break;
+ case GL_PACK_SKIP_ROWS:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipRows);
+ break;
+ case GL_PACK_SWAP_BYTES:
+ params[0] = ctx->Pack.SwapBytes;
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipImages);
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.ImageHeight);
+ break;
+ case GL_PACK_INVERT_MESA:
+ params[0] = ctx->Pack.Invert;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.AtoA.Size);
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.BtoB.Size);
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.GtoG.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoA.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoB.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoG.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoI.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.ItoR.Size);
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.RtoR.Size);
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->PixelMaps.StoS.Size);
+ break;
+ case GL_POINT_SIZE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Size);
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.PointSizeGranularity);
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinPointSizeAA);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxPointSizeAA);
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinPointSize);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxPointSize);
+ break;
+ case GL_POINT_SMOOTH:
+ params[0] = ctx->Point.SmoothFlag;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Params[0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Point.Params[1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_BOOLEAN(ctx->Polygon.BackMode);
+ break;
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetUnits);
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetFactor );
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetUnits );
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ params[0] = ctx->Polygon.OffsetPoint;
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ params[0] = ctx->Polygon.OffsetLine;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ params[0] = ctx->Polygon.OffsetFill;
+ break;
+ case GL_POLYGON_SMOOTH:
+ params[0] = ctx->Polygon.SmoothFlag;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ params[0] = ctx->Polygon.StippleFlag;
+ break;
+ case GL_PROJECTION_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->ProjectionMatrixStack.Depth + 1);
+ break;
+ case GL_READ_BUFFER:
+ params[0] = ENUM_TO_BOOLEAN(ctx->ReadBuffer->ColorReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.RedBias);
+ break;
+ case GL_RED_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.redBits);
+ break;
+ case GL_RED_SCALE:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.RedScale);
+ break;
+ case GL_RENDER_MODE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->RenderMode);
+ break;
+ case GL_RESCALE_NORMAL:
+ params[0] = ctx->Transform.RescaleNormals;
+ break;
+ case GL_RGBA_MODE:
+ params[0] = ctx->DrawBuffer->Visual.rgbMode;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = INT_TO_BOOLEAN(ctx->Scissor.X);
+ params[1] = INT_TO_BOOLEAN(ctx->Scissor.Y);
+ params[2] = INT_TO_BOOLEAN(ctx->Scissor.Width);
+ params[3] = INT_TO_BOOLEAN(ctx->Scissor.Height);
+ break;
+ case GL_SCISSOR_TEST:
+ params[0] = ctx->Scissor.Enabled;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->Select.BufferSize);
+ break;
+ case GL_SHADE_MODEL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ params[0] = ctx->Texture.SharedPalette;
+ break;
+ case GL_STENCIL_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.stencilBits);
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.Clear);
+ break;
+ case GL_STENCIL_FAIL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_FUNC:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.Function[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_REF:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.Ref[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_TEST:
+ params[0] = ctx->Stencil.Enabled;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_WRITEMASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STEREO:
+ params[0] = ctx->DrawBuffer->Visual.stereoMode;
+ break;
+ case GL_SUBPIXEL_BITS:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.SubPixelBits);
+ break;
+ case GL_TEXTURE_1D:
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_1D);
+ break;
+ case GL_TEXTURE_2D:
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_2D);
+ break;
+ case GL_TEXTURE_3D:
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_3D);
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetBooleanv");
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT);
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetBooleanv");
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT);
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
+ break;
+ case GL_TEXTURE_GEN_S:
+ params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0);
+ break;
+ case GL_TEXTURE_GEN_T:
+ params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0);
+ break;
+ case GL_TEXTURE_GEN_R:
+ params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0);
+ break;
+ case GL_TEXTURE_GEN_Q:
+ params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0);
+ break;
+ case GL_TEXTURE_MATRIX:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ params[0] = INT_TO_BOOLEAN(ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.Alignment);
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ params[0] = ctx->Unpack.LsbFirst;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.RowLength);
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipPixels);
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipRows);
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ params[0] = ctx->Unpack.SwapBytes;
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipImages);
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.ImageHeight);
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ params[0] = ctx->Unpack.ClientStorage;
+ break;
+ case GL_VIEWPORT:
+ params[0] = INT_TO_BOOLEAN(ctx->Viewport.X);
+ params[1] = INT_TO_BOOLEAN(ctx->Viewport.Y);
+ params[2] = INT_TO_BOOLEAN(ctx->Viewport.Width);
+ params[3] = INT_TO_BOOLEAN(ctx->Viewport.Height);
+ break;
+ case GL_ZOOM_X:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.ZoomX);
+ break;
+ case GL_ZOOM_Y:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.ZoomY);
+ break;
+ case GL_VERTEX_ARRAY:
+ params[0] = ctx->Array.ArrayObj->Vertex.Enabled;
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Vertex.Size);
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Vertex.Stride);
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_NORMAL_ARRAY:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->Normal.Enabled);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Normal.Stride);
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_COLOR_ARRAY:
+ params[0] = ctx->Array.ArrayObj->Color.Enabled;
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Color.Size);
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Color.Stride);
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_INDEX_ARRAY:
+ params[0] = ctx->Array.ArrayObj->Index.Enabled;
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Index.Stride);
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.Enabled;
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->EdgeFlag.Stride);
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ params[0] = INT_TO_BOOLEAN(0);
+ break;
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureUnits);
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture);
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetBooleanv");
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB);
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name);
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN((1 << (ctx->Const.MaxCubeTextureLevels - 1)));
+ break;
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Hint.TextureCompression);
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ params[0] = INT_TO_BOOLEAN(_mesa_get_compressed_formats(ctx, NULL, GL_FALSE));
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ {
+ GLint formats[100];
+ GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+ ASSERT(n <= 100);
+ for (i = 0; i < n; i++)
+ params[i] = ENUM_TO_BOOLEAN(formats[i]);
+ }
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.LockFirst);
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.LockCount);
+ break;
+ case GL_TRANSPOSE_COLOR_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_PROJECTION_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_TEXTURE_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_SGI:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = INT_TO_BOOLEAN(ctx->ColorMatrixStack.Depth + 1);
+ break;
+ case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = INT_TO_BOOLEAN(MAX_COLOR_STACK_DEPTH);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[3]);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[3]);
+ break;
+ case GL_CONVOLUTION_1D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = ctx->Pixel.Convolution1DEnabled;
+ break;
+ case GL_CONVOLUTION_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = ctx->Pixel.Convolution2DEnabled;
+ break;
+ case GL_SEPARABLE_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = ctx->Pixel.Separable2DEnabled;
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[3]);
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[3]);
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXT1(EXT_histogram, "GetBooleanv");
+ params[0] = ctx->Pixel.HistogramEnabled;
+ break;
+ case GL_MINMAX:
+ CHECK_EXT1(EXT_histogram, "GetBooleanv");
+ params[0] = ctx->Pixel.MinMaxEnabled;
+ break;
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetBooleanv");
+ params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION];
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetBooleanv");
+ params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION];
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetBooleanv");
+ params[0] = ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX];
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_texture_color_table, "GetBooleanv");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled;
+ break;
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXT2(EXT_secondary_color, ARB_vertex_program, "GetBooleanv");
+ params[0] = ctx->Fog.ColorSumEnabled;
+ break;
+ case GL_CURRENT_SECONDARY_COLOR_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetBooleanv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]);
+ params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]);
+ params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]);
+ }
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Enabled;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->SecondaryColor.Type);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->SecondaryColor.Stride);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->SecondaryColor.Size);
+ break;
+ case GL_CURRENT_FOG_COORDINATE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetBooleanv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
+ }
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->FogCoord.Enabled;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Array.ArrayObj->FogCoord.Type);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->FogCoord.Stride);
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Fog.FogCoordinateSource);
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS_EXT:
+ CHECK_EXT1(EXT_texture_lod_bias, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxTextureLodBias);
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ CHECK_EXT1(EXT_texture_filter_anisotropic, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxTextureMaxAnisotropy);
+ break;
+ case GL_MULTISAMPLE_ARB:
+ params[0] = ctx->Multisample.Enabled;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ params[0] = ctx->Multisample.SampleAlphaToCoverage;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ params[0] = ctx->Multisample.SampleAlphaToOne;
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ params[0] = ctx->Multisample.SampleCoverage;
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE_ARB:
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Multisample.SampleCoverageValue);
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ params[0] = ctx->Multisample.SampleCoverageInvert;
+ break;
+ case GL_SAMPLE_BUFFERS_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.sampleBuffers);
+ break;
+ case GL_SAMPLES_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.samples);
+ break;
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXT1(IBM_rasterpos_clip, "GetBooleanv");
+ params[0] = ctx->Transform.RasterPositionUnclipped;
+ break;
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetBooleanv");
+ params[0] = ctx->Point.PointSprite;
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ CHECK_EXT1(NV_point_sprite, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Point.SpriteRMode);
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Point.SpriteOrigin);
+ break;
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ CHECK_EXT1(SGIS_generate_mipmap, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.GenerateMipmap);
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN((ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[0].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[1].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[2].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[3].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[4].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[5].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[6].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[7].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[8].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[9].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[10].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[11].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[12].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[13].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[14].Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Array.ArrayObj->VertexAttrib[15].Enabled;
+ break;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[0];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[1];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[2];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[3];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[4];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[5];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[6];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[7];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[8];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[9];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[10];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[11];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[12];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[13];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[14];
+ break;
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->Eval.Map1Attrib[15];
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXT1(NV_fragment_program, "GetBooleanv");
+ params[0] = ctx->FragmentProgram.Enabled;
+ break;
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_fragment_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0);
+ break;
+ case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV:
+ CHECK_EXT1(NV_fragment_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(MAX_NV_FRAGMENT_PROGRAM_PARAMS);
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetBooleanv");
+ params[0] = _mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV);
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name);
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureRectSize);
+ break;
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetBooleanv");
+ params[0] = ctx->Stencil.TestTwoSide;
+ break;
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT);
+ break;
+ case GL_MAX_SHININESS_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxShininess);
+ break;
+ case GL_MAX_SPOT_EXPONENT_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxSpotExponent);
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayBufferObj->Name);
+ break;
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Vertex.BufferObj->Name);
+ break;
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Normal.BufferObj->Name);
+ break;
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Color.BufferObj->Name);
+ break;
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Index.BufferObj->Name);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name);
+ break;
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->FogCoord.BufferObj->Name);
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ElementArrayBufferObj->Name);
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Pack.BufferObj->Name);
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Unpack.BufferObj->Name);
+ break;
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->VertexProgram.Enabled;
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->VertexProgram.PointSizeEnabled;
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->VertexProgram.TwoSideEnabled;
+ break;
+ case GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxProgramMatrixStackDepth);
+ break;
+ case GL_MAX_PROGRAM_MATRICES_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxProgramMatrices);
+ break;
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetBooleanv");
+ params[0] = ctx->CurrentStack->Depth + 1;
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_fragment_program, "GetBooleanv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ CHECK_EXT2(ARB_vertex_program, ARB_fragment_program, "GetBooleanv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = FLOAT_TO_BOOLEAN(matrix[0]);
+ params[1] = FLOAT_TO_BOOLEAN(matrix[4]);
+ params[2] = FLOAT_TO_BOOLEAN(matrix[8]);
+ params[3] = FLOAT_TO_BOOLEAN(matrix[12]);
+ params[4] = FLOAT_TO_BOOLEAN(matrix[1]);
+ params[5] = FLOAT_TO_BOOLEAN(matrix[5]);
+ params[6] = FLOAT_TO_BOOLEAN(matrix[9]);
+ params[7] = FLOAT_TO_BOOLEAN(matrix[13]);
+ params[8] = FLOAT_TO_BOOLEAN(matrix[2]);
+ params[9] = FLOAT_TO_BOOLEAN(matrix[6]);
+ params[10] = FLOAT_TO_BOOLEAN(matrix[10]);
+ params[11] = FLOAT_TO_BOOLEAN(matrix[14]);
+ params[12] = FLOAT_TO_BOOLEAN(matrix[3]);
+ params[13] = FLOAT_TO_BOOLEAN(matrix[7]);
+ params[14] = FLOAT_TO_BOOLEAN(matrix[11]);
+ params[15] = FLOAT_TO_BOOLEAN(matrix[15]);
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS_ARB:
+ CHECK_EXT1(ARB_vertex_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.VertexProgram.MaxAttribs);
+ break;
+ case GL_PROGRAM_ERROR_POSITION_ARB:
+ CHECK_EXT4(NV_vertex_program, ARB_vertex_program, NV_fragment_program, ARB_fragment_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Program.ErrorPos);
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXT1(ARB_fragment_program, "GetBooleanv");
+ params[0] = ctx->FragmentProgram.Enabled;
+ break;
+ case GL_MAX_TEXTURE_COORDS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureCoordUnits);
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureImageUnits);
+ break;
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetBooleanv");
+ params[0] = ctx->Depth.BoundsTest;
+ break;
+ case GL_DEPTH_BOUNDS_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetBooleanv");
+ params[0] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMin);
+ params[1] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMax);
+ break;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxDrawBuffers);
+ break;
+ case GL_DRAW_BUFFER0_ARB:
+ params[0] = ENUM_TO_BOOLEAN(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_DRAW_BUFFER1_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];
+ params[0] = ENUM_TO_BOOLEAN(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER2_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];
+ params[0] = ENUM_TO_BOOLEAN(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER3_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];
+ params[0] = ENUM_TO_BOOLEAN(buffer);
+ }
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ CHECK_EXT1(OES_read_format, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.ColorReadType);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ CHECK_EXT1(OES_read_format, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.ColorReadFormat);
+ break;
+ case GL_NUM_FRAGMENT_REGISTERS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(6);
+ break;
+ case GL_NUM_FRAGMENT_CONSTANTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(8);
+ break;
+ case GL_NUM_PASSES_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(2);
+ break;
+ case GL_NUM_INSTRUCTIONS_PER_PASS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(8);
+ break;
+ case GL_NUM_INSTRUCTIONS_TOTAL_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(16);
+ break;
+ case GL_COLOR_ALPHA_PAIRING_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = GL_TRUE;
+ break;
+ case GL_NUM_LOOPBACK_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(3);
+ break;
+ case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(3);
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.Function[1]);
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.ValueMask[1]);
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.WriteMask[1]);
+ break;
+ case GL_STENCIL_BACK_REF:
+ params[0] = INT_TO_BOOLEAN(ctx->Stencil.Ref[1]);
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.FailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZFailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZPassFunc[1]);
+ break;
+ case GL_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Name);
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0);
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxColorAttachments);
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxRenderbufferSize);
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_blit, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->ReadBuffer->Name);
+ break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetBooleanv");
+ params[0] = ctx->Light.ProvokingVertex;
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetBooleanv");
+ params[0] = ctx->Const.QuadsFollowProvokingVertexConvention;
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.FragmentProgram.MaxUniformComponents);
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetBooleanv");
+ params[0] = ENUM_TO_BOOLEAN(ctx->Hint.FragmentShaderDerivative);
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.VertexProgram.MaxUniformComponents);
+ break;
+ case GL_MAX_VARYING_FLOATS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVarying * 4);
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVertexTextureImageUnits);
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ break;
+ case GL_CURRENT_PROGRAM:
+ CHECK_EXT1(ARB_shader_objects, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
+ break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Const.MaxSamples);
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetBooleanv");
+ params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayObj->Name);
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetBooleanv");
+ params[0] = ctx->Texture.CubeMapSeamless;
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetBooleanv");
+ params[0] = INT64_TO_BOOLEAN(ctx->Const.MaxServerWaitTimeout);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetFloatv( GLenum pname, GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->Driver.GetFloatv &&
+ ctx->Driver.GetFloatv(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumRedBits);
+ break;
+ case GL_ACCUM_GREEN_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumGreenBits);
+ break;
+ case GL_ACCUM_BLUE_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumBlueBits);
+ break;
+ case GL_ACCUM_ALPHA_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumAlphaBits);
+ 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[0] = ctx->Pixel.AlphaBias;
+ break;
+ case GL_ALPHA_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.alphaBits);
+ break;
+ case GL_ALPHA_SCALE:
+ params[0] = ctx->Pixel.AlphaScale;
+ break;
+ case GL_ALPHA_TEST:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Color.AlphaEnabled);
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ params[0] = ctx->Color.AlphaRef;
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.AutoNormal);
+ break;
+ case GL_AUX_BUFFERS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.numAuxBuffers);
+ break;
+ case GL_BLEND:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Color.BlendEnabled);
+ break;
+ case GL_BLEND_DST:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_EXT:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_EXT:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_EXT:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_EXT:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendEquationRGB );
+ break;
+ case GL_BLEND_EQUATION_ALPHA_EXT:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.BlendEquationA );
+ 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[0] = ctx->Pixel.BlueBias;
+ break;
+ case GL_BLUE_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.blueBits);
+ break;
+ case GL_BLUE_SCALE:
+ params[0] = ctx->Pixel.BlueScale;
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->ClientAttribStackDepth);
+ break;
+ case GL_CLIP_PLANE0:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 0) & 1);
+ break;
+ case GL_CLIP_PLANE1:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 1) & 1);
+ break;
+ case GL_CLIP_PLANE2:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 2) & 1);
+ break;
+ case GL_CLIP_PLANE3:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 3) & 1);
+ break;
+ case GL_CLIP_PLANE4:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 4) & 1);
+ break;
+ case GL_CLIP_PLANE5:
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 5) & 1);
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = ctx->Color.ClearColor[0];
+ params[1] = ctx->Color.ClearColor[1];
+ params[2] = ctx->Color.ClearColor[2];
+ params[3] = ctx->Color.ClearColor[3];
+ break;
+ case GL_COLOR_MATERIAL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.ColorMaterialEnabled);
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ params[0] = ENUM_TO_FLOAT(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ params[0] = ENUM_TO_FLOAT(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = (GLfloat)(ctx->Color.ColorMask[RCOMP] ? 1 : 0);
+ params[1] = (GLfloat)(ctx->Color.ColorMask[GCOMP] ? 1 : 0);
+ params[2] = (GLfloat)(ctx->Color.ColorMask[BCOMP] ? 1 : 0);
+ params[3] = (GLfloat)(ctx->Color.ColorMask[ACOMP] ? 1 : 0);
+ break;
+ case GL_CULL_FACE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.CullFlag);
+ break;
+ case GL_CULL_FACE_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+ params[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+ params[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+ params[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+ }
+ break;
+ case GL_CURRENT_INDEX:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0];
+ }
+ break;
+ case GL_CURRENT_NORMAL:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
+ params[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
+ params[2] = ctx->Current.Attrib[VERT_ATTRIB_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[0] = 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_SECONDARY_COLOR:
+ params[0] = ctx->Current.RasterSecondaryColor[0];
+ params[1] = ctx->Current.RasterSecondaryColor[1];
+ params[2] = ctx->Current.RasterSecondaryColor[2];
+ params[3] = ctx->Current.RasterSecondaryColor[3];
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ params[0] = ctx->Current.RasterTexCoords[texUnit][0];
+ params[1] = ctx->Current.RasterTexCoords[texUnit][1];
+ params[2] = ctx->Current.RasterTexCoords[texUnit][2];
+ params[3] = ctx->Current.RasterTexCoords[texUnit][3];
+ }
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Current.RasterPosValid);
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0];
+ params[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1];
+ params[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2];
+ params[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3];
+ }
+ break;
+ case GL_DEPTH_BIAS:
+ params[0] = ctx->Pixel.DepthBias;
+ break;
+ case GL_DEPTH_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.depthBits);
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ params[0] = ((GLfloat) ctx->Depth.Clear);
+ break;
+ case GL_DEPTH_FUNC:
+ params[0] = ENUM_TO_FLOAT(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = ctx->Viewport.Near;
+ params[1] = ctx->Viewport.Far;
+ break;
+ case GL_DEPTH_SCALE:
+ params[0] = ctx->Pixel.DepthScale;
+ break;
+ case GL_DEPTH_TEST:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.Test);
+ break;
+ case GL_DEPTH_WRITEMASK:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.Mask);
+ break;
+ case GL_DITHER:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Color.DitherFlag);
+ break;
+ case GL_DOUBLEBUFFER:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.doubleBufferMode);
+ break;
+ case GL_DRAW_BUFFER:
+ params[0] = ENUM_TO_FLOAT(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_EDGE_FLAG:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = BOOLEAN_TO_FLOAT((ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0));
+ }
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = (GLfloat)(ctx->Feedback.BufferSize);
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ params[0] = BOOLEAN_TO_FLOAT(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[0] = ctx->Fog.Density;
+ break;
+ case GL_FOG_END:
+ params[0] = ctx->Fog.End;
+ break;
+ case GL_FOG_HINT:
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ params[0] = ctx->Fog.Index;
+ break;
+ case GL_FOG_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ params[0] = ctx->Fog.Start;
+ break;
+ case GL_FRONT_FACE:
+ params[0] = ENUM_TO_FLOAT(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ params[0] = ctx->Pixel.GreenBias;
+ break;
+ case GL_GREEN_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.greenBits);
+ break;
+ case GL_GREEN_SCALE:
+ params[0] = ctx->Pixel.GreenScale;
+ break;
+ case GL_INDEX_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.indexBits);
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ params[0] = (GLfloat)(ctx->Color.ClearIndex);
+ break;
+ case GL_INDEX_MODE:
+ params[0] = BOOLEAN_TO_FLOAT(!ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_INDEX_OFFSET:
+ params[0] = (GLfloat)(ctx->Pixel.IndexOffset);
+ break;
+ case GL_INDEX_SHIFT:
+ params[0] = (GLfloat)(ctx->Pixel.IndexShift);
+ break;
+ case GL_INDEX_WRITEMASK:
+ params[0] = (GLfloat)(ctx->Color.IndexMask);
+ break;
+ case GL_LIGHT0:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[0].Enabled);
+ break;
+ case GL_LIGHT1:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[1].Enabled);
+ break;
+ case GL_LIGHT2:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[2].Enabled);
+ break;
+ case GL_LIGHT3:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[3].Enabled);
+ break;
+ case GL_LIGHT4:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[4].Enabled);
+ break;
+ case GL_LIGHT5:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[5].Enabled);
+ break;
+ case GL_LIGHT6:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[6].Enabled);
+ break;
+ case GL_LIGHT7:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[7].Enabled);
+ break;
+ case GL_LIGHTING:
+ params[0] = BOOLEAN_TO_FLOAT(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[0] = BOOLEAN_TO_FLOAT(ctx->Light.Model.LocalViewer);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Model.TwoSide);
+ break;
+ case GL_LINE_SMOOTH:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Line.SmoothFlag);
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Line.StippleFlag);
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ params[0] = (GLfloat)(ctx->Line.StipplePattern);
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ params[0] = (GLfloat)(ctx->Line.StippleFactor);
+ break;
+ case GL_LINE_WIDTH:
+ params[0] = ctx->Line.Width;
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ params[0] = ctx->Const.LineWidthGranularity;
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = ctx->Const.MinLineWidthAA;
+ params[1] = ctx->Const.MaxLineWidthAA;
+ break;
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = ctx->Const.MinLineWidth;
+ params[1] = ctx->Const.MaxLineWidth;
+ break;
+ case GL_LIST_BASE:
+ params[0] = (GLfloat)(ctx->List.ListBase);
+ break;
+ case GL_LIST_INDEX:
+ params[0] = (GLfloat)((ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0));
+ break;
+ case GL_LIST_MODE:
+ {
+ GLenum mode;
+ if (!ctx->CompileFlag)
+ mode = 0;
+ else if (ctx->ExecuteFlag)
+ mode = GL_COMPILE_AND_EXECUTE;
+ else
+ mode = GL_COMPILE;
+ params[0] = ENUM_TO_FLOAT(mode);
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Color.IndexLogicOpEnabled);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Color.ColorLogicOpEnabled);
+ break;
+ case GL_LOGIC_OP_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ params[0] = BOOLEAN_TO_FLOAT(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[0] = (GLfloat)(ctx->Eval.MapGrid1un);
+ break;
+ case GL_MAP1_INDEX:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Index);
+ break;
+ case GL_MAP1_NORMAL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Normal);
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord1);
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord3);
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord4);
+ break;
+ case GL_MAP1_VERTEX_3:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Vertex3);
+ break;
+ case GL_MAP1_VERTEX_4:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Vertex4);
+ break;
+ case GL_MAP2_COLOR_4:
+ params[0] = BOOLEAN_TO_FLOAT(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[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Index);
+ break;
+ case GL_MAP2_NORMAL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Normal);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord1);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord3);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord4);
+ break;
+ case GL_MAP2_VERTEX_3:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Vertex3);
+ break;
+ case GL_MAP2_VERTEX_4:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Vertex4);
+ break;
+ case GL_MAP_COLOR:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MapColorFlag);
+ break;
+ case GL_MAP_STENCIL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MapStencilFlag);
+ break;
+ case GL_MATRIX_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_CLIENT_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIP_PLANES:
+ params[0] = (GLfloat)(ctx->Const.MaxClipPlanes);
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ params[0] = (GLfloat)(ctx->Const.MaxArrayLockSize);
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ params[0] = (GLfloat)(ctx->Const.MaxArrayLockSize);
+ break;
+ case GL_MAX_EVAL_ORDER:
+ params[0] = (GLfloat)(MAX_EVAL_ORDER);
+ break;
+ case GL_MAX_LIGHTS:
+ params[0] = (GLfloat)(ctx->Const.MaxLights);
+ break;
+ case GL_MAX_LIST_NESTING:
+ params[0] = (GLfloat)(MAX_LIST_NESTING);
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_MODELVIEW_STACK_DEPTH);
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_NAME_STACK_DEPTH);
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ params[0] = (GLfloat)(MAX_PIXEL_MAP_TABLE);
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_PROJECTION_STACK_DEPTH);
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ params[0] = (GLfloat)(1 << (ctx->Const.MaxTextureLevels - 1));
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ params[0] = (GLfloat)(1 << (ctx->Const.Max3DTextureLevels - 1));
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ params[0] = (GLfloat)(MAX_TEXTURE_STACK_DEPTH);
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = (GLfloat)(ctx->Const.MaxViewportWidth);
+ params[1] = (GLfloat)(ctx->Const.MaxViewportHeight);
+ break;
+ case GL_MODELVIEW_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[1];
+ params[2] = matrix[2];
+ params[3] = matrix[3];
+ params[4] = matrix[4];
+ params[5] = matrix[5];
+ params[6] = matrix[6];
+ params[7] = matrix[7];
+ params[8] = matrix[8];
+ params[9] = matrix[9];
+ params[10] = matrix[10];
+ params[11] = matrix[11];
+ params[12] = matrix[12];
+ params[13] = matrix[13];
+ params[14] = matrix[14];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->ModelviewMatrixStack.Depth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->Select.NameStackDepth);
+ break;
+ case GL_NORMALIZE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.Normalize);
+ break;
+ case GL_PACK_ALIGNMENT:
+ params[0] = (GLfloat)(ctx->Pack.Alignment);
+ break;
+ case GL_PACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.LsbFirst);
+ break;
+ case GL_PACK_ROW_LENGTH:
+ params[0] = (GLfloat)(ctx->Pack.RowLength);
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ params[0] = (GLfloat)(ctx->Pack.SkipPixels);
+ break;
+ case GL_PACK_SKIP_ROWS:
+ params[0] = (GLfloat)(ctx->Pack.SkipRows);
+ break;
+ case GL_PACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.SwapBytes);
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ params[0] = (GLfloat)(ctx->Pack.SkipImages);
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ params[0] = (GLfloat)(ctx->Pack.ImageHeight);
+ break;
+ case GL_PACK_INVERT_MESA:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.Invert);
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.AtoA.Size);
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.BtoB.Size);
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.GtoG.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.ItoA.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.ItoB.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.ItoG.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.ItoI.Size);
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.ItoR.Size);
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.RtoR.Size);
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ params[0] = (GLfloat)(ctx->PixelMaps.StoS.Size);
+ break;
+ case GL_POINT_SIZE:
+ params[0] = ctx->Point.Size;
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ params[0] = ctx->Const.PointSizeGranularity;
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = ctx->Const.MinPointSizeAA;
+ params[1] = ctx->Const.MaxPointSizeAA;
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = ctx->Const.MinPointSize;
+ params[1] = ctx->Const.MaxPointSize;
+ break;
+ case GL_POINT_SMOOTH:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Point.SmoothFlag);
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ params[0] = ctx->Point.MinSize;
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ params[0] = ctx->Point.MaxSize;
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ params[0] = ctx->Point.Threshold;
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = ctx->Point.Params[0];
+ params[1] = ctx->Point.Params[1];
+ params[2] = 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;
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ params[0] = ctx->Polygon.OffsetUnits;
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ params[0] = ctx->Polygon.OffsetFactor ;
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ params[0] = ctx->Polygon.OffsetUnits ;
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.OffsetPoint);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.OffsetLine);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.OffsetFill);
+ break;
+ case GL_POLYGON_SMOOTH:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.StippleFlag);
+ break;
+ case GL_PROJECTION_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[1];
+ params[2] = matrix[2];
+ params[3] = matrix[3];
+ params[4] = matrix[4];
+ params[5] = matrix[5];
+ params[6] = matrix[6];
+ params[7] = matrix[7];
+ params[8] = matrix[8];
+ params[9] = matrix[9];
+ params[10] = matrix[10];
+ params[11] = matrix[11];
+ params[12] = matrix[12];
+ params[13] = matrix[13];
+ params[14] = matrix[14];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->ProjectionMatrixStack.Depth + 1);
+ break;
+ case GL_READ_BUFFER:
+ params[0] = ENUM_TO_FLOAT(ctx->ReadBuffer->ColorReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ params[0] = ctx->Pixel.RedBias;
+ break;
+ case GL_RED_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.redBits);
+ break;
+ case GL_RED_SCALE:
+ params[0] = ctx->Pixel.RedScale;
+ break;
+ case GL_RENDER_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->RenderMode);
+ break;
+ case GL_RESCALE_NORMAL:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.RescaleNormals);
+ break;
+ case GL_RGBA_MODE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.rgbMode);
+ 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[0] = BOOLEAN_TO_FLOAT(ctx->Scissor.Enabled);
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = (GLfloat)(ctx->Select.BufferSize);
+ break;
+ case GL_SHADE_MODEL:
+ params[0] = ENUM_TO_FLOAT(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.SharedPalette);
+ break;
+ case GL_STENCIL_BITS:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.stencilBits);
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ params[0] = (GLfloat)(ctx->Stencil.Clear);
+ break;
+ case GL_STENCIL_FAIL:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_FUNC:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.Function[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_REF:
+ params[0] = (GLfloat)(ctx->Stencil.Ref[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_TEST:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Stencil.Enabled);
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ params[0] = (GLfloat)(ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_WRITEMASK:
+ params[0] = (GLfloat)(ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STEREO:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.stereoMode);
+ break;
+ case GL_SUBPIXEL_BITS:
+ params[0] = (GLfloat)(ctx->Const.SubPixelBits);
+ break;
+ case GL_TEXTURE_1D:
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_1D));
+ break;
+ case GL_TEXTURE_2D:
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_2D));
+ break;
+ case GL_TEXTURE_3D:
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_3D));
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name);
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name);
+ break;
+ case GL_TEXTURE_GEN_S:
+ params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_T:
+ params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_R:
+ params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_Q:
+ params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_MATRIX:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[1];
+ params[2] = matrix[2];
+ params[3] = matrix[3];
+ params[4] = matrix[4];
+ params[5] = matrix[5];
+ params[6] = matrix[6];
+ params[7] = matrix[7];
+ params[8] = matrix[8];
+ params[9] = matrix[9];
+ params[10] = matrix[10];
+ params[11] = matrix[11];
+ params[12] = matrix[12];
+ params[13] = matrix[13];
+ params[14] = matrix[14];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ params[0] = (GLfloat)(ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ params[0] = (GLfloat)(ctx->Unpack.Alignment);
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.LsbFirst);
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ params[0] = (GLfloat)(ctx->Unpack.RowLength);
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ params[0] = (GLfloat)(ctx->Unpack.SkipPixels);
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ params[0] = (GLfloat)(ctx->Unpack.SkipRows);
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.SwapBytes);
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ params[0] = (GLfloat)(ctx->Unpack.SkipImages);
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ params[0] = (GLfloat)(ctx->Unpack.ImageHeight);
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.ClientStorage);
+ 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[0] = ctx->Pixel.ZoomX;
+ break;
+ case GL_ZOOM_Y:
+ params[0] = ctx->Pixel.ZoomY;
+ break;
+ case GL_VERTEX_ARRAY:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->Vertex.Enabled);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Vertex.Size);
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Vertex.Stride);
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_NORMAL_ARRAY:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->Normal.Enabled);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Normal.Stride);
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_COLOR_ARRAY:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->Color.Enabled);
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Color.Size);
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Color.Stride);
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_INDEX_ARRAY:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->Index.Enabled);
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Index.Stride);
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->EdgeFlag.Enabled);
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->EdgeFlag.Stride);
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ params[0] = (GLfloat)(0);
+ break;
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxTextureUnits);
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetFloatv");
+ params[0] = (GLfloat)(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetFloatv");
+ params[0] = (GLfloat)(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture);
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB));
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name);
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetFloatv");
+ params[0] = (GLfloat)((1 << (ctx->Const.MaxCubeTextureLevels - 1)));
+ break;
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ params[0] = (GLfloat)(ctx->Hint.TextureCompression);
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ params[0] = (GLfloat)(_mesa_get_compressed_formats(ctx, NULL, GL_FALSE));
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ {
+ GLint formats[100];
+ GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+ ASSERT(n <= 100);
+ for (i = 0; i < n; i++)
+ params[i] = ENUM_TO_FLOAT(formats[i]);
+ }
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.LockFirst);
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.LockCount);
+ break;
+ case GL_TRANSPOSE_COLOR_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[4];
+ params[2] = matrix[8];
+ params[3] = matrix[12];
+ params[4] = matrix[1];
+ params[5] = matrix[5];
+ params[6] = matrix[9];
+ params[7] = matrix[13];
+ params[8] = matrix[2];
+ params[9] = matrix[6];
+ params[10] = matrix[10];
+ params[11] = matrix[14];
+ params[12] = matrix[3];
+ params[13] = matrix[7];
+ params[14] = matrix[11];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[4];
+ params[2] = matrix[8];
+ params[3] = matrix[12];
+ params[4] = matrix[1];
+ params[5] = matrix[5];
+ params[6] = matrix[9];
+ params[7] = matrix[13];
+ params[8] = matrix[2];
+ params[9] = matrix[6];
+ params[10] = matrix[10];
+ params[11] = matrix[14];
+ params[12] = matrix[3];
+ params[13] = matrix[7];
+ params[14] = matrix[11];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_TRANSPOSE_PROJECTION_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[4];
+ params[2] = matrix[8];
+ params[3] = matrix[12];
+ params[4] = matrix[1];
+ params[5] = matrix[5];
+ params[6] = matrix[9];
+ params[7] = matrix[13];
+ params[8] = matrix[2];
+ params[9] = matrix[6];
+ params[10] = matrix[10];
+ params[11] = matrix[14];
+ params[12] = matrix[3];
+ params[13] = matrix[7];
+ params[14] = matrix[11];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_TRANSPOSE_TEXTURE_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[4];
+ params[2] = matrix[8];
+ params[3] = matrix[12];
+ params[4] = matrix[1];
+ params[5] = matrix[5];
+ params[6] = matrix[9];
+ params[7] = matrix[13];
+ params[8] = matrix[2];
+ params[9] = matrix[6];
+ params[10] = matrix[10];
+ params[11] = matrix[14];
+ params[12] = matrix[3];
+ params[13] = matrix[7];
+ params[14] = matrix[11];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_COLOR_MATRIX_SGI:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[1];
+ params[2] = matrix[2];
+ params[3] = matrix[3];
+ params[4] = matrix[4];
+ params[5] = matrix[5];
+ params[6] = matrix[6];
+ params[7] = matrix[7];
+ params[8] = matrix[8];
+ params[9] = matrix[9];
+ params[10] = matrix[10];
+ params[11] = matrix[11];
+ params[12] = matrix[12];
+ params[13] = matrix[13];
+ params[14] = matrix[14];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = (GLfloat)(ctx->ColorMatrixStack.Depth + 1);
+ break;
+ case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = (GLfloat)(MAX_COLOR_STACK_DEPTH);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixScale[0];
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixScale[1];
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixScale[2];
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixScale[3];
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixBias[0];
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixBias[1];
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixBias[2];
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI:
+ params[0] = ctx->Pixel.PostColorMatrixBias[3];
+ break;
+ case GL_CONVOLUTION_1D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Convolution1DEnabled);
+ break;
+ case GL_CONVOLUTION_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Convolution2DEnabled);
+ break;
+ case GL_SEPARABLE_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Separable2DEnabled);
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionScale[0];
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionScale[1];
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionScale[2];
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionScale[3];
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionBias[0];
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionBias[1];
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionBias[2];
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetFloatv");
+ params[0] = ctx->Pixel.PostConvolutionBias[3];
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXT1(EXT_histogram, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.HistogramEnabled);
+ break;
+ case GL_MINMAX:
+ CHECK_EXT1(EXT_histogram, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MinMaxEnabled);
+ break;
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_texture_color_table, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled);
+ break;
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXT2(EXT_secondary_color, ARB_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Fog.ColorSumEnabled);
+ break;
+ case GL_CURRENT_SECONDARY_COLOR_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetFloatv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0];
+ params[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1];
+ params[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2];
+ params[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3];
+ }
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->SecondaryColor.Enabled);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->SecondaryColor.Type);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->SecondaryColor.Stride);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->SecondaryColor.Size);
+ break;
+ case GL_CURRENT_FOG_COORDINATE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetFloatv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
+ }
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->FogCoord.Enabled);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Array.ArrayObj->FogCoord.Type);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->FogCoord.Stride);
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Fog.FogCoordinateSource);
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS_EXT:
+ CHECK_EXT1(EXT_texture_lod_bias, "GetFloatv");
+ params[0] = ctx->Const.MaxTextureLodBias;
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ CHECK_EXT1(EXT_texture_filter_anisotropic, "GetFloatv");
+ params[0] = ctx->Const.MaxTextureMaxAnisotropy;
+ break;
+ case GL_MULTISAMPLE_ARB:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.Enabled);
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToCoverage);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToOne);
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverage);
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE_ARB:
+ params[0] = ctx->Multisample.SampleCoverageValue;
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverageInvert);
+ break;
+ case GL_SAMPLE_BUFFERS_ARB:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.sampleBuffers);
+ break;
+ case GL_SAMPLES_ARB:
+ params[0] = (GLfloat)(ctx->DrawBuffer->Visual.samples);
+ break;
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXT1(IBM_rasterpos_clip, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.RasterPositionUnclipped);
+ break;
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Point.PointSprite);
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ CHECK_EXT1(NV_point_sprite, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Point.SpriteRMode);
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Point.SpriteOrigin);
+ break;
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ CHECK_EXT1(SGIS_generate_mipmap, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.GenerateMipmap);
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = (GLfloat)((ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[0].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[1].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[2].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[3].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[4].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[5].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[6].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[7].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[8].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[9].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[10].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[11].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[12].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[13].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[14].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Array.ArrayObj->VertexAttrib[15].Enabled);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[0]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[1]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[2]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[3]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[4]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[5]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[6]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[7]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[8]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[9]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[10]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[11]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[12]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[13]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[14]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[15]);
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXT1(NV_fragment_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_fragment_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0);
+ break;
+ case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV:
+ CHECK_EXT1(NV_fragment_program, "GetFloatv");
+ params[0] = (GLfloat)(MAX_NV_FRAGMENT_PROGRAM_PARAMS);
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV));
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name);
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxTextureRectSize);
+ break;
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Stencil.TestTwoSide);
+ break;
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT);
+ break;
+ case GL_MAX_SHININESS_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetFloatv");
+ params[0] = ctx->Const.MaxShininess;
+ break;
+ case GL_MAX_SPOT_EXPONENT_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetFloatv");
+ params[0] = ctx->Const.MaxSpotExponent;
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayBufferObj->Name);
+ break;
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Vertex.BufferObj->Name);
+ break;
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Normal.BufferObj->Name);
+ break;
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Color.BufferObj->Name);
+ break;
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Index.BufferObj->Name);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name);
+ break;
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->FogCoord.BufferObj->Name);
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat)(ctx->Array.ElementArrayBufferObj->Name);
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Pack.BufferObj->Name);
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Unpack.BufferObj->Name);
+ break;
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.Enabled);
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.PointSizeEnabled);
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.TwoSideEnabled);
+ break;
+ case GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxProgramMatrixStackDepth);
+ break;
+ case GL_MAX_PROGRAM_MATRICES_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxProgramMatrices);
+ break;
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->CurrentStack->Depth + 1);
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_fragment_program, "GetFloatv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[1];
+ params[2] = matrix[2];
+ params[3] = matrix[3];
+ params[4] = matrix[4];
+ params[5] = matrix[5];
+ params[6] = matrix[6];
+ params[7] = matrix[7];
+ params[8] = matrix[8];
+ params[9] = matrix[9];
+ params[10] = matrix[10];
+ params[11] = matrix[11];
+ params[12] = matrix[12];
+ params[13] = matrix[13];
+ params[14] = matrix[14];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ CHECK_EXT2(ARB_vertex_program, ARB_fragment_program, "GetFloatv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = matrix[0];
+ params[1] = matrix[4];
+ params[2] = matrix[8];
+ params[3] = matrix[12];
+ params[4] = matrix[1];
+ params[5] = matrix[5];
+ params[6] = matrix[9];
+ params[7] = matrix[13];
+ params[8] = matrix[2];
+ params[9] = matrix[6];
+ params[10] = matrix[10];
+ params[11] = matrix[14];
+ params[12] = matrix[3];
+ params[13] = matrix[7];
+ params[14] = matrix[11];
+ params[15] = matrix[15];
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS_ARB:
+ CHECK_EXT1(ARB_vertex_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.VertexProgram.MaxAttribs);
+ break;
+ case GL_PROGRAM_ERROR_POSITION_ARB:
+ CHECK_EXT4(NV_vertex_program, ARB_vertex_program, NV_fragment_program, ARB_fragment_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Program.ErrorPos);
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXT1(ARB_fragment_program, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_MAX_TEXTURE_COORDS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxTextureCoordUnits);
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxTextureImageUnits);
+ break;
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.BoundsTest);
+ break;
+ case GL_DEPTH_BOUNDS_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetFloatv");
+ params[0] = ctx->Depth.BoundsMin;
+ params[1] = ctx->Depth.BoundsMax;
+ break;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ params[0] = (GLfloat)(ctx->Const.MaxDrawBuffers);
+ break;
+ case GL_DRAW_BUFFER0_ARB:
+ params[0] = ENUM_TO_FLOAT(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_DRAW_BUFFER1_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];
+ params[0] = ENUM_TO_FLOAT(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER2_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];
+ params[0] = ENUM_TO_FLOAT(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER3_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];
+ params[0] = ENUM_TO_FLOAT(buffer);
+ }
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ CHECK_EXT1(OES_read_format, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.ColorReadType);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ CHECK_EXT1(OES_read_format, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.ColorReadFormat);
+ break;
+ case GL_NUM_FRAGMENT_REGISTERS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(6);
+ break;
+ case GL_NUM_FRAGMENT_CONSTANTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(8);
+ break;
+ case GL_NUM_PASSES_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(2);
+ break;
+ case GL_NUM_INSTRUCTIONS_PER_PASS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(8);
+ break;
+ case GL_NUM_INSTRUCTIONS_TOTAL_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(16);
+ break;
+ case GL_COLOR_ALPHA_PAIRING_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(GL_TRUE);
+ break;
+ case GL_NUM_LOOPBACK_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(3);
+ break;
+ case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(3);
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.Function[1]);
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ params[0] = (GLfloat)(ctx->Stencil.ValueMask[1]);
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ params[0] = (GLfloat)(ctx->Stencil.WriteMask[1]);
+ break;
+ case GL_STENCIL_BACK_REF:
+ params[0] = (GLfloat)(ctx->Stencil.Ref[1]);
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.FailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc[1]);
+ break;
+ case GL_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->DrawBuffer->Name);
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0);
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxColorAttachments);
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxRenderbufferSize);
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_blit, "GetFloatv");
+ params[0] = (GLfloat)(ctx->ReadBuffer->Name);
+ break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.FragmentProgram.MaxUniformComponents);
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetFloatv");
+ params[0] = ENUM_TO_FLOAT(ctx->Hint.FragmentShaderDerivative);
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.VertexProgram.MaxUniformComponents);
+ break;
+ case GL_MAX_VARYING_FLOATS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxVarying * 4);
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxVertexTextureImageUnits);
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
+ params[0] = (GLfloat)(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
+ break;
+ case GL_CURRENT_PROGRAM:
+ CHECK_EXT1(ARB_shader_objects, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0);
+ break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxSamples);
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Array.ArrayObj->Name);
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetFloatv");
+ params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetFloatv");
+ params[0] = (GLfloat)(ctx->Const.MaxServerWaitTimeout);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname);
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetIntegerv( GLenum pname, GLint *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->Driver.GetIntegerv &&
+ ctx->Driver.GetIntegerv(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumRedBits;
+ break;
+ case GL_ACCUM_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumGreenBits;
+ break;
+ case GL_ACCUM_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumBlueBits;
+ break;
+ case GL_ACCUM_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumAlphaBits;
+ 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[0] = IROUND(ctx->Pixel.AlphaBias);
+ break;
+ case GL_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.alphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ params[0] = IROUND(ctx->Pixel.AlphaScale);
+ break;
+ case GL_ALPHA_TEST:
+ params[0] = BOOLEAN_TO_INT(ctx->Color.AlphaEnabled);
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ params[0] = ENUM_TO_INT(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ params[0] = FLOAT_TO_INT(ctx->Color.AlphaRef);
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->AttribStackDepth;
+ break;
+ case GL_AUTO_NORMAL:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.AutoNormal);
+ break;
+ case GL_AUX_BUFFERS:
+ params[0] = ctx->DrawBuffer->Visual.numAuxBuffers;
+ break;
+ case GL_BLEND:
+ params[0] = BOOLEAN_TO_INT(ctx->Color.BlendEnabled);
+ break;
+ case GL_BLEND_DST:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_EXT:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_EXT:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_EXT:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_EXT:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendEquationRGB );
+ break;
+ case GL_BLEND_EQUATION_ALPHA_EXT:
+ params[0] = ENUM_TO_INT(ctx->Color.BlendEquationA );
+ 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[0] = IROUND(ctx->Pixel.BlueBias);
+ break;
+ case GL_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.blueBits;
+ break;
+ case GL_BLUE_SCALE:
+ params[0] = IROUND(ctx->Pixel.BlueScale);
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->ClientAttribStackDepth;
+ break;
+ case GL_CLIP_PLANE0:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 0) & 1);
+ break;
+ case GL_CLIP_PLANE1:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 1) & 1);
+ break;
+ case GL_CLIP_PLANE2:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 2) & 1);
+ break;
+ case GL_CLIP_PLANE3:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 3) & 1);
+ break;
+ case GL_CLIP_PLANE4:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 4) & 1);
+ break;
+ case GL_CLIP_PLANE5:
+ params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 5) & 1);
+ 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[0] = BOOLEAN_TO_INT(ctx->Light.ColorMaterialEnabled);
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ params[0] = ENUM_TO_INT(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ params[0] = ENUM_TO_INT(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[0] = BOOLEAN_TO_INT(ctx->Polygon.CullFlag);
+ break;
+ case GL_CULL_FACE_MODE:
+ params[0] = ENUM_TO_INT(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]);
+ params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]);
+ params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]);
+ params[3] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]);
+ }
+ break;
+ case GL_CURRENT_INDEX:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]);
+ }
+ break;
+ case GL_CURRENT_NORMAL:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]);
+ params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]);
+ params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_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] = IROUND(ctx->Current.RasterDistance);
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ params[0] = IROUND(ctx->Current.RasterIndex);
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = IROUND(ctx->Current.RasterPos[0]);
+ params[1] = IROUND(ctx->Current.RasterPos[1]);
+ params[2] = IROUND(ctx->Current.RasterPos[2]);
+ params[3] = IROUND(ctx->Current.RasterPos[3]);
+ break;
+ case GL_CURRENT_RASTER_SECONDARY_COLOR:
+ params[0] = FLOAT_TO_INT(ctx->Current.RasterSecondaryColor[0]);
+ params[1] = FLOAT_TO_INT(ctx->Current.RasterSecondaryColor[1]);
+ params[2] = FLOAT_TO_INT(ctx->Current.RasterSecondaryColor[2]);
+ params[3] = FLOAT_TO_INT(ctx->Current.RasterSecondaryColor[3]);
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ params[0] = IROUND(ctx->Current.RasterTexCoords[texUnit][0]);
+ params[1] = IROUND(ctx->Current.RasterTexCoords[texUnit][1]);
+ params[2] = IROUND(ctx->Current.RasterTexCoords[texUnit][2]);
+ params[3] = IROUND(ctx->Current.RasterTexCoords[texUnit][3]);
+ }
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ params[0] = BOOLEAN_TO_INT(ctx->Current.RasterPosValid);
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
+ params[1] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
+ params[2] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
+ params[3] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]);
+ }
+ break;
+ case GL_DEPTH_BIAS:
+ params[0] = IROUND(ctx->Pixel.DepthBias);
+ break;
+ case GL_DEPTH_BITS:
+ params[0] = ctx->DrawBuffer->Visual.depthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT(((GLfloat) ctx->Depth.Clear));
+ break;
+ case GL_DEPTH_FUNC:
+ params[0] = ENUM_TO_INT(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = FLOAT_TO_INT(ctx->Viewport.Near);
+ params[1] = FLOAT_TO_INT(ctx->Viewport.Far);
+ break;
+ case GL_DEPTH_SCALE:
+ params[0] = IROUND(ctx->Pixel.DepthScale);
+ break;
+ case GL_DEPTH_TEST:
+ params[0] = BOOLEAN_TO_INT(ctx->Depth.Test);
+ break;
+ case GL_DEPTH_WRITEMASK:
+ params[0] = BOOLEAN_TO_INT(ctx->Depth.Mask);
+ break;
+ case GL_DITHER:
+ params[0] = BOOLEAN_TO_INT(ctx->Color.DitherFlag);
+ break;
+ case GL_DOUBLEBUFFER:
+ params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.doubleBufferMode);
+ break;
+ case GL_DRAW_BUFFER:
+ params[0] = ENUM_TO_INT(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_EDGE_FLAG:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = BOOLEAN_TO_INT((ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0));
+ }
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ params[0] = BOOLEAN_TO_INT(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[0] = IROUND(ctx->Fog.Density);
+ break;
+ case GL_FOG_END:
+ params[0] = IROUND(ctx->Fog.End);
+ break;
+ case GL_FOG_HINT:
+ params[0] = ENUM_TO_INT(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ params[0] = IROUND(ctx->Fog.Index);
+ break;
+ case GL_FOG_MODE:
+ params[0] = ENUM_TO_INT(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ params[0] = IROUND(ctx->Fog.Start);
+ break;
+ case GL_FRONT_FACE:
+ params[0] = ENUM_TO_INT(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ params[0] = IROUND(ctx->Pixel.GreenBias);
+ break;
+ case GL_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.greenBits;
+ break;
+ case GL_GREEN_SCALE:
+ params[0] = IROUND(ctx->Pixel.GreenScale);
+ break;
+ case GL_INDEX_BITS:
+ params[0] = ctx->DrawBuffer->Visual.indexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ params[0] = ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ params[0] = BOOLEAN_TO_INT(!ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_INDEX_OFFSET:
+ params[0] = ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ params[0] = ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ params[0] = ctx->Color.IndexMask;
+ break;
+ case GL_LIGHT0:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[0].Enabled);
+ break;
+ case GL_LIGHT1:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[1].Enabled);
+ break;
+ case GL_LIGHT2:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[2].Enabled);
+ break;
+ case GL_LIGHT3:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[3].Enabled);
+ break;
+ case GL_LIGHT4:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[4].Enabled);
+ break;
+ case GL_LIGHT5:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[5].Enabled);
+ break;
+ case GL_LIGHT6:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[6].Enabled);
+ break;
+ case GL_LIGHT7:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Light[7].Enabled);
+ break;
+ case GL_LIGHTING:
+ params[0] = BOOLEAN_TO_INT(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] = ENUM_TO_INT(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Model.LocalViewer);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ params[0] = BOOLEAN_TO_INT(ctx->Light.Model.TwoSide);
+ break;
+ case GL_LINE_SMOOTH:
+ params[0] = BOOLEAN_TO_INT(ctx->Line.SmoothFlag);
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ params[0] = BOOLEAN_TO_INT(ctx->Line.StippleFlag);
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ params[0] = ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ params[0] = ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ params[0] = IROUND(ctx->Line.Width);
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ params[0] = IROUND(ctx->Const.LineWidthGranularity);
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = IROUND(ctx->Const.MinLineWidthAA);
+ params[1] = IROUND(ctx->Const.MaxLineWidthAA);
+ break;
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = IROUND(ctx->Const.MinLineWidth);
+ params[1] = IROUND(ctx->Const.MaxLineWidth);
+ break;
+ case GL_LIST_BASE:
+ params[0] = ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ params[0] = (ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0);
+ break;
+ case GL_LIST_MODE:
+ {
+ GLenum mode;
+ if (!ctx->CompileFlag)
+ mode = 0;
+ else if (ctx->ExecuteFlag)
+ mode = GL_COMPILE_AND_EXECUTE;
+ else
+ mode = GL_COMPILE;
+ params[0] = ENUM_TO_INT(mode);
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT(ctx->Color.IndexLogicOpEnabled);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT(ctx->Color.ColorLogicOpEnabled);
+ break;
+ case GL_LOGIC_OP_MODE:
+ params[0] = ENUM_TO_INT(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Color4);
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = IROUND(ctx->Eval.MapGrid1u1);
+ params[1] = IROUND(ctx->Eval.MapGrid1u2);
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Index);
+ break;
+ case GL_MAP1_NORMAL:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Normal);
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord1);
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord3);
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord4);
+ break;
+ case GL_MAP1_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Vertex3);
+ break;
+ case GL_MAP1_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Vertex4);
+ break;
+ case GL_MAP2_COLOR_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Color4);
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = IROUND(ctx->Eval.MapGrid2u1);
+ params[1] = IROUND(ctx->Eval.MapGrid2u2);
+ params[2] = IROUND(ctx->Eval.MapGrid2v1);
+ params[3] = IROUND(ctx->Eval.MapGrid2v2);
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid2un;
+ params[1] = ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Index);
+ break;
+ case GL_MAP2_NORMAL:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Normal);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord1);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord3);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord4);
+ break;
+ case GL_MAP2_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Vertex3);
+ break;
+ case GL_MAP2_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Vertex4);
+ break;
+ case GL_MAP_COLOR:
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.MapColorFlag);
+ break;
+ case GL_MAP_STENCIL:
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.MapStencilFlag);
+ break;
+ case GL_MATRIX_MODE:
+ params[0] = ENUM_TO_INT(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ params[0] = ctx->Const.MaxClipPlanes;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ params[0] = MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ params[0] = ctx->Const.MaxLights;
+ break;
+ case GL_MAX_LIST_NESTING:
+ params[0] = MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ params[0] = MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ params[0] = MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ params[0] = MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ params[0] = MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.MaxTextureLevels - 1);
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ params[0] = MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = ctx->Const.MaxViewportWidth;
+ params[1] = ctx->Const.MaxViewportHeight;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[1]);
+ params[2] = IROUND(matrix[2]);
+ params[3] = IROUND(matrix[3]);
+ params[4] = IROUND(matrix[4]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[6]);
+ params[7] = IROUND(matrix[7]);
+ params[8] = IROUND(matrix[8]);
+ params[9] = IROUND(matrix[9]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[11]);
+ params[12] = IROUND(matrix[12]);
+ params[13] = IROUND(matrix[13]);
+ params[14] = IROUND(matrix[14]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ params[0] = ctx->ModelviewMatrixStack.Depth + 1;
+ break;
+ case GL_NAME_STACK_DEPTH:
+ params[0] = ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ params[0] = BOOLEAN_TO_INT(ctx->Transform.Normalize);
+ break;
+ case GL_PACK_ALIGNMENT:
+ params[0] = ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT(ctx->Pack.LsbFirst);
+ break;
+ case GL_PACK_ROW_LENGTH:
+ params[0] = ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ params[0] = ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ params[0] = ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT(ctx->Pack.SwapBytes);
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Pack.ImageHeight;
+ break;
+ case GL_PACK_INVERT_MESA:
+ params[0] = BOOLEAN_TO_INT(ctx->Pack.Invert);
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ params[0] = ENUM_TO_INT(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.AtoA.Size;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.BtoB.Size;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.GtoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.ItoA.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.ItoB.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.ItoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ params[0] = ctx->PixelMaps.ItoI.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.ItoR.Size;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.RtoR.Size;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ params[0] = ctx->PixelMaps.StoS.Size;
+ break;
+ case GL_POINT_SIZE:
+ params[0] = IROUND(ctx->Point.Size);
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ params[0] = IROUND(ctx->Const.PointSizeGranularity);
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = IROUND(ctx->Const.MinPointSizeAA);
+ params[1] = IROUND(ctx->Const.MaxPointSizeAA);
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = IROUND(ctx->Const.MinPointSize);
+ params[1] = IROUND(ctx->Const.MaxPointSize);
+ break;
+ case GL_POINT_SMOOTH:
+ params[0] = BOOLEAN_TO_INT(ctx->Point.SmoothFlag);
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ params[0] = IROUND(ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ params[0] = IROUND(ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ params[0] = IROUND(ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = IROUND(ctx->Point.Params[0]);
+ params[1] = IROUND(ctx->Point.Params[1]);
+ params[2] = IROUND(ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_INT(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_INT(ctx->Polygon.BackMode);
+ break;
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ params[0] = IROUND(ctx->Polygon.OffsetUnits);
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ params[0] = IROUND(ctx->Polygon.OffsetFactor );
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ params[0] = IROUND(ctx->Polygon.OffsetUnits );
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ params[0] = BOOLEAN_TO_INT(ctx->Polygon.OffsetPoint);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ params[0] = BOOLEAN_TO_INT(ctx->Polygon.OffsetLine);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ params[0] = BOOLEAN_TO_INT(ctx->Polygon.OffsetFill);
+ break;
+ case GL_POLYGON_SMOOTH:
+ params[0] = BOOLEAN_TO_INT(ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ params[0] = BOOLEAN_TO_INT(ctx->Polygon.StippleFlag);
+ break;
+ case GL_PROJECTION_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[1]);
+ params[2] = IROUND(matrix[2]);
+ params[3] = IROUND(matrix[3]);
+ params[4] = IROUND(matrix[4]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[6]);
+ params[7] = IROUND(matrix[7]);
+ params[8] = IROUND(matrix[8]);
+ params[9] = IROUND(matrix[9]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[11]);
+ params[12] = IROUND(matrix[12]);
+ params[13] = IROUND(matrix[13]);
+ params[14] = IROUND(matrix[14]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ params[0] = ctx->ProjectionMatrixStack.Depth + 1;
+ break;
+ case GL_READ_BUFFER:
+ params[0] = ENUM_TO_INT(ctx->ReadBuffer->ColorReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ params[0] = IROUND(ctx->Pixel.RedBias);
+ break;
+ case GL_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.redBits;
+ break;
+ case GL_RED_SCALE:
+ params[0] = IROUND(ctx->Pixel.RedScale);
+ break;
+ case GL_RENDER_MODE:
+ params[0] = ENUM_TO_INT(ctx->RenderMode);
+ break;
+ case GL_RESCALE_NORMAL:
+ params[0] = BOOLEAN_TO_INT(ctx->Transform.RescaleNormals);
+ break;
+ case GL_RGBA_MODE:
+ params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = ctx->Scissor.X;
+ params[1] = ctx->Scissor.Y;
+ params[2] = ctx->Scissor.Width;
+ params[3] = ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ params[0] = BOOLEAN_TO_INT(ctx->Scissor.Enabled);
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ params[0] = ENUM_TO_INT(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ params[0] = BOOLEAN_TO_INT(ctx->Texture.SharedPalette);
+ break;
+ case GL_STENCIL_BITS:
+ params[0] = ctx->DrawBuffer->Visual.stencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ params[0] = ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ params[0] = ENUM_TO_INT(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_FUNC:
+ params[0] = ENUM_TO_INT(ctx->Stencil.Function[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_REF:
+ params[0] = ctx->Stencil.Ref[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_TEST:
+ params[0] = BOOLEAN_TO_INT(ctx->Stencil.Enabled);
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STEREO:
+ params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.stereoMode);
+ break;
+ case GL_SUBPIXEL_BITS:
+ params[0] = ctx->Const.SubPixelBits;
+ break;
+ case GL_TEXTURE_1D:
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_1D));
+ break;
+ case GL_TEXTURE_2D:
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_2D));
+ break;
+ case GL_TEXTURE_3D:
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_3D));
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetIntegerv");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetIntegerv");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_GEN_S:
+ params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_T:
+ params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_R:
+ params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_Q:
+ params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_MATRIX:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[1]);
+ params[2] = IROUND(matrix[2]);
+ params[3] = IROUND(matrix[3]);
+ params[4] = IROUND(matrix[4]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[6]);
+ params[7] = IROUND(matrix[7]);
+ params[8] = IROUND(matrix[8]);
+ params[9] = IROUND(matrix[9]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[11]);
+ params[12] = IROUND(matrix[12]);
+ params[13] = IROUND(matrix[13]);
+ params[14] = IROUND(matrix[14]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ params[0] = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1;
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ params[0] = ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT(ctx->Unpack.LsbFirst);
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ params[0] = ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ params[0] = ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ params[0] = ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT(ctx->Unpack.SwapBytes);
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Unpack.ImageHeight;
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ params[0] = BOOLEAN_TO_INT(ctx->Unpack.ClientStorage);
+ break;
+ case GL_VIEWPORT:
+ params[0] = ctx->Viewport.X;
+ params[1] = ctx->Viewport.Y;
+ params[2] = ctx->Viewport.Width;
+ params[3] = ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ params[0] = IROUND(ctx->Pixel.ZoomX);
+ break;
+ case GL_ZOOM_Y:
+ params[0] = IROUND(ctx->Pixel.ZoomY);
+ break;
+ case GL_VERTEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->Vertex.Enabled);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_NORMAL_ARRAY:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->Normal.Enabled);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_COLOR_ARRAY:
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->Color.Enabled);
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_INDEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->Index.Enabled);
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->EdgeFlag.Enabled);
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetIntegerv");
+ params[0] = ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetIntegerv");
+ params[0] = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetIntegerv");
+ params[0] = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB));
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetIntegerv");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name;
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetIntegerv");
+ params[0] = (1 << (ctx->Const.MaxCubeTextureLevels - 1));
+ break;
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ params[0] = ctx->Hint.TextureCompression;
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ params[0] = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ {
+ GLint formats[100];
+ GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+ ASSERT(n <= 100);
+ for (i = 0; i < n; i++)
+ params[i] = ENUM_TO_INT(formats[i]);
+ }
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetIntegerv");
+ params[0] = ctx->Array.LockFirst;
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetIntegerv");
+ params[0] = ctx->Array.LockCount;
+ break;
+ case GL_TRANSPOSE_COLOR_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[4]);
+ params[2] = IROUND(matrix[8]);
+ params[3] = IROUND(matrix[12]);
+ params[4] = IROUND(matrix[1]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[9]);
+ params[7] = IROUND(matrix[13]);
+ params[8] = IROUND(matrix[2]);
+ params[9] = IROUND(matrix[6]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[14]);
+ params[12] = IROUND(matrix[3]);
+ params[13] = IROUND(matrix[7]);
+ params[14] = IROUND(matrix[11]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[4]);
+ params[2] = IROUND(matrix[8]);
+ params[3] = IROUND(matrix[12]);
+ params[4] = IROUND(matrix[1]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[9]);
+ params[7] = IROUND(matrix[13]);
+ params[8] = IROUND(matrix[2]);
+ params[9] = IROUND(matrix[6]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[14]);
+ params[12] = IROUND(matrix[3]);
+ params[13] = IROUND(matrix[7]);
+ params[14] = IROUND(matrix[11]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_PROJECTION_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[4]);
+ params[2] = IROUND(matrix[8]);
+ params[3] = IROUND(matrix[12]);
+ params[4] = IROUND(matrix[1]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[9]);
+ params[7] = IROUND(matrix[13]);
+ params[8] = IROUND(matrix[2]);
+ params[9] = IROUND(matrix[6]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[14]);
+ params[12] = IROUND(matrix[3]);
+ params[13] = IROUND(matrix[7]);
+ params[14] = IROUND(matrix[11]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_TEXTURE_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[4]);
+ params[2] = IROUND(matrix[8]);
+ params[3] = IROUND(matrix[12]);
+ params[4] = IROUND(matrix[1]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[9]);
+ params[7] = IROUND(matrix[13]);
+ params[8] = IROUND(matrix[2]);
+ params[9] = IROUND(matrix[6]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[14]);
+ params[12] = IROUND(matrix[3]);
+ params[13] = IROUND(matrix[7]);
+ params[14] = IROUND(matrix[11]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_SGI:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[1]);
+ params[2] = IROUND(matrix[2]);
+ params[3] = IROUND(matrix[3]);
+ params[4] = IROUND(matrix[4]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[6]);
+ params[7] = IROUND(matrix[7]);
+ params[8] = IROUND(matrix[8]);
+ params[9] = IROUND(matrix[9]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[11]);
+ params[12] = IROUND(matrix[12]);
+ params[13] = IROUND(matrix[13]);
+ params[14] = IROUND(matrix[14]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = ctx->ColorMatrixStack.Depth + 1;
+ break;
+ case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = MAX_COLOR_STACK_DEPTH;
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[3]);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI:
+ params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[3]);
+ break;
+ case GL_CONVOLUTION_1D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.Convolution1DEnabled);
+ break;
+ case GL_CONVOLUTION_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.Convolution2DEnabled);
+ break;
+ case GL_SEPARABLE_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.Separable2DEnabled);
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionScale[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionScale[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionScale[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionScale[3]);
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionBias[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionBias[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionBias[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetIntegerv");
+ params[0] = IROUND(ctx->Pixel.PostConvolutionBias[3]);
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXT1(EXT_histogram, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.HistogramEnabled);
+ break;
+ case GL_MINMAX:
+ CHECK_EXT1(EXT_histogram, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.MinMaxEnabled);
+ break;
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_texture_color_table, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled);
+ break;
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXT2(EXT_secondary_color, ARB_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Fog.ColorSumEnabled);
+ break;
+ case GL_CURRENT_SECONDARY_COLOR_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetIntegerv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]);
+ params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]);
+ params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]);
+ params[3] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]);
+ }
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->SecondaryColor.Enabled);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->SecondaryColor.Type);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetIntegerv");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Stride;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetIntegerv");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Size;
+ break;
+ case GL_CURRENT_FOG_COORDINATE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetIntegerv");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
+ }
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->FogCoord.Enabled);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Array.ArrayObj->FogCoord.Type);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetIntegerv");
+ params[0] = ctx->Array.ArrayObj->FogCoord.Stride;
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Fog.FogCoordinateSource);
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS_EXT:
+ CHECK_EXT1(EXT_texture_lod_bias, "GetIntegerv");
+ params[0] = IROUND(ctx->Const.MaxTextureLodBias);
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ CHECK_EXT1(EXT_texture_filter_anisotropic, "GetIntegerv");
+ params[0] = IROUND(ctx->Const.MaxTextureMaxAnisotropy);
+ break;
+ case GL_MULTISAMPLE_ARB:
+ params[0] = BOOLEAN_TO_INT(ctx->Multisample.Enabled);
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToCoverage);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToOne);
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverage);
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE_ARB:
+ params[0] = IROUND(ctx->Multisample.SampleCoverageValue);
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverageInvert);
+ break;
+ case GL_SAMPLE_BUFFERS_ARB:
+ params[0] = ctx->DrawBuffer->Visual.sampleBuffers;
+ break;
+ case GL_SAMPLES_ARB:
+ params[0] = ctx->DrawBuffer->Visual.samples;
+ break;
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXT1(IBM_rasterpos_clip, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Transform.RasterPositionUnclipped);
+ break;
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Point.PointSprite);
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ CHECK_EXT1(NV_point_sprite, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Point.SpriteRMode);
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Point.SpriteOrigin);
+ break;
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ CHECK_EXT1(SGIS_generate_mipmap, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Hint.GenerateMipmap);
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = (ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[0].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[1].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[2].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[3].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[4].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[5].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[6].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[7].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[8].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[9].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[10].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[11].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[12].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[13].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[14].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Array.ArrayObj->VertexAttrib[15].Enabled);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[0]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[1]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[2]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[3]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[4]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[5]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[6]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[7]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[8]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[9]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[10]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[11]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[12]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[13]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[14]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[15]);
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXT1(NV_fragment_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_fragment_program, "GetIntegerv");
+ params[0] = ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0;
+ break;
+ case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV:
+ CHECK_EXT1(NV_fragment_program, "GetIntegerv");
+ params[0] = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV));
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetIntegerv");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name;
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetIntegerv");
+ params[0] = ctx->Const.MaxTextureRectSize;
+ break;
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Stencil.TestTwoSide);
+ break;
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT);
+ break;
+ case GL_MAX_SHININESS_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetIntegerv");
+ params[0] = IROUND(ctx->Const.MaxShininess);
+ break;
+ case GL_MAX_SPOT_EXPONENT_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetIntegerv");
+ params[0] = IROUND(ctx->Const.MaxSpotExponent);
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayBufferObj->Name;
+ break;
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Vertex.BufferObj->Name;
+ break;
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Normal.BufferObj->Name;
+ break;
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Color.BufferObj->Name;
+ break;
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Index.BufferObj->Name;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
+ break;
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->FogCoord.BufferObj->Name;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ElementArrayBufferObj->Name;
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetIntegerv");
+ params[0] = ctx->Pack.BufferObj->Name;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetIntegerv");
+ params[0] = ctx->Unpack.BufferObj->Name;
+ break;
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.Enabled);
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.PointSizeEnabled);
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.TwoSideEnabled);
+ break;
+ case GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetIntegerv");
+ params[0] = ctx->Const.MaxProgramMatrixStackDepth;
+ break;
+ case GL_MAX_PROGRAM_MATRICES_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetIntegerv");
+ params[0] = ctx->Const.MaxProgramMatrices;
+ break;
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->CurrentStack->Depth + 1);
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_fragment_program, "GetIntegerv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[1]);
+ params[2] = IROUND(matrix[2]);
+ params[3] = IROUND(matrix[3]);
+ params[4] = IROUND(matrix[4]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[6]);
+ params[7] = IROUND(matrix[7]);
+ params[8] = IROUND(matrix[8]);
+ params[9] = IROUND(matrix[9]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[11]);
+ params[12] = IROUND(matrix[12]);
+ params[13] = IROUND(matrix[13]);
+ params[14] = IROUND(matrix[14]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ CHECK_EXT2(ARB_vertex_program, ARB_fragment_program, "GetIntegerv");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND(matrix[0]);
+ params[1] = IROUND(matrix[4]);
+ params[2] = IROUND(matrix[8]);
+ params[3] = IROUND(matrix[12]);
+ params[4] = IROUND(matrix[1]);
+ params[5] = IROUND(matrix[5]);
+ params[6] = IROUND(matrix[9]);
+ params[7] = IROUND(matrix[13]);
+ params[8] = IROUND(matrix[2]);
+ params[9] = IROUND(matrix[6]);
+ params[10] = IROUND(matrix[10]);
+ params[11] = IROUND(matrix[14]);
+ params[12] = IROUND(matrix[3]);
+ params[13] = IROUND(matrix[7]);
+ params[14] = IROUND(matrix[11]);
+ params[15] = IROUND(matrix[15]);
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS_ARB:
+ CHECK_EXT1(ARB_vertex_program, "GetIntegerv");
+ params[0] = ctx->Const.VertexProgram.MaxAttribs;
+ break;
+ case GL_PROGRAM_ERROR_POSITION_ARB:
+ CHECK_EXT4(NV_vertex_program, ARB_vertex_program, NV_fragment_program, ARB_fragment_program, "GetIntegerv");
+ params[0] = ctx->Program.ErrorPos;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXT1(ARB_fragment_program, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_MAX_TEXTURE_COORDS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetIntegerv");
+ params[0] = ctx->Const.MaxTextureCoordUnits;
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetIntegerv");
+ params[0] = ctx->Const.MaxTextureImageUnits;
+ break;
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Depth.BoundsTest);
+ break;
+ case GL_DEPTH_BOUNDS_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetIntegerv");
+ params[0] = IROUND(ctx->Depth.BoundsMin);
+ params[1] = IROUND(ctx->Depth.BoundsMax);
+ break;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ params[0] = ctx->Const.MaxDrawBuffers;
+ break;
+ case GL_DRAW_BUFFER0_ARB:
+ params[0] = ENUM_TO_INT(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_DRAW_BUFFER1_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];
+ params[0] = ENUM_TO_INT(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER2_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];
+ params[0] = ENUM_TO_INT(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER3_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];
+ params[0] = ENUM_TO_INT(buffer);
+ }
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ CHECK_EXT1(OES_read_format, "GetIntegerv");
+ params[0] = ctx->Const.ColorReadType;
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ CHECK_EXT1(OES_read_format, "GetIntegerv");
+ params[0] = ctx->Const.ColorReadFormat;
+ break;
+ case GL_NUM_FRAGMENT_REGISTERS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 6;
+ break;
+ case GL_NUM_FRAGMENT_CONSTANTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 8;
+ break;
+ case GL_NUM_PASSES_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 2;
+ break;
+ case GL_NUM_INSTRUCTIONS_PER_PASS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 8;
+ break;
+ case GL_NUM_INSTRUCTIONS_TOTAL_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 16;
+ break;
+ case GL_COLOR_ALPHA_PAIRING_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(GL_TRUE);
+ break;
+ case GL_NUM_LOOPBACK_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 3;
+ break;
+ case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetIntegerv");
+ params[0] = 3;
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ params[0] = ENUM_TO_INT(ctx->Stencil.Function[1]);
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[1];
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[1];
+ break;
+ case GL_STENCIL_BACK_REF:
+ params[0] = ctx->Stencil.Ref[1];
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ params[0] = ENUM_TO_INT(ctx->Stencil.FailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT(ctx->Stencil.ZFailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT(ctx->Stencil.ZPassFunc[1]);
+ break;
+ case GL_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->DrawBuffer->Name;
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->Const.MaxColorAttachments;
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->Const.MaxRenderbufferSize;
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_blit, "GetIntegerv");
+ params[0] = ctx->ReadBuffer->Name;
+ break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetIntegerv");
+ params[0] = ctx->Const.FragmentProgram.MaxUniformComponents;
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetIntegerv");
+ params[0] = ENUM_TO_INT(ctx->Hint.FragmentShaderDerivative);
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
+ params[0] = ctx->Const.VertexProgram.MaxUniformComponents;
+ break;
+ case GL_MAX_VARYING_FLOATS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
+ params[0] = ctx->Const.MaxVarying * 4;
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
+ params[0] = ctx->Const.MaxVertexTextureImageUnits;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
+ params[0] = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ break;
+ case GL_CURRENT_PROGRAM:
+ CHECK_EXT1(ARB_shader_objects, "GetIntegerv");
+ params[0] = ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0;
+ break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetIntegerv");
+ params[0] = ctx->Const.MaxSamples;
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetIntegerv");
+ params[0] = ctx->Array.ArrayObj->Name;
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetIntegerv");
+ params[0] = BOOLEAN_TO_INT(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetIntegerv");
+ params[0] = INT64_TO_INT(ctx->Const.MaxServerWaitTimeout);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
+ }
+}
+
+#if FEATURE_ARB_sync
+void GLAPIENTRY
+_mesa_GetInteger64v( GLenum pname, GLint64 *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (ctx->Driver.GetInteger64v &&
+ ctx->Driver.GetInteger64v(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumRedBits;
+ break;
+ case GL_ACCUM_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumGreenBits;
+ break;
+ case GL_ACCUM_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumBlueBits;
+ break;
+ case GL_ACCUM_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.accumAlphaBits;
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(ctx->Accum.ClearColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Accum.ClearColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Accum.ClearColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Accum.ClearColor[3]);
+ break;
+ case GL_ALPHA_BIAS:
+ params[0] = IROUND64(ctx->Pixel.AlphaBias);
+ break;
+ case GL_ALPHA_BITS:
+ params[0] = ctx->DrawBuffer->Visual.alphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ params[0] = IROUND64(ctx->Pixel.AlphaScale);
+ break;
+ case GL_ALPHA_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.AlphaEnabled);
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ params[0] = FLOAT_TO_INT64(ctx->Color.AlphaRef);
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->AttribStackDepth;
+ break;
+ case GL_AUTO_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.AutoNormal);
+ break;
+ case GL_AUX_BUFFERS:
+ params[0] = ctx->DrawBuffer->Visual.numAuxBuffers;
+ break;
+ case GL_BLEND:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.BlendEnabled);
+ break;
+ case GL_BLEND_DST:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendEquationRGB );
+ break;
+ case GL_BLEND_EQUATION_ALPHA_EXT:
+ params[0] = ENUM_TO_INT64(ctx->Color.BlendEquationA );
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = FLOAT_TO_INT64(ctx->Color.BlendColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Color.BlendColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Color.BlendColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Color.BlendColor[3]);
+ break;
+ case GL_BLUE_BIAS:
+ params[0] = IROUND64(ctx->Pixel.BlueBias);
+ break;
+ case GL_BLUE_BITS:
+ params[0] = ctx->DrawBuffer->Visual.blueBits;
+ break;
+ case GL_BLUE_SCALE:
+ params[0] = IROUND64(ctx->Pixel.BlueScale);
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = ctx->ClientAttribStackDepth;
+ break;
+ case GL_CLIP_PLANE0:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 0) & 1);
+ break;
+ case GL_CLIP_PLANE1:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 1) & 1);
+ break;
+ case GL_CLIP_PLANE2:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 2) & 1);
+ break;
+ case GL_CLIP_PLANE3:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 3) & 1);
+ break;
+ case GL_CLIP_PLANE4:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 4) & 1);
+ break;
+ case GL_CLIP_PLANE5:
+ params[0] = BOOLEAN_TO_INT64((ctx->Transform.ClipPlanesEnabled >> 5) & 1);
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(ctx->Color.ClearColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Color.ClearColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Color.ClearColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Color.ClearColor[3]);
+ break;
+ case GL_COLOR_MATERIAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.ColorMaterialEnabled);
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ params[0] = ENUM_TO_INT64(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ params[0] = ENUM_TO_INT64(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[0] = BOOLEAN_TO_INT64(ctx->Polygon.CullFlag);
+ break;
+ case GL_CULL_FACE_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]);
+ }
+ break;
+ case GL_CURRENT_INDEX:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0]);
+ }
+ break;
+ case GL_CURRENT_NORMAL:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]);
+ }
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Current.RasterColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.RasterColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.RasterColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.RasterColor[3]);
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = IROUND64(ctx->Current.RasterDistance);
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ params[0] = IROUND64(ctx->Current.RasterIndex);
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = IROUND64(ctx->Current.RasterPos[0]);
+ params[1] = IROUND64(ctx->Current.RasterPos[1]);
+ params[2] = IROUND64(ctx->Current.RasterPos[2]);
+ params[3] = IROUND64(ctx->Current.RasterPos[3]);
+ break;
+ case GL_CURRENT_RASTER_SECONDARY_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.RasterSecondaryColor[3]);
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ params[0] = IROUND64(ctx->Current.RasterTexCoords[texUnit][0]);
+ params[1] = IROUND64(ctx->Current.RasterTexCoords[texUnit][1]);
+ params[2] = IROUND64(ctx->Current.RasterTexCoords[texUnit][2]);
+ params[3] = IROUND64(ctx->Current.RasterTexCoords[texUnit][3]);
+ }
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ params[0] = BOOLEAN_TO_INT64(ctx->Current.RasterPosValid);
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const GLuint texUnit = ctx->Texture.CurrentUnit;
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]);
+ params[1] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]);
+ params[2] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]);
+ params[3] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]);
+ }
+ break;
+ case GL_DEPTH_BIAS:
+ params[0] = IROUND64(ctx->Pixel.DepthBias);
+ break;
+ case GL_DEPTH_BITS:
+ params[0] = ctx->DrawBuffer->Visual.depthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT64(((GLfloat) ctx->Depth.Clear));
+ break;
+ case GL_DEPTH_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = FLOAT_TO_INT64(ctx->Viewport.Near);
+ params[1] = FLOAT_TO_INT64(ctx->Viewport.Far);
+ break;
+ case GL_DEPTH_SCALE:
+ params[0] = IROUND64(ctx->Pixel.DepthScale);
+ break;
+ case GL_DEPTH_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.Test);
+ break;
+ case GL_DEPTH_WRITEMASK:
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.Mask);
+ break;
+ case GL_DITHER:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.DitherFlag);
+ break;
+ case GL_DOUBLEBUFFER:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.doubleBufferMode);
+ break;
+ case GL_DRAW_BUFFER:
+ params[0] = ENUM_TO_INT64(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_EDGE_FLAG:
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = BOOLEAN_TO_INT64((ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0] == 1.0));
+ }
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ params[0] = ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ params[0] = BOOLEAN_TO_INT64(ctx->Fog.Enabled);
+ break;
+ case GL_FOG_COLOR:
+ params[0] = FLOAT_TO_INT64(ctx->Fog.Color[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Fog.Color[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Fog.Color[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Fog.Color[3]);
+ break;
+ case GL_FOG_DENSITY:
+ params[0] = IROUND64(ctx->Fog.Density);
+ break;
+ case GL_FOG_END:
+ params[0] = IROUND64(ctx->Fog.End);
+ break;
+ case GL_FOG_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ params[0] = IROUND64(ctx->Fog.Index);
+ break;
+ case GL_FOG_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ params[0] = IROUND64(ctx->Fog.Start);
+ break;
+ case GL_FRONT_FACE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ params[0] = IROUND64(ctx->Pixel.GreenBias);
+ break;
+ case GL_GREEN_BITS:
+ params[0] = ctx->DrawBuffer->Visual.greenBits;
+ break;
+ case GL_GREEN_SCALE:
+ params[0] = IROUND64(ctx->Pixel.GreenScale);
+ break;
+ case GL_INDEX_BITS:
+ params[0] = ctx->DrawBuffer->Visual.indexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ params[0] = ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ params[0] = BOOLEAN_TO_INT64(!ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_INDEX_OFFSET:
+ params[0] = ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ params[0] = ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ params[0] = ctx->Color.IndexMask;
+ break;
+ case GL_LIGHT0:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[0].Enabled);
+ break;
+ case GL_LIGHT1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[1].Enabled);
+ break;
+ case GL_LIGHT2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[2].Enabled);
+ break;
+ case GL_LIGHT3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[3].Enabled);
+ break;
+ case GL_LIGHT4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[4].Enabled);
+ break;
+ case GL_LIGHT5:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[5].Enabled);
+ break;
+ case GL_LIGHT6:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[6].Enabled);
+ break;
+ case GL_LIGHT7:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Light[7].Enabled);
+ break;
+ case GL_LIGHTING:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Enabled);
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[0]);
+ params[1] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[1]);
+ params[2] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[2]);
+ params[3] = FLOAT_TO_INT64(ctx->Light.Model.Ambient[3]);
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = ENUM_TO_INT64(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Model.LocalViewer);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.Model.TwoSide);
+ break;
+ case GL_LINE_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Line.SmoothFlag);
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Line.StippleFlag);
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ params[0] = ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ params[0] = ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ params[0] = IROUND64(ctx->Line.Width);
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ params[0] = IROUND64(ctx->Const.LineWidthGranularity);
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = IROUND64(ctx->Const.MinLineWidthAA);
+ params[1] = IROUND64(ctx->Const.MaxLineWidthAA);
+ break;
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = IROUND64(ctx->Const.MinLineWidth);
+ params[1] = IROUND64(ctx->Const.MaxLineWidth);
+ break;
+ case GL_LIST_BASE:
+ params[0] = ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ params[0] = (ctx->ListState.CurrentList ? ctx->ListState.CurrentList->Name : 0);
+ break;
+ case GL_LIST_MODE:
+ {
+ GLenum mode;
+ if (!ctx->CompileFlag)
+ mode = 0;
+ else if (ctx->ExecuteFlag)
+ mode = GL_COMPILE_AND_EXECUTE;
+ else
+ mode = GL_COMPILE;
+ params[0] = ENUM_TO_INT64(mode);
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.IndexLogicOpEnabled);
+ break;
+ case GL_COLOR_LOGIC_OP:
+ params[0] = BOOLEAN_TO_INT64(ctx->Color.ColorLogicOpEnabled);
+ break;
+ case GL_LOGIC_OP_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Color4);
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = IROUND64(ctx->Eval.MapGrid1u1);
+ params[1] = IROUND64(ctx->Eval.MapGrid1u2);
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Index);
+ break;
+ case GL_MAP1_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Normal);
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord1);
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord3);
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1TextureCoord4);
+ break;
+ case GL_MAP1_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Vertex3);
+ break;
+ case GL_MAP1_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Vertex4);
+ break;
+ case GL_MAP2_COLOR_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Color4);
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = IROUND64(ctx->Eval.MapGrid2u1);
+ params[1] = IROUND64(ctx->Eval.MapGrid2u2);
+ params[2] = IROUND64(ctx->Eval.MapGrid2v1);
+ params[3] = IROUND64(ctx->Eval.MapGrid2v2);
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = ctx->Eval.MapGrid2un;
+ params[1] = ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Index);
+ break;
+ case GL_MAP2_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Normal);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord1);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord3);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2TextureCoord4);
+ break;
+ case GL_MAP2_VERTEX_3:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Vertex3);
+ break;
+ case GL_MAP2_VERTEX_4:
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map2Vertex4);
+ break;
+ case GL_MAP_COLOR:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MapColorFlag);
+ break;
+ case GL_MAP_STENCIL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MapStencilFlag);
+ break;
+ case GL_MATRIX_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ params[0] = MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ params[0] = ctx->Const.MaxClipPlanes;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ params[0] = ctx->Const.MaxArrayLockSize;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ params[0] = MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ params[0] = ctx->Const.MaxLights;
+ break;
+ case GL_MAX_LIST_NESTING:
+ params[0] = MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ params[0] = MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ params[0] = MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ params[0] = MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ params[0] = MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.MaxTextureLevels - 1);
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ params[0] = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ params[0] = MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = ctx->Const.MaxViewportWidth;
+ params[1] = ctx->Const.MaxViewportHeight;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ params[0] = ctx->ModelviewMatrixStack.Depth + 1;
+ break;
+ case GL_NAME_STACK_DEPTH:
+ params[0] = ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.Normalize);
+ break;
+ case GL_PACK_ALIGNMENT:
+ params[0] = ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.LsbFirst);
+ break;
+ case GL_PACK_ROW_LENGTH:
+ params[0] = ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ params[0] = ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ params[0] = ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.SwapBytes);
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Pack.ImageHeight;
+ break;
+ case GL_PACK_INVERT_MESA:
+ params[0] = BOOLEAN_TO_INT64(ctx->Pack.Invert);
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.AtoA.Size;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.BtoB.Size;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.GtoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ params[0] = ctx->PixelMaps.ItoA.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ params[0] = ctx->PixelMaps.ItoB.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ params[0] = ctx->PixelMaps.ItoG.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ params[0] = ctx->PixelMaps.ItoI.Size;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.ItoR.Size;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ params[0] = ctx->PixelMaps.RtoR.Size;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ params[0] = ctx->PixelMaps.StoS.Size;
+ break;
+ case GL_POINT_SIZE:
+ params[0] = IROUND64(ctx->Point.Size);
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ params[0] = IROUND64(ctx->Const.PointSizeGranularity);
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = IROUND64(ctx->Const.MinPointSizeAA);
+ params[1] = IROUND64(ctx->Const.MaxPointSizeAA);
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = IROUND64(ctx->Const.MinPointSize);
+ params[1] = IROUND64(ctx->Const.MaxPointSize);
+ break;
+ case GL_POINT_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Point.SmoothFlag);
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ params[0] = IROUND64(ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ params[0] = IROUND64(ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ params[0] = IROUND64(ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = IROUND64(ctx->Point.Params[0]);
+ params[1] = IROUND64(ctx->Point.Params[1]);
+ params[2] = IROUND64(ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_INT64(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_INT64(ctx->Polygon.BackMode);
+ break;
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ params[0] = IROUND64(ctx->Polygon.OffsetUnits);
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ params[0] = IROUND64(ctx->Polygon.OffsetFactor );
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ params[0] = IROUND64(ctx->Polygon.OffsetUnits );
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetPoint);
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetLine);
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.OffsetFill);
+ break;
+ case GL_POLYGON_SMOOTH:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.SmoothFlag);
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ params[0] = ENUM_TO_INT64(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Polygon.StippleFlag);
+ break;
+ case GL_PROJECTION_MATRIX:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ params[0] = ctx->ProjectionMatrixStack.Depth + 1;
+ break;
+ case GL_READ_BUFFER:
+ params[0] = ENUM_TO_INT64(ctx->ReadBuffer->ColorReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ params[0] = IROUND64(ctx->Pixel.RedBias);
+ break;
+ case GL_RED_BITS:
+ params[0] = ctx->DrawBuffer->Visual.redBits;
+ break;
+ case GL_RED_SCALE:
+ params[0] = IROUND64(ctx->Pixel.RedScale);
+ break;
+ case GL_RENDER_MODE:
+ params[0] = ENUM_TO_INT64(ctx->RenderMode);
+ break;
+ case GL_RESCALE_NORMAL:
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.RescaleNormals);
+ break;
+ case GL_RGBA_MODE:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.rgbMode);
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = ctx->Scissor.X;
+ params[1] = ctx->Scissor.Y;
+ params[2] = ctx->Scissor.Width;
+ params[3] = ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Scissor.Enabled);
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ params[0] = ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ params[0] = ENUM_TO_INT64(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.SharedPalette);
+ break;
+ case GL_STENCIL_BITS:
+ params[0] = ctx->DrawBuffer->Visual.stencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ params[0] = ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.Function[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]);
+ break;
+ case GL_STENCIL_REF:
+ params[0] = ctx->Stencil.Ref[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_TEST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Stencil.Enabled);
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STENCIL_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace];
+ break;
+ case GL_STEREO:
+ params[0] = BOOLEAN_TO_INT64(ctx->DrawBuffer->Visual.stereoMode);
+ break;
+ case GL_SUBPIXEL_BITS:
+ params[0] = ctx->Const.SubPixelBits;
+ break;
+ case GL_TEXTURE_1D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_1D));
+ break;
+ case GL_TEXTURE_2D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_2D));
+ break;
+ case GL_TEXTURE_3D:
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_3D));
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_1D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_2D_ARRAY_EXT));
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_3D_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_1D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY_EXT:
+ CHECK_EXT1(MESA_texture_array, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name;
+ break;
+ case GL_TEXTURE_GEN_S:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_T:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_R:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_GEN_Q:
+ params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0));
+ break;
+ case GL_TEXTURE_MATRIX:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ params[0] = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1;
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ params[0] = ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.LsbFirst);
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ params[0] = ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ params[0] = ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ params[0] = ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.SwapBytes);
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ params[0] = ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ params[0] = ctx->Unpack.ImageHeight;
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ params[0] = BOOLEAN_TO_INT64(ctx->Unpack.ClientStorage);
+ break;
+ case GL_VIEWPORT:
+ params[0] = ctx->Viewport.X;
+ params[1] = ctx->Viewport.Y;
+ params[2] = ctx->Viewport.Width;
+ params[3] = ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ params[0] = IROUND64(ctx->Pixel.ZoomX);
+ break;
+ case GL_ZOOM_Y:
+ params[0] = IROUND64(ctx->Pixel.ZoomY);
+ break;
+ case GL_VERTEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Vertex.Enabled);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_NORMAL_ARRAY:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Normal.Enabled);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_COLOR_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Color.Enabled);
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_INDEX_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->Index.Enabled);
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->EdgeFlag.Enabled);
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ params[0] = 0;
+ break;
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ CHECK_EXT1(ARB_multitexture, "GetInteger64v");
+ params[0] = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
+ break;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB));
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_CUBE_INDEX]->Name;
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB:
+ CHECK_EXT1(ARB_texture_cube_map, "GetInteger64v");
+ params[0] = (1 << (ctx->Const.MaxCubeTextureLevels - 1));
+ break;
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ params[0] = ctx->Hint.TextureCompression;
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB:
+ params[0] = _mesa_get_compressed_formats(ctx, NULL, GL_FALSE);
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS_ARB:
+ {
+ GLint formats[100];
+ GLuint i, n = _mesa_get_compressed_formats(ctx, formats, GL_FALSE);
+ ASSERT(n <= 100);
+ for (i = 0; i < n; i++)
+ params[i] = ENUM_TO_INT64(formats[i]);
+ }
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetInteger64v");
+ params[0] = ctx->Array.LockFirst;
+ break;
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT:
+ CHECK_EXT1(EXT_compiled_vertex_array, "GetInteger64v");
+ params[0] = ctx->Array.LockCount;
+ break;
+ case GL_TRANSPOSE_COLOR_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_PROJECTION_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_TEXTURE_MATRIX_ARB:
+ {
+ const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_SGI:
+ {
+ const GLfloat *matrix = ctx->ColorMatrixStack.Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = ctx->ColorMatrixStack.Depth + 1;
+ break;
+ case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI:
+ params[0] = MAX_COLOR_STACK_DEPTH;
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixScale[3]);
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[0]);
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[1]);
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[2]);
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI:
+ params[0] = IROUND64(ctx->Pixel.PostColorMatrixBias[3]);
+ break;
+ case GL_CONVOLUTION_1D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Convolution1DEnabled);
+ break;
+ case GL_CONVOLUTION_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Convolution2DEnabled);
+ break;
+ case GL_SEPARABLE_2D_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.Separable2DEnabled);
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionScale[3]);
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[0]);
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[1]);
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[2]);
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT:
+ CHECK_EXT1(EXT_convolution, "GetInteger64v");
+ params[0] = IROUND64(ctx->Pixel.PostConvolutionBias[3]);
+ break;
+ case GL_HISTOGRAM:
+ CHECK_EXT1(EXT_histogram, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.HistogramEnabled);
+ break;
+ case GL_MINMAX:
+ CHECK_EXT1(EXT_histogram, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.MinMaxEnabled);
+ break;
+ case GL_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION]);
+ break;
+ case GL_POST_CONVOLUTION_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION]);
+ break;
+ case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX]);
+ break;
+ case GL_TEXTURE_COLOR_TABLE_SGI:
+ CHECK_EXT1(SGI_texture_color_table, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled);
+ break;
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXT2(EXT_secondary_color, ARB_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Fog.ColorSumEnabled);
+ break;
+ case GL_CURRENT_SECONDARY_COLOR_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]);
+ params[1] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]);
+ params[2] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]);
+ params[3] = FLOAT_TO_INT64(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]);
+ }
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->SecondaryColor.Enabled);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->SecondaryColor.Type);
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Stride;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT:
+ CHECK_EXT1(EXT_secondary_color, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.Size;
+ break;
+ case GL_CURRENT_FOG_COORDINATE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ {
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = IROUND64(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
+ }
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->FogCoord.Enabled);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_TYPE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Array.ArrayObj->FogCoord.Type);
+ break;
+ case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->FogCoord.Stride;
+ break;
+ case GL_FOG_COORDINATE_SOURCE_EXT:
+ CHECK_EXT1(EXT_fog_coord, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Fog.FogCoordinateSource);
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS_EXT:
+ CHECK_EXT1(EXT_texture_lod_bias, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxTextureLodBias);
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ CHECK_EXT1(EXT_texture_filter_anisotropic, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxTextureMaxAnisotropy);
+ break;
+ case GL_MULTISAMPLE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.Enabled);
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleAlphaToCoverage);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleAlphaToOne);
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleCoverage);
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE_ARB:
+ params[0] = IROUND64(ctx->Multisample.SampleCoverageValue);
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ params[0] = BOOLEAN_TO_INT64(ctx->Multisample.SampleCoverageInvert);
+ break;
+ case GL_SAMPLE_BUFFERS_ARB:
+ params[0] = ctx->DrawBuffer->Visual.sampleBuffers;
+ break;
+ case GL_SAMPLES_ARB:
+ params[0] = ctx->DrawBuffer->Visual.samples;
+ break;
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXT1(IBM_rasterpos_clip, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Transform.RasterPositionUnclipped);
+ break;
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Point.PointSprite);
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ CHECK_EXT1(NV_point_sprite, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Point.SpriteRMode);
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ CHECK_EXT2(NV_point_sprite, ARB_point_sprite, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Point.SpriteOrigin);
+ break;
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ CHECK_EXT1(SGIS_generate_mipmap, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Hint.GenerateMipmap);
+ break;
+ case GL_VERTEX_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = (ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[0].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[1].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[2].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[3].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[4].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[5].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[6].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[7].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[8].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[9].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[10].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[11].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[12].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[13].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[14].Enabled);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Array.ArrayObj->VertexAttrib[15].Enabled);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[0]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[1]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[2]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[3]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[4]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[5]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[6]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[7]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[8]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[9]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[10]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[11]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[12]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[13]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[14]);
+ break;
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXT1(NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Eval.Map1Attrib[15]);
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_FRAGMENT_PROGRAM_BINDING_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0;
+ break;
+ case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV:
+ CHECK_EXT1(NV_fragment_program, "GetInteger64v");
+ params[0] = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV));
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_RECT_INDEX]->Name;
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV:
+ CHECK_EXT1(NV_texture_rectangle, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureRectSize;
+ break;
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Stencil.TestTwoSide);
+ break;
+ case GL_ACTIVE_STENCIL_FACE_EXT:
+ CHECK_EXT1(EXT_stencil_two_side, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT);
+ break;
+ case GL_MAX_SHININESS_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxShininess);
+ break;
+ case GL_MAX_SPOT_EXPONENT_NV:
+ CHECK_EXT1(NV_light_max_exponent, "GetInteger64v");
+ params[0] = IROUND64(ctx->Const.MaxSpotExponent);
+ break;
+ case GL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayBufferObj->Name;
+ break;
+ case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Vertex.BufferObj->Name;
+ break;
+ case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Normal.BufferObj->Name;
+ break;
+ case GL_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Color.BufferObj->Name;
+ break;
+ case GL_INDEX_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->Index.BufferObj->Name;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].BufferObj->Name;
+ break;
+ case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->EdgeFlag.BufferObj->Name;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->SecondaryColor.BufferObj->Name;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ArrayObj->FogCoord.BufferObj->Name;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = ctx->Array.ElementArrayBufferObj->Name;
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetInteger64v");
+ params[0] = ctx->Pack.BufferObj->Name;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_pixel_buffer_object, "GetInteger64v");
+ params[0] = ctx->Unpack.BufferObj->Name;
+ break;
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.Enabled);
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.PointSizeEnabled);
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXT2(ARB_vertex_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->VertexProgram.TwoSideEnabled);
+ break;
+ case GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxProgramMatrixStackDepth;
+ break;
+ case GL_MAX_PROGRAM_MATRICES_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxProgramMatrices;
+ break;
+ case GL_CURRENT_MATRIX_STACK_DEPTH_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_vertex_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->CurrentStack->Depth + 1);
+ break;
+ case GL_CURRENT_MATRIX_ARB:
+ CHECK_EXT3(ARB_vertex_program, ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[1]);
+ params[2] = IROUND64(matrix[2]);
+ params[3] = IROUND64(matrix[3]);
+ params[4] = IROUND64(matrix[4]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[6]);
+ params[7] = IROUND64(matrix[7]);
+ params[8] = IROUND64(matrix[8]);
+ params[9] = IROUND64(matrix[9]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[11]);
+ params[12] = IROUND64(matrix[12]);
+ params[13] = IROUND64(matrix[13]);
+ params[14] = IROUND64(matrix[14]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_TRANSPOSE_CURRENT_MATRIX_ARB:
+ CHECK_EXT2(ARB_vertex_program, ARB_fragment_program, "GetInteger64v");
+ {
+ const GLfloat *matrix = ctx->CurrentStack->Top->m;
+ params[0] = IROUND64(matrix[0]);
+ params[1] = IROUND64(matrix[4]);
+ params[2] = IROUND64(matrix[8]);
+ params[3] = IROUND64(matrix[12]);
+ params[4] = IROUND64(matrix[1]);
+ params[5] = IROUND64(matrix[5]);
+ params[6] = IROUND64(matrix[9]);
+ params[7] = IROUND64(matrix[13]);
+ params[8] = IROUND64(matrix[2]);
+ params[9] = IROUND64(matrix[6]);
+ params[10] = IROUND64(matrix[10]);
+ params[11] = IROUND64(matrix[14]);
+ params[12] = IROUND64(matrix[3]);
+ params[13] = IROUND64(matrix[7]);
+ params[14] = IROUND64(matrix[11]);
+ params[15] = IROUND64(matrix[15]);
+ }
+ break;
+ case GL_MAX_VERTEX_ATTRIBS_ARB:
+ CHECK_EXT1(ARB_vertex_program, "GetInteger64v");
+ params[0] = ctx->Const.VertexProgram.MaxAttribs;
+ break;
+ case GL_PROGRAM_ERROR_POSITION_ARB:
+ CHECK_EXT4(NV_vertex_program, ARB_vertex_program, NV_fragment_program, ARB_fragment_program, "GetInteger64v");
+ params[0] = ctx->Program.ErrorPos;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXT1(ARB_fragment_program, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->FragmentProgram.Enabled);
+ break;
+ case GL_MAX_TEXTURE_COORDS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureCoordUnits;
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT2(ARB_fragment_program, NV_fragment_program, "GetInteger64v");
+ params[0] = ctx->Const.MaxTextureImageUnits;
+ break;
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Depth.BoundsTest);
+ break;
+ case GL_DEPTH_BOUNDS_EXT:
+ CHECK_EXT1(EXT_depth_bounds_test, "GetInteger64v");
+ params[0] = IROUND64(ctx->Depth.BoundsMin);
+ params[1] = IROUND64(ctx->Depth.BoundsMax);
+ break;
+ case GL_MAX_DRAW_BUFFERS_ARB:
+ params[0] = ctx->Const.MaxDrawBuffers;
+ break;
+ case GL_DRAW_BUFFER0_ARB:
+ params[0] = ENUM_TO_INT64(ctx->DrawBuffer->ColorDrawBuffer[0]);
+ break;
+ case GL_DRAW_BUFFER1_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[1];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER2_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[2];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_DRAW_BUFFER3_ARB:
+ {
+ GLenum buffer;
+ if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)");
+ return;
+ }
+ buffer = ctx->DrawBuffer->ColorDrawBuffer[3];
+ params[0] = ENUM_TO_INT64(buffer);
+ }
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+ CHECK_EXT1(OES_read_format, "GetInteger64v");
+ params[0] = ctx->Const.ColorReadType;
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+ CHECK_EXT1(OES_read_format, "GetInteger64v");
+ params[0] = ctx->Const.ColorReadFormat;
+ break;
+ case GL_NUM_FRAGMENT_REGISTERS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 6;
+ break;
+ case GL_NUM_FRAGMENT_CONSTANTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 8;
+ break;
+ case GL_NUM_PASSES_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 2;
+ break;
+ case GL_NUM_INSTRUCTIONS_PER_PASS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 8;
+ break;
+ case GL_NUM_INSTRUCTIONS_TOTAL_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 16;
+ break;
+ case GL_COLOR_ALPHA_PAIRING_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(GL_TRUE);
+ break;
+ case GL_NUM_LOOPBACK_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 3;
+ break;
+ case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI:
+ CHECK_EXT1(ATI_fragment_shader, "GetInteger64v");
+ params[0] = 3;
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.Function[1]);
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ params[0] = ctx->Stencil.ValueMask[1];
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ params[0] = ctx->Stencil.WriteMask[1];
+ break;
+ case GL_STENCIL_BACK_REF:
+ params[0] = ctx->Stencil.Ref[1];
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.FailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZFailFunc[1]);
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ params[0] = ENUM_TO_INT64(ctx->Stencil.ZPassFunc[1]);
+ break;
+ case GL_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->DrawBuffer->Name;
+ break;
+ case GL_RENDERBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxColorAttachments;
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE_EXT:
+ CHECK_EXT1(EXT_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxRenderbufferSize;
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING_EXT:
+ CHECK_EXT1(EXT_framebuffer_blit, "GetInteger64v");
+ params[0] = ctx->ReadBuffer->Name;
+ break;
+ case GL_PROVOKING_VERTEX_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Light.ProvokingVertex);
+ break;
+ case GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT:
+ CHECK_EXT1(EXT_provoking_vertex, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Const.QuadsFollowProvokingVertexConvention);
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetInteger64v");
+ params[0] = ctx->Const.FragmentProgram.MaxUniformComponents;
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ CHECK_EXT1(ARB_fragment_shader, "GetInteger64v");
+ params[0] = ENUM_TO_INT64(ctx->Hint.FragmentShaderDerivative);
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.VertexProgram.MaxUniformComponents;
+ break;
+ case GL_MAX_VARYING_FLOATS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.MaxVarying * 4;
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = ctx->Const.MaxVertexTextureImageUnits;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
+ CHECK_EXT1(ARB_vertex_shader, "GetInteger64v");
+ params[0] = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
+ break;
+ case GL_CURRENT_PROGRAM:
+ CHECK_EXT1(ARB_shader_objects, "GetInteger64v");
+ params[0] = ctx->Shader.CurrentProgram ? ctx->Shader.CurrentProgram->Name : 0;
+ break;
+ case GL_MAX_SAMPLES:
+ CHECK_EXT1(ARB_framebuffer_object, "GetInteger64v");
+ params[0] = ctx->Const.MaxSamples;
+ break;
+ case GL_VERTEX_ARRAY_BINDING_APPLE:
+ CHECK_EXT1(APPLE_vertex_array_object, "GetInteger64v");
+ params[0] = ctx->Array.ArrayObj->Name;
+ break;
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXT1(ARB_seamless_cube_map, "GetInteger64v");
+ params[0] = BOOLEAN_TO_INT64(ctx->Texture.CubeMapSeamless);
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ CHECK_EXT1(ARB_sync, "GetInteger64v");
+ params[0] = ctx->Const.MaxServerWaitTimeout;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetInteger64v(pname=0x%x)", pname);
+ }
+}
+#endif /* FEATURE_ARB_sync */
+
+
+void GLAPIENTRY
+_mesa_GetDoublev( GLenum pname, GLdouble *params )
+{
+ const GLfloat magic = -1234.5F;
+ GLfloat values[16];
+ GLuint i;
+
+ if (!params)
+ return;
+
+ /* Init temp array to magic numbers so we can figure out how many values
+ * are returned by the GetFloatv() call.
+ */
+ for (i = 0; i < 16; i++)
+ values[i] = magic;
+
+ _mesa_GetFloatv(pname, values);
+
+ for (i = 0; i < 16 && values[i] != magic; i++)
+ params[i] = (GLdouble) values[i];
+}
+
diff --git a/mesalib/src/mesa/main/get.h b/mesalib/src/mesa/main/get.h
new file mode 100644
index 000000000..77a9a7d04
--- /dev/null
+++ b/mesalib/src/mesa/main/get.h
@@ -0,0 +1,62 @@
+/**
+ * \file get.h
+ * State query functions.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef GET_H
+#define GET_H
+
+
+#include "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_GetBooleanv( GLenum pname, GLboolean *params );
+
+extern void GLAPIENTRY
+_mesa_GetDoublev( GLenum pname, GLdouble *params );
+
+extern void GLAPIENTRY
+_mesa_GetFloatv( GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetIntegerv( GLenum pname, GLint *params );
+
+extern void GLAPIENTRY
+_mesa_GetInteger64v( GLenum pname, GLint64 *params );
+
+extern void GLAPIENTRY
+_mesa_GetPointerv( GLenum pname, GLvoid **params );
+
+extern const GLubyte * GLAPIENTRY
+_mesa_GetString( GLenum name );
+
+extern GLenum GLAPIENTRY
+_mesa_GetError( void );
+
+#endif
diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c
new file mode 100644
index 000000000..6599ed969
--- /dev/null
+++ b/mesalib/src/mesa/main/getstring.c
@@ -0,0 +1,271 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "glheader.h"
+#include "context.h"
+#include "get.h"
+#include "version.h"
+#include "enums.h"
+#include "extensions.h"
+
+
+/**
+ * Examine enabled GL extensions to determine GL version.
+ * \return version string
+ */
+static const char *
+compute_version(const GLcontext *ctx)
+{
+ static const char *version_1_2 = "1.2 Mesa " MESA_VERSION_STRING;
+ static const char *version_1_3 = "1.3 Mesa " MESA_VERSION_STRING;
+ static const char *version_1_4 = "1.4 Mesa " MESA_VERSION_STRING;
+ static const char *version_1_5 = "1.5 Mesa " MESA_VERSION_STRING;
+ static const char *version_2_0 = "2.0 Mesa " MESA_VERSION_STRING;
+ static const char *version_2_1 = "2.1 Mesa " MESA_VERSION_STRING;
+
+ const GLboolean ver_1_3 = (ctx->Extensions.ARB_multisample &&
+ ctx->Extensions.ARB_multitexture &&
+ ctx->Extensions.ARB_texture_border_clamp &&
+ ctx->Extensions.ARB_texture_compression &&
+ ctx->Extensions.ARB_texture_cube_map &&
+ ctx->Extensions.EXT_texture_env_add &&
+ ctx->Extensions.ARB_texture_env_combine &&
+ ctx->Extensions.ARB_texture_env_dot3);
+ const GLboolean ver_1_4 = (ver_1_3 &&
+ ctx->Extensions.ARB_depth_texture &&
+ ctx->Extensions.ARB_shadow &&
+ ctx->Extensions.ARB_texture_env_crossbar &&
+ ctx->Extensions.ARB_texture_mirrored_repeat &&
+ ctx->Extensions.ARB_window_pos &&
+ ctx->Extensions.EXT_blend_color &&
+ ctx->Extensions.EXT_blend_func_separate &&
+ ctx->Extensions.EXT_blend_minmax &&
+ ctx->Extensions.EXT_blend_subtract &&
+ ctx->Extensions.EXT_fog_coord &&
+ ctx->Extensions.EXT_multi_draw_arrays &&
+ ctx->Extensions.EXT_point_parameters &&
+ ctx->Extensions.EXT_secondary_color &&
+ ctx->Extensions.EXT_stencil_wrap &&
+ ctx->Extensions.EXT_texture_lod_bias &&
+ ctx->Extensions.SGIS_generate_mipmap);
+ const GLboolean ver_1_5 = (ver_1_4 &&
+ ctx->Extensions.ARB_occlusion_query &&
+ ctx->Extensions.ARB_vertex_buffer_object &&
+ ctx->Extensions.EXT_shadow_funcs);
+ const GLboolean ver_2_0 = (ver_1_5 &&
+ ctx->Extensions.ARB_draw_buffers &&
+ ctx->Extensions.ARB_point_sprite &&
+ ctx->Extensions.ARB_shader_objects &&
+ ctx->Extensions.ARB_vertex_shader &&
+ ctx->Extensions.ARB_fragment_shader &&
+ ctx->Extensions.ARB_texture_non_power_of_two &&
+ ctx->Extensions.EXT_blend_equation_separate &&
+
+ /* Technically, 2.0 requires the functionality
+ * of the EXT version. Enable 2.0 if either
+ * extension is available, and assume that a
+ * driver that only exposes the ATI extension
+ * will fallback to software when necessary.
+ */
+ (ctx->Extensions.EXT_stencil_two_side
+ || ctx->Extensions.ATI_separate_stencil));
+ const GLboolean ver_2_1 = (ver_2_0 &&
+ ctx->Extensions.ARB_shading_language_120 &&
+ ctx->Extensions.EXT_pixel_buffer_object &&
+ ctx->Extensions.EXT_texture_sRGB);
+ if (ver_2_1)
+ return version_2_1;
+ if (ver_2_0)
+ return version_2_0;
+ if (ver_1_5)
+ return version_1_5;
+ if (ver_1_4)
+ return version_1_4;
+ if (ver_1_3)
+ return version_1_3;
+ return version_1_2;
+}
+
+
+
+/**
+ * Query string-valued state. The return value should _not_ be freed by
+ * the caller.
+ *
+ * \param name the state variable to query.
+ *
+ * \sa glGetString().
+ *
+ * Tries to get the string from dd_function_table::GetString, otherwise returns
+ * the hardcoded strings.
+ */
+const GLubyte * GLAPIENTRY
+_mesa_GetString( GLenum name )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static const char *vendor = "Brian Paul";
+ static const char *renderer = "Mesa";
+
+ if (!ctx)
+ return NULL;
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+
+ /* this is a required driver function */
+ assert(ctx->Driver.GetString);
+ {
+ /* Give the driver the chance to handle this query */
+ const GLubyte *str = (*ctx->Driver.GetString)(ctx, name);
+ if (str)
+ return str;
+ }
+
+ switch (name) {
+ case GL_VENDOR:
+ return (const GLubyte *) vendor;
+ case GL_RENDERER:
+ return (const GLubyte *) renderer;
+ case GL_VERSION:
+ return (const GLubyte *) compute_version(ctx);
+ case GL_EXTENSIONS:
+ if (!ctx->Extensions.String)
+ ctx->Extensions.String = _mesa_make_extension_string(ctx);
+ return (const GLubyte *) ctx->Extensions.String;
+#if FEATURE_ARB_shading_language_100
+ case GL_SHADING_LANGUAGE_VERSION_ARB:
+ if (ctx->Extensions.ARB_shading_language_120)
+ return (const GLubyte *) "1.20";
+ else if (ctx->Extensions.ARB_shading_language_100)
+ return (const GLubyte *) "1.10";
+ goto error;
+#endif
+#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program || \
+ FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_PROGRAM_ERROR_STRING_NV:
+ if (ctx->Extensions.NV_fragment_program ||
+ ctx->Extensions.ARB_fragment_program ||
+ ctx->Extensions.NV_vertex_program ||
+ ctx->Extensions.ARB_vertex_program) {
+ return (const GLubyte *) ctx->Program.ErrorString;
+ }
+ /* FALL-THROUGH */
+#endif
+#if FEATURE_ARB_shading_language_100
+ error:
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" );
+ return (const GLubyte *) 0;
+ }
+}
+
+
+/**
+ * Return pointer-valued state, such as a vertex array pointer.
+ *
+ * \param pname names state to be queried
+ * \param params returns the pointer value
+ *
+ * \sa glGetPointerv().
+ *
+ * Tries to get the specified pointer via dd_function_table::GetPointerv,
+ * otherwise gets the specified pointer from the current context.
+ */
+void GLAPIENTRY
+_mesa_GetPointerv( GLenum pname, GLvoid **params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint clientUnit = ctx->Array.ActiveTexture;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!params)
+ return;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glGetPointerv %s\n", _mesa_lookup_enum_by_nr(pname));
+
+ if (ctx->Driver.GetPointerv
+ && (*ctx->Driver.GetPointerv)(ctx, pname, params))
+ return;
+
+ switch (pname) {
+ case GL_VERTEX_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->Vertex.Ptr;
+ break;
+ case GL_NORMAL_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->Normal.Ptr;
+ break;
+ case GL_COLOR_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->Color.Ptr;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
+ *params = (GLvoid *) ctx->Array.ArrayObj->SecondaryColor.Ptr;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
+ *params = (GLvoid *) ctx->Array.ArrayObj->FogCoord.Ptr;
+ break;
+ case GL_INDEX_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->Index.Ptr;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->TexCoord[clientUnit].Ptr;
+ break;
+ case GL_EDGE_FLAG_ARRAY_POINTER:
+ *params = (GLvoid *) ctx->Array.ArrayObj->EdgeFlag.Ptr;
+ break;
+ case GL_FEEDBACK_BUFFER_POINTER:
+ *params = ctx->Feedback.Buffer;
+ break;
+ case GL_SELECTION_BUFFER_POINTER:
+ *params = ctx->Select.Buffer;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetPointerv" );
+ return;
+ }
+}
+
+
+/**
+ * Returns the current GL error code, or GL_NO_ERROR.
+ * \return current error code
+ *
+ * Returns __GLcontextRec::ErrorValue.
+ */
+GLenum GLAPIENTRY
+_mesa_GetError( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLenum e = ctx->ErrorValue;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e));
+
+ ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ ctx->ErrorDebugCount = 0;
+ return e;
+}
diff --git a/mesalib/src/mesa/main/glheader.h b/mesalib/src/mesa/main/glheader.h
new file mode 100644
index 000000000..81d4ccf91
--- /dev/null
+++ b/mesalib/src/mesa/main/glheader.h
@@ -0,0 +1,88 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file glheader.h
+ * Wrapper for GL/gl.h and GL/glext.h
+ */
+
+
+#ifndef GLHEADER_H
+#define GLHEADER_H
+
+
+#ifdef WGLAPI
+#undef WGLAPI
+#endif
+
+
+#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP)
+# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
+# define WGLAPI __declspec(dllexport)
+# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
+# define WGLAPI __declspec(dllimport)
+# else /* for use with static link lib build of Win32 edition only */
+# define WGLAPI __declspec(dllimport)
+# endif /* _STATIC_MESA support */
+#endif /* WIN32 / CYGWIN bracket */
+
+
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "GL/internal/glcore.h"
+
+
+#ifndef GL_FIXED
+#define GL_FIXED 0x140C
+#endif
+
+
+#ifndef GL_OES_point_size_array
+#define GL_POINT_SIZE_ARRAY_OES 0x8B9C
+#define GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A
+#define GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B
+#define GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C
+#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F
+#endif
+
+
+#ifndef GL_OES_draw_texture
+#define GL_TEXTURE_CROP_RECT_OES 0x8B9D
+#endif
+
+
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#endif
+
+
+/**
+ * Special, internal token
+ */
+#define GL_SHADER_PROGRAM_MESA 0x9999
+
+
+#endif /* GLHEADER_H */
diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c
new file mode 100644
index 000000000..08c64568c
--- /dev/null
+++ b/mesalib/src/mesa/main/hash.c
@@ -0,0 +1,530 @@
+/**
+ * \file hash.c
+ * Generic hash table.
+ *
+ * Used for display lists, texture objects, vertex/fragment programs,
+ * buffer objects, etc. The hash functions are thread-safe.
+ *
+ * \note key=0 is illegal.
+ *
+ * \author Brian Paul
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "imports.h"
+#include "glapi/glthread.h"
+#include "hash.h"
+
+
+#define TABLE_SIZE 1023 /**< Size of lookup table/array */
+
+#define HASH_FUNC(K) ((K) % TABLE_SIZE)
+
+
+/**
+ * An entry in the hash table.
+ */
+struct HashEntry {
+ GLuint Key; /**< the entry's key */
+ void *Data; /**< the entry's data */
+ struct HashEntry *Next; /**< pointer to next entry */
+};
+
+
+/**
+ * The hash table data structure.
+ */
+struct _mesa_HashTable {
+ struct HashEntry *Table[TABLE_SIZE]; /**< the lookup table */
+ GLuint MaxKey; /**< highest key inserted so far */
+ _glthread_Mutex Mutex; /**< mutual exclusion lock */
+ _glthread_Mutex WalkMutex; /**< for _mesa_HashWalk() */
+ GLboolean InDeleteAll; /**< Debug check */
+};
+
+
+
+/**
+ * Create a new hash table.
+ *
+ * \return pointer to a new, empty hash table.
+ */
+struct _mesa_HashTable *
+_mesa_NewHashTable(void)
+{
+ struct _mesa_HashTable *table = CALLOC_STRUCT(_mesa_HashTable);
+ if (table) {
+ _glthread_INIT_MUTEX(table->Mutex);
+ _glthread_INIT_MUTEX(table->WalkMutex);
+ }
+ return table;
+}
+
+
+
+/**
+ * Delete a hash table.
+ * Frees each entry on the hash table and then the hash table structure itself.
+ * Note that the caller should have already traversed the table and deleted
+ * the objects in the table (i.e. We don't free the entries' data pointer).
+ *
+ * \param table the hash table to delete.
+ */
+void
+_mesa_DeleteHashTable(struct _mesa_HashTable *table)
+{
+ GLuint pos;
+ assert(table);
+ for (pos = 0; pos < TABLE_SIZE; pos++) {
+ struct HashEntry *entry = table->Table[pos];
+ while (entry) {
+ struct HashEntry *next = entry->Next;
+ if (entry->Data) {
+ _mesa_problem(NULL,
+ "In _mesa_DeleteHashTable, found non-freed data");
+ }
+ _mesa_free(entry);
+ entry = next;
+ }
+ }
+ _glthread_DESTROY_MUTEX(table->Mutex);
+ _glthread_DESTROY_MUTEX(table->WalkMutex);
+ _mesa_free(table);
+}
+
+
+
+/**
+ * Lookup an entry in the hash table.
+ *
+ * \param table the hash table.
+ * \param key the key.
+ *
+ * \return pointer to user's data or NULL if key not in table
+ */
+void *
+_mesa_HashLookup(const struct _mesa_HashTable *table, GLuint key)
+{
+ GLuint pos;
+ const struct HashEntry *entry;
+
+ assert(table);
+ assert(key);
+
+ pos = HASH_FUNC(key);
+ entry = table->Table[pos];
+ while (entry) {
+ if (entry->Key == key) {
+ return entry->Data;
+ }
+ entry = entry->Next;
+ }
+ return NULL;
+}
+
+
+
+/**
+ * Insert a key/pointer pair into the hash table.
+ * If an entry with this key already exists we'll replace the existing entry.
+ *
+ * \param table the hash table.
+ * \param key the key (not zero).
+ * \param data pointer to user data.
+ */
+void
+_mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data)
+{
+ /* search for existing entry with this key */
+ GLuint pos;
+ struct HashEntry *entry;
+
+ assert(table);
+ assert(key);
+
+ _glthread_LOCK_MUTEX(table->Mutex);
+
+ if (key > table->MaxKey)
+ table->MaxKey = key;
+
+ pos = HASH_FUNC(key);
+
+ /* check if replacing an existing entry with same key */
+ for (entry = table->Table[pos]; entry; entry = entry->Next) {
+ if (entry->Key == key) {
+ /* replace entry's data */
+#if 0 /* not sure this check is always valid */
+ if (entry->Data) {
+ _mesa_problem(NULL, "Memory leak detected in _mesa_HashInsert");
+ }
+#endif
+ entry->Data = data;
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return;
+ }
+ }
+
+ /* alloc and insert new table entry */
+ entry = MALLOC_STRUCT(HashEntry);
+ entry->Key = key;
+ entry->Data = data;
+ entry->Next = table->Table[pos];
+ table->Table[pos] = entry;
+
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+}
+
+
+
+/**
+ * Remove an entry from the hash table.
+ *
+ * \param table the hash table.
+ * \param key key of entry to remove.
+ *
+ * While holding the hash table's lock, searches the entry with the matching
+ * key and unlinks it.
+ */
+void
+_mesa_HashRemove(struct _mesa_HashTable *table, GLuint key)
+{
+ GLuint pos;
+ struct HashEntry *entry, *prev;
+
+ assert(table);
+ assert(key);
+
+ /* have to check this outside of mutex lock */
+ if (table->InDeleteAll) {
+ _mesa_problem(NULL, "_mesa_HashRemove illegally called from "
+ "_mesa_HashDeleteAll callback function");
+ return;
+ }
+
+ _glthread_LOCK_MUTEX(table->Mutex);
+
+ pos = HASH_FUNC(key);
+ 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;
+ }
+ _mesa_free(entry);
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return;
+ }
+ prev = entry;
+ entry = entry->Next;
+ }
+
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+}
+
+
+
+/**
+ * Delete all entries in a hash table, but don't delete the table itself.
+ * Invoke the given callback function for each table entry.
+ *
+ * \param table the hash table to delete
+ * \param callback the callback function
+ * \param userData arbitrary pointer to pass along to the callback
+ * (this is typically a GLcontext pointer)
+ */
+void
+_mesa_HashDeleteAll(struct _mesa_HashTable *table,
+ void (*callback)(GLuint key, void *data, void *userData),
+ void *userData)
+{
+ GLuint pos;
+ ASSERT(table);
+ ASSERT(callback);
+ _glthread_LOCK_MUTEX(table->Mutex);
+ table->InDeleteAll = GL_TRUE;
+ for (pos = 0; pos < TABLE_SIZE; pos++) {
+ struct HashEntry *entry, *next;
+ for (entry = table->Table[pos]; entry; entry = next) {
+ callback(entry->Key, entry->Data, userData);
+ next = entry->Next;
+ _mesa_free(entry);
+ }
+ table->Table[pos] = NULL;
+ }
+ table->InDeleteAll = GL_FALSE;
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+}
+
+
+/**
+ * Walk over all entries in a hash table, calling callback function for each.
+ * Note: we use a separate mutex in this function to avoid a recursive
+ * locking deadlock (in case the callback calls _mesa_HashRemove()) and to
+ * prevent multiple threads/contexts from getting tangled up.
+ * A lock-less version of this function could be used when the table will
+ * not be modified.
+ * \param table the hash table to walk
+ * \param callback the callback function
+ * \param userData arbitrary pointer to pass along to the callback
+ * (this is typically a GLcontext pointer)
+ */
+void
+_mesa_HashWalk(const struct _mesa_HashTable *table,
+ void (*callback)(GLuint key, void *data, void *userData),
+ void *userData)
+{
+ /* cast-away const */
+ struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table;
+ GLuint pos;
+ ASSERT(table);
+ ASSERT(callback);
+ _glthread_LOCK_MUTEX(table2->WalkMutex);
+ for (pos = 0; pos < TABLE_SIZE; pos++) {
+ struct HashEntry *entry, *next;
+ for (entry = table->Table[pos]; entry; entry = next) {
+ /* save 'next' pointer now in case the callback deletes the entry */
+ next = entry->Next;
+ callback(entry->Key, entry->Data, userData);
+ }
+ }
+ _glthread_UNLOCK_MUTEX(table2->WalkMutex);
+}
+
+
+/**
+ * Return the key of the "first" entry in the hash table.
+ * While holding the lock, walks through all table positions until finding
+ * the first entry of the first non-empty one.
+ *
+ * \param table the hash table
+ * \return key for the "first" entry in the hash table.
+ */
+GLuint
+_mesa_HashFirstEntry(struct _mesa_HashTable *table)
+{
+ GLuint pos;
+ assert(table);
+ _glthread_LOCK_MUTEX(table->Mutex);
+ for (pos = 0; pos < TABLE_SIZE; pos++) {
+ if (table->Table[pos]) {
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return table->Table[pos]->Key;
+ }
+ }
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return 0;
+}
+
+
+/**
+ * Given a hash table key, return the next key. This is used to walk
+ * over all entries in the table. Note that the keys returned during
+ * walking won't be in any particular order.
+ * \return next hash key or 0 if end of table.
+ */
+GLuint
+_mesa_HashNextEntry(const struct _mesa_HashTable *table, GLuint key)
+{
+ const struct HashEntry *entry;
+ GLuint pos;
+
+ assert(table);
+ assert(key);
+
+ /* Find the entry with given key */
+ pos = HASH_FUNC(key);
+ for (entry = table->Table[pos]; entry ; entry = entry->Next) {
+ if (entry->Key == key) {
+ break;
+ }
+ }
+
+ if (!entry) {
+ /* the given key was not found, so we can't find the next entry */
+ return 0;
+ }
+
+ if (entry->Next) {
+ /* return next in linked list */
+ return entry->Next->Key;
+ }
+ else {
+ /* look for next non-empty table slot */
+ pos++;
+ while (pos < TABLE_SIZE) {
+ if (table->Table[pos]) {
+ return table->Table[pos]->Key;
+ }
+ pos++;
+ }
+ return 0;
+ }
+}
+
+
+/**
+ * Dump contents of hash table for debugging.
+ *
+ * \param table the hash table.
+ */
+void
+_mesa_HashPrint(const struct _mesa_HashTable *table)
+{
+ GLuint pos;
+ assert(table);
+ for (pos = 0; pos < TABLE_SIZE; pos++) {
+ const struct HashEntry *entry = table->Table[pos];
+ while (entry) {
+ _mesa_debug(NULL, "%u %p\n", entry->Key, entry->Data);
+ entry = entry->Next;
+ }
+ }
+}
+
+
+
+/**
+ * Find a block of adjacent unused hash keys.
+ *
+ * \param table the hash table.
+ * \param numKeys number of keys needed.
+ *
+ * \return Starting key of free block or 0 if failure.
+ *
+ * If there are enough free keys between the maximum key existing in the table
+ * (_mesa_HashTable::MaxKey) and the maximum key possible, then simply return
+ * the adjacent key. Otherwise do a full search for a free key block in the
+ * allowable key range.
+ */
+GLuint
+_mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys)
+{
+ const GLuint maxKey = ~((GLuint) 0);
+ _glthread_LOCK_MUTEX(table->Mutex);
+ if (maxKey - numKeys > table->MaxKey) {
+ /* the quick solution */
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return table->MaxKey + 1;
+ }
+ else {
+ /* the slow solution */
+ GLuint freeCount = 0;
+ GLuint freeStart = 1;
+ GLuint key;
+ for (key = 1; key != maxKey; key++) {
+ if (_mesa_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) {
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return freeStart;
+ }
+ }
+ }
+ /* cannot allocate a block of numKeys consecutive keys */
+ _glthread_UNLOCK_MUTEX(table->Mutex);
+ return 0;
+ }
+}
+
+
+#if 0 /* debug only */
+
+/**
+ * Test walking over all the entries in a hash table.
+ */
+static void
+test_hash_walking(void)
+{
+ struct _mesa_HashTable *t = _mesa_NewHashTable();
+ const GLuint limit = 50000;
+ GLuint i;
+
+ /* create some entries */
+ for (i = 0; i < limit; i++) {
+ GLuint dummy;
+ GLuint k = (rand() % (limit * 10)) + 1;
+ while (_mesa_HashLookup(t, k)) {
+ /* id already in use, try another */
+ k = (rand() % (limit * 10)) + 1;
+ }
+ _mesa_HashInsert(t, k, &dummy);
+ }
+
+ /* walk over all entries */
+ {
+ GLuint k = _mesa_HashFirstEntry(t);
+ GLuint count = 0;
+ while (k) {
+ GLuint knext = _mesa_HashNextEntry(t, k);
+ assert(knext != k);
+ _mesa_HashRemove(t, k);
+ count++;
+ k = knext;
+ }
+ assert(count == limit);
+ k = _mesa_HashFirstEntry(t);
+ assert(k==0);
+ }
+
+ _mesa_DeleteHashTable(t);
+}
+
+
+void
+_mesa_test_hash_functions(void)
+{
+ int a, b, c;
+ struct _mesa_HashTable *t;
+
+ t = _mesa_NewHashTable();
+ _mesa_HashInsert(t, 501, &a);
+ _mesa_HashInsert(t, 10, &c);
+ _mesa_HashInsert(t, 0xfffffff8, &b);
+ /*_mesa_HashPrint(t);*/
+
+ assert(_mesa_HashLookup(t,501));
+ assert(!_mesa_HashLookup(t,1313));
+ assert(_mesa_HashFindFreeKeyBlock(t, 100));
+
+ _mesa_DeleteHashTable(t);
+
+ test_hash_walking();
+}
+
+#endif
diff --git a/mesalib/src/mesa/main/hash.h b/mesalib/src/mesa/main/hash.h
new file mode 100644
index 000000000..d18db76ab
--- /dev/null
+++ b/mesalib/src/mesa/main/hash.h
@@ -0,0 +1,69 @@
+/**
+ * \file hash.h
+ * Generic hash table.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+
+
+extern struct _mesa_HashTable *_mesa_NewHashTable(void);
+
+extern void _mesa_DeleteHashTable(struct _mesa_HashTable *table);
+
+extern void *_mesa_HashLookup(const struct _mesa_HashTable *table, GLuint key);
+
+extern void _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data);
+
+extern void _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key);
+
+extern void
+_mesa_HashDeleteAll(struct _mesa_HashTable *table,
+ void (*callback)(GLuint key, void *data, void *userData),
+ void *userData);
+
+extern void
+_mesa_HashWalk(const struct _mesa_HashTable *table,
+ void (*callback)(GLuint key, void *data, void *userData),
+ void *userData);
+
+extern GLuint _mesa_HashFirstEntry(struct _mesa_HashTable *table);
+
+extern GLuint _mesa_HashNextEntry(const struct _mesa_HashTable *table, GLuint key);
+
+extern void _mesa_HashPrint(const struct _mesa_HashTable *table);
+
+extern GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys);
+
+extern void _mesa_test_hash_functions(void);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/hint.c b/mesalib/src/mesa/main/hint.c
new file mode 100644
index 000000000..e2d4129a3
--- /dev/null
+++ b/mesalib/src/mesa/main/hint.c
@@ -0,0 +1,149 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "enums.h"
+#include "context.h"
+#include "hint.h"
+#include "imports.h"
+
+
+
+void GLAPIENTRY
+_mesa_Hint( GLenum target, GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glHint %s %d\n",
+ _mesa_lookup_enum_by_nr(target), mode);
+
+ if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)");
+ return;
+ }
+
+ switch (target) {
+ case GL_FOG_HINT:
+ if (ctx->Hint.Fog == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.Fog = mode;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ if (ctx->Hint.LineSmooth == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.LineSmooth = mode;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ if (ctx->Hint.PerspectiveCorrection == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.PerspectiveCorrection = mode;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ if (ctx->Hint.PointSmooth == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.PointSmooth = mode;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ if (ctx->Hint.PolygonSmooth == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.PolygonSmooth = mode;
+ break;
+
+ /* GL_EXT_clip_volume_hint */
+ case GL_CLIP_VOLUME_CLIPPING_HINT_EXT:
+ if (ctx->Hint.ClipVolumeClipping == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.ClipVolumeClipping = mode;
+ break;
+
+ /* GL_ARB_texture_compression */
+ case GL_TEXTURE_COMPRESSION_HINT_ARB:
+ if (ctx->Hint.TextureCompression == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.TextureCompression = mode;
+ break;
+
+ /* GL_SGIS_generate_mipmap */
+ case GL_GENERATE_MIPMAP_HINT_SGIS:
+ if (!ctx->Extensions.SGIS_generate_mipmap) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+ return;
+ }
+ if (ctx->Hint.GenerateMipmap == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.GenerateMipmap = mode;
+ break;
+
+ /* GL_ARB_fragment_shader */
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ if (!ctx->Extensions.ARB_fragment_shader) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+ return;
+ }
+ if (ctx->Hint.FragmentShaderDerivative == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.FragmentShaderDerivative = mode;
+ break;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+ return;
+ }
+
+ if (ctx->Driver.Hint) {
+ (*ctx->Driver.Hint)( ctx, target, mode );
+ }
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+void _mesa_init_hint( GLcontext * ctx )
+{
+ /* 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.ClipVolumeClipping = GL_DONT_CARE;
+ ctx->Hint.TextureCompression = GL_DONT_CARE;
+ ctx->Hint.GenerateMipmap = GL_DONT_CARE;
+ ctx->Hint.FragmentShaderDerivative = GL_DONT_CARE;
+}
diff --git a/mesalib/src/mesa/main/hint.h b/mesalib/src/mesa/main/hint.h
new file mode 100644
index 000000000..bfc388710
--- /dev/null
+++ b/mesalib/src/mesa/main/hint.h
@@ -0,0 +1,57 @@
+/**
+ * \file hint.h
+ * Hints operations.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef HINT_H
+#define HINT_H
+
+
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_Hint( GLenum target, GLenum mode );
+
+extern void
+_mesa_init_hint( GLcontext * ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_hint( c ) ((void) 0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/histogram.c b/mesalib/src/mesa/main/histogram.c
new file mode 100644
index 000000000..ceb0d5a6a
--- /dev/null
+++ b/mesalib/src/mesa/main/histogram.c
@@ -0,0 +1,1078 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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 "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "context.h"
+#include "image.h"
+#include "histogram.h"
+
+
+
+/*
+ * XXX the packed pixel formats haven't been tested.
+ */
+static void
+pack_histogram( GLcontext *ctx,
+ GLuint n, CONST GLuint rgba[][4],
+ GLenum format, GLenum type, GLvoid *destination,
+ const struct gl_pixelstore_attrib *packing )
+{
+ const GLint comps = _mesa_components_in_format(format);
+ GLuint luminance[MAX_WIDTH];
+
+ if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
+ }
+ }
+
+#define PACK_MACRO(TYPE) \
+ { \
+ GLuint i; \
+ switch (format) { \
+ case GL_RED: \
+ for (i=0;i<n;i++) \
+ dst[i] = (TYPE) rgba[i][RCOMP]; \
+ break; \
+ case GL_GREEN: \
+ for (i=0;i<n;i++) \
+ dst[i] = (TYPE) rgba[i][GCOMP]; \
+ break; \
+ case GL_BLUE: \
+ for (i=0;i<n;i++) \
+ dst[i] = (TYPE) rgba[i][BCOMP]; \
+ break; \
+ case GL_ALPHA: \
+ for (i=0;i<n;i++) \
+ dst[i] = (TYPE) rgba[i][ACOMP]; \
+ break; \
+ case GL_LUMINANCE: \
+ for (i=0;i<n;i++) \
+ dst[i] = (TYPE) luminance[i]; \
+ break; \
+ case GL_LUMINANCE_ALPHA: \
+ for (i=0;i<n;i++) { \
+ dst[i*2+0] = (TYPE) luminance[i]; \
+ dst[i*2+1] = (TYPE) rgba[i][ACOMP]; \
+ } \
+ break; \
+ case GL_RGB: \
+ for (i=0;i<n;i++) { \
+ dst[i*3+0] = (TYPE) rgba[i][RCOMP]; \
+ dst[i*3+1] = (TYPE) rgba[i][GCOMP]; \
+ dst[i*3+2] = (TYPE) rgba[i][BCOMP]; \
+ } \
+ break; \
+ case GL_RGBA: \
+ for (i=0;i<n;i++) { \
+ dst[i*4+0] = (TYPE) rgba[i][RCOMP]; \
+ dst[i*4+1] = (TYPE) rgba[i][GCOMP]; \
+ dst[i*4+2] = (TYPE) rgba[i][BCOMP]; \
+ dst[i*4+3] = (TYPE) rgba[i][ACOMP]; \
+ } \
+ break; \
+ case GL_BGR: \
+ for (i=0;i<n;i++) { \
+ dst[i*3+0] = (TYPE) rgba[i][BCOMP]; \
+ dst[i*3+1] = (TYPE) rgba[i][GCOMP]; \
+ dst[i*3+2] = (TYPE) rgba[i][RCOMP]; \
+ } \
+ break; \
+ case GL_BGRA: \
+ for (i=0;i<n;i++) { \
+ dst[i*4+0] = (TYPE) rgba[i][BCOMP]; \
+ dst[i*4+1] = (TYPE) rgba[i][GCOMP]; \
+ dst[i*4+2] = (TYPE) rgba[i][RCOMP]; \
+ dst[i*4+3] = (TYPE) rgba[i][ACOMP]; \
+ } \
+ break; \
+ case GL_ABGR_EXT: \
+ for (i=0;i<n;i++) { \
+ dst[i*4+0] = (TYPE) rgba[i][ACOMP]; \
+ dst[i*4+1] = (TYPE) rgba[i][BCOMP]; \
+ dst[i*4+2] = (TYPE) rgba[i][GCOMP]; \
+ dst[i*4+3] = (TYPE) rgba[i][RCOMP]; \
+ } \
+ break; \
+ default: \
+ _mesa_problem(ctx, "bad format in pack_histogram"); \
+ } \
+ }
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) destination;
+ PACK_MACRO(GLubyte);
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) destination;
+ PACK_MACRO(GLbyte);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) destination;
+ PACK_MACRO(GLushort);
+ if (packing->SwapBytes) {
+ _mesa_swap2(dst, n * comps);
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) destination;
+ PACK_MACRO(GLshort);
+ if (packing->SwapBytes) {
+ _mesa_swap2((GLushort *) dst, n * comps);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) destination;
+ PACK_MACRO(GLuint);
+ if (packing->SwapBytes) {
+ _mesa_swap4(dst, n * comps);
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) destination;
+ PACK_MACRO(GLint);
+ if (packing->SwapBytes) {
+ _mesa_swap4((GLuint *) dst, n * comps);
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) destination;
+ PACK_MACRO(GLfloat);
+ if (packing->SwapBytes) {
+ _mesa_swap4((GLuint *) dst, n * comps);
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ /* temporarily store as GLuints */
+ GLuint temp[4*HISTOGRAM_TABLE_SIZE];
+ GLhalfARB *dst = (GLhalfARB *) destination;
+ GLuint i;
+ /* get GLuint values */
+ PACK_MACRO(GLuint);
+ /* convert to GLhalf */
+ for (i = 0; i < n * comps; i++) {
+ dst[i] = _mesa_float_to_half((GLfloat) temp[i]);
+ }
+ if (packing->SwapBytes) {
+ _mesa_swap2((GLushort *) dst, n * comps);
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ if (format == GL_RGB) {
+ GLubyte *dst = (GLubyte *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x7) << 5)
+ | ((rgba[i][GCOMP] & 0x7) << 2)
+ | ((rgba[i][BCOMP] & 0x3) );
+ }
+ }
+ else {
+ GLubyte *dst = (GLubyte *) destination;
+ GLuint i;
+ ASSERT(format == GL_BGR);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x7) << 5)
+ | ((rgba[i][GCOMP] & 0x7) << 2)
+ | ((rgba[i][RCOMP] & 0x3) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ if (format == GL_RGB) {
+ GLubyte *dst = (GLubyte *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x3) << 6)
+ | ((rgba[i][GCOMP] & 0x7) << 3)
+ | ((rgba[i][BCOMP] & 0x7) );
+ }
+ }
+ else {
+ GLubyte *dst = (GLubyte *) destination;
+ GLuint i;
+ ASSERT(format == GL_BGR);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x3) << 6)
+ | ((rgba[i][GCOMP] & 0x7) << 3)
+ | ((rgba[i][RCOMP] & 0x7) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x3f) << 5)
+ | ((rgba[i][BCOMP] & 0x1f) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_BGR);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x3f) << 5)
+ | ((rgba[i][RCOMP] & 0x1f) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x3f) << 5)
+ | ((rgba[i][RCOMP] & 0x1f) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_BGR);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x3f) << 5)
+ | ((rgba[i][BCOMP] & 0x1f) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ if (format == GL_RGBA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
+ | ((rgba[i][GCOMP] & 0xf) << 8)
+ | ((rgba[i][BCOMP] & 0xf) << 4)
+ | ((rgba[i][ACOMP] & 0xf) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0xf) << 12)
+ | ((rgba[i][GCOMP] & 0xf) << 8)
+ | ((rgba[i][RCOMP] & 0xf) << 4)
+ | ((rgba[i][ACOMP] & 0xf) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
+ | ((rgba[i][BCOMP] & 0xf) << 8)
+ | ((rgba[i][GCOMP] & 0xf) << 4)
+ | ((rgba[i][RCOMP] & 0xf) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ if (format == GL_RGBA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
+ | ((rgba[i][BCOMP] & 0xf) << 8)
+ | ((rgba[i][GCOMP] & 0xf) << 4)
+ | ((rgba[i][RCOMP] & 0xf) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xf) << 12)
+ | ((rgba[i][RCOMP] & 0xf) << 8)
+ | ((rgba[i][GCOMP] & 0xf) << 4)
+ | ((rgba[i][BCOMP] & 0xf) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0xf) << 12)
+ | ((rgba[i][GCOMP] & 0xf) << 8)
+ | ((rgba[i][BCOMP] & 0xf) << 4)
+ | ((rgba[i][ACOMP] & 0xf) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ if (format == GL_RGBA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x1f) << 6)
+ | ((rgba[i][BCOMP] & 0x1f) << 1)
+ | ((rgba[i][ACOMP] & 0x1) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x1f) << 6)
+ | ((rgba[i][RCOMP] & 0x1f) << 1)
+ | ((rgba[i][ACOMP] & 0x1) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
+ | ((rgba[i][BCOMP] & 0x1f) << 6)
+ | ((rgba[i][GCOMP] & 0x1f) << 1)
+ | ((rgba[i][RCOMP] & 0x1) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (format == GL_RGBA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
+ | ((rgba[i][BCOMP] & 0x1f) << 6)
+ | ((rgba[i][GCOMP] & 0x1f) << 1)
+ | ((rgba[i][RCOMP] & 0x1) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11)
+ | ((rgba[i][RCOMP] & 0x1f) << 6)
+ | ((rgba[i][GCOMP] & 0x1f) << 1)
+ | ((rgba[i][BCOMP] & 0x1) );
+ }
+ }
+ else {
+ GLushort *dst = (GLushort *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11)
+ | ((rgba[i][GCOMP] & 0x1f) << 6)
+ | ((rgba[i][BCOMP] & 0x1f) << 1)
+ | ((rgba[i][ACOMP] & 0x1) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
+ | ((rgba[i][GCOMP] & 0xff) << 16)
+ | ((rgba[i][BCOMP] & 0xff) << 8)
+ | ((rgba[i][ACOMP] & 0xff) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0xff) << 24)
+ | ((rgba[i][GCOMP] & 0xff) << 16)
+ | ((rgba[i][RCOMP] & 0xff) << 8)
+ | ((rgba[i][ACOMP] & 0xff) );
+ }
+ }
+ else {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
+ | ((rgba[i][BCOMP] & 0xff) << 16)
+ | ((rgba[i][GCOMP] & 0xff) << 8)
+ | ((rgba[i][RCOMP] & 0xff) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
+ | ((rgba[i][BCOMP] & 0xff) << 16)
+ | ((rgba[i][GCOMP] & 0xff) << 8)
+ | ((rgba[i][RCOMP] & 0xff) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0xff) << 24)
+ | ((rgba[i][RCOMP] & 0xff) << 16)
+ | ((rgba[i][GCOMP] & 0xff) << 8)
+ | ((rgba[i][BCOMP] & 0xff) );
+ }
+ }
+ else {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0xff) << 24)
+ | ((rgba[i][GCOMP] & 0xff) << 16)
+ | ((rgba[i][BCOMP] & 0xff) << 8)
+ | ((rgba[i][ACOMP] & 0xff) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
+ | ((rgba[i][GCOMP] & 0x3ff) << 12)
+ | ((rgba[i][BCOMP] & 0x3ff) << 2)
+ | ((rgba[i][ACOMP] & 0x3) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][BCOMP] & 0x3ff) << 22)
+ | ((rgba[i][GCOMP] & 0x3ff) << 12)
+ | ((rgba[i][RCOMP] & 0x3ff) << 2)
+ | ((rgba[i][ACOMP] & 0x3) );
+ }
+ }
+ else {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
+ | ((rgba[i][BCOMP] & 0x3ff) << 12)
+ | ((rgba[i][GCOMP] & 0x3ff) << 2)
+ | ((rgba[i][RCOMP] & 0x3) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
+ | ((rgba[i][BCOMP] & 0x3ff) << 12)
+ | ((rgba[i][GCOMP] & 0x3ff) << 2)
+ | ((rgba[i][RCOMP] & 0x3) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22)
+ | ((rgba[i][RCOMP] & 0x3ff) << 12)
+ | ((rgba[i][GCOMP] & 0x3ff) << 2)
+ | ((rgba[i][BCOMP] & 0x3) );
+ }
+ }
+ else {
+ GLuint *dst = (GLuint *) destination;
+ GLuint i;
+ ASSERT(format == GL_ABGR_EXT);
+ for (i = 0; i < n; i++) {
+ dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22)
+ | ((rgba[i][GCOMP] & 0x3ff) << 12)
+ | ((rgba[i][BCOMP] & 0x3ff) << 2)
+ | ((rgba[i][ACOMP] & 0x3) );
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad type in pack_histogram");
+ }
+
+#undef PACK_MACRO
+}
+
+
+/*
+ * Given an internalFormat token passed to glHistogram or glMinMax,
+ * return the corresponding base format.
+ * Return -1 if invalid token.
+ */
+static GLint
+base_histogram_format( GLenum format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ 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_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 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 */
+ }
+}
+
+
+
+/**********************************************************************
+ * API functions
+ */
+
+
+void GLAPIENTRY
+_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax");
+ return;
+ }
+
+ if (target != GL_MINMAX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmax(target)");
+ return;
+ }
+
+ if (format != GL_RED &&
+ format != GL_GREEN &&
+ format != GL_BLUE &&
+ format != GL_ALPHA &&
+ format != GL_RGB &&
+ format != GL_BGR &&
+ format != GL_RGBA &&
+ format != GL_BGRA &&
+ format != GL_ABGR_EXT &&
+ format != GL_LUMINANCE &&
+ format != GL_LUMINANCE_ALPHA) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMax(format)");
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)");
+ return;
+ }
+
+
+ values = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack, 2, 1, 1,
+ format, type, values, "glGetMinmax");
+ if (!values)
+ return;
+
+ {
+ GLfloat minmax[2][4];
+ minmax[0][RCOMP] = CLAMP(ctx->MinMax.Min[RCOMP], 0.0F, 1.0F);
+ minmax[0][GCOMP] = CLAMP(ctx->MinMax.Min[GCOMP], 0.0F, 1.0F);
+ minmax[0][BCOMP] = CLAMP(ctx->MinMax.Min[BCOMP], 0.0F, 1.0F);
+ minmax[0][ACOMP] = CLAMP(ctx->MinMax.Min[ACOMP], 0.0F, 1.0F);
+ minmax[1][RCOMP] = CLAMP(ctx->MinMax.Max[RCOMP], 0.0F, 1.0F);
+ minmax[1][GCOMP] = CLAMP(ctx->MinMax.Max[GCOMP], 0.0F, 1.0F);
+ minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F);
+ minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F);
+ _mesa_pack_rgba_span_float(ctx, 2, minmax,
+ format, type, values, &ctx->Pack, 0x0);
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+
+ if (reset) {
+ _mesa_ResetMinmax(GL_MINMAX);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram");
+ return;
+ }
+
+ if (target != GL_HISTOGRAM) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(target)");
+ return;
+ }
+
+ if (format != GL_RED &&
+ format != GL_GREEN &&
+ format != GL_BLUE &&
+ format != GL_ALPHA &&
+ format != GL_RGB &&
+ format != GL_BGR &&
+ format != GL_RGBA &&
+ format != GL_BGRA &&
+ format != GL_ABGR_EXT &&
+ format != GL_LUMINANCE &&
+ format != GL_LUMINANCE_ALPHA) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(format)");
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram(format or type)");
+ return;
+ }
+
+ values = _mesa_map_validate_pbo_dest(ctx, 1, &ctx->Pack,
+ ctx->Histogram.Width, 1, 1,
+ format, type, values,
+ "glGetHistogram");
+ if (!values)
+ return;
+
+ pack_histogram(ctx, ctx->Histogram.Width,
+ (CONST GLuint (*)[4]) ctx->Histogram.Count,
+ format, type, values, &ctx->Pack);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+
+ if (reset) {
+ GLuint i;
+ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
+ ctx->Histogram.Count[i][0] = 0;
+ ctx->Histogram.Count[i][1] = 0;
+ ctx->Histogram.Count[i][2] = 0;
+ ctx->Histogram.Count[i][3] = 0;
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameterfv");
+ return;
+ }
+
+ if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_HISTOGRAM_WIDTH:
+ *params = (GLfloat) ctx->Histogram.Width;
+ break;
+ case GL_HISTOGRAM_FORMAT:
+ *params = (GLfloat) ctx->Histogram.Format;
+ break;
+ case GL_HISTOGRAM_RED_SIZE:
+ *params = (GLfloat) ctx->Histogram.RedSize;
+ break;
+ case GL_HISTOGRAM_GREEN_SIZE:
+ *params = (GLfloat) ctx->Histogram.GreenSize;
+ break;
+ case GL_HISTOGRAM_BLUE_SIZE:
+ *params = (GLfloat) ctx->Histogram.BlueSize;
+ break;
+ case GL_HISTOGRAM_ALPHA_SIZE:
+ *params = (GLfloat) ctx->Histogram.AlphaSize;
+ break;
+ case GL_HISTOGRAM_LUMINANCE_SIZE:
+ *params = (GLfloat) ctx->Histogram.LuminanceSize;
+ break;
+ case GL_HISTOGRAM_SINK:
+ *params = (GLfloat) ctx->Histogram.Sink;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(pname)");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameteriv");
+ return;
+ }
+
+ if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_HISTOGRAM_WIDTH:
+ *params = (GLint) ctx->Histogram.Width;
+ break;
+ case GL_HISTOGRAM_FORMAT:
+ *params = (GLint) ctx->Histogram.Format;
+ break;
+ case GL_HISTOGRAM_RED_SIZE:
+ *params = (GLint) ctx->Histogram.RedSize;
+ break;
+ case GL_HISTOGRAM_GREEN_SIZE:
+ *params = (GLint) ctx->Histogram.GreenSize;
+ break;
+ case GL_HISTOGRAM_BLUE_SIZE:
+ *params = (GLint) ctx->Histogram.BlueSize;
+ break;
+ case GL_HISTOGRAM_ALPHA_SIZE:
+ *params = (GLint) ctx->Histogram.AlphaSize;
+ break;
+ case GL_HISTOGRAM_LUMINANCE_SIZE:
+ *params = (GLint) ctx->Histogram.LuminanceSize;
+ break;
+ case GL_HISTOGRAM_SINK:
+ *params = (GLint) ctx->Histogram.Sink;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(pname)");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameterfv");
+ return;
+ }
+ if (target != GL_MINMAX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameterfv(target)");
+ return;
+ }
+ if (pname == GL_MINMAX_FORMAT) {
+ *params = (GLfloat) ctx->MinMax.Format;
+ }
+ else if (pname == GL_MINMAX_SINK) {
+ *params = (GLfloat) ctx->MinMax.Sink;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameterfv(pname)");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameteriv");
+ return;
+ }
+ if (target != GL_MINMAX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameteriv(target)");
+ return;
+ }
+ if (pname == GL_MINMAX_FORMAT) {
+ *params = (GLint) ctx->MinMax.Format;
+ }
+ else if (pname == GL_MINMAX_SINK) {
+ *params = (GLint) ctx->MinMax.Sink;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameteriv(pname)");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink)
+{
+ GLuint i;
+ GLboolean error = GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glHistogram");
+ return;
+ }
+
+ if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(target)");
+ return;
+ }
+
+ if (width < 0 || width > HISTOGRAM_TABLE_SIZE) {
+ if (target == GL_PROXY_HISTOGRAM) {
+ error = GL_TRUE;
+ }
+ else {
+ if (width < 0)
+ _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)");
+ else
+ _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glHistogram(width)");
+ return;
+ }
+ }
+
+ if (width != 0 && !_mesa_is_pow_two(width)) {
+ if (target == GL_PROXY_HISTOGRAM) {
+ error = GL_TRUE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)");
+ return;
+ }
+ }
+
+ if (base_histogram_format(internalFormat) < 0) {
+ if (target == GL_PROXY_HISTOGRAM) {
+ error = GL_TRUE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(internalFormat)");
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ /* reset histograms */
+ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
+ ctx->Histogram.Count[i][0] = 0;
+ ctx->Histogram.Count[i][1] = 0;
+ ctx->Histogram.Count[i][2] = 0;
+ ctx->Histogram.Count[i][3] = 0;
+ }
+
+ if (error) {
+ ctx->Histogram.Width = 0;
+ ctx->Histogram.Format = 0;
+ ctx->Histogram.RedSize = 0;
+ ctx->Histogram.GreenSize = 0;
+ ctx->Histogram.BlueSize = 0;
+ ctx->Histogram.AlphaSize = 0;
+ ctx->Histogram.LuminanceSize = 0;
+ }
+ else {
+ ctx->Histogram.Width = width;
+ ctx->Histogram.Format = internalFormat;
+ ctx->Histogram.Sink = sink;
+ ctx->Histogram.RedSize = 8 * sizeof(GLuint);
+ ctx->Histogram.GreenSize = 8 * sizeof(GLuint);
+ ctx->Histogram.BlueSize = 8 * sizeof(GLuint);
+ ctx->Histogram.AlphaSize = 8 * sizeof(GLuint);
+ ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_Minmax(GLenum target, GLenum internalFormat, GLboolean sink)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMinmax");
+ return;
+ }
+
+ if (target != GL_MINMAX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(target)");
+ return;
+ }
+
+ if (base_histogram_format(internalFormat) < 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(internalFormat)");
+ return;
+ }
+
+ if (ctx->MinMax.Sink == sink)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->MinMax.Sink = sink;
+}
+
+
+void GLAPIENTRY
+_mesa_ResetHistogram(GLenum target)
+{
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glResetHistogram");
+ return;
+ }
+
+ if (target != GL_HISTOGRAM) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glResetHistogram(target)");
+ return;
+ }
+
+ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
+ ctx->Histogram.Count[i][0] = 0;
+ ctx->Histogram.Count[i][1] = 0;
+ ctx->Histogram.Count[i][2] = 0;
+ ctx->Histogram.Count[i][3] = 0;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_ResetMinmax(GLenum target)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glResetMinmax");
+ return;
+ }
+
+ if (target != GL_MINMAX) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glResetMinMax(target)");
+ return;
+ }
+
+ ctx->MinMax.Min[RCOMP] = 1000; ctx->MinMax.Max[RCOMP] = -1000;
+ ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000;
+ ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000;
+ ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
+}
+
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+void _mesa_init_histogram( GLcontext * ctx )
+{
+ int i;
+
+ /* Histogram group */
+ ctx->Histogram.Width = 0;
+ ctx->Histogram.Format = GL_RGBA;
+ ctx->Histogram.Sink = GL_FALSE;
+ ctx->Histogram.RedSize = 0;
+ ctx->Histogram.GreenSize = 0;
+ ctx->Histogram.BlueSize = 0;
+ ctx->Histogram.AlphaSize = 0;
+ ctx->Histogram.LuminanceSize = 0;
+ for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
+ ctx->Histogram.Count[i][0] = 0;
+ ctx->Histogram.Count[i][1] = 0;
+ ctx->Histogram.Count[i][2] = 0;
+ ctx->Histogram.Count[i][3] = 0;
+ }
+
+ /* Min/Max group */
+ ctx->MinMax.Format = GL_RGBA;
+ ctx->MinMax.Sink = GL_FALSE;
+ ctx->MinMax.Min[RCOMP] = 1000; ctx->MinMax.Max[RCOMP] = -1000;
+ ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000;
+ ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000;
+ ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
+}
diff --git a/mesalib/src/mesa/main/histogram.h b/mesalib/src/mesa/main/histogram.h
new file mode 100644
index 000000000..367e9b11b
--- /dev/null
+++ b/mesalib/src/mesa/main/histogram.h
@@ -0,0 +1,83 @@
+/**
+ * \file histogram.h
+ * Histogram.
+ *
+ * \if subset
+ * (No-op)
+ *
+ * \endif
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef HISTOGRAM_H
+#define HISTOGRAM_H
+
+#include "glheader.h"
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values);
+
+extern void GLAPIENTRY
+_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values);
+
+extern void GLAPIENTRY
+_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_Histogram(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+
+extern void GLAPIENTRY
+_mesa_Minmax(GLenum target, GLenum internalformat, GLboolean sink);
+
+extern void GLAPIENTRY
+_mesa_ResetHistogram(GLenum target);
+
+extern void GLAPIENTRY
+_mesa_ResetMinmax(GLenum target);
+
+extern void _mesa_init_histogram( GLcontext * ctx );
+
+#else
+
+/** No-op */
+#define _mesa_init_histogram( c ) ((void) 0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c
new file mode 100644
index 000000000..baecbab0a
--- /dev/null
+++ b/mesalib/src/mesa/main/image.c
@@ -0,0 +1,5820 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file image.c
+ * Image handling.
+ */
+
+
+#include "glheader.h"
+#include "colormac.h"
+#include "context.h"
+#include "image.h"
+#include "imports.h"
+#include "macros.h"
+#include "pixel.h"
+
+
+/**
+ * NOTE:
+ * Normally, BYTE_TO_FLOAT(0) returns 0.00392 That causes problems when
+ * we later convert the float to a packed integer value (such as for
+ * GL_RGB5_A1) because we'll wind up with a non-zero value.
+ *
+ * We redefine the macros here so zero is handled correctly.
+ */
+#undef BYTE_TO_FLOAT
+#define BYTE_TO_FLOAT(B) ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F)))
+
+#undef SHORT_TO_FLOAT
+#define SHORT_TO_FLOAT(S) ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)))
+
+
+
+/** Compute ceiling of integer quotient of A divided by B. */
+#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+
+
+/**
+ * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise.
+ */
+GLboolean
+_mesa_type_is_packed(GLenum type)
+{
+ switch (type) {
+ 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:
+ 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:
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ case GL_UNSIGNED_INT_24_8_EXT:
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+/**
+ * Flip the 8 bits in each byte of the given array.
+ *
+ * \param p array.
+ * \param n number of bytes.
+ *
+ * \todo try this trick to flip bytes someday:
+ * \code
+ * v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555);
+ * v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333);
+ * v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f);
+ * \endcode
+ */
+static void
+flip_bytes( GLubyte *p, GLuint n )
+{
+ GLuint i, a, b;
+ for (i = 0; i < n; i++) {
+ b = (GLuint) p[i]; /* words are often faster than bytes */
+ 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.
+ *
+ * \param p array.
+ * \param n number of words.
+ */
+void
+_mesa_swap2( GLushort *p, GLuint n )
+{
+ 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
+_mesa_swap4( GLuint *p, GLuint n )
+{
+ 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;
+ }
+}
+
+
+/**
+ * Get the size of a GL data type.
+ *
+ * \param type GL data type.
+ *
+ * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1
+ * if an invalid type enum.
+ */
+GLint
+_mesa_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);
+ case GL_DOUBLE:
+ return sizeof(GLdouble);
+ case GL_HALF_FLOAT_ARB:
+ return sizeof(GLhalfARB);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Same as _mesa_sizeof_type() but also accepting the packed pixel
+ * format data types.
+ */
+GLint
+_mesa_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_HALF_FLOAT_ARB:
+ return sizeof(GLhalfARB);
+ 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(GLushort);
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return sizeof(GLushort);
+ 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);
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_INT_24_8_EXT:
+ return sizeof(GLuint);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Get the number of components in a pixel format.
+ *
+ * \param format pixel format.
+ *
+ * \return the number of components in the given format, or -1 if a bad format.
+ */
+GLint
+_mesa_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:
+ case GL_INTENSITY:
+ 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;
+ case GL_YCBCR_MESA:
+ return 2;
+ case GL_DEPTH_STENCIL_EXT:
+ return 2;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return 2;
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Get the bytes per pixel of pixel format type pair.
+ *
+ * \param format pixel format.
+ * \param type pixel type.
+ *
+ * \return bytes per pixel, or -1 if a bad format or type was given.
+ */
+GLint
+_mesa_bytes_per_pixel( GLenum format, GLenum type )
+{
+ GLint comps = _mesa_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_HALF_FLOAT_ARB:
+ return comps * sizeof(GLhalfARB);
+ 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(GLushort);
+ 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;
+ case GL_UNSIGNED_SHORT_8_8_MESA:
+ case GL_UNSIGNED_SHORT_8_8_REV_MESA:
+ if (format == GL_YCBCR_MESA)
+ return sizeof(GLushort);
+ else
+ return -1;
+ case GL_UNSIGNED_INT_24_8_EXT:
+ if (format == GL_DEPTH_STENCIL_EXT)
+ return sizeof(GLuint);
+ else
+ return -1;
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Test for a legal pixel format and type.
+ *
+ * \param format pixel format.
+ * \param type pixel type.
+ *
+ * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE
+ * otherwise.
+ */
+GLboolean
+_mesa_is_legal_format_and_type( GLcontext *ctx, 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;
+ case GL_HALF_FLOAT_ARB:
+ return ctx->Extensions.ARB_half_float_pixel;
+ default:
+ return GL_FALSE;
+ }
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+#if 0 /* not legal! see table 3.6 of the 1.5 spec */
+ case GL_INTENSITY:
+#endif
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_DEPTH_COMPONENT:
+ 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;
+ case GL_HALF_FLOAT_ARB:
+ return ctx->Extensions.ARB_half_float_pixel;
+ 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;
+ case GL_HALF_FLOAT_ARB:
+ return ctx->Extensions.ARB_half_float_pixel;
+ default:
+ return GL_FALSE;
+ }
+ case GL_BGR:
+ switch (type) {
+ /* NOTE: no packed types are supported with BGR. That's
+ * intentional, according to the GL spec.
+ */
+ 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;
+ case GL_HALF_FLOAT_ARB:
+ return ctx->Extensions.ARB_half_float_pixel;
+ 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;
+ case GL_HALF_FLOAT_ARB:
+ return ctx->Extensions.ARB_half_float_pixel;
+ default:
+ return GL_FALSE;
+ }
+ case GL_YCBCR_MESA:
+ if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
+ type == GL_UNSIGNED_SHORT_8_8_REV_MESA)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+ case GL_DEPTH_STENCIL_EXT:
+ if (ctx->Extensions.EXT_packed_depth_stencil
+ && type == GL_UNSIGNED_INT_24_8_EXT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ 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;
+ }
+ default:
+ ; /* fall-through */
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Test if the given image format is a color/RGBA format (i.e., not color
+ * index, depth, stencil, etc).
+ * \param format the image format value (may by an internal texture format)
+ * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise.
+ */
+GLboolean
+_mesa_is_color_format(GLenum format)
+{
+ switch (format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ 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_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 3:
+ case GL_RGB:
+ case GL_BGR:
+ 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_ABGR_EXT:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ /* float texture formats */
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ /* compressed formats */
+ case GL_COMPRESSED_ALPHA:
+ case GL_COMPRESSED_LUMINANCE:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ case GL_COMPRESSED_INTENSITY:
+ case GL_COMPRESSED_RGB:
+ case GL_COMPRESSED_RGBA:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+#if FEATURE_EXT_texture_sRGB
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+#endif /* FEATURE_EXT_texture_sRGB */
+ return GL_TRUE;
+ /* signed texture formats */
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return GL_TRUE;
+ case GL_YCBCR_MESA: /* not considered to be RGB */
+ /* fall-through */
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a color index format.
+ */
+GLboolean
+_mesa_is_index_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:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a depth component format.
+ */
+GLboolean
+_mesa_is_depth_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a stencil format.
+ */
+GLboolean
+_mesa_is_stencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_STENCIL:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a YCbCr format.
+ */
+GLboolean
+_mesa_is_ycbcr_format(GLenum format)
+{
+ switch (format) {
+ case GL_YCBCR_MESA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Test if the given image format is a depth+stencil format.
+ */
+GLboolean
+_mesa_is_depthstencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH24_STENCIL8_EXT:
+ case GL_DEPTH_STENCIL_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+/**
+ * Test if the given image format is a dudv format.
+ */
+GLboolean
+_mesa_is_dudv_format(GLenum format)
+{
+ switch (format) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Return the address of a specific pixel in an image (1D, 2D or 3D).
+ *
+ * Pixel unpacking/packing parameters are observed according to \p packing.
+ *
+ * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
+ * \param image starting address of image data
+ * \param width the image width
+ * \param height theimage height
+ * \param format the pixel format
+ * \param type the pixel data type
+ * \param packing the pixelstore attributes
+ * \param img which image in the volume (0 for 1D or 2D images)
+ * \param row row of pixel in the image (0 for 1D images)
+ * \param column column of pixel in the image
+ *
+ * \return address of pixel on success, or NULL on error.
+ *
+ * \sa gl_pixelstore_attrib.
+ */
+GLvoid *
+_mesa_image_address( GLuint dimensions,
+ 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;
+
+ ASSERT(dimensions >= 1 && dimensions <= 3);
+
+ 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;
+ }
+
+ skippixels = packing->SkipPixels;
+ /* Note: SKIP_ROWS _is_ used for 1D images */
+ skiprows = packing->SkipRows;
+ /* Note: SKIP_IMAGES is only used for 3D images */
+ skipimages = (dimensions == 3) ? packing->SkipImages : 0;
+
+ 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 = _mesa_sizeof_packed_type( type );
+ if (bytes_per_comp < 0) {
+ return NULL;
+ }
+
+ /* Compute number of components per pixel */
+ comp_per_pixel = _mesa_components_in_format( format );
+ if (comp_per_pixel < 0) {
+ 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;
+ GLint topOfImage;
+
+ bytes_per_pixel = _mesa_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;
+
+ if (packing->Invert) {
+ /* set pixel_addr to the last row */
+ topOfImage = bytes_per_row * (height - 1);
+ bytes_per_row = -bytes_per_row;
+ }
+ else {
+ topOfImage = 0;
+ }
+
+ /* compute final pixel address */
+ pixel_addr = (GLubyte *) image
+ + (skipimages + img) * bytes_per_image
+ + topOfImage
+ + (skiprows + row) * bytes_per_row
+ + (skippixels + column) * bytes_per_pixel;
+ }
+
+ return (GLvoid *) pixel_addr;
+}
+
+
+GLvoid *
+_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width,
+ GLenum format, GLenum type,
+ GLint column )
+{
+ return _mesa_image_address(1, packing, image, width, 1,
+ format, type, 0, 0, column);
+}
+
+
+GLvoid *
+_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint row, GLint column )
+{
+ return _mesa_image_address(2, packing, image, width, height,
+ format, type, 0, row, column);
+}
+
+
+GLvoid *
+_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint img, GLint row, GLint column )
+{
+ return _mesa_image_address(3, packing, image, width, height,
+ format, type, img, row, column);
+}
+
+
+
+/**
+ * Compute the stride (in bytes) between image rows.
+ *
+ * \param packing the pixelstore attributes
+ * \param width image width.
+ * \param format pixel format.
+ * \param type pixel data type.
+ *
+ * \return the stride in bytes for the given parameters, or -1 if error
+ */
+GLint
+_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
+ GLint width, GLenum format, GLenum type )
+{
+ GLint bytesPerRow, remainder;
+
+ ASSERT(packing);
+
+ if (type == GL_BITMAP) {
+ if (packing->RowLength == 0) {
+ bytesPerRow = (width + 7) / 8;
+ }
+ else {
+ bytesPerRow = (packing->RowLength + 7) / 8;
+ }
+ }
+ else {
+ /* Non-BITMAP data */
+ const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
+ if (bytesPerPixel <= 0)
+ return -1; /* error */
+ if (packing->RowLength == 0) {
+ bytesPerRow = bytesPerPixel * width;
+ }
+ else {
+ bytesPerRow = bytesPerPixel * packing->RowLength;
+ }
+ }
+
+ remainder = bytesPerRow % packing->Alignment;
+ if (remainder > 0) {
+ bytesPerRow += (packing->Alignment - remainder);
+ }
+
+ if (packing->Invert) {
+ /* negate the bytes per row (negative row stride) */
+ bytesPerRow = -bytesPerRow;
+ }
+
+ return bytesPerRow;
+}
+
+
+#if _HAVE_FULL_GL
+
+/*
+ * Compute the stride between images in a 3D texture (in bytes) for the given
+ * pixel packing parameters and image width, format and type.
+ */
+GLint
+_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
+ GLint width, GLint height,
+ GLenum format, GLenum type )
+{
+ GLint bytesPerRow, bytesPerImage, remainder;
+
+ ASSERT(packing);
+
+ if (type == GL_BITMAP) {
+ if (packing->RowLength == 0) {
+ bytesPerRow = (width + 7) / 8;
+ }
+ else {
+ bytesPerRow = (packing->RowLength + 7) / 8;
+ }
+ }
+ else {
+ const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
+
+ if (bytesPerPixel <= 0)
+ return -1; /* error */
+ if (packing->RowLength == 0) {
+ bytesPerRow = bytesPerPixel * width;
+ }
+ else {
+ bytesPerRow = bytesPerPixel * packing->RowLength;
+ }
+ }
+
+ remainder = bytesPerRow % packing->Alignment;
+ if (remainder > 0)
+ bytesPerRow += (packing->Alignment - remainder);
+
+ if (packing->ImageHeight == 0)
+ bytesPerImage = bytesPerRow * height;
+ else
+ bytesPerImage = bytesPerRow * packing->ImageHeight;
+
+ return bytesPerImage;
+}
+
+
+/*
+ * Unpack a 32x32 pixel polygon stipple from user memory using the
+ * current pixel unpack settings.
+ */
+void
+_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32],
+ const struct gl_pixelstore_attrib *unpacking )
+{
+ GLubyte *ptrn = (GLubyte *) _mesa_unpack_bitmap(32, 32, pattern, unpacking);
+ if (ptrn) {
+ /* Convert pattern from GLubytes to GLuints and handle big/little
+ * endian differences
+ */
+ GLubyte *p = ptrn;
+ GLint i;
+ for (i = 0; i < 32; i++) {
+ dest[i] = (p[0] << 24)
+ | (p[1] << 16)
+ | (p[2] << 8)
+ | (p[3] );
+ p += 4;
+ }
+ _mesa_free(ptrn);
+ }
+}
+
+
+/*
+ * Pack polygon stipple into user memory given current pixel packing
+ * settings.
+ */
+void
+_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest,
+ const struct gl_pixelstore_attrib *packing )
+{
+ /* Convert pattern from GLuints to GLubytes to handle big/little
+ * endian differences.
+ */
+ GLubyte ptrn[32*4];
+ GLint i;
+ for (i = 0; i < 32; i++) {
+ ptrn[i * 4 + 0] = (GLubyte) ((pattern[i] >> 24) & 0xff);
+ ptrn[i * 4 + 1] = (GLubyte) ((pattern[i] >> 16) & 0xff);
+ ptrn[i * 4 + 2] = (GLubyte) ((pattern[i] >> 8 ) & 0xff);
+ ptrn[i * 4 + 3] = (GLubyte) ((pattern[i] ) & 0xff);
+ }
+
+ _mesa_pack_bitmap(32, 32, ptrn, dest, packing);
+}
+
+
+/*
+ * Unpack bitmap data. Resulting data will be in most-significant-bit-first
+ * order with row alignment = 1 byte.
+ */
+GLvoid *
+_mesa_unpack_bitmap( GLint width, GLint height, const GLubyte *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ GLint bytes, row, width_in_bytes;
+ GLubyte *buffer, *dst;
+
+ if (!pixels)
+ return NULL;
+
+ /* Alloc dest storage */
+ bytes = ((width + 7) / 8 * height);
+ buffer = (GLubyte *) _mesa_malloc( bytes );
+ if (!buffer)
+ return NULL;
+
+ width_in_bytes = CEILING( width, 8 );
+ dst = buffer;
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address2d(packing, pixels, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, row, 0);
+ if (!src) {
+ _mesa_free(buffer);
+ return NULL;
+ }
+
+ if ((packing->SkipPixels & 7) == 0) {
+ _mesa_memcpy( dst, src, width_in_bytes );
+ if (packing->LsbFirst) {
+ flip_bytes( dst, width_in_bytes );
+ }
+ }
+ else {
+ /* handling SkipPixels is a bit tricky (no pun intended!) */
+ GLint i;
+ if (packing->LsbFirst) {
+ GLubyte srcMask = 1 << (packing->SkipPixels & 0x7);
+ GLubyte dstMask = 128;
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 128) {
+ srcMask = 1;
+ s++;
+ }
+ else {
+ srcMask = srcMask << 1;
+ }
+ if (dstMask == 1) {
+ dstMask = 128;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask >> 1;
+ }
+ }
+ }
+ else {
+ GLubyte srcMask = 128 >> (packing->SkipPixels & 0x7);
+ GLubyte dstMask = 128;
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 1) {
+ srcMask = 128;
+ s++;
+ }
+ else {
+ srcMask = srcMask >> 1;
+ }
+ if (dstMask == 1) {
+ dstMask = 128;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask >> 1;
+ }
+ }
+ }
+ }
+ dst += width_in_bytes;
+ }
+
+ return buffer;
+}
+
+
+/*
+ * Pack bitmap data.
+ */
+void
+_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
+ GLubyte *dest, const struct gl_pixelstore_attrib *packing )
+{
+ GLint row, width_in_bytes;
+ const GLubyte *src;
+
+ if (!source)
+ return;
+
+ width_in_bytes = CEILING( width, 8 );
+ src = source;
+ for (row = 0; row < height; row++) {
+ GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest,
+ width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
+ if (!dst)
+ return;
+
+ if ((packing->SkipPixels & 7) == 0) {
+ _mesa_memcpy( dst, src, width_in_bytes );
+ if (packing->LsbFirst) {
+ flip_bytes( dst, width_in_bytes );
+ }
+ }
+ else {
+ /* handling SkipPixels is a bit tricky (no pun intended!) */
+ GLint i;
+ if (packing->LsbFirst) {
+ GLubyte srcMask = 128;
+ GLubyte dstMask = 1 << (packing->SkipPixels & 0x7);
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 1) {
+ srcMask = 128;
+ s++;
+ }
+ else {
+ srcMask = srcMask >> 1;
+ }
+ if (dstMask == 128) {
+ dstMask = 1;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask << 1;
+ }
+ }
+ }
+ else {
+ GLubyte srcMask = 128;
+ GLubyte dstMask = 128 >> (packing->SkipPixels & 0x7);
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 1) {
+ srcMask = 128;
+ s++;
+ }
+ else {
+ srcMask = srcMask >> 1;
+ }
+ if (dstMask == 1) {
+ dstMask = 128;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask >> 1;
+ }
+ }
+ }
+ }
+ src += width_in_bytes;
+ }
+}
+
+
+/**
+ * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
+ * This is typically used to convert a bitmap into a GLubyte/pixel texture.
+ * "On" bits will set texels to \p onValue.
+ * "Off" bits will not modify texels.
+ * \param width src bitmap width in pixels
+ * \param height src bitmap height in pixels
+ * \param unpack bitmap unpacking state
+ * \param bitmap the src bitmap data
+ * \param destBuffer start of dest buffer
+ * \param destStride row stride in dest buffer
+ * \param onValue if bit is 1, set destBuffer pixel to this value
+ */
+void
+_mesa_expand_bitmap(GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ GLubyte *destBuffer, GLint destStride,
+ GLubyte onValue)
+{
+ const GLubyte *srcRow = (const GLubyte *)
+ _mesa_image_address2d(unpack, bitmap, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, 0, 0);
+ const GLint srcStride = _mesa_image_row_stride(unpack, width,
+ GL_COLOR_INDEX, GL_BITMAP);
+ GLint row, col;
+
+#define SET_PIXEL(COL, ROW) \
+ destBuffer[(ROW) * destStride + (COL)] = onValue;
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = srcRow;
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+
+ if (*src & mask) {
+ SET_PIXEL(col, row);
+ }
+
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+
+ srcRow += srcStride;
+ } /* row */
+
+#undef SET_PIXEL
+}
+
+
+/**********************************************************************/
+/***** Pixel processing functions ******/
+/**********************************************************************/
+
+/*
+ * Apply scale and bias factors to an array of RGBA pixels.
+ */
+void
+_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
+ GLfloat rScale, GLfloat gScale,
+ GLfloat bScale, GLfloat aScale,
+ GLfloat rBias, GLfloat gBias,
+ GLfloat bBias, GLfloat aBias)
+{
+ if (rScale != 1.0 || rBias != 0.0) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias;
+ }
+ }
+ if (gScale != 1.0 || gBias != 0.0) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias;
+ }
+ }
+ if (bScale != 1.0 || bBias != 0.0) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias;
+ }
+ }
+ if (aScale != 1.0 || aBias != 0.0) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias;
+ }
+ }
+}
+
+
+/*
+ * Apply pixel mapping to an array of floating point RGBA pixels.
+ */
+void
+_mesa_map_rgba( const GLcontext *ctx, GLuint n, GLfloat rgba[][4] )
+{
+ const GLfloat rscale = (GLfloat) (ctx->PixelMaps.RtoR.Size - 1);
+ const GLfloat gscale = (GLfloat) (ctx->PixelMaps.GtoG.Size - 1);
+ const GLfloat bscale = (GLfloat) (ctx->PixelMaps.BtoB.Size - 1);
+ const GLfloat ascale = (GLfloat) (ctx->PixelMaps.AtoA.Size - 1);
+ const GLfloat *rMap = ctx->PixelMaps.RtoR.Map;
+ const GLfloat *gMap = ctx->PixelMaps.GtoG.Map;
+ const GLfloat *bMap = ctx->PixelMaps.BtoB.Map;
+ const GLfloat *aMap = ctx->PixelMaps.AtoA.Map;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
+ GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
+ GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
+ GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
+ rgba[i][RCOMP] = rMap[IROUND(r * rscale)];
+ rgba[i][GCOMP] = gMap[IROUND(g * gscale)];
+ rgba[i][BCOMP] = bMap[IROUND(b * bscale)];
+ rgba[i][ACOMP] = aMap[IROUND(a * ascale)];
+ }
+}
+
+
+/*
+ * Apply the color matrix and post color matrix scaling and biasing.
+ */
+void
+_mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4])
+{
+ const GLfloat rs = ctx->Pixel.PostColorMatrixScale[0];
+ const GLfloat rb = ctx->Pixel.PostColorMatrixBias[0];
+ const GLfloat gs = ctx->Pixel.PostColorMatrixScale[1];
+ const GLfloat gb = ctx->Pixel.PostColorMatrixBias[1];
+ const GLfloat bs = ctx->Pixel.PostColorMatrixScale[2];
+ const GLfloat bb = ctx->Pixel.PostColorMatrixBias[2];
+ const GLfloat as = ctx->Pixel.PostColorMatrixScale[3];
+ const GLfloat ab = ctx->Pixel.PostColorMatrixBias[3];
+ const GLfloat *m = ctx->ColorMatrixStack.Top->m;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ const GLfloat r = rgba[i][RCOMP];
+ const GLfloat g = rgba[i][GCOMP];
+ const GLfloat b = rgba[i][BCOMP];
+ const GLfloat a = rgba[i][ACOMP];
+ rgba[i][RCOMP] = (m[0] * r + m[4] * g + m[ 8] * b + m[12] * a) * rs + rb;
+ rgba[i][GCOMP] = (m[1] * r + m[5] * g + m[ 9] * b + m[13] * a) * gs + gb;
+ rgba[i][BCOMP] = (m[2] * r + m[6] * g + m[10] * b + m[14] * a) * bs + bb;
+ rgba[i][ACOMP] = (m[3] * r + m[7] * g + m[11] * b + m[15] * a) * as + ab;
+ }
+}
+
+
+/**
+ * Apply a color table lookup to an array of floating point RGBA colors.
+ */
+void
+_mesa_lookup_rgba_float(const struct gl_color_table *table,
+ GLuint n, GLfloat rgba[][4])
+{
+ const GLint max = table->Size - 1;
+ const GLfloat scale = (GLfloat) max;
+ const GLfloat *lut = table->TableF;
+ GLuint i;
+
+ if (!table->TableF || table->Size == 0)
+ return;
+
+ switch (table->_BaseFormat) {
+ case GL_INTENSITY:
+ /* replace RGBA with I */
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND(rgba[i][RCOMP] * scale);
+ GLfloat c = lut[CLAMP(j, 0, max)];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] =
+ rgba[i][ACOMP] = c;
+ }
+ break;
+ case GL_LUMINANCE:
+ /* replace RGB with L */
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND(rgba[i][RCOMP] * scale);
+ GLfloat c = lut[CLAMP(j, 0, max)];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = c;
+ }
+ break;
+ case GL_ALPHA:
+ /* replace A with A */
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND(rgba[i][ACOMP] * scale);
+ rgba[i][ACOMP] = lut[CLAMP(j, 0, max)];
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ /* replace RGBA with LLLA */
+ for (i = 0; i < n; i++) {
+ GLint jL = IROUND(rgba[i][RCOMP] * scale);
+ GLint jA = IROUND(rgba[i][ACOMP] * scale);
+ GLfloat luminance, alpha;
+ jL = CLAMP(jL, 0, max);
+ jA = CLAMP(jA, 0, max);
+ luminance = lut[jL * 2 + 0];
+ alpha = lut[jA * 2 + 1];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = luminance;
+ rgba[i][ACOMP] = alpha;;
+ }
+ break;
+ case GL_RGB:
+ /* replace RGB with RGB */
+ for (i = 0; i < n; i++) {
+ GLint jR = IROUND(rgba[i][RCOMP] * scale);
+ GLint jG = IROUND(rgba[i][GCOMP] * scale);
+ GLint jB = IROUND(rgba[i][BCOMP] * scale);
+ jR = CLAMP(jR, 0, max);
+ jG = CLAMP(jG, 0, max);
+ jB = CLAMP(jB, 0, max);
+ rgba[i][RCOMP] = lut[jR * 3 + 0];
+ rgba[i][GCOMP] = lut[jG * 3 + 1];
+ rgba[i][BCOMP] = lut[jB * 3 + 2];
+ }
+ break;
+ case GL_RGBA:
+ /* replace RGBA with RGBA */
+ for (i = 0; i < n; i++) {
+ GLint jR = IROUND(rgba[i][RCOMP] * scale);
+ GLint jG = IROUND(rgba[i][GCOMP] * scale);
+ GLint jB = IROUND(rgba[i][BCOMP] * scale);
+ GLint jA = IROUND(rgba[i][ACOMP] * scale);
+ jR = CLAMP(jR, 0, max);
+ jG = CLAMP(jG, 0, max);
+ jB = CLAMP(jB, 0, max);
+ jA = CLAMP(jA, 0, max);
+ rgba[i][RCOMP] = lut[jR * 4 + 0];
+ rgba[i][GCOMP] = lut[jG * 4 + 1];
+ rgba[i][BCOMP] = lut[jB * 4 + 2];
+ rgba[i][ACOMP] = lut[jA * 4 + 3];
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float");
+ return;
+ }
+}
+
+
+
+/**
+ * Apply a color table lookup to an array of ubyte/RGBA colors.
+ */
+void
+_mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
+ GLuint n, GLubyte rgba[][4])
+{
+ const GLubyte *lut = table->TableUB;
+ const GLfloat scale = (GLfloat) (table->Size - 1) / (GLfloat)255.0;
+ GLuint i;
+
+ if (!table->TableUB || table->Size == 0)
+ return;
+
+ switch (table->_BaseFormat) {
+ case GL_INTENSITY:
+ /* replace RGBA with I */
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ const GLubyte c = lut[rgba[i][RCOMP]];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] =
+ rgba[i][ACOMP] = c;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] =
+ rgba[i][ACOMP] = lut[j];
+ }
+ }
+ break;
+ case GL_LUMINANCE:
+ /* replace RGB with L */
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ const GLubyte c = lut[rgba[i][RCOMP]];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = c;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale);
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = lut[j];
+ }
+ }
+ break;
+ case GL_ALPHA:
+ /* replace A with A */
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = lut[rgba[i][ACOMP]];
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale);
+ rgba[i][ACOMP] = lut[j];
+ }
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ /* replace RGBA with LLLA */
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ GLubyte l = lut[rgba[i][RCOMP] * 2 + 0];
+ GLubyte a = lut[rgba[i][ACOMP] * 2 + 1];;
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = l;
+ rgba[i][ACOMP] = a;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale);
+ GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
+ GLubyte luminance = lut[jL * 2 + 0];
+ GLubyte alpha = lut[jA * 2 + 1];
+ rgba[i][RCOMP] =
+ rgba[i][GCOMP] =
+ rgba[i][BCOMP] = luminance;
+ rgba[i][ACOMP] = alpha;
+ }
+ }
+ break;
+ case GL_RGB:
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0];
+ rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1];
+ rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2];
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
+ GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
+ GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
+ rgba[i][RCOMP] = lut[jR * 3 + 0];
+ rgba[i][GCOMP] = lut[jG * 3 + 1];
+ rgba[i][BCOMP] = lut[jB * 3 + 2];
+ }
+ }
+ break;
+ case GL_RGBA:
+ if (table->Size == 256) {
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0];
+ rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1];
+ rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2];
+ rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3];
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale);
+ GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale);
+ GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale);
+ GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale);
+ CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]);
+ CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]);
+ CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]);
+ CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]);
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan");
+ return;
+ }
+}
+
+
+
+/*
+ * Map color indexes to float rgba values.
+ */
+void
+_mesa_map_ci_to_rgba( const GLcontext *ctx, GLuint n,
+ const GLuint index[], GLfloat rgba[][4] )
+{
+ GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
+ GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
+ GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
+ GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
+ const GLfloat *rMap = ctx->PixelMaps.ItoR.Map;
+ const GLfloat *gMap = ctx->PixelMaps.ItoG.Map;
+ const GLfloat *bMap = ctx->PixelMaps.ItoB.Map;
+ const GLfloat *aMap = ctx->PixelMaps.ItoA.Map;
+ 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 ubyte color indexes to ubyte/RGBA values.
+ */
+void
+_mesa_map_ci8_to_rgba8(const GLcontext *ctx, GLuint n, const GLubyte index[],
+ GLubyte rgba[][4])
+{
+ GLuint rmask = ctx->PixelMaps.ItoR.Size - 1;
+ GLuint gmask = ctx->PixelMaps.ItoG.Size - 1;
+ GLuint bmask = ctx->PixelMaps.ItoB.Size - 1;
+ GLuint amask = ctx->PixelMaps.ItoA.Size - 1;
+ const GLubyte *rMap = ctx->PixelMaps.ItoR.Map8;
+ const GLubyte *gMap = ctx->PixelMaps.ItoG.Map8;
+ const GLubyte *bMap = ctx->PixelMaps.ItoB.Map8;
+ const GLubyte *aMap = ctx->PixelMaps.ItoA.Map8;
+ 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
+_mesa_scale_and_bias_depth(const GLcontext *ctx, GLuint n,
+ GLfloat depthValues[])
+{
+ const GLfloat scale = ctx->Pixel.DepthScale;
+ const GLfloat bias = ctx->Pixel.DepthBias;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLfloat d = depthValues[i] * scale + bias;
+ depthValues[i] = CLAMP(d, 0.0F, 1.0F);
+ }
+}
+
+
+void
+_mesa_scale_and_bias_depth_uint(const GLcontext *ctx, GLuint n,
+ GLuint depthValues[])
+{
+ const GLdouble max = (double) 0xffffffff;
+ const GLdouble scale = ctx->Pixel.DepthScale;
+ const GLdouble bias = ctx->Pixel.DepthBias * max;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLdouble d = (GLdouble) depthValues[i] * scale + bias;
+ d = CLAMP(d, 0.0, max);
+ depthValues[i] = (GLuint) d;
+ }
+}
+
+
+
+/*
+ * Update the min/max values from an array of fragment colors.
+ */
+static void
+update_minmax(GLcontext *ctx, GLuint n, const GLfloat rgba[][4])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ /* update mins */
+ if (rgba[i][RCOMP] < ctx->MinMax.Min[RCOMP])
+ ctx->MinMax.Min[RCOMP] = rgba[i][RCOMP];
+ if (rgba[i][GCOMP] < ctx->MinMax.Min[GCOMP])
+ ctx->MinMax.Min[GCOMP] = rgba[i][GCOMP];
+ if (rgba[i][BCOMP] < ctx->MinMax.Min[BCOMP])
+ ctx->MinMax.Min[BCOMP] = rgba[i][BCOMP];
+ if (rgba[i][ACOMP] < ctx->MinMax.Min[ACOMP])
+ ctx->MinMax.Min[ACOMP] = rgba[i][ACOMP];
+
+ /* update maxs */
+ if (rgba[i][RCOMP] > ctx->MinMax.Max[RCOMP])
+ ctx->MinMax.Max[RCOMP] = rgba[i][RCOMP];
+ if (rgba[i][GCOMP] > ctx->MinMax.Max[GCOMP])
+ ctx->MinMax.Max[GCOMP] = rgba[i][GCOMP];
+ if (rgba[i][BCOMP] > ctx->MinMax.Max[BCOMP])
+ ctx->MinMax.Max[BCOMP] = rgba[i][BCOMP];
+ if (rgba[i][ACOMP] > ctx->MinMax.Max[ACOMP])
+ ctx->MinMax.Max[ACOMP] = rgba[i][ACOMP];
+ }
+}
+
+
+/*
+ * Update the histogram values from an array of fragment colors.
+ */
+static void
+update_histogram(GLcontext *ctx, GLuint n, const GLfloat rgba[][4])
+{
+ const GLint max = ctx->Histogram.Width - 1;
+ GLfloat w = (GLfloat) max;
+ GLuint i;
+
+ if (ctx->Histogram.Width == 0)
+ return;
+
+ for (i = 0; i < n; i++) {
+ GLint ri = IROUND(rgba[i][RCOMP] * w);
+ GLint gi = IROUND(rgba[i][GCOMP] * w);
+ GLint bi = IROUND(rgba[i][BCOMP] * w);
+ GLint ai = IROUND(rgba[i][ACOMP] * w);
+ ri = CLAMP(ri, 0, max);
+ gi = CLAMP(gi, 0, max);
+ bi = CLAMP(bi, 0, max);
+ ai = CLAMP(ai, 0, max);
+ ctx->Histogram.Count[ri][RCOMP]++;
+ ctx->Histogram.Count[gi][GCOMP]++;
+ ctx->Histogram.Count[bi][BCOMP]++;
+ ctx->Histogram.Count[ai][ACOMP]++;
+ }
+}
+
+
+/**
+ * Apply various pixel transfer operations to an array of RGBA pixels
+ * as indicated by the transferOps bitmask
+ */
+void
+_mesa_apply_rgba_transfer_ops(GLcontext *ctx, GLbitfield transferOps,
+ GLuint n, GLfloat rgba[][4])
+{
+ /* scale & bias */
+ if (transferOps & IMAGE_SCALE_BIAS_BIT) {
+ _mesa_scale_and_bias_rgba(n, rgba,
+ ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
+ ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
+ ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
+ ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
+ }
+ /* color map lookup */
+ if (transferOps & IMAGE_MAP_COLOR_BIT) {
+ _mesa_map_rgba( ctx, n, rgba );
+ }
+ /* GL_COLOR_TABLE lookup */
+ if (transferOps & IMAGE_COLOR_TABLE_BIT) {
+ _mesa_lookup_rgba_float(&ctx->ColorTable[COLORTABLE_PRECONVOLUTION], n, rgba);
+ }
+ /* convolution */
+ if (transferOps & IMAGE_CONVOLUTION_BIT) {
+ /* this has to be done in the calling code */
+ _mesa_problem(ctx, "IMAGE_CONVOLUTION_BIT set in _mesa_apply_transfer_ops");
+ }
+ /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */
+ if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) {
+ _mesa_scale_and_bias_rgba(n, rgba,
+ ctx->Pixel.PostConvolutionScale[RCOMP],
+ ctx->Pixel.PostConvolutionScale[GCOMP],
+ ctx->Pixel.PostConvolutionScale[BCOMP],
+ ctx->Pixel.PostConvolutionScale[ACOMP],
+ ctx->Pixel.PostConvolutionBias[RCOMP],
+ ctx->Pixel.PostConvolutionBias[GCOMP],
+ ctx->Pixel.PostConvolutionBias[BCOMP],
+ ctx->Pixel.PostConvolutionBias[ACOMP]);
+ }
+ /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */
+ if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) {
+ _mesa_lookup_rgba_float(&ctx->ColorTable[COLORTABLE_POSTCONVOLUTION], n, rgba);
+ }
+ /* color matrix transform */
+ if (transferOps & IMAGE_COLOR_MATRIX_BIT) {
+ _mesa_transform_rgba(ctx, n, rgba);
+ }
+ /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */
+ if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) {
+ _mesa_lookup_rgba_float(&ctx->ColorTable[COLORTABLE_POSTCOLORMATRIX], n, rgba);
+ }
+ /* update histogram count */
+ if (transferOps & IMAGE_HISTOGRAM_BIT) {
+ update_histogram(ctx, n, (CONST GLfloat (*)[4]) rgba);
+ }
+ /* update min/max values */
+ if (transferOps & IMAGE_MIN_MAX_BIT) {
+ update_minmax(ctx, n, (CONST GLfloat (*)[4]) rgba);
+ }
+ /* clamping to [0,1] */
+ if (transferOps & IMAGE_CLAMP_BIT) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
+ rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
+ rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
+ rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
+ }
+ }
+}
+
+
+/*
+ * Apply color index shift and offset to an array of pixels.
+ */
+static void
+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 shift, offset and table lookup to an array
+ * of color indexes;
+ */
+void
+_mesa_apply_ci_transfer_ops(const GLcontext *ctx, GLbitfield transferOps,
+ GLuint n, GLuint indexes[])
+{
+ if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
+ shift_and_offset_ci(ctx, n, indexes);
+ }
+ if (transferOps & IMAGE_MAP_COLOR_BIT) {
+ const GLuint mask = ctx->PixelMaps.ItoI.Size - 1;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ const GLuint j = indexes[i] & mask;
+ indexes[i] = IROUND(ctx->PixelMaps.ItoI.Map[j]);
+ }
+ }
+}
+
+
+/**
+ * Apply stencil index shift, offset and table lookup to an array
+ * of stencil values.
+ */
+void
+_mesa_apply_stencil_transfer_ops(const GLcontext *ctx, GLuint n,
+ GLstencil stencil[])
+{
+ if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
+ const GLint offset = ctx->Pixel.IndexOffset;
+ GLint shift = ctx->Pixel.IndexShift;
+ GLuint i;
+ 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;
+ }
+ }
+ }
+ if (ctx->Pixel.MapStencilFlag) {
+ GLuint mask = ctx->PixelMaps.StoS.Size - 1;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ stencil[i] = (GLstencil)ctx->PixelMaps.StoS.Map[ stencil[i] & mask ];
+ }
+ }
+}
+
+
+/**
+ * Used to pack an array [][4] of RGBA float colors as specified
+ * by the dstFormat, dstType and dstPacking. Used by glReadPixels,
+ * glGetConvolutionFilter(), etc.
+ * Note: the rgba values will be modified by this function when any pixel
+ * transfer ops are enabled.
+ */
+void
+_mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
+ GLenum dstFormat, GLenum dstType,
+ GLvoid *dstAddr,
+ const struct gl_pixelstore_attrib *dstPacking,
+ GLbitfield transferOps)
+{
+ GLfloat luminance[MAX_WIDTH];
+ const GLint comps = _mesa_components_in_format(dstFormat);
+ GLuint i;
+
+ /* XXX
+ * This test should probably go away. Have the caller set/clear the
+ * IMAGE_CLAMP_BIT as needed.
+ */
+ if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
+ /* need to clamp to [0, 1] */
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+
+ if (transferOps) {
+ _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba);
+ if ((transferOps & IMAGE_MIN_MAX_BIT) && ctx->MinMax.Sink) {
+ return;
+ }
+ }
+
+ if (dstFormat == GL_LUMINANCE || dstFormat == GL_LUMINANCE_ALPHA) {
+ /* compute luminance values */
+ if (transferOps & IMAGE_CLAMP_BIT) {
+ for (i = 0; i < n; i++) {
+ GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
+ luminance[i] = CLAMP(sum, 0.0F, 1.0F);
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP];
+ }
+ }
+ }
+
+ /*
+ * Pack/store the pixels. Ugh! Lots of cases!!!
+ */
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(rgba[i][ACOMP]);
+ 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(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ dst[i*3+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ dst[i*3+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][ACOMP]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][BCOMP]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(rgba[i][ACOMP]);
+ 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(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[i*3+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ dst[i*3+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][ACOMP]);
+ dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][BCOMP]);
+ dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ CLAMPED_FLOAT_TO_USHORT(dst[i], rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ CLAMPED_FLOAT_TO_USHORT(dst[i], rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ CLAMPED_FLOAT_TO_USHORT(dst[i], rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ CLAMPED_FLOAT_TO_USHORT(dst[i], rgba[i][ACOMP]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ UNCLAMPED_FLOAT_TO_USHORT(dst[i], luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ UNCLAMPED_FLOAT_TO_USHORT(dst[i*2+0], luminance[i]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*2+1], rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+0], rgba[i][RCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+1], rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+2], rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+0], rgba[i][RCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+1], rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+2], rgba[i][BCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+0], rgba[i][BCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+1], rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*3+2], rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+0], rgba[i][BCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+1], rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+2], rgba[i][RCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+0], rgba[i][ACOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+1], rgba[i][BCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+2], rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(rgba[i][ACOMP]);
+ 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(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ dst[i*3+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ dst[i*3+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][ACOMP]);
+ dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][BCOMP]);
+ dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(rgba[i][ACOMP]);
+ 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(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ dst[i*3+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ dst[i*4+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ dst[i*4+3] = FLOAT_TO_UINT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ dst[i*3+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ dst[i*4+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ dst[i*4+3] = FLOAT_TO_UINT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(rgba[i][ACOMP]);
+ dst[i*4+1] = FLOAT_TO_UINT(rgba[i][BCOMP]);
+ dst[i*4+2] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(rgba[i][ACOMP]);
+ 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(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ dst[i*3+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ dst[i*4+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ dst[i*4+3] = FLOAT_TO_INT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ dst[i*3+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ dst[i*3+2] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ dst[i*4+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ dst[i*4+2] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ dst[i*4+3] = FLOAT_TO_INT(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(rgba[i][ACOMP]);
+ dst[i*4+1] = FLOAT_TO_INT(rgba[i][BCOMP]);
+ dst[i*4+2] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
+ dst[i*2+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = rgba[i][RCOMP];
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = rgba[i][GCOMP];
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = rgba[i][BCOMP];
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = rgba[i][ACOMP];
+ 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] = rgba[i][ACOMP];
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = rgba[i][RCOMP];
+ dst[i*3+1] = rgba[i][GCOMP];
+ dst[i*3+2] = rgba[i][BCOMP];
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = rgba[i][RCOMP];
+ dst[i*4+1] = rgba[i][GCOMP];
+ dst[i*4+2] = rgba[i][BCOMP];
+ dst[i*4+3] = rgba[i][ACOMP];
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = rgba[i][BCOMP];
+ dst[i*3+1] = rgba[i][GCOMP];
+ dst[i*3+2] = rgba[i][RCOMP];
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = rgba[i][BCOMP];
+ dst[i*4+1] = rgba[i][GCOMP];
+ dst[i*4+2] = rgba[i][RCOMP];
+ dst[i*4+3] = rgba[i][ACOMP];
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = rgba[i][ACOMP];
+ dst[i*4+1] = rgba[i][BCOMP];
+ dst[i*4+2] = rgba[i][GCOMP];
+ dst[i*4+3] = rgba[i][RCOMP];
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = rgba[i][RCOMP];
+ dst[i*2+1] = rgba[i][GCOMP];
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLhalfARB *dst = (GLhalfARB *) dstAddr;
+ switch (dstFormat) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][RCOMP]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][GCOMP]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][BCOMP]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(rgba[i][ACOMP]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = _mesa_float_to_half(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = _mesa_float_to_half(luminance[i]);
+ dst[i*2+1] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*3+2] = _mesa_float_to_half(rgba[i][BCOMP]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*3+2] = _mesa_float_to_half(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = _mesa_float_to_half(rgba[i][ACOMP]);
+ dst[i*4+1] = _mesa_float_to_half(rgba[i][BCOMP]);
+ dst[i*4+2] = _mesa_float_to_half(rgba[i][GCOMP]);
+ dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]);
+ }
+ break;
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = _mesa_float_to_half(rgba[i][RCOMP]);
+ dst[i*2+1] = _mesa_float_to_half(rgba[i][GCOMP]);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ if (dstFormat == GL_RGB) {
+ GLubyte *dst = (GLubyte *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) << 5)
+ | (IROUND(rgba[i][GCOMP] * 7.0F) << 2)
+ | (IROUND(rgba[i][BCOMP] * 3.0F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ if (dstFormat == GL_RGB) {
+ GLubyte *dst = (GLubyte *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 7.0F) )
+ | (IROUND(rgba[i][GCOMP] * 7.0F) << 3)
+ | (IROUND(rgba[i][BCOMP] * 3.0F) << 6);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (dstFormat == GL_RGB) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 63.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ if (dstFormat == GL_RGB) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 63.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 11);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ if (dstFormat == GL_RGBA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) );
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) );
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) << 12)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ if (dstFormat == GL_RGBA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 15.0F) )
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) << 12);
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 15.0F) )
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 15.0F) << 12);
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 15.0F) )
+ | (IROUND(rgba[i][BCOMP] * 15.0F) << 4)
+ | (IROUND(rgba[i][GCOMP] * 15.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 15.0F) << 12);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ if (dstFormat == GL_RGBA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) );
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][RCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) );
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) << 11)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 6)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 1)
+ | (IROUND(rgba[i][RCOMP] * 1.0F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (dstFormat == GL_RGBA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) << 15);
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 31.0F) )
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][RCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][ACOMP] * 1.0F) << 15);
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLushort *dst = (GLushort *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 31.0F) )
+ | (IROUND(rgba[i][BCOMP] * 31.0F) << 5)
+ | (IROUND(rgba[i][GCOMP] * 31.0F) << 10)
+ | (IROUND(rgba[i][RCOMP] * 1.0F) << 15);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ if (dstFormat == GL_RGBA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][BCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 255.F) );
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][RCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][ACOMP] * 255.F) );
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 255.F) << 24)
+ | (IROUND(rgba[i][BCOMP] * 255.F) << 16)
+ | (IROUND(rgba[i][GCOMP] * 255.F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 255.F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (dstFormat == GL_RGBA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 255.0F) )
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][BCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][ACOMP] * 255.0F) << 24);
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 255.0F) )
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][RCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][ACOMP] * 255.0F) << 24);
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 255.0F) )
+ | (IROUND(rgba[i][BCOMP] * 255.0F) << 8)
+ | (IROUND(rgba[i][GCOMP] * 255.0F) << 16)
+ | (IROUND(rgba[i][RCOMP] * 255.0F) << 24);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ if (dstFormat == GL_RGBA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) );
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][RCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) );
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) << 22)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 12)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 2)
+ | (IROUND(rgba[i][RCOMP] * 3.0F) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (dstFormat == GL_RGBA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][RCOMP] * 1023.0F) )
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) << 30);
+ }
+ }
+ else if (dstFormat == GL_BGRA) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][BCOMP] * 1023.0F) )
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][RCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][ACOMP] * 3.0F) << 30);
+ }
+ }
+ else if (dstFormat == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) dstAddr;
+ for (i=0;i<n;i++) {
+ dst[i] = (IROUND(rgba[i][ACOMP] * 1023.0F) )
+ | (IROUND(rgba[i][BCOMP] * 1023.0F) << 10)
+ | (IROUND(rgba[i][GCOMP] * 1023.0F) << 20)
+ | (IROUND(rgba[i][RCOMP] * 3.0F) << 30);
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad type in _mesa_pack_rgba_span_float");
+ return;
+ }
+
+ if (dstPacking->SwapBytes) {
+ GLint swapSize = _mesa_sizeof_packed_type(dstType);
+ if (swapSize == 2) {
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2((GLushort *) dstAddr, n * comps);
+ }
+ }
+ else if (swapSize == 4) {
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4((GLuint *) dstAddr, n * comps);
+ }
+ }
+ }
+}
+
+
+#define SWAP2BYTE(VALUE) \
+ { \
+ GLubyte *bytes = (GLubyte *) &(VALUE); \
+ GLubyte tmp = bytes[0]; \
+ bytes[0] = bytes[1]; \
+ bytes[1] = tmp; \
+ }
+
+#define SWAP4BYTE(VALUE) \
+ { \
+ GLubyte *bytes = (GLubyte *) &(VALUE); \
+ GLubyte tmp = bytes[0]; \
+ bytes[0] = bytes[3]; \
+ bytes[3] = tmp; \
+ tmp = bytes[1]; \
+ bytes[1] = bytes[2]; \
+ bytes[2] = tmp; \
+ }
+
+
+static void
+extract_uint_indexes(GLuint n, GLuint indexes[],
+ GLenum srcFormat, GLenum srcType, const GLvoid *src,
+ const struct gl_pixelstore_attrib *unpack )
+{
+ ASSERT(srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX);
+
+ ASSERT(srcType == GL_BITMAP ||
+ srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_UNSIGNED_INT_24_8_EXT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT);
+
+ switch (srcType) {
+ case GL_BITMAP:
+ {
+ GLubyte *ubsrc = (GLubyte *) src;
+ if (unpack->LsbFirst) {
+ GLubyte mask = 1 << (unpack->SkipPixels & 0x7);
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ indexes[i] = (*ubsrc & mask) ? 1 : 0;
+ if (mask == 128) {
+ mask = 1;
+ ubsrc++;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+ }
+ else {
+ GLubyte mask = 128 >> (unpack->SkipPixels & 0x7);
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ indexes[i] = (*ubsrc & mask) ? 1 : 0;
+ if (mask == 1) {
+ mask = 128;
+ ubsrc++;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ {
+ GLuint i;
+ const GLubyte *s = (const GLubyte *) src;
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLuint i;
+ const GLbyte *s = (const GLbyte *) src;
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLuint i;
+ const GLushort *s = (const GLushort *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLushort value = s[i];
+ SWAP2BYTE(value);
+ indexes[i] = value;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLuint i;
+ const GLshort *s = (const GLshort *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLshort value = s[i];
+ SWAP2BYTE(value);
+ indexes[i] = value;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint i;
+ const GLuint *s = (const GLuint *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLuint value = s[i];
+ SWAP4BYTE(value);
+ indexes[i] = value;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLuint i;
+ const GLint *s = (const GLint *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLint value = s[i];
+ SWAP4BYTE(value);
+ indexes[i] = value;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i];
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLuint i;
+ const GLfloat *s = (const GLfloat *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLfloat value = s[i];
+ SWAP4BYTE(value);
+ indexes[i] = (GLuint) value;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = (GLuint) s[i];
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLuint i;
+ const GLhalfARB *s = (const GLhalfARB *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLhalfARB value = s[i];
+ SWAP2BYTE(value);
+ indexes[i] = (GLuint) _mesa_half_to_float(value);
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = (GLuint) _mesa_half_to_float(s[i]);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_24_8_EXT:
+ {
+ GLuint i;
+ const GLuint *s = (const GLuint *) src;
+ if (unpack->SwapBytes) {
+ for (i = 0; i < n; i++) {
+ GLuint value = s[i];
+ SWAP4BYTE(value);
+ indexes[i] = value & 0xff; /* lower 8 bits */
+ }
+ }
+ else {
+ for (i = 0; i < n; i++)
+ indexes[i] = s[i] & 0xff; /* lower 8 bits */
+ }
+ }
+ break;
+
+ default:
+ _mesa_problem(NULL, "bad srcType in extract_uint_indexes");
+ return;
+ }
+}
+
+
+/*
+ * This function extracts floating point RGBA values from arbitrary
+ * image data. srcFormat and srcType are the format and type parameters
+ * passed to glDrawPixels, glTexImage[123]D, glTexSubImage[123]D, etc.
+ *
+ * Refering to section 3.6.4 of the OpenGL 1.2 spec, this function
+ * implements the "Conversion to floating point", "Conversion to RGB",
+ * and "Final Expansion to RGBA" operations.
+ *
+ * Args: n - number of pixels
+ * rgba - output colors
+ * srcFormat - format of incoming data
+ * srcType - data type of incoming data
+ * src - source data pointer
+ * swapBytes - perform byteswapping of incoming data?
+ */
+static void
+extract_float_rgba(GLuint n, GLfloat rgba[][4],
+ GLenum srcFormat, GLenum srcType, const GLvoid *src,
+ GLboolean swapBytes)
+{
+ GLint redIndex, greenIndex, blueIndex, alphaIndex;
+ GLint stride;
+ GLint rComp, bComp, gComp, aComp;
+
+ ASSERT(srcFormat == GL_RED ||
+ srcFormat == GL_GREEN ||
+ srcFormat == GL_BLUE ||
+ srcFormat == GL_ALPHA ||
+ srcFormat == GL_LUMINANCE ||
+ srcFormat == GL_LUMINANCE_ALPHA ||
+ srcFormat == GL_INTENSITY ||
+ srcFormat == GL_RGB ||
+ srcFormat == GL_BGR ||
+ srcFormat == GL_RGBA ||
+ srcFormat == GL_BGRA ||
+ srcFormat == GL_ABGR_EXT ||
+ srcFormat == GL_DUDV_ATI);
+
+ ASSERT(srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT ||
+ srcType == GL_UNSIGNED_BYTE_3_3_2 ||
+ srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5 ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5_REV ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ srcType == GL_UNSIGNED_INT_10_10_10_2 ||
+ srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
+
+ rComp = gComp = bComp = aComp = -1;
+
+ switch (srcFormat) {
+ case GL_RED:
+ redIndex = 0;
+ greenIndex = blueIndex = alphaIndex = -1;
+ stride = 1;
+ break;
+ case GL_GREEN:
+ greenIndex = 0;
+ redIndex = blueIndex = alphaIndex = -1;
+ stride = 1;
+ break;
+ case GL_BLUE:
+ blueIndex = 0;
+ redIndex = greenIndex = alphaIndex = -1;
+ stride = 1;
+ break;
+ case GL_ALPHA:
+ redIndex = greenIndex = blueIndex = -1;
+ alphaIndex = 0;
+ stride = 1;
+ break;
+ case GL_LUMINANCE:
+ redIndex = greenIndex = blueIndex = 0;
+ alphaIndex = -1;
+ stride = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ redIndex = greenIndex = blueIndex = 0;
+ alphaIndex = 1;
+ stride = 2;
+ break;
+ case GL_INTENSITY:
+ redIndex = greenIndex = blueIndex = alphaIndex = 0;
+ stride = 1;
+ break;
+ case GL_RGB:
+ redIndex = 0;
+ greenIndex = 1;
+ blueIndex = 2;
+ alphaIndex = -1;
+ rComp = 0;
+ gComp = 1;
+ bComp = 2;
+ aComp = 3;
+ stride = 3;
+ break;
+ case GL_BGR:
+ redIndex = 2;
+ greenIndex = 1;
+ blueIndex = 0;
+ alphaIndex = -1;
+ rComp = 2;
+ gComp = 1;
+ bComp = 0;
+ aComp = 3;
+ stride = 3;
+ break;
+ case GL_RGBA:
+ redIndex = 0;
+ greenIndex = 1;
+ blueIndex = 2;
+ alphaIndex = 3;
+ rComp = 0;
+ gComp = 1;
+ bComp = 2;
+ aComp = 3;
+ stride = 4;
+ break;
+ case GL_BGRA:
+ redIndex = 2;
+ greenIndex = 1;
+ blueIndex = 0;
+ alphaIndex = 3;
+ rComp = 2;
+ gComp = 1;
+ bComp = 0;
+ aComp = 3;
+ stride = 4;
+ break;
+ case GL_ABGR_EXT:
+ redIndex = 3;
+ greenIndex = 2;
+ blueIndex = 1;
+ alphaIndex = 0;
+ rComp = 3;
+ gComp = 2;
+ bComp = 1;
+ aComp = 0;
+ stride = 4;
+ break;
+ case GL_DUDV_ATI:
+ redIndex = 0;
+ greenIndex = 1;
+ blueIndex = -1;
+ alphaIndex = -1;
+ stride = 2;
+ break;
+ default:
+ _mesa_problem(NULL, "bad srcFormat in extract float data");
+ return;
+ }
+
+
+#define PROCESS(INDEX, CHANNEL, DEFAULT, TYPE, CONVERSION) \
+ if ((INDEX) < 0) { \
+ GLuint i; \
+ for (i = 0; i < n; i++) { \
+ rgba[i][CHANNEL] = DEFAULT; \
+ } \
+ } \
+ else if (swapBytes) { \
+ const TYPE *s = (const TYPE *) src; \
+ GLuint i; \
+ for (i = 0; i < n; i++) { \
+ TYPE value = s[INDEX]; \
+ if (sizeof(TYPE) == 2) { \
+ SWAP2BYTE(value); \
+ } \
+ else if (sizeof(TYPE) == 4) { \
+ SWAP4BYTE(value); \
+ } \
+ rgba[i][CHANNEL] = (GLfloat) CONVERSION(value); \
+ s += stride; \
+ } \
+ } \
+ else { \
+ const TYPE *s = (const TYPE *) src; \
+ GLuint i; \
+ for (i = 0; i < n; i++) { \
+ rgba[i][CHANNEL] = (GLfloat) CONVERSION(s[INDEX]); \
+ s += stride; \
+ } \
+ }
+
+ switch (srcType) {
+ case GL_UNSIGNED_BYTE:
+ PROCESS(redIndex, RCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLubyte, UBYTE_TO_FLOAT);
+ break;
+ case GL_BYTE:
+ PROCESS(redIndex, RCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLbyte, BYTE_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_SHORT:
+ PROCESS(redIndex, RCOMP, 0.0F, GLushort, USHORT_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLushort, USHORT_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLushort, USHORT_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLushort, USHORT_TO_FLOAT);
+ break;
+ case GL_SHORT:
+ PROCESS(redIndex, RCOMP, 0.0F, GLshort, SHORT_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLshort, SHORT_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLshort, SHORT_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLshort, SHORT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_INT:
+ PROCESS(redIndex, RCOMP, 0.0F, GLuint, UINT_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLuint, UINT_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLuint, UINT_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLuint, UINT_TO_FLOAT);
+ break;
+ case GL_INT:
+ PROCESS(redIndex, RCOMP, 0.0F, GLint, INT_TO_FLOAT);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLint, INT_TO_FLOAT);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLint, INT_TO_FLOAT);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLint, INT_TO_FLOAT);
+ break;
+ case GL_FLOAT:
+ PROCESS(redIndex, RCOMP, 0.0F, GLfloat, (GLfloat));
+ PROCESS(greenIndex, GCOMP, 0.0F, GLfloat, (GLfloat));
+ PROCESS(blueIndex, BCOMP, 0.0F, GLfloat, (GLfloat));
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLfloat, (GLfloat));
+ break;
+ case GL_HALF_FLOAT_ARB:
+ PROCESS(redIndex, RCOMP, 0.0F, GLhalfARB, _mesa_half_to_float);
+ PROCESS(greenIndex, GCOMP, 0.0F, GLhalfARB, _mesa_half_to_float);
+ PROCESS(blueIndex, BCOMP, 0.0F, GLhalfARB, _mesa_half_to_float);
+ PROCESS(alphaIndex, ACOMP, 1.0F, GLhalfARB, _mesa_half_to_float);
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ {
+ const GLubyte *ubsrc = (const GLubyte *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLubyte p = ubsrc[i];
+ rgba[i][rComp] = ((p >> 5) ) * (1.0F / 7.0F);
+ rgba[i][gComp] = ((p >> 2) & 0x7) * (1.0F / 7.0F);
+ rgba[i][bComp] = ((p ) & 0x3) * (1.0F / 3.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ {
+ const GLubyte *ubsrc = (const GLubyte *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLubyte p = ubsrc[i];
+ rgba[i][rComp] = ((p ) & 0x7) * (1.0F / 7.0F);
+ rgba[i][gComp] = ((p >> 3) & 0x7) * (1.0F / 7.0F);
+ rgba[i][bComp] = ((p >> 6) ) * (1.0F / 3.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F);
+ rgba[i][bComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F);
+ rgba[i][bComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F);
+ rgba[i][bComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F);
+ rgba[i][bComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][aComp] = 1.0F;
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F);
+ rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F);
+ rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F);
+ rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F);
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F);
+ rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F);
+ rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F);
+ rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F);
+ rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F);
+ rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F);
+ rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F);
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F);
+ rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F);
+ rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F);
+ rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F);
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (swapBytes) {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ SWAP2BYTE(p);
+ rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F);
+ }
+ }
+ else {
+ const GLushort *ussrc = (const GLushort *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLushort p = ussrc[i];
+ rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F);
+ rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ if (swapBytes) {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = UBYTE_TO_FLOAT((p ) & 0xff);
+ rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff);
+ rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff);
+ rgba[i][aComp] = UBYTE_TO_FLOAT((p >> 24) );
+ }
+ }
+ else {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = UBYTE_TO_FLOAT((p >> 24) );
+ rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff);
+ rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff);
+ rgba[i][aComp] = UBYTE_TO_FLOAT((p ) & 0xff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (swapBytes) {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = UBYTE_TO_FLOAT((p >> 24) );
+ rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff);
+ rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff);
+ rgba[i][aComp] = UBYTE_TO_FLOAT((p ) & 0xff);
+ }
+ }
+ else {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = UBYTE_TO_FLOAT((p ) & 0xff);
+ rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff);
+ rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff);
+ rgba[i][aComp] = UBYTE_TO_FLOAT((p >> 24) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ if (swapBytes) {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ SWAP4BYTE(p);
+ rgba[i][rComp] = ((p >> 22) ) * (1.0F / 1023.0F);
+ rgba[i][gComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][bComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][aComp] = ((p ) & 0x3 ) * (1.0F / 3.0F);
+ }
+ }
+ else {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = ((p >> 22) ) * (1.0F / 1023.0F);
+ rgba[i][gComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][bComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][aComp] = ((p ) & 0x3 ) * (1.0F / 3.0F);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (swapBytes) {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ SWAP4BYTE(p);
+ rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F);
+ }
+ }
+ else {
+ const GLuint *uisrc = (const GLuint *) src;
+ GLuint i;
+ for (i = 0; i < n; i ++) {
+ GLuint p = uisrc[i];
+ rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F);
+ rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F);
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "bad srcType in extract float data");
+ break;
+ }
+}
+
+
+/*
+ * Unpack a row of color image data from a client buffer according to
+ * the pixel unpacking parameters.
+ * Return GLchan values in the specified dest image format.
+ * This is used by glDrawPixels and glTexImage?D().
+ * \param ctx - the context
+ * n - number of pixels in the span
+ * dstFormat - format of destination color array
+ * dest - the destination color array
+ * srcFormat - source image format
+ * srcType - source image data type
+ * source - source image pointer
+ * srcPacking - pixel unpacking parameters
+ * transferOps - bitmask of IMAGE_*_BIT values of operations to apply
+ *
+ * XXX perhaps expand this to process whole images someday.
+ */
+void
+_mesa_unpack_color_span_chan( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLchan dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(dstFormat == GL_ALPHA ||
+ dstFormat == GL_LUMINANCE ||
+ dstFormat == GL_LUMINANCE_ALPHA ||
+ dstFormat == GL_INTENSITY ||
+ dstFormat == GL_RGB ||
+ dstFormat == GL_RGBA ||
+ dstFormat == GL_COLOR_INDEX);
+
+ ASSERT(srcFormat == GL_RED ||
+ srcFormat == GL_GREEN ||
+ srcFormat == GL_BLUE ||
+ srcFormat == GL_ALPHA ||
+ srcFormat == GL_LUMINANCE ||
+ srcFormat == GL_LUMINANCE_ALPHA ||
+ srcFormat == GL_INTENSITY ||
+ srcFormat == GL_RGB ||
+ srcFormat == GL_BGR ||
+ srcFormat == GL_RGBA ||
+ srcFormat == GL_BGRA ||
+ srcFormat == GL_ABGR_EXT ||
+ srcFormat == GL_COLOR_INDEX);
+
+ ASSERT(srcType == GL_BITMAP ||
+ srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT ||
+ srcType == GL_UNSIGNED_BYTE_3_3_2 ||
+ srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5 ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5_REV ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ srcType == GL_UNSIGNED_INT_10_10_10_2 ||
+ srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
+
+ /* Try simple cases first */
+ if (transferOps == 0) {
+ if (srcType == CHAN_TYPE) {
+ if (dstFormat == GL_RGBA) {
+ if (srcFormat == GL_RGBA) {
+ _mesa_memcpy( dest, source, n * 4 * sizeof(GLchan) );
+ return;
+ }
+ else if (srcFormat == GL_RGB) {
+ GLuint i;
+ const GLchan *src = (const GLchan *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = CHAN_MAX;
+ src += 3;
+ dst += 4;
+ }
+ return;
+ }
+ }
+ else if (dstFormat == GL_RGB) {
+ if (srcFormat == GL_RGB) {
+ _mesa_memcpy( dest, source, n * 3 * sizeof(GLchan) );
+ return;
+ }
+ else if (srcFormat == GL_RGBA) {
+ GLuint i;
+ const GLchan *src = (const GLchan *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ src += 4;
+ dst += 3;
+ }
+ return;
+ }
+ }
+ else if (dstFormat == srcFormat) {
+ GLint comps = _mesa_components_in_format(srcFormat);
+ assert(comps > 0);
+ _mesa_memcpy( dest, source, n * comps * sizeof(GLchan) );
+ return;
+ }
+ }
+ /*
+ * Common situation, loading 8bit RGBA/RGB source images
+ * into 16/32 bit destination. (OSMesa16/32)
+ */
+ else if (srcType == GL_UNSIGNED_BYTE) {
+ if (dstFormat == GL_RGBA) {
+ if (srcFormat == GL_RGB) {
+ GLuint i;
+ const GLubyte *src = (const GLubyte *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = UBYTE_TO_CHAN(src[0]);
+ dst[1] = UBYTE_TO_CHAN(src[1]);
+ dst[2] = UBYTE_TO_CHAN(src[2]);
+ dst[3] = CHAN_MAX;
+ src += 3;
+ dst += 4;
+ }
+ return;
+ }
+ else if (srcFormat == GL_RGBA) {
+ GLuint i;
+ const GLubyte *src = (const GLubyte *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = UBYTE_TO_CHAN(src[0]);
+ dst[1] = UBYTE_TO_CHAN(src[1]);
+ dst[2] = UBYTE_TO_CHAN(src[2]);
+ dst[3] = UBYTE_TO_CHAN(src[3]);
+ src += 4;
+ dst += 4;
+ }
+ return;
+ }
+ }
+ else if (dstFormat == GL_RGB) {
+ if (srcFormat == GL_RGB) {
+ GLuint i;
+ const GLubyte *src = (const GLubyte *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = UBYTE_TO_CHAN(src[0]);
+ dst[1] = UBYTE_TO_CHAN(src[1]);
+ dst[2] = UBYTE_TO_CHAN(src[2]);
+ src += 3;
+ dst += 3;
+ }
+ return;
+ }
+ else if (srcFormat == GL_RGBA) {
+ GLuint i;
+ const GLubyte *src = (const GLubyte *) source;
+ GLchan *dst = dest;
+ for (i = 0; i < n; i++) {
+ dst[0] = UBYTE_TO_CHAN(src[0]);
+ dst[1] = UBYTE_TO_CHAN(src[1]);
+ dst[2] = UBYTE_TO_CHAN(src[2]);
+ src += 4;
+ dst += 3;
+ }
+ return;
+ }
+ }
+ }
+ }
+
+
+ /* general solution begins here */
+ {
+ GLint dstComponents;
+ GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex;
+ GLint dstLuminanceIndex, dstIntensityIndex;
+ GLfloat rgba[MAX_WIDTH][4];
+
+ dstComponents = _mesa_components_in_format( dstFormat );
+ /* source & dest image formats should have been error checked by now */
+ assert(dstComponents > 0);
+
+ /*
+ * Extract image data and convert to RGBA floats
+ */
+ assert(n <= MAX_WIDTH);
+ if (srcFormat == GL_COLOR_INDEX) {
+ GLuint indexes[MAX_WIDTH];
+ extract_uint_indexes(n, indexes, srcFormat, srcType, source,
+ srcPacking);
+
+ if (dstFormat == GL_COLOR_INDEX) {
+ GLuint i;
+ _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes);
+ /* convert to GLchan and return */
+ for (i = 0; i < n; i++) {
+ dest[i] = (GLchan) (indexes[i] & 0xff);
+ }
+ return;
+ }
+ else {
+ /* Convert indexes to RGBA */
+ if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
+ shift_and_offset_ci(ctx, n, indexes);
+ }
+ _mesa_map_ci_to_rgba(ctx, n, indexes, rgba);
+ }
+
+ /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting
+ * with color indexes.
+ */
+ transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT);
+ }
+ else {
+ /* non-color index data */
+ extract_float_rgba(n, rgba, srcFormat, srcType, source,
+ srcPacking->SwapBytes);
+ }
+
+ /* Need to clamp if returning GLubytes or GLushorts */
+#if CHAN_TYPE != GL_FLOAT
+ transferOps |= IMAGE_CLAMP_BIT;
+#endif
+
+ if (transferOps) {
+ _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba);
+ }
+
+ /* Now determine which color channels we need to produce.
+ * And determine the dest index (offset) within each color tuple.
+ */
+ switch (dstFormat) {
+ case GL_ALPHA:
+ dstAlphaIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = -1;
+ dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ case GL_LUMINANCE:
+ dstLuminanceIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1;
+ dstIntensityIndex = -1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ dstLuminanceIndex = 0;
+ dstAlphaIndex = 1;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = -1;
+ dstIntensityIndex = -1;
+ break;
+ case GL_INTENSITY:
+ dstIntensityIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1;
+ dstLuminanceIndex = -1;
+ break;
+ case GL_RGB:
+ dstRedIndex = 0;
+ dstGreenIndex = 1;
+ dstBlueIndex = 2;
+ dstAlphaIndex = dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ case GL_RGBA:
+ dstRedIndex = 0;
+ dstGreenIndex = 1;
+ dstBlueIndex = 2;
+ dstAlphaIndex = 3;
+ dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ default:
+ _mesa_problem(ctx, "bad dstFormat in _mesa_unpack_chan_span()");
+ return;
+ }
+
+
+ /* Now return the GLchan data in the requested dstFormat */
+
+ if (dstRedIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ CLAMPED_FLOAT_TO_CHAN(dst[dstRedIndex], rgba[i][RCOMP]);
+ dst += dstComponents;
+ }
+ }
+
+ if (dstGreenIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ CLAMPED_FLOAT_TO_CHAN(dst[dstGreenIndex], rgba[i][GCOMP]);
+ dst += dstComponents;
+ }
+ }
+
+ if (dstBlueIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ CLAMPED_FLOAT_TO_CHAN(dst[dstBlueIndex], rgba[i][BCOMP]);
+ dst += dstComponents;
+ }
+ }
+
+ if (dstAlphaIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ CLAMPED_FLOAT_TO_CHAN(dst[dstAlphaIndex], rgba[i][ACOMP]);
+ dst += dstComponents;
+ }
+ }
+
+ if (dstIntensityIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ assert(dstIntensityIndex == 0);
+ assert(dstComponents == 1);
+ for (i = 0; i < n; i++) {
+ /* Intensity comes from red channel */
+ CLAMPED_FLOAT_TO_CHAN(dst[i], rgba[i][RCOMP]);
+ }
+ }
+
+ if (dstLuminanceIndex >= 0) {
+ GLchan *dst = dest;
+ GLuint i;
+ assert(dstLuminanceIndex == 0);
+ for (i = 0; i < n; i++) {
+ /* Luminance comes from red channel */
+ CLAMPED_FLOAT_TO_CHAN(dst[0], rgba[i][RCOMP]);
+ dst += dstComponents;
+ }
+ }
+ }
+}
+
+
+/**
+ * Same as _mesa_unpack_color_span_chan(), but return GLfloat data
+ * instead of GLchan.
+ */
+void
+_mesa_unpack_color_span_float( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLfloat dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(dstFormat == GL_ALPHA ||
+ dstFormat == GL_LUMINANCE ||
+ dstFormat == GL_LUMINANCE_ALPHA ||
+ dstFormat == GL_INTENSITY ||
+ dstFormat == GL_RGB ||
+ dstFormat == GL_RGBA ||
+ dstFormat == GL_COLOR_INDEX);
+
+ ASSERT(srcFormat == GL_RED ||
+ srcFormat == GL_GREEN ||
+ srcFormat == GL_BLUE ||
+ srcFormat == GL_ALPHA ||
+ srcFormat == GL_LUMINANCE ||
+ srcFormat == GL_LUMINANCE_ALPHA ||
+ srcFormat == GL_INTENSITY ||
+ srcFormat == GL_RGB ||
+ srcFormat == GL_BGR ||
+ srcFormat == GL_RGBA ||
+ srcFormat == GL_BGRA ||
+ srcFormat == GL_ABGR_EXT ||
+ srcFormat == GL_COLOR_INDEX);
+
+ ASSERT(srcType == GL_BITMAP ||
+ srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT ||
+ srcType == GL_UNSIGNED_BYTE_3_3_2 ||
+ srcType == GL_UNSIGNED_BYTE_2_3_3_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5 ||
+ srcType == GL_UNSIGNED_SHORT_5_6_5_REV ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4 ||
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+ srcType == GL_UNSIGNED_SHORT_5_5_5_1 ||
+ srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV ||
+ srcType == GL_UNSIGNED_INT_10_10_10_2 ||
+ srcType == GL_UNSIGNED_INT_2_10_10_10_REV);
+
+ /* general solution, no special cases, yet */
+ {
+ GLint dstComponents;
+ GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex;
+ GLint dstLuminanceIndex, dstIntensityIndex;
+ GLfloat rgba[MAX_WIDTH][4];
+
+ dstComponents = _mesa_components_in_format( dstFormat );
+ /* source & dest image formats should have been error checked by now */
+ assert(dstComponents > 0);
+
+ /*
+ * Extract image data and convert to RGBA floats
+ */
+ assert(n <= MAX_WIDTH);
+ if (srcFormat == GL_COLOR_INDEX) {
+ GLuint indexes[MAX_WIDTH];
+ extract_uint_indexes(n, indexes, srcFormat, srcType, source,
+ srcPacking);
+
+ if (dstFormat == GL_COLOR_INDEX) {
+ GLuint i;
+ _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes);
+ /* convert to GLchan and return */
+ for (i = 0; i < n; i++) {
+ dest[i] = (GLchan) (indexes[i] & 0xff);
+ }
+ return;
+ }
+ else {
+ /* Convert indexes to RGBA */
+ if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
+ shift_and_offset_ci(ctx, n, indexes);
+ }
+ _mesa_map_ci_to_rgba(ctx, n, indexes, rgba);
+ }
+
+ /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting
+ * with color indexes.
+ */
+ transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT);
+ }
+ else {
+ /* non-color index data */
+ extract_float_rgba(n, rgba, srcFormat, srcType, source,
+ srcPacking->SwapBytes);
+ }
+
+ if (transferOps) {
+ _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba);
+ }
+
+ /* Now determine which color channels we need to produce.
+ * And determine the dest index (offset) within each color tuple.
+ */
+ switch (dstFormat) {
+ case GL_ALPHA:
+ dstAlphaIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = -1;
+ dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ case GL_LUMINANCE:
+ dstLuminanceIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1;
+ dstIntensityIndex = -1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ dstLuminanceIndex = 0;
+ dstAlphaIndex = 1;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = -1;
+ dstIntensityIndex = -1;
+ break;
+ case GL_INTENSITY:
+ dstIntensityIndex = 0;
+ dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1;
+ dstLuminanceIndex = -1;
+ break;
+ case GL_RGB:
+ dstRedIndex = 0;
+ dstGreenIndex = 1;
+ dstBlueIndex = 2;
+ dstAlphaIndex = dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ case GL_RGBA:
+ dstRedIndex = 0;
+ dstGreenIndex = 1;
+ dstBlueIndex = 2;
+ dstAlphaIndex = 3;
+ dstLuminanceIndex = dstIntensityIndex = -1;
+ break;
+ default:
+ _mesa_problem(ctx, "bad dstFormat in _mesa_unpack_color_span_float()");
+ return;
+ }
+
+ /* Now pack results in the requested dstFormat */
+ if (dstRedIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[dstRedIndex] = rgba[i][RCOMP];
+ dst += dstComponents;
+ }
+ }
+
+ if (dstGreenIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[dstGreenIndex] = rgba[i][GCOMP];
+ dst += dstComponents;
+ }
+ }
+
+ if (dstBlueIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[dstBlueIndex] = rgba[i][BCOMP];
+ dst += dstComponents;
+ }
+ }
+
+ if (dstAlphaIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[dstAlphaIndex] = rgba[i][ACOMP];
+ dst += dstComponents;
+ }
+ }
+
+ if (dstIntensityIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ assert(dstIntensityIndex == 0);
+ assert(dstComponents == 1);
+ for (i = 0; i < n; i++) {
+ /* Intensity comes from red channel */
+ dst[i] = rgba[i][RCOMP];
+ }
+ }
+
+ if (dstLuminanceIndex >= 0) {
+ GLfloat *dst = dest;
+ GLuint i;
+ assert(dstLuminanceIndex == 0);
+ for (i = 0; i < n; i++) {
+ /* Luminance comes from red channel */
+ dst[0] = rgba[i][RCOMP];
+ dst += dstComponents;
+ }
+ }
+ }
+}
+
+/**
+ * Similar to _mesa_unpack_color_span_float(), but for dudv data instead of rgba,
+ * directly return GLbyte data, no transfer ops apply.
+ */
+void
+_mesa_unpack_dudv_span_byte( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLbyte dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(dstFormat == GL_DUDV_ATI);
+ ASSERT(srcFormat == GL_DUDV_ATI);
+
+ ASSERT(srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT);
+
+ /* general solution */
+ {
+ GLint dstComponents;
+ GLfloat rgba[MAX_WIDTH][4];
+ GLbyte *dst = dest;
+ GLuint i;
+
+ dstComponents = _mesa_components_in_format( dstFormat );
+ /* source & dest image formats should have been error checked by now */
+ assert(dstComponents > 0);
+
+ /*
+ * Extract image data and convert to RGBA floats
+ */
+ assert(n <= MAX_WIDTH);
+ extract_float_rgba(n, rgba, srcFormat, srcType, source,
+ srcPacking->SwapBytes);
+
+
+ /* Now determine which color channels we need to produce.
+ * And determine the dest index (offset) within each color tuple.
+ */
+
+ /* Now pack results in the requested dstFormat */
+ for (i = 0; i < n; i++) {
+ /* not sure - need clamp[-1,1] here? */
+ dst[0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
+ dst[1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
+ dst += dstComponents;
+ }
+ }
+}
+
+/*
+ * Unpack a row of color index data from a client buffer according to
+ * the pixel unpacking parameters.
+ * This is (or will be) used by glDrawPixels, glTexImage[123]D, etc.
+ *
+ * Args: ctx - the context
+ * n - number of pixels
+ * dstType - destination data type
+ * dest - destination array
+ * srcType - source pixel type
+ * source - source data pointer
+ * srcPacking - pixel unpacking parameters
+ * transferOps - the pixel transfer operations to apply
+ */
+void
+_mesa_unpack_index_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(srcType == GL_BITMAP ||
+ srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT);
+
+ ASSERT(dstType == GL_UNSIGNED_BYTE ||
+ dstType == GL_UNSIGNED_SHORT ||
+ dstType == GL_UNSIGNED_INT);
+
+
+ transferOps &= (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT);
+
+ /*
+ * Try simple cases first
+ */
+ if (transferOps == 0 && srcType == GL_UNSIGNED_BYTE
+ && dstType == GL_UNSIGNED_BYTE) {
+ _mesa_memcpy(dest, source, n * sizeof(GLubyte));
+ }
+ else if (transferOps == 0 && srcType == GL_UNSIGNED_INT
+ && dstType == GL_UNSIGNED_INT && !srcPacking->SwapBytes) {
+ _mesa_memcpy(dest, source, n * sizeof(GLuint));
+ }
+ else {
+ /*
+ * general solution
+ */
+ GLuint indexes[MAX_WIDTH];
+ assert(n <= MAX_WIDTH);
+
+ extract_uint_indexes(n, indexes, GL_COLOR_INDEX, srcType, source,
+ srcPacking);
+
+ if (transferOps)
+ _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes);
+
+ /* convert to dest type */
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLubyte) (indexes[i] & 0xff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLushort) (indexes[i] & 0xffff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ _mesa_memcpy(dest, indexes, n * sizeof(GLuint));
+ break;
+ default:
+ _mesa_problem(ctx, "bad dstType in _mesa_unpack_index_span");
+ }
+ }
+}
+
+
+void
+_mesa_pack_index_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, const GLuint *source,
+ const struct gl_pixelstore_attrib *dstPacking,
+ GLbitfield transferOps )
+{
+ GLuint indexes[MAX_WIDTH];
+
+ ASSERT(n <= MAX_WIDTH);
+
+ transferOps &= (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT);
+
+ if (transferOps & (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT)) {
+ /* make a copy of input */
+ _mesa_memcpy(indexes, source, n * sizeof(GLuint));
+ _mesa_apply_ci_transfer_ops(ctx, transferOps, n, indexes);
+ source = indexes;
+ }
+
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ *dst++ = (GLubyte) source[i];
+ }
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLbyte) source[i];
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLushort) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLshort) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLuint) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLint) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLfloat) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLhalfARB *dst = (GLhalfARB *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = _mesa_float_to_half((GLfloat) source[i]);
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad type in _mesa_pack_index_span");
+ }
+}
+
+
+/*
+ * Unpack a row of stencil data from a client buffer according to
+ * the pixel unpacking parameters.
+ * This is (or will be) used by glDrawPixels
+ *
+ * Args: ctx - the context
+ * n - number of pixels
+ * dstType - destination data type
+ * dest - destination array
+ * srcType - source pixel type
+ * source - source data pointer
+ * srcPacking - pixel unpacking parameters
+ * transferOps - apply offset/bias/lookup ops?
+ */
+void
+_mesa_unpack_stencil_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps )
+{
+ ASSERT(srcType == GL_BITMAP ||
+ srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_BYTE ||
+ srcType == GL_UNSIGNED_SHORT ||
+ srcType == GL_SHORT ||
+ srcType == GL_UNSIGNED_INT ||
+ srcType == GL_INT ||
+ srcType == GL_UNSIGNED_INT_24_8_EXT ||
+ srcType == GL_HALF_FLOAT_ARB ||
+ srcType == GL_FLOAT);
+
+ ASSERT(dstType == GL_UNSIGNED_BYTE ||
+ dstType == GL_UNSIGNED_SHORT ||
+ dstType == GL_UNSIGNED_INT);
+
+ /* only shift and offset apply to stencil */
+ transferOps &= IMAGE_SHIFT_OFFSET_BIT;
+
+ /*
+ * Try simple cases first
+ */
+ if (transferOps == 0 &&
+ !ctx->Pixel.MapStencilFlag &&
+ srcType == GL_UNSIGNED_BYTE &&
+ dstType == GL_UNSIGNED_BYTE) {
+ _mesa_memcpy(dest, source, n * sizeof(GLubyte));
+ }
+ else if (transferOps == 0 &&
+ !ctx->Pixel.MapStencilFlag &&
+ srcType == GL_UNSIGNED_INT &&
+ dstType == GL_UNSIGNED_INT &&
+ !srcPacking->SwapBytes) {
+ _mesa_memcpy(dest, source, n * sizeof(GLuint));
+ }
+ else {
+ /*
+ * general solution
+ */
+ GLuint indexes[MAX_WIDTH];
+ assert(n <= MAX_WIDTH);
+
+ extract_uint_indexes(n, indexes, GL_STENCIL_INDEX, srcType, source,
+ srcPacking);
+
+ if (transferOps & IMAGE_SHIFT_OFFSET_BIT) {
+ /* shift and offset indexes */
+ shift_and_offset_ci(ctx, n, indexes);
+ }
+
+ if (ctx->Pixel.MapStencilFlag) {
+ /* Apply stencil lookup table */
+ const GLuint mask = ctx->PixelMaps.StoS.Size - 1;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ indexes[i] = (GLuint)ctx->PixelMaps.StoS.Map[ indexes[i] & mask ];
+ }
+ }
+
+ /* convert to dest type */
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLubyte) (indexes[i] & 0xff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = (GLushort) (indexes[i] & 0xffff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ _mesa_memcpy(dest, indexes, n * sizeof(GLuint));
+ break;
+ default:
+ _mesa_problem(ctx, "bad dstType in _mesa_unpack_stencil_span");
+ }
+ }
+}
+
+
+void
+_mesa_pack_stencil_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, const GLstencil *source,
+ const struct gl_pixelstore_attrib *dstPacking )
+{
+ GLstencil stencil[MAX_WIDTH];
+
+ ASSERT(n <= MAX_WIDTH);
+
+ if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
+ ctx->Pixel.MapStencilFlag) {
+ /* make a copy of input */
+ _mesa_memcpy(stencil, source, n * sizeof(GLstencil));
+ _mesa_apply_stencil_transfer_ops(ctx, n, stencil);
+ source = stencil;
+ }
+
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ if (sizeof(GLstencil) == 1) {
+ _mesa_memcpy( dest, source, n );
+ }
+ else {
+ GLubyte *dst = (GLubyte *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLubyte) source[i];
+ }
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLbyte) (source[i] & 0x7f);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLushort) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLshort) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLuint) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLint) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = (GLfloat) source[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLhalfARB *dst = (GLhalfARB *) dest;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ dst[i] = _mesa_float_to_half( (float) source[i] );
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_BITMAP:
+ if (dstPacking->LsbFirst) {
+ GLubyte *dst = (GLubyte *) dest;
+ GLint shift = 0;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ if (shift == 0)
+ *dst = 0;
+ *dst |= ((source[i] != 0) << shift);
+ shift++;
+ if (shift == 8) {
+ shift = 0;
+ dst++;
+ }
+ }
+ }
+ else {
+ GLubyte *dst = (GLubyte *) dest;
+ GLint shift = 7;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ if (shift == 7)
+ *dst = 0;
+ *dst |= ((source[i] != 0) << shift);
+ shift--;
+ if (shift < 0) {
+ shift = 7;
+ dst++;
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad type in _mesa_pack_index_span");
+ }
+}
+
+#define DEPTH_VALUES(GLTYPE, GLTYPE2FLOAT) \
+ do { \
+ GLuint i; \
+ const GLTYPE *src = (const GLTYPE *)source; \
+ for (i = 0; i < n; i++) { \
+ GLTYPE value = src[i]; \
+ if (srcPacking->SwapBytes) { \
+ if (sizeof(GLTYPE) == 2) { \
+ SWAP2BYTE(value); \
+ } else if (sizeof(GLTYPE) == 4) { \
+ SWAP4BYTE(value); \
+ } \
+ } \
+ depthValues[i] = GLTYPE2FLOAT(value); \
+ } \
+ } while (0)
+
+
+/**
+ * Unpack a row of depth/z values from memory, returning GLushort, GLuint
+ * or GLfloat values.
+ * The glPixelTransfer (scale/bias) params will be applied.
+ *
+ * \param dstType one of GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_FLOAT
+ * \param depthMax max value for returned GLushort or GLuint values
+ * (ignored for GLfloat).
+ */
+void
+_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, GLuint depthMax,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking )
+{
+ GLfloat depthTemp[MAX_WIDTH], *depthValues;
+ GLboolean needClamp = GL_FALSE;
+
+ /* Look for special cases first.
+ * Not only are these faster, they're less prone to numeric conversion
+ * problems. Otherwise, converting from an int type to a float then
+ * back to an int type can introduce errors that will show up as
+ * artifacts in things like depth peeling which uses glCopyTexImage.
+ */
+ if (ctx->Pixel.DepthScale == 1.0 && ctx->Pixel.DepthBias == 0.0) {
+ if (srcType == GL_UNSIGNED_INT && dstType == GL_UNSIGNED_SHORT) {
+ const GLuint *src = (const GLuint *) source;
+ GLushort *dst = (GLushort *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i] >> 16;
+ }
+ return;
+ }
+ if (srcType == GL_UNSIGNED_SHORT
+ && dstType == GL_UNSIGNED_INT
+ && depthMax == 0xffffffff) {
+ const GLushort *src = (const GLushort *) source;
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i] | (src[i] << 16);
+ }
+ return;
+ }
+ if (srcType == GL_UNSIGNED_INT_24_8
+ && dstType == GL_UNSIGNED_INT
+ && depthMax == 0xffffff) {
+ const GLuint *src = (const GLuint *) source;
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i] >> 8;
+ }
+ return;
+ }
+ /* XXX may want to add additional cases here someday */
+ }
+
+ /* general case path follows */
+
+ if (dstType == GL_FLOAT) {
+ depthValues = (GLfloat *) dest;
+ }
+ else {
+ depthValues = depthTemp;
+ }
+
+ /* Convert incoming values to GLfloat. Some conversions will require
+ * clamping, below.
+ */
+ switch (srcType) {
+ case GL_BYTE:
+ DEPTH_VALUES(GLbyte, BYTE_TO_FLOAT);
+ needClamp = GL_TRUE;
+ break;
+ case GL_UNSIGNED_BYTE:
+ DEPTH_VALUES(GLubyte, UBYTE_TO_FLOAT);
+ break;
+ case GL_SHORT:
+ DEPTH_VALUES(GLshort, SHORT_TO_FLOAT);
+ needClamp = GL_TRUE;
+ break;
+ case GL_UNSIGNED_SHORT:
+ DEPTH_VALUES(GLushort, USHORT_TO_FLOAT);
+ break;
+ case GL_INT:
+ DEPTH_VALUES(GLint, INT_TO_FLOAT);
+ needClamp = GL_TRUE;
+ break;
+ case GL_UNSIGNED_INT:
+ DEPTH_VALUES(GLuint, UINT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_INT_24_8_EXT: /* GL_EXT_packed_depth_stencil */
+ if (dstType == GL_UNSIGNED_INT_24_8_EXT &&
+ depthMax == 0xffffff &&
+ ctx->Pixel.DepthScale == 1.0 &&
+ ctx->Pixel.DepthBias == 0.0) {
+ const GLuint *src = (const GLuint *) source;
+ GLuint *zValues = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLuint value = src[i];
+ if (srcPacking->SwapBytes) {
+ SWAP4BYTE(value);
+ }
+ zValues[i] = value & 0xffffff00;
+ }
+ return;
+ }
+ else {
+ const GLuint *src = (const GLuint *) source;
+ const GLfloat scale = 1.0f / 0xffffff;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLuint value = src[i];
+ if (srcPacking->SwapBytes) {
+ SWAP4BYTE(value);
+ }
+ depthValues[i] = (value >> 8) * scale;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ DEPTH_VALUES(GLfloat, 1*);
+ needClamp = GL_TRUE;
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLuint i;
+ const GLhalfARB *src = (const GLhalfARB *) source;
+ for (i = 0; i < n; i++) {
+ GLhalfARB value = src[i];
+ if (srcPacking->SwapBytes) {
+ SWAP2BYTE(value);
+ }
+ depthValues[i] = _mesa_half_to_float(value);
+ }
+ needClamp = GL_TRUE;
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()");
+ return;
+ }
+
+ /* apply depth scale and bias */
+ {
+ const GLfloat scale = ctx->Pixel.DepthScale;
+ const GLfloat bias = ctx->Pixel.DepthBias;
+ if (scale != 1.0 || bias != 0.0) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ depthValues[i] = depthValues[i] * scale + bias;
+ }
+ needClamp = GL_TRUE;
+ }
+ }
+
+ /* clamp to [0, 1] */
+ if (needClamp) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ depthValues[i] = (GLfloat)CLAMP(depthValues[i], 0.0, 1.0);
+ }
+ }
+
+ /*
+ * Convert values to dstType
+ */
+ if (dstType == GL_UNSIGNED_INT) {
+ GLuint *zValues = (GLuint *) dest;
+ GLuint i;
+ if (depthMax <= 0xffffff) {
+ /* no overflow worries */
+ for (i = 0; i < n; i++) {
+ zValues[i] = (GLuint) (depthValues[i] * (GLfloat) depthMax);
+ }
+ }
+ else {
+ /* need to use double precision to prevent overflow problems */
+ for (i = 0; i < n; i++) {
+ GLdouble z = depthValues[i] * (GLfloat) depthMax;
+ if (z >= (GLdouble) 0xffffffff)
+ zValues[i] = 0xffffffff;
+ else
+ zValues[i] = (GLuint) z;
+ }
+ }
+ }
+ else if (dstType == GL_UNSIGNED_SHORT) {
+ GLushort *zValues = (GLushort *) dest;
+ GLuint i;
+ ASSERT(depthMax <= 0xffff);
+ for (i = 0; i < n; i++) {
+ zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax);
+ }
+ }
+ else {
+ ASSERT(dstType == GL_FLOAT);
+ /*ASSERT(depthMax == 1.0F);*/
+ }
+}
+
+
+/*
+ * Pack an array of depth values. The values are floats in [0,1].
+ */
+void
+_mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest,
+ GLenum dstType, const GLfloat *depthSpan,
+ const struct gl_pixelstore_attrib *dstPacking )
+{
+ GLfloat depthCopy[MAX_WIDTH];
+
+ ASSERT(n <= MAX_WIDTH);
+
+ if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) {
+ _mesa_memcpy(depthCopy, depthSpan, n * sizeof(GLfloat));
+ _mesa_scale_and_bias_depth(ctx, n, depthCopy);
+ depthSpan = depthCopy;
+ }
+
+ switch (dstType) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = FLOAT_TO_UBYTE( depthSpan[i] );
+ }
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = FLOAT_TO_BYTE( depthSpan[i] );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ CLAMPED_FLOAT_TO_USHORT(dst[i], depthSpan[i]);
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = FLOAT_TO_SHORT( depthSpan[i] );
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = FLOAT_TO_UINT( depthSpan[i] );
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = FLOAT_TO_INT( depthSpan[i] );
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = depthSpan[i];
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_HALF_FLOAT_ARB:
+ {
+ GLhalfARB *dst = (GLhalfARB *) dest;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dst[i] = _mesa_float_to_half(depthSpan[i]);
+ }
+ if (dstPacking->SwapBytes) {
+ _mesa_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "bad type in _mesa_pack_depth_span");
+ }
+}
+
+
+
+/**
+ * Pack depth and stencil values as GL_DEPTH_STENCIL/GL_UNSIGNED_INT_24_8.
+ */
+void
+_mesa_pack_depth_stencil_span(const GLcontext *ctx, GLuint n, GLuint *dest,
+ const GLfloat *depthVals,
+ const GLstencil *stencilVals,
+ const struct gl_pixelstore_attrib *dstPacking)
+{
+ GLfloat depthCopy[MAX_WIDTH];
+ GLstencil stencilCopy[MAX_WIDTH];
+ GLuint i;
+
+ ASSERT(n <= MAX_WIDTH);
+
+ if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) {
+ _mesa_memcpy(depthCopy, depthVals, n * sizeof(GLfloat));
+ _mesa_scale_and_bias_depth(ctx, n, depthCopy);
+ depthVals = depthCopy;
+ }
+
+ if (ctx->Pixel.IndexShift ||
+ ctx->Pixel.IndexOffset ||
+ ctx->Pixel.MapStencilFlag) {
+ _mesa_memcpy(stencilCopy, stencilVals, n * sizeof(GLstencil));
+ _mesa_apply_stencil_transfer_ops(ctx, n, stencilCopy);
+ stencilVals = stencilCopy;
+ }
+
+ for (i = 0; i < n; i++) {
+ GLuint z = (GLuint) (depthVals[i] * 0xffffff);
+ dest[i] = (z << 8) | (stencilVals[i] & 0xff);
+ }
+
+ if (dstPacking->SwapBytes) {
+ _mesa_swap4(dest, n);
+ }
+}
+
+
+
+
+/**
+ * Unpack image data. Apply byte swapping, byte flipping (bitmap).
+ * Return all image data in a contiguous block. This is used when we
+ * compile glDrawPixels, glTexImage, etc into a display list. We
+ * need a copy of the data in a standard format.
+ */
+void *
+_mesa_unpack_image( GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack )
+{
+ GLint bytesPerRow, compsPerRow;
+ GLboolean flipBytes, swap2, swap4;
+
+ if (!pixels)
+ return NULL; /* not necessarily an error */
+
+ if (width <= 0 || height <= 0 || depth <= 0)
+ return NULL; /* generate error later */
+
+ if (type == GL_BITMAP) {
+ bytesPerRow = (width + 7) >> 3;
+ flipBytes = unpack->LsbFirst;
+ swap2 = swap4 = GL_FALSE;
+ compsPerRow = 0;
+ }
+ else {
+ const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
+ GLint components = _mesa_components_in_format(format);
+ GLint bytesPerComp;
+
+ if (_mesa_type_is_packed(type))
+ components = 1;
+
+ if (bytesPerPixel <= 0 || components <= 0)
+ return NULL; /* bad format or type. generate error later */
+ bytesPerRow = bytesPerPixel * width;
+ bytesPerComp = bytesPerPixel / components;
+ flipBytes = GL_FALSE;
+ swap2 = (bytesPerComp == 2) && unpack->SwapBytes;
+ swap4 = (bytesPerComp == 4) && unpack->SwapBytes;
+ compsPerRow = components * width;
+ assert(compsPerRow >= width);
+ }
+
+ {
+ GLubyte *destBuffer
+ = (GLubyte *) _mesa_malloc(bytesPerRow * height * depth);
+ GLubyte *dst;
+ GLint img, row;
+ if (!destBuffer)
+ return NULL; /* generate GL_OUT_OF_MEMORY later */
+
+ dst = destBuffer;
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels,
+ width, height, format, type, img, row, 0);
+
+ if ((type == GL_BITMAP) && (unpack->SkipPixels & 0x7)) {
+ GLint i;
+ flipBytes = GL_FALSE;
+ if (unpack->LsbFirst) {
+ GLubyte srcMask = 1 << (unpack->SkipPixels & 0x7);
+ GLubyte dstMask = 128;
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 128) {
+ srcMask = 1;
+ s++;
+ }
+ else {
+ srcMask = srcMask << 1;
+ }
+ if (dstMask == 1) {
+ dstMask = 128;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask >> 1;
+ }
+ }
+ }
+ else {
+ GLubyte srcMask = 128 >> (unpack->SkipPixels & 0x7);
+ GLubyte dstMask = 128;
+ const GLubyte *s = src;
+ GLubyte *d = dst;
+ *d = 0;
+ for (i = 0; i < width; i++) {
+ if (*s & srcMask) {
+ *d |= dstMask;
+ }
+ if (srcMask == 1) {
+ srcMask = 128;
+ s++;
+ }
+ else {
+ srcMask = srcMask >> 1;
+ }
+ if (dstMask == 1) {
+ dstMask = 128;
+ d++;
+ *d = 0;
+ }
+ else {
+ dstMask = dstMask >> 1;
+ }
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, bytesPerRow);
+ }
+
+ /* byte flipping/swapping */
+ if (flipBytes) {
+ flip_bytes((GLubyte *) dst, bytesPerRow);
+ }
+ else if (swap2) {
+ _mesa_swap2((GLushort*) dst, compsPerRow);
+ }
+ else if (swap4) {
+ _mesa_swap4((GLuint*) dst, compsPerRow);
+ }
+ dst += bytesPerRow;
+ }
+ }
+ return destBuffer;
+ }
+}
+
+#endif /* _HAVE_FULL_GL */
+
+
+
+/**
+ * Convert an array of RGBA colors from one datatype to another.
+ * NOTE: src may equal dst. In that case, we use a temporary buffer.
+ */
+void
+_mesa_convert_colors(GLenum srcType, const GLvoid *src,
+ GLenum dstType, GLvoid *dst,
+ GLuint count, const GLubyte mask[])
+{
+ GLuint tempBuffer[MAX_WIDTH][4];
+ const GLboolean useTemp = (src == dst);
+
+ ASSERT(srcType != dstType);
+
+ switch (srcType) {
+ case GL_UNSIGNED_BYTE:
+ if (dstType == GL_UNSIGNED_SHORT) {
+ const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
+ GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
+ dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
+ dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
+ dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
+ }
+ else {
+ const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
+ GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ ASSERT(dstType == GL_FLOAT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
+ dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
+ dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
+ dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (dstType == GL_UNSIGNED_BYTE) {
+ const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
+ GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
+ dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
+ dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
+ dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
+ }
+ else {
+ const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
+ GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ ASSERT(dstType == GL_FLOAT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
+ dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
+ dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
+ dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
+ }
+ break;
+ case GL_FLOAT:
+ if (dstType == GL_UNSIGNED_BYTE) {
+ const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
+ GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
+ }
+ else {
+ const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
+ GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
+ GLuint i;
+ ASSERT(dstType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
+ }
+ }
+ if (useTemp)
+ _mesa_memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
+ }
+}
+
+
+
+
+/**
+ * Perform basic clipping for glDrawPixels. The image's position and size
+ * and the unpack SkipPixels and SkipRows are adjusted so that the image
+ * region is entirely within the window and scissor bounds.
+ * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
+ * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
+ * we'll actually write. Beforehand, *destY-1 is the first drawing row.
+ *
+ * \return GL_TRUE if image is ready for drawing or
+ * GL_FALSE if image was completely clipped away (draw nothing)
+ */
+GLboolean
+_mesa_clip_drawpixels(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLsizei *width, GLsizei *height,
+ struct gl_pixelstore_attrib *unpack)
+{
+ const GLframebuffer *buffer = ctx->DrawBuffer;
+
+ if (unpack->RowLength == 0) {
+ unpack->RowLength = *width;
+ }
+
+ ASSERT(ctx->Pixel.ZoomX == 1.0F);
+ ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
+
+ /* left clipping */
+ if (*destX < buffer->_Xmin) {
+ unpack->SkipPixels += (buffer->_Xmin - *destX);
+ *width -= (buffer->_Xmin - *destX);
+ *destX = buffer->_Xmin;
+ }
+ /* right clipping */
+ if (*destX + *width > buffer->_Xmax)
+ *width -= (*destX + *width - buffer->_Xmax);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ if (ctx->Pixel.ZoomY == 1.0F) {
+ /* bottom clipping */
+ if (*destY < buffer->_Ymin) {
+ unpack->SkipRows += (buffer->_Ymin - *destY);
+ *height -= (buffer->_Ymin - *destY);
+ *destY = buffer->_Ymin;
+ }
+ /* top clipping */
+ if (*destY + *height > buffer->_Ymax)
+ *height -= (*destY + *height - buffer->_Ymax);
+ }
+ else { /* upside down */
+ /* top clipping */
+ if (*destY > buffer->_Ymax) {
+ unpack->SkipRows += (*destY - buffer->_Ymax);
+ *height -= (*destY - buffer->_Ymax);
+ *destY = buffer->_Ymax;
+ }
+ /* bottom clipping */
+ if (*destY - *height < buffer->_Ymin)
+ *height -= (buffer->_Ymin - (*destY - *height));
+ /* adjust destY so it's the first row to write to */
+ (*destY)--;
+ }
+
+ if (*height <= 0)
+ return GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Perform clipping for glReadPixels. The image's window position
+ * and size, and the pack skipPixels, skipRows and rowLength are adjusted
+ * so that the image region is entirely within the window bounds.
+ * Note: this is different from _mesa_clip_drawpixels() in that the
+ * scissor box is ignored, and we use the bounds of the current readbuffer
+ * surface.
+ *
+ * \return GL_TRUE if image is ready for drawing or
+ * GL_FALSE if image was completely clipped away (draw nothing)
+ */
+GLboolean
+_mesa_clip_readpixels(const GLcontext *ctx,
+ GLint *srcX, GLint *srcY,
+ GLsizei *width, GLsizei *height,
+ struct gl_pixelstore_attrib *pack)
+{
+ const GLframebuffer *buffer = ctx->ReadBuffer;
+
+ if (pack->RowLength == 0) {
+ pack->RowLength = *width;
+ }
+
+ /* left clipping */
+ if (*srcX < 0) {
+ pack->SkipPixels += (0 - *srcX);
+ *width -= (0 - *srcX);
+ *srcX = 0;
+ }
+ /* right clipping */
+ if (*srcX + *width > (GLsizei) buffer->Width)
+ *width -= (*srcX + *width - buffer->Width);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*srcY < 0) {
+ pack->SkipRows += (0 - *srcY);
+ *height -= (0 - *srcY);
+ *srcY = 0;
+ }
+ /* top clipping */
+ if (*srcY + *height > (GLsizei) buffer->Height)
+ *height -= (*srcY + *height - buffer->Height);
+
+ if (*height <= 0)
+ return GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do clipping for a glCopyTexSubImage call.
+ * The framebuffer source region might extend outside the framebuffer
+ * bounds. Clip the source region against the framebuffer bounds and
+ * adjust the texture/dest position and size accordingly.
+ *
+ * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
+ */
+GLboolean
+_mesa_clip_copytexsubimage(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLint *srcX, GLint *srcY,
+ GLsizei *width, GLsizei *height)
+{
+ const struct gl_framebuffer *fb = ctx->ReadBuffer;
+ const GLint srcX0 = *srcX, srcY0 = *srcY;
+
+ if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
+ srcX, srcY, width, height)) {
+ *destX = *destX + *srcX - srcX0;
+ *destY = *destY + *srcY - srcY0;
+
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/**
+ * Clip the rectangle defined by (x, y, width, height) against the bounds
+ * specified by [xmin, xmax) and [ymin, ymax).
+ * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
+ */
+GLboolean
+_mesa_clip_to_region(GLint xmin, GLint ymin,
+ GLint xmax, GLint ymax,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height )
+{
+ /* left clipping */
+ if (*x < xmin) {
+ *width -= (xmin - *x);
+ *x = xmin;
+ }
+
+ /* right clipping */
+ if (*x + *width > xmax)
+ *width -= (*x + *width - xmax);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom (or top) clipping */
+ if (*y < ymin) {
+ *height -= (ymin - *y);
+ *y = ymin;
+ }
+
+ /* top (or bottom) clipping */
+ if (*y + *height > ymax)
+ *height -= (*y + *height - ymax);
+
+ if (*height <= 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Clip dst coords against Xmax (or Ymax).
+ */
+static INLINE void
+clip_right_or_top(GLint *srcX0, GLint *srcX1,
+ GLint *dstX0, GLint *dstX1,
+ GLint maxValue)
+{
+ GLfloat t, bias;
+
+ if (*dstX1 > maxValue) {
+ /* X1 outside right edge */
+ ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */
+ t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
+ /* chop off [t, 1] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX1 = maxValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
+ *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
+ }
+ else if (*dstX0 > maxValue) {
+ /* X0 outside right edge */
+ ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */
+ t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
+ /* chop off [t, 1] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX0 = maxValue;
+ bias = (*srcX0 < *srcX1) ? -0.5 : 0.5;
+ *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
+ }
+}
+
+
+/**
+ * Clip dst coords against Xmin (or Ymin).
+ */
+static INLINE void
+clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
+ GLint *dstX0, GLint *dstX1,
+ GLint minValue)
+{
+ GLfloat t, bias;
+
+ if (*dstX0 < minValue) {
+ /* X0 outside left edge */
+ ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */
+ t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
+ /* chop off [0, t] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX0 = minValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5; /* flipped??? */
+ *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
+ }
+ else if (*dstX1 < minValue) {
+ /* X1 outside left edge */
+ ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */
+ t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
+ /* chop off [0, t] part */
+ ASSERT(t >= 0.0 && t <= 1.0);
+ *dstX1 = minValue;
+ bias = (*srcX0 < *srcX1) ? 0.5 : -0.5;
+ *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
+ }
+}
+
+
+/**
+ * Do clipping of blit src/dest rectangles.
+ * The dest rect is clipped against both the buffer bounds and scissor bounds.
+ * The src rect is just clipped against the buffer bounds.
+ *
+ * When either the src or dest rect is clipped, the other is also clipped
+ * proportionately!
+ *
+ * Note that X0 need not be less than X1 (same for Y) for either the source
+ * and dest rects. That makes the clipping a little trickier.
+ *
+ * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
+ */
+GLboolean
+_mesa_clip_blit(GLcontext *ctx,
+ GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
+ GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
+{
+ const GLint srcXmin = 0;
+ const GLint srcXmax = ctx->ReadBuffer->Width;
+ const GLint srcYmin = 0;
+ const GLint srcYmax = ctx->ReadBuffer->Height;
+
+ /* these include scissor bounds */
+ const GLint dstXmin = ctx->DrawBuffer->_Xmin;
+ const GLint dstXmax = ctx->DrawBuffer->_Xmax;
+ const GLint dstYmin = ctx->DrawBuffer->_Ymin;
+ const GLint dstYmax = ctx->DrawBuffer->_Ymax;
+
+ /*
+ printf("PreClipX: src: %d .. %d dst: %d .. %d\n",
+ *srcX0, *srcX1, *dstX0, *dstX1);
+ printf("PreClipY: src: %d .. %d dst: %d .. %d\n",
+ *srcY0, *srcY1, *dstY0, *dstY1);
+ */
+
+ /* trivial rejection tests */
+ if (*dstX0 == *dstX1)
+ return GL_FALSE; /* no width */
+ if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
+ return GL_FALSE; /* totally out (left) of bounds */
+ if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
+ return GL_FALSE; /* totally out (right) of bounds */
+
+ if (*dstY0 == *dstY1)
+ return GL_FALSE;
+ if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
+ return GL_FALSE;
+ if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
+ return GL_FALSE;
+
+ if (*srcX0 == *srcX1)
+ return GL_FALSE;
+ if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
+ return GL_FALSE;
+ if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
+ return GL_FALSE;
+
+ if (*srcY0 == *srcY1)
+ return GL_FALSE;
+ if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
+ return GL_FALSE;
+ if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
+ return GL_FALSE;
+
+ /*
+ * dest clip
+ */
+ clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
+ clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
+ clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
+ clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
+
+ /*
+ * src clip (just swap src/dst values from above)
+ */
+ clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
+ clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
+ clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
+ clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
+
+ /*
+ printf("PostClipX: src: %d .. %d dst: %d .. %d\n",
+ *srcX0, *srcX1, *dstX0, *dstX1);
+ printf("PostClipY: src: %d .. %d dst: %d .. %d\n",
+ *srcY0, *srcY1, *dstY0, *dstY1);
+ */
+
+ ASSERT(*dstX0 >= dstXmin);
+ ASSERT(*dstX0 <= dstXmax);
+ ASSERT(*dstX1 >= dstXmin);
+ ASSERT(*dstX1 <= dstXmax);
+
+ ASSERT(*dstY0 >= dstYmin);
+ ASSERT(*dstY0 <= dstYmax);
+ ASSERT(*dstY1 >= dstYmin);
+ ASSERT(*dstY1 <= dstYmax);
+
+ ASSERT(*srcX0 >= srcXmin);
+ ASSERT(*srcX0 <= srcXmax);
+ ASSERT(*srcX1 >= srcXmin);
+ ASSERT(*srcX1 <= srcXmax);
+
+ ASSERT(*srcY0 >= srcYmin);
+ ASSERT(*srcY0 <= srcYmax);
+ ASSERT(*srcY1 >= srcYmin);
+ ASSERT(*srcY1 <= srcYmax);
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/main/image.h b/mesalib/src/mesa/main/image.h
new file mode 100644
index 000000000..72717d678
--- /dev/null
+++ b/mesalib/src/mesa/main/image.h
@@ -0,0 +1,328 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "mtypes.h"
+
+
+extern void
+_mesa_swap2( GLushort *p, GLuint n );
+
+extern void
+_mesa_swap4( GLuint *p, GLuint n );
+
+extern GLboolean
+_mesa_type_is_packed(GLenum type);
+
+extern GLint
+_mesa_sizeof_type( GLenum type );
+
+extern GLint
+_mesa_sizeof_packed_type( GLenum type );
+
+extern GLint
+_mesa_components_in_format( GLenum format );
+
+extern GLint
+_mesa_bytes_per_pixel( GLenum format, GLenum type );
+
+extern GLboolean
+_mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type );
+
+extern GLboolean
+_mesa_is_color_format(GLenum format);
+
+extern GLboolean
+_mesa_is_index_format(GLenum format);
+
+extern GLboolean
+_mesa_is_depth_format(GLenum format);
+
+extern GLboolean
+_mesa_is_stencil_format(GLenum format);
+
+extern GLboolean
+_mesa_is_ycbcr_format(GLenum format);
+
+extern GLboolean
+_mesa_is_depthstencil_format(GLenum format);
+
+extern GLboolean
+_mesa_is_dudv_format(GLenum format);
+
+
+extern GLvoid *
+_mesa_image_address( GLuint dimensions,
+ const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint img, GLint row, GLint column );
+
+extern GLvoid *
+_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width,
+ GLenum format, GLenum type,
+ GLint column );
+
+extern GLvoid *
+_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint row, GLint column );
+
+extern GLvoid *
+_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLint img, GLint row, GLint column );
+
+
+extern GLint
+_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
+ GLint width, GLenum format, GLenum type );
+
+
+extern GLint
+_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
+ GLint width, GLint height,
+ GLenum format, GLenum type );
+
+extern void
+_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32],
+ const struct gl_pixelstore_attrib *unpacking );
+
+
+extern void
+_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest,
+ const struct gl_pixelstore_attrib *packing );
+
+
+extern GLvoid *
+_mesa_unpack_bitmap( GLint width, GLint height, const GLubyte *pixels,
+ const struct gl_pixelstore_attrib *packing );
+
+extern void
+_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source,
+ GLubyte *dest, const struct gl_pixelstore_attrib *packing );
+
+extern void
+_mesa_expand_bitmap(GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap,
+ GLubyte *destBuffer, GLint destStride,
+ GLubyte onValue);
+
+
+/** \name Pixel processing functions */
+/*@{*/
+
+extern void
+_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4],
+ GLfloat rScale, GLfloat gScale,
+ GLfloat bScale, GLfloat aScale,
+ GLfloat rBias, GLfloat gBias,
+ GLfloat bBias, GLfloat aBias);
+
+extern void
+_mesa_map_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4]);
+
+
+extern void
+_mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4]);
+
+
+extern void
+_mesa_lookup_rgba_float(const struct gl_color_table *table,
+ GLuint n, GLfloat rgba[][4]);
+
+extern void
+_mesa_lookup_rgba_ubyte(const struct gl_color_table *table,
+ GLuint n, GLubyte rgba[][4]);
+
+
+extern void
+_mesa_map_ci_to_rgba(const GLcontext *ctx,
+ GLuint n, const GLuint index[], GLfloat rgba[][4]);
+
+
+extern void
+_mesa_map_ci8_to_rgba8(const GLcontext *ctx, GLuint n, const GLubyte index[],
+ GLubyte rgba[][4]);
+
+
+extern void
+_mesa_scale_and_bias_depth(const GLcontext *ctx, GLuint n,
+ GLfloat depthValues[]);
+
+extern void
+_mesa_scale_and_bias_depth_uint(const GLcontext *ctx, GLuint n,
+ GLuint depthValues[]);
+
+extern void
+_mesa_apply_rgba_transfer_ops(GLcontext *ctx, GLbitfield transferOps,
+ GLuint n, GLfloat rgba[][4]);
+
+
+extern void
+_mesa_apply_ci_transfer_ops(const GLcontext *ctx, GLbitfield transferOps,
+ GLuint n, GLuint indexes[]);
+
+
+extern void
+_mesa_apply_stencil_transfer_ops(const GLcontext *ctx, GLuint n,
+ GLstencil stencil[]);
+
+
+extern void
+_mesa_pack_rgba_span_float( GLcontext *ctx, GLuint n, GLfloat rgba[][4],
+ GLenum dstFormat, GLenum dstType, GLvoid *dstAddr,
+ const struct gl_pixelstore_attrib *dstPacking,
+ GLbitfield transferOps );
+
+
+extern void
+_mesa_unpack_color_span_chan( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLchan dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
+
+
+extern void
+_mesa_unpack_color_span_float( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLfloat dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
+
+extern void
+_mesa_unpack_dudv_span_byte( GLcontext *ctx,
+ GLuint n, GLenum dstFormat, GLbyte dest[],
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
+
+extern void
+_mesa_unpack_index_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
+
+
+extern void
+_mesa_pack_index_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, const GLuint *source,
+ const struct gl_pixelstore_attrib *dstPacking,
+ GLbitfield transferOps );
+
+
+extern void
+_mesa_unpack_stencil_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking,
+ GLbitfield transferOps );
+
+extern void
+_mesa_pack_stencil_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, const GLstencil *source,
+ const struct gl_pixelstore_attrib *dstPacking );
+
+
+extern void
+_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n,
+ GLenum dstType, GLvoid *dest, GLuint depthMax,
+ GLenum srcType, const GLvoid *source,
+ const struct gl_pixelstore_attrib *srcPacking );
+
+extern void
+_mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest,
+ GLenum dstType, const GLfloat *depthSpan,
+ const struct gl_pixelstore_attrib *dstPacking );
+
+
+extern void
+_mesa_pack_depth_stencil_span(const GLcontext *ctx, GLuint n, GLuint *dest,
+ const GLfloat *depthVals,
+ const GLstencil *stencilVals,
+ const struct gl_pixelstore_attrib *dstPacking);
+
+
+extern void *
+_mesa_unpack_image( GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack );
+
+
+extern void
+_mesa_convert_colors(GLenum srcType, const GLvoid *src,
+ GLenum dstType, GLvoid *dst,
+ GLuint count, const GLubyte mask[]);
+
+
+extern GLboolean
+_mesa_clip_drawpixels(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLsizei *width, GLsizei *height,
+ struct gl_pixelstore_attrib *unpack);
+
+
+extern GLboolean
+_mesa_clip_readpixels(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLsizei *width, GLsizei *height,
+ struct gl_pixelstore_attrib *pack);
+
+extern GLboolean
+_mesa_clip_copytexsubimage(const GLcontext *ctx,
+ GLint *destX, GLint *destY,
+ GLint *srcX, GLint *srcY,
+ GLsizei *width, GLsizei *height);
+
+extern GLboolean
+_mesa_clip_to_region(GLint xmin, GLint ymin,
+ GLint xmax, GLint ymax,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height );
+
+extern GLboolean
+_mesa_clip_blit(GLcontext *ctx,
+ GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
+ GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c
new file mode 100644
index 000000000..6ffaddcde
--- /dev/null
+++ b/mesalib/src/mesa/main/imports.c
@@ -0,0 +1,1231 @@
+/**
+ * \file imports.c
+ * Standard C library function wrappers.
+ *
+ * Imports are services which the device driver or window system or
+ * operating system provides to the core renderer. The core renderer (Mesa)
+ * will call these functions in order to do memory allocation, simple I/O,
+ * etc.
+ *
+ * Some drivers will want to override/replace this file with something
+ * specialized, but that'll be rare.
+ *
+ * Eventually, I want to move roll the glheader.h file into this.
+ *
+ * \todo Functions still needed:
+ * - scanf
+ * - qsort
+ * - rand and RAND_MAX
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "imports.h"
+#include "context.h"
+#include "version.h"
+
+
+#define MAXSTRING 4000 /* for vsnprintf() */
+
+#ifdef WIN32
+#define vsnprintf _vsnprintf
+#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 )
+extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
+#ifdef __VMS
+#include "vsnprintf.c"
+#endif
+#endif
+
+/**********************************************************************/
+/** \name Memory */
+/*@{*/
+
+/** Wrapper around malloc() */
+void *
+_mesa_malloc(size_t bytes)
+{
+ return malloc(bytes);
+}
+
+/** Wrapper around calloc() */
+void *
+_mesa_calloc(size_t bytes)
+{
+ return calloc(1, bytes);
+}
+
+/** Wrapper around free() */
+void
+_mesa_free(void *ptr)
+{
+ free(ptr);
+}
+
+/**
+ * Allocate aligned memory.
+ *
+ * \param bytes number of bytes to allocate.
+ * \param alignment alignment (must be greater than zero).
+ *
+ * Allocates extra memory to accommodate rounding up the address for
+ * alignment and to record the real malloc address.
+ *
+ * \sa _mesa_align_free().
+ */
+void *
+_mesa_align_malloc(size_t bytes, unsigned long alignment)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *mem;
+
+ (void) posix_memalign(& mem, alignment, bytes);
+ return mem;
+#elif defined(_WIN32) && defined(_MSC_VER)
+ return _aligned_malloc(bytes, alignment);
+#else
+ uintptr_t ptr, buf;
+
+ ASSERT( alignment > 0 );
+
+ ptr = (uintptr_t) _mesa_malloc(bytes + alignment + sizeof(void *));
+ if (!ptr)
+ return NULL;
+
+ buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
+ *(uintptr_t *)(buf - sizeof(void *)) = ptr;
+
+#ifdef DEBUG
+ /* mark the non-aligned area */
+ while ( ptr < buf - sizeof(void *) ) {
+ *(unsigned long *)ptr = 0xcdcdcdcd;
+ ptr += sizeof(unsigned long);
+ }
+#endif
+
+ return (void *) buf;
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Same as _mesa_align_malloc(), but using _mesa_calloc() instead of
+ * _mesa_malloc()
+ */
+void *
+_mesa_align_calloc(size_t bytes, unsigned long alignment)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *mem;
+
+ mem = _mesa_align_malloc(bytes, alignment);
+ if (mem != NULL) {
+ (void) memset(mem, 0, bytes);
+ }
+
+ return mem;
+#elif defined(_WIN32) && defined(_MSC_VER)
+ void *mem;
+
+ mem = _aligned_malloc(bytes, alignment);
+ if (mem != NULL) {
+ (void) memset(mem, 0, bytes);
+ }
+
+ return mem;
+#else
+ uintptr_t ptr, buf;
+
+ ASSERT( alignment > 0 );
+
+ ptr = (uintptr_t) _mesa_calloc(bytes + alignment + sizeof(void *));
+ if (!ptr)
+ return NULL;
+
+ buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
+ *(uintptr_t *)(buf - sizeof(void *)) = ptr;
+
+#ifdef DEBUG
+ /* mark the non-aligned area */
+ while ( ptr < buf - sizeof(void *) ) {
+ *(unsigned long *)ptr = 0xcdcdcdcd;
+ ptr += sizeof(unsigned long);
+ }
+#endif
+
+ return (void *)buf;
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Free memory which was allocated with either _mesa_align_malloc()
+ * or _mesa_align_calloc().
+ * \param ptr pointer to the memory to be freed.
+ * The actual address to free is stored in the word immediately before the
+ * address the client sees.
+ */
+void
+_mesa_align_free(void *ptr)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ free(ptr);
+#elif defined(_WIN32) && defined(_MSC_VER)
+ _aligned_free(ptr);
+#else
+ void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
+ void *realAddr = *cubbyHole;
+ _mesa_free(realAddr);
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Reallocate memory, with alignment.
+ */
+void *
+_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
+ unsigned long alignment)
+{
+#if defined(_WIN32) && defined(_MSC_VER)
+ (void) oldSize;
+ return _aligned_realloc(oldBuffer, newSize, alignment);
+#else
+ const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
+ void *newBuf = _mesa_align_malloc(newSize, alignment);
+ if (newBuf && oldBuffer && copySize > 0) {
+ _mesa_memcpy(newBuf, oldBuffer, copySize);
+ }
+ if (oldBuffer)
+ _mesa_align_free(oldBuffer);
+ return newBuf;
+#endif
+}
+
+
+
+/** Reallocate memory */
+void *
+_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
+{
+ const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
+ void *newBuffer = _mesa_malloc(newSize);
+ if (newBuffer && oldBuffer && copySize > 0)
+ _mesa_memcpy(newBuffer, oldBuffer, copySize);
+ if (oldBuffer)
+ _mesa_free(oldBuffer);
+ return newBuffer;
+}
+
+/** memcpy wrapper */
+void *
+_mesa_memcpy(void *dest, const void *src, size_t n)
+{
+#if defined(SUNOS4)
+ return memcpy((char *) dest, (char *) src, (int) n);
+#else
+ return memcpy(dest, src, n);
+#endif
+}
+
+/** Wrapper around memset() */
+void
+_mesa_memset( void *dst, int val, size_t n )
+{
+#if defined(SUNOS4)
+ memset( (char *) dst, (int) val, (int) n );
+#else
+ memset(dst, val, n);
+#endif
+}
+
+/**
+ * Fill memory with a constant 16bit word.
+ * \param dst destination pointer.
+ * \param val value.
+ * \param n number of words.
+ */
+void
+_mesa_memset16( unsigned short *dst, unsigned short val, size_t n )
+{
+ while (n-- > 0)
+ *dst++ = val;
+}
+
+/** Wrapper around either memset() or bzero() */
+void
+_mesa_bzero( void *dst, size_t n )
+{
+#if defined(__FreeBSD__)
+ bzero( dst, n );
+#else
+ memset( dst, 0, n );
+#endif
+}
+
+/** Wrapper around memcmp() */
+int
+_mesa_memcmp( const void *s1, const void *s2, size_t n )
+{
+#if defined(SUNOS4)
+ return memcmp( (char *) s1, (char *) s2, (int) n );
+#else
+ return memcmp(s1, s2, n);
+#endif
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Math */
+/*@{*/
+
+/** Wrapper around sin() */
+double
+_mesa_sin(double a)
+{
+ return sin(a);
+}
+
+/** Single precision wrapper around sin() */
+float
+_mesa_sinf(float a)
+{
+ return (float) sin((double) a);
+}
+
+/** Wrapper around cos() */
+double
+_mesa_cos(double a)
+{
+ return cos(a);
+}
+
+/** Single precision wrapper around asin() */
+float
+_mesa_asinf(float x)
+{
+ return (float) asin((double) x);
+}
+
+/** Single precision wrapper around atan() */
+float
+_mesa_atanf(float x)
+{
+ return (float) atan((double) x);
+}
+
+/** Wrapper around sqrt() */
+double
+_mesa_sqrtd(double x)
+{
+ return sqrt(x);
+}
+
+
+/*
+ * A High Speed, Low Precision Square Root
+ * by Paul Lalonde and Robert Dawson
+ * from "Graphics Gems", Academic Press, 1990
+ *
+ * SPARC implementation of a fast square root by table
+ * lookup.
+ * SPARC floating point format is as follows:
+ *
+ * BIT 31 30 23 22 0
+ * sign exponent mantissa
+ */
+static short sqrttab[0x100]; /* declare table of square roots */
+
+void
+_mesa_init_sqrt_table(void)
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ unsigned short i;
+ fi_type fi; /* to access the bits of a float in C quickly */
+ /* we use a union defined in glheader.h */
+
+ for(i=0; i<= 0x7f; i++) {
+ fi.i = 0;
+
+ /*
+ * Build a float with the bit pattern i as mantissa
+ * and an exponent of 0, stored as 127
+ */
+
+ fi.i = (i << 16) | (127 << 23);
+ fi.f = _mesa_sqrtd(fi.f);
+
+ /*
+ * Take the square root then strip the first 7 bits of
+ * the mantissa into the table
+ */
+
+ sqrttab[i] = (fi.i & 0x7fffff) >> 16;
+
+ /*
+ * Repeat the process, this time with an exponent of
+ * 1, stored as 128
+ */
+
+ fi.i = 0;
+ fi.i = (i << 16) | (128 << 23);
+ fi.f = sqrt(fi.f);
+ sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16;
+ }
+#else
+ (void) sqrttab; /* silence compiler warnings */
+#endif /*HAVE_FAST_MATH*/
+}
+
+
+/**
+ * Single precision square root.
+ */
+float
+_mesa_sqrtf( float x )
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ fi_type num;
+ /* to access the bits of a float in C
+ * we use a union from glheader.h */
+
+ short e; /* the exponent */
+ if (x == 0.0F) return 0.0F; /* check for square root of 0 */
+ num.f = x;
+ e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */
+ /* exponent is stored with 127 added */
+ num.i &= 0x7fffff; /* leave only the mantissa */
+ if (e & 0x01) num.i |= 0x800000;
+ /* the exponent is odd so we have to */
+ /* look it up in the second half of */
+ /* the lookup table, so we set the */
+ /* high bit */
+ e >>= 1; /* divide the exponent by two */
+ /* note that in C the shift */
+ /* operators are sign preserving */
+ /* for signed operands */
+ /* Do the table lookup, based on the quaternary mantissa,
+ * then reconstruct the result back into a float
+ */
+ num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23);
+
+ return num.f;
+#else
+ return (float) _mesa_sqrtd((double) x);
+#endif
+}
+
+
+/**
+ inv_sqrt - A single precision 1/sqrt routine for IEEE format floats.
+ written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk
+ and Vesa Karvonen.
+*/
+float
+_mesa_inv_sqrtf(float n)
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ float r0, x0, y0;
+ float r1, x1, y1;
+ float r2, x2, y2;
+#if 0 /* not used, see below -BP */
+ float r3, x3, y3;
+#endif
+ union { float f; unsigned int i; } u;
+ unsigned int magic;
+
+ /*
+ Exponent part of the magic number -
+
+ We want to:
+ 1. subtract the bias from the exponent,
+ 2. negate it
+ 3. divide by two (rounding towards -inf)
+ 4. add the bias back
+
+ Which is the same as subtracting the exponent from 381 and dividing
+ by 2.
+
+ floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2)
+ */
+
+ magic = 381 << 23;
+
+ /*
+ Significand part of magic number -
+
+ With the current magic number, "(magic - u.i) >> 1" will give you:
+
+ for 1 <= u.f <= 2: 1.25 - u.f / 4
+ for 2 <= u.f <= 4: 1.00 - u.f / 8
+
+ This isn't a bad approximation of 1/sqrt. The maximum difference from
+ 1/sqrt will be around .06. After three Newton-Raphson iterations, the
+ maximum difference is less than 4.5e-8. (Which is actually close
+ enough to make the following bias academic...)
+
+ To get a better approximation you can add a bias to the magic
+ number. For example, if you subtract 1/2 of the maximum difference in
+ the first approximation (.03), you will get the following function:
+
+ for 1 <= u.f <= 2: 1.22 - u.f / 4
+ for 2 <= u.f <= 3.76: 0.97 - u.f / 8
+ for 3.76 <= u.f <= 4: 0.72 - u.f / 16
+ (The 3.76 to 4 range is where the result is < .5.)
+
+ This is the closest possible initial approximation, but with a maximum
+ error of 8e-11 after three NR iterations, it is still not perfect. If
+ you subtract 0.0332281 instead of .03, the maximum error will be
+ 2.5e-11 after three NR iterations, which should be about as close as
+ is possible.
+
+ for 1 <= u.f <= 2: 1.2167719 - u.f / 4
+ for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8
+ for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16
+
+ */
+
+ magic -= (int)(0.0332281 * (1 << 25));
+
+ u.f = n;
+ u.i = (magic - u.i) >> 1;
+
+ /*
+ Instead of Newton-Raphson, we use Goldschmidt's algorithm, which
+ allows more parallelism. From what I understand, the parallelism
+ comes at the cost of less precision, because it lets error
+ accumulate across iterations.
+ */
+ x0 = 1.0f;
+ y0 = 0.5f * n;
+ r0 = u.f;
+
+ x1 = x0 * r0;
+ y1 = y0 * r0 * r0;
+ r1 = 1.5f - y1;
+
+ x2 = x1 * r1;
+ y2 = y1 * r1 * r1;
+ r2 = 1.5f - y2;
+
+#if 1
+ return x2 * r2; /* we can stop here, and be conformant -BP */
+#else
+ x3 = x2 * r2;
+ y3 = y2 * r2 * r2;
+ r3 = 1.5f - y3;
+
+ return x3 * r3;
+#endif
+#else
+ return (float) (1.0 / sqrt(n));
+#endif
+}
+
+
+/** Wrapper around pow() */
+double
+_mesa_pow(double x, double y)
+{
+ return pow(x, y);
+}
+
+
+/**
+ * Find the first bit set in a word.
+ */
+int
+_mesa_ffs(int32_t i)
+{
+#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__)
+ register int bit = 0;
+ if (i != 0) {
+ if ((i & 0xffff) == 0) {
+ bit += 16;
+ i >>= 16;
+ }
+ if ((i & 0xff) == 0) {
+ bit += 8;
+ i >>= 8;
+ }
+ if ((i & 0xf) == 0) {
+ bit += 4;
+ i >>= 4;
+ }
+ while ((i & 1) == 0) {
+ bit++;
+ i >>= 1;
+ }
+ bit++;
+ }
+ return bit;
+#else
+ return ffs(i);
+#endif
+}
+
+
+/**
+ * Find position of first bit set in given value.
+ * XXX Warning: this function can only be used on 64-bit systems!
+ * \return position of least-significant bit set, starting at 1, return zero
+ * if no bits set.
+ */
+int
+_mesa_ffsll(int64_t val)
+{
+#ifdef ffsll
+ return ffsll(val);
+#else
+ int bit;
+
+ assert(sizeof(val) == 8);
+
+ bit = _mesa_ffs((int32_t)val);
+ if (bit != 0)
+ return bit;
+
+ bit = _mesa_ffs((int32_t)(val >> 32));
+ if (bit != 0)
+ return 32 + bit;
+
+ return 0;
+#endif
+}
+
+
+/**
+ * Return number of bits set in given GLuint.
+ */
+unsigned int
+_mesa_bitcount(unsigned int n)
+{
+ unsigned int bits;
+ for (bits = 0; n > 0; n = n >> 1) {
+ bits += (n & 1);
+ }
+ return bits;
+}
+
+
+/**
+ * Convert a 4-byte float to a 2-byte half float.
+ * Based on code from:
+ * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
+ */
+GLhalfARB
+_mesa_float_to_half(float val)
+{
+ const int flt = *((int *) (void *) &val);
+ const int flt_m = flt & 0x7fffff;
+ const int flt_e = (flt >> 23) & 0xff;
+ const int flt_s = (flt >> 31) & 0x1;
+ int s, e, m = 0;
+ GLhalfARB result;
+
+ /* sign bit */
+ s = flt_s;
+
+ /* handle special cases */
+ if ((flt_e == 0) && (flt_m == 0)) {
+ /* zero */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if ((flt_e == 0) && (flt_m != 0)) {
+ /* denorm -- denorm float maps to 0 half */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if ((flt_e == 0xff) && (flt_m == 0)) {
+ /* infinity */
+ /* m = 0; - already set */
+ e = 31;
+ }
+ else if ((flt_e == 0xff) && (flt_m != 0)) {
+ /* NaN */
+ m = 1;
+ e = 31;
+ }
+ else {
+ /* regular number */
+ const int new_exp = flt_e - 127;
+ if (new_exp < -24) {
+ /* this maps to 0 */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if (new_exp < -14) {
+ /* this maps to a denorm */
+ unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/
+ e = 0;
+ switch (exp_val) {
+ case 0:
+ _mesa_warning(NULL,
+ "float_to_half: logical error in denorm creation!\n");
+ /* m = 0; - already set */
+ break;
+ case 1: m = 512 + (flt_m >> 14); break;
+ case 2: m = 256 + (flt_m >> 15); break;
+ case 3: m = 128 + (flt_m >> 16); break;
+ case 4: m = 64 + (flt_m >> 17); break;
+ case 5: m = 32 + (flt_m >> 18); break;
+ case 6: m = 16 + (flt_m >> 19); break;
+ case 7: m = 8 + (flt_m >> 20); break;
+ case 8: m = 4 + (flt_m >> 21); break;
+ case 9: m = 2 + (flt_m >> 22); break;
+ case 10: m = 1; break;
+ }
+ }
+ else if (new_exp > 15) {
+ /* map this value to infinity */
+ /* m = 0; - already set */
+ e = 31;
+ }
+ else {
+ /* regular */
+ e = new_exp + 15;
+ m = flt_m >> 13;
+ }
+ }
+
+ result = (s << 15) | (e << 10) | m;
+ return result;
+}
+
+
+/**
+ * Convert a 2-byte half float to a 4-byte float.
+ * Based on code from:
+ * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
+ */
+float
+_mesa_half_to_float(GLhalfARB val)
+{
+ /* XXX could also use a 64K-entry lookup table */
+ const int m = val & 0x3ff;
+ const int e = (val >> 10) & 0x1f;
+ const int s = (val >> 15) & 0x1;
+ int flt_m, flt_e, flt_s, flt;
+ float result;
+
+ /* sign bit */
+ flt_s = s;
+
+ /* handle special cases */
+ if ((e == 0) && (m == 0)) {
+ /* zero */
+ flt_m = 0;
+ flt_e = 0;
+ }
+ else if ((e == 0) && (m != 0)) {
+ /* denorm -- denorm half will fit in non-denorm single */
+ const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */
+ float mantissa = ((float) (m)) / 1024.0f;
+ float sign = s ? -1.0f : 1.0f;
+ return sign * mantissa * half_denorm;
+ }
+ else if ((e == 31) && (m == 0)) {
+ /* infinity */
+ flt_e = 0xff;
+ flt_m = 0;
+ }
+ else if ((e == 31) && (m != 0)) {
+ /* NaN */
+ flt_e = 0xff;
+ flt_m = 1;
+ }
+ else {
+ /* regular */
+ flt_e = e + 112;
+ flt_m = m << 13;
+ }
+
+ flt = (flt_s << 31) | (flt_e << 23) | flt_m;
+ result = *((float *) (void *) &flt);
+ return result;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Sort & Search */
+/*@{*/
+
+/**
+ * Wrapper for bsearch().
+ */
+void *
+_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *) )
+{
+#if defined(_WIN32_WCE)
+ void *mid;
+ int cmp;
+ while (nmemb) {
+ nmemb >>= 1;
+ mid = (char *)base + nmemb * size;
+ cmp = (*compar)(key, mid);
+ if (cmp == 0)
+ return mid;
+ if (cmp > 0) {
+ base = (char *)mid + size;
+ --nmemb;
+ }
+ }
+ return NULL;
+#else
+ return bsearch(key, base, nmemb, size, compar);
+#endif
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Environment vars */
+/*@{*/
+
+/**
+ * Wrapper for getenv().
+ */
+char *
+_mesa_getenv( const char *var )
+{
+#if defined(_XBOX) || defined(_WIN32_WCE)
+ return NULL;
+#else
+ return getenv(var);
+#endif
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name String */
+/*@{*/
+
+/** Wrapper around strstr() */
+char *
+_mesa_strstr( const char *haystack, const char *needle )
+{
+ return strstr(haystack, needle);
+}
+
+/** Wrapper around strncat() */
+char *
+_mesa_strncat( char *dest, const char *src, size_t n )
+{
+ return strncat(dest, src, n);
+}
+
+/** Wrapper around strcpy() */
+char *
+_mesa_strcpy( char *dest, const char *src )
+{
+ return strcpy(dest, src);
+}
+
+/** Wrapper around strncpy() */
+char *
+_mesa_strncpy( char *dest, const char *src, size_t n )
+{
+ return strncpy(dest, src, n);
+}
+
+/** Wrapper around strlen() */
+size_t
+_mesa_strlen( const char *s )
+{
+ return strlen(s);
+}
+
+/** Wrapper around strcmp() */
+int
+_mesa_strcmp( const char *s1, const char *s2 )
+{
+ return strcmp(s1, s2);
+}
+
+/** Wrapper around strncmp() */
+int
+_mesa_strncmp( const char *s1, const char *s2, size_t n )
+{
+ return strncmp(s1, s2, n);
+}
+
+/**
+ * Implemented using _mesa_malloc() and _mesa_strcpy.
+ * Note that NULL is handled accordingly.
+ */
+char *
+_mesa_strdup( const char *s )
+{
+ if (s) {
+ size_t l = _mesa_strlen(s);
+ char *s2 = (char *) _mesa_malloc(l + 1);
+ if (s2)
+ _mesa_strcpy(s2, s);
+ return s2;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/** Wrapper around atoi() */
+int
+_mesa_atoi(const char *s)
+{
+ return atoi(s);
+}
+
+/** Wrapper around strtod() */
+double
+_mesa_strtod( const char *s, char **end )
+{
+ return strtod(s, end);
+}
+
+/** Compute simple checksum/hash for a string */
+unsigned int
+_mesa_str_checksum(const char *str)
+{
+ /* This could probably be much better */
+ unsigned int sum, i;
+ const char *c;
+ sum = i = 1;
+ for (c = str; *c; c++)
+ sum += *c * (i % 100);
+ return sum;
+}
+
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name I/O */
+/*@{*/
+
+/** Wrapper around vsprintf() */
+int
+_mesa_sprintf( char *str, const char *fmt, ... )
+{
+ int r;
+ va_list args;
+ va_start( args, fmt );
+ r = vsprintf( str, fmt, args );
+ va_end( args );
+ return r;
+}
+
+/** Wrapper around vsnprintf() */
+int
+_mesa_snprintf( char *str, size_t size, const char *fmt, ... )
+{
+ int r;
+ va_list args;
+ va_start( args, fmt );
+ r = vsnprintf( str, size, fmt, args );
+ va_end( args );
+ return r;
+}
+
+/** Wrapper around printf(), using vsprintf() for the formatting. */
+void
+_mesa_printf( const char *fmtString, ... )
+{
+ va_list args;
+ va_start( args, fmtString );
+ vfprintf(stderr, fmtString, args);
+ va_end( args );
+}
+
+/** Wrapper around fprintf(), using vsprintf() for the formatting. */
+void
+_mesa_fprintf( FILE *f, const char *fmtString, ... )
+{
+ char s[MAXSTRING];
+ va_list args;
+ va_start( args, fmtString );
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end( args );
+ fprintf(f, "%s", s);
+}
+
+
+/** Wrapper around vsprintf() */
+int
+_mesa_vsprintf( char *str, const char *fmt, va_list args )
+{
+ return vsprintf( str, fmt, args );
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Diagnostics */
+/*@{*/
+
+static void
+output_if_debug(const char *prefixString, const char *outputString,
+ GLboolean newline)
+{
+ static int debug = -1;
+
+ /* Check the MESA_DEBUG environment variable if it hasn't
+ * been checked yet. We only have to check it once...
+ */
+ if (debug == -1) {
+ char *env = _mesa_getenv("MESA_DEBUG");
+
+ /* In a debug build, we print warning messages *unless*
+ * MESA_DEBUG is 0. In a non-debug build, we don't
+ * print warning messages *unless* MESA_DEBUG is
+ * set *to any value*.
+ */
+#ifdef DEBUG
+ debug = (env != NULL && _mesa_atoi(env) == 0) ? 0 : 1;
+#else
+ debug = (env != NULL) ? 1 : 0;
+#endif
+ }
+
+ /* Now only print the string if we're required to do so. */
+ if (debug) {
+ fprintf(stderr, "%s: %s", prefixString, outputString);
+ if (newline)
+ fprintf(stderr, "\n");
+
+#if defined(_WIN32) && !defined(_WIN32_WCE)
+ /* stderr from windows applications without console is not usually
+ * visible, so communicate with the debugger instead */
+ {
+ char buf[4096];
+ _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
+ OutputDebugStringA(buf);
+ }
+#endif
+ }
+}
+
+
+/**
+ * Return string version of GL error code.
+ */
+static const char *
+error_string( GLenum error )
+{
+ switch (error) {
+ case GL_NO_ERROR:
+ return "GL_NO_ERROR";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
+ case GL_TABLE_TOO_LARGE:
+ return "GL_TABLE_TOO_LARGE";
+ case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+ return "GL_INVALID_FRAMEBUFFER_OPERATION";
+ default:
+ return "unknown";
+ }
+}
+
+
+/**
+ * When a new type of error is recorded, print a message describing
+ * previous errors which were accumulated.
+ */
+static void
+flush_delayed_errors( GLcontext *ctx )
+{
+ char s[MAXSTRING];
+
+ if (ctx->ErrorDebugCount) {
+ _mesa_snprintf(s, MAXSTRING, "%d similar %s errors",
+ ctx->ErrorDebugCount,
+ error_string(ctx->ErrorValue));
+
+ output_if_debug("Mesa", s, GL_TRUE);
+
+ ctx->ErrorDebugCount = 0;
+ }
+}
+
+
+/**
+ * Report a warning (a recoverable error condition) to stderr if
+ * either DEBUG is defined or the MESA_DEBUG env var is set.
+ *
+ * \param ctx GL context.
+ * \param fmtString printf()-like format string.
+ */
+void
+_mesa_warning( GLcontext *ctx, const char *fmtString, ... )
+{
+ char str[MAXSTRING];
+ va_list args;
+ va_start( args, fmtString );
+ (void) vsnprintf( str, MAXSTRING, fmtString, args );
+ va_end( args );
+
+ if (ctx)
+ flush_delayed_errors( ctx );
+
+ output_if_debug("Mesa warning", str, GL_TRUE);
+}
+
+
+/**
+ * Report an internal implementation problem.
+ * Prints the message to stderr via fprintf().
+ *
+ * \param ctx GL context.
+ * \param fmtString problem description string.
+ */
+void
+_mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
+{
+ va_list args;
+ char str[MAXSTRING];
+ (void) ctx;
+
+ va_start( args, fmtString );
+ vsnprintf( str, MAXSTRING, fmtString, args );
+ va_end( args );
+
+ fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str);
+ fprintf(stderr, "Please report at bugzilla.freedesktop.org\n");
+}
+
+
+/**
+ * Record an OpenGL state error. These usually occur when the user
+ * passes invalid parameters to a GL function.
+ *
+ * If debugging is enabled (either at compile-time via the DEBUG macro, or
+ * run-time via the MESA_DEBUG environment variable), report the error with
+ * _mesa_debug().
+ *
+ * \param ctx the GL context.
+ * \param error the error value.
+ * \param fmtString printf() style format string, followed by optional args
+ */
+void
+_mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
+{
+ static GLint debug = -1;
+
+ /* Check debug environment variable only once:
+ */
+ if (debug == -1) {
+ const char *debugEnv = _mesa_getenv("MESA_DEBUG");
+
+#ifdef DEBUG
+ if (debugEnv && _mesa_strstr(debugEnv, "silent"))
+ debug = GL_FALSE;
+ else
+ debug = GL_TRUE;
+#else
+ if (debugEnv)
+ debug = GL_TRUE;
+ else
+ debug = GL_FALSE;
+#endif
+ }
+
+ if (debug) {
+ if (ctx->ErrorValue == error &&
+ ctx->ErrorDebugFmtString == fmtString) {
+ ctx->ErrorDebugCount++;
+ }
+ else {
+ char s[MAXSTRING], s2[MAXSTRING];
+ va_list args;
+
+ flush_delayed_errors( ctx );
+
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+
+ _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s);
+ output_if_debug("Mesa: User error", s2, GL_TRUE);
+
+ ctx->ErrorDebugFmtString = fmtString;
+ ctx->ErrorDebugCount = 0;
+ }
+ }
+
+ _mesa_record_error(ctx, error);
+}
+
+
+/**
+ * Report debug information. Print error message to stderr via fprintf().
+ * No-op if DEBUG mode not enabled.
+ *
+ * \param ctx GL context.
+ * \param fmtString printf()-style format string, followed by optional args.
+ */
+void
+_mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
+{
+#ifdef DEBUG
+ char s[MAXSTRING];
+ va_list args;
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+ output_if_debug("Mesa", s, GL_FALSE);
+#endif /* DEBUG */
+ (void) ctx;
+ (void) fmtString;
+}
+
+/*@}*/
+
+
+/**
+ * Wrapper for exit().
+ */
+void
+_mesa_exit( int status )
+{
+ exit(status);
+}
diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h
new file mode 100644
index 000000000..7d4012a85
--- /dev/null
+++ b/mesalib/src/mesa/main/imports.h
@@ -0,0 +1,630 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file imports.h
+ * Standard C library function wrappers.
+ *
+ * This file provides wrappers for all the standard C library functions
+ * like malloc(), free(), printf(), getenv(), etc.
+ */
+
+
+#ifndef IMPORTS_H
+#define IMPORTS_H
+
+
+#include "compiler.h"
+#include "glheader.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**********************************************************************/
+/** Memory macros */
+/*@{*/
+
+/** Allocate \p BYTES bytes */
+#define MALLOC(BYTES) _mesa_malloc(BYTES)
+/** Allocate and zero \p BYTES bytes */
+#define CALLOC(BYTES) _mesa_calloc(BYTES)
+/** Allocate a structure of type \p T */
+#define MALLOC_STRUCT(T) (struct T *) _mesa_malloc(sizeof(struct T))
+/** Allocate and zero a structure of type \p T */
+#define CALLOC_STRUCT(T) (struct T *) _mesa_calloc(sizeof(struct T))
+/** Free memory */
+#define FREE(PTR) _mesa_free(PTR)
+
+/** Allocate \p BYTES aligned at \p N bytes */
+#define ALIGN_MALLOC(BYTES, N) _mesa_align_malloc(BYTES, N)
+/** Allocate and zero \p BYTES bytes aligned at \p N bytes */
+#define ALIGN_CALLOC(BYTES, N) _mesa_align_calloc(BYTES, N)
+/** Allocate a structure of type \p T aligned at \p N bytes */
+#define ALIGN_MALLOC_STRUCT(T, N) (struct T *) _mesa_align_malloc(sizeof(struct T), N)
+/** Allocate and zero a structure of type \p T aligned at \p N bytes */
+#define ALIGN_CALLOC_STRUCT(T, N) (struct T *) _mesa_align_calloc(sizeof(struct T), N)
+/** Free aligned memory */
+#define ALIGN_FREE(PTR) _mesa_align_free(PTR)
+
+/** Copy \p BYTES bytes from \p SRC into \p DST */
+#define MEMCPY( DST, SRC, BYTES) _mesa_memcpy(DST, SRC, BYTES)
+/** Set \p N bytes in \p DST to \p VAL */
+#define MEMSET( DST, VAL, N ) _mesa_memset(DST, VAL, N)
+
+/*@}*/
+
+
+/*
+ * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers
+ * as offsets into buffer stores. Since the vertex array pointer and
+ * buffer store pointer are both pointers and we need to add them, we use
+ * this macro.
+ * Both pointers/offsets are expressed in bytes.
+ */
+#define ADD_POINTERS(A, B) ( (GLubyte *) (A) + (uintptr_t) (B) )
+
+
+/**
+ * Sometimes we treat GLfloats as GLints. On x86 systems, moving a float
+ * as a int (thereby using integer registers instead of FP registers) is
+ * a performance win. Typically, this can be done with ordinary casts.
+ * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0)
+ * these casts generate warnings.
+ * The following union typedef is used to solve that.
+ */
+typedef union { GLfloat f; GLint i; } fi_type;
+
+
+
+/**********************************************************************
+ * Math macros
+ */
+
+#define MAX_GLUSHORT 0xffff
+#define MAX_GLUINT 0xffffffff
+
+/* Degrees to radians conversion: */
+#define DEG2RAD (M_PI/180.0)
+
+
+/***
+ *** SQRTF: single-precision square root
+ ***/
+#if 0 /* _mesa_sqrtf() not accurate enough - temporarily disabled */
+# define SQRTF(X) _mesa_sqrtf(X)
+#else
+# define SQRTF(X) (float) sqrt((float) (X))
+#endif
+
+
+/***
+ *** INV_SQRTF: single-precision inverse square root
+ ***/
+#if 0
+#define INV_SQRTF(X) _mesa_inv_sqrt(X)
+#else
+#define INV_SQRTF(X) (1.0F / SQRTF(X)) /* this is faster on a P4 */
+#endif
+
+
+/***
+ *** LOG2: Log base 2 of float
+ ***/
+#ifdef USE_IEEE
+#if 0
+/* This is pretty fast, but not accurate enough (only 2 fractional bits).
+ * Based on code from http://www.stereopsis.com/log2.html
+ */
+static INLINE GLfloat LOG2(GLfloat x)
+{
+ const GLfloat y = x * x * x * x;
+ const GLuint ix = *((GLuint *) &y);
+ const GLuint exp = (ix >> 23) & 0xFF;
+ const GLint log2 = ((GLint) exp) - 127;
+ return (GLfloat) log2 * (1.0 / 4.0); /* 4, because of x^4 above */
+}
+#endif
+/* Pretty fast, and accurate.
+ * Based on code from http://www.flipcode.com/totd/
+ */
+static INLINE GLfloat LOG2(GLfloat val)
+{
+ fi_type num;
+ GLint log_2;
+ num.f = val;
+ log_2 = ((num.i >> 23) & 255) - 128;
+ num.i &= ~(255 << 23);
+ num.i += 127 << 23;
+ num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3;
+ return num.f + log_2;
+}
+#else
+/*
+ * NOTE: log_base_2(x) = log(x) / log(2)
+ * NOTE: 1.442695 = 1/log(2).
+ */
+#define LOG2(x) ((GLfloat) (log(x) * 1.442695F))
+#endif
+
+
+/***
+ *** IS_INF_OR_NAN: test if float is infinite or NaN
+ ***/
+#ifdef USE_IEEE
+static INLINE int IS_INF_OR_NAN( float x )
+{
+ fi_type tmp;
+ tmp.f = x;
+ return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
+}
+#elif defined(isfinite)
+#define IS_INF_OR_NAN(x) (!isfinite(x))
+#elif defined(finite)
+#define IS_INF_OR_NAN(x) (!finite(x))
+#elif defined(__VMS)
+#define IS_INF_OR_NAN(x) (!finite(x))
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define IS_INF_OR_NAN(x) (!isfinite(x))
+#else
+#define IS_INF_OR_NAN(x) (!finite(x))
+#endif
+
+
+/***
+ *** IS_NEGATIVE: test if float is negative
+ ***/
+#if defined(USE_IEEE)
+static INLINE int GET_FLOAT_BITS( float x )
+{
+ fi_type fi;
+ fi.f = x;
+ return fi.i;
+}
+#define IS_NEGATIVE(x) (GET_FLOAT_BITS(x) < 0)
+#else
+#define IS_NEGATIVE(x) (x < 0.0F)
+#endif
+
+
+/***
+ *** DIFFERENT_SIGNS: test if two floats have opposite signs
+ ***/
+#if defined(USE_IEEE)
+#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#define DIFFERENT_SIGNS(x,y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
+#endif
+
+
+/***
+ *** CEILF: ceiling of float
+ *** FLOORF: floor of float
+ *** FABSF: absolute value of float
+ *** LOGF: the natural logarithm (base e) of the value
+ *** EXPF: raise e to the value
+ *** LDEXPF: multiply value by an integral power of two
+ *** FREXPF: extract mantissa and exponent from value
+ ***/
+#if defined(__gnu_linux__)
+/* C99 functions */
+#define CEILF(x) ceilf(x)
+#define FLOORF(x) floorf(x)
+#define FABSF(x) fabsf(x)
+#define LOGF(x) logf(x)
+#define EXPF(x) expf(x)
+#define LDEXPF(x,y) ldexpf(x,y)
+#define FREXPF(x,y) frexpf(x,y)
+#else
+#define CEILF(x) ((GLfloat) ceil(x))
+#define FLOORF(x) ((GLfloat) floor(x))
+#define FABSF(x) ((GLfloat) fabs(x))
+#define LOGF(x) ((GLfloat) log(x))
+#define EXPF(x) ((GLfloat) exp(x))
+#define LDEXPF(x,y) ((GLfloat) ldexp(x,y))
+#define FREXPF(x,y) ((GLfloat) frexp(x,y))
+#endif
+
+
+/***
+ *** IROUND: return (as an integer) float rounded to nearest integer
+ ***/
+#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \
+ (!(defined(__BEOS__) || defined(__HAIKU__)) || \
+ (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
+static INLINE int iround(float f)
+{
+ int r;
+ __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
+ return r;
+}
+#define IROUND(x) iround(x)
+#elif defined(USE_X86_ASM) && defined(_MSC_VER)
+static INLINE int iround(float f)
+{
+ int r;
+ _asm {
+ fld f
+ fistp r
+ }
+ return r;
+}
+#define IROUND(x) iround(x)
+#elif defined(__WATCOMC__) && defined(__386__)
+long iround(float f);
+#pragma aux iround = \
+ "push eax" \
+ "fistp dword ptr [esp]" \
+ "pop eax" \
+ parm [8087] \
+ value [eax] \
+ modify exact [eax];
+#define IROUND(x) iround(x)
+#else
+#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
+#endif
+
+#define IROUND64(f) ((GLint64) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
+
+/***
+ *** IROUND_POS: return (as an integer) positive float rounded to nearest int
+ ***/
+#ifdef DEBUG
+#define IROUND_POS(f) (assert((f) >= 0.0F), IROUND(f))
+#else
+#define IROUND_POS(f) (IROUND(f))
+#endif
+
+
+/***
+ *** IFLOOR: return (as an integer) floor of float
+ ***/
+#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
+/*
+ * IEEE floor for computers that round to nearest or even.
+ * 'f' must be between -4194304 and 4194303.
+ * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1",
+ * but uses some IEEE specific tricks for better speed.
+ * Contributed by Josh Vanderhoof
+ */
+static INLINE int ifloor(float f)
+{
+ int ai, bi;
+ double af, bf;
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+ /* GCC generates an extra fstp/fld without this. */
+ __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
+ __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
+ return (ai - bi) >> 1;
+}
+#define IFLOOR(x) ifloor(x)
+#elif defined(USE_IEEE)
+static INLINE int ifloor(float f)
+{
+ int ai, bi;
+ double af, bf;
+ fi_type u;
+
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+ u.f = (float) af; ai = u.i;
+ u.f = (float) bf; bi = u.i;
+ return (ai - bi) >> 1;
+}
+#define IFLOOR(x) ifloor(x)
+#else
+static INLINE int ifloor(float f)
+{
+ int i = IROUND(f);
+ return (i > f) ? i - 1 : i;
+}
+#define IFLOOR(x) ifloor(x)
+#endif
+
+
+/***
+ *** ICEIL: return (as an integer) ceiling of float
+ ***/
+#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
+/*
+ * IEEE ceil for computers that round to nearest or even.
+ * 'f' must be between -4194304 and 4194303.
+ * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1",
+ * but uses some IEEE specific tricks for better speed.
+ * Contributed by Josh Vanderhoof
+ */
+static INLINE int iceil(float f)
+{
+ int ai, bi;
+ double af, bf;
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+ /* GCC generates an extra fstp/fld without this. */
+ __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
+ __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
+ return (ai - bi + 1) >> 1;
+}
+#define ICEIL(x) iceil(x)
+#elif defined(USE_IEEE)
+static INLINE int iceil(float f)
+{
+ int ai, bi;
+ double af, bf;
+ fi_type u;
+ af = (3 << 22) + 0.5 + (double)f;
+ bf = (3 << 22) + 0.5 - (double)f;
+ u.f = (float) af; ai = u.i;
+ u.f = (float) bf; bi = u.i;
+ return (ai - bi + 1) >> 1;
+}
+#define ICEIL(x) iceil(x)
+#else
+static INLINE int iceil(float f)
+{
+ int i = IROUND(f);
+ return (i < f) ? i + 1 : i;
+}
+#define ICEIL(x) iceil(x)
+#endif
+
+
+/**
+ * Is x a power of two?
+ */
+static INLINE int
+_mesa_is_pow_two(int x)
+{
+ return !(x & (x - 1));
+}
+
+
+/***
+ *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255]
+ *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255]
+ ***/
+#if defined(USE_IEEE) && !defined(DEBUG)
+#define IEEE_0996 0x3f7f0000 /* 0.996 or so */
+/* This function/macro is sensitive to precision. Test very carefully
+ * if you change it!
+ */
+#define UNCLAMPED_FLOAT_TO_UBYTE(UB, F) \
+ do { \
+ fi_type __tmp; \
+ __tmp.f = (F); \
+ if (__tmp.i < 0) \
+ UB = (GLubyte) 0; \
+ else if (__tmp.i >= IEEE_0996) \
+ UB = (GLubyte) 255; \
+ else { \
+ __tmp.f = __tmp.f * (255.0F/256.0F) + 32768.0F; \
+ UB = (GLubyte) __tmp.i; \
+ } \
+ } while (0)
+#define CLAMPED_FLOAT_TO_UBYTE(UB, F) \
+ do { \
+ fi_type __tmp; \
+ __tmp.f = (F) * (255.0F/256.0F) + 32768.0F; \
+ UB = (GLubyte) __tmp.i; \
+ } while (0)
+#else
+#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
+ ub = ((GLubyte) IROUND(CLAMP((f), 0.0F, 1.0F) * 255.0F))
+#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
+ ub = ((GLubyte) IROUND((f) * 255.0F))
+#endif
+
+
+/**
+ * Return 1 if this is a little endian machine, 0 if big endian.
+ */
+static INLINE GLboolean
+_mesa_little_endian(void)
+{
+ const GLuint ui = 1; /* intentionally not static */
+ return *((const GLubyte *) &ui);
+}
+
+
+
+/**********************************************************************
+ * Functions
+ */
+
+extern void *
+_mesa_malloc( size_t bytes );
+
+extern void *
+_mesa_calloc( size_t bytes );
+
+extern void
+_mesa_free( void *ptr );
+
+extern void *
+_mesa_align_malloc( size_t bytes, unsigned long alignment );
+
+extern void *
+_mesa_align_calloc( size_t bytes, unsigned long alignment );
+
+extern void
+_mesa_align_free( void *ptr );
+
+extern void *
+_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
+ unsigned long alignment);
+
+extern void *
+_mesa_exec_malloc( GLuint size );
+
+extern void
+_mesa_exec_free( void *addr );
+
+extern void *
+_mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize );
+
+extern void *
+_mesa_memcpy( void *dest, const void *src, size_t n );
+
+extern void
+_mesa_memset( void *dst, int val, size_t n );
+
+extern void
+_mesa_memset16( unsigned short *dst, unsigned short val, size_t n );
+
+extern void
+_mesa_bzero( void *dst, size_t n );
+
+extern int
+_mesa_memcmp( const void *s1, const void *s2, size_t n );
+
+extern double
+_mesa_sin(double a);
+
+extern float
+_mesa_sinf(float a);
+
+extern double
+_mesa_cos(double a);
+
+extern float
+_mesa_asinf(float x);
+
+extern float
+_mesa_atanf(float x);
+
+extern double
+_mesa_sqrtd(double x);
+
+extern float
+_mesa_sqrtf(float x);
+
+extern float
+_mesa_inv_sqrtf(float x);
+
+extern void
+_mesa_init_sqrt_table(void);
+
+extern double
+_mesa_pow(double x, double y);
+
+extern int
+_mesa_ffs(int32_t i);
+
+extern int
+_mesa_ffsll(int64_t i);
+
+extern unsigned int
+_mesa_bitcount(unsigned int n);
+
+extern GLhalfARB
+_mesa_float_to_half(float f);
+
+extern float
+_mesa_half_to_float(GLhalfARB h);
+
+
+extern void *
+_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *) );
+
+extern char *
+_mesa_getenv( const char *var );
+
+extern char *
+_mesa_strstr( const char *haystack, const char *needle );
+
+extern char *
+_mesa_strncat( char *dest, const char *src, size_t n );
+
+extern char *
+_mesa_strcpy( char *dest, const char *src );
+
+extern char *
+_mesa_strncpy( char *dest, const char *src, size_t n );
+
+extern size_t
+_mesa_strlen( const char *s );
+
+extern int
+_mesa_strcmp( const char *s1, const char *s2 );
+
+extern int
+_mesa_strncmp( const char *s1, const char *s2, size_t n );
+
+extern char *
+_mesa_strdup( const char *s );
+
+extern int
+_mesa_atoi( const char *s );
+
+extern double
+_mesa_strtod( const char *s, char **end );
+
+extern unsigned int
+_mesa_str_checksum(const char *str);
+
+extern int
+_mesa_sprintf( char *str, const char *fmt, ... );
+
+extern int
+_mesa_snprintf( char *str, size_t size, const char *fmt, ... );
+
+extern void
+_mesa_printf( const char *fmtString, ... );
+
+extern void
+_mesa_fprintf( FILE *f, const char *fmtString, ... );
+
+extern int
+_mesa_vsprintf( char *str, const char *fmt, va_list args );
+
+
+extern void
+_mesa_warning( __GLcontext *gc, const char *fmtString, ... );
+
+extern void
+_mesa_problem( const __GLcontext *ctx, const char *fmtString, ... );
+
+extern void
+_mesa_error( __GLcontext *ctx, GLenum error, const char *fmtString, ... );
+
+extern void
+_mesa_debug( const __GLcontext *ctx, const char *fmtString, ... );
+
+extern void
+_mesa_exit( int status );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* IMPORTS_H */
diff --git a/mesalib/src/mesa/main/light.c b/mesalib/src/mesa/main/light.c
new file mode 100644
index 000000000..10c89f436
--- /dev/null
+++ b/mesalib/src/mesa/main/light.c
@@ -0,0 +1,1427 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "enums.h"
+#include "light.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "mtypes.h"
+#include "math/m_matrix.h"
+
+
+void GLAPIENTRY
+_mesa_ShadeModel( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ if (mode != GL_FLAT && mode != GL_SMOOTH) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel");
+ return;
+ }
+
+ if (ctx->Light.ShadeModel == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.ShadeModel = mode;
+ if (mode == GL_FLAT)
+ ctx->_TriangleCaps |= DD_FLATSHADE;
+ else
+ ctx->_TriangleCaps &= ~DD_FLATSHADE;
+
+ if (ctx->Driver.ShadeModel)
+ ctx->Driver.ShadeModel( ctx, mode );
+}
+
+
+/**
+ * Set the provoking vertex (the vertex which specifies the prim's
+ * color when flat shading) to either the first or last vertex of the
+ * triangle or line.
+ */
+void GLAPIENTRY
+_mesa_ProvokingVertexEXT(GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode);
+
+ switch (mode) {
+ case GL_FIRST_VERTEX_CONVENTION_EXT:
+ case GL_LAST_VERTEX_CONVENTION_EXT:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode);
+ return;
+ }
+
+ if (ctx->Light.ProvokingVertex == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.ProvokingVertex = mode;
+}
+
+
+/**
+ * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
+ * per-light state.
+ * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction
+ * will have already been transformed by the modelview matrix!
+ * Also, all error checking should have already been done.
+ */
+void
+_mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
+{
+ struct gl_light *light;
+
+ ASSERT(lnum < MAX_LIGHTS);
+ light = &ctx->Light.Light[lnum];
+
+ switch (pname) {
+ case GL_AMBIENT:
+ if (TEST_EQ_4V(light->Ambient, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_4V( light->Ambient, params );
+ break;
+ case GL_DIFFUSE:
+ if (TEST_EQ_4V(light->Diffuse, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_4V( light->Diffuse, params );
+ break;
+ case GL_SPECULAR:
+ if (TEST_EQ_4V(light->Specular, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_4V( light->Specular, params );
+ break;
+ case GL_POSITION:
+ /* NOTE: position has already been transformed by ModelView! */
+ if (TEST_EQ_4V(light->EyePosition, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_4V(light->EyePosition, params);
+ if (light->EyePosition[3] != 0.0F)
+ light->_Flags |= LIGHT_POSITIONAL;
+ else
+ light->_Flags &= ~LIGHT_POSITIONAL;
+ break;
+ case GL_SPOT_DIRECTION:
+ /* NOTE: Direction already transformed by inverse ModelView! */
+ if (TEST_EQ_3V(light->SpotDirection, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_3V(light->SpotDirection, params);
+ break;
+ case GL_SPOT_EXPONENT:
+ ASSERT(params[0] >= 0.0);
+ ASSERT(params[0] <= ctx->Const.MaxSpotExponent);
+ if (light->SpotExponent == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ light->SpotExponent = params[0];
+ _mesa_invalidate_spot_exp_table(light);
+ break;
+ case GL_SPOT_CUTOFF:
+ ASSERT(params[0] == 180.0 || (params[0] >= 0.0 && params[0] <= 90.0));
+ if (light->SpotCutoff == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ light->SpotCutoff = params[0];
+ light->_CosCutoffNeg = (GLfloat) (_mesa_cos(light->SpotCutoff * DEG2RAD));
+ if (light->_CosCutoffNeg < 0)
+ light->_CosCutoff = 0;
+ else
+ light->_CosCutoff = light->_CosCutoffNeg;
+ if (light->SpotCutoff != 180.0F)
+ light->_Flags |= LIGHT_SPOT;
+ else
+ light->_Flags &= ~LIGHT_SPOT;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ ASSERT(params[0] >= 0.0);
+ if (light->ConstantAttenuation == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ light->ConstantAttenuation = params[0];
+ break;
+ case GL_LINEAR_ATTENUATION:
+ ASSERT(params[0] >= 0.0);
+ if (light->LinearAttenuation == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ light->LinearAttenuation = params[0];
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ ASSERT(params[0] >= 0.0);
+ if (light->QuadraticAttenuation == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ light->QuadraticAttenuation = params[0];
+ break;
+ default:
+ _mesa_problem(ctx, "Unexpected pname in _mesa_light()");
+ return;
+ }
+
+ if (ctx->Driver.Lightfv)
+ ctx->Driver.Lightfv( ctx, GL_LIGHT0 + lnum, pname, params );
+}
+
+
+void GLAPIENTRY
+_mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
+{
+ _mesa_Lightfv( light, pname, &param );
+}
+
+
+void GLAPIENTRY
+_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i = (GLint) (light - GL_LIGHT0);
+ GLfloat temp[4];
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
+ return;
+ }
+
+ /* do particular error checks, transformations */
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ /* nothing */
+ break;
+ case GL_POSITION:
+ /* transform position by ModelView matrix */
+ TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params);
+ params = temp;
+ break;
+ case GL_SPOT_DIRECTION:
+ /* transform direction by inverse modelview */
+ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
+ _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
+ }
+ TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
+ params = temp;
+ break;
+ case GL_SPOT_EXPONENT:
+ if (params[0] < 0.0 || params[0] > ctx->Const.MaxSpotExponent) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
+ return;
+ }
+ break;
+ case GL_SPOT_CUTOFF:
+ if ((params[0] < 0.0 || params[0] > 90.0) && params[0] != 180.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
+ return;
+ }
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ if (params[0] < 0.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
+ return;
+ }
+ break;
+ case GL_LINEAR_ATTENUATION:
+ if (params[0] < 0.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
+ return;
+ }
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ if (params[0] < 0.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
+ return;
+ }
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname);
+ return;
+ }
+
+ _mesa_light(ctx, i, pname, params);
+}
+
+
+void GLAPIENTRY
+_mesa_Lighti( GLenum light, GLenum pname, GLint param )
+{
+ _mesa_Lightiv( light, pname, &param );
+}
+
+
+void GLAPIENTRY
+_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
+{
+ GLfloat fparam[4];
+
+ switch (pname) {
+ case GL_AMBIENT:
+ case GL_DIFFUSE:
+ case GL_SPECULAR:
+ fparam[0] = INT_TO_FLOAT( params[0] );
+ fparam[1] = INT_TO_FLOAT( params[1] );
+ fparam[2] = INT_TO_FLOAT( params[2] );
+ fparam[3] = INT_TO_FLOAT( params[3] );
+ break;
+ case GL_POSITION:
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = (GLfloat) params[1];
+ fparam[2] = (GLfloat) params[2];
+ fparam[3] = (GLfloat) params[3];
+ break;
+ case GL_SPOT_DIRECTION:
+ fparam[0] = (GLfloat) params[0];
+ fparam[1] = (GLfloat) params[1];
+ fparam[2] = (GLfloat) params[2];
+ break;
+ case GL_SPOT_EXPONENT:
+ case GL_SPOT_CUTOFF:
+ case GL_CONSTANT_ATTENUATION:
+ case GL_LINEAR_ATTENUATION:
+ case GL_QUADRATIC_ATTENUATION:
+ fparam[0] = (GLfloat) params[0];
+ break;
+ default:
+ /* error will be caught later in gl_Lightfv */
+ ;
+ }
+
+ _mesa_Lightfv( light, pname, fparam );
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint l = (GLint) (light - GL_LIGHT0);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
+ _mesa_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].SpotDirection );
+ 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:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
+ break;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint l = (GLint) (light - GL_LIGHT0);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
+ _mesa_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].SpotDirection[0];
+ params[1] = (GLint) ctx->Light.Light[l].SpotDirection[1];
+ params[2] = (GLint) ctx->Light.Light[l].SpotDirection[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:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
+ break;
+ }
+}
+
+
+
+/**********************************************************************/
+/*** Light Model ***/
+/**********************************************************************/
+
+
+void GLAPIENTRY
+_mesa_LightModelfv( GLenum pname, const GLfloat *params )
+{
+ GLenum newenum;
+ GLboolean newbool;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ COPY_4V( ctx->Light.Model.Ambient, params );
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ newbool = (params[0]!=0.0);
+ if (ctx->Light.Model.LocalViewer == newbool)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Model.LocalViewer = newbool;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ newbool = (params[0]!=0.0);
+ if (ctx->Light.Model.TwoSide == newbool)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Model.TwoSide = newbool;
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+ ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+ else
+ ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ if (params[0] == (GLfloat) GL_SINGLE_COLOR)
+ newenum = GL_SINGLE_COLOR;
+ else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
+ newenum = GL_SEPARATE_SPECULAR_COLOR;
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
+ (GLint) params[0] );
+ return;
+ }
+ if (ctx->Light.Model.ColorControl == newenum)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Model.ColorControl = newenum;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
+ break;
+ }
+
+ if (ctx->Driver.LightModelfv)
+ ctx->Driver.LightModelfv( ctx, pname, params );
+}
+
+
+void GLAPIENTRY
+_mesa_LightModeliv( GLenum pname, const GLint *params )
+{
+ GLfloat fparam[4];
+
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ fparam[0] = INT_TO_FLOAT( params[0] );
+ fparam[1] = INT_TO_FLOAT( params[1] );
+ fparam[2] = INT_TO_FLOAT( params[2] );
+ fparam[3] = INT_TO_FLOAT( params[3] );
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ fparam[0] = (GLfloat) params[0];
+ break;
+ default:
+ /* Error will be caught later in gl_LightModelfv */
+ ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ _mesa_LightModelfv( pname, fparam );
+}
+
+
+void GLAPIENTRY
+_mesa_LightModeli( GLenum pname, GLint param )
+{
+ _mesa_LightModeliv( pname, &param );
+}
+
+
+void GLAPIENTRY
+_mesa_LightModelf( GLenum pname, GLfloat param )
+{
+ _mesa_LightModelfv( pname, &param );
+}
+
+
+
+/********** MATERIAL **********/
+
+
+/*
+ * Given a face and pname value (ala glColorMaterial), compute a bitmask
+ * of the targeted material values.
+ */
+GLuint
+_mesa_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 |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION;
+ break;
+ case GL_AMBIENT:
+ bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
+ break;
+ case GL_DIFFUSE:
+ bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
+ break;
+ case GL_SPECULAR:
+ bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR;
+ break;
+ case GL_SHININESS:
+ bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS;
+ break;
+ case GL_AMBIENT_AND_DIFFUSE:
+ bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
+ bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
+ break;
+ case GL_COLOR_INDEXES:
+ bitmask |= MAT_BIT_FRONT_INDEXES | MAT_BIT_BACK_INDEXES;
+ break;
+ default:
+ _mesa_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) {
+ _mesa_error( ctx, GL_INVALID_ENUM, where );
+ return 0;
+ }
+
+ if (bitmask & ~legal) {
+ _mesa_error( ctx, GL_INVALID_ENUM, where );
+ return 0;
+ }
+
+ return bitmask;
+}
+
+
+
+/* Perform a straight copy between materials.
+ */
+void
+_mesa_copy_materials( struct gl_material *dst,
+ const struct gl_material *src,
+ GLuint bitmask )
+{
+ int i;
+
+ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+ if (bitmask & (1<<i))
+ COPY_4FV( dst->Attrib[i], src->Attrib[i] );
+}
+
+
+
+/* Update derived values following a change in ctx->Light.Material
+ */
+void
+_mesa_update_material( GLcontext *ctx, GLuint bitmask )
+{
+ struct gl_light *light, *list = &ctx->Light.EnabledList;
+ GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+
+ if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
+ _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
+
+ if (!bitmask)
+ return;
+
+ /* update material ambience */
+ if (bitmask & MAT_BIT_FRONT_AMBIENT) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatAmbient[0], light->Ambient,
+ mat[MAT_ATTRIB_FRONT_AMBIENT]);
+ }
+ }
+
+ if (bitmask & MAT_BIT_BACK_AMBIENT) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatAmbient[1], light->Ambient,
+ mat[MAT_ATTRIB_BACK_AMBIENT]);
+ }
+ }
+
+ /* update BaseColor = emission + scene's ambience * material's ambience */
+ if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) {
+ COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] );
+ ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT],
+ ctx->Light.Model.Ambient );
+ }
+
+ if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) {
+ COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] );
+ ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT],
+ ctx->Light.Model.Ambient );
+ }
+
+ /* update material diffuse values */
+ if (bitmask & MAT_BIT_FRONT_DIFFUSE) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatDiffuse[0], light->Diffuse,
+ mat[MAT_ATTRIB_FRONT_DIFFUSE] );
+ }
+ }
+
+ if (bitmask & MAT_BIT_BACK_DIFFUSE) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatDiffuse[1], light->Diffuse,
+ mat[MAT_ATTRIB_BACK_DIFFUSE] );
+ }
+ }
+
+ /* update material specular values */
+ if (bitmask & MAT_BIT_FRONT_SPECULAR) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatSpecular[0], light->Specular,
+ mat[MAT_ATTRIB_FRONT_SPECULAR]);
+ }
+ }
+
+ if (bitmask & MAT_BIT_BACK_SPECULAR) {
+ foreach (light, list) {
+ SCALE_3V( light->_MatSpecular[1], light->Specular,
+ mat[MAT_ATTRIB_BACK_SPECULAR]);
+ }
+ }
+
+ if (bitmask & MAT_BIT_FRONT_SHININESS) {
+ _mesa_invalidate_shine_table( ctx, 0 );
+ }
+
+ if (bitmask & MAT_BIT_BACK_SHININESS) {
+ _mesa_invalidate_shine_table( ctx, 1 );
+ }
+}
+
+
+/*
+ * Update the current materials from the given rgba color
+ * according to the bitmask in ColorMaterialBitmask, which is
+ * set by glColorMaterial().
+ */
+void
+_mesa_update_color_material( GLcontext *ctx, const GLfloat color[4] )
+{
+ GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ struct gl_material *mat = &ctx->Light.Material;
+ int i;
+
+ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+ if (bitmask & (1<<i))
+ COPY_4FV( mat->Attrib[i], color );
+
+ _mesa_update_material( ctx, bitmask );
+}
+
+
+void GLAPIENTRY
+_mesa_ColorMaterial( GLenum face, GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint bitmask;
+ GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION |
+ MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR |
+ MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE |
+ MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glColorMaterial %s %s\n",
+ _mesa_lookup_enum_by_nr(face),
+ _mesa_lookup_enum_by_nr(mode));
+
+ bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
+
+ if (ctx->Light.ColorMaterialBitmask == bitmask &&
+ ctx->Light.ColorMaterialFace == face &&
+ ctx->Light.ColorMaterialMode == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.ColorMaterialBitmask = bitmask;
+ ctx->Light.ColorMaterialFace = face;
+ ctx->Light.ColorMaterialMode = mode;
+
+ if (ctx->Light.ColorMaterialEnabled) {
+ FLUSH_CURRENT( ctx, 0 );
+ _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ }
+
+ if (ctx->Driver.ColorMaterial)
+ ctx->Driver.ColorMaterial( ctx, face, mode );
+}
+
+
+void GLAPIENTRY
+_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint f;
+ GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
+
+ FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
+
+ if (face==GL_FRONT) {
+ f = 0;
+ }
+ else if (face==GL_BACK) {
+ f = 1;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_AMBIENT:
+ COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] );
+ break;
+ case GL_DIFFUSE:
+ COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] );
+ break;
+ case GL_SPECULAR:
+ COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] );
+ break;
+ case GL_EMISSION:
+ COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] );
+ break;
+ case GL_SHININESS:
+ *params = mat[MAT_ATTRIB_SHININESS(f)][0];
+ break;
+ case GL_COLOR_INDEXES:
+ params[0] = mat[MAT_ATTRIB_INDEXES(f)][0];
+ params[1] = mat[MAT_ATTRIB_INDEXES(f)][1];
+ params[2] = mat[MAT_ATTRIB_INDEXES(f)][2];
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint f;
+ GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */
+
+ FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
+
+ if (face==GL_FRONT) {
+ f = 0;
+ }
+ else if (face==GL_BACK) {
+ f = 1;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
+ return;
+ }
+ switch (pname) {
+ case GL_AMBIENT:
+ params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] );
+ params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] );
+ params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] );
+ params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] );
+ break;
+ case GL_DIFFUSE:
+ params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] );
+ params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] );
+ params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] );
+ params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] );
+ break;
+ case GL_SPECULAR:
+ params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] );
+ params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] );
+ params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] );
+ params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] );
+ break;
+ case GL_EMISSION:
+ params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] );
+ params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] );
+ params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] );
+ params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] );
+ break;
+ case GL_SHININESS:
+ *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] );
+ break;
+ case GL_COLOR_INDEXES:
+ params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] );
+ params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] );
+ params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] );
+ break;
+ default:
+ _mesa_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
+_mesa_invalidate_spot_exp_table( struct gl_light *l )
+{
+ l->_SpotExpTable[0][0] = -1;
+}
+
+
+static void
+validate_spot_exp_table( struct gl_light *l )
+{
+ GLint i;
+ GLdouble exponent = l->SpotExponent;
+ GLdouble tmp = 0;
+ GLint clamp = 0;
+
+ l->_SpotExpTable[0][0] = 0.0;
+
+ for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) {
+ if (clamp == 0) {
+ tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent);
+ if (tmp < FLT_MIN * 100.0) {
+ tmp = 0.0;
+ clamp = 1;
+ }
+ }
+ l->_SpotExpTable[i][0] = (GLfloat) 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.
+ */
+void
+_mesa_invalidate_shine_table( GLcontext *ctx, GLuint side )
+{
+ ASSERT(side < 2);
+ if (ctx->_ShineTable[side])
+ ctx->_ShineTable[side]->refcount--;
+ ctx->_ShineTable[side] = NULL;
+}
+
+
+static void
+validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess )
+{
+ struct gl_shine_tab *list = ctx->_ShineTabList;
+ struct gl_shine_tab *s;
+
+ ASSERT(side < 2);
+
+ foreach(s, list)
+ if ( s->shininess == shininess )
+ break;
+
+ if (s == list) {
+ GLint j;
+ GLfloat *m;
+
+ foreach(s, list)
+ if (s->refcount == 0)
+ break;
+
+ m = s->tab;
+ m[0] = 0.0;
+ if (shininess == 0.0) {
+ for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
+ m[j] = 1.0;
+ }
+ else {
+ for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
+ GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
+ if (x < 0.005) /* underflow check */
+ x = 0.005;
+ t = _mesa_pow(x, shininess);
+ if (t > 1e-20)
+ m[j] = (GLfloat) t;
+ else
+ m[j] = 0.0;
+ }
+ m[SHINE_TABLE_SIZE] = 1.0;
+ }
+
+ s->shininess = shininess;
+ }
+
+ if (ctx->_ShineTable[side])
+ ctx->_ShineTable[side]->refcount--;
+
+ ctx->_ShineTable[side] = s;
+ move_to_tail( list, s );
+ s->refcount++;
+}
+
+
+void
+_mesa_validate_all_lighting_tables( GLcontext *ctx )
+{
+ GLuint i;
+ GLfloat shininess;
+
+ shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
+ if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess)
+ validate_shine_table( ctx, 0, shininess );
+
+ shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
+ if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess)
+ validate_shine_table( ctx, 1, shininess );
+
+ for (i = 0; i < ctx->Const.MaxLights; i++)
+ if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1)
+ validate_spot_exp_table( &ctx->Light.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
+_mesa_update_lighting( GLcontext *ctx )
+{
+ struct gl_light *light;
+ ctx->Light._NeedEyeCoords = GL_FALSE;
+ ctx->Light._Flags = 0;
+
+ if (!ctx->Light.Enabled)
+ return;
+
+ foreach(light, &ctx->Light.EnabledList) {
+ 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._NeedEyeCoords = ((ctx->Light._Flags & LIGHT_POSITIONAL) ||
+ ctx->Light.Model.LocalViewer);
+
+ /* XXX: This test is overkill & needs to be fixed both for software and
+ * hardware t&l drivers. The above should be sufficient & should
+ * be tested to verify this.
+ */
+ if (ctx->Light._NeedVertices)
+ ctx->Light._NeedEyeCoords = GL_TRUE;
+
+ /* Precompute some shading values. Although we reference
+ * Light.Material here, we can get away without flushing
+ * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
+ * are flushed, they will update the derived state at that time.
+ */
+ if (ctx->Visual.rgbMode) {
+ if (ctx->Light.Model.TwoSide)
+ _mesa_update_material( ctx,
+ MAT_BIT_FRONT_EMISSION |
+ MAT_BIT_FRONT_AMBIENT |
+ MAT_BIT_FRONT_DIFFUSE |
+ MAT_BIT_FRONT_SPECULAR |
+ MAT_BIT_BACK_EMISSION |
+ MAT_BIT_BACK_AMBIENT |
+ MAT_BIT_BACK_DIFFUSE |
+ MAT_BIT_BACK_SPECULAR);
+ else
+ _mesa_update_material( ctx,
+ MAT_BIT_FRONT_EMISSION |
+ MAT_BIT_FRONT_AMBIENT |
+ MAT_BIT_FRONT_DIFFUSE |
+ MAT_BIT_FRONT_SPECULAR);
+ }
+ else {
+ static const GLfloat ci[3] = { .30F, .59F, .11F };
+ foreach(light, &ctx->Light.EnabledList) {
+ light->_dli = DOT3(ci, light->Diffuse);
+ light->_sli = DOT3(ci, light->Specular);
+ }
+ }
+}
+
+
+/**
+ * Update state derived from light position, spot direction.
+ * Called upon:
+ * _NEW_MODELVIEW
+ * _NEW_LIGHT
+ * _TNL_NEW_NEED_EYE_COORDS
+ *
+ * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled.
+ * Also update on lighting space changes.
+ */
+static void
+compute_light_positions( GLcontext *ctx )
+{
+ struct gl_light *light;
+ static const GLfloat eye_z[3] = { 0, 0, 1 };
+
+ if (!ctx->Light.Enabled)
+ return;
+
+ if (ctx->_NeedEyeCoords) {
+ COPY_3V( ctx->_EyeZDir, eye_z );
+ }
+ else {
+ TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
+ }
+
+ foreach (light, &ctx->Light.EnabledList) {
+
+ if (ctx->_NeedEyeCoords) {
+ /* _Position is in eye coordinate space */
+ COPY_4FV( light->_Position, light->EyePosition );
+ }
+ else {
+ /* _Position is in object coordinate space */
+ TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
+ 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;
+ }
+ else {
+ /* positional light w/ homogeneous coordinate, divide by W */
+ GLfloat wInv = (GLfloat)1.0 / light->_Position[3];
+ light->_Position[0] *= wInv;
+ light->_Position[1] *= wInv;
+ light->_Position[2] *= wInv;
+ }
+
+ if (light->_Flags & LIGHT_SPOT) {
+ /* Note: we normalize the spot direction now */
+
+ if (ctx->_NeedEyeCoords) {
+ COPY_3V( light->_NormSpotDirection, light->SpotDirection );
+ NORMALIZE_3FV( light->_NormSpotDirection );
+ }
+ else {
+ GLfloat spotDir[3];
+ COPY_3V(spotDir, light->SpotDirection);
+ NORMALIZE_3FV(spotDir);
+ TRANSFORM_NORMAL( light->_NormSpotDirection,
+ spotDir,
+ ctx->ModelviewMatrixStack.Top->m);
+ }
+
+ NORMALIZE_3FV( light->_NormSpotDirection );
+
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
+ light->_NormSpotDirection);
+
+ if (PV_dot_dir > light->_CosCutoff) {
+ double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ int k = (int) x;
+ light->_VP_inf_spot_attenuation =
+ (GLfloat) (light->_SpotExpTable[k][0] +
+ (x-k)*light->_SpotExpTable[k][1]);
+ }
+ else {
+ light->_VP_inf_spot_attenuation = 0;
+ }
+ }
+ }
+ }
+}
+
+
+
+static void
+update_modelview_scale( GLcontext *ctx )
+{
+ ctx->_ModelViewInvScale = 1.0F;
+ if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) {
+ const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
+ GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
+ if (f < 1e-12) f = 1.0;
+ if (ctx->_NeedEyeCoords)
+ ctx->_ModelViewInvScale = (GLfloat) INV_SQRTF(f);
+ else
+ ctx->_ModelViewInvScale = (GLfloat) SQRTF(f);
+ }
+}
+
+
+/**
+ * Bring up to date any state that relies on _NeedEyeCoords.
+ */
+void
+_mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state )
+{
+ const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
+
+ (void) new_state;
+ ctx->_NeedEyeCoords = GL_FALSE;
+
+ if (ctx->_ForceEyeCoords ||
+ (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) ||
+ ctx->Point._Attenuated ||
+ ctx->Light._NeedEyeCoords)
+ ctx->_NeedEyeCoords = GL_TRUE;
+
+ if (ctx->Light.Enabled &&
+ !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top))
+ ctx->_NeedEyeCoords = GL_TRUE;
+
+ /* Check if the truth-value interpretations of the bitfields have
+ * changed:
+ */
+ if (oldneedeyecoords != ctx->_NeedEyeCoords) {
+ /* Recalculate all state that depends on _NeedEyeCoords.
+ */
+ update_modelview_scale(ctx);
+ compute_light_positions( ctx );
+
+ if (ctx->Driver.LightingSpaceChange)
+ ctx->Driver.LightingSpaceChange( ctx );
+ }
+ else {
+ GLuint new_state2 = ctx->NewState;
+
+ /* Recalculate that same state only if it has been invalidated
+ * by other statechanges.
+ */
+ if (new_state2 & _NEW_MODELVIEW)
+ update_modelview_scale(ctx);
+
+ if (new_state2 & (_NEW_LIGHT|_NEW_MODELVIEW))
+ compute_light_positions( ctx );
+ }
+}
+
+
+/**
+ * Drivers may need this if the hardware tnl unit doesn't support the
+ * light-in-modelspace optimization. It's also useful for debugging.
+ */
+void
+_mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag )
+{
+ ctx->_ForceEyeCoords = !flag;
+ ctx->NewState |= _NEW_POINT; /* one of the bits from
+ * _MESA_NEW_NEED_EYE_COORDS.
+ */
+}
+
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * Initialize the n-th light data structure.
+ *
+ * \param l pointer to the gl_light structure to be initialized.
+ * \param n number of the light.
+ * \note 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->SpotDirection, 0.0, 0.0, -1.0 );
+ l->SpotExponent = 0.0;
+ _mesa_invalidate_spot_exp_table( l );
+ l->SpotCutoff = 180.0;
+ l->_CosCutoffNeg = -1.0f;
+ 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;
+}
+
+
+/**
+ * Initialize the light model data structure.
+ *
+ * \param lm pointer to the gl_lightmodel structure to be initialized.
+ */
+static void
+init_lightmodel( struct gl_lightmodel *lm )
+{
+ ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F );
+ lm->LocalViewer = GL_FALSE;
+ lm->TwoSide = GL_FALSE;
+ lm->ColorControl = GL_SINGLE_COLOR;
+}
+
+
+/**
+ * Initialize the material data structure.
+ *
+ * \param m pointer to the gl_material structure to be initialized.
+ */
+static void
+init_material( struct gl_material *m )
+{
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
+
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
+ ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
+}
+
+
+/**
+ * Initialize all lighting state for the given context.
+ */
+void
+_mesa_init_lighting( GLcontext *ctx )
+{
+ GLuint i;
+
+ /* 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 );
+ ctx->Light.ShadeModel = GL_SMOOTH;
+ ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
+ ctx->Light.Enabled = GL_FALSE;
+ ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
+ ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
+ ctx->Light.ColorMaterialBitmask = _mesa_material_bitmask( ctx,
+ GL_FRONT_AND_BACK,
+ GL_AMBIENT_AND_DIFFUSE, ~0,
+ NULL );
+
+ ctx->Light.ColorMaterialEnabled = GL_FALSE;
+ ctx->Light.ClampVertexColor = GL_TRUE;
+
+ /* Lighting miscellaneous */
+ ctx->_ShineTabList = MALLOC_STRUCT( gl_shine_tab );
+ make_empty_list( ctx->_ShineTabList );
+ /* Allocate 10 (arbitrary) shininess lookup tables */
+ 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 );
+ }
+
+ /* Miscellaneous */
+ ctx->Light._NeedEyeCoords = GL_FALSE;
+ ctx->_NeedEyeCoords = GL_FALSE;
+ ctx->_ForceEyeCoords = GL_FALSE;
+ ctx->_ModelViewInvScale = 1.0;
+}
+
+
+/**
+ * Deallocate malloc'd lighting state attached to given context.
+ */
+void
+_mesa_free_lighting_data( GLcontext *ctx )
+{
+ struct gl_shine_tab *s, *tmps;
+
+ /* Free lighting shininess exponentiation table */
+ foreach_s( s, tmps, ctx->_ShineTabList ) {
+ _mesa_free( s );
+ }
+ _mesa_free( ctx->_ShineTabList );
+}
diff --git a/mesalib/src/mesa/main/light.h b/mesalib/src/mesa/main/light.h
new file mode 100644
index 000000000..9c1a5eefa
--- /dev/null
+++ b/mesalib/src/mesa/main/light.h
@@ -0,0 +1,146 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "mtypes.h"
+
+extern void GLAPIENTRY
+_mesa_ShadeModel( GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_ProvokingVertexEXT(GLenum mode);
+
+
+#if _HAVE_FULL_GL
+extern void GLAPIENTRY
+_mesa_ColorMaterial( GLenum face, GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_Lightf( GLenum light, GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params );
+
+extern void GLAPIENTRY
+_mesa_Lighti( GLenum light, GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_LightModelf( GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_LightModelfv( GLenum pname, const GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_LightModeli( GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_LightModeliv( GLenum pname, const GLint *params );
+
+extern void GLAPIENTRY
+_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params );
+
+extern void GLAPIENTRY
+_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params );
+
+
+extern void
+_mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params);
+
+
+/* Lerp between adjacent values in the f(x) lookup table, giving a
+ * continuous function, with adequeate overall accuracy. (Though
+ * still pretty good compared to a straight lookup).
+ * Result should be a GLfloat.
+ */
+#define GET_SHINE_TAB_ENTRY( table, dp, result ) \
+do { \
+ struct gl_shine_tab *_tab = table; \
+ float f = (dp * (SHINE_TABLE_SIZE-1)); \
+ int k = (int) f; \
+ if (k < 0 /* gcc may cast an overflow float value to negative int value*/ \
+ || k > SHINE_TABLE_SIZE-2) \
+ result = (GLfloat) _mesa_pow( dp, _tab->shininess ); \
+ else \
+ result = _tab->tab[k] + (f-k)*(_tab->tab[k+1]-_tab->tab[k]); \
+} while (0)
+
+
+extern GLuint _mesa_material_bitmask( GLcontext *ctx,
+ GLenum face, GLenum pname,
+ GLuint legal,
+ const char * );
+
+extern void _mesa_invalidate_spot_exp_table( struct gl_light *l );
+
+extern void _mesa_invalidate_shine_table( GLcontext *ctx, GLuint i );
+
+extern void _mesa_validate_all_lighting_tables( GLcontext *ctx );
+
+extern void _mesa_update_lighting( GLcontext *ctx );
+
+extern void _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state );
+
+extern void _mesa_update_material( GLcontext *ctx,
+ GLuint bitmask );
+
+extern void _mesa_copy_materials( struct gl_material *dst,
+ const struct gl_material *src,
+ GLuint bitmask );
+
+extern void _mesa_update_color_material( GLcontext *ctx,
+ const GLfloat rgba[4] );
+
+extern void _mesa_init_lighting( GLcontext *ctx );
+
+extern void _mesa_free_lighting_data( GLcontext *ctx );
+
+extern void _mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag );
+
+#else
+#define _mesa_update_color_material( c, r ) ((void)0)
+#define _mesa_validate_all_lighting_tables( c ) ((void)0)
+#define _mesa_invalidate_spot_exp_table( l ) ((void)0)
+#define _mesa_material_bitmask( c, f, p, l, s ) 0
+#define _mesa_init_lighting( c ) ((void)0)
+#define _mesa_free_lighting_data( c ) ((void)0)
+#define _mesa_update_lighting( c ) ((void)0)
+#define _mesa_update_tnl_spaces( c, n ) ((void)0)
+#define GET_SHINE_TAB_ENTRY( table, dp, result ) ((result)=0)
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/lines.c b/mesalib/src/mesa/main/lines.c
new file mode 100644
index 000000000..81d0d33ab
--- /dev/null
+++ b/mesalib/src/mesa/main/lines.c
@@ -0,0 +1,118 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "context.h"
+#include "depth.h"
+#include "lines.h"
+#include "macros.h"
+#include "texstate.h"
+#include "mtypes.h"
+
+
+/**
+ * Set the line width.
+ *
+ * \param width line width in pixels.
+ *
+ * \sa glLineWidth().
+ */
+void GLAPIENTRY
+_mesa_LineWidth( GLfloat width )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (width<=0.0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
+ return;
+ }
+
+ if (ctx->Line.Width == width)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.Width = width;
+
+ if (width != 1.0F)
+ ctx->_TriangleCaps |= DD_LINE_WIDTH;
+ else
+ ctx->_TriangleCaps &= ~DD_LINE_WIDTH;
+
+ if (ctx->Driver.LineWidth)
+ ctx->Driver.LineWidth(ctx, width);
+}
+
+
+/**
+ * Set the line stipple pattern.
+ *
+ * \param factor pattern scale factor.
+ * \param pattern bit pattern.
+ *
+ * \sa glLineStipple().
+ *
+ * Updates gl_line_attrib::StippleFactor and gl_line_attrib::StipplePattern. On
+ * change flushes the vertices and notifies the driver via
+ * the dd_function_table::LineStipple callback.
+ */
+void GLAPIENTRY
+_mesa_LineStipple( GLint factor, GLushort pattern )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ factor = CLAMP( factor, 1, 256 );
+
+ if (ctx->Line.StippleFactor == factor &&
+ ctx->Line.StipplePattern == pattern)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.StippleFactor = factor;
+ ctx->Line.StipplePattern = pattern;
+
+ if (ctx->Driver.LineStipple)
+ ctx->Driver.LineStipple( ctx, factor, pattern );
+}
+
+
+/**
+ * Initialize the context line state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __GLcontextRec::Line and line related constants in
+ * __GLcontextRec::Const.
+ */
+void GLAPIENTRY
+_mesa_init_line( GLcontext * ctx )
+{
+ ctx->Line.SmoothFlag = GL_FALSE;
+ ctx->Line.StippleFlag = GL_FALSE;
+ ctx->Line.Width = 1.0;
+ ctx->Line.StipplePattern = 0xffff;
+ ctx->Line.StippleFactor = 1;
+}
diff --git a/mesalib/src/mesa/main/lines.h b/mesalib/src/mesa/main/lines.h
new file mode 100644
index 000000000..5a47e9858
--- /dev/null
+++ b/mesalib/src/mesa/main/lines.h
@@ -0,0 +1,48 @@
+/**
+ * \file lines.h
+ * Line operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#ifndef LINES_H
+#define LINES_H
+
+
+#include "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_LineWidth( GLfloat width );
+
+extern void GLAPIENTRY
+_mesa_LineStipple( GLint factor, GLushort pattern );
+
+extern void GLAPIENTRY
+_mesa_init_line( GLcontext * ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h
new file mode 100644
index 000000000..3d9a1aba9
--- /dev/null
+++ b/mesalib/src/mesa/main/macros.h
@@ -0,0 +1,695 @@
+/**
+ * \file macros.h
+ * A collection of useful macros.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 MACROS_H
+#define MACROS_H
+
+#include "imports.h"
+
+
+/**
+ * \name Integer / float conversion for colors, normals, etc.
+ */
+/*@{*/
+
+/** Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */
+extern GLfloat _mesa_ubyte_to_float_color_tab[256];
+#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)]
+
+/** 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 GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */
+#define BYTE_TO_FLOAT_TEX(B) ((B) == -128 ? -1.0F : (B) * (1.0F/127.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */
+#define FLOAT_TO_BYTE_TEX(X) ( (GLint) (127.0F * (X)) )
+
+
+/** Convert GLushort in [0,65535] 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, 65535] */
+#define FLOAT_TO_USHORT(X) ((GLuint) ((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 [-1.0,1.0] to GLshort in [-32768,32767] */
+#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
+
+
+/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */
+#define SHORT_TO_FLOAT_TEX(S) ((S) == -32768 ? -1.0F : (S) * (1.0F/32767.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */
+#define FLOAT_TO_SHORT_TEX(X) ( (GLint) (32767.0F * (X)) )
+
+
+/** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
+#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0))
+
+/** 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.0))
+
+/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */
+/* causes overflow:
+#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0 * (X))) - 1) / 2 )
+*/
+/* a close approximation: */
+#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) )
+
+/** Convert GLfloat in [-1.0,1.0] to GLint64 in [-(1<<63),(1 << 63) -1] */
+#define FLOAT_TO_INT64(X) ( (GLint64) (9223372036854775807.0 * (double)(X)) )
+
+
+/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */
+#define INT_TO_FLOAT_TEX(I) ((I) == -2147483648 ? -1.0F : (I) * (1.0F/2147483647.0))
+
+/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */
+#define FLOAT_TO_INT_TEX(X) ( (GLint) (2147483647.0 * (X)) )
+
+
+#define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
+#define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
+#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8))
+#define INT_TO_UBYTE(i) ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23)))
+#define UINT_TO_UBYTE(i) ((GLubyte) ((i) >> 24))
+
+
+#define BYTE_TO_USHORT(b) ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255)))
+#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b))
+#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767))))
+#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
+#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
+#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \
+ us = ( (GLushort) IROUND( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )
+#define CLAMPED_FLOAT_TO_USHORT(us, f) \
+ us = ( (GLushort) IROUND( (f) * 65535.0F) )
+
+/*@}*/
+
+
+/** Stepping a GLfloat pointer by a byte stride */
+#define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i))
+/** Stepping a GLuint pointer by a byte stride */
+#define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i))
+/** Stepping a GLubyte[4] pointer by a byte stride */
+#define STRIDE_4UB(p, i) (p = (GLubyte (*)[4])((GLubyte *)p + i))
+/** Stepping a GLfloat[4] pointer by a byte stride */
+#define STRIDE_4F(p, i) (p = (GLfloat (*)[4])((GLubyte *)p + i))
+/** Stepping a GLchan[4] pointer by a byte stride */
+#define STRIDE_4CHAN(p, i) (p = (GLchan (*)[4])((GLubyte *)p + i))
+/** Stepping a GLchan pointer by a byte stride */
+#define STRIDE_CHAN(p, i) (p = (GLchan *)((GLubyte *)p + i))
+/** Stepping a \p t pointer by a byte stride */
+#define STRIDE_T(p, t, i) (p = (t)((GLubyte *)p + i))
+
+
+/**********************************************************************/
+/** \name 4-element vector operations */
+/*@{*/
+
+/** Zero */
+#define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0
+
+/** Test for equality */
+#define TEST_EQ_4V(a,b) ((a)[0] == (b)[0] && \
+ (a)[1] == (b)[1] && \
+ (a)[2] == (b)[2] && \
+ (a)[3] == (b)[3])
+
+/** Test for equality (unsigned bytes) */
+#if defined(__i386__)
+#define TEST_EQ_4UBV(DST, SRC) *((GLuint*)(DST)) == *((GLuint*)(SRC))
+#else
+#define TEST_EQ_4UBV(DST, SRC) TEST_EQ_4V(DST, SRC)
+#endif
+
+/** Copy a 4-element vector */
+#define COPY_4V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+ (DST)[3] = (SRC)[3]; \
+} while (0)
+
+/** Copy a 4-element vector with cast */
+#define COPY_4V_CAST( DST, SRC, CAST ) \
+do { \
+ (DST)[0] = (CAST)(SRC)[0]; \
+ (DST)[1] = (CAST)(SRC)[1]; \
+ (DST)[2] = (CAST)(SRC)[2]; \
+ (DST)[3] = (CAST)(SRC)[3]; \
+} while (0)
+
+/** Copy a 4-element unsigned byte vector */
+#if defined(__i386__)
+#define COPY_4UBV(DST, SRC) \
+do { \
+ *((GLuint*)(DST)) = *((GLuint*)(SRC)); \
+} while (0)
+#else
+/* The GLuint cast might fail if DST or SRC are not dword-aligned (RISC) */
+#define COPY_4UBV(DST, SRC) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+ (DST)[3] = (SRC)[3]; \
+} while (0)
+#endif
+
+/**
+ * Copy a 4-element float vector (avoid using FPU registers)
+ * XXX Could use two 64-bit moves on 64-bit systems
+ */
+#define COPY_4FV( DST, SRC ) \
+do { \
+ const GLuint *_s = (const GLuint *) (SRC); \
+ GLuint *_d = (GLuint *) (DST); \
+ _d[0] = _s[0]; \
+ _d[1] = _s[1]; \
+ _d[2] = _s[2]; \
+ _d[3] = _s[3]; \
+} while (0)
+
+/** Copy \p SZ elements into a 4-element vector */
+#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)
+
+/** Copy \p SZ elements into a homegeneous (4-element) vector, giving
+ * default values to the remaining */
+#define COPY_CLEAN_4V(DST, SZ, SRC) \
+do { \
+ ASSIGN_4V( DST, 0, 0, 0, 1 ); \
+ COPY_SZ_4V( DST, SZ, SRC ); \
+} while (0)
+
+/** Subtraction */
+#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)
+
+/** Addition */
+#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)
+
+/** Element-wise multiplication */
+#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)
+
+/** In-place addition */
+#define ACC_4V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+ (DST)[2] += (SRC)[2]; \
+ (DST)[3] += (SRC)[3]; \
+} while (0)
+
+/** Element-wise multiplication and addition */
+#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)
+
+/** In-place scalar multiplication and addition */
+#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)
+
+/** Scalar multiplication */
+#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)
+
+/** In-place scalar multiplication */
+#define SELF_SCALE_SCALAR_4V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+ (DST)[2] *= S; \
+ (DST)[3] *= S; \
+} while (0)
+
+/** Assignment */
+#define ASSIGN_4V( V, V0, V1, V2, V3 ) \
+do { \
+ V[0] = V0; \
+ V[1] = V1; \
+ V[2] = V2; \
+ V[3] = V3; \
+} while(0)
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name 3-element vector operations*/
+/*@{*/
+
+/** Zero */
+#define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0
+
+/** Test for equality */
+#define TEST_EQ_3V(a,b) \
+ ((a)[0] == (b)[0] && \
+ (a)[1] == (b)[1] && \
+ (a)[2] == (b)[2])
+
+/** Copy a 3-element vector */
+#define COPY_3V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+} while (0)
+
+/** Copy a 3-element vector with cast */
+#define COPY_3V_CAST( DST, SRC, CAST ) \
+do { \
+ (DST)[0] = (CAST)(SRC)[0]; \
+ (DST)[1] = (CAST)(SRC)[1]; \
+ (DST)[2] = (CAST)(SRC)[2]; \
+} while (0)
+
+/** Copy a 3-element float vector */
+#define COPY_3FV( DST, SRC ) \
+do { \
+ const GLfloat *_tmp = (SRC); \
+ (DST)[0] = _tmp[0]; \
+ (DST)[1] = _tmp[1]; \
+ (DST)[2] = _tmp[2]; \
+} while (0)
+
+/** Subtraction */
+#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)
+
+/** Addition */
+#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)
+
+/** In-place scalar multiplication */
+#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)
+
+/** In-place element-wise multiplication */
+#define SELF_SCALE_3V( DST, SRC ) \
+do { \
+ (DST)[0] *= (SRC)[0]; \
+ (DST)[1] *= (SRC)[1]; \
+ (DST)[2] *= (SRC)[2]; \
+} while (0)
+
+/** In-place addition */
+#define ACC_3V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+ (DST)[2] += (SRC)[2]; \
+} while (0)
+
+/** Element-wise multiplication and addition */
+#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)
+
+/** Scalar multiplication */
+#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)
+
+/** In-place scalar multiplication and addition */
+#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)
+
+/** In-place scalar multiplication */
+#define SELF_SCALE_SCALAR_3V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+ (DST)[2] *= S; \
+} while (0)
+
+/** In-place scalar addition */
+#define ACC_SCALAR_3V( DST, S ) \
+do { \
+ (DST)[0] += S; \
+ (DST)[1] += S; \
+ (DST)[2] += S; \
+} while (0)
+
+/** Assignment */
+#define ASSIGN_3V( V, V0, V1, V2 ) \
+do { \
+ V[0] = V0; \
+ V[1] = V1; \
+ V[2] = V2; \
+} while(0)
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name 2-element vector operations*/
+/*@{*/
+
+/** Zero */
+#define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0
+
+/** Copy a 2-element vector */
+#define COPY_2V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+} while (0)
+
+/** Copy a 2-element vector with cast */
+#define COPY_2V_CAST( DST, SRC, CAST ) \
+do { \
+ (DST)[0] = (CAST)(SRC)[0]; \
+ (DST)[1] = (CAST)(SRC)[1]; \
+} while (0)
+
+/** Copy a 2-element float vector */
+#define COPY_2FV( DST, SRC ) \
+do { \
+ const GLfloat *_tmp = (SRC); \
+ (DST)[0] = _tmp[0]; \
+ (DST)[1] = _tmp[1]; \
+} while (0)
+
+/** Subtraction */
+#define SUB_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] - (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] - (SRCB)[1]; \
+} while (0)
+
+/** Addition */
+#define ADD_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] + (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] + (SRCB)[1]; \
+} while (0)
+
+/** In-place scalar multiplication */
+#define SCALE_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] * (SRCB)[1]; \
+} while (0)
+
+/** In-place addition */
+#define ACC_2V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+} while (0)
+
+/** Element-wise multiplication and addition */
+#define ACC_SCALE_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] += (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] += (SRCA)[1] * (SRCB)[1]; \
+} while (0)
+
+/** Scalar multiplication */
+#define SCALE_SCALAR_2V( DST, S, SRCB ) \
+do { \
+ (DST)[0] = S * (SRCB)[0]; \
+ (DST)[1] = S * (SRCB)[1]; \
+} while (0)
+
+/** In-place scalar multiplication and addition */
+#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \
+do { \
+ (DST)[0] += S * (SRCB)[0]; \
+ (DST)[1] += S * (SRCB)[1]; \
+} while (0)
+
+/** In-place scalar multiplication */
+#define SELF_SCALE_SCALAR_2V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+} while (0)
+
+/** In-place scalar addition */
+#define ACC_SCALAR_2V( DST, S ) \
+do { \
+ (DST)[0] += S; \
+ (DST)[1] += S; \
+} while (0)
+
+/** Assign scalers to short vectors */
+#define ASSIGN_2V( V, V0, V1 ) \
+do { \
+ V[0] = V0; \
+ V[1] = V1; \
+} while(0)
+
+/*@}*/
+
+
+/** \name Linear interpolation macros */
+/*@{*/
+
+/**
+ * Linear interpolation
+ *
+ * \note \p OUT argument is evaluated twice!
+ * \note Be wary of using *coord++ as an argument to any of these macros!
+ */
+#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
+
+/* Can do better with integer math
+ */
+#define INTERP_UB( t, dstub, outub, inub ) \
+do { \
+ GLfloat inf = UBYTE_TO_FLOAT( inub ); \
+ GLfloat outf = UBYTE_TO_FLOAT( outub ); \
+ GLfloat dstf = LINTERP( t, outf, inf ); \
+ UNCLAMPED_FLOAT_TO_UBYTE( dstub, dstf ); \
+} while (0)
+
+#define INTERP_CHAN( t, dstc, outc, inc ) \
+do { \
+ GLfloat inf = CHAN_TO_FLOAT( inc ); \
+ GLfloat outf = CHAN_TO_FLOAT( outc ); \
+ GLfloat dstf = LINTERP( t, outf, inf ); \
+ UNCLAMPED_FLOAT_TO_CHAN( dstc, dstf ); \
+} while (0)
+
+#define INTERP_UI( t, dstui, outui, inui ) \
+ dstui = (GLuint) (GLint) LINTERP( (t), (GLfloat) (outui), (GLfloat) (inui) )
+
+#define INTERP_F( t, dstf, outf, inf ) \
+ dstf = LINTERP( t, outf, inf )
+
+#define INTERP_4F( t, dst, out, in ) \
+do { \
+ dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \
+ dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \
+ dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \
+ dst[3] = LINTERP( (t), (out)[3], (in)[3] ); \
+} while (0)
+
+#define INTERP_3F( t, dst, out, in ) \
+do { \
+ dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \
+ dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \
+ dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \
+} while (0)
+
+#define INTERP_4CHAN( t, dst, out, in ) \
+do { \
+ INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \
+ INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \
+ INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \
+ INTERP_CHAN( (t), (dst)[3], (out)[3], (in)[3] ); \
+} while (0)
+
+#define INTERP_3CHAN( t, dst, out, in ) \
+do { \
+ INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \
+ INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \
+ INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \
+} while (0)
+
+#define INTERP_SZ( t, vec, to, out, in, sz ) \
+do { \
+ switch (sz) { \
+ case 4: vec[to][3] = LINTERP( (t), (vec)[out][3], (vec)[in][3] ); \
+ case 3: vec[to][2] = LINTERP( (t), (vec)[out][2], (vec)[in][2] ); \
+ case 2: vec[to][1] = LINTERP( (t), (vec)[out][1], (vec)[in][1] ); \
+ case 1: vec[to][0] = LINTERP( (t), (vec)[out][0], (vec)[in][0] ); \
+ } \
+} while(0)
+
+/*@}*/
+
+
+
+/** 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)) )
+
+
+
+/** Minimum of two values: */
+#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
+
+/** Maximum 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] )
+
+/** Dot product of two 4-element vectors */
+#define DOT4V(v,a,b,c,d) (v[0]*(a) + v[1]*(b) + v[2]*(c) + v[3]*(d))
+
+
+/** Cross product of two 3-element vectors */
+#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)
+
+
+/* Normalize a 3-element vector to unit length. */
+#define NORMALIZE_3FV( V ) \
+do { \
+ GLfloat len = (GLfloat) LEN_SQUARED_3FV(V); \
+ if (len) { \
+ len = INV_SQRTF(len); \
+ (V)[0] = (GLfloat) ((V)[0] * len); \
+ (V)[1] = (GLfloat) ((V)[1] * len); \
+ (V)[2] = (GLfloat) ((V)[2] * len); \
+ } \
+} while(0)
+
+#define LEN_3FV( V ) (SQRTF((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2]))
+#define LEN_2FV( V ) (SQRTF((V)[0]*(V)[0]+(V)[1]*(V)[1]))
+
+#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2])
+#define LEN_SQUARED_2FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1])
+
+
+/** casts to silence warnings with some compilers */
+#define ENUM_TO_INT(E) ((GLint)(E))
+#define ENUM_TO_FLOAT(E) ((GLfloat)(GLint)(E))
+#define ENUM_TO_DOUBLE(E) ((GLdouble)(GLint)(E))
+#define ENUM_TO_BOOLEAN(E) ((E) ? GL_TRUE : GL_FALSE)
+
+
+#endif
diff --git a/mesalib/src/mesa/main/matrix.c b/mesalib/src/mesa/main/matrix.c
new file mode 100644
index 000000000..ebc3cbd59
--- /dev/null
+++ b/mesalib/src/mesa/main/matrix.c
@@ -0,0 +1,793 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file matrix.c
+ * Matrix operations.
+ *
+ * \note
+ * -# 4x4 transformation matrices are stored in memory in column major order.
+ * -# Points/vertices are to be thought of as column vectors.
+ * -# Transformation of a point p by a matrix M is: p' = M * p
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "math/m_matrix.h"
+
+
+/**
+ * Apply a perspective projection matrix.
+ *
+ * \param left left clipping plane coordinate.
+ * \param right right clipping plane coordinate.
+ * \param bottom bottom clipping plane coordinate.
+ * \param top top clipping plane coordinate.
+ * \param nearval distance to the near clipping plane.
+ * \param farval distance to the far clipping plane.
+ *
+ * \sa glFrustum().
+ *
+ * Flushes vertices and validates parameters. Calls _math_matrix_frustum() with
+ * the top matrix of the current matrix stack and sets
+ * __GLcontextRec::NewState.
+ */
+void GLAPIENTRY
+_mesa_Frustum( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (nearval <= 0.0 ||
+ farval <= 0.0 ||
+ nearval == farval ||
+ left == right ||
+ top == bottom)
+ {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glFrustum" );
+ return;
+ }
+
+ _math_matrix_frustum( ctx->CurrentStack->Top,
+ (GLfloat) left, (GLfloat) right,
+ (GLfloat) bottom, (GLfloat) top,
+ (GLfloat) nearval, (GLfloat) farval );
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Apply an orthographic projection matrix.
+ *
+ * \param left left clipping plane coordinate.
+ * \param right right clipping plane coordinate.
+ * \param bottom bottom clipping plane coordinate.
+ * \param top top clipping plane coordinate.
+ * \param nearval distance to the near clipping plane.
+ * \param farval distance to the far clipping plane.
+ *
+ * \sa glOrtho().
+ *
+ * Flushes vertices and validates parameters. Calls _math_matrix_ortho() with
+ * the top matrix of the current matrix stack and sets
+ * __GLcontextRec::NewState.
+ */
+void GLAPIENTRY
+_mesa_Ortho( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glOrtho(%f, %f, %f, %f, %f, %f)\n",
+ left, right, bottom, top, nearval, farval);
+
+ if (left == right ||
+ bottom == top ||
+ nearval == farval)
+ {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glOrtho" );
+ return;
+ }
+
+ _math_matrix_ortho( ctx->CurrentStack->Top,
+ (GLfloat) left, (GLfloat) right,
+ (GLfloat) bottom, (GLfloat) top,
+ (GLfloat) nearval, (GLfloat) farval );
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Set the current matrix stack.
+ *
+ * \param mode matrix stack.
+ *
+ * \sa glMatrixMode().
+ *
+ * Flushes the vertices, validates the parameter and updates
+ * __GLcontextRec::CurrentStack and gl_transform_attrib::MatrixMode with the
+ * specified matrix stack.
+ */
+void GLAPIENTRY
+_mesa_MatrixMode( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+
+ switch (mode) {
+ case GL_MODELVIEW:
+ ctx->CurrentStack = &ctx->ModelviewMatrixStack;
+ break;
+ case GL_PROJECTION:
+ ctx->CurrentStack = &ctx->ProjectionMatrixStack;
+ break;
+ case GL_TEXTURE:
+ /* This error check is disabled because if we're called from
+ * glPopAttrib() when the active texture unit is >= MaxTextureCoordUnits
+ * we'll generate an unexpected error.
+ * From the GL_ARB_vertex_shader spec it sounds like we should instead
+ * do error checking in other places when we actually try to access
+ * texture matrices beyond MaxTextureCoordUnits.
+ */
+#if 0
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMatrixMode(invalid tex unit %d)",
+ ctx->Texture.CurrentUnit);
+ return;
+ }
+#endif
+ ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->TextureMatrixStack));
+ ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
+ break;
+ case GL_COLOR:
+ ctx->CurrentStack = &ctx->ColorMatrixStack;
+ break;
+ case GL_MATRIX0_NV:
+ case GL_MATRIX1_NV:
+ case GL_MATRIX2_NV:
+ case GL_MATRIX3_NV:
+ case GL_MATRIX4_NV:
+ case GL_MATRIX5_NV:
+ case GL_MATRIX6_NV:
+ case GL_MATRIX7_NV:
+ if (ctx->Extensions.NV_vertex_program) {
+ ctx->CurrentStack = &ctx->ProgramMatrixStack[mode - GL_MATRIX0_NV];
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" );
+ return;
+ }
+ break;
+ case GL_MATRIX0_ARB:
+ case GL_MATRIX1_ARB:
+ case GL_MATRIX2_ARB:
+ case GL_MATRIX3_ARB:
+ case GL_MATRIX4_ARB:
+ case GL_MATRIX5_ARB:
+ case GL_MATRIX6_ARB:
+ case GL_MATRIX7_ARB:
+ if (ctx->Extensions.ARB_vertex_program ||
+ ctx->Extensions.ARB_fragment_program) {
+ const GLuint m = mode - GL_MATRIX0_ARB;
+ if (m > ctx->Const.MaxProgramMatrices) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glMatrixMode(GL_MATRIX%d_ARB)", m);
+ return;
+ }
+ ctx->CurrentStack = &ctx->ProgramMatrixStack[m];
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" );
+ return;
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" );
+ return;
+ }
+
+ ctx->Transform.MatrixMode = mode;
+}
+
+
+/**
+ * Push the current matrix stack.
+ *
+ * \sa glPushMatrix().
+ *
+ * Verifies the current matrix stack is not full, and duplicates the top-most
+ * matrix in the stack. Marks __GLcontextRec::NewState with the stack dirty
+ * flag.
+ */
+void GLAPIENTRY
+_mesa_PushMatrix( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_matrix_stack *stack = ctx->CurrentStack;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPushMatrix %s\n",
+ _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+ if (stack->Depth + 1 >= stack->MaxDepth) {
+ if (ctx->Transform.MatrixMode == GL_TEXTURE) {
+ _mesa_error(ctx, GL_STACK_OVERFLOW,
+ "glPushMatrix(mode=GL_TEXTURE, unit=%d)",
+ ctx->Texture.CurrentUnit);
+ }
+ else {
+ _mesa_error(ctx, GL_STACK_OVERFLOW, "glPushMatrix(mode=%s)",
+ _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+ }
+ return;
+ }
+ _math_matrix_copy( &stack->Stack[stack->Depth + 1],
+ &stack->Stack[stack->Depth] );
+ stack->Depth++;
+ stack->Top = &(stack->Stack[stack->Depth]);
+ ctx->NewState |= stack->DirtyFlag;
+}
+
+
+/**
+ * Pop the current matrix stack.
+ *
+ * \sa glPopMatrix().
+ *
+ * Flushes the vertices, verifies the current matrix stack is not empty, and
+ * moves the stack head down. Marks __GLcontextRec::NewState with the dirty
+ * stack flag.
+ */
+void GLAPIENTRY
+_mesa_PopMatrix( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_matrix_stack *stack = ctx->CurrentStack;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPopMatrix %s\n",
+ _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+ if (stack->Depth == 0) {
+ if (ctx->Transform.MatrixMode == GL_TEXTURE) {
+ _mesa_error(ctx, GL_STACK_UNDERFLOW,
+ "glPopMatrix(mode=GL_TEXTURE, unit=%d)",
+ ctx->Texture.CurrentUnit);
+ }
+ else {
+ _mesa_error(ctx, GL_STACK_UNDERFLOW, "glPopMatrix(mode=%s)",
+ _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+ }
+ return;
+ }
+ stack->Depth--;
+ stack->Top = &(stack->Stack[stack->Depth]);
+ ctx->NewState |= stack->DirtyFlag;
+}
+
+
+/**
+ * Replace the current matrix with the identity matrix.
+ *
+ * \sa glLoadIdentity().
+ *
+ * Flushes the vertices and calls _math_matrix_set_identity() with the top-most
+ * matrix in the current stack. Marks __GLcontextRec::NewState with the stack
+ * dirty flag.
+ */
+void GLAPIENTRY
+_mesa_LoadIdentity( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glLoadIdentity()");
+
+ _math_matrix_set_identity( ctx->CurrentStack->Top );
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Replace the current matrix with a given matrix.
+ *
+ * \param m matrix.
+ *
+ * \sa glLoadMatrixf().
+ *
+ * Flushes the vertices and calls _math_matrix_loadf() with the top-most matrix
+ * in the current stack and the given matrix. Marks __GLcontextRec::NewState
+ * with the dirty stack flag.
+ */
+void GLAPIENTRY
+_mesa_LoadMatrixf( const GLfloat *m )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (!m) return;
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glLoadMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _math_matrix_loadf( ctx->CurrentStack->Top, m );
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Multiply the current matrix with a given matrix.
+ *
+ * \param m matrix.
+ *
+ * \sa glMultMatrixf().
+ *
+ * Flushes the vertices and calls _math_matrix_mul_floats() with the top-most
+ * matrix in the current stack and the given matrix. Marks
+ * __GLcontextRec::NewState with the dirty stack flag.
+ */
+void GLAPIENTRY
+_mesa_MultMatrixf( const GLfloat *m )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (!m) return;
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glMultMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _math_matrix_mul_floats( ctx->CurrentStack->Top, m );
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Multiply the current matrix with a rotation matrix.
+ *
+ * \param angle angle of rotation, in degrees.
+ * \param x rotation vector x coordinate.
+ * \param y rotation vector y coordinate.
+ * \param z rotation vector z coordinate.
+ *
+ * \sa glRotatef().
+ *
+ * Flushes the vertices and calls _math_matrix_rotate() with the top-most
+ * matrix in the current stack and the given parameters. Marks
+ * __GLcontextRec::NewState with the dirty stack flag.
+ */
+void GLAPIENTRY
+_mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ if (angle != 0.0F) {
+ _math_matrix_rotate( ctx->CurrentStack->Top, angle, x, y, z);
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+ }
+}
+
+
+/**
+ * Multiply the current matrix with a general scaling matrix.
+ *
+ * \param x x axis scale factor.
+ * \param y y axis scale factor.
+ * \param z z axis scale factor.
+ *
+ * \sa glScalef().
+ *
+ * Flushes the vertices and calls _math_matrix_scale() with the top-most
+ * matrix in the current stack and the given parameters. Marks
+ * __GLcontextRec::NewState with the dirty stack flag.
+ */
+void GLAPIENTRY
+_mesa_Scalef( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _math_matrix_scale( ctx->CurrentStack->Top, x, y, z);
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+/**
+ * Multiply the current matrix with a translation matrix.
+ *
+ * \param x translation vector x coordinate.
+ * \param y translation vector y coordinate.
+ * \param z translation vector z coordinate.
+ *
+ * \sa glTranslatef().
+ *
+ * Flushes the vertices and calls _math_matrix_translate() with the top-most
+ * matrix in the current stack and the given parameters. Marks
+ * __GLcontextRec::NewState with the dirty stack flag.
+ */
+void GLAPIENTRY
+_mesa_Translatef( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _math_matrix_translate( ctx->CurrentStack->Top, x, y, z);
+ ctx->NewState |= ctx->CurrentStack->DirtyFlag;
+}
+
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_LoadMatrixd( const GLdouble *m )
+{
+ GLint i;
+ GLfloat f[16];
+ if (!m) return;
+ for (i = 0; i < 16; i++)
+ f[i] = (GLfloat) m[i];
+ _mesa_LoadMatrixf(f);
+}
+
+void GLAPIENTRY
+_mesa_MultMatrixd( const GLdouble *m )
+{
+ GLint i;
+ GLfloat f[16];
+ if (!m) return;
+ for (i = 0; i < 16; i++)
+ f[i] = (GLfloat) m[i];
+ _mesa_MultMatrixf( f );
+}
+
+
+void GLAPIENTRY
+_mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
+{
+ _mesa_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+
+void GLAPIENTRY
+_mesa_Scaled( GLdouble x, GLdouble y, GLdouble z )
+{
+ _mesa_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+
+
+void GLAPIENTRY
+_mesa_Translated( GLdouble x, GLdouble y, GLdouble z )
+{
+ _mesa_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
+}
+#endif
+
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_LoadTransposeMatrixfARB( const GLfloat *m )
+{
+ GLfloat tm[16];
+ if (!m) return;
+ _math_transposef(tm, m);
+ _mesa_LoadMatrixf(tm);
+}
+
+
+void GLAPIENTRY
+_mesa_LoadTransposeMatrixdARB( const GLdouble *m )
+{
+ GLfloat tm[16];
+ if (!m) return;
+ _math_transposefd(tm, m);
+ _mesa_LoadMatrixf(tm);
+}
+
+
+void GLAPIENTRY
+_mesa_MultTransposeMatrixfARB( const GLfloat *m )
+{
+ GLfloat tm[16];
+ if (!m) return;
+ _math_transposef(tm, m);
+ _mesa_MultMatrixf(tm);
+}
+
+
+void GLAPIENTRY
+_mesa_MultTransposeMatrixdARB( const GLdouble *m )
+{
+ GLfloat tm[16];
+ if (!m) return;
+ _math_transposefd(tm, m);
+ _mesa_MultMatrixf(tm);
+}
+#endif
+
+
+
+/**********************************************************************/
+/** \name State management */
+/*@{*/
+
+
+/**
+ * Update the projection matrix stack.
+ *
+ * \param ctx GL context.
+ *
+ * Calls _math_matrix_analyse() with the top-matrix of the projection matrix
+ * stack, and recomputes user clip positions if necessary.
+ *
+ * \note This routine references __GLcontextRec::Tranform attribute values to
+ * compute userclip positions in clip space, but is only called on
+ * _NEW_PROJECTION. The _mesa_ClipPlane() function keeps these values up to
+ * date across changes to the __GLcontextRec::Transform attributes.
+ */
+static void
+update_projection( GLcontext *ctx )
+{
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
+
+#if FEATURE_userclip
+ /* Recompute clip plane positions in clipspace. This is also done
+ * in _mesa_ClipPlane().
+ */
+ if (ctx->Transform.ClipPlanesEnabled) {
+ GLuint p;
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrixStack.Top->inv );
+ }
+ }
+ }
+#endif
+}
+
+
+/**
+ * Calculate the combined modelview-projection matrix.
+ *
+ * \param ctx GL context.
+ *
+ * Multiplies the top matrices of the projection and model view stacks into
+ * __GLcontextRec::_ModelProjectMatrix via _math_matrix_mul_matrix() and
+ * analyzes the resulting matrix via _math_matrix_analyse().
+ */
+static void
+calculate_model_project_matrix( GLcontext *ctx )
+{
+ _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix,
+ ctx->ProjectionMatrixStack.Top,
+ ctx->ModelviewMatrixStack.Top );
+
+ _math_matrix_analyse( &ctx->_ModelProjectMatrix );
+}
+
+
+/**
+ * Updates the combined modelview-projection matrix.
+ *
+ * \param ctx GL context.
+ * \param new_state new state bit mask.
+ *
+ * If there is a new model view matrix then analyzes it. If there is a new
+ * projection matrix, updates it. Finally calls
+ * calculate_model_project_matrix() to recalculate the modelview-projection
+ * matrix.
+ */
+void _mesa_update_modelview_project( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_MODELVIEW) {
+ _math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
+
+ /* Bring cull position uptodate.
+ */
+ TRANSFORM_POINT3( ctx->Transform.CullObjPos,
+ ctx->ModelviewMatrixStack.Top->inv,
+ ctx->Transform.CullEyePos );
+ }
+
+
+ if (new_state & _NEW_PROJECTION)
+ update_projection( ctx );
+
+ /* Keep ModelviewProject uptodate always to allow tnl
+ * implementations that go model->clip even when eye is required.
+ */
+ calculate_model_project_matrix(ctx);
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** Matrix stack initialization */
+/*@{*/
+
+
+/**
+ * Initialize a matrix stack.
+ *
+ * \param stack matrix stack.
+ * \param maxDepth maximum stack depth.
+ * \param dirtyFlag dirty flag.
+ *
+ * Allocates an array of \p maxDepth elements for the matrix stack and calls
+ * _math_matrix_ctr() and _math_matrix_alloc_inv() for each element to
+ * initialize it.
+ */
+static void
+init_matrix_stack( struct gl_matrix_stack *stack,
+ GLuint maxDepth, GLuint dirtyFlag )
+{
+ GLuint i;
+
+ stack->Depth = 0;
+ stack->MaxDepth = maxDepth;
+ stack->DirtyFlag = dirtyFlag;
+ /* The stack */
+ stack->Stack = (GLmatrix *) CALLOC(maxDepth * sizeof(GLmatrix));
+ for (i = 0; i < maxDepth; i++) {
+ _math_matrix_ctr(&stack->Stack[i]);
+ _math_matrix_alloc_inv(&stack->Stack[i]);
+ }
+ stack->Top = stack->Stack;
+}
+
+/**
+ * Free matrix stack.
+ *
+ * \param stack matrix stack.
+ *
+ * Calls _math_matrix_dtr() for each element of the matrix stack and
+ * frees the array.
+ */
+static void
+free_matrix_stack( struct gl_matrix_stack *stack )
+{
+ GLuint i;
+ for (i = 0; i < stack->MaxDepth; i++) {
+ _math_matrix_dtr(&stack->Stack[i]);
+ }
+ FREE(stack->Stack);
+ stack->Stack = stack->Top = NULL;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+
+/**
+ * Initialize the context matrix data.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes each of the matrix stacks and the combined modelview-projection
+ * matrix.
+ */
+void _mesa_init_matrix( GLcontext * ctx )
+{
+ GLint i;
+
+ /* Initialize matrix stacks */
+ init_matrix_stack(&ctx->ModelviewMatrixStack, MAX_MODELVIEW_STACK_DEPTH,
+ _NEW_MODELVIEW);
+ init_matrix_stack(&ctx->ProjectionMatrixStack, MAX_PROJECTION_STACK_DEPTH,
+ _NEW_PROJECTION);
+ init_matrix_stack(&ctx->ColorMatrixStack, MAX_COLOR_STACK_DEPTH,
+ _NEW_COLOR_MATRIX);
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+ init_matrix_stack(&ctx->TextureMatrixStack[i], MAX_TEXTURE_STACK_DEPTH,
+ _NEW_TEXTURE_MATRIX);
+ for (i = 0; i < MAX_PROGRAM_MATRICES; i++)
+ init_matrix_stack(&ctx->ProgramMatrixStack[i],
+ MAX_PROGRAM_MATRIX_STACK_DEPTH, _NEW_TRACK_MATRIX);
+ ctx->CurrentStack = &ctx->ModelviewMatrixStack;
+
+ /* Init combined Modelview*Projection matrix */
+ _math_matrix_ctr( &ctx->_ModelProjectMatrix );
+}
+
+
+/**
+ * Free the context matrix data.
+ *
+ * \param ctx GL context.
+ *
+ * Frees each of the matrix stacks and the combined modelview-projection
+ * matrix.
+ */
+void _mesa_free_matrix_data( GLcontext *ctx )
+{
+ GLint i;
+
+ free_matrix_stack(&ctx->ModelviewMatrixStack);
+ free_matrix_stack(&ctx->ProjectionMatrixStack);
+ free_matrix_stack(&ctx->ColorMatrixStack);
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+ free_matrix_stack(&ctx->TextureMatrixStack[i]);
+ for (i = 0; i < MAX_PROGRAM_MATRICES; i++)
+ free_matrix_stack(&ctx->ProgramMatrixStack[i]);
+ /* combined Modelview*Projection matrix */
+ _math_matrix_dtr( &ctx->_ModelProjectMatrix );
+
+}
+
+
+/**
+ * Initialize the context transform attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * \todo Move this to a new file with other 'transform' routines.
+ */
+void _mesa_init_transform( GLcontext *ctx )
+{
+ GLint i;
+
+ /* Transformation group */
+ ctx->Transform.MatrixMode = GL_MODELVIEW;
+ ctx->Transform.Normalize = GL_FALSE;
+ ctx->Transform.RescaleNormals = GL_FALSE;
+ ctx->Transform.RasterPositionUnclipped = GL_FALSE;
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 );
+ }
+ ctx->Transform.ClipPlanesEnabled = 0;
+
+ ASSIGN_4V( ctx->Transform.CullObjPos, 0.0, 0.0, 1.0, 0.0 );
+ ASSIGN_4V( ctx->Transform.CullEyePos, 0.0, 0.0, 1.0, 0.0 );
+}
+
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/matrix.h b/mesalib/src/mesa/main/matrix.h
new file mode 100644
index 000000000..a53d1045c
--- /dev/null
+++ b/mesalib/src/mesa/main/matrix.h
@@ -0,0 +1,112 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_Frustum( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval );
+
+extern void GLAPIENTRY
+_mesa_Ortho( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval );
+
+extern void GLAPIENTRY
+_mesa_PushMatrix( void );
+
+extern void GLAPIENTRY
+_mesa_PopMatrix( void );
+
+extern void GLAPIENTRY
+_mesa_LoadIdentity( void );
+
+extern void GLAPIENTRY
+_mesa_LoadMatrixf( const GLfloat *m );
+
+extern void GLAPIENTRY
+_mesa_LoadMatrixd( const GLdouble *m );
+
+extern void GLAPIENTRY
+_mesa_MatrixMode( GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_MultMatrixf( const GLfloat *m );
+
+extern void GLAPIENTRY
+_mesa_MultMatrixd( const GLdouble *m );
+
+extern void GLAPIENTRY
+_mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z );
+
+extern void GLAPIENTRY
+_mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z );
+
+extern void GLAPIENTRY
+_mesa_Scalef( GLfloat x, GLfloat y, GLfloat z );
+
+extern void GLAPIENTRY
+_mesa_Scaled( GLdouble x, GLdouble y, GLdouble z );
+
+extern void GLAPIENTRY
+_mesa_Translatef( GLfloat x, GLfloat y, GLfloat z );
+
+extern void GLAPIENTRY
+_mesa_Translated( GLdouble x, GLdouble y, GLdouble z );
+
+extern void GLAPIENTRY
+_mesa_LoadTransposeMatrixfARB( const GLfloat *m );
+
+extern void GLAPIENTRY
+_mesa_LoadTransposeMatrixdARB( const GLdouble *m );
+
+extern void GLAPIENTRY
+_mesa_MultTransposeMatrixfARB( const GLfloat *m );
+
+extern void GLAPIENTRY
+_mesa_MultTransposeMatrixdARB( const GLdouble *m );
+
+
+extern void
+_mesa_init_matrix( GLcontext * ctx );
+
+extern void
+_mesa_init_transform( GLcontext *ctx );
+
+extern void
+_mesa_free_matrix_data( GLcontext *ctx );
+
+extern void
+_mesa_update_modelview_project( GLcontext *ctx, GLuint newstate );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/mfeatures.h b/mesalib/src/mesa/main/mfeatures.h
new file mode 100644
index 000000000..e23cdb1f4
--- /dev/null
+++ b/mesalib/src/mesa/main/mfeatures.h
@@ -0,0 +1,86 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file mfeatures.h
+ * Flags to enable/disable specific parts of the API.
+ */
+
+#ifndef FEATURES_H
+#define FEATURES_H
+
+
+#ifndef _HAVE_FULL_GL
+#define _HAVE_FULL_GL 1
+#endif
+
+#define FEATURE_accum _HAVE_FULL_GL
+#define FEATURE_attrib_stack _HAVE_FULL_GL
+#define FEATURE_colortable _HAVE_FULL_GL
+#define FEATURE_convolve _HAVE_FULL_GL
+#define FEATURE_dispatch _HAVE_FULL_GL
+#define FEATURE_dlist _HAVE_FULL_GL
+#define FEATURE_draw_read_buffer _HAVE_FULL_GL
+#define FEATURE_drawpix _HAVE_FULL_GL
+#define FEATURE_evaluators _HAVE_FULL_GL
+#define FEATURE_feedback _HAVE_FULL_GL
+#define FEATURE_fixedpt 0
+#define FEATURE_histogram _HAVE_FULL_GL
+#define FEATURE_pixel_transfer _HAVE_FULL_GL
+#define FEATURE_point_size_array 0
+#define FEATURE_texgen _HAVE_FULL_GL
+#define FEATURE_texture_fxt1 _HAVE_FULL_GL
+#define FEATURE_texture_s3tc _HAVE_FULL_GL
+#define FEATURE_userclip _HAVE_FULL_GL
+#define FEATURE_vertex_array_byte 0
+#define FEATURE_windowpos _HAVE_FULL_GL
+#define FEATURE_es2_glsl 0
+
+#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL
+#define FEATURE_ARB_fragment_program _HAVE_FULL_GL
+#define FEATURE_ARB_framebuffer_object _HAVE_FULL_GL
+#define FEATURE_ARB_map_buffer_range _HAVE_FULL_GL
+#define FEATURE_ARB_pixel_buffer_object _HAVE_FULL_GL
+#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL
+#define FEATURE_ARB_vertex_program _HAVE_FULL_GL
+#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL
+#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL
+#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader)
+#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects
+#define FEATURE_ARB_shading_language_120 FEATURE_ARB_shader_objects
+#define FEATURE_ARB_sync _HAVE_FULL_GL
+
+#define FEATURE_EXT_framebuffer_blit _HAVE_FULL_GL
+#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL
+#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL
+#define FEATURE_EXT_texture_sRGB _HAVE_FULL_GL
+#define FEATURE_EXT_timer_query _HAVE_FULL_GL
+#define FEATURE_ATI_fragment_shader _HAVE_FULL_GL
+#define FEATURE_NV_fence _HAVE_FULL_GL
+#define FEATURE_NV_fragment_program _HAVE_FULL_GL
+#define FEATURE_NV_vertex_program _HAVE_FULL_GL
+
+
+#endif /* FEATURES_H */
diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c
new file mode 100644
index 000000000..3dca09d9f
--- /dev/null
+++ b/mesalib/src/mesa/main/mipmap.c
@@ -0,0 +1,1794 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file mipmap.c mipmap generation and teximage resizing functions.
+ */
+
+#include "imports.h"
+#include "mipmap.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "image.h"
+
+
+
+static GLint
+bytes_per_pixel(GLenum datatype, GLuint comps)
+{
+ GLint b = _mesa_sizeof_packed_type(datatype);
+ assert(b >= 0);
+
+ if (_mesa_type_is_packed(datatype))
+ return b;
+ else
+ return b * comps;
+}
+
+
+/**
+ * \name Support macros for do_row and do_row_3d
+ *
+ * The macro madness is here for two reasons. First, it compacts the code
+ * slightly. Second, it makes it much easier to adjust the specifics of the
+ * filter to tune the rounding characteristics.
+ */
+/*@{*/
+#define DECLARE_ROW_POINTERS(t, e) \
+ const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
+ const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
+ const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
+ const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
+ t(*dst)[e] = (t(*)[e]) dstRow
+
+#define DECLARE_ROW_POINTERS0(t) \
+ const t *rowA = (const t *) srcRowA; \
+ const t *rowB = (const t *) srcRowB; \
+ const t *rowC = (const t *) srcRowC; \
+ const t *rowD = (const t *) srcRowD; \
+ t *dst = (t *) dstRow
+
+#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
+ ((unsigned) Aj + (unsigned) Ak \
+ + (unsigned) Bj + (unsigned) Bk \
+ + (unsigned) Cj + (unsigned) Ck \
+ + (unsigned) Dj + (unsigned) Dk \
+ + 4) >> 3
+
+#define FILTER_3D(e) \
+ do { \
+ dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
+ rowB[j][e], rowB[k][e], \
+ rowC[j][e], rowC[k][e], \
+ rowD[j][e], rowD[k][e]); \
+ } while(0)
+
+#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
+ (Aj + Ak \
+ + Bj + Bk \
+ + Cj + Ck \
+ + Dj + Dk \
+ + 4) / 8
+
+#define FILTER_3D_SIGNED(e) \
+ do { \
+ dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
+ rowB[j][e], rowB[k][e], \
+ rowC[j][e], rowC[k][e], \
+ rowD[j][e], rowD[k][e]); \
+ } while(0)
+
+#define FILTER_F_3D(e) \
+ do { \
+ dst[i][e] = (rowA[j][e] + rowA[k][e] \
+ + rowB[j][e] + rowB[k][e] \
+ + rowC[j][e] + rowC[k][e] \
+ + rowD[j][e] + rowD[k][e]) * 0.125F; \
+ } while(0)
+
+#define FILTER_HF_3D(e) \
+ do { \
+ const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
+ const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
+ const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
+ const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
+ const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
+ const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
+ const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
+ const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
+ dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
+ * 0.125F); \
+ } while(0)
+/*@}*/
+
+
+/**
+ * Average together two rows of a source image to produce a single new
+ * row in the dest image. It's legal for the two source rows to point
+ * to the same data. The source width must be equal to either the
+ * dest width or two times the dest width.
+ * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
+ * \param comps number of components per pixel (1..4)
+ */
+static void
+do_row(GLenum datatype, GLuint comps, GLint srcWidth,
+ const GLvoid *srcRowA, const GLvoid *srcRowB,
+ GLint dstWidth, GLvoid *dstRow)
+{
+ const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
+ const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
+
+ ASSERT(comps >= 1);
+ ASSERT(comps <= 4);
+
+ /* This assertion is no longer valid with non-power-of-2 textures
+ assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
+ */
+
+ if (datatype == GL_UNSIGNED_BYTE && comps == 4) {
+ GLuint i, j, k;
+ const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA;
+ const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB;
+ GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_BYTE && comps == 3) {
+ GLuint i, j, k;
+ const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA;
+ const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB;
+ GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_BYTE && comps == 2) {
+ GLuint i, j, k;
+ const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA;
+ const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB;
+ GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_BYTE && comps == 1) {
+ GLuint i, j, k;
+ const GLubyte *rowA = (const GLubyte *) srcRowA;
+ const GLubyte *rowB = (const GLubyte *) srcRowB;
+ GLubyte *dst = (GLubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
+ }
+ }
+
+ else if (datatype == GL_BYTE && comps == 4) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA;
+ const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB;
+ GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 3) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA;
+ const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB;
+ GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 2) {
+ GLuint i, j, k;
+ const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
+ const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
+ GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ }
+ }
+ else if (datatype == GL_BYTE && comps == 1) {
+ GLuint i, j, k;
+ const GLbyte *rowA = (const GLbyte *) srcRowA;
+ const GLbyte *rowB = (const GLbyte *) srcRowB;
+ GLbyte *dst = (GLbyte *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+ }
+ }
+
+ else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
+ GLuint i, j, k;
+ const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
+ const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB;
+ GLushort(*dst)[4] = (GLushort(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_SHORT && comps == 3) {
+ GLuint i, j, k;
+ const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA;
+ const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB;
+ GLushort(*dst)[3] = (GLushort(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_SHORT && comps == 2) {
+ GLuint i, j, k;
+ const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA;
+ const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB;
+ GLushort(*dst)[2] = (GLushort(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_SHORT && comps == 1) {
+ GLuint i, j, k;
+ const GLushort *rowA = (const GLushort *) srcRowA;
+ const GLushort *rowB = (const GLushort *) srcRowB;
+ GLushort *dst = (GLushort *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+ }
+ }
+ else if (datatype == GL_FLOAT && comps == 4) {
+ GLuint i, j, k;
+ const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
+ const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB;
+ GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ dst[i][3] = (rowA[j][3] + rowA[k][3] +
+ rowB[j][3] + rowB[k][3]) * 0.25F;
+ }
+ }
+ else if (datatype == GL_FLOAT && comps == 3) {
+ GLuint i, j, k;
+ const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA;
+ const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB;
+ GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ dst[i][2] = (rowA[j][2] + rowA[k][2] +
+ rowB[j][2] + rowB[k][2]) * 0.25F;
+ }
+ }
+ else if (datatype == GL_FLOAT && comps == 2) {
+ GLuint i, j, k;
+ const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA;
+ const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB;
+ GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i][0] = (rowA[j][0] + rowA[k][0] +
+ rowB[j][0] + rowB[k][0]) * 0.25F;
+ dst[i][1] = (rowA[j][1] + rowA[k][1] +
+ rowB[j][1] + rowB[k][1]) * 0.25F;
+ }
+ }
+ else if (datatype == GL_FLOAT && comps == 1) {
+ GLuint i, j, k;
+ const GLfloat *rowA = (const GLfloat *) srcRowA;
+ const GLfloat *rowB = (const GLfloat *) srcRowB;
+ GLfloat *dst = (GLfloat *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
+ }
+ }
+
+ else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) {
+ GLuint i, j, k, comp;
+ const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA;
+ const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB;
+ GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 4; comp++) {
+ GLfloat aj, ak, bj, bk;
+ aj = _mesa_half_to_float(rowA[j][comp]);
+ ak = _mesa_half_to_float(rowA[k][comp]);
+ bj = _mesa_half_to_float(rowB[j][comp]);
+ bk = _mesa_half_to_float(rowB[k][comp]);
+ dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) {
+ GLuint i, j, k, comp;
+ const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA;
+ const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB;
+ GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 3; comp++) {
+ GLfloat aj, ak, bj, bk;
+ aj = _mesa_half_to_float(rowA[j][comp]);
+ ak = _mesa_half_to_float(rowA[k][comp]);
+ bj = _mesa_half_to_float(rowB[j][comp]);
+ bk = _mesa_half_to_float(rowB[k][comp]);
+ dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) {
+ GLuint i, j, k, comp;
+ const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA;
+ const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB;
+ GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ for (comp = 0; comp < 2; comp++) {
+ GLfloat aj, ak, bj, bk;
+ aj = _mesa_half_to_float(rowA[j][comp]);
+ ak = _mesa_half_to_float(rowA[k][comp]);
+ bj = _mesa_half_to_float(rowB[j][comp]);
+ bk = _mesa_half_to_float(rowB[k][comp]);
+ dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+ }
+ else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) {
+ GLuint i, j, k;
+ const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
+ const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
+ GLhalfARB *dst = (GLhalfARB *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ GLfloat aj, ak, bj, bk;
+ aj = _mesa_half_to_float(rowA[j]);
+ ak = _mesa_half_to_float(rowA[k]);
+ bj = _mesa_half_to_float(rowB[j]);
+ bk = _mesa_half_to_float(rowB[k]);
+ dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
+ }
+ }
+
+ else if (datatype == GL_UNSIGNED_INT && comps == 1) {
+ GLuint i, j, k;
+ const GLuint *rowA = (const GLuint *) srcRowA;
+ const GLuint *rowB = (const GLuint *) srcRowB;
+ GLfloat *dst = (GLfloat *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4);
+ }
+ }
+
+ else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) {
+ GLuint i, j, k;
+ const GLushort *rowA = (const GLushort *) srcRowA;
+ const GLushort *rowB = (const GLushort *) srcRowB;
+ GLushort *dst = (GLushort *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x1f;
+ const GLint rowAr1 = rowA[k] & 0x1f;
+ const GLint rowBr0 = rowB[j] & 0x1f;
+ const GLint rowBr1 = rowB[k] & 0x1f;
+ const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
+ const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
+ const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
+ const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
+ const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
+ const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
+ const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
+ const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
+ const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 11) | (green << 5) | red;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) {
+ GLuint i, j, k;
+ const GLushort *rowA = (const GLushort *) srcRowA;
+ const GLushort *rowB = (const GLushort *) srcRowB;
+ GLushort *dst = (GLushort *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0xf;
+ const GLint rowAr1 = rowA[k] & 0xf;
+ const GLint rowBr0 = rowB[j] & 0xf;
+ const GLint rowBr1 = rowB[k] & 0xf;
+ const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
+ const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
+ const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
+ const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
+ const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
+ const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
+ const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
+ const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
+ const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
+ const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
+ const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
+ const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
+ const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) {
+ GLuint i, j, k;
+ const GLushort *rowA = (const GLushort *) srcRowA;
+ const GLushort *rowB = (const GLushort *) srcRowB;
+ GLushort *dst = (GLushort *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x1f;
+ const GLint rowAr1 = rowA[k] & 0x1f;
+ const GLint rowBr0 = rowB[j] & 0x1f;
+ const GLint rowBr1 = rowB[k] & 0x1f;
+ const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
+ const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
+ const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
+ const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
+ const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
+ const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
+ const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
+ const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
+ const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
+ const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
+ const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
+ const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
+ const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
+ dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
+ }
+ }
+ else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) {
+ GLuint i, j, k;
+ const GLubyte *rowA = (const GLubyte *) srcRowA;
+ const GLubyte *rowB = (const GLubyte *) srcRowB;
+ GLubyte *dst = (GLubyte *) dstRow;
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x3;
+ const GLint rowAr1 = rowA[k] & 0x3;
+ const GLint rowBr0 = rowB[j] & 0x3;
+ const GLint rowBr1 = rowB[k] & 0x3;
+ const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
+ const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
+ const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
+ const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
+ const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
+ const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
+ const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
+ const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
+ const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
+ const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
+ const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
+ dst[i] = (blue << 5) | (green << 2) | red;
+ }
+ }
+ else {
+ _mesa_problem(NULL, "bad format in do_row()");
+ }
+}
+
+
+/**
+ * Average together four rows of a source image to produce a single new
+ * row in the dest image. It's legal for the two source rows to point
+ * to the same data. The source width must be equal to either the
+ * dest width or two times the dest width.
+ *
+ * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
+ * \c GL_FLOAT, etc.
+ * \param comps number of components per pixel (1..4)
+ * \param srcWidth Width of a row in the source data
+ * \param srcRowA Pointer to one of the rows of source data
+ * \param srcRowB Pointer to one of the rows of source data
+ * \param srcRowC Pointer to one of the rows of source data
+ * \param srcRowD Pointer to one of the rows of source data
+ * \param dstWidth Width of a row in the destination data
+ * \param srcRowA Pointer to the row of destination data
+ */
+static void
+do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
+ const GLvoid *srcRowA, const GLvoid *srcRowB,
+ const GLvoid *srcRowC, const GLvoid *srcRowD,
+ GLint dstWidth, GLvoid *dstRow)
+{
+ const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
+ const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
+ GLuint i, j, k;
+
+ ASSERT(comps >= 1);
+ ASSERT(comps <= 4);
+
+ if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLubyte, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ FILTER_3D(3);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLubyte, 3);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLubyte, 2);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLubyte, 1);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ }
+ }
+ if ((datatype == GL_BYTE) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLbyte, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ FILTER_3D_SIGNED(2);
+ FILTER_3D_SIGNED(3);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLbyte, 3);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ FILTER_3D_SIGNED(2);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLbyte, 2);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ FILTER_3D_SIGNED(1);
+ }
+ }
+ else if ((datatype == GL_BYTE) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLbyte, 1);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D_SIGNED(0);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLushort, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ FILTER_3D(3);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLushort, 3);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ FILTER_3D(2);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLushort, 2);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ FILTER_3D(1);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLushort, 1);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_3D(0);
+ }
+ }
+ else if ((datatype == GL_FLOAT) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLfloat, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ FILTER_F_3D(2);
+ FILTER_F_3D(3);
+ }
+ }
+ else if ((datatype == GL_FLOAT) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLfloat, 3);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ FILTER_F_3D(2);
+ }
+ }
+ else if ((datatype == GL_FLOAT) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLfloat, 2);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ FILTER_F_3D(1);
+ }
+ }
+ else if ((datatype == GL_FLOAT) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLfloat, 1);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_F_3D(0);
+ }
+ }
+ else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) {
+ DECLARE_ROW_POINTERS(GLhalfARB, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ FILTER_HF_3D(2);
+ FILTER_HF_3D(3);
+ }
+ }
+ else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
+ DECLARE_ROW_POINTERS(GLhalfARB, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ FILTER_HF_3D(2);
+ }
+ }
+ else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
+ DECLARE_ROW_POINTERS(GLhalfARB, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ FILTER_HF_3D(1);
+ }
+ }
+ else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
+ DECLARE_ROW_POINTERS(GLhalfARB, 4);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ FILTER_HF_3D(0);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) {
+ const GLuint *rowA = (const GLuint *) srcRowA;
+ const GLuint *rowB = (const GLuint *) srcRowB;
+ const GLuint *rowC = (const GLuint *) srcRowC;
+ const GLuint *rowD = (const GLuint *) srcRowD;
+ GLfloat *dst = (GLfloat *) dstRow;
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
+ + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
+ + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
+ + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
+ dst[i] = (GLfloat)((double) tmp * 0.125);
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) {
+ DECLARE_ROW_POINTERS0(GLushort);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x1f;
+ const GLint rowAr1 = rowA[k] & 0x1f;
+ const GLint rowBr0 = rowB[j] & 0x1f;
+ const GLint rowBr1 = rowB[k] & 0x1f;
+ const GLint rowCr0 = rowC[j] & 0x1f;
+ const GLint rowCr1 = rowC[k] & 0x1f;
+ const GLint rowDr0 = rowD[j] & 0x1f;
+ const GLint rowDr1 = rowD[k] & 0x1f;
+ const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
+ const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
+ const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
+ const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
+ const GLint rowCg0 = (rowC[j] >> 5) & 0x3f;
+ const GLint rowCg1 = (rowC[k] >> 5) & 0x3f;
+ const GLint rowDg0 = (rowD[j] >> 5) & 0x3f;
+ const GLint rowDg1 = (rowD[k] >> 5) & 0x3f;
+ const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
+ const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
+ const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
+ const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
+ const GLint rowCb0 = (rowC[j] >> 11) & 0x1f;
+ const GLint rowCb1 = (rowC[k] >> 11) & 0x1f;
+ const GLint rowDb0 = (rowD[j] >> 11) & 0x1f;
+ const GLint rowDb1 = (rowD[k] >> 11) & 0x1f;
+ const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ dst[i] = (b << 11) | (g << 5) | r;
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) {
+ DECLARE_ROW_POINTERS0(GLushort);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0xf;
+ const GLint rowAr1 = rowA[k] & 0xf;
+ const GLint rowBr0 = rowB[j] & 0xf;
+ const GLint rowBr1 = rowB[k] & 0xf;
+ const GLint rowCr0 = rowC[j] & 0xf;
+ const GLint rowCr1 = rowC[k] & 0xf;
+ const GLint rowDr0 = rowD[j] & 0xf;
+ const GLint rowDr1 = rowD[k] & 0xf;
+ const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
+ const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
+ const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
+ const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
+ const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
+ const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
+ const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
+ const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
+ const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
+ const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
+ const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
+ const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
+ const GLint rowCb0 = (rowC[j] >> 8) & 0xf;
+ const GLint rowCb1 = (rowC[k] >> 8) & 0xf;
+ const GLint rowDb0 = (rowD[j] >> 8) & 0xf;
+ const GLint rowDb1 = (rowD[k] >> 8) & 0xf;
+ const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
+ const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
+ const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
+ const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
+ const GLint rowCa0 = (rowC[j] >> 12) & 0xf;
+ const GLint rowCa1 = (rowC[k] >> 12) & 0xf;
+ const GLint rowDa0 = (rowD[j] >> 12) & 0xf;
+ const GLint rowDa1 = (rowD[k] >> 12) & 0xf;
+ const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
+ rowCa0, rowCa1, rowDa0, rowDa1);
+
+ dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) {
+ DECLARE_ROW_POINTERS0(GLushort);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x1f;
+ const GLint rowAr1 = rowA[k] & 0x1f;
+ const GLint rowBr0 = rowB[j] & 0x1f;
+ const GLint rowBr1 = rowB[k] & 0x1f;
+ const GLint rowCr0 = rowC[j] & 0x1f;
+ const GLint rowCr1 = rowC[k] & 0x1f;
+ const GLint rowDr0 = rowD[j] & 0x1f;
+ const GLint rowDr1 = rowD[k] & 0x1f;
+ const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
+ const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
+ const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
+ const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
+ const GLint rowCg0 = (rowC[j] >> 5) & 0x1f;
+ const GLint rowCg1 = (rowC[k] >> 5) & 0x1f;
+ const GLint rowDg0 = (rowD[j] >> 5) & 0x1f;
+ const GLint rowDg1 = (rowD[k] >> 5) & 0x1f;
+ const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
+ const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
+ const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
+ const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
+ const GLint rowCb0 = (rowC[j] >> 10) & 0x1f;
+ const GLint rowCb1 = (rowC[k] >> 10) & 0x1f;
+ const GLint rowDb0 = (rowD[j] >> 10) & 0x1f;
+ const GLint rowDb1 = (rowD[k] >> 10) & 0x1f;
+ const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
+ const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
+ const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
+ const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
+ const GLint rowCa0 = (rowC[j] >> 15) & 0x1;
+ const GLint rowCa1 = (rowC[k] >> 15) & 0x1;
+ const GLint rowDa0 = (rowD[j] >> 15) & 0x1;
+ const GLint rowDa1 = (rowD[k] >> 15) & 0x1;
+ const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
+ rowCa0, rowCa1, rowDa0, rowDa1);
+
+ dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
+ }
+ }
+ else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
+ DECLARE_ROW_POINTERS0(GLushort);
+
+ for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+ i++, j += colStride, k += colStride) {
+ const GLint rowAr0 = rowA[j] & 0x3;
+ const GLint rowAr1 = rowA[k] & 0x3;
+ const GLint rowBr0 = rowB[j] & 0x3;
+ const GLint rowBr1 = rowB[k] & 0x3;
+ const GLint rowCr0 = rowC[j] & 0x3;
+ const GLint rowCr1 = rowC[k] & 0x3;
+ const GLint rowDr0 = rowD[j] & 0x3;
+ const GLint rowDr1 = rowD[k] & 0x3;
+ const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
+ const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
+ const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
+ const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
+ const GLint rowCg0 = (rowC[j] >> 2) & 0x7;
+ const GLint rowCg1 = (rowC[k] >> 2) & 0x7;
+ const GLint rowDg0 = (rowD[j] >> 2) & 0x7;
+ const GLint rowDg1 = (rowD[k] >> 2) & 0x7;
+ const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
+ const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
+ const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
+ const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
+ const GLint rowCb0 = (rowC[j] >> 5) & 0x7;
+ const GLint rowCb1 = (rowC[k] >> 5) & 0x7;
+ const GLint rowDb0 = (rowD[j] >> 5) & 0x7;
+ const GLint rowDb1 = (rowD[k] >> 5) & 0x7;
+ const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
+ rowCr0, rowCr1, rowDr0, rowDr1);
+ const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
+ rowCg0, rowCg1, rowDg0, rowDg1);
+ const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
+ rowCb0, rowCb1, rowDb0, rowDb1);
+ dst[i] = (b << 5) | (g << 2) | r;
+ }
+ }
+ else {
+ _mesa_problem(NULL, "bad format in do_row()");
+ }
+}
+
+
+/*
+ * These functions generate a 1/2-size mipmap image from a source image.
+ * Texture borders are handled by copying or averaging the source image's
+ * border texels, depending on the scale-down factor.
+ */
+
+static void
+make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
+ GLint srcWidth, const GLubyte *srcPtr,
+ GLint dstWidth, GLubyte *dstPtr)
+{
+ const GLint bpt = bytes_per_pixel(datatype, comps);
+ const GLubyte *src;
+ GLubyte *dst;
+
+ /* skip the border pixel, if any */
+ src = srcPtr + border * bpt;
+ dst = dstPtr + border * bpt;
+
+ /* we just duplicate the input row, kind of hack, saves code */
+ do_row(datatype, comps, srcWidth - 2 * border, src, src,
+ dstWidth - 2 * border, dst);
+
+ if (border) {
+ /* copy left-most pixel from source */
+ MEMCPY(dstPtr, srcPtr, bpt);
+ /* copy right-most pixel from source */
+ MEMCPY(dstPtr + (dstWidth - 1) * bpt,
+ srcPtr + (srcWidth - 1) * bpt,
+ bpt);
+ }
+}
+
+
+static void
+make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
+ GLint srcWidth, GLint srcHeight,
+ const GLubyte *srcPtr, GLint srcRowStride,
+ GLint dstWidth, GLint dstHeight,
+ GLubyte *dstPtr, GLint dstRowStride)
+{
+ const GLint bpt = bytes_per_pixel(datatype, comps);
+ const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
+ const GLint dstWidthNB = dstWidth - 2 * border;
+ const GLint dstHeightNB = dstHeight - 2 * border;
+ const GLint srcRowBytes = bpt * srcRowStride;
+ const GLint dstRowBytes = bpt * dstRowStride;
+ const GLubyte *srcA, *srcB;
+ GLubyte *dst;
+ GLint row;
+
+ /* Compute src and dst pointers, skipping any border */
+ srcA = srcPtr + border * ((srcWidth + 1) * bpt);
+ if (srcHeight > 1)
+ srcB = srcA + srcRowBytes;
+ else
+ srcB = srcA;
+ dst = dstPtr + border * ((dstWidth + 1) * bpt);
+
+ for (row = 0; row < dstHeightNB; row++) {
+ do_row(datatype, comps, srcWidthNB, srcA, srcB,
+ dstWidthNB, dst);
+ srcA += 2 * srcRowBytes;
+ srcB += 2 * srcRowBytes;
+ dst += dstRowBytes;
+ }
+
+ /* This is ugly but probably won't be used much */
+ if (border > 0) {
+ /* fill in dest border */
+ /* lower-left border pixel */
+ MEMCPY(dstPtr, srcPtr, bpt);
+ /* lower-right border pixel */
+ MEMCPY(dstPtr + (dstWidth - 1) * bpt,
+ srcPtr + (srcWidth - 1) * bpt, bpt);
+ /* upper-left border pixel */
+ MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
+ srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
+ /* upper-right border pixel */
+ MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
+ srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
+ /* lower border */
+ do_row(datatype, comps, srcWidthNB,
+ srcPtr + bpt,
+ srcPtr + bpt,
+ dstWidthNB, dstPtr + bpt);
+ /* upper border */
+ do_row(datatype, comps, srcWidthNB,
+ srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
+ srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
+ dstWidthNB,
+ dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
+ /* left and right borders */
+ if (srcHeight == dstHeight) {
+ /* copy border pixel from src to dst */
+ for (row = 1; row < srcHeight; row++) {
+ MEMCPY(dstPtr + dstWidth * row * bpt,
+ srcPtr + srcWidth * row * bpt, bpt);
+ MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
+ srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
+ }
+ }
+ else {
+ /* average two src pixels each dest pixel */
+ for (row = 0; row < dstHeightNB; row += 2) {
+ do_row(datatype, comps, 1,
+ srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
+ srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
+ 1, dstPtr + (dstWidth * row + 1) * bpt);
+ do_row(datatype, comps, 1,
+ srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
+ srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
+ 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
+ }
+ }
+ }
+}
+
+
+static void
+make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ const GLubyte *srcPtr, GLint srcRowStride,
+ GLint dstWidth, GLint dstHeight, GLint dstDepth,
+ GLubyte *dstPtr, GLint dstRowStride)
+{
+ const GLint bpt = bytes_per_pixel(datatype, comps);
+ const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
+ const GLint srcDepthNB = srcDepth - 2 * border;
+ const GLint dstWidthNB = dstWidth - 2 * border;
+ const GLint dstHeightNB = dstHeight - 2 * border;
+ const GLint dstDepthNB = dstDepth - 2 * border;
+ GLint img, row;
+ GLint bytesPerSrcImage, bytesPerDstImage;
+ GLint bytesPerSrcRow, bytesPerDstRow;
+ GLint srcImageOffset, srcRowOffset;
+
+ (void) srcDepthNB; /* silence warnings */
+
+
+ bytesPerSrcImage = srcWidth * srcHeight * bpt;
+ bytesPerDstImage = dstWidth * dstHeight * bpt;
+
+ bytesPerSrcRow = srcWidth * bpt;
+ bytesPerDstRow = dstWidth * bpt;
+
+ /* Offset between adjacent src images to be averaged together */
+ srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
+
+ /* Offset between adjacent src rows to be averaged together */
+ srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
+
+ /*
+ * Need to average together up to 8 src pixels for each dest pixel.
+ * Break that down into 3 operations:
+ * 1. take two rows from source image and average them together.
+ * 2. take two rows from next source image and average them together.
+ * 3. take the two averaged rows and average them for the final dst row.
+ */
+
+ /*
+ _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
+ srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
+ */
+
+ for (img = 0; img < dstDepthNB; img++) {
+ /* first source image pointer, skipping border */
+ const GLubyte *imgSrcA = srcPtr
+ + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
+ + img * (bytesPerSrcImage + srcImageOffset);
+ /* second source image pointer, skipping border */
+ const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
+ /* address of the dest image, skipping border */
+ GLubyte *imgDst = dstPtr
+ + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
+ + img * bytesPerDstImage;
+
+ /* setup the four source row pointers and the dest row pointer */
+ const GLubyte *srcImgARowA = imgSrcA;
+ const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
+ const GLubyte *srcImgBRowA = imgSrcB;
+ const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
+ GLubyte *dstImgRow = imgDst;
+
+ for (row = 0; row < dstHeightNB; row++) {
+ do_row_3D(datatype, comps, srcWidthNB,
+ srcImgARowA, srcImgARowB,
+ srcImgBRowA, srcImgBRowB,
+ dstWidthNB, dstImgRow);
+
+ /* advance to next rows */
+ srcImgARowA += bytesPerSrcRow + srcRowOffset;
+ srcImgARowB += bytesPerSrcRow + srcRowOffset;
+ srcImgBRowA += bytesPerSrcRow + srcRowOffset;
+ srcImgBRowB += bytesPerSrcRow + srcRowOffset;
+ dstImgRow += bytesPerDstRow;
+ }
+ }
+
+
+ /* Luckily we can leverage the make_2d_mipmap() function here! */
+ if (border > 0) {
+ /* do front border image */
+ make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
+ dstWidth, dstHeight, dstPtr, dstRowStride);
+ /* do back border image */
+ make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
+ srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
+ dstWidth, dstHeight,
+ dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
+ /* do four remaining border edges that span the image slices */
+ if (srcDepth == dstDepth) {
+ /* just copy border pixels from src to dst */
+ for (img = 0; img < dstDepthNB; img++) {
+ const GLubyte *src;
+ GLubyte *dst;
+
+ /* do border along [img][row=0][col=0] */
+ src = srcPtr + (img + 1) * bytesPerSrcImage;
+ dst = dstPtr + (img + 1) * bytesPerDstImage;
+ MEMCPY(dst, src, bpt);
+
+ /* do border along [img][row=dstHeight-1][col=0] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (srcHeight - 1) * bytesPerSrcRow;
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (dstHeight - 1) * bytesPerDstRow;
+ MEMCPY(dst, src, bpt);
+
+ /* do border along [img][row=0][col=dstWidth-1] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (srcWidth - 1) * bpt;
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (dstWidth - 1) * bpt;
+ MEMCPY(dst, src, bpt);
+
+ /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (bytesPerSrcImage - bpt);
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (bytesPerDstImage - bpt);
+ MEMCPY(dst, src, bpt);
+ }
+ }
+ else {
+ /* average border pixels from adjacent src image pairs */
+ ASSERT(srcDepthNB == 2 * dstDepthNB);
+ for (img = 0; img < dstDepthNB; img++) {
+ const GLubyte *src;
+ GLubyte *dst;
+
+ /* do border along [img][row=0][col=0] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
+ dst = dstPtr + (img + 1) * bytesPerDstImage;
+ do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
+
+ /* do border along [img][row=dstHeight-1][col=0] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (srcHeight - 1) * bytesPerSrcRow;
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (dstHeight - 1) * bytesPerDstRow;
+ do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
+
+ /* do border along [img][row=0][col=dstWidth-1] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (srcWidth - 1) * bpt;
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (dstWidth - 1) * bpt;
+ do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
+
+ /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
+ src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
+ + (bytesPerSrcImage - bpt);
+ dst = dstPtr + (img + 1) * bytesPerDstImage
+ + (bytesPerDstImage - bpt);
+ do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
+ }
+ }
+ }
+}
+
+
+static void
+make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
+ GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride,
+ GLint dstWidth, GLint dstHeight,
+ GLubyte *dstPtr, GLuint dstRowStride )
+{
+ const GLint bpt = bytes_per_pixel(datatype, comps);
+ const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
+ const GLint dstWidthNB = dstWidth - 2 * border;
+ const GLint dstHeightNB = dstHeight - 2 * border;
+ const GLint srcRowBytes = bpt * srcRowStride;
+ const GLint dstRowBytes = bpt * dstRowStride;
+ const GLubyte *src;
+ GLubyte *dst;
+ GLint row;
+
+ /* Compute src and dst pointers, skipping any border */
+ src = srcPtr + border * ((srcWidth + 1) * bpt);
+ dst = dstPtr + border * ((dstWidth + 1) * bpt);
+
+ for (row = 0; row < dstHeightNB; row++) {
+ do_row(datatype, comps, srcWidthNB, src, src,
+ dstWidthNB, dst);
+ src += srcRowBytes;
+ dst += dstRowBytes;
+ }
+
+ if (border) {
+ /* copy left-most pixel from source */
+ MEMCPY(dstPtr, srcPtr, bpt);
+ /* copy right-most pixel from source */
+ MEMCPY(dstPtr + (dstWidth - 1) * bpt,
+ srcPtr + (srcWidth - 1) * bpt,
+ bpt);
+ }
+}
+
+
+/**
+ * \bug
+ * There is quite a bit of refactoring that could be done with this function
+ * and \c make_2d_mipmap.
+ */
+static void
+make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
+ GLint srcWidth, GLint srcHeight,
+ const GLubyte *srcPtr, GLint srcRowStride,
+ GLint dstWidth, GLint dstHeight, GLint dstDepth,
+ GLubyte *dstPtr, GLint dstRowStride)
+{
+ const GLint bpt = bytes_per_pixel(datatype, comps);
+ const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
+ const GLint dstWidthNB = dstWidth - 2 * border;
+ const GLint dstHeightNB = dstHeight - 2 * border;
+ const GLint dstDepthNB = dstDepth - 2 * border;
+ const GLint srcRowBytes = bpt * srcRowStride;
+ const GLint dstRowBytes = bpt * dstRowStride;
+ const GLubyte *srcA, *srcB;
+ GLubyte *dst;
+ GLint layer;
+ GLint row;
+
+ /* Compute src and dst pointers, skipping any border */
+ srcA = srcPtr + border * ((srcWidth + 1) * bpt);
+ if (srcHeight > 1)
+ srcB = srcA + srcRowBytes;
+ else
+ srcB = srcA;
+ dst = dstPtr + border * ((dstWidth + 1) * bpt);
+
+ for (layer = 0; layer < dstDepthNB; layer++) {
+ for (row = 0; row < dstHeightNB; row++) {
+ do_row(datatype, comps, srcWidthNB, srcA, srcB,
+ dstWidthNB, dst);
+ srcA += 2 * srcRowBytes;
+ srcB += 2 * srcRowBytes;
+ dst += dstRowBytes;
+ }
+
+ /* This is ugly but probably won't be used much */
+ if (border > 0) {
+ /* fill in dest border */
+ /* lower-left border pixel */
+ MEMCPY(dstPtr, srcPtr, bpt);
+ /* lower-right border pixel */
+ MEMCPY(dstPtr + (dstWidth - 1) * bpt,
+ srcPtr + (srcWidth - 1) * bpt, bpt);
+ /* upper-left border pixel */
+ MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
+ srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
+ /* upper-right border pixel */
+ MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
+ srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
+ /* lower border */
+ do_row(datatype, comps, srcWidthNB,
+ srcPtr + bpt,
+ srcPtr + bpt,
+ dstWidthNB, dstPtr + bpt);
+ /* upper border */
+ do_row(datatype, comps, srcWidthNB,
+ srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
+ srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
+ dstWidthNB,
+ dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
+ /* left and right borders */
+ if (srcHeight == dstHeight) {
+ /* copy border pixel from src to dst */
+ for (row = 1; row < srcHeight; row++) {
+ MEMCPY(dstPtr + dstWidth * row * bpt,
+ srcPtr + srcWidth * row * bpt, bpt);
+ MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
+ srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
+ }
+ }
+ else {
+ /* average two src pixels each dest pixel */
+ for (row = 0; row < dstHeightNB; row += 2) {
+ do_row(datatype, comps, 1,
+ srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
+ srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
+ 1, dstPtr + (dstWidth * row + 1) * bpt);
+ do_row(datatype, comps, 1,
+ srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
+ srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
+ 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Down-sample a texture image to produce the next lower mipmap level.
+ * \param comps components per texel (1, 2, 3 or 4)
+ * \param srcRowStride stride between source rows, in texels
+ * \param dstRowStride stride between destination rows, in texels
+ */
+void
+_mesa_generate_mipmap_level(GLenum target,
+ GLenum datatype, GLuint comps,
+ GLint border,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ const GLubyte *srcData,
+ GLint srcRowStride,
+ GLint dstWidth, GLint dstHeight, GLint dstDepth,
+ GLubyte *dstData,
+ GLint dstRowStride)
+{
+ /*
+ * We use simple 2x2 averaging to compute the next mipmap level.
+ */
+ switch (target) {
+ case GL_TEXTURE_1D:
+ make_1d_mipmap(datatype, comps, border,
+ srcWidth, srcData,
+ dstWidth, dstData);
+ break;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ make_2d_mipmap(datatype, comps, border,
+ srcWidth, srcHeight, srcData, srcRowStride,
+ dstWidth, dstHeight, dstData, dstRowStride);
+ break;
+ case GL_TEXTURE_3D:
+ make_3d_mipmap(datatype, comps, border,
+ srcWidth, srcHeight, srcDepth,
+ srcData, srcRowStride,
+ dstWidth, dstHeight, dstDepth,
+ dstData, dstRowStride);
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ make_1d_stack_mipmap(datatype, comps, border,
+ srcWidth, srcData, srcRowStride,
+ dstWidth, dstHeight,
+ dstData, dstRowStride);
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ make_2d_stack_mipmap(datatype, comps, border,
+ srcWidth, srcHeight,
+ srcData, srcRowStride,
+ dstWidth, dstHeight,
+ dstDepth, dstData, dstRowStride);
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ /* no mipmaps, do nothing */
+ break;
+ default:
+ _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
+ return;
+ }
+}
+
+
+/**
+ * compute next (level+1) image size
+ * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
+ */
+static GLboolean
+next_mipmap_level_size(GLenum target, GLint border,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
+{
+ if (srcWidth - 2 * border > 1) {
+ *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
+ }
+ else {
+ *dstWidth = srcWidth; /* can't go smaller */
+ }
+
+ if ((srcHeight - 2 * border > 1) &&
+ (target != GL_TEXTURE_1D_ARRAY_EXT)) {
+ *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
+ }
+ else {
+ *dstHeight = srcHeight; /* can't go smaller */
+ }
+
+ if ((srcDepth - 2 * border > 1) &&
+ (target != GL_TEXTURE_2D_ARRAY_EXT)) {
+ *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
+ }
+ else {
+ *dstDepth = srcDepth; /* can't go smaller */
+ }
+
+ if (*dstWidth == srcWidth &&
+ *dstHeight == srcHeight &&
+ *dstDepth == srcDepth) {
+ return GL_FALSE;
+ }
+ else {
+ return GL_TRUE;
+ }
+}
+
+
+
+
+/**
+ * Automatic mipmap generation.
+ * This is the fallback/default function for ctx->Driver.GenerateMipmap().
+ * Generate a complete set of mipmaps from texObj's BaseLevel image.
+ * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
+ * For cube maps, target will be one of
+ * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
+ */
+void
+_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ const struct gl_texture_image *srcImage;
+ const struct gl_texture_format *convertFormat;
+ const GLubyte *srcData = NULL;
+ GLubyte *dstData = NULL;
+ GLint level, maxLevels;
+ GLenum datatype;
+ GLuint comps;
+
+ ASSERT(texObj);
+ /* XXX choose cube map face here??? */
+ srcImage = texObj->Image[0][texObj->BaseLevel];
+ ASSERT(srcImage);
+
+ maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
+ ASSERT(maxLevels > 0); /* bad target */
+
+ /* Find convertFormat - the format that do_row() will process */
+ if (srcImage->IsCompressed) {
+ /* setup for compressed textures */
+ GLuint row;
+ GLint components, size;
+ GLchan *dst;
+
+ assert(texObj->Target == GL_TEXTURE_2D ||
+ texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
+
+ if (srcImage->_BaseFormat == GL_RGB) {
+ convertFormat = &_mesa_texformat_rgb;
+ components = 3;
+ }
+ else if (srcImage->_BaseFormat == GL_RGBA) {
+ convertFormat = &_mesa_texformat_rgba;
+ components = 4;
+ }
+ else {
+ _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
+ return;
+ }
+
+ /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
+ size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
+ * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
+ /* 20 extra bytes, just be safe when calling last FetchTexel */
+ srcData = (GLubyte *) _mesa_malloc(size);
+ if (!srcData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
+ return;
+ }
+ dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */
+ if (!dstData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
+ _mesa_free((void *) srcData);
+ return;
+ }
+
+ /* decompress base image here */
+ dst = (GLchan *) srcData;
+ for (row = 0; row < srcImage->Height; row++) {
+ GLuint col;
+ for (col = 0; col < srcImage->Width; col++) {
+ srcImage->FetchTexelc(srcImage, col, row, 0, dst);
+ dst += components;
+ }
+ }
+ }
+ else {
+ /* uncompressed */
+ convertFormat = srcImage->TexFormat;
+ }
+
+ _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
+
+ for (level = texObj->BaseLevel; level < texObj->MaxLevel
+ && level < maxLevels - 1; level++) {
+ /* generate image[level+1] from image[level] */
+ const struct gl_texture_image *srcImage;
+ struct gl_texture_image *dstImage;
+ GLint srcWidth, srcHeight, srcDepth;
+ GLint dstWidth, dstHeight, dstDepth;
+ GLint border, bytesPerTexel;
+ GLboolean nextLevel;
+
+ /* get src image parameters */
+ srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(srcImage);
+ srcWidth = srcImage->Width;
+ srcHeight = srcImage->Height;
+ srcDepth = srcImage->Depth;
+ border = srcImage->Border;
+
+ nextLevel = next_mipmap_level_size(target, border,
+ srcWidth, srcHeight, srcDepth,
+ &dstWidth, &dstHeight, &dstDepth);
+ if (!nextLevel) {
+ /* all done */
+ if (srcImage->IsCompressed) {
+ _mesa_free((void *) srcData);
+ _mesa_free(dstData);
+ }
+ return;
+ }
+
+ /* get dest gl_texture_image */
+ dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
+ if (!dstImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+
+ /* Free old image data */
+ if (dstImage->Data)
+ ctx->Driver.FreeTexImageData(ctx, dstImage);
+
+ /* initialize new image */
+ _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
+ dstDepth, border, srcImage->InternalFormat);
+ dstImage->DriverData = NULL;
+ dstImage->TexFormat = srcImage->TexFormat;
+ dstImage->FetchTexelc = srcImage->FetchTexelc;
+ dstImage->FetchTexelf = srcImage->FetchTexelf;
+ dstImage->IsCompressed = srcImage->IsCompressed;
+ if (dstImage->IsCompressed) {
+ dstImage->CompressedSize
+ = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width,
+ dstImage->Height,
+ dstImage->Depth,
+ dstImage->TexFormat->MesaFormat);
+ ASSERT(dstImage->CompressedSize > 0);
+ }
+
+ ASSERT(dstImage->TexFormat);
+ ASSERT(dstImage->FetchTexelc);
+ ASSERT(dstImage->FetchTexelf);
+
+ /* Alloc new teximage data buffer.
+ * Setup src and dest data pointers.
+ */
+ if (dstImage->IsCompressed) {
+ dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize);
+ if (!dstImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+ /* srcData and dstData are already set */
+ ASSERT(srcData);
+ ASSERT(dstData);
+ }
+ else {
+ bytesPerTexel = dstImage->TexFormat->TexelBytes;
+ ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
+ dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight
+ * dstDepth * bytesPerTexel);
+ if (!dstImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
+ return;
+ }
+ srcData = (const GLubyte *) srcImage->Data;
+ dstData = (GLubyte *) dstImage->Data;
+ }
+
+ _mesa_generate_mipmap_level(target, datatype, comps, border,
+ srcWidth, srcHeight, srcDepth,
+ srcData, srcImage->RowStride,
+ dstWidth, dstHeight, dstDepth,
+ dstData, dstImage->RowStride);
+
+
+ if (dstImage->IsCompressed) {
+ GLubyte *temp;
+ /* compress image from dstData into dstImage->Data */
+ const GLenum srcFormat = convertFormat->BaseFormat;
+ GLint dstRowStride
+ = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth);
+ ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
+ dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat,
+ dstImage->TexFormat,
+ dstImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride, 0, /* strides */
+ dstWidth, dstHeight, 1, /* size */
+ srcFormat, CHAN_TYPE,
+ dstData, /* src data, actually */
+ &ctx->DefaultPacking);
+ /* swap src and dest pointers */
+ temp = (GLubyte *) srcData;
+ srcData = dstData;
+ dstData = temp;
+ }
+
+ } /* loop over mipmap levels */
+}
+
+
+/**
+ * Helper function for drivers which need to rescale texture images to
+ * certain aspect ratios.
+ * Nearest filtering only (for broken hardware that can't support
+ * all aspect ratios). This can be made a lot faster, but I don't
+ * really care enough...
+ */
+void
+_mesa_rescale_teximage2d(GLuint bytesPerPixel,
+ GLuint srcStrideInPixels,
+ GLuint dstRowStride,
+ GLint srcWidth, GLint srcHeight,
+ GLint dstWidth, GLint dstHeight,
+ const GLvoid *srcImage, GLvoid *dstImage)
+{
+ GLint row, col;
+
+#define INNER_LOOP( TYPE, HOP, WOP ) \
+ for ( row = 0 ; row < dstHeight ; row++ ) { \
+ GLint srcRow = row HOP hScale; \
+ for ( col = 0 ; col < dstWidth ; col++ ) { \
+ GLint srcCol = col WOP wScale; \
+ dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
+ } \
+ dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
+ } \
+
+#define RESCALE_IMAGE( TYPE ) \
+do { \
+ const TYPE *src = (const TYPE *)srcImage; \
+ TYPE *dst = (TYPE *)dstImage; \
+ \
+ if ( srcHeight < dstHeight ) { \
+ const GLint hScale = dstHeight / srcHeight; \
+ if ( srcWidth < dstWidth ) { \
+ const GLint wScale = dstWidth / srcWidth; \
+ INNER_LOOP( TYPE, /, / ); \
+ } \
+ else { \
+ const GLint wScale = srcWidth / dstWidth; \
+ INNER_LOOP( TYPE, /, * ); \
+ } \
+ } \
+ else { \
+ const GLint hScale = srcHeight / dstHeight; \
+ if ( srcWidth < dstWidth ) { \
+ const GLint wScale = dstWidth / srcWidth; \
+ INNER_LOOP( TYPE, *, / ); \
+ } \
+ else { \
+ const GLint wScale = srcWidth / dstWidth; \
+ INNER_LOOP( TYPE, *, * ); \
+ } \
+ } \
+} while (0)
+
+ switch ( bytesPerPixel ) {
+ case 4:
+ RESCALE_IMAGE( GLuint );
+ break;
+
+ case 2:
+ RESCALE_IMAGE( GLushort );
+ break;
+
+ case 1:
+ RESCALE_IMAGE( GLubyte );
+ break;
+ default:
+ _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
+ }
+}
+
+
+/**
+ * Upscale an image by replication, not (typical) stretching.
+ * We use this when the image width or height is less than a
+ * certain size (4, 8) and we need to upscale an image.
+ */
+void
+_mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight,
+ GLsizei outWidth, GLsizei outHeight,
+ GLint comps, const GLchan *src, GLint srcRowStride,
+ GLchan *dest )
+{
+ GLint i, j, k;
+
+ ASSERT(outWidth >= inWidth);
+ ASSERT(outHeight >= inHeight);
+#if 0
+ ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
+ ASSERT((outWidth & 3) == 0);
+ ASSERT((outHeight & 3) == 0);
+#endif
+
+ for (i = 0; i < outHeight; i++) {
+ const GLint ii = i % inHeight;
+ for (j = 0; j < outWidth; j++) {
+ const GLint jj = j % inWidth;
+ for (k = 0; k < comps; k++) {
+ dest[(i * outWidth + j) * comps + k]
+ = src[ii * srcRowStride + jj * comps + k];
+ }
+ }
+ }
+}
+
diff --git a/mesalib/src/mesa/main/mipmap.h b/mesalib/src/mesa/main/mipmap.h
new file mode 100644
index 000000000..22094c343
--- /dev/null
+++ b/mesalib/src/mesa/main/mipmap.h
@@ -0,0 +1,64 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 MIPMAP_H
+#define MIPMAP_H
+
+#include "mtypes.h"
+
+
+extern void
+_mesa_generate_mipmap_level(GLenum target,
+ GLenum datatype, GLuint comps,
+ GLint border,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ const GLubyte *srcData,
+ GLint srcRowStride,
+ GLint dstWidth, GLint dstHeight, GLint dstDepth,
+ GLubyte *dstData,
+ GLint dstRowStride);
+
+
+extern void
+_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
+
+extern void
+_mesa_rescale_teximage2d(GLuint bytesPerPixel,
+ GLuint srcStrideInPixels,
+ GLuint dstRowStride,
+ GLint srcWidth, GLint srcHeight,
+ GLint dstWidth, GLint dstHeight,
+ const GLvoid *srcImage, GLvoid *dstImage);
+
+extern void
+_mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight,
+ GLsizei outWidth, GLsizei outHeight,
+ GLint comps, const GLchan *src, GLint srcRowStride,
+ GLchan *dest);
+
+
+#endif /* MIPMAP_H */
diff --git a/mesalib/src/mesa/main/mm.c b/mesalib/src/mesa/main/mm.c
new file mode 100644
index 000000000..d430bcdb8
--- /dev/null
+++ b/mesalib/src/mesa/main/mm.c
@@ -0,0 +1,278 @@
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "mm.h"
+
+
+void
+mmDumpMemInfo(const struct mem_block *heap)
+{
+ fprintf(stderr, "Memory heap %p:\n", (void *)heap);
+ if (heap == 0) {
+ fprintf(stderr, " heap == 0\n");
+ } else {
+ const struct mem_block *p;
+
+ for(p = heap->next; p != heap; p = p->next) {
+ fprintf(stderr, " Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+ p->free ? 'F':'.',
+ p->reserved ? 'R':'.');
+ }
+
+ fprintf(stderr, "\nFree list:\n");
+
+ for(p = heap->next_free; p != heap; p = p->next_free) {
+ fprintf(stderr, " FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+ p->free ? 'F':'.',
+ p->reserved ? 'R':'.');
+ }
+
+ }
+ fprintf(stderr, "End of memory blocks\n");
+}
+
+struct mem_block *
+mmInit(unsigned ofs, unsigned size)
+{
+ struct mem_block *heap, *block;
+
+ if (!size)
+ return NULL;
+
+ heap = (struct mem_block *) _mesa_calloc(sizeof(struct mem_block));
+ if (!heap)
+ return NULL;
+
+ block = (struct mem_block *) _mesa_calloc(sizeof(struct mem_block));
+ if (!block) {
+ _mesa_free(heap);
+ return NULL;
+ }
+
+ heap->next = block;
+ heap->prev = block;
+ heap->next_free = block;
+ heap->prev_free = block;
+
+ block->heap = heap;
+ block->next = heap;
+ block->prev = heap;
+ block->next_free = heap;
+ block->prev_free = heap;
+
+ block->ofs = ofs;
+ block->size = size;
+ block->free = 1;
+
+ return heap;
+}
+
+
+static struct mem_block *
+SliceBlock(struct mem_block *p,
+ unsigned startofs, unsigned size,
+ unsigned reserved, unsigned alignment)
+{
+ struct mem_block *newblock;
+
+ /* break left [p, newblock, p->next], then p = newblock */
+ if (startofs > p->ofs) {
+ newblock = (struct mem_block*) _mesa_calloc(sizeof(struct mem_block));
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+ newblock->heap = p->heap;
+
+ newblock->next = p->next;
+ newblock->prev = p;
+ p->next->prev = newblock;
+ p->next = newblock;
+
+ newblock->next_free = p->next_free;
+ newblock->prev_free = p;
+ p->next_free->prev_free = newblock;
+ p->next_free = newblock;
+
+ p->size -= newblock->size;
+ p = newblock;
+ }
+
+ /* break right, also [p, newblock, p->next] */
+ if (size < p->size) {
+ newblock = (struct mem_block*) _mesa_calloc(sizeof(struct mem_block));
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+ newblock->heap = p->heap;
+
+ newblock->next = p->next;
+ newblock->prev = p;
+ p->next->prev = newblock;
+ p->next = newblock;
+
+ newblock->next_free = p->next_free;
+ newblock->prev_free = p;
+ p->next_free->prev_free = newblock;
+ p->next_free = newblock;
+
+ p->size = size;
+ }
+
+ /* p = middle block */
+ p->free = 0;
+
+ /* Remove p from the free list:
+ */
+ p->next_free->prev_free = p->prev_free;
+ p->prev_free->next_free = p->next_free;
+
+ p->next_free = 0;
+ p->prev_free = 0;
+
+ p->reserved = reserved;
+ return p;
+}
+
+
+struct mem_block *
+mmAllocMem(struct mem_block *heap, unsigned size, unsigned align2, unsigned startSearch)
+{
+ struct mem_block *p;
+ const unsigned mask = (1 << align2)-1;
+ unsigned startofs = 0;
+ unsigned endofs;
+
+ if (!heap || !size)
+ return NULL;
+
+ for (p = heap->next_free; p != heap; p = p->next_free) {
+ assert(p->free);
+
+ startofs = (p->ofs + mask) & ~mask;
+ if ( startofs < startSearch ) {
+ startofs = startSearch;
+ }
+ endofs = startofs+size;
+ if (endofs <= (p->ofs+p->size))
+ break;
+ }
+
+ if (p == heap)
+ return NULL;
+
+ assert(p->free);
+ p = SliceBlock(p,startofs,size,0,mask+1);
+
+ return p;
+}
+
+
+struct mem_block *
+mmFindBlock(struct mem_block *heap, unsigned start)
+{
+ struct mem_block *p;
+
+ for (p = heap->next; p != heap; p = p->next) {
+ if (p->ofs == start)
+ return p;
+ }
+
+ return NULL;
+}
+
+
+static INLINE int
+Join2Blocks(struct mem_block *p)
+{
+ /* XXX there should be some assertions here */
+
+ /* NOTE: heap->free == 0 */
+
+ if (p->free && p->next->free) {
+ struct mem_block *q = p->next;
+
+ assert(p->ofs + p->size == q->ofs);
+ p->size += q->size;
+
+ p->next = q->next;
+ q->next->prev = p;
+
+ q->next_free->prev_free = q->prev_free;
+ q->prev_free->next_free = q->next_free;
+
+ _mesa_free(q);
+ return 1;
+ }
+ return 0;
+}
+
+int
+mmFreeMem(struct mem_block *b)
+{
+ if (!b)
+ return 0;
+
+ if (b->free) {
+ fprintf(stderr, "block already free\n");
+ return -1;
+ }
+ if (b->reserved) {
+ fprintf(stderr, "block is reserved\n");
+ return -1;
+ }
+
+ b->free = 1;
+ b->next_free = b->heap->next_free;
+ b->prev_free = b->heap;
+ b->next_free->prev_free = b;
+ b->prev_free->next_free = b;
+
+ Join2Blocks(b);
+ if (b->prev != b->heap)
+ Join2Blocks(b->prev);
+
+ return 0;
+}
+
+
+void
+mmDestroy(struct mem_block *heap)
+{
+ struct mem_block *p;
+
+ if (!heap)
+ return;
+
+ for (p = heap->next; p != heap; ) {
+ struct mem_block *next = p->next;
+ _mesa_free(p);
+ p = next;
+ }
+
+ _mesa_free(heap);
+}
diff --git a/mesalib/src/mesa/main/mm.h b/mesalib/src/mesa/main/mm.h
new file mode 100644
index 000000000..df340808a
--- /dev/null
+++ b/mesalib/src/mesa/main/mm.h
@@ -0,0 +1,93 @@
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * Memory manager code. Primarily used by device drivers to manage texture
+ * heaps, etc.
+ */
+
+
+#ifndef MM_H
+#define MM_H
+
+
+#include "imports.h"
+
+
+struct mem_block {
+ struct mem_block *next, *prev;
+ struct mem_block *next_free, *prev_free;
+ struct mem_block *heap;
+ unsigned ofs;
+ unsigned size;
+ unsigned free:1;
+ unsigned reserved:1;
+};
+
+
+
+/**
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+extern struct mem_block *mmInit(unsigned ofs, unsigned size);
+
+/**
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input: size = size of block
+ * align2 = 2^align2 bytes alignment
+ * startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+extern struct mem_block *mmAllocMem(struct mem_block *heap, unsigned size,
+ unsigned align2, unsigned startSearch);
+
+/**
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+extern int mmFreeMem(struct mem_block *b);
+
+/**
+ * Free block starts at offset
+ * input: pointer to a heap, start offset
+ * return: pointer to a block
+ */
+extern struct mem_block *mmFindBlock(struct mem_block *heap, unsigned start);
+
+/**
+ * destroy MM
+ */
+extern void mmDestroy(struct mem_block *mmInit);
+
+/**
+ * For debuging purpose.
+ */
+extern void mmDumpMemInfo(const struct mem_block *mmInit);
+
+#endif
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
new file mode 100644
index 000000000..f8e4e4158
--- /dev/null
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -0,0 +1,3139 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file mtypes.h
+ * Main Mesa data structures.
+ *
+ * Please try to mark derived values with a leading underscore ('_').
+ */
+
+#ifndef MTYPES_H
+#define MTYPES_H
+
+
+#include "main/glheader.h"
+#include "main/config.h"
+#include "main/compiler.h"
+#include "main/mfeatures.h"
+#include "glapi/glapi.h"
+#include "math/m_matrix.h" /* GLmatrix */
+#include "main/simple_list.h" /* struct simple_node */
+
+
+/**
+ * Color channel data type.
+ */
+#if CHAN_BITS == 8
+ typedef GLubyte GLchan;
+#define CHAN_MAX 255
+#define CHAN_MAXF 255.0F
+#define CHAN_TYPE GL_UNSIGNED_BYTE
+#elif CHAN_BITS == 16
+ typedef GLushort GLchan;
+#define CHAN_MAX 65535
+#define CHAN_MAXF 65535.0F
+#define CHAN_TYPE GL_UNSIGNED_SHORT
+#elif CHAN_BITS == 32
+ typedef GLfloat GLchan;
+#define CHAN_MAX 1.0
+#define CHAN_MAXF 1.0F
+#define CHAN_TYPE GL_FLOAT
+#else
+#error "illegal number of color channel bits"
+#endif
+
+
+/**
+ * Stencil buffer data type.
+ */
+#if STENCIL_BITS==8
+ typedef GLubyte GLstencil;
+#elif STENCIL_BITS==16
+ typedef GLushort GLstencil;
+#else
+# error "illegal number of stencil bits"
+#endif
+
+
+/**
+ * \name Some forward type declarations
+ */
+/*@{*/
+struct _mesa_HashTable;
+struct gl_attrib_node;
+struct gl_meta_state;
+struct gl_pixelstore_attrib;
+struct gl_program_cache;
+struct gl_texture_format;
+struct gl_texture_image;
+struct gl_texture_object;
+struct st_context;
+typedef struct __GLcontextRec GLcontext;
+typedef struct __GLcontextModesRec GLvisual;
+typedef struct gl_framebuffer GLframebuffer;
+/*@}*/
+
+
+
+/**
+ * Indexes for vertex program attributes.
+ * GL_NV_vertex_program aliases generic attributes over the conventional
+ * attributes. In GL_ARB_vertex_program shader the aliasing is optional.
+ * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
+ * generic attributes are distinct/separate).
+ */
+typedef enum
+{
+ VERT_ATTRIB_POS = 0,
+ VERT_ATTRIB_WEIGHT = 1,
+ VERT_ATTRIB_NORMAL = 2,
+ VERT_ATTRIB_COLOR0 = 3,
+ VERT_ATTRIB_COLOR1 = 4,
+ VERT_ATTRIB_FOG = 5,
+ VERT_ATTRIB_COLOR_INDEX = 6,
+ VERT_ATTRIB_POINT_SIZE = 6, /*alias*/
+ VERT_ATTRIB_EDGEFLAG = 7,
+ VERT_ATTRIB_TEX0 = 8,
+ VERT_ATTRIB_TEX1 = 9,
+ VERT_ATTRIB_TEX2 = 10,
+ VERT_ATTRIB_TEX3 = 11,
+ VERT_ATTRIB_TEX4 = 12,
+ VERT_ATTRIB_TEX5 = 13,
+ VERT_ATTRIB_TEX6 = 14,
+ VERT_ATTRIB_TEX7 = 15,
+ VERT_ATTRIB_GENERIC0 = 16,
+ VERT_ATTRIB_GENERIC1 = 17,
+ VERT_ATTRIB_GENERIC2 = 18,
+ VERT_ATTRIB_GENERIC3 = 19,
+ VERT_ATTRIB_GENERIC4 = 20,
+ VERT_ATTRIB_GENERIC5 = 21,
+ VERT_ATTRIB_GENERIC6 = 22,
+ VERT_ATTRIB_GENERIC7 = 23,
+ VERT_ATTRIB_GENERIC8 = 24,
+ VERT_ATTRIB_GENERIC9 = 25,
+ VERT_ATTRIB_GENERIC10 = 26,
+ VERT_ATTRIB_GENERIC11 = 27,
+ VERT_ATTRIB_GENERIC12 = 28,
+ VERT_ATTRIB_GENERIC13 = 29,
+ VERT_ATTRIB_GENERIC14 = 30,
+ VERT_ATTRIB_GENERIC15 = 31,
+ VERT_ATTRIB_MAX = 32
+} gl_vert_attrib;
+
+/**
+ * Bitflags for vertex attributes.
+ * These are used in bitfields in many places.
+ */
+/*@{*/
+#define VERT_BIT_POS (1 << VERT_ATTRIB_POS)
+#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT)
+#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL)
+#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0)
+#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1)
+#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG)
+#define VERT_BIT_COLOR_INDEX (1 << VERT_ATTRIB_COLOR_INDEX)
+#define VERT_BIT_EDGEFLAG (1 << VERT_ATTRIB_EDGEFLAG)
+#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0)
+#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1)
+#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2)
+#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3)
+#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4)
+#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5)
+#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6)
+#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7)
+#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0)
+#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1)
+#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2)
+#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3)
+#define VERT_BIT_GENERIC4 (1 << VERT_ATTRIB_GENERIC4)
+#define VERT_BIT_GENERIC5 (1 << VERT_ATTRIB_GENERIC5)
+#define VERT_BIT_GENERIC6 (1 << VERT_ATTRIB_GENERIC6)
+#define VERT_BIT_GENERIC7 (1 << VERT_ATTRIB_GENERIC7)
+#define VERT_BIT_GENERIC8 (1 << VERT_ATTRIB_GENERIC8)
+#define VERT_BIT_GENERIC9 (1 << VERT_ATTRIB_GENERIC9)
+#define VERT_BIT_GENERIC10 (1 << VERT_ATTRIB_GENERIC10)
+#define VERT_BIT_GENERIC11 (1 << VERT_ATTRIB_GENERIC11)
+#define VERT_BIT_GENERIC12 (1 << VERT_ATTRIB_GENERIC12)
+#define VERT_BIT_GENERIC13 (1 << VERT_ATTRIB_GENERIC13)
+#define VERT_BIT_GENERIC14 (1 << VERT_ATTRIB_GENERIC14)
+#define VERT_BIT_GENERIC15 (1 << VERT_ATTRIB_GENERIC15)
+
+#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u)))
+#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g)))
+/*@}*/
+
+
+/**
+ * Indexes for vertex program result attributes
+ */
+typedef enum
+{
+ VERT_RESULT_HPOS = 0,
+ VERT_RESULT_COL0 = 1,
+ VERT_RESULT_COL1 = 2,
+ VERT_RESULT_FOGC = 3,
+ VERT_RESULT_TEX0 = 4,
+ VERT_RESULT_TEX1 = 5,
+ VERT_RESULT_TEX2 = 6,
+ VERT_RESULT_TEX3 = 7,
+ VERT_RESULT_TEX4 = 8,
+ VERT_RESULT_TEX5 = 9,
+ VERT_RESULT_TEX6 = 10,
+ VERT_RESULT_TEX7 = 11,
+ VERT_RESULT_PSIZ = 12,
+ VERT_RESULT_BFC0 = 13,
+ VERT_RESULT_BFC1 = 14,
+ VERT_RESULT_EDGE = 15,
+ VERT_RESULT_VAR0 = 16 /**< shader varying */,
+ VERT_RESULT_MAX = (VERT_RESULT_VAR0 + MAX_VARYING)
+} gl_vert_result;
+
+
+/**
+ * Indexes for fragment program input attributes.
+ */
+typedef enum
+{
+ FRAG_ATTRIB_WPOS = 0,
+ FRAG_ATTRIB_COL0 = 1,
+ FRAG_ATTRIB_COL1 = 2,
+ FRAG_ATTRIB_FOGC = 3,
+ FRAG_ATTRIB_TEX0 = 4,
+ FRAG_ATTRIB_TEX1 = 5,
+ FRAG_ATTRIB_TEX2 = 6,
+ FRAG_ATTRIB_TEX3 = 7,
+ FRAG_ATTRIB_TEX4 = 8,
+ FRAG_ATTRIB_TEX5 = 9,
+ FRAG_ATTRIB_TEX6 = 10,
+ FRAG_ATTRIB_TEX7 = 11,
+ FRAG_ATTRIB_FACE = 12, /**< front/back face */
+ FRAG_ATTRIB_PNTC = 13, /**< sprite/point coord */
+ FRAG_ATTRIB_VAR0 = 14, /**< shader varying */
+ FRAG_ATTRIB_MAX = (FRAG_ATTRIB_VAR0 + MAX_VARYING)
+} gl_frag_attrib;
+
+/**
+ * Bitflags for fragment program input attributes.
+ */
+/*@{*/
+#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS)
+#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0)
+#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1)
+#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC)
+#define FRAG_BIT_FACE (1 << FRAG_ATTRIB_FACE)
+#define FRAG_BIT_PNTC (1 << FRAG_ATTRIB_PNTC)
+#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0)
+#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1)
+#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2)
+#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3)
+#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4)
+#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5)
+#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6)
+#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7)
+#define FRAG_BIT_VAR0 (1 << FRAG_ATTRIB_VAR0)
+
+#define FRAG_BIT_TEX(U) (FRAG_BIT_TEX0 << (U))
+#define FRAG_BIT_VAR(V) (FRAG_BIT_VAR0 << (V))
+
+#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \
+ FRAG_BIT_TEX1| \
+ FRAG_BIT_TEX2| \
+ FRAG_BIT_TEX3| \
+ FRAG_BIT_TEX4| \
+ FRAG_BIT_TEX5| \
+ FRAG_BIT_TEX6| \
+ FRAG_BIT_TEX7)
+/*@}*/
+
+
+/**
+ * Fragment program results
+ */
+typedef enum
+{
+ FRAG_RESULT_DEPTH = 0,
+ FRAG_RESULT_COLOR = 1,
+ FRAG_RESULT_DATA0 = 2,
+ FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
+} gl_frag_result;
+
+
+/**
+ * Indexes for all renderbuffers
+ */
+typedef enum
+{
+ /* the four standard color buffers */
+ BUFFER_FRONT_LEFT,
+ BUFFER_BACK_LEFT,
+ BUFFER_FRONT_RIGHT,
+ BUFFER_BACK_RIGHT,
+ BUFFER_DEPTH,
+ BUFFER_STENCIL,
+ BUFFER_ACCUM,
+ /* optional aux buffer */
+ BUFFER_AUX0,
+ /* generic renderbuffers */
+ BUFFER_COLOR0,
+ BUFFER_COLOR1,
+ BUFFER_COLOR2,
+ BUFFER_COLOR3,
+ BUFFER_COLOR4,
+ BUFFER_COLOR5,
+ BUFFER_COLOR6,
+ BUFFER_COLOR7,
+ BUFFER_COUNT
+} gl_buffer_index;
+
+/**
+ * Bit flags for all renderbuffers
+ */
+#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT)
+#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT)
+#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT)
+#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT)
+#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0)
+#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1)
+#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2)
+#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3)
+#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH)
+#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL)
+#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM)
+#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0)
+#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1)
+#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2)
+#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3)
+#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4)
+#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5)
+#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6)
+#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7)
+
+/**
+ * Mask of all the color buffer bits (but not accum).
+ */
+#define BUFFER_BITS_COLOR (BUFFER_BIT_FRONT_LEFT | \
+ BUFFER_BIT_BACK_LEFT | \
+ BUFFER_BIT_FRONT_RIGHT | \
+ BUFFER_BIT_BACK_RIGHT | \
+ BUFFER_BIT_AUX0 | \
+ BUFFER_BIT_COLOR0 | \
+ BUFFER_BIT_COLOR1 | \
+ BUFFER_BIT_COLOR2 | \
+ BUFFER_BIT_COLOR3 | \
+ BUFFER_BIT_COLOR4 | \
+ BUFFER_BIT_COLOR5 | \
+ BUFFER_BIT_COLOR6 | \
+ BUFFER_BIT_COLOR7)
+
+
+/** The pixel transfer path has three color tables: */
+typedef enum
+{
+ COLORTABLE_PRECONVOLUTION,
+ COLORTABLE_POSTCONVOLUTION,
+ COLORTABLE_POSTCOLORMATRIX,
+ COLORTABLE_MAX
+} gl_colortable_index;
+
+
+/**
+ * Data structure for color tables
+ */
+struct gl_color_table
+{
+ GLenum InternalFormat; /**< The user-specified format */
+ GLenum _BaseFormat; /**< GL_ALPHA, GL_RGBA, GL_RGB, etc */
+ GLuint Size; /**< number of entries in table */
+ GLfloat *TableF; /**< Color table, floating point values */
+ GLubyte *TableUB; /**< Color table, ubyte values */
+ GLubyte RedSize;
+ GLubyte GreenSize;
+ GLubyte BlueSize;
+ GLubyte AlphaSize;
+ GLubyte LuminanceSize;
+ GLubyte IntensitySize;
+};
+
+
+/**
+ * \name Bit flags used for updating material values.
+ */
+/*@{*/
+#define MAT_ATTRIB_FRONT_AMBIENT 0
+#define MAT_ATTRIB_BACK_AMBIENT 1
+#define MAT_ATTRIB_FRONT_DIFFUSE 2
+#define MAT_ATTRIB_BACK_DIFFUSE 3
+#define MAT_ATTRIB_FRONT_SPECULAR 4
+#define MAT_ATTRIB_BACK_SPECULAR 5
+#define MAT_ATTRIB_FRONT_EMISSION 6
+#define MAT_ATTRIB_BACK_EMISSION 7
+#define MAT_ATTRIB_FRONT_SHININESS 8
+#define MAT_ATTRIB_BACK_SHININESS 9
+#define MAT_ATTRIB_FRONT_INDEXES 10
+#define MAT_ATTRIB_BACK_INDEXES 11
+#define MAT_ATTRIB_MAX 12
+
+#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f))
+#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f))
+#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f))
+#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f))
+#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f))
+#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f))
+
+#define MAT_INDEX_AMBIENT 0
+#define MAT_INDEX_DIFFUSE 1
+#define MAT_INDEX_SPECULAR 2
+
+#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT)
+#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT)
+#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE)
+#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE)
+#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR)
+#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR)
+#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION)
+#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION)
+#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS)
+#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS)
+#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES)
+#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES)
+
+
+#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \
+ MAT_BIT_FRONT_AMBIENT | \
+ MAT_BIT_FRONT_DIFFUSE | \
+ MAT_BIT_FRONT_SPECULAR | \
+ MAT_BIT_FRONT_SHININESS | \
+ MAT_BIT_FRONT_INDEXES)
+
+#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \
+ MAT_BIT_BACK_AMBIENT | \
+ MAT_BIT_BACK_DIFFUSE | \
+ MAT_BIT_BACK_SPECULAR | \
+ MAT_BIT_BACK_SHININESS | \
+ MAT_BIT_BACK_INDEXES)
+
+#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS)
+/*@}*/
+
+
+#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */
+#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
+
+/**
+ * Material shininess lookup table.
+ */
+struct gl_shine_tab
+{
+ struct gl_shine_tab *next, *prev;
+ GLfloat tab[SHINE_TABLE_SIZE+1];
+ GLfloat shininess;
+ GLuint refcount;
+};
+
+
+/**
+ * Light source state.
+ */
+struct gl_light
+{
+ struct gl_light *next; /**< double linked list with sentinel */
+ struct gl_light *prev;
+
+ GLfloat Ambient[4]; /**< ambient color */
+ GLfloat Diffuse[4]; /**< diffuse color */
+ GLfloat Specular[4]; /**< specular color */
+ GLfloat EyePosition[4]; /**< position in eye coordinates */
+ GLfloat SpotDirection[4]; /**< spotlight direction in eye coordinates */
+ GLfloat SpotExponent;
+ GLfloat SpotCutoff; /**< in degrees */
+ GLfloat _CosCutoffNeg; /**< = cos(SpotCutoff) */
+ GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */
+ GLfloat ConstantAttenuation;
+ GLfloat LinearAttenuation;
+ GLfloat QuadraticAttenuation;
+ GLboolean Enabled; /**< On/off flag */
+
+ /**
+ * \name Derived fields
+ */
+ /*@{*/
+ GLbitfield _Flags; /**< State */
+
+ GLfloat _Position[4]; /**< position in eye/obj coordinates */
+ GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */
+ GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */
+ GLfloat _NormSpotDirection[4]; /**< normalized spotlight direction */
+ GLfloat _VP_inf_spot_attenuation;
+
+ GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */
+ GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */
+ GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */
+ GLfloat _MatSpecular[2][3]; /**< material spec * light specular */
+ GLfloat _dli; /**< CI diffuse light intensity */
+ GLfloat _sli; /**< CI specular light intensity */
+ /*@}*/
+};
+
+
+/**
+ * Light model state.
+ */
+struct gl_lightmodel
+{
+ GLfloat Ambient[4]; /**< ambient color */
+ GLboolean LocalViewer; /**< Local (or infinite) view point? */
+ GLboolean TwoSide; /**< Two (or one) sided lighting? */
+ GLenum ColorControl; /**< either GL_SINGLE_COLOR
+ * or GL_SEPARATE_SPECULAR_COLOR */
+};
+
+
+/**
+ * Material state.
+ */
+struct gl_material
+{
+ GLfloat Attrib[MAT_ATTRIB_MAX][4];
+};
+
+
+/**
+ * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT)
+ */
+struct gl_accum_attrib
+{
+ GLfloat ClearColor[4]; /**< Accumulation buffer clear color */
+};
+
+
+/**
+ * Color buffer attribute group (GL_COLOR_BUFFER_BIT).
+ */
+struct gl_colorbuffer_attrib
+{
+ GLuint ClearIndex; /**< Index to use for glClear */
+ GLclampf ClearColor[4]; /**< Color to use for glClear */
+
+ GLuint IndexMask; /**< Color index write mask */
+ GLubyte ColorMask[4]; /**< Each flag is 0xff or 0x0 */
+
+ GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
+
+ /**
+ * \name alpha testing
+ */
+ /*@{*/
+ GLboolean AlphaEnabled; /**< Alpha test enabled flag */
+ GLenum AlphaFunc; /**< Alpha test function */
+ GLclampf AlphaRef; /**< Alpha reference value */
+ /*@}*/
+
+ /**
+ * \name Blending
+ */
+ /*@{*/
+ GLboolean BlendEnabled; /**< Blending enabled flag */
+ GLenum BlendSrcRGB; /**< Blending source operator */
+ GLenum BlendDstRGB; /**< Blending destination operator */
+ GLenum BlendSrcA; /**< GL_INGR_blend_func_separate */
+ GLenum BlendDstA; /**< GL_INGR_blend_func_separate */
+ GLenum BlendEquationRGB; /**< Blending equation */
+ GLenum BlendEquationA; /**< GL_EXT_blend_equation_separate */
+ GLfloat BlendColor[4]; /**< Blending color */
+ /*@}*/
+
+ /**
+ * \name Logic op
+ */
+ /*@{*/
+ GLenum LogicOp; /**< Logic operator */
+ GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */
+ GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */
+ GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */
+ /*@}*/
+
+ GLboolean DitherFlag; /**< Dither enable flag */
+
+ GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+};
+
+
+/**
+ * Current attribute group (GL_CURRENT_BIT).
+ */
+struct gl_current_attrib
+{
+ /**
+ * \name Current vertex attributes.
+ * \note Values are valid only after FLUSH_VERTICES has been called.
+ * \note Index and Edgeflag current values are stored as floats in the
+ * SIX and SEVEN attribute slots.
+ */
+ GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Position, color, texcoords, etc */
+
+ /**
+ * \name Current raster position attributes (always valid).
+ * \note This set of attributes is very similar to the SWvertex struct.
+ */
+ /*@{*/
+ GLfloat RasterPos[4];
+ GLfloat RasterDistance;
+ GLfloat RasterColor[4];
+ GLfloat RasterSecondaryColor[4];
+ GLfloat RasterIndex;
+ GLfloat RasterTexCoords[MAX_TEXTURE_UNITS][4];
+ GLboolean RasterPosValid;
+ /*@}*/
+};
+
+
+/**
+ * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT).
+ */
+struct gl_depthbuffer_attrib
+{
+ GLenum Func; /**< Function for depth buffer compare */
+ GLclampd Clear; /**< Value to clear depth buffer to */
+ GLboolean Test; /**< Depth buffering enabled flag */
+ GLboolean Mask; /**< Depth buffer writable? */
+ GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */
+ GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */
+};
+
+
+/**
+ * Evaluator attribute group (GL_EVAL_BIT).
+ */
+struct gl_eval_attrib
+{
+ /**
+ * \name Enable bits
+ */
+ /*@{*/
+ GLboolean Map1Color4;
+ GLboolean Map1Index;
+ GLboolean Map1Normal;
+ GLboolean Map1TextureCoord1;
+ GLboolean Map1TextureCoord2;
+ GLboolean Map1TextureCoord3;
+ GLboolean Map1TextureCoord4;
+ GLboolean Map1Vertex3;
+ GLboolean Map1Vertex4;
+ GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean Map2Color4;
+ GLboolean Map2Index;
+ GLboolean Map2Normal;
+ GLboolean Map2TextureCoord1;
+ GLboolean Map2TextureCoord2;
+ GLboolean Map2TextureCoord3;
+ GLboolean Map2TextureCoord4;
+ GLboolean Map2Vertex3;
+ GLboolean Map2Vertex4;
+ GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */
+ GLboolean AutoNormal;
+ /*@}*/
+
+ /**
+ * \name Map Grid endpoints and divisions and calculated du values
+ */
+ /*@{*/
+ GLint MapGrid1un;
+ GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du;
+ GLint MapGrid2un, MapGrid2vn;
+ GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du;
+ GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv;
+ /*@}*/
+};
+
+
+/**
+ * Fog attribute group (GL_FOG_BIT).
+ */
+struct gl_fog_attrib
+{
+ GLboolean Enabled; /**< Fog enabled flag */
+ GLfloat Color[4]; /**< Fog color */
+ GLfloat Density; /**< Density >= 0.0 */
+ GLfloat Start; /**< Start distance in eye coords */
+ GLfloat End; /**< End distance in eye coords */
+ GLfloat Index; /**< Fog index */
+ GLenum Mode; /**< Fog mode */
+ GLboolean ColorSumEnabled;
+ GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */
+ GLfloat _Scale; /**< (End == Start) ? 1.0 : 1.0 / (End - Start) */
+};
+
+
+/**
+ * Hint attribute group (GL_HINT_BIT).
+ *
+ * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE.
+ */
+struct gl_hint_attrib
+{
+ GLenum PerspectiveCorrection;
+ GLenum PointSmooth;
+ GLenum LineSmooth;
+ GLenum PolygonSmooth;
+ GLenum Fog;
+ GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */
+ GLenum TextureCompression; /**< GL_ARB_texture_compression */
+ GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */
+};
+
+
+/**
+ * Histogram attributes.
+ */
+struct gl_histogram_attrib
+{
+ GLuint Width; /**< number of table entries */
+ GLint Format; /**< GL_ALPHA, GL_RGB, etc */
+ GLuint Count[HISTOGRAM_TABLE_SIZE][4]; /**< the histogram */
+ GLboolean Sink; /**< terminate image transfer? */
+ GLubyte RedSize; /**< Bits per counter */
+ GLubyte GreenSize;
+ GLubyte BlueSize;
+ GLubyte AlphaSize;
+ GLubyte LuminanceSize;
+};
+
+
+/**
+ * Color Min/max state.
+ */
+struct gl_minmax_attrib
+{
+ GLenum Format;
+ GLboolean Sink;
+ GLfloat Min[4], Max[4]; /**< RGBA */
+};
+
+
+/**
+ * Image convolution state.
+ */
+struct gl_convolution_attrib
+{
+ GLenum Format;
+ GLenum InternalFormat;
+ GLuint Width;
+ GLuint Height;
+ GLfloat Filter[MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_HEIGHT * 4];
+};
+
+
+/**
+ * Light state flags.
+ */
+/*@{*/
+#define LIGHT_SPOT 0x1
+#define LIGHT_LOCAL_VIEWER 0x2
+#define LIGHT_POSITIONAL 0x4
+#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER)
+/*@}*/
+
+
+/**
+ * Lighting attribute group (GL_LIGHT_BIT).
+ */
+struct gl_light_attrib
+{
+ struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */
+ struct gl_lightmodel Model; /**< Lighting model */
+
+ /**
+ * Must flush FLUSH_VERTICES before referencing:
+ */
+ /*@{*/
+ struct gl_material Material; /**< Includes front & back values */
+ /*@}*/
+
+ GLboolean Enabled; /**< Lighting enabled flag */
+ GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */
+ GLenum ProvokingVertex; /**< GL_EXT_provoking_vertex */
+ GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */
+ GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */
+ GLbitfield ColorMaterialBitmask; /**< bitmask formed from Face and Mode */
+ GLboolean ColorMaterialEnabled;
+ GLenum ClampVertexColor;
+
+ struct gl_light EnabledList; /**< List sentinel */
+
+ /**
+ * Derived state for optimizations:
+ */
+ /*@{*/
+ GLboolean _NeedEyeCoords;
+ GLboolean _NeedVertices; /**< Use fast shader? */
+ GLbitfield _Flags; /**< LIGHT_* flags, see above */
+ GLfloat _BaseColor[2][3];
+ /*@}*/
+};
+
+
+/**
+ * Line attribute group (GL_LINE_BIT).
+ */
+struct gl_line_attrib
+{
+ GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */
+ GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */
+ GLushort StipplePattern; /**< Stipple pattern */
+ GLint StippleFactor; /**< Stipple repeat factor */
+ GLfloat Width; /**< Line width */
+};
+
+
+/**
+ * Display list attribute group (GL_LIST_BIT).
+ */
+struct gl_list_attrib
+{
+ GLuint ListBase;
+};
+
+
+/**
+ * Used by device drivers to hook new commands into display lists.
+ */
+struct gl_list_instruction
+{
+ GLuint Size;
+ void (*Execute)( GLcontext *ctx, void *data );
+ void (*Destroy)( GLcontext *ctx, void *data );
+ void (*Print)( GLcontext *ctx, void *data );
+};
+
+#define MAX_DLIST_EXT_OPCODES 16
+
+/**
+ * Used by device drivers to hook new commands into display lists.
+ */
+struct gl_list_extensions
+{
+ struct gl_list_instruction Opcode[MAX_DLIST_EXT_OPCODES];
+ GLuint NumOpcodes;
+};
+
+
+/**
+ * Multisample attribute group (GL_MULTISAMPLE_BIT).
+ */
+struct gl_multisample_attrib
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /**< true if Enabled and multisample buffer */
+ GLboolean SampleAlphaToCoverage;
+ GLboolean SampleAlphaToOne;
+ GLboolean SampleCoverage;
+ GLfloat SampleCoverageValue;
+ GLboolean SampleCoverageInvert;
+};
+
+
+/**
+ * A pixelmap (see glPixelMap)
+ */
+struct gl_pixelmap
+{
+ GLint Size;
+ GLfloat Map[MAX_PIXEL_MAP_TABLE];
+ GLubyte Map8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */
+};
+
+
+/**
+ * Collection of all pixelmaps
+ */
+struct gl_pixelmaps
+{
+ struct gl_pixelmap RtoR; /**< i.e. GL_PIXEL_MAP_R_TO_R */
+ struct gl_pixelmap GtoG;
+ struct gl_pixelmap BtoB;
+ struct gl_pixelmap AtoA;
+ struct gl_pixelmap ItoR;
+ struct gl_pixelmap ItoG;
+ struct gl_pixelmap ItoB;
+ struct gl_pixelmap ItoA;
+ struct gl_pixelmap ItoI;
+ struct gl_pixelmap StoS;
+};
+
+
+/**
+ * Pixel attribute group (GL_PIXEL_MODE_BIT).
+ */
+struct gl_pixel_attrib
+{
+ GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */
+
+ /*--- Begin Pixel Transfer State ---*/
+ /* Fields are in the order in which they're applied... */
+
+ /** Scale & Bias (index shift, offset) */
+ /*@{*/
+ GLfloat RedBias, RedScale;
+ GLfloat GreenBias, GreenScale;
+ GLfloat BlueBias, BlueScale;
+ GLfloat AlphaBias, AlphaScale;
+ GLfloat DepthBias, DepthScale;
+ GLint IndexShift, IndexOffset;
+ /*@}*/
+
+ /* Pixel Maps */
+ /* Note: actual pixel maps are not part of this attrib group */
+ GLboolean MapColorFlag;
+ GLboolean MapStencilFlag;
+
+ /* There are multiple color table stages: */
+ GLboolean ColorTableEnabled[COLORTABLE_MAX];
+ GLfloat ColorTableScale[COLORTABLE_MAX][4]; /**< RGBA */
+ GLfloat ColorTableBias[COLORTABLE_MAX][4]; /**< RGBA */
+
+ /* Convolution (GL_EXT_convolution) */
+ GLboolean Convolution1DEnabled;
+ GLboolean Convolution2DEnabled;
+ GLboolean Separable2DEnabled;
+ GLfloat ConvolutionBorderColor[3][4]; /**< RGBA */
+ GLenum ConvolutionBorderMode[3];
+ GLfloat ConvolutionFilterScale[3][4]; /**< RGBA */
+ GLfloat ConvolutionFilterBias[3][4]; /**< RGBA */
+ GLfloat PostConvolutionScale[4]; /**< RGBA */
+ GLfloat PostConvolutionBias[4]; /**< RGBA */
+
+ /* Color matrix (GL_SGI_color_matrix) */
+ /* Note: the color matrix is not part of this attrib group */
+ GLfloat PostColorMatrixScale[4]; /**< RGBA */
+ GLfloat PostColorMatrixBias[4]; /**< RGBA */
+
+ /* Histogram & minmax (GL_EXT_histogram) */
+ /* Note: histogram and minmax data are not part of this attrib group */
+ GLboolean HistogramEnabled;
+ GLboolean MinMaxEnabled;
+
+ /*--- End Pixel Transfer State ---*/
+
+ /** glPixelZoom */
+ GLfloat ZoomX, ZoomY;
+
+ /** GL_SGI_texture_color_table */
+ GLfloat TextureColorTableScale[4]; /**< RGBA */
+ GLfloat TextureColorTableBias[4]; /**< RGBA */
+};
+
+
+/**
+ * Point attribute group (GL_POINT_BIT).
+ */
+struct gl_point_attrib
+{
+ GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */
+ GLfloat Size; /**< User-specified point size */
+ GLfloat Params[3]; /**< GL_EXT_point_parameters */
+ GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */
+ GLfloat Threshold; /**< GL_EXT_point_parameters */
+ GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */
+ GLboolean PointSprite; /**< GL_NV/ARB_point_sprite */
+ GLboolean CoordReplace[MAX_TEXTURE_UNITS]; /**< GL_ARB_point_sprite */
+ GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */
+ GLenum SpriteOrigin; /**< GL_ARB_point_sprite */
+};
+
+
+/**
+ * Polygon attribute group (GL_POLYGON_BIT).
+ */
+struct gl_polygon_attrib
+{
+ GLenum FrontFace; /**< Either GL_CW or GL_CCW */
+ GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */
+ GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */
+ GLboolean CullFlag; /**< Culling on/off flag */
+ GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */
+ GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */
+ GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */
+ GLfloat OffsetFactor; /**< Polygon offset factor, from user */
+ GLfloat OffsetUnits; /**< Polygon offset units, from user */
+ GLboolean OffsetPoint; /**< Offset in GL_POINT mode */
+ GLboolean OffsetLine; /**< Offset in GL_LINE mode */
+ GLboolean OffsetFill; /**< Offset in GL_FILL mode */
+};
+
+
+/**
+ * Scissor attributes (GL_SCISSOR_BIT).
+ */
+struct gl_scissor_attrib
+{
+ GLboolean Enabled; /**< Scissor test enabled? */
+ GLint X, Y; /**< Lower left corner of box */
+ GLsizei Width, Height; /**< Size of box */
+};
+
+
+/**
+ * Stencil attribute group (GL_STENCIL_BUFFER_BIT).
+ *
+ * Three sets of stencil data are tracked so that OpenGL 2.0,
+ * GL_EXT_stencil_two_side, and GL_ATI_separate_stencil can all be supported
+ * simultaneously. In each of the stencil state arrays, element 0 corresponds
+ * to GL_FRONT. Element 1 corresponds to the OpenGL 2.0 /
+ * GL_ATI_separate_stencil GL_BACK state. Element 2 corresponds to the
+ * GL_EXT_stencil_two_side GL_BACK state.
+ *
+ * The derived value \c _BackFace is either 1 or 2 depending on whether or
+ * not GL_STENCIL_TEST_TWO_SIDE_EXT is enabled.
+ *
+ * The derived value \c _TestTwoSide is set when the front-face and back-face
+ * stencil state are different.
+ */
+struct gl_stencil_attrib
+{
+ GLboolean Enabled; /**< Enabled flag */
+ GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */
+ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */
+ GLboolean _Enabled; /**< Enabled and stencil buffer present */
+ GLboolean _TestTwoSide;
+ GLubyte _BackFace; /**< Current back stencil state (1 or 2) */
+ GLenum Function[3]; /**< Stencil function */
+ GLenum FailFunc[3]; /**< Fail function */
+ GLenum ZPassFunc[3]; /**< Depth buffer pass function */
+ GLenum ZFailFunc[3]; /**< Depth buffer fail function */
+ GLint Ref[3]; /**< Reference value */
+ GLuint ValueMask[3]; /**< Value mask */
+ GLuint WriteMask[3]; /**< Write mask */
+ GLuint Clear; /**< Clear value */
+};
+
+
+/**
+ * An index for each type of texture object. These correspond to the GL
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * Note: the order is from highest priority to lowest priority.
+ */
+typedef enum
+{
+ TEXTURE_2D_ARRAY_INDEX,
+ TEXTURE_1D_ARRAY_INDEX,
+ TEXTURE_CUBE_INDEX,
+ TEXTURE_3D_INDEX,
+ TEXTURE_RECT_INDEX,
+ TEXTURE_2D_INDEX,
+ TEXTURE_1D_INDEX,
+ NUM_TEXTURE_TARGETS
+} gl_texture_index;
+
+
+/**
+ * Bit flags for each type of texture object
+ * Used for Texture.Unit[]._ReallyEnabled flags.
+ */
+/*@{*/
+#define TEXTURE_2D_ARRAY_BIT (1 << TEXTURE_2D_ARRAY_INDEX)
+#define TEXTURE_1D_ARRAY_BIT (1 << TEXTURE_1D_ARRAY_INDEX)
+#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX)
+#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX)
+#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX)
+#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX)
+#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX)
+/*@}*/
+
+
+/**
+ * TexGenEnabled flags.
+ */
+/*@{*/
+#define S_BIT 1
+#define T_BIT 2
+#define R_BIT 4
+#define Q_BIT 8
+/*@}*/
+
+
+/**
+ * Bit flag versions of the corresponding GL_ constants.
+ */
+/*@{*/
+#define TEXGEN_SPHERE_MAP 0x1
+#define TEXGEN_OBJ_LINEAR 0x2
+#define TEXGEN_EYE_LINEAR 0x4
+#define TEXGEN_REFLECTION_MAP_NV 0x8
+#define TEXGEN_NORMAL_MAP_NV 0x10
+
+#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV)
+#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV | \
+ TEXGEN_NORMAL_MAP_NV | \
+ TEXGEN_EYE_LINEAR)
+/*@}*/
+
+
+
+/** Tex-gen enabled for texture unit? */
+#define ENABLE_TEXGEN(unit) (1 << (unit))
+
+/** Non-identity texture matrix for texture unit? */
+#define ENABLE_TEXMAT(unit) (1 << (unit))
+
+
+/**
+ * Texel fetch function prototype. We use texel fetch functions to
+ * extract RGBA, color indexes and depth components out of 1D, 2D and 3D
+ * texture images. These functions help to isolate us from the gritty
+ * details of all the various texture image encodings.
+ *
+ * \param texImage texture image.
+ * \param col texel column.
+ * \param row texel row.
+ * \param img texel image level/layer.
+ * \param texelOut output texel (up to 4 GLchans)
+ */
+typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLchan *texelOut );
+
+/**
+ * As above, but returns floats.
+ * Used for depth component images and for upcoming signed/float
+ * texture images.
+ */
+typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ GLfloat *texelOut );
+
+
+typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ const void *texel);
+
+
+/**
+ * This macro defines the (many) parameters to the texstore functions.
+ * \param dims either 1 or 2 or 3
+ * \param baseInternalFormat user-specified base internal format
+ * \param dstFormat destination Mesa texture format
+ * \param dstAddr destination image address
+ * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
+ * \param dstRowStride destination image row stride, in bytes
+ * \param dstImageOffsets offset of each 2D slice within 3D texture, in texels
+ * \param srcWidth/Height/Depth source image size, in pixels
+ * \param srcFormat incoming image format
+ * \param srcType incoming image data type
+ * \param srcAddr source image address
+ * \param srcPacking source image packing parameters
+ */
+#define TEXSTORE_PARAMS \
+ GLcontext *ctx, GLuint dims, \
+ GLenum baseInternalFormat, \
+ const struct gl_texture_format *dstFormat, \
+ GLvoid *dstAddr, \
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, \
+ GLint dstRowStride, const GLuint *dstImageOffsets, \
+ GLint srcWidth, GLint srcHeight, GLint srcDepth, \
+ GLenum srcFormat, GLenum srcType, \
+ const GLvoid *srcAddr, \
+ const struct gl_pixelstore_attrib *srcPacking
+
+
+
+/**
+ * Texture image storage function.
+ */
+typedef GLboolean (*StoreTexImageFunc)(TEXSTORE_PARAMS);
+
+
+/**
+ * Texture format record
+ */
+struct gl_texture_format
+{
+ GLint MesaFormat; /**< One of the MESA_FORMAT_* values */
+
+ GLenum BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
+ * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_COLOR_INDEX or
+ * GL_DEPTH_COMPONENT.
+ */
+ GLenum DataType; /**< GL_FLOAT or GL_UNSIGNED_NORMALIZED_ARB */
+
+ /**
+ * Bits per texel component. These are just rough approximations
+ * for compressed texture formats.
+ */
+ /*@{*/
+ GLubyte RedBits;
+ GLubyte GreenBits;
+ GLubyte BlueBits;
+ GLubyte AlphaBits;
+ GLubyte LuminanceBits;
+ GLubyte IntensityBits;
+ GLubyte IndexBits;
+ GLubyte DepthBits;
+ GLubyte StencilBits; /**< GL_EXT_packed_depth_stencil */
+ /*@}*/
+
+ GLuint TexelBytes; /**< Bytes per texel, 0 if compressed format */
+
+ StoreTexImageFunc StoreImage;
+
+ /**
+ * \name Texel fetch function pointers
+ */
+ /*@{*/
+ FetchTexelFuncC FetchTexel1D;
+ FetchTexelFuncC FetchTexel2D;
+ FetchTexelFuncC FetchTexel3D;
+ FetchTexelFuncF FetchTexel1Df;
+ FetchTexelFuncF FetchTexel2Df;
+ FetchTexelFuncF FetchTexel3Df;
+ /*@}*/
+
+ StoreTexelFunc StoreTexel;
+};
+
+
+/**
+ * Texture image state. Describes the dimensions of a texture image,
+ * the texel format and pointers to Texel Fetch functions.
+ */
+struct gl_texture_image
+{
+ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA,
+ * GL_LUMINANCE, GL_LUMINANCE_ALPHA,
+ * GL_INTENSITY, GL_COLOR_INDEX,
+ * GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT
+ * only. Used for choosing TexEnv arithmetic.
+ */
+ GLint InternalFormat; /**< Internal format as given by the user */
+ GLuint Border; /**< 0 or 1 */
+ GLuint Width; /**< = 2^WidthLog2 + 2*Border */
+ GLuint Height; /**< = 2^HeightLog2 + 2*Border */
+ GLuint Depth; /**< = 2^DepthLog2 + 2*Border */
+ GLuint Width2; /**< = Width - 2*Border */
+ GLuint Height2; /**< = Height - 2*Border */
+ GLuint Depth2; /**< = Depth - 2*Border */
+ GLuint WidthLog2; /**< = log2(Width2) */
+ GLuint HeightLog2; /**< = log2(Height2) */
+ GLuint DepthLog2; /**< = log2(Depth2) */
+ GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */
+ GLfloat WidthScale; /**< used for mipmap LOD computation */
+ GLfloat HeightScale; /**< used for mipmap LOD computation */
+ GLfloat DepthScale; /**< used for mipmap LOD computation */
+ GLboolean IsClientData; /**< Data owned by client? */
+ GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */
+
+ const struct gl_texture_format *TexFormat;
+
+ struct gl_texture_object *TexObject; /**< Pointer back to parent object */
+
+ FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */
+ FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */
+
+ GLboolean IsCompressed; /**< GL_ARB_texture_compression */
+ GLuint CompressedSize; /**< GL_ARB_texture_compression */
+
+ GLuint RowStride; /**< Padded width in units of texels */
+ GLuint *ImageOffsets; /**< if 3D texture: array [Depth] of offsets to
+ each 2D slice in 'Data', in texels */
+ GLvoid *Data; /**< Image data, accessed via FetchTexel() */
+
+ /**
+ * \name For device driver:
+ */
+ /*@{*/
+ void *DriverData; /**< Arbitrary device driver data */
+ /*@}*/
+};
+
+
+/**
+ * Indexes for cube map faces.
+ */
+typedef enum
+{
+ FACE_POS_X = 0,
+ FACE_NEG_X = 1,
+ FACE_POS_Y = 2,
+ FACE_NEG_Y = 3,
+ FACE_POS_Z = 4,
+ FACE_NEG_Z = 5,
+ MAX_FACES = 6
+} gl_face_index;
+
+
+/**
+ * Texture object state. Contains the array of mipmap images, border color,
+ * wrap modes, filter modes, shadow/texcompare state, and the per-texture
+ * color palette.
+ */
+struct gl_texture_object
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< reference count */
+ GLuint Name; /**< the user-visible texture object ID */
+ GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */
+ GLfloat Priority; /**< in [0,1] */
+ GLfloat BorderColor[4]; /**< unclamped */
+ GLenum WrapS; /**< S-axis texture image wrap mode */
+ GLenum WrapT; /**< T-axis texture image wrap mode */
+ GLenum WrapR; /**< R-axis texture image wrap mode */
+ GLenum MinFilter; /**< minification filter */
+ GLenum MagFilter; /**< magnification filter */
+ GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
+ GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
+ GLfloat LodBias; /**< OpenGL 1.4 */
+ GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */
+ GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */
+ GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLenum CompareMode; /**< GL_ARB_shadow */
+ GLenum CompareFunc; /**< GL_ARB_shadow */
+ GLfloat CompareFailValue; /**< GL_ARB_shadow_ambient */
+ GLenum DepthMode; /**< GL_ARB_depth_texture */
+ GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */
+ GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */
+ GLint CropRect[4]; /**< GL_OES_draw_texture */
+ GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */
+ GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */
+ GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */
+ GLboolean _Complete; /**< Is texture object complete? */
+ GLboolean _RenderToTexture; /**< Any rendering to this texture? */
+
+ /** Actual texture images, indexed by [cube face] and [mipmap level] */
+ struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
+
+ /** GL_EXT_paletted_texture */
+ struct gl_color_table Palette;
+
+ /**
+ * \name For device driver.
+ * Note: instead of attaching driver data to this pointer, it's preferable
+ * to instead use this struct as a base class for your own texture object
+ * class. Driver->NewTextureObject() can be used to implement the
+ * allocation.
+ */
+ void *DriverData; /**< Arbitrary device driver data */
+};
+
+
+/** Up to four combiner sources are possible with GL_NV_texture_env_combine4 */
+#define MAX_COMBINER_TERMS 4
+
+
+/**
+ * Texture combine environment state.
+ */
+struct gl_tex_env_combine_state
+{
+ GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */
+ /** Source terms: GL_PRIMARY_COLOR, GL_TEXTURE, etc */
+ GLenum SourceRGB[MAX_COMBINER_TERMS];
+ GLenum SourceA[MAX_COMBINER_TERMS];
+ /** Source operands: GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, etc */
+ GLenum OperandRGB[MAX_COMBINER_TERMS];
+ GLenum OperandA[MAX_COMBINER_TERMS];
+ GLuint ScaleShiftRGB; /**< 0, 1 or 2 */
+ GLuint ScaleShiftA; /**< 0, 1 or 2 */
+ GLuint _NumArgsRGB; /**< Number of inputs used for the RGB combiner */
+ GLuint _NumArgsA; /**< Number of inputs used for the A combiner */
+};
+
+
+/**
+ * Texture coord generation state.
+ */
+struct gl_texgen
+{
+ GLenum Mode; /**< GL_EYE_LINEAR, GL_SPHERE_MAP, etc */
+ GLbitfield _ModeBit; /**< TEXGEN_x bit corresponding to Mode */
+ GLfloat ObjectPlane[4];
+ GLfloat EyePlane[4];
+};
+
+
+/**
+ * Texture unit state. Contains enable flags, texture environment/function/
+ * combiners, texgen state, pointers to current texture objects and
+ * post-filter color tables.
+ */
+struct gl_texture_unit
+{
+ GLbitfield Enabled; /**< bitmask of TEXTURE_*_BIT flags */
+ GLbitfield _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */
+
+ GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
+ GLfloat EnvColor[4];
+
+ struct gl_texgen GenS;
+ struct gl_texgen GenT;
+ struct gl_texgen GenR;
+ struct gl_texgen GenQ;
+ GLbitfield TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */
+ GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
+
+ GLfloat LodBias; /**< for biasing mipmap levels */
+ GLenum BumpTarget;
+ GLfloat RotMatrix[4]; /* 2x2 matrix */
+
+ /**
+ * \name GL_EXT_texture_env_combine
+ */
+ struct gl_tex_env_combine_state Combine;
+
+ /**
+ * Derived state based on \c EnvMode and the \c BaseFormat of the
+ * currently enabled texture.
+ */
+ struct gl_tex_env_combine_state _EnvMode;
+
+ /**
+ * Currently enabled combiner state. This will point to either
+ * \c Combine or \c _EnvMode.
+ */
+ struct gl_tex_env_combine_state *_CurrentCombine;
+
+ /** Current texture object pointers */
+ struct gl_texture_object *CurrentTex[NUM_TEXTURE_TARGETS];
+
+ /** Points to highest priority, complete and enabled texture object */
+ struct gl_texture_object *_Current;
+
+ /** GL_SGI_texture_color_table */
+ /*@{*/
+ struct gl_color_table ColorTable;
+ struct gl_color_table ProxyColorTable;
+ GLboolean ColorTableEnabled;
+ /*@}*/
+};
+
+
+/**
+ * Texture attribute group (GL_TEXTURE_BIT).
+ */
+struct gl_texture_attrib
+{
+ GLuint CurrentUnit; /**< GL_ACTIVE_TEXTURE */
+ struct gl_texture_unit Unit[MAX_TEXTURE_UNITS];
+
+ struct gl_texture_object *ProxyTex[NUM_TEXTURE_TARGETS];
+
+ /** GL_ARB_seamless_cubemap */
+ GLboolean CubeMapSeamless;
+
+ /** GL_EXT_shared_texture_palette */
+ GLboolean SharedPalette;
+ struct gl_color_table Palette;
+
+ /** Texture units/samplers used by vertex or fragment texturing */
+ GLbitfield _EnabledUnits;
+
+ /** Texture coord units/sets used for fragment texturing */
+ GLbitfield _EnabledCoordUnits;
+
+ /** Texture coord units that have texgen enabled */
+ GLbitfield _TexGenEnabled;
+
+ /** Texture coord units that have non-identity matrices */
+ GLbitfield _TexMatEnabled;
+
+ /** Bitwise-OR of all Texture.Unit[i]._GenFlags */
+ GLbitfield _GenFlags;
+};
+
+
+/**
+ * Transformation attribute group (GL_TRANSFORM_BIT).
+ */
+struct gl_transform_attrib
+{
+ GLenum MatrixMode; /**< Matrix mode */
+ GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
+ GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
+ GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
+ GLboolean Normalize; /**< Normalize all normals? */
+ GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */
+ GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */
+
+ GLboolean CullVertexFlag; /**< True if GL_CULL_VERTEX_EXT is enabled */
+ GLfloat CullEyePos[4];
+ GLfloat CullObjPos[4];
+};
+
+
+/**
+ * Viewport attribute group (GL_VIEWPORT_BIT).
+ */
+struct gl_viewport_attrib
+{
+ GLint X, Y; /**< position */
+ GLsizei Width, Height; /**< size */
+ GLfloat Near, Far; /**< Depth buffer range */
+ GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
+};
+
+
+/**
+ * GL_ARB_vertex/pixel_buffer_object buffer object
+ */
+struct gl_buffer_object
+{
+ GLint RefCount;
+ GLuint Name;
+ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */
+ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */
+ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
+ /** Fields describing a mapped buffer */
+ /*@{*/
+ GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
+ GLvoid *Pointer; /**< User-space address of mapping */
+ GLintptr Offset; /**< Mapped offset */
+ GLsizeiptr Length; /**< Mapped length */
+ /*@}*/
+ GLboolean Written; /**< Ever written to? (for debugging) */
+};
+
+
+/**
+ * Client pixel packing/unpacking attributes
+ */
+struct gl_pixelstore_attrib
+{
+ GLint Alignment;
+ GLint RowLength;
+ GLint SkipPixels;
+ GLint SkipRows;
+ GLint ImageHeight;
+ GLint SkipImages;
+ GLboolean SwapBytes;
+ GLboolean LsbFirst;
+ GLboolean ClientStorage; /**< GL_APPLE_client_storage */
+ GLboolean Invert; /**< GL_MESA_pack_invert */
+ struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
+};
+
+
+/**
+ * Client vertex array attributes
+ */
+struct gl_client_array
+{
+ GLint Size; /**< components per element (1,2,3,4) */
+ GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */
+ GLenum Format; /**< default: GL_RGBA, but may be GL_BGRA */
+ GLsizei Stride; /**< user-specified stride */
+ GLsizei StrideB; /**< actual stride in bytes */
+ const GLubyte *Ptr; /**< Points to array data */
+ GLboolean Enabled; /**< Enabled flag is a boolean */
+ GLboolean Normalized; /**< GL_ARB_vertex_program */
+ GLuint _ElementSize; /**< size of each element in bytes */
+
+ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
+ GLuint _MaxElement; /**< max element index into array buffer + 1 */
+};
+
+
+/**
+ * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
+ * extension, but a nice encapsulation in any case.
+ */
+struct gl_array_object
+{
+ /** Name of the array object as received from glGenVertexArrayAPPLE. */
+ GLuint Name;
+
+ GLint RefCount;
+ _glthread_Mutex Mutex;
+ GLboolean VBOonly; /**< require all arrays to live in VBOs? */
+
+ /** Conventional vertex arrays */
+ /*@{*/
+ struct gl_client_array Vertex;
+ struct gl_client_array Weight;
+ struct gl_client_array Normal;
+ struct gl_client_array Color;
+ struct gl_client_array SecondaryColor;
+ struct gl_client_array FogCoord;
+ struct gl_client_array Index;
+ struct gl_client_array EdgeFlag;
+ struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS];
+ struct gl_client_array PointSize;
+ /*@}*/
+
+ /**
+ * Generic arrays for vertex programs/shaders.
+ * For NV vertex programs, these attributes alias and take priority
+ * over the conventional attribs above. For ARB vertex programs and
+ * GLSL vertex shaders, these attributes are separate.
+ */
+ struct gl_client_array VertexAttrib[MAX_VERTEX_GENERIC_ATTRIBS];
+
+ /** Mask of _NEW_ARRAY_* values indicating which arrays are enabled */
+ GLbitfield _Enabled;
+
+ /**
+ * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
+ * we can determine the max legal (in bounds) glDrawElements array index.
+ */
+ GLuint _MaxElement;
+};
+
+
+/**
+ * Vertex array state
+ */
+struct gl_array_attrib
+{
+ /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
+ struct gl_array_object *ArrayObj;
+
+ /** The default vertex array object */
+ struct gl_array_object *DefaultArrayObj;
+
+ /** Array objects (GL_ARB/APPLE_vertex_array_object) */
+ struct _mesa_HashTable *Objects;
+
+ GLint ActiveTexture; /**< Client Active Texture */
+ GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */
+ GLuint LockCount; /**< GL_EXT_compiled_vertex_array */
+
+ GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
+
+#if FEATURE_ARB_vertex_buffer_object
+ struct gl_buffer_object *ArrayBufferObj;
+ struct gl_buffer_object *ElementArrayBufferObj;
+#endif
+};
+
+
+/**
+ * Feedback buffer state
+ */
+struct gl_feedback
+{
+ GLenum Type;
+ GLbitfield _Mask; /**< FB_* bits */
+ GLfloat *Buffer;
+ GLuint BufferSize;
+ GLuint Count;
+};
+
+
+/**
+ * Selection buffer state
+ */
+struct gl_selection
+{
+ GLuint *Buffer; /**< selection buffer */
+ GLuint BufferSize; /**< size of the selection buffer */
+ GLuint BufferCount; /**< number of values in the selection buffer */
+ GLuint Hits; /**< number of records in the selection buffer */
+ GLuint NameStackDepth; /**< name stack depth */
+ GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */
+ GLboolean HitFlag; /**< hit flag */
+ GLfloat HitMinZ; /**< minimum hit depth */
+ GLfloat HitMaxZ; /**< maximum hit depth */
+};
+
+
+/**
+ * 1-D Evaluator control points
+ */
+struct gl_1d_map
+{
+ GLuint Order; /**< Number of control points */
+ GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * 2-D Evaluator control points
+ */
+struct gl_2d_map
+{
+ GLuint Uorder; /**< Number of control points in U dimension */
+ GLuint Vorder; /**< Number of control points in V dimension */
+ GLfloat u1, u2, du;
+ GLfloat v1, v2, dv;
+ GLfloat *Points; /**< Points to contiguous control points */
+};
+
+
+/**
+ * All evaluator control point state
+ */
+struct gl_evaluators
+{
+ /**
+ * \name 1-D maps
+ */
+ /*@{*/
+ struct gl_1d_map Map1Vertex3;
+ struct gl_1d_map Map1Vertex4;
+ struct gl_1d_map Map1Index;
+ struct gl_1d_map Map1Color4;
+ struct gl_1d_map Map1Normal;
+ struct gl_1d_map Map1Texture1;
+ struct gl_1d_map Map1Texture2;
+ struct gl_1d_map Map1Texture3;
+ struct gl_1d_map Map1Texture4;
+ struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+
+ /**
+ * \name 2-D maps
+ */
+ /*@{*/
+ struct gl_2d_map Map2Vertex3;
+ struct gl_2d_map Map2Vertex4;
+ struct gl_2d_map Map2Index;
+ struct gl_2d_map Map2Color4;
+ struct gl_2d_map Map2Normal;
+ struct gl_2d_map Map2Texture1;
+ struct gl_2d_map Map2Texture2;
+ struct gl_2d_map Map2Texture3;
+ struct gl_2d_map Map2Texture4;
+ struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */
+ /*@}*/
+};
+
+
+/**
+ * Names of the various vertex/fragment program register files, etc.
+ *
+ * NOTE: first four tokens must fit into 2 bits (see t_vb_arbprogram.c)
+ * All values should fit in a 4-bit field.
+ *
+ * NOTE: PROGRAM_ENV_PARAM, PROGRAM_STATE_VAR, PROGRAM_NAMED_PARAM,
+ * PROGRAM_CONSTANT, and PROGRAM_UNIFORM can all be considered to
+ * be "uniform" variables since they can only be set outside glBegin/End.
+ * They're also all stored in the same Parameters array.
+ */
+typedef enum
+{
+ PROGRAM_TEMPORARY, /**< machine->Temporary[] */
+ PROGRAM_INPUT, /**< machine->Inputs[] */
+ PROGRAM_OUTPUT, /**< machine->Outputs[] */
+ PROGRAM_VARYING, /**< machine->Inputs[]/Outputs[] */
+ PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */
+ PROGRAM_ENV_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_STATE_VAR, /**< gl_program->Parameters[] */
+ PROGRAM_NAMED_PARAM, /**< gl_program->Parameters[] */
+ PROGRAM_CONSTANT, /**< gl_program->Parameters[] */
+ PROGRAM_UNIFORM, /**< gl_program->Parameters[] */
+ PROGRAM_WRITE_ONLY, /**< A dummy, write-only register */
+ PROGRAM_ADDRESS, /**< machine->AddressReg */
+ PROGRAM_SAMPLER, /**< for shader samplers, compile-time only */
+ PROGRAM_UNDEFINED, /**< Invalid/TBD value */
+ PROGRAM_FILE_MAX
+} gl_register_file;
+
+
+/** Vertex and fragment instructions */
+struct prog_instruction;
+struct gl_program_parameter_list;
+struct gl_uniform_list;
+
+
+/**
+ * Base class for any kind of program object
+ */
+struct gl_program
+{
+ GLuint Id;
+ GLubyte *String; /**< Null-terminated program text */
+ GLint RefCount;
+ GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_FRAGMENT_PROGRAM_NV */
+ GLenum Format; /**< String encoding format */
+ GLboolean Resident;
+
+ struct prog_instruction *Instructions;
+
+ GLbitfield InputsRead; /**< Bitmask of which input regs are read */
+ GLbitfield OutputsWritten; /**< Bitmask of which output regs are written to */
+ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */
+ GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */
+ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */
+ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
+
+
+ /** Named parameters, constants, etc. from program text */
+ struct gl_program_parameter_list *Parameters;
+ /** Numbered local parameters */
+ GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4];
+
+ /** Vertex/fragment shader varying vars */
+ struct gl_program_parameter_list *Varying;
+ /** Vertex program user-defined attributes */
+ struct gl_program_parameter_list *Attributes;
+
+ /** Map from sampler unit to texture unit (set by glUniform1i()) */
+ GLubyte SamplerUnits[MAX_SAMPLERS];
+ /** Which texture target is being sampled (TEXTURE_1D/2D/3D/etc_INDEX) */
+ gl_texture_index SamplerTargets[MAX_SAMPLERS];
+
+ /** Logical counts */
+ /*@{*/
+ GLuint NumInstructions;
+ GLuint NumTemporaries;
+ GLuint NumParameters;
+ GLuint NumAttributes;
+ GLuint NumAddressRegs;
+ GLuint NumAluInstructions;
+ GLuint NumTexInstructions;
+ GLuint NumTexIndirections;
+ /*@}*/
+ /** Native, actual h/w counts */
+ /*@{*/
+ GLuint NumNativeInstructions;
+ GLuint NumNativeTemporaries;
+ GLuint NumNativeParameters;
+ GLuint NumNativeAttributes;
+ GLuint NumNativeAddressRegs;
+ GLuint NumNativeAluInstructions;
+ GLuint NumNativeTexInstructions;
+ GLuint NumNativeTexIndirections;
+ /*@}*/
+};
+
+
+/** Vertex program object */
+struct gl_vertex_program
+{
+ struct gl_program Base; /**< base class */
+ GLboolean IsNVProgram; /**< is this a GL_NV_vertex_program program? */
+ GLboolean IsPositionInvariant;
+ void *TnlData; /**< should probably use Base.DriverData */
+};
+
+
+/** Fragment program object */
+struct gl_fragment_program
+{
+ struct gl_program Base; /**< base class */
+ GLenum FogOption;
+ GLboolean UsesKill; /**< shader uses KIL instruction */
+};
+
+
+/**
+ * State common to vertex and fragment programs.
+ */
+struct gl_program_state
+{
+ GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_ARB/NV */
+ const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_ARB/NV */
+};
+
+
+/**
+ * Context state for vertex programs.
+ */
+struct gl_vertex_program_state
+{
+ GLboolean Enabled; /**< User-set GL_VERTEX_PROGRAM_ARB/NV flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_ARB/NV */
+ GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_ARB/NV */
+ struct gl_vertex_program *Current; /**< User-bound vertex program */
+
+ /** Currently enabled and valid vertex program (including internal
+ * programs, user-defined vertex programs and GLSL vertex shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_vertex_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /* For GL_NV_vertex_program only: */
+ GLenum TrackMatrix[MAX_PROGRAM_ENV_PARAMS / 4];
+ GLenum TrackMatrixTransform[MAX_PROGRAM_ENV_PARAMS / 4];
+
+ /** Should fixed-function T&L be implemented with a vertex prog? */
+ GLboolean _MaintainTnlProgram;
+
+ /** Program to emulate fixed-function T&L (see above) */
+ struct gl_vertex_program *_TnlProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+
+ GLboolean _Overriden;
+};
+
+
+/**
+ * Context state for fragment programs.
+ */
+struct gl_fragment_program_state
+{
+ GLboolean Enabled; /**< User-set fragment program enable flag */
+ GLboolean _Enabled; /**< Enabled and _valid_ user program? */
+ struct gl_fragment_program *Current; /**< User-bound fragment program */
+
+ /** Currently enabled and valid fragment program (including internal
+ * programs, user-defined fragment programs and GLSL fragment shaders).
+ * This is the program we must use when rendering.
+ */
+ struct gl_fragment_program *_Current;
+
+ GLfloat Parameters[MAX_PROGRAM_ENV_PARAMS][4]; /**< Env params */
+
+ /** Should fixed-function texturing be implemented with a fragment prog? */
+ GLboolean _MaintainTexEnvProgram;
+
+ /** Program to emulate fixed-function texture env/combine (see above) */
+ struct gl_fragment_program *_TexEnvProgram;
+
+ /** Cache of fixed-function programs */
+ struct gl_program_cache *Cache;
+};
+
+
+/**
+ * ATI_fragment_shader runtime state
+ */
+#define ATI_FS_INPUT_PRIMARY 0
+#define ATI_FS_INPUT_SECONDARY 1
+
+struct atifs_instruction;
+struct atifs_setupinst;
+
+/**
+ * ATI fragment shader
+ */
+struct ati_fragment_shader
+{
+ GLuint Id;
+ GLint RefCount;
+ struct atifs_instruction *Instructions[2];
+ struct atifs_setupinst *SetupInst[2];
+ GLfloat Constants[8][4];
+ GLbitfield LocalConstDef; /** Indicates which constants have been set */
+ GLubyte numArithInstr[2];
+ GLubyte regsAssigned[2];
+ GLubyte NumPasses; /** 1 or 2 */
+ GLubyte cur_pass;
+ GLubyte last_optype;
+ GLboolean interpinp1;
+ GLboolean isValid;
+ GLuint swizzlerq;
+};
+
+/**
+ * Context state for GL_ATI_fragment_shader
+ */
+struct gl_ati_fragment_shader_state
+{
+ GLboolean Enabled;
+ GLboolean _Enabled; /** enabled and valid shader? */
+ GLboolean Compiling;
+ GLfloat GlobalConstants[8][4];
+ struct ati_fragment_shader *Current;
+};
+
+
+/**
+ * Occlusion/timer query object.
+ */
+struct gl_query_object
+{
+ GLenum Target; /**< The query target, when active */
+ GLuint Id; /**< hash table ID/name */
+ GLuint64EXT Result; /**< the counter */
+ GLboolean Active; /**< inside Begin/EndQuery */
+ GLboolean Ready; /**< result is ready? */
+};
+
+
+/**
+ * Context state for query objects.
+ */
+struct gl_query_state
+{
+ struct _mesa_HashTable *QueryObjects;
+ struct gl_query_object *CurrentOcclusionObject; /* GL_ARB_occlusion_query */
+ struct gl_query_object *CurrentTimerObject; /* GL_EXT_timer_query */
+};
+
+
+/** Sync object state */
+struct gl_sync_object {
+ struct simple_node link;
+ GLenum Type; /**< GL_SYNC_FENCE */
+ GLuint Name; /**< Fence name */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending; /**< Object was deleted while there were still
+ * live references (e.g., sync not yet finished)
+ */
+ GLenum SyncCondition;
+ GLbitfield Flags; /**< Flags passed to glFenceSync */
+ GLuint StatusFlag:1; /**< Has the sync object been signaled? */
+};
+
+
+/** Set by #pragma directives */
+struct gl_sl_pragmas
+{
+ GLboolean IgnoreOptimize; /**< ignore #pragma optimize(on/off) ? */
+ GLboolean IgnoreDebug; /**< ignore #pragma debug(on/off) ? */
+ GLboolean Optimize; /**< defaults on */
+ GLboolean Debug; /**< defaults off */
+};
+
+
+/**
+ * A GLSL vertex or fragment shader object.
+ */
+struct gl_shader
+{
+ GLenum Type; /**< GL_FRAGMENT_SHADER || GL_VERTEX_SHADER (first field!) */
+ GLuint Name; /**< AKA the handle */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+ GLboolean CompileStatus;
+ GLboolean Main; /**< shader defines main() */
+ GLboolean UnresolvedRefs;
+ const GLchar *Source; /**< Source code string */
+ GLuint SourceChecksum; /**< for debug/logging purposes */
+ struct gl_program *Program; /**< Post-compile assembly code */
+ GLchar *InfoLog;
+ struct gl_sl_pragmas Pragmas;
+};
+
+
+/**
+ * A GLSL program object.
+ * Basically a linked collection of vertex and fragment shaders.
+ */
+struct gl_shader_program
+{
+ GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */
+ GLuint Name; /**< aka handle or ID */
+ GLint RefCount; /**< Reference count */
+ GLboolean DeletePending;
+
+ GLuint NumShaders; /**< number of attached shaders */
+ struct gl_shader **Shaders; /**< List of attached the shaders */
+
+ /** User-defined attribute bindings (glBindAttribLocation) */
+ struct gl_program_parameter_list *Attributes;
+
+ /* post-link info: */
+ struct gl_vertex_program *VertexProgram; /**< Linked vertex program */
+ struct gl_fragment_program *FragmentProgram; /**< Linked fragment prog */
+ struct gl_uniform_list *Uniforms;
+ struct gl_program_parameter_list *Varying;
+ GLboolean LinkStatus; /**< GL_LINK_STATUS */
+ GLboolean Validated;
+ GLboolean _Used; /**< Ever used for drawing? */
+ GLchar *InfoLog;
+};
+
+
+#define GLSL_DUMP 0x1 /**< Dump shaders to stdout */
+#define GLSL_LOG 0x2 /**< Write shaders to files */
+#define GLSL_OPT 0x4 /**< Force optimizations (override pragmas) */
+#define GLSL_NO_OPT 0x8 /**< Force no optimizations (override pragmas) */
+#define GLSL_UNIFORMS 0x10 /**< Print glUniform calls */
+
+
+/**
+ * Context state for GLSL vertex/fragment shaders.
+ */
+struct gl_shader_state
+{
+ struct gl_shader_program *CurrentProgram; /**< The user-bound program */
+ /** Driver-selectable options: */
+ GLboolean EmitHighLevelInstructions; /**< IF/ELSE/ENDIF vs. BRA, etc. */
+ GLboolean EmitContReturn; /**< Emit CONT/RET opcodes? */
+ GLboolean EmitCondCodes; /**< Use condition codes? */
+ GLboolean EmitComments; /**< Annotated instructions */
+ GLboolean EmitNVTempInitialization; /**< 0-fill NV temp registers */
+ void *MemPool;
+ GLbitfield Flags; /**< Mask of GLSL_x flags */
+ struct gl_sl_pragmas DefaultPragmas; /**< Default #pragma settings */
+};
+
+
+/**
+ * State which can be shared by multiple contexts:
+ */
+struct gl_shared_state
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLint RefCount; /**< Reference count */
+ struct _mesa_HashTable *DisplayList; /**< Display lists hash table */
+ struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */
+
+ /** Default texture objects (shared by all texture units) */
+ struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
+
+ /**
+ * \name Thread safety and statechange notification for texture
+ * objects.
+ *
+ * \todo Improve the granularity of locking.
+ */
+ /*@{*/
+ _glthread_Mutex TexMutex; /**< texobj thread safety */
+ GLuint TextureStateStamp; /**< state notification for shared tex */
+ /*@}*/
+
+ /** Default buffer object for vertex arrays that aren't in VBOs */
+ struct gl_buffer_object *NullBufferObj;
+
+ /**
+ * \name Vertex/fragment programs
+ */
+ /*@{*/
+ struct _mesa_HashTable *Programs; /**< All vertex/fragment programs */
+#if FEATURE_ARB_vertex_program
+ struct gl_vertex_program *DefaultVertexProgram;
+#endif
+#if FEATURE_ARB_fragment_program
+ struct gl_fragment_program *DefaultFragmentProgram;
+#endif
+ /*@}*/
+
+#if FEATURE_ATI_fragment_shader
+ struct _mesa_HashTable *ATIShaders;
+ struct ati_fragment_shader *DefaultFragmentShader;
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ struct _mesa_HashTable *BufferObjects;
+#endif
+
+#if FEATURE_ARB_shader_objects
+ /** Table of both gl_shader and gl_shader_program objects */
+ struct _mesa_HashTable *ShaderObjects;
+#endif
+
+#if FEATURE_EXT_framebuffer_object
+ struct _mesa_HashTable *RenderBuffers;
+ struct _mesa_HashTable *FrameBuffers;
+#endif
+
+#if FEATURE_ARB_sync
+ struct simple_node SyncObjects;
+#endif
+
+ void *DriverData; /**< Device driver shared state */
+};
+
+
+
+
+/**
+ * A renderbuffer stores colors or depth values or stencil values.
+ * A framebuffer object will have a collection of these.
+ * Data are read/written to the buffer with a handful of Get/Put functions.
+ *
+ * Instances of this object are allocated with the Driver's NewRenderbuffer
+ * hook. Drivers will likely wrap this class inside a driver-specific
+ * class to simulate inheritance.
+ */
+struct gl_renderbuffer
+{
+#define RB_MAGIC 0xaabbccdd
+ int Magic; /** XXX TEMPORARY DEBUG INFO */
+ _glthread_Mutex Mutex; /**< for thread safety */
+ GLuint ClassID; /**< Useful for drivers */
+ GLuint Name;
+ GLint RefCount;
+ GLuint Width, Height;
+ GLenum InternalFormat; /**< The user-specified format */
+ GLenum _ActualFormat; /**< The driver-chosen format */
+ GLenum _BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or
+ GL_STENCIL_INDEX. */
+ GLenum ColorEncoding; /**< GL_LINEAR or GL_SRGB */
+ GLenum ComponentType; /**< GL_FLOAT, GL_INT, GL_UNSIGNED_INT,
+ GL_UNSIGNED_NORMALIZED or GL_INDEX */
+ GLubyte RedBits; /**< Bits of red per pixel */
+ GLubyte GreenBits;
+ GLubyte BlueBits;
+ GLubyte AlphaBits;
+ GLubyte IndexBits;
+ GLubyte DepthBits;
+ GLubyte StencilBits;
+ GLubyte NumSamples;
+
+ GLenum DataType; /**< Type of values passed to the Get/Put functions */
+ GLvoid *Data; /**< This may not be used by some kinds of RBs */
+
+ /* Used to wrap one renderbuffer around another: */
+ struct gl_renderbuffer *Wrapped;
+
+ /* Delete this renderbuffer */
+ void (*Delete)(struct gl_renderbuffer *rb);
+
+ /* Allocate new storage for this renderbuffer */
+ GLboolean (*AllocStorage)(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height);
+
+ /* Lock/Unlock are called before/after calling the Get/Put functions.
+ * Not sure this is the right place for these yet.
+ void (*Lock)(GLcontext *ctx, struct gl_renderbuffer *rb);
+ void (*Unlock)(GLcontext *ctx, struct gl_renderbuffer *rb);
+ */
+
+ /* Return a pointer to the element/pixel at (x,y).
+ * Should return NULL if the buffer memory can't be directly addressed.
+ */
+ void *(*GetPointer)(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y);
+
+ /* Get/Read a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values);
+
+ /* Get/Read values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*GetValues)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values);
+
+ /* Put/Write a row of values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+ /* Put/Write a row of RGB values. This is a special-case routine that's
+ * only used for RGBA renderbuffers when the source data is GL_RGB. That's
+ * a common case for glDrawPixels and some triangle routines.
+ * The values will be of format GL_RGB and type DataType.
+ */
+ void (*PutRowRGB)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask);
+
+
+ /* Put/Write a row of identical values.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask);
+
+ /* Put/Write values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutValues)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask);
+ /* Put/Write identical values at arbitrary locations.
+ * The values will be of format _BaseFormat and type DataType.
+ */
+ void (*PutMonoValues)(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask);
+};
+
+
+/**
+ * A renderbuffer attachment points to either a texture object (and specifies
+ * a mipmap level, cube face or 3D texture slice) or points to a renderbuffer.
+ */
+struct gl_renderbuffer_attachment
+{
+ GLenum Type; /**< \c GL_NONE or \c GL_TEXTURE or \c GL_RENDERBUFFER_EXT */
+ GLboolean Complete;
+
+ /**
+ * If \c Type is \c GL_RENDERBUFFER_EXT, this stores a pointer to the
+ * application supplied renderbuffer object.
+ */
+ struct gl_renderbuffer *Renderbuffer;
+
+ /**
+ * If \c Type is \c GL_TEXTURE, this stores a pointer to the application
+ * supplied texture object.
+ */
+ struct gl_texture_object *Texture;
+ GLuint TextureLevel; /**< Attached mipmap level. */
+ GLuint CubeMapFace; /**< 0 .. 5, for cube map textures. */
+ GLuint Zoffset; /**< Slice for 3D textures, or layer for both 1D
+ * and 2D array textures */
+};
+
+
+/**
+ * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc).
+ * In C++ terms, think of this as a base class from which device drivers
+ * will make derived classes.
+ */
+struct gl_framebuffer
+{
+ _glthread_Mutex Mutex; /**< for thread safety */
+ /**
+ * If zero, this is a window system framebuffer. If non-zero, this
+ * is a FBO framebuffer; note that for some devices (i.e. those with
+ * a natural pixel coordinate system for FBOs that differs from the
+ * OpenGL/Mesa coordinate system), this means that the viewport,
+ * polygon face orientation, and polygon stipple will have to be inverted.
+ */
+ GLuint Name;
+
+ GLint RefCount;
+ GLboolean DeletePending;
+
+ /**
+ * The framebuffer's visual. Immutable if this is a window system buffer.
+ * Computed from attachments if user-made FBO.
+ */
+ GLvisual Visual;
+
+ GLboolean Initialized;
+
+ GLuint Width, Height; /**< size of frame buffer in pixels */
+
+ /** \name Drawing bounds (Intersection of buffer size and scissor box) */
+ /*@{*/
+ GLint _Xmin, _Xmax; /**< inclusive */
+ GLint _Ymin, _Ymax; /**< exclusive */
+ /*@}*/
+
+ /** \name Derived Z buffer stuff */
+ /*@{*/
+ GLuint _DepthMax; /**< Max depth buffer value */
+ GLfloat _DepthMaxF; /**< Float max depth buffer value */
+ GLfloat _MRD; /**< minimum resolvable difference in Z values */
+ /*@}*/
+
+ /** One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */
+ GLenum _Status;
+
+ /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */
+ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT];
+
+ /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER
+ * attribute group and GL_PIXEL attribute group, respectively.
+ */
+ GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS];
+ GLenum ColorReadBuffer;
+
+ /** Computed from ColorDraw/ReadBuffer above */
+ GLuint _NumColorDrawBuffers;
+ GLint _ColorDrawBufferIndexes[MAX_DRAW_BUFFERS]; /**< BUFFER_x or -1 */
+ GLint _ColorReadBufferIndex; /* -1 = None */
+ struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS];
+ struct gl_renderbuffer *_ColorReadBuffer;
+
+ /** The Actual depth/stencil buffers to use. May be wrappers around the
+ * depth/stencil buffers attached above. */
+ struct gl_renderbuffer *_DepthBuffer;
+ struct gl_renderbuffer *_StencilBuffer;
+
+ /** Delete this framebuffer */
+ void (*Delete)(struct gl_framebuffer *fb);
+};
+
+
+/**
+ * Limits for vertex and fragment programs.
+ */
+struct gl_program_constants
+{
+ /* logical limits */
+ GLuint MaxInstructions;
+ GLuint MaxAluInstructions; /* fragment programs only, for now */
+ GLuint MaxTexInstructions; /* fragment programs only, for now */
+ GLuint MaxTexIndirections; /* fragment programs only, for now */
+ GLuint MaxAttribs;
+ GLuint MaxTemps;
+ GLuint MaxAddressRegs; /* vertex program only, for now */
+ GLuint MaxParameters;
+ GLuint MaxLocalParams;
+ GLuint MaxEnvParams;
+ /* native/hardware limits */
+ GLuint MaxNativeInstructions;
+ GLuint MaxNativeAluInstructions; /* fragment programs only, for now */
+ GLuint MaxNativeTexInstructions; /* fragment programs only, for now */
+ GLuint MaxNativeTexIndirections; /* fragment programs only, for now */
+ GLuint MaxNativeAttribs;
+ GLuint MaxNativeTemps;
+ GLuint MaxNativeAddressRegs; /* vertex program only, for now */
+ GLuint MaxNativeParameters;
+ /* For shaders */
+ GLuint MaxUniformComponents;
+};
+
+
+/**
+ * Constants which may be overridden by device driver during context creation
+ * but are never changed after that.
+ */
+struct gl_constants
+{
+ GLint MaxTextureLevels; /**< Max mipmap levels. */
+ GLint Max3DTextureLevels; /**< Max mipmap levels for 3D textures */
+ GLint MaxCubeTextureLevels; /**< Max mipmap levels for cube textures */
+ GLint MaxArrayTextureLayers; /**< Max layers in array textures */
+ GLint MaxTextureRectSize; /**< Max rectangle texture size, in pixes */
+ GLuint MaxTextureCoordUnits;
+ GLuint MaxTextureImageUnits;
+ GLuint MaxVertexTextureImageUnits;
+ GLuint MaxTextureUnits; /**< = MIN(CoordUnits, ImageUnits) */
+ GLfloat MaxTextureMaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */
+ GLfloat MaxTextureLodBias; /**< GL_EXT_texture_lod_bias */
+
+ GLuint MaxArrayLockSize;
+
+ GLint SubPixelBits;
+
+ GLfloat MinPointSize, MaxPointSize; /**< aliased */
+ GLfloat MinPointSizeAA, MaxPointSizeAA; /**< antialiased */
+ GLfloat PointSizeGranularity;
+ GLfloat MinLineWidth, MaxLineWidth; /**< aliased */
+ GLfloat MinLineWidthAA, MaxLineWidthAA; /**< antialiased */
+ GLfloat LineWidthGranularity;
+
+ GLuint MaxColorTableSize;
+ GLuint MaxConvolutionWidth;
+ GLuint MaxConvolutionHeight;
+
+ GLuint MaxClipPlanes;
+ GLuint MaxLights;
+ GLfloat MaxShininess; /**< GL_NV_light_max_exponent */
+ GLfloat MaxSpotExponent; /**< GL_NV_light_max_exponent */
+
+ GLuint MaxViewportWidth, MaxViewportHeight;
+
+ struct gl_program_constants VertexProgram; /**< GL_ARB_vertex_program */
+ struct gl_program_constants FragmentProgram; /**< GL_ARB_fragment_program */
+ GLuint MaxProgramMatrices;
+ GLuint MaxProgramMatrixStackDepth;
+
+ /** vertex array / buffer object bounds checking */
+ GLboolean CheckArrayBounds;
+
+ GLuint MaxDrawBuffers; /**< GL_ARB_draw_buffers */
+
+ GLenum ColorReadFormat; /**< GL_OES_read_format */
+ GLenum ColorReadType; /**< GL_OES_read_format */
+
+ GLuint MaxColorAttachments; /**< GL_EXT_framebuffer_object */
+ GLuint MaxRenderbufferSize; /**< GL_EXT_framebuffer_object */
+ GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
+
+ GLuint MaxVarying; /**< Number of float[4] varying parameters */
+
+ GLbitfield SupportedBumpUnits; /**> units supporting GL_ATI_envmap_bumpmap as targets */
+
+ /**
+ * Maximum amount of time, measured in nanseconds, that the server can wait.
+ */
+ GLuint64 MaxServerWaitTimeout;
+
+
+ /**< GL_EXT_provoking_vertex */
+ GLboolean QuadsFollowProvokingVertexConvention;
+};
+
+
+/**
+ * Enable flag for each OpenGL extension. Different device drivers will
+ * enable different extensions at runtime.
+ */
+struct gl_extensions
+{
+ GLboolean dummy; /* don't remove this! */
+ GLboolean ARB_copy_buffer;
+ GLboolean ARB_depth_texture;
+ GLboolean ARB_draw_buffers;
+ GLboolean ARB_fragment_program;
+ GLboolean ARB_fragment_program_shadow;
+ GLboolean ARB_fragment_shader;
+ GLboolean ARB_framebuffer_object;
+ GLboolean ARB_half_float_pixel;
+ GLboolean ARB_imaging;
+ GLboolean ARB_map_buffer_range;
+ GLboolean ARB_multisample;
+ GLboolean ARB_multitexture;
+ GLboolean ARB_occlusion_query;
+ GLboolean ARB_point_sprite;
+ GLboolean ARB_seamless_cube_map;
+ GLboolean ARB_shader_objects;
+ GLboolean ARB_shading_language_100;
+ GLboolean ARB_shading_language_120;
+ GLboolean ARB_shadow;
+ GLboolean ARB_shadow_ambient; /* or GL_ARB_shadow_ambient */
+ GLboolean ARB_sync;
+ GLboolean ARB_texture_border_clamp;
+ GLboolean ARB_texture_compression;
+ GLboolean ARB_texture_cube_map;
+ GLboolean ARB_texture_env_combine;
+ GLboolean ARB_texture_env_crossbar;
+ GLboolean ARB_texture_env_dot3;
+ GLboolean ARB_texture_float;
+ GLboolean ARB_texture_mirrored_repeat;
+ GLboolean ARB_texture_non_power_of_two;
+ GLboolean ARB_transpose_matrix;
+ GLboolean ARB_vertex_array_object;
+ GLboolean ARB_vertex_buffer_object;
+ GLboolean ARB_vertex_program;
+ GLboolean ARB_vertex_shader;
+ GLboolean ARB_window_pos;
+ GLboolean EXT_abgr;
+ GLboolean EXT_bgra;
+ GLboolean EXT_blend_color;
+ GLboolean EXT_blend_equation_separate;
+ GLboolean EXT_blend_func_separate;
+ GLboolean EXT_blend_logic_op;
+ GLboolean EXT_blend_minmax;
+ GLboolean EXT_blend_subtract;
+ GLboolean EXT_clip_volume_hint;
+ GLboolean EXT_cull_vertex;
+ GLboolean EXT_convolution;
+ GLboolean EXT_compiled_vertex_array;
+ GLboolean EXT_copy_texture;
+ GLboolean EXT_depth_bounds_test;
+ GLboolean EXT_draw_range_elements;
+ GLboolean EXT_framebuffer_object;
+ GLboolean EXT_fog_coord;
+ GLboolean EXT_framebuffer_blit;
+ GLboolean EXT_gpu_program_parameters;
+ GLboolean EXT_histogram;
+ GLboolean EXT_multi_draw_arrays;
+ GLboolean EXT_paletted_texture;
+ GLboolean EXT_packed_depth_stencil;
+ GLboolean EXT_packed_pixels;
+ GLboolean EXT_pixel_buffer_object;
+ GLboolean EXT_point_parameters;
+ GLboolean EXT_polygon_offset;
+ GLboolean EXT_provoking_vertex;
+ GLboolean EXT_rescale_normal;
+ GLboolean EXT_shadow_funcs;
+ GLboolean EXT_secondary_color;
+ GLboolean EXT_separate_specular_color;
+ GLboolean EXT_shared_texture_palette;
+ GLboolean EXT_stencil_wrap;
+ GLboolean EXT_stencil_two_side;
+ GLboolean EXT_subtexture;
+ GLboolean EXT_texture;
+ GLboolean EXT_texture_object;
+ GLboolean EXT_texture3D;
+ GLboolean EXT_texture_compression_s3tc;
+ GLboolean EXT_texture_env_add;
+ GLboolean EXT_texture_env_combine;
+ GLboolean EXT_texture_env_dot3;
+ GLboolean EXT_texture_filter_anisotropic;
+ GLboolean EXT_texture_lod_bias;
+ GLboolean EXT_texture_mirror_clamp;
+ GLboolean EXT_texture_sRGB;
+ GLboolean EXT_texture_swizzle;
+ GLboolean EXT_timer_query;
+ GLboolean EXT_vertex_array;
+ GLboolean EXT_vertex_array_bgra;
+ GLboolean EXT_vertex_array_set;
+ /* vendor extensions */
+ GLboolean APPLE_client_storage;
+ GLboolean APPLE_packed_pixels;
+ GLboolean APPLE_vertex_array_object;
+ GLboolean ATI_envmap_bumpmap;
+ GLboolean ATI_texture_mirror_once;
+ GLboolean ATI_texture_env_combine3;
+ GLboolean ATI_fragment_shader;
+ GLboolean ATI_separate_stencil;
+ GLboolean IBM_rasterpos_clip;
+ GLboolean IBM_multimode_draw_arrays;
+ GLboolean MESA_pack_invert;
+ GLboolean MESA_packed_depth_stencil;
+ GLboolean MESA_resize_buffers;
+ GLboolean MESA_ycbcr_texture;
+ GLboolean MESA_texture_array;
+ GLboolean MESA_texture_signed_rgba;
+ GLboolean NV_blend_square;
+ GLboolean NV_fragment_program;
+ GLboolean NV_light_max_exponent;
+ GLboolean NV_point_sprite;
+ GLboolean NV_texgen_reflection;
+ GLboolean NV_texture_env_combine4;
+ GLboolean NV_texture_rectangle;
+ GLboolean NV_vertex_program;
+ GLboolean NV_vertex_program1_1;
+ GLboolean OES_read_format;
+ GLboolean SGI_color_matrix;
+ GLboolean SGI_color_table;
+ GLboolean SGI_texture_color_table;
+ GLboolean SGIS_generate_mipmap;
+ GLboolean SGIS_texture_edge_clamp;
+ GLboolean SGIS_texture_lod;
+ GLboolean TDFX_texture_compression_FXT1;
+ GLboolean S3_s3tc;
+ /** The extension string */
+ const GLubyte *String;
+};
+
+
+/**
+ * A stack of matrices (projection, modelview, color, texture, etc).
+ */
+struct gl_matrix_stack
+{
+ GLmatrix *Top; /**< points into Stack */
+ GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */
+ GLuint Depth; /**< 0 <= Depth < MaxDepth */
+ GLuint MaxDepth; /**< size of Stack[] array */
+ GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */
+};
+
+
+/**
+ * \name Bits for image transfer operations
+ * \sa __GLcontextRec::ImageTransferState.
+ */
+/*@{*/
+#define IMAGE_SCALE_BIAS_BIT 0x1
+#define IMAGE_SHIFT_OFFSET_BIT 0x2
+#define IMAGE_MAP_COLOR_BIT 0x4
+#define IMAGE_COLOR_TABLE_BIT 0x8
+#define IMAGE_CONVOLUTION_BIT 0x10
+#define IMAGE_POST_CONVOLUTION_SCALE_BIAS 0x20
+#define IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT 0x40
+#define IMAGE_COLOR_MATRIX_BIT 0x80
+#define IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT 0x100
+#define IMAGE_HISTOGRAM_BIT 0x200
+#define IMAGE_MIN_MAX_BIT 0x400
+#define IMAGE_CLAMP_BIT 0x800
+
+
+/** Pixel Transfer ops up to convolution */
+#define IMAGE_PRE_CONVOLUTION_BITS (IMAGE_SCALE_BIAS_BIT | \
+ IMAGE_SHIFT_OFFSET_BIT | \
+ IMAGE_MAP_COLOR_BIT | \
+ IMAGE_COLOR_TABLE_BIT)
+
+/** Pixel transfer ops after convolution */
+#define IMAGE_POST_CONVOLUTION_BITS (IMAGE_POST_CONVOLUTION_SCALE_BIAS | \
+ IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT | \
+ IMAGE_COLOR_MATRIX_BIT | \
+ IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT |\
+ IMAGE_HISTOGRAM_BIT | \
+ IMAGE_MIN_MAX_BIT)
+/*@}*/
+
+
+/**
+ * \name Bits to indicate what state has changed.
+ *
+ * 4 unused flags.
+ */
+/*@{*/
+#define _NEW_MODELVIEW 0x1 /**< __GLcontextRec::ModelView */
+#define _NEW_PROJECTION 0x2 /**< __GLcontextRec::Projection */
+#define _NEW_TEXTURE_MATRIX 0x4 /**< __GLcontextRec::TextureMatrix */
+#define _NEW_COLOR_MATRIX 0x8 /**< __GLcontextRec::ColorMatrix */
+#define _NEW_ACCUM 0x10 /**< __GLcontextRec::Accum */
+#define _NEW_COLOR 0x20 /**< __GLcontextRec::Color */
+#define _NEW_DEPTH 0x40 /**< __GLcontextRec::Depth */
+#define _NEW_EVAL 0x80 /**< __GLcontextRec::Eval, __GLcontextRec::EvalMap */
+#define _NEW_FOG 0x100 /**< __GLcontextRec::Fog */
+#define _NEW_HINT 0x200 /**< __GLcontextRec::Hint */
+#define _NEW_LIGHT 0x400 /**< __GLcontextRec::Light */
+#define _NEW_LINE 0x800 /**< __GLcontextRec::Line */
+#define _NEW_PIXEL 0x1000 /**< __GLcontextRec::Pixel */
+#define _NEW_POINT 0x2000 /**< __GLcontextRec::Point */
+#define _NEW_POLYGON 0x4000 /**< __GLcontextRec::Polygon */
+#define _NEW_POLYGONSTIPPLE 0x8000 /**< __GLcontextRec::PolygonStipple */
+#define _NEW_SCISSOR 0x10000 /**< __GLcontextRec::Scissor */
+#define _NEW_STENCIL 0x20000 /**< __GLcontextRec::Stencil */
+#define _NEW_TEXTURE 0x40000 /**< __GLcontextRec::Texture */
+#define _NEW_TRANSFORM 0x80000 /**< __GLcontextRec::Transform */
+#define _NEW_VIEWPORT 0x100000 /**< __GLcontextRec::Viewport */
+#define _NEW_PACKUNPACK 0x200000 /**< __GLcontextRec::Pack, __GLcontextRec::Unpack */
+#define _NEW_ARRAY 0x400000 /**< __GLcontextRec::Array */
+#define _NEW_RENDERMODE 0x800000 /**< __GLcontextRec::RenderMode, __GLcontextRec::Feedback, __GLcontextRec::Select */
+#define _NEW_BUFFERS 0x1000000 /**< __GLcontextRec::Visual, __GLcontextRec::DrawBuffer, */
+#define _NEW_MULTISAMPLE 0x2000000 /**< __GLcontextRec::Multisample */
+#define _NEW_TRACK_MATRIX 0x4000000 /**< __GLcontextRec::VertexProgram */
+#define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */
+#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */
+#define _NEW_PROGRAM_CONSTANTS 0x20000000
+#define _NEW_BUFFER_OBJECT 0x40000000
+#define _NEW_ALL ~0
+/*@}*/
+
+
+/**
+ * \name Bits to track array state changes
+ *
+ * Also used to summarize array enabled.
+ */
+/*@{*/
+#define _NEW_ARRAY_VERTEX VERT_BIT_POS
+#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT
+#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL
+#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0
+#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1
+#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG
+#define _NEW_ARRAY_INDEX VERT_BIT_COLOR_INDEX
+#define _NEW_ARRAY_EDGEFLAG VERT_BIT_EDGEFLAG
+#define _NEW_ARRAY_POINT_SIZE VERT_BIT_COLOR_INDEX /* aliased */
+#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0
+#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1
+#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2
+#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3
+#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4
+#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5
+#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6
+#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7
+#define _NEW_ARRAY_ATTRIB_0 VERT_BIT_GENERIC0 /* start at bit 16 */
+#define _NEW_ARRAY_ALL 0xffffffff
+
+
+#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i))
+#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i))
+/*@}*/
+
+
+
+/**
+ * \name A bunch of flags that we think might be useful to drivers.
+ *
+ * Set in the __GLcontextRec::_TriangleCaps bitfield.
+ */
+/*@{*/
+#define DD_FLATSHADE 0x1
+#define DD_SEPARATE_SPECULAR 0x2
+#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */
+#define DD_TRI_LIGHT_TWOSIDE 0x8
+#define DD_TRI_UNFILLED 0x10
+#define DD_TRI_SMOOTH 0x20
+#define DD_TRI_STIPPLE 0x40
+#define DD_TRI_OFFSET 0x80
+#define DD_LINE_SMOOTH 0x100
+#define DD_LINE_STIPPLE 0x200
+#define DD_LINE_WIDTH 0x400
+#define DD_POINT_SMOOTH 0x800
+#define DD_POINT_SIZE 0x1000
+#define DD_POINT_ATTEN 0x2000
+#define DD_TRI_TWOSTENCIL 0x4000
+/*@}*/
+
+
+/**
+ * \name Define the state changes under which each of these bits might change
+ */
+/*@{*/
+#define _DD_NEW_FLATSHADE _NEW_LIGHT
+#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM)
+#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON
+#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT
+#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON
+#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON
+#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON
+#define _DD_NEW_TRI_OFFSET _NEW_POLYGON
+#define _DD_NEW_LINE_SMOOTH _NEW_LINE
+#define _DD_NEW_LINE_STIPPLE _NEW_LINE
+#define _DD_NEW_LINE_WIDTH _NEW_LINE
+#define _DD_NEW_POINT_SMOOTH _NEW_POINT
+#define _DD_NEW_POINT_SIZE _NEW_POINT
+#define _DD_NEW_POINT_ATTEN _NEW_POINT
+/*@}*/
+
+
+/**
+ * Composite state flags
+ */
+/*@{*/
+#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_POINT | \
+ _NEW_PROGRAM | \
+ _NEW_MODELVIEW)
+
+#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \
+ _NEW_TEXTURE)
+
+#define _MESA_NEW_TRANSFER_STATE (_NEW_PIXEL | \
+ _NEW_COLOR_MATRIX)
+/*@}*/
+
+
+
+
+/* This has to be included here. */
+#include "dd.h"
+
+
+#define NUM_VERTEX_FORMAT_ENTRIES (sizeof(GLvertexformat) / sizeof(void *))
+
+/**
+ * Core Mesa's support for tnl modules:
+ */
+struct gl_tnl_module
+{
+ /**
+ * Vertex format to be lazily swapped into current dispatch.
+ */
+ const GLvertexformat *Current;
+
+ /**
+ * \name Record of functions swapped out.
+ * On restore, only need to swap these functions back in.
+ */
+ /*@{*/
+ struct {
+ _glapi_proc * location;
+ _glapi_proc function;
+ } Swapped[NUM_VERTEX_FORMAT_ENTRIES];
+ GLuint SwapCount;
+ /*@}*/
+};
+
+
+/**
+ * Display list flags.
+ * Strictly this is a tnl-private concept, but it doesn't seem
+ * worthwhile adding a tnl private structure just to hold this one bit
+ * of information:
+ */
+#define DLIST_DANGLING_REFS 0x1
+
+
+/** Opaque declaration of display list payload data type */
+union gl_dlist_node;
+
+
+/**
+ * Provide a location where information about a display list can be
+ * collected. Could be extended with driverPrivate structures,
+ * etc. in the future.
+ */
+struct gl_display_list
+{
+ GLuint Name;
+ GLbitfield Flags; /**< DLIST_x flags */
+ /** The dlist commands are in a linked list of nodes */
+ union gl_dlist_node *Head;
+};
+
+
+/**
+ * State used during display list compilation and execution.
+ */
+struct gl_dlist_state
+{
+ GLuint CallDepth; /**< Current recursion calling depth */
+
+ struct gl_display_list *CurrentList; /**< List currently being compiled */
+ union gl_dlist_node *CurrentBlock; /**< Pointer to current block of nodes */
+ GLuint CurrentPos; /**< Index into current block of nodes */
+
+ GLvertexformat ListVtxfmt;
+
+ GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
+ GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4];
+
+ GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX];
+ GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4];
+
+ GLubyte ActiveIndex;
+ GLfloat CurrentIndex;
+
+ GLubyte ActiveEdgeFlag;
+ GLboolean CurrentEdgeFlag;
+
+ struct {
+ /* State known to have been set by the currently-compiling display
+ * list. Used to eliminate some redundant state changes.
+ */
+ GLenum ShadeModel;
+ } Current;
+};
+
+
+/**
+ * Mesa rendering context.
+ *
+ * This is the central context data structure for Mesa. Almost all
+ * OpenGL state is contained in this structure.
+ * Think of this as a base class from which device drivers will derive
+ * sub classes.
+ *
+ * The GLcontext typedef names this structure.
+ */
+struct __GLcontextRec
+{
+ /** State possibly shared with other contexts in the address space */
+ struct gl_shared_state *Shared;
+
+ /** \name API function pointer tables */
+ /*@{*/
+ struct _glapi_table *Save; /**< Display list save functions */
+ struct _glapi_table *Exec; /**< Execute functions */
+ struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
+ /*@}*/
+
+ GLvisual Visual;
+ GLframebuffer *DrawBuffer; /**< buffer for writing */
+ GLframebuffer *ReadBuffer; /**< buffer for reading */
+ GLframebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */
+ GLframebuffer *WinSysReadBuffer; /**< set with MakeCurrent */
+
+ /**
+ * Device driver function pointer table
+ */
+ struct dd_function_table Driver;
+
+ void *DriverCtx; /**< Points to device driver context/state */
+
+ /** Core/Driver constants */
+ struct gl_constants Const;
+
+ /** \name The various 4x4 matrix stacks */
+ /*@{*/
+ struct gl_matrix_stack ModelviewMatrixStack;
+ struct gl_matrix_stack ProjectionMatrixStack;
+ struct gl_matrix_stack ColorMatrixStack;
+ struct gl_matrix_stack TextureMatrixStack[MAX_TEXTURE_UNITS];
+ struct gl_matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES];
+ struct gl_matrix_stack *CurrentStack; /**< Points to one of the above stacks */
+ /*@}*/
+
+ /** Combined modelview and projection matrix */
+ GLmatrix _ModelProjectMatrix;
+
+ /** \name Display lists */
+ struct gl_dlist_state ListState;
+
+ GLboolean ExecuteFlag; /**< Execute GL commands? */
+ GLboolean CompileFlag; /**< Compile GL commands into display list? */
+
+ /** Extension information */
+ struct gl_extensions Extensions;
+
+ /** \name State attribute stack (for glPush/PopAttrib) */
+ /*@{*/
+ GLuint AttribStackDepth;
+ struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Renderer attribute groups
+ *
+ * We define a struct for each attribute group to make pushing and popping
+ * attributes easy. Also it's a good organization.
+ */
+ /*@{*/
+ struct gl_accum_attrib Accum; /**< Accum buffer attributes */
+ struct gl_colorbuffer_attrib Color; /**< Color buffer attributes */
+ struct gl_current_attrib Current; /**< Current attributes */
+ struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */
+ struct gl_eval_attrib Eval; /**< Eval attributes */
+ struct gl_fog_attrib Fog; /**< Fog attributes */
+ struct gl_hint_attrib Hint; /**< Hint attributes */
+ struct gl_light_attrib Light; /**< Light attributes */
+ struct gl_line_attrib Line; /**< Line attributes */
+ struct gl_list_attrib List; /**< List attributes */
+ struct gl_multisample_attrib Multisample;
+ struct gl_pixel_attrib Pixel; /**< Pixel attributes */
+ struct gl_point_attrib Point; /**< Point attributes */
+ struct gl_polygon_attrib Polygon; /**< Polygon attributes */
+ GLuint PolygonStipple[32]; /**< Polygon stipple */
+ struct gl_scissor_attrib Scissor; /**< Scissor attributes */
+ struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */
+ struct gl_texture_attrib Texture; /**< Texture attributes */
+ struct gl_transform_attrib Transform; /**< Transformation attributes */
+ struct gl_viewport_attrib Viewport; /**< Viewport attributes */
+ /*@}*/
+
+ /** \name Client attribute stack */
+ /*@{*/
+ GLuint ClientAttribStackDepth;
+ struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH];
+ /*@}*/
+
+ /** \name Client attribute groups */
+ /*@{*/
+ struct gl_array_attrib Array; /**< Vertex arrays */
+ struct gl_pixelstore_attrib Pack; /**< Pixel packing */
+ struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
+ struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
+ /*@}*/
+
+ /** \name Other assorted state (not pushed/popped on attribute stack) */
+ /*@{*/
+ struct gl_pixelmaps PixelMaps;
+ struct gl_histogram_attrib Histogram;
+ struct gl_minmax_attrib MinMax;
+ struct gl_convolution_attrib Convolution1D;
+ struct gl_convolution_attrib Convolution2D;
+ struct gl_convolution_attrib Separable2D;
+
+ struct gl_evaluators EvalMap; /**< All evaluators */
+ struct gl_feedback Feedback; /**< Feedback */
+ struct gl_selection Select; /**< Selection */
+
+ struct gl_color_table ColorTable[COLORTABLE_MAX];
+ struct gl_color_table ProxyColorTable[COLORTABLE_MAX];
+
+ struct gl_program_state Program; /**< general program state */
+ struct gl_vertex_program_state VertexProgram;
+ struct gl_fragment_program_state FragmentProgram;
+ struct gl_ati_fragment_shader_state ATIFragmentShader;
+
+ struct gl_shader_state Shader; /**< GLSL shader object state */
+
+ struct gl_query_state Query; /**< occlusion, timer queries */
+
+ struct gl_buffer_object *CopyReadBuffer; /**< GL_ARB_copy_buffer */
+ struct gl_buffer_object *CopyWriteBuffer; /**< GL_ARB_copy_buffer */
+ /*@}*/
+
+ struct gl_meta_state *Meta; /**< for "meta" operations */
+
+#if FEATURE_EXT_framebuffer_object
+ struct gl_renderbuffer *CurrentRenderbuffer;
+#endif
+
+ GLenum ErrorValue; /**< Last error code */
+
+ /**
+ * Recognize and silence repeated error debug messages in buggy apps.
+ */
+ const char *ErrorDebugFmtString;
+ GLuint ErrorDebugCount;
+
+ GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
+ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */
+
+ GLboolean ViewportInitialized; /**< has viewport size been initialized? */
+
+ GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */
+
+ /** \name Derived state */
+ /*@{*/
+ /** Bitwise-or of DD_* flags. Note that this bitfield may be used before
+ * state validation so they need to always be current.
+ */
+ GLbitfield _TriangleCaps;
+ GLbitfield _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */
+ GLfloat _EyeZDir[3];
+ GLfloat _ModelViewInvScale;
+ GLboolean _NeedEyeCoords;
+ GLboolean _ForceEyeCoords;
+
+ GLuint TextureStateTimestamp; /**< detect changes to shared state */
+
+ struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
+ struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
+ /**@}*/
+
+ struct gl_list_extensions ListExt; /**< driver dlist extensions */
+
+ /** \name For debugging/development only */
+ /*@{*/
+ GLboolean FirstTimeCurrent;
+ /*@}*/
+
+ /** Dither disable via MESA_NO_DITHER env var */
+ GLboolean NoDither;
+
+ /** software compression/decompression supported or not */
+ GLboolean Mesa_DXTn;
+
+ /**
+ * Use dp4 (rather than mul/mad) instructions for position
+ * transformation?
+ */
+ GLboolean mvp_with_dp4;
+
+ /** Core tnl module support */
+ struct gl_tnl_module TnlModule;
+
+ /**
+ * \name Hooks for module contexts.
+ *
+ * These will eventually live in the driver or elsewhere.
+ */
+ /*@{*/
+ void *swrast_context;
+ void *swsetup_context;
+ void *swtnl_context;
+ void *swtnl_im;
+ struct st_context *st;
+ void *aelt_context;
+ /*@}*/
+};
+
+
+/** The string names for GL_POINT, GL_LINE_LOOP, etc */
+extern const char *_mesa_prim_name[GL_POLYGON+4];
+
+
+#ifdef DEBUG
+extern int MESA_VERBOSE;
+extern int MESA_DEBUG_FLAGS;
+# define MESA_FUNCTION __FUNCTION__
+#else
+# define MESA_VERBOSE 0
+# define MESA_DEBUG_FLAGS 0
+# define MESA_FUNCTION "a function"
+# ifndef NDEBUG
+# define NDEBUG
+# endif
+#endif
+
+
+enum _verbose
+{
+ VERBOSE_VARRAY = 0x0001,
+ VERBOSE_TEXTURE = 0x0002,
+ VERBOSE_IMMEDIATE = 0x0004,
+ VERBOSE_PIPELINE = 0x0008,
+ VERBOSE_DRIVER = 0x0010,
+ VERBOSE_STATE = 0x0020,
+ VERBOSE_API = 0x0040,
+ VERBOSE_DISPLAY_LIST = 0x0100,
+ VERBOSE_LIGHTING = 0x0200,
+ VERBOSE_PRIMS = 0x0400,
+ VERBOSE_VERTS = 0x0800,
+ VERBOSE_DISASSEM = 0x1000,
+};
+
+
+enum _debug
+{
+ DEBUG_ALWAYS_FLUSH = 0x1
+};
+
+
+
+#endif /* MTYPES_H */
diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c
new file mode 100644
index 000000000..01b68df7a
--- /dev/null
+++ b/mesalib/src/mesa/main/multisample.c
@@ -0,0 +1,61 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/multisample.h"
+
+
+/**
+ * Called via glSampleCoverageARB
+ */
+void GLAPIENTRY
+_mesa_SampleCoverageARB(GLclampf value, GLboolean invert)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
+
+ ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0);
+ ctx->Multisample.SampleCoverageInvert = invert;
+ ctx->NewState |= _NEW_MULTISAMPLE;
+}
+
+
+/**
+ * Initialize the context's multisample state.
+ * \param ctx the GL context.
+ */
+void
+_mesa_init_multisample(GLcontext *ctx)
+{
+ ctx->Multisample.Enabled = GL_TRUE;
+ ctx->Multisample.SampleAlphaToCoverage = GL_FALSE;
+ ctx->Multisample.SampleAlphaToOne = GL_FALSE;
+ ctx->Multisample.SampleCoverage = GL_FALSE;
+ ctx->Multisample.SampleCoverageValue = 1.0;
+ ctx->Multisample.SampleCoverageInvert = GL_FALSE;
+}
diff --git a/mesalib/src/mesa/main/multisample.h b/mesalib/src/mesa/main/multisample.h
new file mode 100644
index 000000000..4305900cc
--- /dev/null
+++ b/mesalib/src/mesa/main/multisample.h
@@ -0,0 +1,38 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 MULTISAMPLE_H
+#define MULTISAMPLE_H
+
+
+extern void GLAPIENTRY
+_mesa_SampleCoverageARB(GLclampf value, GLboolean invert);
+
+
+extern void
+_mesa_init_multisample(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c
new file mode 100644
index 000000000..fcef6dfd4
--- /dev/null
+++ b/mesalib/src/mesa/main/pixel.c
@@ -0,0 +1,845 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file pixel.c
+ * Pixel transfer functions (glPixelZoom, glPixelMap, glPixelTransfer)
+ */
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "pixel.h"
+#include "mtypes.h"
+
+
+/**********************************************************************/
+/***** glPixelZoom *****/
+/**********************************************************************/
+
+void GLAPIENTRY
+_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->Pixel.ZoomX == xfactor &&
+ ctx->Pixel.ZoomY == yfactor)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.ZoomX = xfactor;
+ ctx->Pixel.ZoomY = yfactor;
+}
+
+
+
+/**********************************************************************/
+/***** glPixelMap *****/
+/**********************************************************************/
+
+/**
+ * Return pointer to a pixelmap by name.
+ */
+static struct gl_pixelmap *
+get_pixelmap(GLcontext *ctx, GLenum map)
+{
+ switch (map) {
+ case GL_PIXEL_MAP_I_TO_I:
+ return &ctx->PixelMaps.ItoI;
+ case GL_PIXEL_MAP_S_TO_S:
+ return &ctx->PixelMaps.StoS;
+ case GL_PIXEL_MAP_I_TO_R:
+ return &ctx->PixelMaps.ItoR;
+ case GL_PIXEL_MAP_I_TO_G:
+ return &ctx->PixelMaps.ItoG;
+ case GL_PIXEL_MAP_I_TO_B:
+ return &ctx->PixelMaps.ItoB;
+ case GL_PIXEL_MAP_I_TO_A:
+ return &ctx->PixelMaps.ItoA;
+ case GL_PIXEL_MAP_R_TO_R:
+ return &ctx->PixelMaps.RtoR;
+ case GL_PIXEL_MAP_G_TO_G:
+ return &ctx->PixelMaps.GtoG;
+ case GL_PIXEL_MAP_B_TO_B:
+ return &ctx->PixelMaps.BtoB;
+ case GL_PIXEL_MAP_A_TO_A:
+ return &ctx->PixelMaps.AtoA;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ * Helper routine used by the other _mesa_PixelMap() functions.
+ */
+static void
+store_pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize,
+ const GLfloat *values)
+{
+ GLint i;
+ struct gl_pixelmap *pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPixelMap(map)");
+ return;
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ /* special case */
+ ctx->PixelMaps.StoS.Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ ctx->PixelMaps.StoS.Map[i] = (GLfloat)IROUND(values[i]);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ /* special case */
+ ctx->PixelMaps.ItoI.Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ ctx->PixelMaps.ItoI.Map[i] = values[i];
+ }
+ break;
+ default:
+ /* general case */
+ pm->Size = mapsize;
+ for (i = 0; i < mapsize; i++) {
+ GLfloat val = CLAMP(values[i], 0.0F, 1.0F);
+ pm->Map[i] = val;
+ pm->Map8[i] = (GLint) (val * 255.0F);
+ }
+ }
+}
+
+
+/**
+ * Convenience wrapper for _mesa_validate_pbo_access() for gl[Get]PixelMap().
+ */
+static GLboolean
+validate_pbo_access(GLcontext *ctx, struct gl_pixelstore_attrib *pack,
+ GLsizei mapsize, GLenum format, GLenum type,
+ const GLvoid *ptr)
+{
+ GLboolean ok;
+
+ /* Note, need to use DefaultPacking and Unpack's buffer object */
+ ctx->DefaultPacking.BufferObj = pack->BufferObj;
+
+ ok = _mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1,
+ format, type, ptr);
+
+ /* restore */
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
+
+ if (!ok) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMap(invalid PBO access)");
+ }
+ return ok;
+}
+
+
+void GLAPIENTRY
+_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_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 */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (const GLfloat *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapfv(PBO is mapped)");
+ }
+ return;
+ }
+
+ store_pixelmap(ctx, map, mapsize, values);
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+void GLAPIENTRY
+_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(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 */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (const GLuint *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapuiv(PBO is mapped)");
+ }
+ return;
+ }
+
+ /* convert to floats */
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = UINT_TO_FLOAT( values[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ store_pixelmap(ctx, map, mapsize, fvalues);
+}
+
+
+void GLAPIENTRY
+_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
+{
+ GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(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 */
+ if (!_mesa_is_pow_two(mapsize)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" );
+ return;
+ }
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
+ if (!validate_pbo_access(ctx, &ctx->Unpack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (const GLushort *) _mesa_map_pbo_source(ctx, &ctx->Unpack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glPixelMapusv(PBO is mapped)");
+ }
+ return;
+ }
+
+ /* convert to floats */
+ if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = (GLfloat) values[i];
+ }
+ }
+ else {
+ GLint i;
+ for (i = 0; i < mapsize; i++) {
+ fvalues[i] = USHORT_TO_FLOAT( values[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+
+ store_pixelmap(ctx, map, mapsize, fvalues);
+}
+
+
+void GLAPIENTRY
+_mesa_GetPixelMapfv( GLenum map, GLfloat *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapfv(map)");
+ return;
+ }
+
+ mapsize = pm->Size;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_FLOAT, values)) {
+ return;
+ }
+
+ values = (GLfloat *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapfv(PBO is mapped)");
+ }
+ return;
+ }
+
+ if (map == GL_PIXEL_MAP_S_TO_S) {
+ /* special case */
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLfloat) ctx->PixelMaps.StoS.Map[i];
+ }
+ }
+ else {
+ MEMCPY(values, pm->Map, mapsize * sizeof(GLfloat));
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+void GLAPIENTRY
+_mesa_GetPixelMapuiv( GLenum map, GLuint *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapuiv(map)");
+ return;
+ }
+ mapsize = pm->Size;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_INT, values)) {
+ return;
+ }
+
+ values = (GLuint *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapuiv(PBO is mapped)");
+ }
+ return;
+ }
+
+ if (map == GL_PIXEL_MAP_S_TO_S) {
+ /* special case */
+ MEMCPY(values, ctx->PixelMaps.StoS.Map, mapsize * sizeof(GLint));
+ }
+ else {
+ for (i = 0; i < mapsize; i++) {
+ values[i] = FLOAT_TO_UINT( pm->Map[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+void GLAPIENTRY
+_mesa_GetPixelMapusv( GLenum map, GLushort *values )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint mapsize, i;
+ const struct gl_pixelmap *pm;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ pm = get_pixelmap(ctx, map);
+ if (!pm) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelMapusv(map)");
+ return;
+ }
+ mapsize = pm ? pm->Size : 0;
+
+ if (!validate_pbo_access(ctx, &ctx->Pack, mapsize,
+ GL_INTENSITY, GL_UNSIGNED_SHORT, values)) {
+ return;
+ }
+
+ values = (GLushort *) _mesa_map_pbo_dest(ctx, &ctx->Pack, values);
+ if (!values) {
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetPixelMapusv(PBO is mapped)");
+ }
+ return;
+ }
+
+ switch (map) {
+ /* special cases */
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLushort) CLAMP(ctx->PixelMaps.ItoI.Map[i], 0.0, 65535.);
+ }
+ break;
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i = 0; i < mapsize; i++) {
+ values[i] = (GLushort) CLAMP(ctx->PixelMaps.StoS.Map[i], 0.0, 65535.);
+ }
+ break;
+ default:
+ for (i = 0; i < mapsize; i++) {
+ CLAMPED_FLOAT_TO_USHORT(values[i], pm->Map[i] );
+ }
+ }
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+
+/**********************************************************************/
+/***** glPixelTransfer *****/
+/**********************************************************************/
+
+
+/*
+ * Implements glPixelTransfer[fi] whether called immediately or from a
+ * display list.
+ */
+void GLAPIENTRY
+_mesa_PixelTransferf( GLenum pname, GLfloat param )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_MAP_COLOR:
+ if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_MAP_STENCIL:
+ if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_INDEX_SHIFT:
+ if (ctx->Pixel.IndexShift == (GLint) param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.IndexShift = (GLint) param;
+ break;
+ case GL_INDEX_OFFSET:
+ if (ctx->Pixel.IndexOffset == (GLint) param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.IndexOffset = (GLint) param;
+ break;
+ case GL_RED_SCALE:
+ if (ctx->Pixel.RedScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.RedScale = param;
+ break;
+ case GL_RED_BIAS:
+ if (ctx->Pixel.RedBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.RedBias = param;
+ break;
+ case GL_GREEN_SCALE:
+ if (ctx->Pixel.GreenScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.GreenScale = param;
+ break;
+ case GL_GREEN_BIAS:
+ if (ctx->Pixel.GreenBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.GreenBias = param;
+ break;
+ case GL_BLUE_SCALE:
+ if (ctx->Pixel.BlueScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.BlueScale = param;
+ break;
+ case GL_BLUE_BIAS:
+ if (ctx->Pixel.BlueBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.BlueBias = param;
+ break;
+ case GL_ALPHA_SCALE:
+ if (ctx->Pixel.AlphaScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.AlphaScale = param;
+ break;
+ case GL_ALPHA_BIAS:
+ if (ctx->Pixel.AlphaBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.AlphaBias = param;
+ break;
+ case GL_DEPTH_SCALE:
+ if (ctx->Pixel.DepthScale == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.DepthScale = param;
+ break;
+ case GL_DEPTH_BIAS:
+ if (ctx->Pixel.DepthBias == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.DepthBias = param;
+ break;
+ case GL_POST_COLOR_MATRIX_RED_SCALE:
+ if (ctx->Pixel.PostColorMatrixScale[0] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixScale[0] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_RED_BIAS:
+ if (ctx->Pixel.PostColorMatrixBias[0] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixBias[0] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_SCALE:
+ if (ctx->Pixel.PostColorMatrixScale[1] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixScale[1] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_GREEN_BIAS:
+ if (ctx->Pixel.PostColorMatrixBias[1] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixBias[1] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_SCALE:
+ if (ctx->Pixel.PostColorMatrixScale[2] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixScale[2] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_BLUE_BIAS:
+ if (ctx->Pixel.PostColorMatrixBias[2] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixBias[2] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_SCALE:
+ if (ctx->Pixel.PostColorMatrixScale[3] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixScale[3] = param;
+ break;
+ case GL_POST_COLOR_MATRIX_ALPHA_BIAS:
+ if (ctx->Pixel.PostColorMatrixBias[3] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostColorMatrixBias[3] = param;
+ break;
+ case GL_POST_CONVOLUTION_RED_SCALE:
+ if (ctx->Pixel.PostConvolutionScale[0] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionScale[0] = param;
+ break;
+ case GL_POST_CONVOLUTION_RED_BIAS:
+ if (ctx->Pixel.PostConvolutionBias[0] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionBias[0] = param;
+ break;
+ case GL_POST_CONVOLUTION_GREEN_SCALE:
+ if (ctx->Pixel.PostConvolutionScale[1] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionScale[1] = param;
+ break;
+ case GL_POST_CONVOLUTION_GREEN_BIAS:
+ if (ctx->Pixel.PostConvolutionBias[1] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionBias[1] = param;
+ break;
+ case GL_POST_CONVOLUTION_BLUE_SCALE:
+ if (ctx->Pixel.PostConvolutionScale[2] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionScale[2] = param;
+ break;
+ case GL_POST_CONVOLUTION_BLUE_BIAS:
+ if (ctx->Pixel.PostConvolutionBias[2] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionBias[2] = param;
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_SCALE:
+ if (ctx->Pixel.PostConvolutionScale[3] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionScale[3] = param;
+ break;
+ case GL_POST_CONVOLUTION_ALPHA_BIAS:
+ if (ctx->Pixel.PostConvolutionBias[3] == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+ ctx->Pixel.PostConvolutionBias[3] = param;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_PixelTransferi( GLenum pname, GLint param )
+{
+ _mesa_PixelTransferf( pname, (GLfloat) param );
+}
+
+
+
+/**********************************************************************/
+/***** State Management *****/
+/**********************************************************************/
+
+/*
+ * Return a bitmask of IMAGE_*_BIT flags which to indicate which
+ * pixel transfer operations are enabled.
+ */
+static void
+update_image_transfer_state(GLcontext *ctx)
+{
+ GLuint mask = 0;
+
+ 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)
+ mask |= IMAGE_SCALE_BIAS_BIT;
+
+ if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset)
+ mask |= IMAGE_SHIFT_OFFSET_BIT;
+
+ if (ctx->Pixel.MapColorFlag)
+ mask |= IMAGE_MAP_COLOR_BIT;
+
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_PRECONVOLUTION])
+ mask |= IMAGE_COLOR_TABLE_BIT;
+
+ if (ctx->Pixel.Convolution1DEnabled ||
+ ctx->Pixel.Convolution2DEnabled ||
+ ctx->Pixel.Separable2DEnabled) {
+ mask |= IMAGE_CONVOLUTION_BIT;
+ if (ctx->Pixel.PostConvolutionScale[0] != 1.0F ||
+ ctx->Pixel.PostConvolutionScale[1] != 1.0F ||
+ ctx->Pixel.PostConvolutionScale[2] != 1.0F ||
+ ctx->Pixel.PostConvolutionScale[3] != 1.0F ||
+ ctx->Pixel.PostConvolutionBias[0] != 0.0F ||
+ ctx->Pixel.PostConvolutionBias[1] != 0.0F ||
+ ctx->Pixel.PostConvolutionBias[2] != 0.0F ||
+ ctx->Pixel.PostConvolutionBias[3] != 0.0F) {
+ mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS;
+ }
+ }
+
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCONVOLUTION])
+ mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT;
+
+ if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY ||
+ ctx->Pixel.PostColorMatrixScale[0] != 1.0F ||
+ ctx->Pixel.PostColorMatrixBias[0] != 0.0F ||
+ ctx->Pixel.PostColorMatrixScale[1] != 1.0F ||
+ ctx->Pixel.PostColorMatrixBias[1] != 0.0F ||
+ ctx->Pixel.PostColorMatrixScale[2] != 1.0F ||
+ ctx->Pixel.PostColorMatrixBias[2] != 0.0F ||
+ ctx->Pixel.PostColorMatrixScale[3] != 1.0F ||
+ ctx->Pixel.PostColorMatrixBias[3] != 0.0F)
+ mask |= IMAGE_COLOR_MATRIX_BIT;
+
+ if (ctx->Pixel.ColorTableEnabled[COLORTABLE_POSTCOLORMATRIX])
+ mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT;
+
+ if (ctx->Pixel.HistogramEnabled)
+ mask |= IMAGE_HISTOGRAM_BIT;
+
+ if (ctx->Pixel.MinMaxEnabled)
+ mask |= IMAGE_MIN_MAX_BIT;
+
+ ctx->_ImageTransferState = mask;
+}
+
+
+/**
+ * Update mesa pixel transfer derived state.
+ */
+void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_COLOR_MATRIX)
+ _math_matrix_analyse( ctx->ColorMatrixStack.Top );
+
+ /* References ColorMatrix.type (derived above).
+ */
+ if (new_state & _MESA_NEW_TRANSFER_STATE)
+ update_image_transfer_state(ctx);
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+static void
+init_pixelmap(struct gl_pixelmap *map)
+{
+ map->Size = 1;
+ map->Map[0] = 0.0;
+ map->Map8[0] = 0;
+}
+
+
+/**
+ * Initialize the context's PIXEL attribute group.
+ */
+void
+_mesa_init_pixel( GLcontext *ctx )
+{
+ int i;
+
+ /* 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.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;
+ init_pixelmap(&ctx->PixelMaps.StoS);
+ init_pixelmap(&ctx->PixelMaps.ItoI);
+ init_pixelmap(&ctx->PixelMaps.ItoR);
+ init_pixelmap(&ctx->PixelMaps.ItoG);
+ init_pixelmap(&ctx->PixelMaps.ItoB);
+ init_pixelmap(&ctx->PixelMaps.ItoA);
+ init_pixelmap(&ctx->PixelMaps.RtoR);
+ init_pixelmap(&ctx->PixelMaps.GtoG);
+ init_pixelmap(&ctx->PixelMaps.BtoB);
+ init_pixelmap(&ctx->PixelMaps.AtoA);
+ ctx->Pixel.HistogramEnabled = GL_FALSE;
+ ctx->Pixel.MinMaxEnabled = GL_FALSE;
+ ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0);
+ ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0);
+ for (i = 0; i < COLORTABLE_MAX; i++) {
+ ASSIGN_4V(ctx->Pixel.ColorTableScale[i], 1.0, 1.0, 1.0, 1.0);
+ ASSIGN_4V(ctx->Pixel.ColorTableBias[i], 0.0, 0.0, 0.0, 0.0);
+ ctx->Pixel.ColorTableEnabled[i] = GL_FALSE;
+ }
+ ctx->Pixel.Convolution1DEnabled = GL_FALSE;
+ ctx->Pixel.Convolution2DEnabled = GL_FALSE;
+ ctx->Pixel.Separable2DEnabled = GL_FALSE;
+ for (i = 0; i < 3; i++) {
+ ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0);
+ ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE;
+ ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0);
+ ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0);
+ }
+ for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) {
+ ctx->Convolution1D.Filter[i] = 0.0;
+ ctx->Convolution2D.Filter[i] = 0.0;
+ ctx->Separable2D.Filter[i] = 0.0;
+ }
+ ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0);
+ ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0);
+ /* GL_SGI_texture_color_table */
+ ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0);
+ ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0);
+
+ if (ctx->Visual.doubleBufferMode) {
+ ctx->Pixel.ReadBuffer = GL_BACK;
+ }
+ else {
+ ctx->Pixel.ReadBuffer = GL_FRONT;
+ }
+
+ /* Miscellaneous */
+ ctx->_ImageTransferState = 0;
+}
diff --git a/mesalib/src/mesa/main/pixel.h b/mesalib/src/mesa/main/pixel.h
new file mode 100644
index 000000000..cb6c5262a
--- /dev/null
+++ b/mesalib/src/mesa/main/pixel.h
@@ -0,0 +1,80 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file pixel.h
+ * Pixel operations.
+ */
+
+
+#ifndef PIXEL_H
+#define PIXEL_H
+
+
+#include "mtypes.h"
+
+
+/** \name API functions */
+/*@{*/
+
+extern void GLAPIENTRY
+_mesa_GetPixelMapfv( GLenum map, GLfloat *values );
+
+extern void GLAPIENTRY
+_mesa_GetPixelMapuiv( GLenum map, GLuint *values );
+
+extern void GLAPIENTRY
+_mesa_GetPixelMapusv( GLenum map, GLushort *values );
+
+extern void GLAPIENTRY
+_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values );
+
+extern void GLAPIENTRY
+_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values );
+
+extern void GLAPIENTRY
+_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values );
+
+extern void GLAPIENTRY
+_mesa_PixelTransferf( GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_PixelTransferi( GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor );
+
+/*@}*/
+
+
+extern void
+_mesa_update_pixel( GLcontext *ctx, GLuint newstate );
+
+extern void
+_mesa_init_pixel( GLcontext * ctx );
+
+/*@}*/
+
+#endif
diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c
new file mode 100644
index 000000000..6a641f83f
--- /dev/null
+++ b/mesalib/src/mesa/main/pixelstore.c
@@ -0,0 +1,286 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file pixelstore.c
+ * glPixelStore functions.
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "pixelstore.h"
+#include "mtypes.h"
+
+
+void GLAPIENTRY
+_mesa_PixelStorei( GLenum pname, GLint param )
+{
+ /* NOTE: this call can't be compiled into the display list */
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_PACK_SWAP_BYTES:
+ if (param == (GLint)ctx->Pack.SwapBytes)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PACK_LSB_FIRST:
+ if (param == (GLint)ctx->Pack.LsbFirst)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.RowLength == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.RowLength = param;
+ break;
+ case GL_PACK_IMAGE_HEIGHT:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.ImageHeight == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.ImageHeight = param;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.SkipPixels == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.SkipPixels = param;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.SkipRows == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.SkipRows = param;
+ break;
+ case GL_PACK_SKIP_IMAGES:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.SkipImages == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.SkipImages = param;
+ break;
+ case GL_PACK_ALIGNMENT:
+ if (param!=1 && param!=2 && param!=4 && param!=8) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Pack.Alignment == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.Alignment = param;
+ break;
+ case GL_PACK_INVERT_MESA:
+ if (!ctx->Extensions.MESA_pack_invert) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" );
+ return;
+ }
+ if (ctx->Pack.Invert == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Pack.Invert = param;
+ break;
+
+ case GL_UNPACK_SWAP_BYTES:
+ if (param == (GLint)ctx->Unpack.SwapBytes)
+ return;
+ if ((GLint)ctx->Unpack.SwapBytes == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ if (param == (GLint)ctx->Unpack.LsbFirst)
+ return;
+ if ((GLint)ctx->Unpack.LsbFirst == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Unpack.RowLength == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.RowLength = param;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Unpack.ImageHeight == param)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.ImageHeight = param;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Unpack.SkipPixels == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.SkipPixels = param;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ if (param<0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Unpack.SkipRows == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.SkipRows = param;
+ break;
+ case GL_UNPACK_SKIP_IMAGES:
+ if (param < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ return;
+ }
+ if (ctx->Unpack.SkipImages == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.SkipImages = param;
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ if (param!=1 && param!=2 && param!=4 && param!=8) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
+ return;
+ }
+ if (ctx->Unpack.Alignment == param)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.Alignment = param;
+ break;
+ case GL_UNPACK_CLIENT_STORAGE_APPLE:
+ if (param == (GLint)ctx->Unpack.ClientStorage)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PACKUNPACK);
+ ctx->Unpack.ClientStorage = param ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_PixelStoref( GLenum pname, GLfloat param )
+{
+ _mesa_PixelStorei( pname, (GLint) param );
+}
+
+
+
+/**
+ * Initialize the context's pixel store state.
+ */
+void
+_mesa_init_pixelstore( GLcontext *ctx )
+{
+ /* Pixel transfer */
+ ctx->Pack.Alignment = 4;
+ ctx->Pack.RowLength = 0;
+ ctx->Pack.ImageHeight = 0;
+ ctx->Pack.SkipPixels = 0;
+ ctx->Pack.SkipRows = 0;
+ ctx->Pack.SkipImages = 0;
+ ctx->Pack.SwapBytes = GL_FALSE;
+ ctx->Pack.LsbFirst = GL_FALSE;
+ ctx->Pack.ClientStorage = GL_FALSE;
+ ctx->Pack.Invert = GL_FALSE;
+#if FEATURE_EXT_pixel_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+ ctx->Unpack.Alignment = 4;
+ ctx->Unpack.RowLength = 0;
+ ctx->Unpack.ImageHeight = 0;
+ ctx->Unpack.SkipPixels = 0;
+ ctx->Unpack.SkipRows = 0;
+ ctx->Unpack.SkipImages = 0;
+ ctx->Unpack.SwapBytes = GL_FALSE;
+ ctx->Unpack.LsbFirst = GL_FALSE;
+ ctx->Unpack.ClientStorage = GL_FALSE;
+ ctx->Unpack.Invert = GL_FALSE;
+#if FEATURE_EXT_pixel_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+
+ /*
+ * _mesa_unpack_image() returns image data in this format. When we
+ * execute image commands (glDrawPixels(), glTexImage(), etc) from
+ * within display lists we have to be sure to set the current
+ * unpacking parameters to these values!
+ */
+ ctx->DefaultPacking.Alignment = 1;
+ ctx->DefaultPacking.RowLength = 0;
+ ctx->DefaultPacking.SkipPixels = 0;
+ ctx->DefaultPacking.SkipRows = 0;
+ ctx->DefaultPacking.ImageHeight = 0;
+ ctx->DefaultPacking.SkipImages = 0;
+ ctx->DefaultPacking.SwapBytes = GL_FALSE;
+ ctx->DefaultPacking.LsbFirst = GL_FALSE;
+ ctx->DefaultPacking.ClientStorage = GL_FALSE;
+ ctx->DefaultPacking.Invert = GL_FALSE;
+#if FEATURE_EXT_pixel_buffer_object
+ _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+}
diff --git a/mesalib/src/mesa/main/pixelstore.h b/mesalib/src/mesa/main/pixelstore.h
new file mode 100644
index 000000000..ee963f9ba
--- /dev/null
+++ b/mesalib/src/mesa/main/pixelstore.h
@@ -0,0 +1,50 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file pixelstore.h
+ * glPixelStore functions.
+ */
+
+
+#ifndef PIXELSTORE_H
+#define PIXELSTORE_H
+
+
+#include "glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_PixelStorei( GLenum pname, GLint param );
+
+
+extern void GLAPIENTRY
+_mesa_PixelStoref( GLenum pname, GLfloat param );
+
+
+extern void
+_mesa_init_pixelstore( GLcontext *ctx );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/points.c b/mesalib/src/mesa/main/points.c
new file mode 100644
index 000000000..4c8fc1f72
--- /dev/null
+++ b/mesalib/src/mesa/main/points.c
@@ -0,0 +1,263 @@
+/**
+ * \file points.c
+ * Point operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "points.h"
+#include "texstate.h"
+#include "mtypes.h"
+
+
+/**
+ * Set current point size.
+ * \param size point diameter in pixels
+ * \sa glPointSize().
+ */
+void GLAPIENTRY
+_mesa_PointSize( GLfloat size )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (size <= 0.0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" );
+ return;
+ }
+
+ if (ctx->Point.Size == size)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.Size = size;
+
+ if (ctx->Driver.PointSize)
+ ctx->Driver.PointSize(ctx, size);
+}
+
+
+#if _HAVE_FULL_GL
+
+
+void GLAPIENTRY
+_mesa_PointParameteri( GLenum pname, GLint param )
+{
+ const GLfloat value = (GLfloat) param;
+ _mesa_PointParameterfv(pname, &value);
+}
+
+
+void GLAPIENTRY
+_mesa_PointParameteriv( GLenum pname, const GLint *params )
+{
+ GLfloat p[3];
+ p[0] = (GLfloat) params[0];
+ if (pname == GL_DISTANCE_ATTENUATION_EXT) {
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ }
+ _mesa_PointParameterfv(pname, p);
+}
+
+
+void GLAPIENTRY
+_mesa_PointParameterf( GLenum pname, GLfloat param)
+{
+ _mesa_PointParameterfv(pname, &param);
+}
+
+
+void GLAPIENTRY
+_mesa_PointParameterfv( GLenum pname, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (pname) {
+ case GL_DISTANCE_ATTENUATION_EXT:
+ if (ctx->Extensions.EXT_point_parameters) {
+ if (TEST_EQ_3V(ctx->Point.Params, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ COPY_3V(ctx->Point.Params, params);
+ ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0 ||
+ ctx->Point.Params[1] != 0.0 ||
+ ctx->Point.Params[2] != 0.0);
+
+ if (ctx->Point._Attenuated)
+ ctx->_TriangleCaps |= DD_POINT_ATTEN;
+ else
+ ctx->_TriangleCaps &= ~DD_POINT_ATTEN;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ if (ctx->Extensions.EXT_point_parameters) {
+ if (params[0] < 0.0F) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glPointParameterf[v]{EXT,ARB}(param)" );
+ return;
+ }
+ if (ctx->Point.MinSize == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.MinSize = params[0];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ if (ctx->Extensions.EXT_point_parameters) {
+ if (params[0] < 0.0F) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glPointParameterf[v]{EXT,ARB}(param)" );
+ return;
+ }
+ if (ctx->Point.MaxSize == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.MaxSize = params[0];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ if (ctx->Extensions.EXT_point_parameters) {
+ if (params[0] < 0.0F) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glPointParameterf[v]{EXT,ARB}(param)" );
+ return;
+ }
+ if (ctx->Point.Threshold == params[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.Threshold = params[0];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ case GL_POINT_SPRITE_R_MODE_NV:
+ /* This is one area where ARB_point_sprite and NV_point_sprite
+ * differ. In ARB_point_sprite the POINT_SPRITE_R_MODE is
+ * always ZERO. NV_point_sprite adds the S and R modes.
+ */
+ if (ctx->Extensions.NV_point_sprite) {
+ GLenum value = (GLenum) params[0];
+ if (value != GL_ZERO && value != GL_S && value != GL_R) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glPointParameterf[v]{EXT,ARB}(param)");
+ return;
+ }
+ if (ctx->Point.SpriteRMode == value)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.SpriteRMode = value;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ case GL_POINT_SPRITE_COORD_ORIGIN:
+ if (ctx->Extensions.ARB_point_sprite || ctx->Extensions.NV_point_sprite) {
+ GLenum value = (GLenum) params[0];
+ if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glPointParameterf[v]{EXT,ARB}(param)");
+ return;
+ }
+ if (ctx->Point.SpriteOrigin == value)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.SpriteOrigin = value;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)");
+ return;
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM,
+ "glPointParameterf[v]{EXT,ARB}(pname)" );
+ return;
+ }
+
+ if (ctx->Driver.PointParameterfv)
+ (*ctx->Driver.PointParameterfv)(ctx, pname, params);
+}
+#endif
+
+
+
+/**
+ * Initialize the context point state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __GLcontextRec::Point and point related constants in
+ * __GLcontextRec::Const.
+ */
+void
+_mesa_init_point(GLcontext *ctx)
+{
+ GLuint i;
+
+ 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
+ = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA);
+ ctx->Point.Threshold = 1.0;
+ ctx->Point.PointSprite = GL_FALSE; /* GL_ARB/NV_point_sprite */
+ ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite (only!) */
+ ctx->Point.SpriteOrigin = GL_UPPER_LEFT; /* GL_ARB_point_sprite */
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ ctx->Point.CoordReplace[i] = GL_FALSE; /* GL_ARB/NV_point_sprite */
+ }
+}
diff --git a/mesalib/src/mesa/main/points.h b/mesalib/src/mesa/main/points.h
new file mode 100644
index 000000000..156641eab
--- /dev/null
+++ b/mesalib/src/mesa/main/points.h
@@ -0,0 +1,57 @@
+/**
+ * \file points.h
+ * Point operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_PointSize( GLfloat size );
+
+extern void GLAPIENTRY
+_mesa_PointParameteri( GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_PointParameteriv( GLenum pname, const GLint *params );
+
+extern void GLAPIENTRY
+_mesa_PointParameterf( GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_PointParameterfv( GLenum pname, const GLfloat *params );
+
+extern void
+_mesa_init_point( GLcontext * ctx );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/polygon.c b/mesalib/src/mesa/main/polygon.c
new file mode 100644
index 000000000..376a87a39
--- /dev/null
+++ b/mesalib/src/mesa/main/polygon.c
@@ -0,0 +1,322 @@
+/**
+ * \file polygon.c
+ * Polygon operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "image.h"
+#include "enums.h"
+#include "macros.h"
+#include "polygon.h"
+#include "mtypes.h"
+
+
+/**
+ * Specify whether to cull front- or back-facing facets.
+ *
+ * \param mode culling mode.
+ *
+ * \sa glCullFace().
+ *
+ * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
+ * change, flushes the vertices and notifies the driver via
+ * the dd_function_table::CullFace callback.
+ */
+void GLAPIENTRY
+_mesa_CullFace( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" );
+ return;
+ }
+
+ if (ctx->Polygon.CullFaceMode == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.CullFaceMode = mode;
+
+ if (ctx->Driver.CullFace)
+ ctx->Driver.CullFace( ctx, mode );
+}
+
+
+/**
+ * Define front- and back-facing
+ *
+ * \param mode orientation of front-facing polygons.
+ *
+ * \sa glFrontFace().
+ *
+ * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change
+ * flushes the vertices and notifies the driver via
+ * the dd_function_table::FrontFace callback.
+ */
+void GLAPIENTRY
+_mesa_FrontFace( GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_CW && mode!=GL_CCW) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
+ return;
+ }
+
+ if (ctx->Polygon.FrontFace == mode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontFace = mode;
+
+ ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
+
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace( ctx, mode );
+}
+
+
+/**
+ * Set the polygon rasterization mode.
+ *
+ * \param face the polygons which \p mode applies to.
+ * \param mode how polygons should be rasterized.
+ *
+ * \sa glPolygonMode().
+ *
+ * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
+ * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::PolygonMode callback.
+ */
+void GLAPIENTRY
+_mesa_PolygonMode( GLenum face, GLenum mode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonMode %s %s\n",
+ _mesa_lookup_enum_by_nr(face),
+ _mesa_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
+ return;
+ }
+
+ switch (face) {
+ case GL_FRONT:
+ if (ctx->Polygon.FrontMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontMode = mode;
+ break;
+ case GL_FRONT_AND_BACK:
+ if (ctx->Polygon.FrontMode == mode &&
+ ctx->Polygon.BackMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.FrontMode = mode;
+ ctx->Polygon.BackMode = mode;
+ break;
+ case GL_BACK:
+ if (ctx->Polygon.BackMode == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.BackMode = mode;
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
+ return;
+ }
+
+ if (ctx->Polygon.FrontMode == GL_FILL && ctx->Polygon.BackMode == GL_FILL)
+ ctx->_TriangleCaps &= ~DD_TRI_UNFILLED;
+ else
+ ctx->_TriangleCaps |= DD_TRI_UNFILLED;
+
+ if (ctx->Driver.PolygonMode)
+ ctx->Driver.PolygonMode(ctx, face, mode);
+}
+
+#if _HAVE_FULL_GL
+
+
+/**
+ * This routine updates the ctx->Polygon.Stipple state.
+ * If we're getting the stipple data from a PBO, we map the buffer
+ * in order to access the data.
+ * In any case, we obey the current pixel unpacking parameters when fetching
+ * the stipple data.
+ *
+ * In the future, this routine should be used as a fallback, called via
+ * ctx->Driver.PolygonStipple(). We'll have to update all the DRI drivers
+ * too.
+ */
+void
+_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern)
+{
+ pattern = _mesa_map_validate_pbo_source(ctx, 2,
+ &ctx->Unpack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, pattern,
+ "glPolygonStipple");
+ if (!pattern)
+ return;
+
+ _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
+
+ _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
+}
+
+
+/**
+ * Called by glPolygonStipple.
+ */
+void GLAPIENTRY
+_mesa_PolygonStipple( const GLubyte *pattern )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonStipple\n");
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
+
+ _mesa_polygon_stipple(ctx, pattern);
+
+ if (ctx->Driver.PolygonStipple)
+ ctx->Driver.PolygonStipple(ctx, pattern);
+}
+
+
+/**
+ * Called by glPolygonStipple.
+ */
+void GLAPIENTRY
+_mesa_GetPolygonStipple( GLubyte *dest )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glGetPolygonStipple\n");
+
+ dest = _mesa_map_validate_pbo_dest(ctx, 2,
+ &ctx->Pack, 32, 32, 1,
+ GL_COLOR_INDEX, GL_BITMAP, dest,
+ "glGetPolygonStipple");
+ if (!dest)
+ return;
+
+ _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
+
+ _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
+}
+
+
+void GLAPIENTRY
+_mesa_PolygonOffset( GLfloat factor, GLfloat units )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
+
+ if (ctx->Polygon.OffsetFactor == factor &&
+ ctx->Polygon.OffsetUnits == units)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetFactor = factor;
+ ctx->Polygon.OffsetUnits = units;
+
+ if (ctx->Driver.PolygonOffset)
+ ctx->Driver.PolygonOffset( ctx, factor, units );
+}
+
+
+void GLAPIENTRY
+_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* XXX mult by DepthMaxF here??? */
+ _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
+}
+
+#endif
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialize the context polygon state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __GLcontextRec::Polygon and __GLcontextRec::PolygonStipple
+ * attribute groups.
+ */
+void _mesa_init_polygon( GLcontext * ctx )
+{
+ /* 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.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) );
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/polygon.h b/mesalib/src/mesa/main/polygon.h
new file mode 100644
index 000000000..78e8394d0
--- /dev/null
+++ b/mesalib/src/mesa/main/polygon.h
@@ -0,0 +1,66 @@
+/**
+ * \file polygon.h
+ * Polygon operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 "mtypes.h"
+
+
+extern void
+_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern);
+
+
+extern void GLAPIENTRY
+_mesa_CullFace( GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_FrontFace( GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_PolygonMode( GLenum face, GLenum mode );
+
+extern void GLAPIENTRY
+_mesa_PolygonOffset( GLfloat factor, GLfloat units );
+
+extern void GLAPIENTRY
+_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias );
+
+extern void GLAPIENTRY
+_mesa_PolygonStipple( const GLubyte *mask );
+
+extern void GLAPIENTRY
+_mesa_GetPolygonStipple( GLubyte *mask );
+
+extern void
+_mesa_init_polygon( GLcontext * ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
new file mode 100644
index 000000000..a73c6e050
--- /dev/null
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -0,0 +1,576 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "glheader.h"
+#include "context.h"
+#include "hash.h"
+#include "imports.h"
+#include "queryobj.h"
+#include "mtypes.h"
+
+
+/**
+ * Allocate a new query object. This is a fallback routine called via
+ * ctx->Driver.NewQueryObject().
+ * \param ctx - rendering context
+ * \param id - the new object's ID
+ * \return pointer to new query_object object or NULL if out of memory.
+ */
+static struct gl_query_object *
+_mesa_new_query_object(GLcontext *ctx, GLuint id)
+{
+ struct gl_query_object *q = MALLOC_STRUCT(gl_query_object);
+ (void) ctx;
+ if (q) {
+ q->Id = id;
+ q->Result = 0;
+ q->Active = GL_FALSE;
+ q->Ready = GL_TRUE; /* correct, see spec */
+ }
+ return q;
+}
+
+
+/**
+ * Begin a query. Software driver fallback.
+ * Called via ctx->Driver.BeginQuery().
+ */
+static void
+_mesa_begin_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ /* no-op */
+}
+
+
+/**
+ * End a query. Software driver fallback.
+ * Called via ctx->Driver.EndQuery().
+ */
+static void
+_mesa_end_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ q->Ready = GL_TRUE;
+}
+
+
+/**
+ * Wait for query to complete. Software driver fallback.
+ * Called via ctx->Driver.WaitQuery().
+ */
+static void
+_mesa_wait_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ /* For software drivers, _mesa_end_query() should have completed the query.
+ * For real hardware, implement a proper WaitQuery() driver function,
+ * which may require issuing a flush.
+ */
+ assert(q->Ready);
+}
+
+
+/**
+ * Check if a query results are ready. Software driver fallback.
+ * Called via ctx->Driver.CheckQuery().
+ */
+static void
+_mesa_check_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ /* No-op for sw rendering.
+ * HW drivers may need to flush at this time.
+ */
+}
+
+
+/**
+ * Delete a query object. Called via ctx->Driver.DeleteQuery().
+ * Not removed from hash table here.
+ */
+static void
+_mesa_delete_query(GLcontext *ctx, struct gl_query_object *q)
+{
+ _mesa_free(q);
+}
+
+
+static struct gl_query_object *
+lookup_query_object(GLcontext *ctx, GLuint id)
+{
+ return (struct gl_query_object *)
+ _mesa_HashLookup(ctx->Query.QueryObjects, id);
+}
+
+
+
+void
+_mesa_init_query_object_functions(struct dd_function_table *driver)
+{
+ driver->NewQueryObject = _mesa_new_query_object;
+ driver->DeleteQuery = _mesa_delete_query;
+ driver->BeginQuery = _mesa_begin_query;
+ driver->EndQuery = _mesa_end_query;
+ driver->WaitQuery = _mesa_wait_query;
+ driver->CheckQuery = _mesa_check_query;
+}
+
+
+void GLAPIENTRY
+_mesa_GenQueriesARB(GLsizei n, GLuint *ids)
+{
+ GLuint first;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
+ return;
+ }
+
+ /* No query objects can be active at this time! */
+ if (ctx->Query.CurrentOcclusionObject ||
+ ctx->Query.CurrentTimerObject) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB");
+ return;
+ }
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n);
+ if (first) {
+ GLsizei i;
+ for (i = 0; i < n; i++) {
+ struct gl_query_object *q
+ = ctx->Driver.NewQueryObject(ctx, first + i);
+ if (!q) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
+ return;
+ }
+ ids[i] = first + i;
+ _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)");
+ return;
+ }
+
+ /* No query objects can be active at this time! */
+ if (ctx->Query.CurrentOcclusionObject ||
+ ctx->Query.CurrentTimerObject) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (ids[i] > 0) {
+ struct gl_query_object *q = lookup_query_object(ctx, ids[i]);
+ if (q) {
+ ASSERT(!q->Active); /* should be caught earlier */
+ _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]);
+ ctx->Driver.DeleteQuery(ctx, q);
+ }
+ }
+ }
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsQueryARB(GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (id && lookup_query_object(ctx, id))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_BeginQueryARB(GLenum target, GLuint id)
+{
+ struct gl_query_object *q;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+
+ switch (target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (!ctx->Extensions.ARB_occlusion_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+ return;
+ }
+ if (ctx->Query.CurrentOcclusionObject) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB");
+ return;
+ }
+ break;
+#if FEATURE_EXT_timer_query
+ case GL_TIME_ELAPSED_EXT:
+ if (!ctx->Extensions.EXT_timer_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+ return;
+ }
+ if (ctx->Query.CurrentTimerObject) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB");
+ return;
+ }
+ break;
+#endif
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)");
+ return;
+ }
+
+ if (id == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)");
+ return;
+ }
+
+ q = lookup_query_object(ctx, id);
+ if (!q) {
+ /* create new object */
+ q = ctx->Driver.NewQueryObject(ctx, id);
+ if (!q) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB");
+ return;
+ }
+ _mesa_HashInsert(ctx->Query.QueryObjects, id, q);
+ }
+ else {
+ /* pre-existing object */
+ if (q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBeginQueryARB(query already active)");
+ return;
+ }
+ }
+
+ q->Target = target;
+ q->Active = GL_TRUE;
+ q->Result = 0;
+ q->Ready = GL_FALSE;
+
+ if (target == GL_SAMPLES_PASSED_ARB) {
+ ctx->Query.CurrentOcclusionObject = q;
+ }
+#if FEATURE_EXT_timer_query
+ else if (target == GL_TIME_ELAPSED_EXT) {
+ ctx->Query.CurrentTimerObject = q;
+ }
+#endif
+
+ ctx->Driver.BeginQuery(ctx, q);
+}
+
+
+void GLAPIENTRY
+_mesa_EndQueryARB(GLenum target)
+{
+ struct gl_query_object *q;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+
+ switch (target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (!ctx->Extensions.ARB_occlusion_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+ q = ctx->Query.CurrentOcclusionObject;
+ ctx->Query.CurrentOcclusionObject = NULL;
+ break;
+#if FEATURE_EXT_timer_query
+ case GL_TIME_ELAPSED_EXT:
+ if (!ctx->Extensions.EXT_timer_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+ q = ctx->Query.CurrentTimerObject;
+ ctx->Query.CurrentTimerObject = NULL;
+ break;
+#endif
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+
+ if (!q || !q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glEndQueryARB(no matching glBeginQueryARB)");
+ return;
+ }
+
+ q->Active = GL_FALSE;
+ ctx->Driver.EndQuery(ctx, q);
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params)
+{
+ struct gl_query_object *q;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ switch (target) {
+ case GL_SAMPLES_PASSED_ARB:
+ if (!ctx->Extensions.ARB_occlusion_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+ q = ctx->Query.CurrentOcclusionObject;
+ break;
+#if FEATURE_EXT_timer_query
+ case GL_TIME_ELAPSED_EXT:
+ if (!ctx->Extensions.EXT_timer_query) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)");
+ return;
+ }
+ q = ctx->Query.CurrentTimerObject;
+ break;
+#endif
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_COUNTER_BITS_ARB:
+ *params = 8 * sizeof(q->Result);
+ break;
+ case GL_CURRENT_QUERY_ARB:
+ *params = q ? q->Id : 0;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params)
+{
+ struct gl_query_object *q = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (id)
+ q = lookup_query_object(ctx, id);
+
+ if (!q || q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetQueryObjectivARB(id=%d is invalid or active)", id);
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ if (!q->Ready)
+ ctx->Driver.WaitQuery(ctx, q);
+ /* if result is too large for returned type, clamp to max value */
+ if (q->Result > 0x7fffffff) {
+ *params = 0x7fffffff;
+ }
+ else {
+ *params = (GLint)q->Result;
+ }
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
+ *params = q->Ready;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params)
+{
+ struct gl_query_object *q = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (id)
+ q = lookup_query_object(ctx, id);
+
+ if (!q || q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetQueryObjectuivARB(id=%d is invalid or active)", id);
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ if (!q->Ready)
+ ctx->Driver.WaitQuery(ctx, q);
+ /* if result is too large for returned type, clamp to max value */
+ if (q->Result > 0xffffffff) {
+ *params = 0xffffffff;
+ }
+ else {
+ *params = (GLuint)q->Result;
+ }
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
+ *params = q->Ready;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)");
+ return;
+ }
+}
+
+
+#if FEATURE_EXT_timer_query
+
+/**
+ * New with GL_EXT_timer_query
+ */
+void GLAPIENTRY
+_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
+{
+ struct gl_query_object *q = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (id)
+ q = lookup_query_object(ctx, id);
+
+ if (!q || q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetQueryObjectui64vARB(id=%d is invalid or active)", id);
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ if (!q->Ready)
+ ctx->Driver.WaitQuery(ctx, q);
+ *params = q->Result;
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
+ *params = q->Ready;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)");
+ return;
+ }
+}
+
+
+/**
+ * New with GL_EXT_timer_query
+ */
+void GLAPIENTRY
+_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
+{
+ struct gl_query_object *q = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (id)
+ q = lookup_query_object(ctx, id);
+
+ if (!q || q->Active) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id);
+ return;
+ }
+
+ switch (pname) {
+ case GL_QUERY_RESULT_ARB:
+ if (!q->Ready)
+ ctx->Driver.WaitQuery(ctx, q);
+ *params = q->Result;
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_ARB:
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
+ *params = q->Ready;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)");
+ return;
+ }
+}
+
+#endif /* FEATURE_EXT_timer_query */
+
+
+/**
+ * Allocate/init the context state related to query objects.
+ */
+void
+_mesa_init_query(GLcontext *ctx)
+{
+#if FEATURE_ARB_occlusion_query
+ ctx->Query.QueryObjects = _mesa_NewHashTable();
+ ctx->Query.CurrentOcclusionObject = NULL;
+#endif
+}
+
+
+/**
+ * Callback for deleting a query object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_queryobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_query_object *q= (struct gl_query_object *) data;
+ GLcontext *ctx = (GLcontext *)userData;
+ ctx->Driver.DeleteQuery(ctx, q);
+}
+
+
+/**
+ * Free the context state related to query objects.
+ */
+void
+_mesa_free_query_data(GLcontext *ctx)
+{
+ _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, ctx);
+ _mesa_DeleteHashTable(ctx->Query.QueryObjects);
+}
diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h
new file mode 100644
index 000000000..ee775ef95
--- /dev/null
+++ b/mesalib/src/mesa/main/queryobj.h
@@ -0,0 +1,71 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 OCCLUDE_H
+#define OCCLUDE_H
+
+
+extern void
+_mesa_init_query(GLcontext *ctx);
+
+extern void
+_mesa_free_query_data(GLcontext *ctx);
+
+extern void
+_mesa_init_query_object_functions(struct dd_function_table *driver);
+
+
+extern void GLAPIENTRY
+_mesa_GenQueriesARB(GLsizei n, GLuint *ids);
+
+extern void GLAPIENTRY
+_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsQueryARB(GLuint id);
+
+extern void GLAPIENTRY
+_mesa_BeginQueryARB(GLenum target, GLuint id);
+
+extern void GLAPIENTRY
+_mesa_EndQueryARB(GLenum target);
+
+extern void GLAPIENTRY
+_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params);
+
+extern void GLAPIENTRY
+_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params);
+
+extern void GLAPIENTRY
+_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params);
+
+
+#endif /* OCCLUDE_H */
diff --git a/mesalib/src/mesa/main/rastpos.c b/mesalib/src/mesa/main/rastpos.c
new file mode 100644
index 000000000..9f309d6ab
--- /dev/null
+++ b/mesalib/src/mesa/main/rastpos.c
@@ -0,0 +1,508 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file rastpos.c
+ * Raster position operations.
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "feedback.h"
+#include "macros.h"
+#include "rastpos.h"
+#include "state.h"
+
+
+/**
+ * Helper function for all the RasterPos functions.
+ */
+static void
+rasterpos(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat p[4];
+
+ p[0] = x;
+ p[1] = y;
+ p[2] = z;
+ p[3] = w;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT(ctx, 0);
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ ctx->Driver.RasterPos(ctx, p);
+}
+
+
+void GLAPIENTRY
+_mesa_RasterPos2d(GLdouble x, GLdouble y)
+{
+ rasterpos((GLfloat)x, (GLfloat)y, (GLfloat)0.0, (GLfloat)1.0);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2f(GLfloat x, GLfloat y)
+{
+ rasterpos(x, y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2i(GLint x, GLint y)
+{
+ rasterpos((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2s(GLshort x, GLshort y)
+{
+ rasterpos(x, y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ rasterpos(x, y, z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3i(GLint x, GLint y, GLint z)
+{
+ rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z)
+{
+ rasterpos(x, y, z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ rasterpos(x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w)
+{
+ rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ rasterpos(x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2dv(const GLdouble *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2fv(const GLfloat *v)
+{
+ rasterpos(v[0], v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2iv(const GLint *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos2sv(const GLshort *v)
+{
+ rasterpos(v[0], v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3dv(const GLdouble *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3fv(const GLfloat *v)
+{
+ rasterpos(v[0], v[1], v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3iv(const GLint *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos3sv(const GLshort *v)
+{
+ rasterpos(v[0], v[1], v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4dv(const GLdouble *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4fv(const GLfloat *v)
+{
+ rasterpos(v[0], v[1], v[2], v[3]);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4iv(const GLint *v)
+{
+ rasterpos((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void GLAPIENTRY
+_mesa_RasterPos4sv(const GLshort *v)
+{
+ rasterpos(v[0], v[1], v[2], v[3]);
+}
+
+
+/**********************************************************************/
+/*** GL_ARB_window_pos / GL_MESA_window_pos ***/
+/**********************************************************************/
+
+#if FEATURE_drawpix
+/**
+ * All glWindowPosMESA and glWindowPosARB commands call this function to
+ * update the current raster position.
+ */
+static void
+window_pos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat z2;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT(ctx, 0);
+
+ z2 = CLAMP(z, 0.0F, 1.0F) * (ctx->Viewport.Far - ctx->Viewport.Near)
+ + ctx->Viewport.Near;
+
+ /* set raster position */
+ ctx->Current.RasterPos[0] = x;
+ ctx->Current.RasterPos[1] = y;
+ ctx->Current.RasterPos[2] = z2;
+ ctx->Current.RasterPos[3] = 1.0F;
+
+ ctx->Current.RasterPosValid = GL_TRUE;
+
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
+ else
+ ctx->Current.RasterDistance = 0.0;
+
+ /* raster color = current color or index */
+ if (ctx->Visual.rgbMode) {
+ ctx->Current.RasterColor[0]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0], 0.0F, 1.0F);
+ ctx->Current.RasterColor[1]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1], 0.0F, 1.0F);
+ ctx->Current.RasterColor[2]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2], 0.0F, 1.0F);
+ ctx->Current.RasterColor[3]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3], 0.0F, 1.0F);
+ ctx->Current.RasterSecondaryColor[0]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0], 0.0F, 1.0F);
+ ctx->Current.RasterSecondaryColor[1]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1], 0.0F, 1.0F);
+ ctx->Current.RasterSecondaryColor[2]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2], 0.0F, 1.0F);
+ ctx->Current.RasterSecondaryColor[3]
+ = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3], 0.0F, 1.0F);
+ }
+ else {
+ ctx->Current.RasterIndex
+ = ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0];
+ }
+
+ /* raster texcoord = current texcoord */
+ {
+ GLuint texSet;
+ for (texSet = 0; texSet < ctx->Const.MaxTextureCoordUnits; texSet++) {
+ COPY_4FV( ctx->Current.RasterTexCoords[texSet],
+ ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texSet] );
+ }
+ }
+
+ if (ctx->RenderMode==GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
+
+
+/* This is just to support the GL_MESA_window_pos version */
+static void
+window_pos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ window_pos3f(x, y, z);
+ ctx->Current.RasterPos[3] = w;
+}
+
+
+void GLAPIENTRY
+_mesa_WindowPos2dMESA(GLdouble x, GLdouble y)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2fMESA(GLfloat x, GLfloat y)
+{
+ window_pos4f(x, y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2iMESA(GLint x, GLint y)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2sMESA(GLshort x, GLshort y)
+{
+ window_pos4f(x, y, 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z)
+{
+ window_pos4f(x, y, z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3iMESA(GLint x, GLint y, GLint z)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3sMESA(GLshort x, GLshort y, GLshort z)
+{
+ window_pos4f(x, y, z, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ window_pos4f(x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w)
+{
+ window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ window_pos4f(x, y, z, w);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2dvMESA(const GLdouble *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2fvMESA(const GLfloat *v)
+{
+ window_pos4f(v[0], v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2ivMESA(const GLint *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos2svMESA(const GLshort *v)
+{
+ window_pos4f(v[0], v[1], 0.0F, 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3dvMESA(const GLdouble *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3fvMESA(const GLfloat *v)
+{
+ window_pos4f(v[0], v[1], v[2], 1.0);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3ivMESA(const GLint *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos3svMESA(const GLshort *v)
+{
+ window_pos4f(v[0], v[1], v[2], 1.0F);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4dvMESA(const GLdouble *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4fvMESA(const GLfloat *v)
+{
+ window_pos4f(v[0], v[1], v[2], v[3]);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4ivMESA(const GLint *v)
+{
+ window_pos4f((GLfloat) v[0], (GLfloat) v[1],
+ (GLfloat) v[2], (GLfloat) v[3]);
+}
+
+void GLAPIENTRY
+_mesa_WindowPos4svMESA(const GLshort *v)
+{
+ window_pos4f(v[0], v[1], v[2], v[3]);
+}
+
+#endif
+
+#if 0
+
+/*
+ * OpenGL implementation of glWindowPos*MESA()
+ */
+void glWindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GLfloat fx, fy;
+
+ /* Push current matrix mode and viewport attributes */
+ glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
+
+ /* Setup projection parameters */
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+
+ glDepthRange( z, z );
+ glViewport( (int) x - 1, (int) y - 1, 2, 2 );
+
+ /* set the raster (window) position */
+ fx = x - (int) x;
+ fy = y - (int) y;
+ glRasterPos4f( fx, fy, 0.0, w );
+
+ /* restore matrices, viewport and matrix mode */
+ glPopMatrix();
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix();
+
+ glPopAttrib();
+}
+
+#endif
+
+
+/**********************************************************************/
+/** \name Initialization */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * Initialize the context current raster position information.
+ *
+ * \param ctx GL context.
+ *
+ * Initialize the current raster position information in
+ * __GLcontextRec::Current, and adds the extension entry points to the
+ * dispatcher.
+ */
+void _mesa_init_rastpos( GLcontext * ctx )
+{
+ int i;
+
+ 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 );
+ ASSIGN_4V( ctx->Current.RasterSecondaryColor, 0.0, 0.0, 0.0, 1.0 );
+ ctx->Current.RasterIndex = 1.0;
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+ ASSIGN_4V( ctx->Current.RasterTexCoords[i], 0.0, 0.0, 0.0, 1.0 );
+ ctx->Current.RasterPosValid = GL_TRUE;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/rastpos.h b/mesalib/src/mesa/main/rastpos.h
new file mode 100644
index 000000000..363f86ad8
--- /dev/null
+++ b/mesalib/src/mesa/main/rastpos.h
@@ -0,0 +1,193 @@
+/**
+ * \file rastpos.h
+ * Raster position operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef RASTPOS_H
+#define RASTPOS_H
+
+
+#include "glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_RasterPos2d(GLdouble x, GLdouble y);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2f(GLfloat x, GLfloat y);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2i(GLint x, GLint y);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2s(GLshort x, GLshort y);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3i(GLint x, GLint y, GLint z);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2dv(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2fv(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2iv(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos2sv(const GLshort *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3dv(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3fv(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3iv(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos3sv(const GLshort *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4dv(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4fv(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4iv(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_RasterPos4sv(const GLshort *v);
+
+
+/**********************************************************************/
+/** \name GL_MESA_window_pos */
+/**********************************************************************/
+/*@{*/
+
+extern void GLAPIENTRY
+_mesa_WindowPos2dMESA(GLdouble x, GLdouble y);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2fMESA(GLfloat x, GLfloat y);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2iMESA(GLint x, GLint y);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2sMESA(GLshort x, GLshort y);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3iMESA(GLint x, GLint y, GLint z);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3sMESA(GLshort x, GLshort y, GLshort z);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2dvMESA(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2fvMESA(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2ivMESA(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos2svMESA(const GLshort *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3dvMESA(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3fvMESA(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3ivMESA(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos3svMESA(const GLshort *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4dvMESA(const GLdouble *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4fvMESA(const GLfloat *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4ivMESA(const GLint *v);
+
+extern void GLAPIENTRY
+_mesa_WindowPos4svMESA(const GLshort *v);
+
+extern void
+_mesa_init_rastpos( GLcontext * ctx );
+
+/*@}*/
+
+#endif
diff --git a/mesalib/src/mesa/main/rbadaptors.c b/mesalib/src/mesa/main/rbadaptors.c
new file mode 100644
index 000000000..c1ac0606c
--- /dev/null
+++ b/mesalib/src/mesa/main/rbadaptors.c
@@ -0,0 +1,577 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * Renderbuffer adaptors.
+ * These fuctions are used to convert rendering from core Mesa's GLchan
+ * colors to 8 or 16-bit color channels in RGBA renderbuffers.
+ * This means Mesa can be compiled for 16 or 32-bit color processing
+ * and still render into 8 and 16-bit/channel renderbuffers.
+ */
+
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "renderbuffer.h"
+#include "rbadaptors.h"
+
+
+static void
+Delete_wrapper(struct gl_renderbuffer *rb)
+{
+ /* Decrement reference count on the buffer we're wrapping and delete
+ * it if refcount hits zero.
+ */
+ _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
+
+ /* delete myself */
+ _mesa_delete_renderbuffer(rb);
+}
+
+
+static GLboolean
+AllocStorage_wrapper(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ GLboolean b = rb->Wrapped->AllocStorage(ctx, rb->Wrapped, internalFormat,
+ width, height);
+ if (b) {
+ rb->Width = width;
+ rb->Height = height;
+ }
+ return b;
+}
+
+
+static void *
+GetPointer_wrapper(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ (void) ctx;
+ (void) rb;
+ (void) x;
+ (void) y;
+ return NULL;
+}
+
+
+static void
+GetRow_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLushort *values16 = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(count <= MAX_WIDTH);
+
+ /* get 8bpp values */
+ rb->Wrapped->GetRow(ctx, rb->Wrapped, count, x, y, values8);
+
+ /* convert 8bpp to 16bpp */
+ for (i = 0; i < 4 * count; i++) {
+ values16[i] = (values8[i] << 8) | values8[i];
+ }
+}
+
+
+static void
+GetValues_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLushort *values16 = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+
+ rb->Wrapped->GetValues(ctx, rb->Wrapped, count, x, y, values8);
+
+ for (i = 0; i < 4 * count; i++) {
+ values16[i] = (values8[i] << 8) | values8[i];
+ }
+}
+
+
+static void
+PutRow_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLushort *values16 = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 4 * count; i++) {
+ values8[i] = values16[i] >> 8;
+ }
+ rb->Wrapped->PutRow(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutRowRGB_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 3];
+ GLushort *values16 = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 3 * count; i++) {
+ values8[i] = values16[i] >> 8;
+ }
+ rb->Wrapped->PutRowRGB(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutMonoRow_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ GLubyte value8[4];
+ GLushort *value16 = (GLushort *) value;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ value8[0] = value16[0] >> 8;
+ value8[1] = value16[1] >> 8;
+ value8[2] = value16[2] >> 8;
+ value8[3] = value16[3] >> 8;
+ rb->Wrapped->PutMonoRow(ctx, rb->Wrapped, count, x, y, value8, mask);
+}
+
+
+static void
+PutValues_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLushort *values16 = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 4 * count; i++) {
+ values8[i] = values16[i] >> 8;
+ }
+ rb->Wrapped->PutValues(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutMonoValues_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ GLubyte value8[4];
+ GLushort *value16 = (GLushort *) value;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ value8[0] = value16[0] >> 8;
+ value8[1] = value16[1] >> 8;
+ value8[2] = value16[2] >> 8;
+ value8[3] = value16[3] >> 8;
+ rb->Wrapped->PutMonoValues(ctx, rb->Wrapped, count, x, y, value8, mask);
+}
+
+
+/**
+ * Wrap an 8-bit/channel renderbuffer with a 16-bit/channel
+ * renderbuffer adaptor.
+ */
+struct gl_renderbuffer *
+_mesa_new_renderbuffer_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb8)
+{
+ struct gl_renderbuffer *rb16;
+
+ rb16 = _mesa_new_renderbuffer(ctx, rb8->Name);
+ if (rb16) {
+ ASSERT(rb8->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb8->_BaseFormat == GL_RGBA);
+
+ _glthread_LOCK_MUTEX(rb8->Mutex);
+ rb8->RefCount++;
+ _glthread_UNLOCK_MUTEX(rb8->Mutex);
+
+ rb16->InternalFormat = rb8->InternalFormat;
+ rb16->_ActualFormat = rb8->_ActualFormat;
+ rb16->_BaseFormat = rb8->_BaseFormat;
+ rb16->DataType = GL_UNSIGNED_SHORT;
+ /* Note: passing through underlying bits/channel */
+ rb16->RedBits = rb8->RedBits;
+ rb16->GreenBits = rb8->GreenBits;
+ rb16->BlueBits = rb8->BlueBits;
+ rb16->AlphaBits = rb8->AlphaBits;
+ rb16->Wrapped = rb8;
+
+ rb16->AllocStorage = AllocStorage_wrapper;
+ rb16->Delete = Delete_wrapper;
+ rb16->GetPointer = GetPointer_wrapper;
+ rb16->GetRow = GetRow_16wrap8;
+ rb16->GetValues = GetValues_16wrap8;
+ rb16->PutRow = PutRow_16wrap8;
+ rb16->PutRowRGB = PutRowRGB_16wrap8;
+ rb16->PutMonoRow = PutMonoRow_16wrap8;
+ rb16->PutValues = PutValues_16wrap8;
+ rb16->PutMonoValues = PutMonoValues_16wrap8;
+ }
+ return rb16;
+}
+
+
+
+
+static void
+GetRow_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(count <= MAX_WIDTH);
+
+ /* get 8bpp values */
+ rb->Wrapped->GetRow(ctx, rb->Wrapped, count, x, y, values8);
+
+ /* convert 8bpp to 32bpp */
+ for (i = 0; i < 4 * count; i++) {
+ values32[i] = UBYTE_TO_FLOAT(values8[i]);
+ }
+}
+
+
+static void
+GetValues_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+
+ rb->Wrapped->GetValues(ctx, rb->Wrapped, count, x, y, values8);
+
+ for (i = 0; i < 4 * count; i++) {
+ values32[i] = UBYTE_TO_FLOAT(values8[i]);
+ }
+}
+
+
+static void
+PutRow_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 4 * count; i++) {
+ UNCLAMPED_FLOAT_TO_UBYTE(values8[i], values32[i]);
+ }
+ rb->Wrapped->PutRow(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutRowRGB_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 3];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 3 * count; i++) {
+ UNCLAMPED_FLOAT_TO_UBYTE(values8[i], values32[i]);
+ }
+ rb->Wrapped->PutRowRGB(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutMonoRow_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ GLubyte value8[4];
+ GLfloat *value32 = (GLfloat *) value;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[0], value32[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[1], value32[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[2], value32[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[3], value32[3]);
+ rb->Wrapped->PutMonoRow(ctx, rb->Wrapped, count, x, y, value8, mask);
+}
+
+
+static void
+PutValues_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ GLubyte values8[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < 4 * count; i++) {
+ UNCLAMPED_FLOAT_TO_UBYTE(values8[i], values32[i]);
+ }
+ rb->Wrapped->PutValues(ctx, rb->Wrapped, count, x, y, values8, mask);
+}
+
+
+static void
+PutMonoValues_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ GLubyte value8[4];
+ GLfloat *value32 = (GLfloat *) value;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_BYTE);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[0], value32[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[1], value32[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[2], value32[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(value8[3], value32[3]);
+ rb->Wrapped->PutMonoValues(ctx, rb->Wrapped, count, x, y, value8, mask);
+}
+
+
+/**
+ * Wrap an 8-bit/channel renderbuffer with a 32-bit/channel
+ * renderbuffer adaptor.
+ */
+struct gl_renderbuffer *
+_mesa_new_renderbuffer_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb8)
+{
+ struct gl_renderbuffer *rb32;
+
+ rb32 = _mesa_new_renderbuffer(ctx, rb8->Name);
+ if (rb32) {
+ ASSERT(rb8->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb8->_BaseFormat == GL_RGBA);
+
+ _glthread_LOCK_MUTEX(rb8->Mutex);
+ rb8->RefCount++;
+ _glthread_UNLOCK_MUTEX(rb8->Mutex);
+
+ rb32->InternalFormat = rb8->InternalFormat;
+ rb32->_ActualFormat = rb8->_ActualFormat;
+ rb32->_BaseFormat = rb8->_BaseFormat;
+ rb32->DataType = GL_FLOAT;
+ /* Note: passing through underlying bits/channel */
+ rb32->RedBits = rb8->RedBits;
+ rb32->GreenBits = rb8->GreenBits;
+ rb32->BlueBits = rb8->BlueBits;
+ rb32->AlphaBits = rb8->AlphaBits;
+ rb32->Wrapped = rb8;
+
+ rb32->AllocStorage = AllocStorage_wrapper;
+ rb32->Delete = Delete_wrapper;
+ rb32->GetPointer = GetPointer_wrapper;
+ rb32->GetRow = GetRow_32wrap8;
+ rb32->GetValues = GetValues_32wrap8;
+ rb32->PutRow = PutRow_32wrap8;
+ rb32->PutRowRGB = PutRowRGB_32wrap8;
+ rb32->PutMonoRow = PutMonoRow_32wrap8;
+ rb32->PutValues = PutValues_32wrap8;
+ rb32->PutMonoValues = PutMonoValues_32wrap8;
+ }
+ return rb32;
+}
+
+
+
+
+static void
+GetRow_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ GLushort values16[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(count <= MAX_WIDTH);
+
+ /* get 16bpp values */
+ rb->Wrapped->GetRow(ctx, rb->Wrapped, count, x, y, values16);
+
+ /* convert 16bpp to 32bpp */
+ for (i = 0; i < 4 * count; i++) {
+ values32[i] = USHORT_TO_FLOAT(values16[i]);
+ }
+}
+
+
+static void
+GetValues_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLushort values16[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+
+ rb->Wrapped->GetValues(ctx, rb->Wrapped, count, x, y, values16);
+
+ for (i = 0; i < 4 * count; i++) {
+ values32[i] = USHORT_TO_FLOAT(values16[i]);
+ }
+}
+
+
+static void
+PutRow_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLushort values16[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < 4 * count; i++) {
+ UNCLAMPED_FLOAT_TO_USHORT(values16[i], values32[i]);
+ }
+ rb->Wrapped->PutRow(ctx, rb->Wrapped, count, x, y, values16, mask);
+}
+
+
+static void
+PutRowRGB_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ GLushort values16[MAX_WIDTH * 3];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < 3 * count; i++) {
+ UNCLAMPED_FLOAT_TO_USHORT(values16[i], values32[i]);
+ }
+ rb->Wrapped->PutRowRGB(ctx, rb->Wrapped, count, x, y, values16, mask);
+}
+
+
+static void
+PutMonoRow_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ GLushort value16[4];
+ GLfloat *value32 = (GLfloat *) value;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[0], value32[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[1], value32[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[2], value32[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[3], value32[3]);
+ rb->Wrapped->PutMonoRow(ctx, rb->Wrapped, count, x, y, value16, mask);
+}
+
+
+static void
+PutValues_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ GLushort values16[MAX_WIDTH * 4];
+ GLfloat *values32 = (GLfloat *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < 4 * count; i++) {
+ UNCLAMPED_FLOAT_TO_USHORT(values16[i], values32[i]);
+ }
+ rb->Wrapped->PutValues(ctx, rb->Wrapped, count, x, y, values16, mask);
+}
+
+
+static void
+PutMonoValues_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ GLushort value16[4];
+ GLfloat *value32 = (GLfloat *) value;
+ ASSERT(rb->DataType == GL_FLOAT);
+ ASSERT(rb->Wrapped->DataType == GL_UNSIGNED_SHORT);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[0], value32[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[1], value32[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[2], value32[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(value16[3], value32[3]);
+ rb->Wrapped->PutMonoValues(ctx, rb->Wrapped, count, x, y, value16, mask);
+}
+
+
+/**
+ * Wrap an 16-bit/channel renderbuffer with a 32-bit/channel
+ * renderbuffer adaptor.
+ */
+struct gl_renderbuffer *
+_mesa_new_renderbuffer_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb16)
+{
+ struct gl_renderbuffer *rb32;
+
+ rb32 = _mesa_new_renderbuffer(ctx, rb16->Name);
+ if (rb32) {
+ ASSERT(rb16->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb16->_BaseFormat == GL_RGBA);
+
+ _glthread_LOCK_MUTEX(rb16->Mutex);
+ rb16->RefCount++;
+ _glthread_UNLOCK_MUTEX(rb16->Mutex);
+
+ rb32->InternalFormat = rb16->InternalFormat;
+ rb32->_ActualFormat = rb16->_ActualFormat;
+ rb32->_BaseFormat = rb16->_BaseFormat;
+ rb32->DataType = GL_FLOAT;
+ /* Note: passing through underlying bits/channel */
+ rb32->RedBits = rb16->RedBits;
+ rb32->GreenBits = rb16->GreenBits;
+ rb32->BlueBits = rb16->BlueBits;
+ rb32->AlphaBits = rb16->AlphaBits;
+ rb32->Wrapped = rb16;
+
+ rb32->AllocStorage = AllocStorage_wrapper;
+ rb32->Delete = Delete_wrapper;
+ rb32->GetPointer = GetPointer_wrapper;
+ rb32->GetRow = GetRow_32wrap16;
+ rb32->GetValues = GetValues_32wrap16;
+ rb32->PutRow = PutRow_32wrap16;
+ rb32->PutRowRGB = PutRowRGB_32wrap16;
+ rb32->PutMonoRow = PutMonoRow_32wrap16;
+ rb32->PutValues = PutValues_32wrap16;
+ rb32->PutMonoValues = PutMonoValues_32wrap16;
+ }
+ return rb32;
+}
diff --git a/mesalib/src/mesa/main/rbadaptors.h b/mesalib/src/mesa/main/rbadaptors.h
new file mode 100644
index 000000000..1d45b287d
--- /dev/null
+++ b/mesalib/src/mesa/main/rbadaptors.h
@@ -0,0 +1,40 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 RBADAPTORS_H
+#define RBADAPTORS_H
+
+
+extern struct gl_renderbuffer *
+_mesa_new_renderbuffer_16wrap8(GLcontext *ctx, struct gl_renderbuffer *rb8);
+
+extern struct gl_renderbuffer *
+_mesa_new_renderbuffer_32wrap8(GLcontext *ctx, struct gl_renderbuffer *rb8);
+
+extern struct gl_renderbuffer *
+_mesa_new_renderbuffer_32wrap16(GLcontext *ctx, struct gl_renderbuffer *rb16);
+
+
+#endif /* RBADAPTORS_H */
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c
new file mode 100644
index 000000000..feea1d375
--- /dev/null
+++ b/mesalib/src/mesa/main/readpix.c
@@ -0,0 +1,210 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "readpix.h"
+#include "framebuffer.h"
+#include "image.h"
+#include "state.h"
+
+
+/**
+ * Do error checking of the format/type parameters to glReadPixels and
+ * glDrawPixels.
+ * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
+ * for ReadPixels.
+ * \return GL_TRUE if error detected, GL_FALSE if no errors
+ */
+GLboolean
+_mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
+ GLboolean drawing)
+{
+ const char *readDraw = drawing ? "Draw" : "Read";
+ const GLboolean reading = !drawing;
+
+ /* state validation should have already been done */
+ ASSERT(ctx->NewState == 0x0);
+
+ if (ctx->Extensions.EXT_packed_depth_stencil
+ && type == GL_UNSIGNED_INT_24_8_EXT
+ && format != GL_DEPTH_STENCIL_EXT) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* basic combinations test */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "gl%sPixels(format or type)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* additional checks */
+ switch (format) {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ if (drawing) {
+ if (!ctx->DrawBuffer->Visual.rgbMode) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing RGB pixels into color index buffer)");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ }
+ break;
+ case GL_COLOR_INDEX:
+ if (drawing) {
+ if (ctx->DrawBuffer->Visual.rgbMode &&
+ (ctx->PixelMaps.ItoR.Size == 0 ||
+ ctx->PixelMaps.ItoG.Size == 0 ||
+ ctx->PixelMaps.ItoB.Size == 0)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing color index pixels into RGB buffer)");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!ctx->Extensions.EXT_packed_depth_stencil ||
+ type != GL_UNSIGNED_INT_24_8_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
+ return GL_TRUE;
+ }
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth or stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ default:
+ /* this should have been caught in _mesa_is_legal_format_type() */
+ _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
+ return GL_TRUE;
+ }
+
+ /* no errors */
+ return GL_FALSE;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glReadPixels(width=%d height=%d)", width, height );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
+ /* found an error */
+ return;
+ }
+
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glReadPixels(incomplete framebuffer)" );
+ return;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
+ return;
+ }
+
+ if (width == 0 || height == 0)
+ return; /* nothing to do */
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(invalid PBO access)");
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+ return;
+ }
+ }
+
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, pixels);
+}
diff --git a/mesalib/src/mesa/main/readpix.h b/mesalib/src/mesa/main/readpix.h
new file mode 100644
index 000000000..1bf02fb8e
--- /dev/null
+++ b/mesalib/src/mesa/main/readpix.h
@@ -0,0 +1,42 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 READPIXELS_H
+#define READPIXELS_H
+
+
+#include "main/mtypes.h"
+
+
+extern GLboolean
+_mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
+ GLboolean drawing);
+
+extern void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels );
+
+
+#endif
diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c
new file mode 100644
index 000000000..38be8266e
--- /dev/null
+++ b/mesalib/src/mesa/main/renderbuffer.c
@@ -0,0 +1,2209 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/**
+ * Functions for allocating/managing renderbuffers.
+ * Also, routines for reading/writing software-based renderbuffer data as
+ * ubytes, ushorts, uints, etc.
+ *
+ * The 'alpha8' renderbuffer is interesting. It's used to add a software-based
+ * alpha channel to RGB renderbuffers. This is done by wrapping the RGB
+ * renderbuffer with the alpha renderbuffer. We can do this because of the
+ * OO-nature of renderbuffers.
+ *
+ * Down the road we'll use this for run-time support of 8, 16 and 32-bit
+ * color channels. For example, Mesa may use 32-bit/float color channels
+ * internally (swrast) and use wrapper renderbuffers to convert 32-bit
+ * values down to 16 or 8-bit values for whatever kind of framebuffer we have.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "mtypes.h"
+#include "fbobject.h"
+#include "renderbuffer.h"
+
+#include "rbadaptors.h"
+
+
+/* 32-bit color index format. Not a public format. */
+#define COLOR_INDEX32 0x424243
+
+
+/*
+ * Routines for get/put values in common buffer formats follow.
+ * Someday add support for arbitrary row stride to make them more
+ * flexible.
+ */
+
+/**********************************************************************
+ * Functions for buffers of 1 X GLubyte values.
+ * Typically stencil.
+ */
+
+static void *
+get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ if (!rb->Data)
+ return NULL;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ /* Can't assert _ActualFormat since these funcs may be used for serveral
+ * different formats (GL_ALPHA8, GL_STENCIL_INDEX8, etc).
+ */
+ return (GLubyte *) rb->Data + y * rb->Width + x;
+}
+
+
+static void
+get_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ _mesa_memcpy(values, src, count * sizeof(GLubyte));
+}
+
+
+static void
+get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLubyte *dst = (GLubyte *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+ dst[i] = *src;
+ }
+}
+
+
+static void
+put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = src[i];
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, values, count * sizeof(GLubyte));
+ }
+}
+
+
+static void
+put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const GLubyte val = *((const GLubyte *) value);
+ GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = val;
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ dst[i] = val;
+ }
+ }
+}
+
+
+static void
+put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte *mask)
+{
+ const GLubyte *src = (const GLubyte *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = src[i];
+ }
+ }
+}
+
+
+static void
+put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ const GLubyte val = *((const GLubyte *) value);
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = val;
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Functions for buffers of 1 X GLushort values.
+ * Typically depth/Z.
+ */
+
+static void *
+get_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ if (!rb->Data)
+ return NULL;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ ASSERT(rb->Width > 0);
+ return (GLushort *) rb->Data + y * rb->Width + x;
+}
+
+
+static void
+get_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const void *src = rb->GetPointer(ctx, rb, x, y);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ _mesa_memcpy(values, src, count * sizeof(GLushort));
+}
+
+
+static void
+get_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLushort *dst = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < count; i++) {
+ const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
+ dst[i] = *src;
+ }
+}
+
+
+static void
+put_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLushort *src = (const GLushort *) values;
+ GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = src[i];
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, count * sizeof(GLushort));
+ }
+}
+
+
+static void
+put_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const GLushort val = *((const GLushort *) value);
+ GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = val;
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ dst[i] = val;
+ }
+ }
+}
+
+
+static void
+put_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ const GLushort *src = (const GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = src[i];
+ }
+ }
+}
+
+
+static void
+put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ const GLushort val = *((const GLushort *) value);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = val;
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = val;
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Functions for buffers of 1 X GLuint values.
+ * Typically depth/Z or color index.
+ */
+
+static void *
+get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ if (!rb->Data)
+ return NULL;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ return (GLuint *) rb->Data + y * rb->Width + x;
+}
+
+
+static void
+get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const void *src = rb->GetPointer(ctx, rb, x, y);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ _mesa_memcpy(values, src, count * sizeof(GLuint));
+}
+
+
+static void
+get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLuint *dst = (GLuint *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ for (i = 0; i < count; i++) {
+ const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
+ dst[i] = *src;
+ }
+}
+
+
+static void
+put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLuint *src = (const GLuint *) values;
+ GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = src[i];
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, count * sizeof(GLuint));
+ }
+}
+
+
+static void
+put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const GLuint val = *((const GLuint *) value);
+ GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = val;
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ dst[i] = val;
+ }
+ }
+}
+
+
+static void
+put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ const GLuint *src = (const GLuint *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = src[i];
+ }
+ }
+}
+
+
+static void
+put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *value,
+ const GLubyte *mask)
+{
+ const GLuint val = *((const GLuint *) value);
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT ||
+ rb->DataType == GL_UNSIGNED_INT_24_8_EXT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i];
+ *dst = val;
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Functions for buffers of 3 X GLubyte (or GLbyte) values.
+ * Typically color buffers.
+ * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming
+ * alpha values and return 255 for outgoing alpha values.
+ */
+
+static void *
+get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ /* No direct access since this buffer is RGB but caller will be
+ * treating it as if it were RGBA.
+ */
+ return NULL;
+}
+
+
+static void
+get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x);
+ GLubyte *dst = (GLubyte *) values;
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ dst[i * 4 + 0] = src[i * 3 + 0];
+ dst[i * 4 + 1] = src[i * 3 + 1];
+ dst[i * 4 + 2] = src[i * 3 + 2];
+ dst[i * 4 + 3] = 255;
+ }
+}
+
+
+static void
+get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLubyte *dst = (GLubyte *) values;
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ const GLubyte *src
+ = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
+ dst[i * 4 + 0] = src[0];
+ dst[i * 4 + 1] = src[1];
+ dst[i * 4 + 2] = src[2];
+ dst[i * 4 + 3] = 255;
+ }
+}
+
+
+static void
+put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ /* note: incoming values are RGB+A! */
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i * 3 + 0] = src[i * 4 + 0];
+ dst[i * 3 + 1] = src[i * 4 + 1];
+ dst[i * 3 + 2] = src[i * 4 + 2];
+ }
+ }
+}
+
+
+static void
+put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ /* note: incoming values are RGB+A! */
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i * 3 + 0] = src[i * 3 + 0];
+ dst[i * 3 + 1] = src[i * 3 + 1];
+ dst[i * 3 + 2] = src[i * 3 + 2];
+ }
+ }
+}
+
+
+static void
+put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ /* note: incoming value is RGB+A! */
+ const GLubyte val0 = ((const GLubyte *) value)[0];
+ const GLubyte val1 = ((const GLubyte *) value)[1];
+ const GLubyte val2 = ((const GLubyte *) value)[2];
+ GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x);
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ if (!mask && val0 == val1 && val1 == val2) {
+ /* optimized case */
+ _mesa_memset(dst, val0, 3 * count);
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i * 3 + 0] = val0;
+ dst[i * 3 + 1] = val1;
+ dst[i * 3 + 2] = val2;
+ }
+ }
+ }
+}
+
+
+static void
+put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ /* note: incoming values are RGB+A! */
+ const GLubyte *src = (const GLubyte *) values;
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
+ dst[0] = src[i * 4 + 0];
+ dst[1] = src[i * 4 + 1];
+ dst[2] = src[i * 4 + 2];
+ }
+ }
+}
+
+
+static void
+put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ /* note: incoming value is RGB+A! */
+ const GLubyte val0 = ((const GLubyte *) value)[0];
+ const GLubyte val1 = ((const GLubyte *) value)[1];
+ const GLubyte val2 = ((const GLubyte *) value)[2];
+ GLuint i;
+ ASSERT(rb->_ActualFormat == GL_RGB8);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]);
+ dst[0] = val0;
+ dst[1] = val1;
+ dst[2] = val2;
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Functions for buffers of 4 X GLubyte (or GLbyte) values.
+ * Typically color buffers.
+ */
+
+static void *
+get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ if (!rb->Data)
+ return NULL;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ return (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
+}
+
+
+static void
+get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const GLubyte *src = (const GLubyte *) rb->Data + 4 * (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ _mesa_memcpy(values, src, 4 * count * sizeof(GLubyte));
+}
+
+
+static void
+get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ /* treat 4*GLubyte as 1*GLuint */
+ GLuint *dst = (GLuint *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ for (i = 0; i < count; i++) {
+ const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
+ dst[i] = *src;
+ }
+}
+
+
+static void
+put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ /* treat 4*GLubyte as 1*GLuint */
+ const GLuint *src = (const GLuint *) values;
+ GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = src[i];
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte));
+ }
+}
+
+
+static void
+put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ /* Store RGB values in RGBA buffer */
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x);
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i * 4 + 0] = src[i * 3 + 0];
+ dst[i * 4 + 1] = src[i * 3 + 1];
+ dst[i * 4 + 2] = src[i * 3 + 2];
+ dst[i * 4 + 3] = 0xff;
+ }
+ }
+}
+
+
+static void
+put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ /* treat 4*GLubyte as 1*GLuint */
+ const GLuint val = *((const GLuint *) value);
+ GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ if (!mask && val == 0) {
+ /* common case */
+ _mesa_bzero(dst, count * 4 * sizeof(GLubyte));
+ }
+ else {
+ /* general case */
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = val;
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ dst[i] = val;
+ }
+ }
+ }
+}
+
+
+static void
+put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ /* treat 4*GLubyte as 1*GLuint */
+ const GLuint *src = (const GLuint *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
+ *dst = src[i];
+ }
+ }
+}
+
+
+static void
+put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ /* treat 4*GLubyte as 1*GLuint */
+ const GLuint val = *((const GLuint *) value);
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ ASSERT(rb->_ActualFormat == GL_RGBA8);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]);
+ *dst = val;
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Functions for buffers of 4 X GLushort (or GLshort) values.
+ * Typically accum buffer.
+ */
+
+static void *
+get_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint x, GLint y)
+{
+ if (!rb->Data)
+ return NULL;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ return (GLushort *) rb->Data + 4 * (y * rb->Width + x);
+}
+
+
+static void
+get_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ _mesa_memcpy(values, src, 4 * count * sizeof(GLshort));
+}
+
+
+static void
+get_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLushort *dst = (GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ for (i = 0; i < count; i++) {
+ const GLushort *src
+ = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
+ dst[i] = *src;
+ }
+}
+
+
+static void
+put_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLushort *src = (const GLushort *) values;
+ GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i * 4 + 0] = src[i * 4 + 0];
+ dst[i * 4 + 1] = src[i * 4 + 1];
+ dst[i * 4 + 2] = src[i * 4 + 2];
+ dst[i * 4 + 3] = src[i * 4 + 3];
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
+ }
+}
+
+
+static void
+put_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ /* Put RGB values in RGBA buffer */
+ const GLushort *src = (const GLushort *) values;
+ GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i * 4 + 0] = src[i * 3 + 0];
+ dst[i * 4 + 1] = src[i * 3 + 1];
+ dst[i * 4 + 2] = src[i * 3 + 2];
+ dst[i * 4 + 3] = 0xffff;
+ }
+ }
+ }
+ else {
+ _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort));
+ }
+}
+
+
+static void
+put_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const GLushort val0 = ((const GLushort *) value)[0];
+ const GLushort val1 = ((const GLushort *) value)[1];
+ const GLushort val2 = ((const GLushort *) value)[2];
+ const GLushort val3 = ((const GLushort *) value)[3];
+ GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) {
+ /* common case for clearing accum buffer */
+ _mesa_bzero(dst, count * 4 * sizeof(GLushort));
+ }
+ else {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i * 4 + 0] = val0;
+ dst[i * 4 + 1] = val1;
+ dst[i * 4 + 2] = val2;
+ dst[i * 4 + 3] = val3;
+ }
+ }
+ }
+}
+
+
+static void
+put_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ const GLushort *src = (const GLushort *) values;
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
+ dst[0] = src[i * 4 + 0];
+ dst[1] = src[i * 4 + 1];
+ dst[2] = src[i * 4 + 2];
+ dst[3] = src[i * 4 + 3];
+ }
+ }
+}
+
+
+static void
+put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ const GLushort val0 = ((const GLushort *) value)[0];
+ const GLushort val1 = ((const GLushort *) value)[1];
+ const GLushort val2 = ((const GLushort *) value)[2];
+ const GLushort val3 = ((const GLushort *) value)[3];
+ GLuint i;
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]);
+ dst[0] = val0;
+ dst[1] = val1;
+ dst[2] = val2;
+ dst[3] = val3;
+ }
+ }
+}
+
+
+
+/**
+ * This is a software fallback for the gl_renderbuffer->AllocStorage
+ * function.
+ * Device drivers will typically override this function for the buffers
+ * which it manages (typically color buffers, Z and stencil).
+ * Other buffers (like software accumulation and aux buffers) which the driver
+ * doesn't manage can be handled with this function.
+ *
+ * This one multi-purpose function can allocate stencil, depth, accum, color
+ * or color-index buffers!
+ *
+ * This function also plugs in the appropriate GetPointer, Get/PutRow and
+ * Get/PutValues functions.
+ */
+GLboolean
+_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height)
+{
+ GLuint pixelSize;
+
+ /* first clear these fields */
+ rb->RedBits =
+ rb->GreenBits =
+ rb->BlueBits =
+ rb->AlphaBits =
+ rb->IndexBits =
+ rb->DepthBits =
+ rb->StencilBits = 0;
+
+ switch (internalFormat) {
+ 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:
+ rb->_ActualFormat = GL_RGB8;
+ rb->_BaseFormat = GL_RGB;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->GetPointer = get_pointer_ubyte3;
+ rb->GetRow = get_row_ubyte3;
+ rb->GetValues = get_values_ubyte3;
+ rb->PutRow = put_row_ubyte3;
+ rb->PutRowRGB = put_row_rgb_ubyte3;
+ rb->PutMonoRow = put_mono_row_ubyte3;
+ rb->PutValues = put_values_ubyte3;
+ rb->PutMonoValues = put_mono_values_ubyte3;
+ rb->RedBits = 8 * sizeof(GLubyte);
+ rb->GreenBits = 8 * sizeof(GLubyte);
+ rb->BlueBits = 8 * sizeof(GLubyte);
+ rb->AlphaBits = 0;
+ pixelSize = 3 * sizeof(GLubyte);
+ break;
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ rb->_ActualFormat = GL_RGBA8;
+ rb->_BaseFormat = GL_RGBA;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->GetPointer = get_pointer_ubyte4;
+ rb->GetRow = get_row_ubyte4;
+ rb->GetValues = get_values_ubyte4;
+ rb->PutRow = put_row_ubyte4;
+ rb->PutRowRGB = put_row_rgb_ubyte4;
+ rb->PutMonoRow = put_mono_row_ubyte4;
+ rb->PutValues = put_values_ubyte4;
+ rb->PutMonoValues = put_mono_values_ubyte4;
+ rb->RedBits = 8 * sizeof(GLubyte);
+ rb->GreenBits = 8 * sizeof(GLubyte);
+ rb->BlueBits = 8 * sizeof(GLubyte);
+ rb->AlphaBits = 8 * sizeof(GLubyte);
+ pixelSize = 4 * sizeof(GLubyte);
+ break;
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ rb->_ActualFormat = GL_RGBA16;
+ rb->_BaseFormat = GL_RGBA;
+ rb->DataType = GL_UNSIGNED_SHORT;
+ rb->GetPointer = get_pointer_ushort4;
+ rb->GetRow = get_row_ushort4;
+ rb->GetValues = get_values_ushort4;
+ rb->PutRow = put_row_ushort4;
+ rb->PutRowRGB = put_row_rgb_ushort4;
+ rb->PutMonoRow = put_mono_row_ushort4;
+ rb->PutValues = put_values_ushort4;
+ rb->PutMonoValues = put_mono_values_ushort4;
+ rb->RedBits = 8 * sizeof(GLushort);
+ rb->GreenBits = 8 * sizeof(GLushort);
+ rb->BlueBits = 8 * sizeof(GLushort);
+ rb->AlphaBits = 8 * sizeof(GLushort);
+ pixelSize = 4 * sizeof(GLushort);
+ break;
+#if 00
+ case GL_ALPHA8:
+ rb->_ActualFormat = GL_ALPHA8;
+ rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->GetPointer = get_pointer_alpha8;
+ rb->GetRow = get_row_alpha8;
+ rb->GetValues = get_values_alpha8;
+ rb->PutRow = put_row_alpha8;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_alpha8;
+ rb->PutValues = put_values_alpha8;
+ rb->PutMonoValues = put_mono_values_alpha8;
+ rb->RedBits = 0; /*red*/
+ rb->GreenBits = 0; /*green*/
+ rb->BlueBits = 0; /*blue*/
+ rb->AlphaBits = 8 * sizeof(GLubyte);
+ pixelSize = sizeof(GLubyte);
+ break;
+#endif
+ case GL_STENCIL_INDEX:
+ case GL_STENCIL_INDEX1_EXT:
+ case GL_STENCIL_INDEX4_EXT:
+ case GL_STENCIL_INDEX8_EXT:
+ rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
+ rb->_BaseFormat = GL_STENCIL_INDEX;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->GetPointer = get_pointer_ubyte;
+ rb->GetRow = get_row_ubyte;
+ rb->GetValues = get_values_ubyte;
+ rb->PutRow = put_row_ubyte;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_ubyte;
+ rb->PutValues = put_values_ubyte;
+ rb->PutMonoValues = put_mono_values_ubyte;
+ rb->StencilBits = 8 * sizeof(GLubyte);
+ pixelSize = sizeof(GLubyte);
+ break;
+ case GL_STENCIL_INDEX16_EXT:
+ rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
+ rb->_BaseFormat = GL_STENCIL_INDEX;
+ rb->DataType = GL_UNSIGNED_SHORT;
+ rb->GetPointer = get_pointer_ushort;
+ rb->GetRow = get_row_ushort;
+ rb->GetValues = get_values_ushort;
+ rb->PutRow = put_row_ushort;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_ushort;
+ rb->PutValues = put_values_ushort;
+ rb->PutMonoValues = put_mono_values_ushort;
+ rb->StencilBits = 8 * sizeof(GLushort);
+ pixelSize = sizeof(GLushort);
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ rb->_ActualFormat = GL_DEPTH_COMPONENT16;
+ rb->_BaseFormat = GL_DEPTH_COMPONENT;
+ rb->DataType = GL_UNSIGNED_SHORT;
+ rb->GetPointer = get_pointer_ushort;
+ rb->GetRow = get_row_ushort;
+ rb->GetValues = get_values_ushort;
+ rb->PutRow = put_row_ushort;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_ushort;
+ rb->PutValues = put_values_ushort;
+ rb->PutMonoValues = put_mono_values_ushort;
+ rb->DepthBits = 8 * sizeof(GLushort);
+ pixelSize = sizeof(GLushort);
+ break;
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ rb->_BaseFormat = GL_DEPTH_COMPONENT;
+ rb->DataType = GL_UNSIGNED_INT;
+ rb->GetPointer = get_pointer_uint;
+ rb->GetRow = get_row_uint;
+ rb->GetValues = get_values_uint;
+ rb->PutRow = put_row_uint;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_uint;
+ rb->PutValues = put_values_uint;
+ rb->PutMonoValues = put_mono_values_uint;
+ if (internalFormat == GL_DEPTH_COMPONENT24) {
+ rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+ rb->DepthBits = 24;
+ }
+ else {
+ rb->_ActualFormat = GL_DEPTH_COMPONENT32;
+ rb->DepthBits = 32;
+ }
+ pixelSize = sizeof(GLuint);
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ rb->_BaseFormat = GL_DEPTH_STENCIL_EXT;
+ rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+ rb->GetPointer = get_pointer_uint;
+ rb->GetRow = get_row_uint;
+ rb->GetValues = get_values_uint;
+ rb->PutRow = put_row_uint;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_uint;
+ rb->PutValues = put_values_uint;
+ rb->PutMonoValues = put_mono_values_uint;
+ rb->DepthBits = 24;
+ rb->StencilBits = 8;
+ pixelSize = sizeof(GLuint);
+ break;
+ case GL_COLOR_INDEX8_EXT:
+ rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
+ rb->_BaseFormat = GL_COLOR_INDEX;
+ rb->DataType = GL_UNSIGNED_BYTE;
+ rb->GetPointer = get_pointer_ubyte;
+ rb->GetRow = get_row_ubyte;
+ rb->GetValues = get_values_ubyte;
+ rb->PutRow = put_row_ubyte;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_ubyte;
+ rb->PutValues = put_values_ubyte;
+ rb->PutMonoValues = put_mono_values_ubyte;
+ rb->IndexBits = 8 * sizeof(GLubyte);
+ pixelSize = sizeof(GLubyte);
+ break;
+ case GL_COLOR_INDEX16_EXT:
+ rb->_ActualFormat = GL_COLOR_INDEX16_EXT;
+ rb->_BaseFormat = GL_COLOR_INDEX;
+ rb->DataType = GL_UNSIGNED_SHORT;
+ rb->GetPointer = get_pointer_ushort;
+ rb->GetRow = get_row_ushort;
+ rb->GetValues = get_values_ushort;
+ rb->PutRow = put_row_ushort;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_ushort;
+ rb->PutValues = put_values_ushort;
+ rb->PutMonoValues = put_mono_values_ushort;
+ rb->IndexBits = 8 * sizeof(GLushort);
+ pixelSize = sizeof(GLushort);
+ break;
+ case COLOR_INDEX32:
+ rb->_ActualFormat = COLOR_INDEX32;
+ rb->_BaseFormat = GL_COLOR_INDEX;
+ rb->DataType = GL_UNSIGNED_INT;
+ rb->GetPointer = get_pointer_uint;
+ rb->GetRow = get_row_uint;
+ rb->GetValues = get_values_uint;
+ rb->PutRow = put_row_uint;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = put_mono_row_uint;
+ rb->PutValues = put_values_uint;
+ rb->PutMonoValues = put_mono_values_uint;
+ rb->IndexBits = 8 * sizeof(GLuint);
+ pixelSize = sizeof(GLuint);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad internalFormat in _mesa_soft_renderbuffer_storage");
+ return GL_FALSE;
+ }
+
+ ASSERT(rb->DataType);
+ ASSERT(rb->GetPointer);
+ ASSERT(rb->GetRow);
+ ASSERT(rb->GetValues);
+ ASSERT(rb->PutRow);
+ ASSERT(rb->PutMonoRow);
+ ASSERT(rb->PutValues);
+ ASSERT(rb->PutMonoValues);
+
+ /* free old buffer storage */
+ if (rb->Data) {
+ _mesa_free(rb->Data);
+ rb->Data = NULL;
+ }
+
+ if (width > 0 && height > 0) {
+ /* allocate new buffer storage */
+ rb->Data = malloc(width * height * pixelSize);
+
+ if (rb->Data == NULL) {
+ rb->Width = 0;
+ rb->Height = 0;
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "software renderbuffer allocation (%d x %d x %d)",
+ width, height, pixelSize);
+ return GL_FALSE;
+ }
+ }
+
+ rb->Width = width;
+ rb->Height = height;
+
+ return GL_TRUE;
+}
+
+
+
+/**********************************************************************/
+/**********************************************************************/
+/**********************************************************************/
+
+
+/**
+ * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha
+ * buffer wrapper around an existing RGB renderbuffer (hw or sw).
+ *
+ * When PutRow is called (for example), we store the alpha values in
+ * this buffer, then pass on the PutRow call to the wrapped RGB
+ * buffer.
+ */
+
+
+static GLboolean
+alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
+ GLenum internalFormat, GLuint width, GLuint height)
+{
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->_ActualFormat == GL_ALPHA8);
+
+ /* first, pass the call to the wrapped RGB buffer */
+ if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat,
+ width, height)) {
+ return GL_FALSE;
+ }
+
+ /* next, resize my alpha buffer */
+ if (arb->Data) {
+ _mesa_free(arb->Data);
+ }
+
+ arb->Data = _mesa_malloc(width * height * sizeof(GLubyte));
+ if (arb->Data == NULL) {
+ arb->Width = 0;
+ arb->Height = 0;
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation");
+ return GL_FALSE;
+ }
+
+ arb->Width = width;
+ arb->Height = height;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer.
+ */
+static void
+delete_renderbuffer_alpha8(struct gl_renderbuffer *arb)
+{
+ if (arb->Data) {
+ _mesa_free(arb->Data);
+ }
+ ASSERT(arb->Wrapped);
+ ASSERT(arb != arb->Wrapped);
+ arb->Wrapped->Delete(arb->Wrapped);
+ arb->Wrapped = NULL;
+ _mesa_free(arb);
+}
+
+
+static void *
+get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
+ GLint x, GLint y)
+{
+ return NULL; /* don't allow direct access! */
+}
+
+
+static void
+get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ /* NOTE: 'values' is RGBA format! */
+ const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x;
+ GLubyte *dst = (GLubyte *) values;
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values);
+ /* second, fill in alpha values from this buffer! */
+ for (i = 0; i < count; i++) {
+ dst[i * 4 + 3] = src[i];
+ }
+}
+
+
+static void
+get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ GLubyte *dst = (GLubyte *) values;
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values);
+ /* second, fill in alpha values from this buffer! */
+ for (i = 0; i < count; i++) {
+ const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
+ dst[i * 4 + 3] = *src;
+ }
+}
+
+
+static void
+put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask);
+ /* second, store alpha in our buffer */
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = src[i * 4 + 3];
+ }
+ }
+}
+
+
+static void
+put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const GLubyte *src = (const GLubyte *) values;
+ GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask);
+ /* second, store alpha in our buffer */
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ dst[i] = src[i * 4 + 3];
+ }
+ }
+}
+
+
+static void
+put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const GLubyte val = ((const GLubyte *) value)[3];
+ GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask);
+ /* second, store alpha in our buffer */
+ if (mask) {
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ dst[i] = val;
+ }
+ }
+ }
+ else {
+ _mesa_memset(dst, val, count);
+ }
+}
+
+
+static void
+put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count,
+ const GLint x[], const GLint y[],
+ const void *values, const GLubyte *mask)
+{
+ const GLubyte *src = (const GLubyte *) values;
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask);
+ /* second, store alpha in our buffer */
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
+ *dst = src[i * 4 + 3];
+ }
+ }
+}
+
+
+static void
+put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ const GLubyte val = ((const GLubyte *) value)[3];
+ GLuint i;
+ ASSERT(arb != arb->Wrapped);
+ ASSERT(arb->DataType == GL_UNSIGNED_BYTE);
+ /* first, pass the call to the wrapped RGB buffer */
+ arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask);
+ /* second, store alpha in our buffer */
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i];
+ *dst = val;
+ }
+ }
+}
+
+
+static void
+copy_buffer_alpha8(struct gl_renderbuffer* dst, struct gl_renderbuffer* src)
+{
+ ASSERT(dst->_ActualFormat == GL_ALPHA8);
+ ASSERT(src->_ActualFormat == GL_ALPHA8);
+ ASSERT(dst->Width == src->Width);
+ ASSERT(dst->Height == src->Height);
+
+ _mesa_memcpy(dst->Data, src->Data, dst->Width * dst->Height * sizeof(GLubyte));
+}
+
+
+/**********************************************************************/
+/**********************************************************************/
+/**********************************************************************/
+
+
+/**
+ * Default GetPointer routine. Always return NULL to indicate that
+ * direct buffer access is not supported.
+ */
+static void *
+nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y)
+{
+ return NULL;
+}
+
+
+/**
+ * Initialize the fields of a gl_renderbuffer to default values.
+ */
+void
+_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
+{
+ _glthread_INIT_MUTEX(rb->Mutex);
+
+ rb->Magic = RB_MAGIC;
+ rb->ClassID = 0;
+ rb->Name = name;
+ rb->RefCount = 0;
+ rb->Delete = _mesa_delete_renderbuffer;
+
+ /* The rest of these should be set later by the caller of this function or
+ * the AllocStorage method:
+ */
+ rb->AllocStorage = NULL;
+
+ rb->Width = 0;
+ rb->Height = 0;
+ rb->InternalFormat = GL_NONE;
+ rb->_ActualFormat = GL_NONE;
+ rb->_BaseFormat = GL_NONE;
+
+ rb->ComponentType = GL_UNSIGNED_NORMALIZED; /* ARB_fbo */
+ rb->ColorEncoding = GL_LINEAR; /* ARB_fbo */
+
+ rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = 0;
+ rb->IndexBits = 0;
+ rb->DepthBits = 0;
+ rb->StencilBits = 0;
+
+ rb->DataType = GL_NONE;
+ rb->Data = NULL;
+
+ /* Point back to ourself so that we don't have to check for Wrapped==NULL
+ * all over the drivers.
+ */
+ rb->Wrapped = rb;
+
+ rb->GetPointer = nop_get_pointer;
+ rb->GetRow = NULL;
+ rb->GetValues = NULL;
+ rb->PutRow = NULL;
+ rb->PutRowRGB = NULL;
+ rb->PutMonoRow = NULL;
+ rb->PutValues = NULL;
+ rb->PutMonoValues = NULL;
+}
+
+
+/**
+ * Allocate a new gl_renderbuffer object. This can be used for user-created
+ * renderbuffers or window-system renderbuffers.
+ */
+struct gl_renderbuffer *
+_mesa_new_renderbuffer(GLcontext *ctx, GLuint name)
+{
+ struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
+ if (rb) {
+ _mesa_init_renderbuffer(rb, name);
+ }
+ return rb;
+}
+
+
+/**
+ * Delete a gl_framebuffer.
+ * This is the default function for renderbuffer->Delete().
+ */
+void
+_mesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ if (rb->Data) {
+ _mesa_free(rb->Data);
+ }
+ _mesa_free(rb);
+}
+
+
+/**
+ * Allocate a software-based renderbuffer. This is called via the
+ * ctx->Driver.NewRenderbuffer() function when the user creates a new
+ * renderbuffer.
+ * This would not be used for hardware-based renderbuffers.
+ */
+struct gl_renderbuffer *
+_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name)
+{
+ struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
+ if (rb) {
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ /* Normally, one would setup the PutRow, GetRow, etc functions here.
+ * But we're doing that in the _mesa_soft_renderbuffer_storage() function
+ * instead.
+ */
+ }
+ return rb;
+}
+
+
+/**
+ * Add software-based color renderbuffers to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint rgbBits, GLuint alphaBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight)
+{
+ GLuint b;
+
+ if (rgbBits > 16 || alphaBits > 16) {
+ _mesa_problem(ctx,
+ "Unsupported bit depth in _mesa_add_color_renderbuffers");
+ return GL_FALSE;
+ }
+
+ assert(MAX_COLOR_ATTACHMENTS >= 4);
+
+ for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
+ struct gl_renderbuffer *rb;
+
+ if (b == BUFFER_FRONT_LEFT && !frontLeft)
+ continue;
+ else if (b == BUFFER_BACK_LEFT && !backLeft)
+ continue;
+ else if (b == BUFFER_FRONT_RIGHT && !frontRight)
+ continue;
+ else if (b == BUFFER_BACK_RIGHT && !backRight)
+ continue;
+
+ assert(fb->Attachment[b].Renderbuffer == NULL);
+
+ rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
+ return GL_FALSE;
+ }
+
+ if (rgbBits <= 8) {
+ if (alphaBits)
+ rb->_ActualFormat = GL_RGBA8;
+ else
+ rb->_ActualFormat = GL_RGB8;
+ }
+ else {
+ assert(rgbBits <= 16);
+ if (alphaBits)
+ rb->_ActualFormat = GL_RGBA16;
+ else
+ rb->_ActualFormat = GL_RGBA16; /* don't really have RGB16 yet */
+ }
+ rb->InternalFormat = rb->_ActualFormat;
+
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, b, rb);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Add software-based color index renderbuffers to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint indexBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight)
+{
+ GLuint b;
+
+ if (indexBits > 8) {
+ _mesa_problem(ctx,
+ "Unsupported bit depth in _mesa_add_color_index_renderbuffers");
+ return GL_FALSE;
+ }
+
+ assert(MAX_COLOR_ATTACHMENTS >= 4);
+
+ for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
+ struct gl_renderbuffer *rb;
+
+ if (b == BUFFER_FRONT_LEFT && !frontLeft)
+ continue;
+ else if (b == BUFFER_BACK_LEFT && !backLeft)
+ continue;
+ else if (b == BUFFER_FRONT_RIGHT && !frontRight)
+ continue;
+ else if (b == BUFFER_BACK_RIGHT && !backRight)
+ continue;
+
+ assert(fb->Attachment[b].Renderbuffer == NULL);
+
+ rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer");
+ return GL_FALSE;
+ }
+
+ if (indexBits <= 8) {
+ /* only support GLuint for now */
+ /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/
+ rb->_ActualFormat = COLOR_INDEX32;
+ }
+ else {
+ rb->_ActualFormat = COLOR_INDEX32;
+ }
+ rb->InternalFormat = rb->_ActualFormat;
+
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, b, rb);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Add software-based alpha renderbuffers to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint alphaBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight)
+{
+ GLuint b;
+
+ /* for window system framebuffers only! */
+ assert(fb->Name == 0);
+
+ if (alphaBits > 8) {
+ _mesa_problem(ctx,
+ "Unsupported bit depth in _mesa_add_alpha_renderbuffers");
+ return GL_FALSE;
+ }
+
+ assert(MAX_COLOR_ATTACHMENTS >= 4);
+
+ /* Wrap each of the RGB color buffers with an alpha renderbuffer.
+ */
+ for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) {
+ struct gl_renderbuffer *arb;
+
+ if (b == BUFFER_FRONT_LEFT && !frontLeft)
+ continue;
+ else if (b == BUFFER_BACK_LEFT && !backLeft)
+ continue;
+ else if (b == BUFFER_FRONT_RIGHT && !frontRight)
+ continue;
+ else if (b == BUFFER_BACK_RIGHT && !backRight)
+ continue;
+
+ /* the RGB buffer to wrap must already exist!! */
+ assert(fb->Attachment[b].Renderbuffer);
+
+ /* only GLubyte supported for now */
+ assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE);
+
+ /* allocate alpha renderbuffer */
+ arb = _mesa_new_renderbuffer(ctx, 0);
+ if (!arb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer");
+ return GL_FALSE;
+ }
+
+ /* wrap the alpha renderbuffer around the RGB renderbuffer */
+ arb->Wrapped = fb->Attachment[b].Renderbuffer;
+
+ /* Set up my alphabuffer fields and plug in my functions.
+ * The functions will put/get the alpha values from/to RGBA arrays
+ * and then call the wrapped buffer's functions to handle the RGB
+ * values.
+ */
+ arb->InternalFormat = arb->Wrapped->InternalFormat;
+ arb->_ActualFormat = GL_ALPHA8;
+ arb->_BaseFormat = arb->Wrapped->_BaseFormat;
+ arb->DataType = arb->Wrapped->DataType;
+ arb->AllocStorage = alloc_storage_alpha8;
+ arb->Delete = delete_renderbuffer_alpha8;
+ arb->GetPointer = get_pointer_alpha8;
+ arb->GetRow = get_row_alpha8;
+ arb->GetValues = get_values_alpha8;
+ arb->PutRow = put_row_alpha8;
+ arb->PutRowRGB = put_row_rgb_alpha8;
+ arb->PutMonoRow = put_mono_row_alpha8;
+ arb->PutValues = put_values_alpha8;
+ arb->PutMonoValues = put_mono_values_alpha8;
+
+ /* clear the pointer to avoid assertion/sanity check failure later */
+ fb->Attachment[b].Renderbuffer = NULL;
+
+ /* plug the alpha renderbuffer into the colorbuffer attachment */
+ _mesa_add_renderbuffer(fb, b, arb);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * For framebuffers that use a software alpha channel wrapper
+ * created by _mesa_add_alpha_renderbuffer or _mesa_add_soft_renderbuffers,
+ * copy the back buffer alpha channel into the front buffer alpha channel.
+ */
+void
+_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer)
+ copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer,
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+
+
+ if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer)
+ copy_buffer_alpha8(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer,
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+}
+
+
+/**
+ * Add a software-based depth renderbuffer to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint depthBits)
+{
+ struct gl_renderbuffer *rb;
+
+ if (depthBits > 32) {
+ _mesa_problem(ctx,
+ "Unsupported depthBits in _mesa_add_depth_renderbuffer");
+ return GL_FALSE;
+ }
+
+ assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL);
+
+ rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer");
+ return GL_FALSE;
+ }
+
+ if (depthBits <= 16) {
+ rb->_ActualFormat = GL_DEPTH_COMPONENT16;
+ }
+ else if (depthBits <= 24) {
+ rb->_ActualFormat = GL_DEPTH_COMPONENT24;
+ }
+ else {
+ rb->_ActualFormat = GL_DEPTH_COMPONENT32;
+ }
+ rb->InternalFormat = rb->_ActualFormat;
+
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Add a software-based stencil renderbuffer to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint stencilBits)
+{
+ struct gl_renderbuffer *rb;
+
+ if (stencilBits > 16) {
+ _mesa_problem(ctx,
+ "Unsupported stencilBits in _mesa_add_stencil_renderbuffer");
+ return GL_FALSE;
+ }
+
+ assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL);
+
+ rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer");
+ return GL_FALSE;
+ }
+
+ if (stencilBits <= 8) {
+ rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
+ }
+ else {
+ /* not really supported (see s_stencil.c code) */
+ rb->_ActualFormat = GL_STENCIL_INDEX16_EXT;
+ }
+ rb->InternalFormat = rb->_ActualFormat;
+
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Add a software-based accumulation renderbuffer to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ */
+GLboolean
+_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint redBits, GLuint greenBits,
+ GLuint blueBits, GLuint alphaBits)
+{
+ struct gl_renderbuffer *rb;
+
+ if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) {
+ _mesa_problem(ctx,
+ "Unsupported accumBits in _mesa_add_accum_renderbuffer");
+ return GL_FALSE;
+ }
+
+ assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL);
+
+ rb = _mesa_new_renderbuffer(ctx, 0);
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
+ return GL_FALSE;
+ }
+
+ rb->_ActualFormat = GL_RGBA16;
+ rb->InternalFormat = GL_RGBA16;
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Add a software-based accumulation renderbuffer to the given framebuffer.
+ * This is a helper routine for device drivers when creating a
+ * window system framebuffer (not a user-created render/framebuffer).
+ * Once this function is called, you can basically forget about this
+ * renderbuffer; core Mesa will handle all the buffer management and
+ * rendering!
+ *
+ * NOTE: color-index aux buffers not supported.
+ */
+GLboolean
+_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint colorBits, GLuint numBuffers)
+{
+ GLuint i;
+
+ if (colorBits > 16) {
+ _mesa_problem(ctx,
+ "Unsupported accumBits in _mesa_add_aux_renderbuffers");
+ return GL_FALSE;
+ }
+
+ assert(numBuffers < MAX_AUX_BUFFERS);
+
+ for (i = 0; i < numBuffers; i++) {
+ struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0);
+
+ assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL);
+
+ if (!rb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer");
+ return GL_FALSE;
+ }
+
+ if (colorBits <= 8) {
+ rb->_ActualFormat = GL_RGBA8;
+ }
+ else {
+ rb->_ActualFormat = GL_RGBA16;
+ }
+ rb->InternalFormat = rb->_ActualFormat;
+
+ rb->AllocStorage = _mesa_soft_renderbuffer_storage;
+ _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Create/attach software-based renderbuffers to the given framebuffer.
+ * This is a helper routine for device drivers. Drivers can just as well
+ * call the individual _mesa_add_*_renderbuffer() routines directly.
+ */
+void
+_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
+ GLboolean color,
+ GLboolean depth,
+ GLboolean stencil,
+ GLboolean accum,
+ GLboolean alpha,
+ GLboolean aux)
+{
+ GLboolean frontLeft = GL_TRUE;
+ GLboolean backLeft = fb->Visual.doubleBufferMode;
+ GLboolean frontRight = fb->Visual.stereoMode;
+ GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
+
+ if (color) {
+ if (fb->Visual.rgbMode) {
+ assert(fb->Visual.redBits == fb->Visual.greenBits);
+ assert(fb->Visual.redBits == fb->Visual.blueBits);
+ _mesa_add_color_renderbuffers(NULL, fb,
+ fb->Visual.redBits,
+ fb->Visual.alphaBits,
+ frontLeft, backLeft,
+ frontRight, backRight);
+ }
+ else {
+ _mesa_add_color_index_renderbuffers(NULL, fb,
+ fb->Visual.indexBits,
+ frontLeft, backLeft,
+ frontRight, backRight);
+ }
+ }
+
+ if (depth) {
+ assert(fb->Visual.depthBits > 0);
+ _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
+ }
+
+ if (stencil) {
+ assert(fb->Visual.stencilBits > 0);
+ _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
+ }
+
+ if (accum) {
+ assert(fb->Visual.rgbMode);
+ assert(fb->Visual.accumRedBits > 0);
+ assert(fb->Visual.accumGreenBits > 0);
+ assert(fb->Visual.accumBlueBits > 0);
+ _mesa_add_accum_renderbuffer(NULL, fb,
+ fb->Visual.accumRedBits,
+ fb->Visual.accumGreenBits,
+ fb->Visual.accumBlueBits,
+ fb->Visual.accumAlphaBits);
+ }
+
+ if (aux) {
+ assert(fb->Visual.rgbMode);
+ assert(fb->Visual.numAuxBuffers > 0);
+ _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
+ fb->Visual.numAuxBuffers);
+ }
+
+ if (alpha) {
+ assert(fb->Visual.rgbMode);
+ assert(fb->Visual.alphaBits > 0);
+ _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
+ frontLeft, backLeft,
+ frontRight, backRight);
+ }
+
+#if 0
+ if (multisample) {
+ /* maybe someday */
+ }
+#endif
+}
+
+
+/**
+ * Attach a renderbuffer to a framebuffer.
+ */
+void
+_mesa_add_renderbuffer(struct gl_framebuffer *fb,
+ GLuint bufferName, struct gl_renderbuffer *rb)
+{
+ assert(fb);
+ assert(rb);
+ assert(bufferName < BUFFER_COUNT);
+
+ /* There should be no previous renderbuffer on this attachment point,
+ * with the exception of depth/stencil since the same renderbuffer may
+ * be used for both.
+ */
+ assert(bufferName == BUFFER_DEPTH ||
+ bufferName == BUFFER_STENCIL ||
+ fb->Attachment[bufferName].Renderbuffer == NULL);
+
+ /* winsys vs. user-created buffer cross check */
+ if (fb->Name) {
+ assert(rb->Name);
+ }
+ else {
+ assert(!rb->Name);
+ }
+
+ /* If Mesa's compiled with deep color channels (16 or 32 bits / channel)
+ * and the device driver is expecting 8-bit values (GLubyte), we can
+ * use a "renderbuffer adaptor/wrapper" to do the necessary conversions.
+ */
+ if (rb->_BaseFormat == GL_RGBA) {
+ if (CHAN_BITS == 16 && rb->DataType == GL_UNSIGNED_BYTE) {
+ GET_CURRENT_CONTEXT(ctx);
+ rb = _mesa_new_renderbuffer_16wrap8(ctx, rb);
+ }
+ else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_BYTE) {
+ GET_CURRENT_CONTEXT(ctx);
+ rb = _mesa_new_renderbuffer_32wrap8(ctx, rb);
+ }
+ else if (CHAN_BITS == 32 && rb->DataType == GL_UNSIGNED_SHORT) {
+ GET_CURRENT_CONTEXT(ctx);
+ rb = _mesa_new_renderbuffer_32wrap16(ctx, rb);
+ }
+ }
+
+ fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
+ fb->Attachment[bufferName].Complete = GL_TRUE;
+ _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
+}
+
+
+/**
+ * Remove the named renderbuffer from the given framebuffer.
+ */
+void
+_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName)
+{
+ struct gl_renderbuffer *rb;
+
+ assert(bufferName < BUFFER_COUNT);
+
+ rb = fb->Attachment[bufferName].Renderbuffer;
+ if (!rb)
+ return;
+
+ _mesa_reference_renderbuffer(&rb, NULL);
+
+ fb->Attachment[bufferName].Renderbuffer = NULL;
+}
+
+
+/**
+ * Set *ptr to point to rb. If *ptr points to another renderbuffer,
+ * dereference that buffer first. The new renderbuffer's refcount will
+ * be incremented. The old renderbuffer's refcount will be decremented.
+ */
+void
+_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
+ struct gl_renderbuffer *rb)
+{
+ assert(ptr);
+ if (*ptr == rb) {
+ /* no change */
+ return;
+ }
+
+ if (*ptr) {
+ /* Unreference the old renderbuffer */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_renderbuffer *oldRb = *ptr;
+
+ assert(oldRb->Magic == RB_MAGIC);
+ _glthread_LOCK_MUTEX(oldRb->Mutex);
+ assert(oldRb->Magic == RB_MAGIC);
+ ASSERT(oldRb->RefCount > 0);
+ oldRb->RefCount--;
+ /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/
+ deleteFlag = (oldRb->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldRb->Mutex);
+
+ if (deleteFlag) {
+ oldRb->Magic = 0; /* now invalid memory! */
+ oldRb->Delete(oldRb);
+ }
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (rb) {
+ assert(rb->Magic == RB_MAGIC);
+ /* reference new renderbuffer */
+ _glthread_LOCK_MUTEX(rb->Mutex);
+ rb->RefCount++;
+ /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/
+ _glthread_UNLOCK_MUTEX(rb->Mutex);
+ *ptr = rb;
+ }
+}
+
+
+/**
+ * Create a new combined depth/stencil renderbuffer for implementing
+ * the GL_EXT_packed_depth_stencil extension.
+ * \return new depth/stencil renderbuffer
+ */
+struct gl_renderbuffer *
+_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name)
+{
+ struct gl_renderbuffer *dsrb;
+
+ dsrb = _mesa_new_renderbuffer(ctx, name);
+ if (!dsrb)
+ return NULL;
+
+ /* init fields not covered by _mesa_new_renderbuffer() */
+ dsrb->InternalFormat = GL_DEPTH24_STENCIL8_EXT;
+ dsrb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ dsrb->AllocStorage = _mesa_soft_renderbuffer_storage;
+
+ return dsrb;
+}
diff --git a/mesalib/src/mesa/main/renderbuffer.h b/mesalib/src/mesa/main/renderbuffer.h
new file mode 100644
index 000000000..c9bf88854
--- /dev/null
+++ b/mesalib/src/mesa/main/renderbuffer.h
@@ -0,0 +1,112 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 RENDERBUFFER_H
+#define RENDERBUFFER_H
+
+
+extern void
+_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name);
+
+extern struct gl_renderbuffer *
+_mesa_new_renderbuffer(GLcontext *ctx, GLuint name);
+
+extern void
+_mesa_delete_renderbuffer(struct gl_renderbuffer *rb);
+
+
+extern struct gl_renderbuffer *
+_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name);
+
+
+extern GLboolean
+_mesa_soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width, GLuint height);
+
+extern GLboolean
+_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint rgbBits, GLuint alphaBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight);
+
+extern GLboolean
+_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint indexBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight);
+
+extern GLboolean
+_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint alphaBits,
+ GLboolean frontLeft, GLboolean backLeft,
+ GLboolean frontRight, GLboolean backRight);
+
+extern void
+_mesa_copy_soft_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb);
+
+extern GLboolean
+_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint depthBits);
+
+extern GLboolean
+_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint stencilBits);
+
+
+extern GLboolean
+_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint redBits, GLuint greenBits,
+ GLuint blueBits, GLuint alphaBits);
+
+extern GLboolean
+_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLuint bits, GLuint numBuffers);
+
+extern void
+_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
+ GLboolean color,
+ GLboolean depth,
+ GLboolean stencil,
+ GLboolean accum,
+ GLboolean alpha,
+ GLboolean aux);
+
+extern void
+_mesa_add_renderbuffer(struct gl_framebuffer *fb,
+ GLuint bufferName, struct gl_renderbuffer *rb);
+
+extern void
+_mesa_remove_renderbuffer(struct gl_framebuffer *fb, GLuint bufferName);
+
+extern void
+_mesa_reference_renderbuffer(struct gl_renderbuffer **ptr,
+ struct gl_renderbuffer *rb);
+
+extern struct gl_renderbuffer *
+_mesa_new_depthstencil_renderbuffer(GLcontext *ctx, GLuint name);
+
+
+#endif /* RENDERBUFFER_H */
diff --git a/mesalib/src/mesa/main/scissor.c b/mesalib/src/mesa/main/scissor.c
new file mode 100644
index 000000000..b5f4cde78
--- /dev/null
+++ b/mesalib/src/mesa/main/scissor.c
@@ -0,0 +1,99 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/scissor.h"
+
+
+/**
+ * Called via glScissor
+ */
+void GLAPIENTRY
+_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
+ return;
+ }
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
+
+ _mesa_set_scissor(ctx, x, y, width, height);
+}
+
+
+/**
+ * Define the scissor box.
+ *
+ * \param x, y coordinates of the scissor box lower-left corner.
+ * \param width width of the scissor box.
+ * \param height height of the scissor box.
+ *
+ * \sa glScissor().
+ *
+ * Verifies the parameters and updates __GLcontextRec::Scissor. On a
+ * change flushes the vertices and notifies the driver via
+ * the dd_function_table::Scissor callback.
+ */
+void
+_mesa_set_scissor(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (x == ctx->Scissor.X &&
+ y == ctx->Scissor.Y &&
+ width == ctx->Scissor.Width &&
+ height == ctx->Scissor.Height)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.X = x;
+ ctx->Scissor.Y = y;
+ ctx->Scissor.Width = width;
+ ctx->Scissor.Height = height;
+
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor( ctx, x, y, width, height );
+}
+
+
+/**
+ * Initialize the context's scissor state.
+ * \param ctx the GL context.
+ */
+void
+_mesa_init_scissor(GLcontext *ctx)
+{
+ /* Scissor group */
+ ctx->Scissor.Enabled = GL_FALSE;
+ ctx->Scissor.X = 0;
+ ctx->Scissor.Y = 0;
+ ctx->Scissor.Width = 0;
+ ctx->Scissor.Height = 0;
+}
diff --git a/mesalib/src/mesa/main/scissor.h b/mesalib/src/mesa/main/scissor.h
new file mode 100644
index 000000000..b852a2122
--- /dev/null
+++ b/mesalib/src/mesa/main/scissor.h
@@ -0,0 +1,46 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 SCISSOR_H
+#define SCISSOR_H
+
+
+#include "main/mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+extern void
+_mesa_set_scissor(GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+extern void
+_mesa_init_scissor(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/shaders.c b/mesalib/src/mesa/main/shaders.c
new file mode 100644
index 000000000..bc76b9129
--- /dev/null
+++ b/mesalib/src/mesa/main/shaders.c
@@ -0,0 +1,728 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 2004-2008 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 "glheader.h"
+#include "context.h"
+#include "shaders.h"
+
+
+/**
+ * These are basically just wrappers/adaptors for calling the
+ * ctx->Driver.foobar() GLSL-related functions.
+ *
+ * Things are biased toward the OpenGL 2.0 functions rather than the
+ * ARB extensions (i.e. the ARB functions are layered on the 2.0 functions).
+ *
+ * The general idea here is to allow enough modularity such that a
+ * completely different GLSL implemenation can be plugged in and co-exist
+ * with Mesa's native GLSL code.
+ */
+
+
+
+void GLAPIENTRY
+_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.AttachShader(ctx, program, shader);
+}
+
+
+void GLAPIENTRY
+_mesa_AttachShader(GLuint program, GLuint shader)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.AttachShader(ctx, program, shader);
+}
+
+
+void GLAPIENTRY
+_mesa_BindAttribLocationARB(GLhandleARB program, GLuint index,
+ const GLcharARB *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.BindAttribLocation(ctx, program, index, name);
+}
+
+
+void GLAPIENTRY
+_mesa_CompileShaderARB(GLhandleARB shaderObj)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.CompileShader(ctx, shaderObj);
+}
+
+
+GLuint GLAPIENTRY
+_mesa_CreateShader(GLenum type)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.CreateShader(ctx, type);
+}
+
+
+GLhandleARB GLAPIENTRY
+_mesa_CreateShaderObjectARB(GLenum type)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.CreateShader(ctx, type);
+}
+
+
+GLuint GLAPIENTRY
+_mesa_CreateProgram(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.CreateProgram(ctx);
+}
+
+
+GLhandleARB GLAPIENTRY
+_mesa_CreateProgramObjectARB(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.CreateProgram(ctx);
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteObjectARB(GLhandleARB obj)
+{
+ if (obj) {
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx->Driver.IsProgram(ctx, obj)) {
+ ctx->Driver.DeleteProgram2(ctx, obj);
+ }
+ else if (ctx->Driver.IsShader(ctx, obj)) {
+ ctx->Driver.DeleteShader(ctx, obj);
+ }
+ else {
+ /* error? */
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteProgram(GLuint name)
+{
+ if (name) {
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.DeleteProgram2(ctx, name);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DeleteShader(GLuint name)
+{
+ if (name) {
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.DeleteShader(ctx, name);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.DetachShader(ctx, program, shader);
+}
+
+
+void GLAPIENTRY
+_mesa_DetachShader(GLuint program, GLuint shader)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.DetachShader(ctx, program, shader);
+}
+
+
+void GLAPIENTRY
+_mesa_GetActiveAttribARB(GLhandleARB program, GLuint index,
+ GLsizei maxLength, GLsizei * length, GLint * size,
+ GLenum * type, GLcharARB * name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetActiveAttrib(ctx, program, index, maxLength, length, size,
+ type, name);
+}
+
+
+void GLAPIENTRY
+_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
+ GLsizei maxLength, GLsizei * length, GLint * size,
+ GLenum * type, GLcharARB * name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetActiveUniform(ctx, program, index, maxLength, length, size,
+ type, name);
+}
+
+
+void GLAPIENTRY
+_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
+ GLsizei * count, GLhandleARB * obj)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetAttachedShaders(ctx, container, maxCount, count, obj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
+ GLsizei *count, GLuint *obj)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetAttachedShaders(ctx, program, maxCount, count, obj);
+}
+
+
+GLint GLAPIENTRY
+_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.GetAttribLocation(ctx, program, name);
+}
+
+
+void GLAPIENTRY
+_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
+ GLcharARB * infoLog)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* Implement in terms of GetProgramInfoLog, GetShaderInfoLog */
+ if (ctx->Driver.IsProgram(ctx, object)) {
+ ctx->Driver.GetProgramInfoLog(ctx, object, maxLength, length, infoLog);
+ }
+ else if (ctx->Driver.IsShader(ctx, object)) {
+ ctx->Driver.GetShaderInfoLog(ctx, object, maxLength, length, infoLog);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ /* Implement in terms of GetProgramiv, GetShaderiv */
+ if (ctx->Driver.IsProgram(ctx, object)) {
+ if (pname == GL_OBJECT_TYPE_ARB) {
+ *params = GL_PROGRAM_OBJECT_ARB;
+ }
+ else {
+ ctx->Driver.GetProgramiv(ctx, object, pname, params);
+ }
+ }
+ else if (ctx->Driver.IsShader(ctx, object)) {
+ if (pname == GL_OBJECT_TYPE_ARB) {
+ *params = GL_SHADER_OBJECT_ARB;
+ }
+ else {
+ ctx->Driver.GetShaderiv(ctx, object, pname, params);
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname,
+ GLfloat *params)
+{
+ GLint iparams[1]; /* XXX is one element enough? */
+ _mesa_GetObjectParameterivARB(object, pname, iparams);
+ params[0] = (GLfloat) iparams[0];
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetProgramiv(ctx, program, pname, params);
+}
+
+
+void GLAPIENTRY
+_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetShaderiv(ctx, shader, pname, params);
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetProgramInfoLog(ctx, program, bufSize, length, infoLog);
+}
+
+
+void GLAPIENTRY
+_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetShaderInfoLog(ctx, shader, bufSize, length, infoLog);
+}
+
+
+void GLAPIENTRY
+_mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength,
+ GLsizei *length, GLcharARB *sourceOut)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetShaderSource(ctx, shader, maxLength, length, sourceOut);
+}
+
+
+void GLAPIENTRY
+_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat * params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetUniformfv(ctx, program, location, params);
+}
+
+
+void GLAPIENTRY
+_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint * params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.GetUniformiv(ctx, program, location, params);
+}
+
+
+
+#if 0
+GLint GLAPIENTRY
+_mesa_GetUniformLocation(GLuint program, const GLcharARB *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.GetUniformLocation(ctx, program, name);
+}
+#endif
+
+
+GLhandleARB GLAPIENTRY
+_mesa_GetHandleARB(GLenum pname)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.GetHandle(ctx, pname);
+}
+
+
+GLint GLAPIENTRY
+_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.GetUniformLocation(ctx, programObj, name);
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsProgram(GLuint name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.IsProgram(ctx, name);
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsShader(GLuint name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return ctx->Driver.IsShader(ctx, name);
+}
+
+
+void GLAPIENTRY
+_mesa_LinkProgramARB(GLhandleARB programObj)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.LinkProgram(ctx, programObj);
+}
+
+
+
+/**
+ * Read shader source code from a file.
+ * Useful for debugging to override an app's shader.
+ */
+static GLcharARB *
+_mesa_read_shader(const char *fname)
+{
+ const int max = 50*1000;
+ FILE *f = fopen(fname, "r");
+ GLcharARB *buffer, *shader;
+ int len;
+
+ if (!f) {
+ _mesa_fprintf(stderr, "Unable to open shader file %s\n", fname);
+ return NULL;
+ }
+
+ buffer = (char *) malloc(max);
+ len = fread(buffer, 1, max, f);
+ buffer[len] = 0;
+
+ fclose(f);
+
+ shader = _mesa_strdup(buffer);
+ free(buffer);
+
+ if (0) {
+ _mesa_fprintf(stderr, "Read shader %s:\n", fname);
+ _mesa_fprintf(stderr, "%s\n", shader);
+ }
+
+ return shader;
+}
+
+
+
+/**
+ * Called via glShaderSource() and glShaderSourceARB() API functions.
+ * Basically, concatenate the source code strings into one long string
+ * and pass it to ctx->Driver.ShaderSource().
+ */
+void GLAPIENTRY
+_mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
+ const GLcharARB ** string, const GLint * length)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint *offsets;
+ GLsizei i, totalLength;
+ GLcharARB *source;
+
+ if (!shaderObj || string == NULL) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
+ return;
+ }
+
+ /*
+ * This array holds offsets of where the appropriate string ends, thus the
+ * last element will be set to the total length of the source code.
+ */
+ offsets = (GLint *) _mesa_malloc(count * sizeof(GLint));
+ if (offsets == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (string[i] == NULL) {
+ _mesa_free((GLvoid *) offsets);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)");
+ return;
+ }
+ if (length == NULL || length[i] < 0)
+ offsets[i] = _mesa_strlen(string[i]);
+ else
+ offsets[i] = length[i];
+ /* accumulate string lengths */
+ if (i > 0)
+ offsets[i] += offsets[i - 1];
+ }
+
+ /* Total length of source string is sum off all strings plus two.
+ * One extra byte for terminating zero, another extra byte to silence
+ * valgrind warnings in the parser/grammer code.
+ */
+ totalLength = offsets[count - 1] + 2;
+ source = (GLcharARB *) _mesa_malloc(totalLength * sizeof(GLcharARB));
+ if (source == NULL) {
+ _mesa_free((GLvoid *) offsets);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ GLint start = (i > 0) ? offsets[i - 1] : 0;
+ _mesa_memcpy(source + start, string[i],
+ (offsets[i] - start) * sizeof(GLcharARB));
+ }
+ source[totalLength - 1] = '\0';
+ source[totalLength - 2] = '\0';
+
+#if 0
+ if (0) {
+ GLcharARB *newSource;
+
+ newSource = _mesa_read_shader("newshader.frag");
+ if (newSource) {
+ _mesa_free(source);
+ source = newSource;
+ }
+ }
+#else
+ (void) _mesa_read_shader;
+#endif
+
+ ctx->Driver.ShaderSource(ctx, shaderObj, source);
+
+ _mesa_free(offsets);
+}
+
+
+void GLAPIENTRY
+_mesa_Uniform1fARB(GLint location, GLfloat v0)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, 1, &v0, GL_FLOAT);
+}
+
+void GLAPIENTRY
+_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat v[2];
+ v[0] = v0;
+ v[1] = v1;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC2);
+}
+
+void GLAPIENTRY
+_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat v[3];
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC3);
+}
+
+void GLAPIENTRY
+_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
+ GLfloat v3)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat v[4];
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC4);
+}
+
+void GLAPIENTRY
+_mesa_Uniform1iARB(GLint location, GLint v0)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, 1, &v0, GL_INT);
+}
+
+void GLAPIENTRY
+_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint v[2];
+ v[0] = v0;
+ v[1] = v1;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC2);
+}
+
+void GLAPIENTRY
+_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint v[3];
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC3);
+}
+
+void GLAPIENTRY
+_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint v[4];
+ v[0] = v0;
+ v[1] = v1;
+ v[2] = v2;
+ v[3] = v3;
+ ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC4);
+}
+
+void GLAPIENTRY
+_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT);
+}
+
+void GLAPIENTRY
+_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC2);
+}
+
+void GLAPIENTRY
+_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC3);
+}
+
+void GLAPIENTRY
+_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC4);
+}
+
+void GLAPIENTRY
+_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_INT);
+}
+
+void GLAPIENTRY
+_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC2);
+}
+
+void GLAPIENTRY
+_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC3);
+}
+
+void GLAPIENTRY
+_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC4);
+}
+
+
+void GLAPIENTRY
+_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 2, 2, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 3, 3, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat * value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 4, 4, location, count, transpose, value);
+}
+
+
+/**
+ * Non-square UniformMatrix are OpenGL 2.1
+ */
+void GLAPIENTRY
+_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 2, 3, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 3, 2, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 2, 4, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 4, 2, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 3, 4, location, count, transpose, value);
+}
+
+void GLAPIENTRY
+_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.UniformMatrix(ctx, 4, 3, location, count, transpose, value);
+}
+
+
+void GLAPIENTRY
+_mesa_UseProgramObjectARB(GLhandleARB program)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->Driver.UseProgram(ctx, program);
+}
+
+
+void GLAPIENTRY
+_mesa_ValidateProgramARB(GLhandleARB program)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Driver.ValidateProgram(ctx, program);
+}
+
diff --git a/mesalib/src/mesa/main/shaders.h b/mesalib/src/mesa/main/shaders.h
new file mode 100644
index 000000000..17339ccf6
--- /dev/null
+++ b/mesalib/src/mesa/main/shaders.h
@@ -0,0 +1,236 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2004-2007 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 SHADERS_H
+#define SHADERS_H
+
+
+#include "glheader.h"
+#include "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_DeleteObjectARB(GLhandleARB obj);
+
+extern GLhandleARB GLAPIENTRY
+_mesa_GetHandleARB(GLenum pname);
+
+extern void GLAPIENTRY
+_mesa_DetachObjectARB (GLhandleARB, GLhandleARB);
+
+extern GLhandleARB GLAPIENTRY
+_mesa_CreateShaderObjectARB (GLenum);
+
+extern void GLAPIENTRY
+_mesa_ShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *);
+
+extern void GLAPIENTRY
+_mesa_CompileShaderARB (GLhandleARB);
+
+extern GLhandleARB GLAPIENTRY
+_mesa_CreateProgramObjectARB (void);
+
+extern void GLAPIENTRY
+_mesa_AttachObjectARB (GLhandleARB, GLhandleARB);
+
+extern void GLAPIENTRY
+_mesa_LinkProgramARB (GLhandleARB);
+
+extern void GLAPIENTRY
+_mesa_UseProgramObjectARB (GLhandleARB);
+
+extern void GLAPIENTRY
+_mesa_ValidateProgramARB (GLhandleARB);
+
+extern void GLAPIENTRY
+_mesa_Uniform1fARB (GLint, GLfloat);
+
+extern void GLAPIENTRY
+_mesa_Uniform2fARB (GLint, GLfloat, GLfloat);
+
+extern void GLAPIENTRY
+_mesa_Uniform3fARB (GLint, GLfloat, GLfloat, GLfloat);
+
+extern void GLAPIENTRY
+_mesa_Uniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+
+extern void GLAPIENTRY
+_mesa_Uniform1iARB (GLint, GLint);
+
+extern void GLAPIENTRY
+_mesa_Uniform2iARB (GLint, GLint, GLint);
+
+extern void GLAPIENTRY
+_mesa_Uniform3iARB (GLint, GLint, GLint, GLint);
+
+extern void GLAPIENTRY
+_mesa_Uniform4iARB (GLint, GLint, GLint, GLint, GLint);
+
+extern void GLAPIENTRY
+_mesa_Uniform1fvARB (GLint, GLsizei, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_Uniform2fvARB (GLint, GLsizei, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_Uniform3fvARB (GLint, GLsizei, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_Uniform4fvARB (GLint, GLsizei, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_Uniform1ivARB (GLint, GLsizei, const GLint *);
+
+extern void GLAPIENTRY
+_mesa_Uniform2ivARB (GLint, GLsizei, const GLint *);
+
+extern void GLAPIENTRY
+_mesa_Uniform3ivARB (GLint, GLsizei, const GLint *);
+
+extern void GLAPIENTRY
+_mesa_Uniform4ivARB (GLint, GLsizei, const GLint *);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_GetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_GetObjectParameterivARB (GLhandleARB, GLenum, GLint *);
+
+extern void GLAPIENTRY
+_mesa_GetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+
+extern void GLAPIENTRY
+_mesa_GetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
+
+extern GLint GLAPIENTRY
+_mesa_GetUniformLocationARB (GLhandleARB, const GLcharARB *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+
+extern void GLAPIENTRY
+_mesa_GetUniformfvARB (GLhandleARB, GLint, GLfloat *);
+
+extern void GLAPIENTRY
+_mesa_GetUniformivARB (GLhandleARB, GLint, GLint *);
+
+extern void GLAPIENTRY
+_mesa_GetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
+
+#if FEATURE_ARB_vertex_shader
+
+extern void GLAPIENTRY
+_mesa_BindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *);
+
+extern void GLAPIENTRY
+_mesa_GetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *);
+
+extern GLint GLAPIENTRY
+_mesa_GetAttribLocationARB (GLhandleARB, const GLcharARB *);
+
+#endif /* FEATURE_ARB_vertex_shader */
+
+
+/* 2.0 */
+extern void GLAPIENTRY
+_mesa_AttachShader(GLuint program, GLuint shader);
+
+extern GLuint GLAPIENTRY
+_mesa_CreateShader(GLenum);
+
+extern GLuint GLAPIENTRY
+_mesa_CreateProgram(void);
+
+extern void GLAPIENTRY
+_mesa_DeleteProgram(GLuint program);
+
+extern void GLAPIENTRY
+_mesa_DeleteShader(GLuint shader);
+
+extern void GLAPIENTRY
+_mesa_DetachShader(GLuint program, GLuint shader);
+
+extern void GLAPIENTRY
+_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
+ GLsizei *count, GLuint *obj);
+
+extern void GLAPIENTRY
+_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog);
+
+extern void GLAPIENTRY
+_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsProgram(GLuint program);
+
+extern GLboolean GLAPIENTRY
+_mesa_IsShader(GLuint shader);
+
+
+
+/* 2.1 */
+extern void GLAPIENTRY
+_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+extern void GLAPIENTRY
+_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
+ const GLfloat *value);
+
+
+#endif /* SHADERS_H */
diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c
new file mode 100644
index 000000000..643ad3354
--- /dev/null
+++ b/mesalib/src/mesa/main/shared.c
@@ -0,0 +1,374 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file shared.c
+ * Shared-context state
+ */
+
+
+
+#include "imports.h"
+#include "mtypes.h"
+#include "hash.h"
+#include "arrayobj.h"
+#include "bufferobj.h"
+#include "shared.h"
+#include "shader/program.h"
+#include "shader/shader_api.h"
+#if FEATURE_dlist
+#include "dlist.h"
+#endif
+#if FEATURE_ATI_fragment_shader
+#include "shader/atifragshader.h"
+#endif
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+#endif
+
+/**
+ * Allocate and initialize a shared context state structure.
+ * Initializes the display list, texture objects and vertex programs hash
+ * tables, allocates the texture objects. If it runs out of memory, frees
+ * everything already allocated before returning NULL.
+ *
+ * \return pointer to a gl_shared_state structure on success, or NULL on
+ * failure.
+ */
+struct gl_shared_state *
+_mesa_alloc_shared_state(GLcontext *ctx)
+{
+ struct gl_shared_state *shared;
+ GLuint i;
+
+ shared = CALLOC_STRUCT(gl_shared_state);
+ if (!shared)
+ return NULL;
+
+ _glthread_INIT_MUTEX(shared->Mutex);
+
+ shared->DisplayList = _mesa_NewHashTable();
+ shared->TexObjects = _mesa_NewHashTable();
+ shared->Programs = _mesa_NewHashTable();
+
+#if FEATURE_ARB_vertex_program
+ shared->DefaultVertexProgram = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+#endif
+
+#if FEATURE_ARB_fragment_program
+ shared->DefaultFragmentProgram = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+#endif
+
+#if FEATURE_ATI_fragment_shader
+ shared->ATIShaders = _mesa_NewHashTable();
+ shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
+#endif
+
+#if FEATURE_ARB_shader_objects
+ shared->ShaderObjects = _mesa_NewHashTable();
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ shared->BufferObjects = _mesa_NewHashTable();
+#endif
+
+ /* Allocate the default buffer object and set refcount so high that
+ * it never gets deleted.
+ * XXX with recent/improved refcounting this may not longer be needed.
+ */
+ shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0);
+ shared->NullBufferObj->RefCount = 1000 * 1000 * 1000;
+
+ /* Create default texture objects */
+ for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
+ /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */
+ static const GLenum targets[NUM_TEXTURE_TARGETS] = {
+ GL_TEXTURE_2D_ARRAY_EXT,
+ GL_TEXTURE_1D_ARRAY_EXT,
+ GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_3D,
+ GL_TEXTURE_RECTANGLE_NV,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_1D
+ };
+ shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]);
+ }
+
+ /* sanity check */
+ assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
+
+ /* Mutex and timestamp for texobj state validation */
+ _glthread_INIT_MUTEX(shared->TexMutex);
+ shared->TextureStateStamp = 0;
+
+#if FEATURE_EXT_framebuffer_object
+ shared->FrameBuffers = _mesa_NewHashTable();
+ shared->RenderBuffers = _mesa_NewHashTable();
+#endif
+
+#if FEATURE_ARB_sync
+ make_empty_list(& shared->SyncObjects);
+#endif
+
+ return shared;
+}
+
+
+/**
+ * Callback for deleting a display list. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_displaylist_cb(GLuint id, void *data, void *userData)
+{
+#if FEATURE_dlist
+ struct gl_display_list *list = (struct gl_display_list *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_list(ctx, list);
+#endif
+}
+
+
+/**
+ * Callback for deleting a texture object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_texture_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_texture_object *texObj = (struct gl_texture_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ ctx->Driver.DeleteTexture(ctx, texObj);
+}
+
+
+/**
+ * Callback for deleting a program object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_program_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_program *prog = (struct gl_program *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ if(prog != &_mesa_DummyProgram) {
+ ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
+ prog->RefCount = 0; /* now going away */
+ ctx->Driver.DeleteProgram(ctx, prog);
+ }
+}
+
+
+#if FEATURE_ATI_fragment_shader
+/**
+ * Callback for deleting an ATI fragment shader object.
+ * Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_fragshader_cb(GLuint id, void *data, void *userData)
+{
+ struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_ati_fragment_shader(ctx, shader);
+}
+#endif
+
+
+/**
+ * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_bufferobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ if (_mesa_bufferobj_mapped(bufObj)) {
+ ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+ bufObj->Pointer = NULL;
+ }
+ ctx->Driver.DeleteBuffer(ctx, bufObj);
+}
+
+
+/**
+ * Callback for freeing shader program data. Call it before delete_shader_cb
+ * to avoid memory access error.
+ */
+static void
+free_shader_program_data_cb(GLuint id, void *data, void *userData)
+{
+ GLcontext *ctx = (GLcontext *) userData;
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+
+ if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
+ _mesa_free_shader_program_data(ctx, shProg);
+ }
+}
+
+
+/**
+ * Callback for deleting shader and shader programs objects.
+ * Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_shader_cb(GLuint id, void *data, void *userData)
+{
+ GLcontext *ctx = (GLcontext *) userData;
+ struct gl_shader *sh = (struct gl_shader *) data;
+ if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
+ _mesa_free_shader(ctx, sh);
+ }
+ else {
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+ ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
+ _mesa_free_shader_program(ctx, shProg);
+ }
+}
+
+
+/**
+ * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_framebuffer_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ /* The fact that the framebuffer is in the hashtable means its refcount
+ * is one, but we're removing from the hashtable now. So clear refcount.
+ */
+ /*assert(fb->RefCount == 1);*/
+ fb->RefCount = 0;
+
+ /* NOTE: Delete should always be defined but there are two reports
+ * of it being NULL (bugs 13507, 14293). Work-around for now.
+ */
+ if (fb->Delete)
+ fb->Delete(fb);
+}
+
+
+/**
+ * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_renderbuffer_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
+ rb->RefCount = 0; /* see comment for FBOs above */
+ if (rb->Delete)
+ rb->Delete(rb);
+}
+
+
+/**
+ * Deallocate a shared state object and all children structures.
+ *
+ * \param ctx GL context.
+ * \param shared shared state pointer.
+ *
+ * Frees the display lists, the texture objects (calling the driver texture
+ * deletion callback to free its private data) and the vertex programs, as well
+ * as their hash tables.
+ *
+ * \sa alloc_shared_state().
+ */
+void
+_mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared)
+{
+ GLuint i;
+
+ /*
+ * Free display lists
+ */
+ _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx);
+ _mesa_DeleteHashTable(shared->DisplayList);
+
+#if FEATURE_ARB_shader_objects
+ _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx);
+ _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx);
+ _mesa_DeleteHashTable(shared->ShaderObjects);
+#endif
+
+ _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx);
+ _mesa_DeleteHashTable(shared->Programs);
+
+#if FEATURE_ARB_vertex_program
+ _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL);
+#endif
+
+#if FEATURE_ARB_fragment_program
+ _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
+#endif
+
+#if FEATURE_ATI_fragment_shader
+ _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
+ _mesa_DeleteHashTable(shared->ATIShaders);
+ _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object
+ _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
+ _mesa_DeleteHashTable(shared->BufferObjects);
+#endif
+
+#if FEATURE_EXT_framebuffer_object
+ _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx);
+ _mesa_DeleteHashTable(shared->FrameBuffers);
+ _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx);
+ _mesa_DeleteHashTable(shared->RenderBuffers);
+#endif
+
+#if FEATURE_ARB_vertex_buffer_object
+ ctx->Driver.DeleteBuffer(ctx, shared->NullBufferObj);
+#endif
+
+#if FEATURE_ARB_sync
+ {
+ struct simple_node *node;
+ struct simple_node *temp;
+
+ foreach_s(node, temp, & shared->SyncObjects) {
+ _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node);
+ }
+ }
+#endif
+
+ /*
+ * Free texture objects (after FBOs since some textures might have
+ * been bound to FBOs).
+ */
+ ASSERT(ctx->Driver.DeleteTexture);
+ /* the default textures */
+ for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
+ ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
+ }
+
+ /* all other textures */
+ _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
+ _mesa_DeleteHashTable(shared->TexObjects);
+
+ _glthread_DESTROY_MUTEX(shared->Mutex);
+ _glthread_DESTROY_MUTEX(shared->TexMutex);
+
+ _mesa_free(shared);
+}
diff --git a/mesalib/src/mesa/main/shared.h b/mesalib/src/mesa/main/shared.h
new file mode 100644
index 000000000..e59177e96
--- /dev/null
+++ b/mesalib/src/mesa/main/shared.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 SHARED_H
+#define SHARED_H
+
+
+struct gl_shared_state *
+_mesa_alloc_shared_state(GLcontext *ctx);
+
+
+void
+_mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/simple_list.h b/mesalib/src/mesa/main/simple_list.h
new file mode 100644
index 000000000..ff7f88823
--- /dev/null
+++ b/mesalib/src/mesa/main/simple_list.h
@@ -0,0 +1,202 @@
+/**
+ * \file simple_list.h
+ * Simple macros for type-safe, intrusive lists.
+ *
+ * Intended to work with a list sentinal which is created as an empty
+ * list. Insert & delete are O(1).
+ *
+ * \author
+ * (C) 1997, Keith Whitwell
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _SIMPLE_LIST_H
+#define _SIMPLE_LIST_H
+
+struct simple_node {
+ struct simple_node *next;
+ struct simple_node *prev;
+};
+
+/**
+ * Remove an element from list.
+ *
+ * \param elem element to remove.
+ */
+#define remove_from_list(elem) \
+do { \
+ (elem)->next->prev = (elem)->prev; \
+ (elem)->prev->next = (elem)->next; \
+} while (0)
+
+/**
+ * Insert an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_head(list, elem) \
+do { \
+ (elem)->prev = list; \
+ (elem)->next = (list)->next; \
+ (list)->next->prev = elem; \
+ (list)->next = elem; \
+} while(0)
+
+/**
+ * Insert an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to insert.
+ */
+#define insert_at_tail(list, elem) \
+do { \
+ (elem)->next = list; \
+ (elem)->prev = (list)->prev; \
+ (list)->prev->next = elem; \
+ (list)->prev = elem; \
+} while(0)
+
+/**
+ * Move an element to the list head.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_head(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_head(list, elem); \
+} while (0)
+
+/**
+ * Move an element to the list tail.
+ *
+ * \param list list.
+ * \param elem element to move.
+ */
+#define move_to_tail(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_tail(list, elem); \
+} while (0)
+
+/**
+ * Make a empty list empty.
+ *
+ * \param sentinal list (sentinal element).
+ */
+#define make_empty_list(sentinal) \
+do { \
+ (sentinal)->next = sentinal; \
+ (sentinal)->prev = sentinal; \
+} while (0)
+
+/**
+ * Get list first element.
+ *
+ * \param list list.
+ *
+ * \return pointer to first element.
+ */
+#define first_elem(list) ((list)->next)
+
+/**
+ * Get list last element.
+ *
+ * \param list list.
+ *
+ * \return pointer to last element.
+ */
+#define last_elem(list) ((list)->prev)
+
+/**
+ * Get next element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to next element.
+ */
+#define next_elem(elem) ((elem)->next)
+
+/**
+ * Get previous element.
+ *
+ * \param elem element.
+ *
+ * \return pointer to previous element.
+ */
+#define prev_elem(elem) ((elem)->prev)
+
+/**
+ * Test whether element is at end of the list.
+ *
+ * \param list list.
+ * \param elem element.
+ *
+ * \return non-zero if element is at end of list, or zero otherwise.
+ */
+#define at_end(list, elem) ((elem) == (list))
+
+/**
+ * Test if a list is empty.
+ *
+ * \param list list.
+ *
+ * \return non-zero if list empty, or zero otherwise.
+ */
+#define is_empty_list(list) ((list)->next == (list))
+
+/**
+ * Walk through the elements of a list.
+ *
+ * \param ptr pointer to the current element.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach(ptr, list) \
+ for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
+
+/**
+ * Walk through the elements of a list.
+ *
+ * Same as #foreach but lets you unlink the current value during a list
+ * traversal. Useful for freeing a list, element by element.
+ *
+ * \param ptr pointer to the current element.
+ * \param t temporary pointer.
+ * \param list list.
+ *
+ * \note It should be followed by a { } block or a single statement, as in a \c
+ * for loop.
+ */
+#define foreach_s(ptr, t, list) \
+ for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
+
+#endif
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
new file mode 100644
index 000000000..140a998df
--- /dev/null
+++ b/mesalib/src/mesa/main/state.c
@@ -0,0 +1,718 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file state.c
+ * State management.
+ *
+ * This file manages recalculation of derived values in GLcontext.
+ */
+
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "context.h"
+#include "debug.h"
+#include "macros.h"
+#include "ffvertex_prog.h"
+#include "framebuffer.h"
+#include "light.h"
+#include "matrix.h"
+#if FEATURE_pixel_transfer
+#include "pixel.h"
+#endif
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "state.h"
+#include "stencil.h"
+#include "texenvprogram.h"
+#include "texobj.h"
+#include "texstate.h"
+#include "viewport.h"
+
+
+static void
+update_separate_specular(GLcontext *ctx)
+{
+ if (NEED_SECONDARY_COLOR(ctx))
+ ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR;
+ else
+ ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR;
+}
+
+
+/**
+ * Compute the index of the last array element that can be safely accessed
+ * in a vertex array. We can really only do this when the array lives in
+ * a VBO.
+ * The array->_MaxElement field will be updated.
+ * Later in glDrawArrays/Elements/etc we can do some bounds checking.
+ */
+static void
+compute_max_element(struct gl_client_array *array)
+{
+ assert(array->Enabled);
+ if (array->BufferObj->Name) {
+ GLsizeiptrARB offset = (GLsizeiptrARB) array->Ptr;
+ GLsizeiptrARB obj_size = (GLsizeiptrARB) array->BufferObj->Size;
+
+ if (offset < obj_size) {
+ array->_MaxElement = (obj_size - offset +
+ array->StrideB -
+ array->_ElementSize) / array->StrideB;
+ } else {
+ array->_MaxElement = 0;
+ }
+ /* Compute the max element we can access in the VBO without going
+ * out of bounds.
+ */
+ array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size
+ - (GLsizeiptrARB) array->Ptr + array->StrideB
+ - array->_ElementSize) / array->StrideB;
+ }
+ else {
+ /* user-space array, no idea how big it is */
+ array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
+ }
+}
+
+
+/**
+ * Helper for update_arrays().
+ * \return min(current min, array->_MaxElement).
+ */
+static GLuint
+update_min(GLuint min, struct gl_client_array *array)
+{
+ compute_max_element(array);
+ return MIN2(min, array->_MaxElement);
+}
+
+
+/**
+ * Update ctx->Array._MaxElement (the max legal index into all enabled arrays).
+ * Need to do this upon new array state or new buffer object state.
+ */
+static void
+update_arrays( GLcontext *ctx )
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i, min = ~0;
+
+ /* find min of _MaxElement values for all enabled arrays */
+
+ /* 0 */
+ if (ctx->VertexProgram._Current
+ && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
+ }
+ else if (arrayObj->Vertex.Enabled) {
+ min = update_min(min, &arrayObj->Vertex);
+ }
+
+ /* 1 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]);
+ }
+ /* no conventional vertex weight array */
+
+ /* 2 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
+ }
+ else if (arrayObj->Normal.Enabled) {
+ min = update_min(min, &arrayObj->Normal);
+ }
+
+ /* 3 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
+ }
+ else if (arrayObj->Color.Enabled) {
+ min = update_min(min, &arrayObj->Color);
+ }
+
+ /* 4 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]);
+ }
+ else if (arrayObj->SecondaryColor.Enabled) {
+ min = update_min(min, &arrayObj->SecondaryColor);
+ }
+
+ /* 5 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]);
+ }
+ else if (arrayObj->FogCoord.Enabled) {
+ min = update_min(min, &arrayObj->FogCoord);
+ }
+
+ /* 6 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]);
+ }
+ else if (arrayObj->Index.Enabled) {
+ min = update_min(min, &arrayObj->Index);
+ }
+
+ /* 7 */
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]);
+ }
+
+ /* 8..15 */
+ for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) {
+ if (ctx->VertexProgram._Enabled
+ && arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
+ }
+ else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits
+ && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) {
+ min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]);
+ }
+ }
+
+ /* 16..31 */
+ if (ctx->VertexProgram._Current) {
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ if (arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
+ }
+ }
+ }
+
+ if (arrayObj->EdgeFlag.Enabled) {
+ min = update_min(min, &arrayObj->EdgeFlag);
+ }
+
+ /* _MaxElement is one past the last legal array element */
+ arrayObj->_MaxElement = min;
+}
+
+
+/**
+ * Update the following fields:
+ * ctx->VertexProgram._Enabled
+ * ctx->FragmentProgram._Enabled
+ * ctx->ATIFragmentShader._Enabled
+ * This needs to be done before texture state validation.
+ */
+static void
+update_program_enables(GLcontext *ctx)
+{
+ /* These _Enabled flags indicate if the program is enabled AND valid. */
+ ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled
+ && ctx->VertexProgram.Current->Base.Instructions;
+ ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled
+ && ctx->FragmentProgram.Current->Base.Instructions;
+ ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled
+ && ctx->ATIFragmentShader.Current->Instructions[0];
+}
+
+
+/**
+ * Update vertex/fragment program state. In particular, update these fields:
+ * ctx->VertexProgram._Current
+ * ctx->VertexProgram._TnlProgram,
+ * These point to the highest priority enabled vertex/fragment program or are
+ * NULL if fixed-function processing is to be done.
+ *
+ * This function needs to be called after texture state validation in case
+ * we're generating a fragment program from fixed-function texture state.
+ *
+ * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex
+ * or fragment program is being used.
+ */
+static GLbitfield
+update_program(GLcontext *ctx)
+{
+ const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current;
+ const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current;
+ GLbitfield new_state = 0x0;
+
+ /*
+ * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
+ * pointers to the programs that should be used for rendering. If either
+ * is NULL, use fixed-function code paths.
+ *
+ * These programs may come from several sources. The priority is as
+ * follows:
+ * 1. OpenGL 2.0/ARB vertex/fragment shaders
+ * 2. ARB/NV vertex/fragment programs
+ * 3. Programs derived from fixed-function state.
+ *
+ * Note: it's possible for a vertex shader to get used with a fragment
+ * program (and vice versa) here, but in practice that shouldn't ever
+ * come up, or matter.
+ */
+
+ if (shProg && shProg->LinkStatus && shProg->FragmentProgram) {
+ /* Use shader programs */
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ shProg->FragmentProgram);
+ }
+ else if (ctx->FragmentProgram._Enabled) {
+ /* use user-defined vertex program */
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ ctx->FragmentProgram.Current);
+ }
+ else if (ctx->FragmentProgram._MaintainTexEnvProgram) {
+ /* Use fragment program generated from fixed-function state.
+ */
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
+ _mesa_get_fixed_func_fragment_program(ctx));
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram,
+ ctx->FragmentProgram._Current);
+ }
+ else {
+ /* no fragment program */
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
+ }
+
+ /* Examine vertex program after fragment program as
+ * _mesa_get_fixed_func_vertex_program() needs to know active
+ * fragprog inputs.
+ */
+ if (shProg && shProg->LinkStatus && shProg->VertexProgram) {
+ /* Use shader programs */
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
+ shProg->VertexProgram);
+ }
+ else if (ctx->VertexProgram._Enabled) {
+ /* use user-defined vertex program */
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
+ ctx->VertexProgram.Current);
+ }
+ else if (ctx->VertexProgram._MaintainTnlProgram) {
+ /* Use vertex program generated from fixed-function state.
+ */
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
+ _mesa_get_fixed_func_vertex_program(ctx));
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram,
+ ctx->VertexProgram._Current);
+ }
+ else {
+ /* no vertex program */
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
+ }
+
+ /* Let the driver know what's happening:
+ */
+ if (ctx->FragmentProgram._Current != prevFP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ (struct gl_program *) ctx->FragmentProgram._Current);
+ }
+ }
+
+ if (ctx->VertexProgram._Current != prevVP) {
+ new_state |= _NEW_PROGRAM;
+ if (ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ (struct gl_program *) ctx->VertexProgram._Current);
+ }
+ }
+
+ return new_state;
+}
+
+
+/**
+ * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0.
+ */
+static GLbitfield
+update_program_constants(GLcontext *ctx)
+{
+ GLbitfield new_state = 0x0;
+
+ if (ctx->FragmentProgram._Current) {
+ const struct gl_program_parameter_list *params =
+ ctx->FragmentProgram._Current->Base.Parameters;
+ if (params && params->StateFlags & ctx->NewState) {
+ new_state |= _NEW_PROGRAM_CONSTANTS;
+ }
+ }
+
+ if (ctx->VertexProgram._Current) {
+ const struct gl_program_parameter_list *params =
+ ctx->VertexProgram._Current->Base.Parameters;
+ if (params && params->StateFlags & ctx->NewState) {
+ new_state |= _NEW_PROGRAM_CONSTANTS;
+ }
+ }
+
+ return new_state;
+}
+
+
+
+
+static void
+update_viewport_matrix(GLcontext *ctx)
+{
+ const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
+
+ ASSERT(depthMax > 0);
+
+ /* Compute scale and bias values. This is really driver-specific
+ * and should be maintained elsewhere if at all.
+ * NOTE: RasterPos uses this.
+ */
+ _math_matrix_viewport(&ctx->Viewport._WindowMap,
+ ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height,
+ ctx->Viewport.Near, ctx->Viewport.Far,
+ depthMax);
+}
+
+
+/**
+ * Update derived multisample state.
+ */
+static void
+update_multisample(GLcontext *ctx)
+{
+ ctx->Multisample._Enabled = GL_FALSE;
+ if (ctx->Multisample.Enabled &&
+ ctx->DrawBuffer &&
+ ctx->DrawBuffer->Visual.sampleBuffers)
+ ctx->Multisample._Enabled = GL_TRUE;
+}
+
+
+/**
+ * Update derived color/blend/logicop state.
+ */
+static void
+update_color(GLcontext *ctx)
+{
+ /* This is needed to support 1.1's RGB logic ops AND
+ * 1.0's blending logicops.
+ */
+ ctx->Color._LogicOpEnabled = RGBA_LOGICOP_ENABLED(ctx);
+}
+
+
+/*
+ * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET
+ * in ctx->_TriangleCaps if needed.
+ */
+static void
+update_polygon(GLcontext *ctx)
+{
+ ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET);
+
+ if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+ ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
+
+ if ( ctx->Polygon.OffsetPoint
+ || ctx->Polygon.OffsetLine
+ || ctx->Polygon.OffsetFill)
+ ctx->_TriangleCaps |= DD_TRI_OFFSET;
+}
+
+
+/**
+ * Update the ctx->_TriangleCaps bitfield.
+ * XXX that bitfield should really go away someday!
+ * This function must be called after other update_*() functions since
+ * there are dependencies on some other derived values.
+ */
+#if 0
+static void
+update_tricaps(GLcontext *ctx, GLbitfield new_state)
+{
+ ctx->_TriangleCaps = 0;
+
+ /*
+ * Points
+ */
+ if (1/*new_state & _NEW_POINT*/) {
+ if (ctx->Point.SmoothFlag)
+ ctx->_TriangleCaps |= DD_POINT_SMOOTH;
+ if (ctx->Point.Size != 1.0F)
+ ctx->_TriangleCaps |= DD_POINT_SIZE;
+ if (ctx->Point._Attenuated)
+ ctx->_TriangleCaps |= DD_POINT_ATTEN;
+ }
+
+ /*
+ * Lines
+ */
+ if (1/*new_state & _NEW_LINE*/) {
+ if (ctx->Line.SmoothFlag)
+ ctx->_TriangleCaps |= DD_LINE_SMOOTH;
+ if (ctx->Line.StippleFlag)
+ ctx->_TriangleCaps |= DD_LINE_STIPPLE;
+ if (ctx->Line.Width != 1.0)
+ ctx->_TriangleCaps |= DD_LINE_WIDTH;
+ }
+
+ /*
+ * Polygons
+ */
+ if (1/*new_state & _NEW_POLYGON*/) {
+ if (ctx->Polygon.SmoothFlag)
+ ctx->_TriangleCaps |= DD_TRI_SMOOTH;
+ if (ctx->Polygon.StippleFlag)
+ ctx->_TriangleCaps |= DD_TRI_STIPPLE;
+ if (ctx->Polygon.FrontMode != GL_FILL
+ || ctx->Polygon.BackMode != GL_FILL)
+ ctx->_TriangleCaps |= DD_TRI_UNFILLED;
+ if (ctx->Polygon.CullFlag
+ && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+ ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
+ if (ctx->Polygon.OffsetPoint ||
+ ctx->Polygon.OffsetLine ||
+ ctx->Polygon.OffsetFill)
+ ctx->_TriangleCaps |= DD_TRI_OFFSET;
+ }
+
+ /*
+ * Lighting and shading
+ */
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+ ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+ if (ctx->Light.ShadeModel == GL_FLAT)
+ ctx->_TriangleCaps |= DD_FLATSHADE;
+ if (NEED_SECONDARY_COLOR(ctx))
+ ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR;
+
+ /*
+ * Stencil
+ */
+ if (ctx->Stencil._TestTwoSide)
+ ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
+}
+#endif
+
+
+/**
+ * Compute derived GL state.
+ * If __GLcontextRec::NewState is non-zero then this function \b must
+ * be called before rendering anything.
+ *
+ * Calls dd_function_table::UpdateState to perform any internal state
+ * management necessary.
+ *
+ * \sa _mesa_update_modelview_project(), _mesa_update_texture(),
+ * _mesa_update_buffer_bounds(),
+ * _mesa_update_lighting() and _mesa_update_tnl_spaces().
+ */
+void
+_mesa_update_state_locked( GLcontext *ctx )
+{
+ GLbitfield new_state = ctx->NewState;
+ GLbitfield prog_flags = _NEW_PROGRAM;
+ GLbitfield new_prog_state = 0x0;
+
+ if (new_state == _NEW_CURRENT_ATTRIB)
+ goto out;
+
+ if (MESA_VERBOSE & VERBOSE_STATE)
+ _mesa_print_state("_mesa_update_state", new_state);
+
+ /* Determine which state flags effect vertex/fragment program state */
+ if (ctx->FragmentProgram._MaintainTexEnvProgram) {
+ prog_flags |= (_NEW_TEXTURE | _NEW_FOG |
+ _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE |
+ _NEW_PROGRAM);
+ }
+ if (ctx->VertexProgram._MaintainTnlProgram) {
+ prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
+ _NEW_TRANSFORM | _NEW_POINT |
+ _NEW_FOG | _NEW_LIGHT |
+ _MESA_NEW_NEED_EYE_COORDS);
+ }
+
+ /*
+ * Now update derived state info
+ */
+
+ if (new_state & prog_flags)
+ update_program_enables( ctx );
+
+ if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
+ _mesa_update_modelview_project( ctx, new_state );
+
+ if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX))
+ _mesa_update_texture( ctx, new_state );
+
+ if (new_state & _NEW_BUFFERS)
+ _mesa_update_framebuffer(ctx);
+
+ if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
+ _mesa_update_draw_buffer_bounds( ctx );
+
+ if (new_state & _NEW_POLYGON)
+ update_polygon( ctx );
+
+ if (new_state & _NEW_LIGHT)
+ _mesa_update_lighting( ctx );
+
+ if (new_state & (_NEW_STENCIL | _NEW_BUFFERS))
+ _mesa_update_stencil( ctx );
+
+#if FEATURE_pixel_transfer
+ if (new_state & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_pixel( ctx, new_state );
+#endif
+
+ if (new_state & _DD_NEW_SEPARATE_SPECULAR)
+ update_separate_specular( ctx );
+
+ if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT))
+ update_arrays( ctx );
+
+ if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT))
+ update_viewport_matrix(ctx);
+
+ if (new_state & _NEW_MULTISAMPLE)
+ update_multisample( ctx );
+
+ if (new_state & _NEW_COLOR)
+ update_color( ctx );
+
+#if 0
+ if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT
+ | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR))
+ update_tricaps( ctx, new_state );
+#endif
+
+ /* ctx->_NeedEyeCoords is now up to date.
+ *
+ * If the truth value of this variable has changed, update for the
+ * new lighting space and recompute the positions of lights and the
+ * normal transform.
+ *
+ * If the lighting space hasn't changed, may still need to recompute
+ * light positions & normal transforms for other reasons.
+ */
+ if (new_state & _MESA_NEW_NEED_EYE_COORDS)
+ _mesa_update_tnl_spaces( ctx, new_state );
+
+ if (new_state & prog_flags) {
+ /* When we generate programs from fixed-function vertex/fragment state
+ * this call may generate/bind a new program. If so, we need to
+ * propogate the _NEW_PROGRAM flag to the driver.
+ */
+ new_prog_state |= update_program( ctx );
+ }
+
+
+ out:
+ new_prog_state |= update_program_constants(ctx);
+
+ /*
+ * Give the driver a chance to act upon the new_state flags.
+ * The driver might plug in different span functions, for example.
+ * Also, this is where the driver can invalidate the state of any
+ * active modules (such as swrast_setup, swrast, tnl, etc).
+ *
+ * Set ctx->NewState to zero to avoid recursion if
+ * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?)
+ */
+ new_state = ctx->NewState | new_prog_state;
+ ctx->NewState = 0;
+ ctx->Driver.UpdateState(ctx, new_state);
+ ctx->Array.NewState = 0;
+}
+
+
+/* This is the usual entrypoint for state updates:
+ */
+void
+_mesa_update_state( GLcontext *ctx )
+{
+ _mesa_lock_context_textures(ctx);
+ _mesa_update_state_locked(ctx);
+ _mesa_unlock_context_textures(ctx);
+}
+
+
+
+
+/**
+ * Want to figure out which fragment program inputs are actually
+ * constant/current values from ctx->Current. These should be
+ * referenced as a tracked state variable rather than a fragment
+ * program input, to save the overhead of putting a constant value in
+ * every submitted vertex, transferring it to hardware, interpolating
+ * it across the triangle, etc...
+ *
+ * When there is a VP bound, just use vp->outputs. But when we're
+ * generating vp from fixed function state, basically want to
+ * calculate:
+ *
+ * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) |
+ * potential_vp_outputs )
+ *
+ * Where potential_vp_outputs is calculated by looking at enabled
+ * texgen, etc.
+ *
+ * The generated fragment program should then only declare inputs that
+ * may vary or otherwise differ from the ctx->Current values.
+ * Otherwise, the fp should track them as state values instead.
+ */
+void
+_mesa_set_varying_vp_inputs( GLcontext *ctx,
+ GLbitfield varying_inputs )
+{
+ if (ctx->varying_vp_inputs != varying_inputs) {
+ ctx->varying_vp_inputs = varying_inputs;
+ ctx->NewState |= _NEW_ARRAY;
+ /*_mesa_printf("%s %x\n", __FUNCTION__, varying_inputs);*/
+ }
+}
+
+
+/**
+ * Used by drivers to tell core Mesa that the driver is going to
+ * install/ use its own vertex program. In particular, this will
+ * prevent generated fragment programs from using state vars instead
+ * of ordinary varyings/inputs.
+ */
+void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag)
+{
+ if (ctx->VertexProgram._Overriden != flag) {
+ ctx->VertexProgram._Overriden = flag;
+
+ /* Set one of the bits which will trigger fragment program
+ * regeneration:
+ */
+ ctx->NewState |= _NEW_PROGRAM;
+ }
+}
diff --git a/mesalib/src/mesa/main/state.h b/mesalib/src/mesa/main/state.h
new file mode 100644
index 000000000..29db08a0b
--- /dev/null
+++ b/mesalib/src/mesa/main/state.h
@@ -0,0 +1,49 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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 STATE_H
+#define STATE_H
+
+#include "mtypes.h"
+
+extern void
+_mesa_update_state(GLcontext *ctx);
+
+/* As above but can only be called between _mesa_lock_context_textures() and
+ * _mesa_unlock_context_textures().
+ */
+extern void
+_mesa_update_state_locked(GLcontext *ctx);
+
+
+extern void
+_mesa_set_varying_vp_inputs(GLcontext *ctx, GLbitfield varying_inputs);
+
+
+extern void
+_mesa_set_vp_override(GLcontext *ctx, GLboolean flag);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/stencil.c b/mesalib/src/mesa/main/stencil.c
new file mode 100644
index 000000000..15c98e201
--- /dev/null
+++ b/mesalib/src/mesa/main/stencil.c
@@ -0,0 +1,590 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file stencil.c
+ * Stencil operations.
+ *
+ * Note: There's some conflict between GL_EXT_stencil_two_side and
+ * OpenGL 2.0's two-sided stencil feature.
+ *
+ * With GL_EXT_stencil_two_side, calling glStencilOp/Func/Mask() only the
+ * front OR back face state (as set by glActiveStencilFaceEXT) is set.
+ *
+ * But with OpenGL 2.0, calling glStencilOp/Func/Mask() sets BOTH the
+ * front AND back state.
+ *
+ * Also, note that GL_ATI_separate_stencil is different as well:
+ * glStencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, ...) vs.
+ * glStencilFuncSeparate(GLenum face, GLenum func, ...).
+ *
+ * This problem is solved by keeping three sets of stencil state:
+ * state[0] = GL_FRONT state.
+ * state[1] = OpenGL 2.0 / GL_ATI_separate_stencil GL_BACK state.
+ * state[2] = GL_EXT_stencil_two_side GL_BACK state.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "stencil.h"
+#include "mtypes.h"
+
+
+static GLboolean
+validate_stencil_op(GLcontext *ctx, GLenum op)
+{
+ switch (op) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ return GL_TRUE;
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+ if (ctx->Extensions.EXT_stencil_wrap) {
+ return GL_TRUE;
+ }
+ /* FALL-THROUGH */
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean
+validate_stencil_func(GLcontext *ctx, GLenum func)
+{
+ 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:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Set the clear value for the stencil buffer.
+ *
+ * \param s clear value.
+ *
+ * \sa glClearStencil().
+ *
+ * Updates gl_stencil_attrib::Clear. On change
+ * flushes the vertices and notifies the driver via
+ * the dd_function_table::ClearStencil callback.
+ */
+void GLAPIENTRY
+_mesa_ClearStencil( GLint s )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Stencil.Clear == (GLuint) s)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Clear = (GLuint) s;
+
+ if (ctx->Driver.ClearStencil) {
+ ctx->Driver.ClearStencil( ctx, s );
+ }
+}
+
+
+/**
+ * Set the function and reference value for stencil testing.
+ *
+ * \param frontfunc front test function.
+ * \param backfunc back test function.
+ * \param ref front and back reference value.
+ * \param mask front and back bitmask.
+ *
+ * \sa glStencilFunc().
+ *
+ * Verifies the parameters and updates the respective values in
+ * __GLcontextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilFunc callback.
+ */
+void GLAPIENTRY
+_mesa_StencilFuncSeparateATI( GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!validate_stencil_func(ctx, frontfunc)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glStencilFuncSeparateATI(frontfunc)");
+ return;
+ }
+ if (!validate_stencil_func(ctx, backfunc)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glStencilFuncSeparateATI(backfunc)");
+ return;
+ }
+
+ ref = CLAMP( ref, 0, stencilMax );
+
+ /* set both front and back state */
+ if (ctx->Stencil.Function[0] == frontfunc &&
+ ctx->Stencil.Function[1] == backfunc &&
+ ctx->Stencil.ValueMask[0] == mask &&
+ ctx->Stencil.ValueMask[1] == mask &&
+ ctx->Stencil.Ref[0] == ref &&
+ ctx->Stencil.Ref[1] == ref)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Function[0] = frontfunc;
+ ctx->Stencil.Function[1] = backfunc;
+ ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref;
+ ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
+ if (ctx->Driver.StencilFuncSeparate) {
+ ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
+ frontfunc, ref, mask);
+ ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
+ backfunc, ref, mask);
+ }
+}
+
+
+/**
+ * Set the function and reference value for stencil testing.
+ *
+ * \param func test function.
+ * \param ref reference value.
+ * \param mask bitmask.
+ *
+ * \sa glStencilFunc().
+ *
+ * Verifies the parameters and updates the respective values in
+ * __GLcontextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilFunc callback.
+ */
+void GLAPIENTRY
+_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+ const GLint face = ctx->Stencil.ActiveFace;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!validate_stencil_func(ctx, func)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFunc(func)");
+ return;
+ }
+
+ ref = CLAMP( ref, 0, stencilMax );
+
+ if (face != 0) {
+ if (ctx->Stencil.Function[face] == func &&
+ ctx->Stencil.ValueMask[face] == mask &&
+ ctx->Stencil.Ref[face] == ref)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Function[face] = func;
+ ctx->Stencil.Ref[face] = ref;
+ ctx->Stencil.ValueMask[face] = mask;
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilFuncSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, func, ref, mask);
+ }
+ }
+ else {
+ /* set both front and back state */
+ if (ctx->Stencil.Function[0] == func &&
+ ctx->Stencil.Function[1] == func &&
+ ctx->Stencil.ValueMask[0] == mask &&
+ ctx->Stencil.ValueMask[1] == mask &&
+ ctx->Stencil.Ref[0] == ref &&
+ ctx->Stencil.Ref[1] == ref)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Function[0] = ctx->Stencil.Function[1] = func;
+ ctx->Stencil.Ref[0] = ctx->Stencil.Ref[1] = ref;
+ ctx->Stencil.ValueMask[0] = ctx->Stencil.ValueMask[1] = mask;
+ if (ctx->Driver.StencilFuncSeparate) {
+ ctx->Driver.StencilFuncSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
+ func, ref, mask);
+ }
+ }
+}
+
+
+/**
+ * Set the stencil writing mask.
+ *
+ * \param mask bit-mask to enable/disable writing of individual bits in the
+ * stencil planes.
+ *
+ * \sa glStencilMask().
+ *
+ * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and
+ * notifies the driver via the dd_function_table::StencilMask callback.
+ */
+void GLAPIENTRY
+_mesa_StencilMask( GLuint mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLint face = ctx->Stencil.ActiveFace;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (face != 0) {
+ /* Only modify the EXT_stencil_two_side back-face state.
+ */
+ if (ctx->Stencil.WriteMask[face] == mask)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.WriteMask[face] = mask;
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilMaskSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, mask);
+ }
+ }
+ else {
+ /* set both front and back state */
+ if (ctx->Stencil.WriteMask[0] == mask &&
+ ctx->Stencil.WriteMask[1] == mask)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
+ if (ctx->Driver.StencilMaskSeparate) {
+ ctx->Driver.StencilMaskSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
+ mask);
+ }
+ }
+}
+
+
+/**
+ * Set the stencil test actions.
+ *
+ * \param fail action to take when stencil test fails.
+ * \param zfail action to take when stencil test passes, but depth test fails.
+ * \param zpass action to take when stencil test passes and the depth test
+ * passes (or depth testing is not enabled).
+ *
+ * \sa glStencilOp().
+ *
+ * Verifies the parameters and updates the respective fields in
+ * __GLcontextRec::Stencil. On change flushes the vertices and notifies the
+ * driver via the dd_function_table::StencilOp callback.
+ */
+void GLAPIENTRY
+_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLint face = ctx->Stencil.ActiveFace;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!validate_stencil_op(ctx, fail)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)");
+ return;
+ }
+ if (!validate_stencil_op(ctx, zfail)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)");
+ return;
+ }
+ if (!validate_stencil_op(ctx, zpass)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)");
+ return;
+ }
+
+ if (face != 0) {
+ /* only set active face state */
+ if (ctx->Stencil.ZFailFunc[face] == zfail &&
+ ctx->Stencil.ZPassFunc[face] == zpass &&
+ ctx->Stencil.FailFunc[face] == fail)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.ZFailFunc[face] = zfail;
+ ctx->Stencil.ZPassFunc[face] = zpass;
+ ctx->Stencil.FailFunc[face] = fail;
+
+ /* Only propagate the change to the driver if EXT_stencil_two_side
+ * is enabled.
+ */
+ if (ctx->Driver.StencilOpSeparate && ctx->Stencil.TestTwoSide) {
+ ctx->Driver.StencilOpSeparate(ctx, GL_BACK, fail, zfail, zpass);
+ }
+ }
+ else {
+ /* set both front and back state */
+ if (ctx->Stencil.ZFailFunc[0] == zfail &&
+ ctx->Stencil.ZFailFunc[1] == zfail &&
+ ctx->Stencil.ZPassFunc[0] == zpass &&
+ ctx->Stencil.ZPassFunc[1] == zpass &&
+ ctx->Stencil.FailFunc[0] == fail &&
+ ctx->Stencil.FailFunc[1] == fail)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail;
+ ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass;
+ ctx->Stencil.FailFunc[0] = ctx->Stencil.FailFunc[1] = fail;
+ if (ctx->Driver.StencilOpSeparate) {
+ ctx->Driver.StencilOpSeparate(ctx,
+ ((ctx->Stencil.TestTwoSide)
+ ? GL_FRONT : GL_FRONT_AND_BACK),
+ fail, zfail, zpass);
+ }
+ }
+}
+
+
+
+#if _HAVE_FULL_GL
+/* GL_EXT_stencil_two_side */
+void GLAPIENTRY
+_mesa_ActiveStencilFaceEXT(GLenum face)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.EXT_stencil_two_side) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT");
+ return;
+ }
+
+ if (face == GL_FRONT || face == GL_BACK) {
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 2;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)");
+ }
+}
+#endif
+
+
+
+/**
+ * OpenGL 2.0 function.
+ * \todo Make StencilOp() call this function. And eventually remove the
+ * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate
+ * instead.
+ */
+void GLAPIENTRY
+_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass)
+{
+ GLboolean set = GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!validate_stencil_op(ctx, sfail)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)");
+ return;
+ }
+ if (!validate_stencil_op(ctx, zfail)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)");
+ return;
+ }
+ if (!validate_stencil_op(ctx, zpass)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)");
+ return;
+ }
+ if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)");
+ return;
+ }
+
+ if (face != GL_BACK) {
+ /* set front */
+ if (ctx->Stencil.ZFailFunc[0] != zfail ||
+ ctx->Stencil.ZPassFunc[0] != zpass ||
+ ctx->Stencil.FailFunc[0] != sfail){
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.ZFailFunc[0] = zfail;
+ ctx->Stencil.ZPassFunc[0] = zpass;
+ ctx->Stencil.FailFunc[0] = sfail;
+ set = GL_TRUE;
+ }
+ }
+ if (face != GL_FRONT) {
+ /* set back */
+ if (ctx->Stencil.ZFailFunc[1] != zfail ||
+ ctx->Stencil.ZPassFunc[1] != zpass ||
+ ctx->Stencil.FailFunc[1] != sfail) {
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.ZFailFunc[1] = zfail;
+ ctx->Stencil.ZPassFunc[1] = zpass;
+ ctx->Stencil.FailFunc[1] = sfail;
+ set = GL_TRUE;
+ }
+ }
+ if (set && ctx->Driver.StencilOpSeparate) {
+ ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass);
+ }
+}
+
+
+/* OpenGL 2.0 */
+void GLAPIENTRY
+_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)");
+ return;
+ }
+ if (!validate_stencil_func(ctx, func)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)");
+ return;
+ }
+
+ ref = CLAMP(ref, 0, stencilMax);
+
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+
+ if (face != GL_BACK) {
+ /* set front */
+ ctx->Stencil.Function[0] = func;
+ ctx->Stencil.Ref[0] = ref;
+ ctx->Stencil.ValueMask[0] = mask;
+ }
+ if (face != GL_FRONT) {
+ /* set back */
+ ctx->Stencil.Function[1] = func;
+ ctx->Stencil.Ref[1] = ref;
+ ctx->Stencil.ValueMask[1] = mask;
+ }
+ if (ctx->Driver.StencilFuncSeparate) {
+ ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
+ }
+}
+
+
+/* OpenGL 2.0 */
+void GLAPIENTRY
+_mesa_StencilMaskSeparate(GLenum face, GLuint mask)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+
+ if (face != GL_BACK) {
+ ctx->Stencil.WriteMask[0] = mask;
+ }
+ if (face != GL_FRONT) {
+ ctx->Stencil.WriteMask[1] = mask;
+ }
+ if (ctx->Driver.StencilMaskSeparate) {
+ ctx->Driver.StencilMaskSeparate(ctx, face, mask);
+ }
+}
+
+
+/**
+ * Update derived stencil state.
+ */
+void
+_mesa_update_stencil(GLcontext *ctx)
+{
+ const GLint face = ctx->Stencil._BackFace;
+
+ ctx->Stencil._Enabled = (ctx->Stencil.Enabled &&
+ ctx->DrawBuffer->Visual.stencilBits > 0);
+
+ ctx->Stencil._TestTwoSide =
+ ctx->Stencil._Enabled &&
+ (ctx->Stencil.Function[0] != ctx->Stencil.Function[face] ||
+ ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[face] ||
+ ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[face] ||
+ ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[face] ||
+ ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] ||
+ ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] ||
+ ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]);
+}
+
+
+/**
+ * Initialize the context stipple state.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes __GLcontextRec::Stencil attribute group.
+ */
+void
+_mesa_init_stencil(GLcontext *ctx)
+{
+ ctx->Stencil.Enabled = GL_FALSE;
+ ctx->Stencil.TestTwoSide = GL_FALSE;
+ ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 2 = GL_BACK */
+ ctx->Stencil.Function[0] = GL_ALWAYS;
+ ctx->Stencil.Function[1] = GL_ALWAYS;
+ ctx->Stencil.Function[2] = GL_ALWAYS;
+ ctx->Stencil.FailFunc[0] = GL_KEEP;
+ ctx->Stencil.FailFunc[1] = GL_KEEP;
+ ctx->Stencil.FailFunc[2] = GL_KEEP;
+ ctx->Stencil.ZPassFunc[0] = GL_KEEP;
+ ctx->Stencil.ZPassFunc[1] = GL_KEEP;
+ ctx->Stencil.ZPassFunc[2] = GL_KEEP;
+ ctx->Stencil.ZFailFunc[0] = GL_KEEP;
+ ctx->Stencil.ZFailFunc[1] = GL_KEEP;
+ ctx->Stencil.ZFailFunc[2] = GL_KEEP;
+ ctx->Stencil.Ref[0] = 0;
+ ctx->Stencil.Ref[1] = 0;
+ ctx->Stencil.Ref[2] = 0;
+ ctx->Stencil.ValueMask[0] = ~0U;
+ ctx->Stencil.ValueMask[1] = ~0U;
+ ctx->Stencil.ValueMask[2] = ~0U;
+ ctx->Stencil.WriteMask[0] = ~0U;
+ ctx->Stencil.WriteMask[1] = ~0U;
+ ctx->Stencil.WriteMask[2] = ~0U;
+ ctx->Stencil.Clear = 0;
+ ctx->Stencil._BackFace = 1;
+}
diff --git a/mesalib/src/mesa/main/stencil.h b/mesalib/src/mesa/main/stencil.h
new file mode 100644
index 000000000..252ac932a
--- /dev/null
+++ b/mesalib/src/mesa/main/stencil.h
@@ -0,0 +1,80 @@
+/**
+ * \file stencil.h
+ * Stencil operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "mtypes.h"
+
+
+extern void GLAPIENTRY
+_mesa_ClearStencil( GLint s );
+
+
+extern void GLAPIENTRY
+_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask );
+
+
+extern void GLAPIENTRY
+_mesa_StencilMask( GLuint mask );
+
+
+extern void GLAPIENTRY
+_mesa_StencilOp( GLenum fail, GLenum zfail, GLenum zpass );
+
+
+extern void GLAPIENTRY
+_mesa_ActiveStencilFaceEXT(GLenum face);
+
+
+extern void GLAPIENTRY
+_mesa_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+
+
+extern void GLAPIENTRY
+_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+
+
+extern void GLAPIENTRY
+_mesa_StencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+
+extern void GLAPIENTRY
+_mesa_StencilMaskSeparate(GLenum face, GLuint mask);
+
+
+extern void
+_mesa_update_stencil(GLcontext *ctx);
+
+
+extern void
+_mesa_init_stencil( GLcontext * ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c
new file mode 100644
index 000000000..64f923ff9
--- /dev/null
+++ b/mesalib/src/mesa/main/syncobj.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file syncobj.c
+ * Sync object management.
+ *
+ * Unlike textures and other objects that are shared between contexts, sync
+ * objects are not bound to the context. As a result, the reference counting
+ * and delete behavior of sync objects is slightly different. References to
+ * sync objects are added:
+ *
+ * - By \c glFencSynce. This sets the initial reference count to 1.
+ * - At the start of \c glClientWaitSync. The reference is held for the
+ * duration of the wait call.
+ *
+ * References are removed:
+ *
+ * - By \c glDeleteSync.
+ * - At the end of \c glClientWaitSync.
+ *
+ * Additionally, drivers may call \c _mesa_ref_sync_object and
+ * \c _mesa_unref_sync_object as needed to implement \c ServerWaitSync.
+ *
+ * As with shader objects, sync object names become invalid as soon as
+ * \c glDeleteSync is called. For this reason \c glDeleteSync sets the
+ * \c DeletePending flag. All functions validate object handles by testing
+ * this flag.
+ *
+ * \note
+ * Only \c GL_ARB_sync objects are shared between contexts. If support is ever
+ * added for either \c GL_NV_fence or \c GL_APPLE_fence different semantics
+ * will need to be implemented.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+
+#if FEATURE_ARB_sync
+#include "syncobj.h"
+
+static struct gl_sync_object *
+_mesa_new_sync_object(GLcontext *ctx, GLenum type)
+{
+ struct gl_sync_object *s = MALLOC_STRUCT(gl_sync_object);
+ (void) ctx;
+ (void) type;
+
+ return s;
+}
+
+
+static void
+_mesa_delete_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ (void) ctx;
+ _mesa_free(syncObj);
+}
+
+
+static void
+_mesa_fence_sync(GLcontext *ctx, struct gl_sync_object *syncObj,
+ GLenum condition, GLbitfield flags)
+{
+ (void) ctx;
+ (void) condition;
+ (void) flags;
+
+ syncObj->StatusFlag = 1;
+}
+
+
+static void
+_mesa_check_sync(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ (void) ctx;
+ (void) syncObj;
+
+ /* No-op for software rendering. Hardware drivers will need to determine
+ * whether the state of the sync object has changed.
+ */
+}
+
+
+static void
+_mesa_wait_sync(GLcontext *ctx, struct gl_sync_object *syncObj,
+ GLbitfield flags, GLuint64 timeout)
+{
+ (void) ctx;
+ (void) syncObj;
+ (void) flags;
+ (void) timeout;
+
+ /* No-op for software rendering. Hardware drivers will need to wait until
+ * the state of the sync object changes or the timeout expires.
+ */
+}
+
+
+void
+_mesa_init_sync_object_functions(struct dd_function_table *driver)
+{
+ driver->NewSyncObject = _mesa_new_sync_object;
+ driver->FenceSync = _mesa_fence_sync;
+ driver->DeleteSyncObject = _mesa_delete_sync_object;
+ driver->CheckSync = _mesa_check_sync;
+
+ /* Use the same no-op wait function for both.
+ */
+ driver->ClientWaitSync = _mesa_wait_sync;
+ driver->ServerWaitSync = _mesa_wait_sync;
+}
+
+
+/**
+ * Allocate/init the context state related to sync objects.
+ */
+void
+_mesa_init_sync(GLcontext *ctx)
+{
+ (void) ctx;
+}
+
+
+/**
+ * Free the context state related to sync objects.
+ */
+void
+_mesa_free_sync_data(GLcontext *ctx)
+{
+ (void) ctx;
+}
+
+
+static int
+_mesa_validate_sync(struct gl_sync_object *syncObj)
+{
+ return (syncObj != NULL)
+ && (syncObj->Type == GL_SYNC_FENCE)
+ && !syncObj->DeletePending;
+}
+
+
+void
+_mesa_ref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ syncObj->RefCount++;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+void
+_mesa_unref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj)
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ syncObj->RefCount--;
+ if (syncObj->RefCount == 0) {
+ remove_from_list(& syncObj->link);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ ctx->Driver.DeleteSyncObject(ctx, syncObj);
+ } else {
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+}
+
+
+GLboolean
+_mesa_IsSync(GLsync sync)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ return _mesa_validate_sync(syncObj) ? GL_TRUE : GL_FALSE;
+}
+
+
+void
+_mesa_DeleteSync(GLsync sync)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* From the GL_ARB_sync spec:
+ *
+ * DeleteSync will silently ignore a <sync> value of zero. An
+ * INVALID_VALUE error is generated if <sync> is neither zero nor the
+ * name of a sync object.
+ */
+ if (sync == 0) {
+ return;
+ }
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteSync");
+ return;
+ }
+
+ /* If there are no client-waits or server-waits pending on this sync, delete
+ * the underlying object.
+ */
+ syncObj->DeletePending = GL_TRUE;
+ _mesa_unref_sync_object(ctx, syncObj);
+}
+
+
+GLsync
+_mesa_FenceSync(GLenum condition, GLbitfield flags)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *syncObj;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
+
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glFenceSync(condition=0x%x)",
+ condition);
+ return 0;
+ }
+
+ if (flags != 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glFenceSync(flags=0x%x)",
+ condition);
+ return 0;
+ }
+
+ syncObj = ctx->Driver.NewSyncObject(ctx, GL_SYNC_FENCE);
+ if (syncObj != NULL) {
+ syncObj->Type = GL_SYNC_FENCE;
+ /* The name is not currently used, and it is never visible to
+ * applications. If sync support is extended to provide support for
+ * NV_fence, this field will be used. We'll also need to add an object
+ * ID hashtable.
+ */
+ syncObj->Name = 1;
+ syncObj->RefCount = 1;
+ syncObj->DeletePending = GL_FALSE;
+ syncObj->SyncCondition = condition;
+ syncObj->Flags = flags;
+ syncObj->StatusFlag = 0;
+
+ ctx->Driver.FenceSync(ctx, syncObj, condition, flags);
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ insert_at_tail(& ctx->Shared->SyncObjects, & syncObj->link);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ return (GLsync) syncObj;
+ }
+
+ return NULL;
+}
+
+
+GLenum
+_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ GLenum ret;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glClientWaitSync");
+ return GL_WAIT_FAILED;
+ }
+
+ if ((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) != 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClientWaitSync(flags=0x%x)", flags);
+ return GL_WAIT_FAILED;
+ }
+
+ _mesa_ref_sync_object(ctx, syncObj);
+
+ /* From the GL_ARB_sync spec:
+ *
+ * ClientWaitSync returns one of four status values. A return value of
+ * ALREADY_SIGNALED indicates that <sync> was signaled at the time
+ * ClientWaitSync was called. ALREADY_SIGNALED will always be returned
+ * if <sync> was signaled, even if the value of <timeout> is zero.
+ */
+ ctx->Driver.CheckSync(ctx, syncObj);
+ if (syncObj->StatusFlag) {
+ ret = GL_ALREADY_SIGNALED;
+ } else {
+ ctx->Driver.ClientWaitSync(ctx, syncObj, flags, timeout);
+
+ ret = syncObj->StatusFlag ? GL_CONDITION_SATISFIED : GL_TIMEOUT_EXPIRED;
+ }
+
+ _mesa_unref_sync_object(ctx, syncObj);
+ return ret;
+}
+
+
+void
+_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glWaitSync");
+ return;
+ }
+
+ if (flags != 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glWaitSync(flags=0x%x)", flags);
+ return;
+ }
+
+ /* From the GL_ARB_sync spec:
+ *
+ * If the value of <timeout> is zero, then WaitSync does nothing.
+ */
+ if (timeout == 0) {
+ return;
+ }
+
+ ctx->Driver.ServerWaitSync(ctx, syncObj, flags, timeout);
+}
+
+
+void
+_mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
+ GLint *values)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync;
+ GLsizei size = 0;
+ GLint v[1];
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!_mesa_validate_sync(syncObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSynciv");
+ return;
+ }
+
+ switch (pname) {
+ case GL_OBJECT_TYPE:
+ v[0] = syncObj->Type;
+ size = 1;
+ break;
+
+ case GL_SYNC_CONDITION:
+ v[0] = syncObj->SyncCondition;
+ size = 1;
+ break;
+
+ case GL_SYNC_STATUS:
+ /* Update the state of the sync by dipping into the driver. Note that
+ * this call won't block. It just updates state in the common object
+ * data from the current driver state.
+ */
+ ctx->Driver.CheckSync(ctx, syncObj);
+
+ v[0] = (syncObj->StatusFlag) ? GL_SIGNALED : GL_UNSIGNALED;
+ size = 1;
+ break;
+
+ case GL_SYNC_FLAGS:
+ v[0] = syncObj->Flags;
+ size = 1;
+ break;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetSynciv(pname=0x%x)\n", pname);
+ return;
+ }
+
+ if (size > 0) {
+ const GLsizei copy_count = MIN2(size, bufSize);
+
+ _mesa_memcpy(values, v, sizeof(GLint) * copy_count);
+ }
+
+ if (length != NULL) {
+ *length = size;
+ }
+}
+
+#endif /* FEATURE_ARB_sync */
diff --git a/mesalib/src/mesa/main/syncobj.h b/mesalib/src/mesa/main/syncobj.h
new file mode 100644
index 000000000..fc160af28
--- /dev/null
+++ b/mesalib/src/mesa/main/syncobj.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file syncobj.h
+ * Sync object management.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#ifndef SYNCOBJ_H
+#define SYNCOBJ_H
+
+#include "context.h"
+
+extern void
+_mesa_init_sync_object_functions(struct dd_function_table *driver);
+
+extern void
+_mesa_init_sync(GLcontext *);
+
+extern void
+_mesa_free_sync_data(GLcontext *);
+
+extern void
+_mesa_ref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj);
+
+extern void
+_mesa_unref_sync_object(GLcontext *ctx, struct gl_sync_object *syncObj);
+
+extern GLboolean
+_mesa_IsSync(GLsync sync);
+
+extern void
+_mesa_DeleteSync(GLsync sync);
+
+extern GLsync
+_mesa_FenceSync(GLenum condition, GLbitfield flags);
+
+extern GLenum
+_mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+extern void
+_mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+extern void
+_mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
+ GLint *values);
+
+#endif /* SYNCOBJ_H */
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
new file mode 100644
index 000000000..c1b8c7675
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -0,0 +1,362 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texcompress.c
+ * Helper functions for texture compression.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "image.h"
+#include "mipmap.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texstore.h"
+
+
+/**
+ * Return list of (and count of) all specific texture compression
+ * formats that are supported.
+ *
+ * \param ctx the GL context
+ * \param formats the resulting format list (may be NULL).
+ * \param all if true return all formats, even those with some kind
+ * of restrictions/limitations (See GL_ARB_texture_compression
+ * spec for more info).
+ *
+ * \return number of formats.
+ */
+GLuint
+_mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all)
+{
+ GLuint n = 0;
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX;
+ formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ }
+ else {
+ n += 2;
+ }
+ }
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ /* This format has some restrictions/limitations and so should
+ * not be returned via the GL_COMPRESSED_TEXTURE_FORMATS query.
+ * Specifically, all transparent pixels become black. NVIDIA
+ * omits this format too.
+ */
+ if (all)
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ }
+ else {
+ n += 3;
+ if (all)
+ n += 1;
+ }
+ }
+ if (ctx->Extensions.S3_s3tc) {
+ if (formats) {
+ formats[n++] = GL_RGB_S3TC;
+ formats[n++] = GL_RGB4_S3TC;
+ formats[n++] = GL_RGBA_S3TC;
+ formats[n++] = GL_RGBA4_S3TC;
+ }
+ else {
+ n += 4;
+ }
+ }
+#if FEATURE_EXT_texture_sRGB
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ if (formats) {
+ formats[n++] = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ formats[n++] = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ }
+ else {
+ n += 4;
+ }
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+ return n;
+}
+
+
+
+/**
+ * Return number of bytes needed to store a texture of the given size
+ * using the specified compressed format.
+ * This is called via the ctx->Driver.CompressedTextureSize function,
+ * unless a device driver overrides it.
+ *
+ * \param width texture width in texels.
+ * \param height texture height in texels.
+ * \param depth texture depth in texels.
+ * \param mesaFormat one of the MESA_FORMAT_* compressed formats
+ *
+ * \return size in bytes, or zero if bad format
+ */
+GLuint
+_mesa_compressed_texture_size( GLcontext *ctx,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLuint mesaFormat )
+{
+ GLuint size;
+
+ ASSERT(depth == 1);
+ (void) depth;
+ (void) size;
+
+ switch (mesaFormat) {
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+ /* round up width to next multiple of 8, height to next multiple of 4 */
+ width = (width + 7) & ~7;
+ height = (height + 3) & ~3;
+ /* 16 bytes per 8x4 tile of RGB[A] texels */
+ size = width * height / 2;
+ /* Textures smaller than 8x4 will effectively be made into 8x4 and
+ * take 16 bytes.
+ */
+ return size;
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
+ /* round up width, height to next multiple of 4 */
+ width = (width + 3) & ~3;
+ height = (height + 3) & ~3;
+ /* 8 bytes per 4x4 tile of RGB[A] texels */
+ size = width * height / 2;
+ /* Textures smaller than 4x4 will effectively be made into 4x4 and
+ * take 8 bytes.
+ */
+ return size;
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
+ /* round up width, height to next multiple of 4 */
+ width = (width + 3) & ~3;
+ height = (height + 3) & ~3;
+ /* 16 bytes per 4x4 tile of RGBA texels */
+ size = width * height; /* simple! */
+ /* Textures smaller than 4x4 will effectively be made into 4x4 and
+ * take 16 bytes.
+ */
+ return size;
+#endif
+ default:
+ _mesa_problem(ctx, "bad mesaFormat in _mesa_compressed_texture_size");
+ return 0;
+ }
+}
+
+
+/**
+ * As above, but format is specified by a GLenum (GL_COMPRESSED_*) token.
+ *
+ * Note: This function CAN NOT return a padded hardware texture size.
+ * That's why we don't call the ctx->Driver.CompressedTextureSize() function.
+ *
+ * We use this function to validate the <imageSize> parameter
+ * of glCompressedTex[Sub]Image1/2/3D(), which must be an exact match.
+ */
+GLuint
+_mesa_compressed_texture_size_glenum(GLcontext *ctx,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLenum glformat)
+{
+ GLuint mesaFormat;
+
+ switch (glformat) {
+#if FEATURE_texture_fxt1
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ mesaFormat = MESA_FORMAT_RGB_FXT1;
+ break;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ mesaFormat = MESA_FORMAT_RGBA_FXT1;
+ break;
+#endif
+#if FEATURE_texture_s3tc
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_RGB_S3TC:
+ mesaFormat = MESA_FORMAT_RGB_DXT1;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_RGB4_S3TC:
+ mesaFormat = MESA_FORMAT_RGBA_DXT1;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_RGBA_S3TC:
+ mesaFormat = MESA_FORMAT_RGBA_DXT3;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_RGBA4_S3TC:
+ mesaFormat = MESA_FORMAT_RGBA_DXT5;
+ break;
+#if FEATURE_EXT_texture_sRGB
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGB_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT3;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ mesaFormat = MESA_FORMAT_SRGBA_DXT5;
+ break;
+#endif
+#endif
+ default:
+ return 0;
+ }
+
+ return _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
+}
+
+
+/*
+ * Compute the bytes per row in a compressed texture image.
+ * We use this for computing the destination address for sub-texture updates.
+ * \param mesaFormat one of the MESA_FORMAT_* compressed formats
+ * \param width image width in pixels
+ * \return stride, in bytes, between rows for compressed image
+ */
+GLint
+_mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width)
+{
+ GLint stride;
+
+ switch (mesaFormat) {
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+ stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */
+ break;
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
+ stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */
+ break;
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
+ stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */
+ break;
+#endif
+ default:
+ _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_row_stride");
+ return 0;
+ }
+
+ return stride;
+}
+
+
+/*
+ * Return the address of the pixel at (col, row, img) in a
+ * compressed texture image.
+ * \param col, row, img - image position (3D)
+ * \param format - compressed image format
+ * \param width - image width
+ * \param image - the image address
+ * \return address of pixel at (row, col)
+ */
+GLubyte *
+_mesa_compressed_image_address(GLint col, GLint row, GLint img,
+ GLuint mesaFormat,
+ GLsizei width, const GLubyte *image)
+{
+ GLubyte *addr;
+
+ (void) img;
+
+ /* We try to spot a "complete" subtexture "above" ROW, COL;
+ * this texture is given by appropriate rounding of WIDTH x ROW.
+ * Then we just add the amount left (usually on the left).
+ *
+ * Example for X*Y microtiles (Z bytes each)
+ * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X);
+ */
+
+ switch (mesaFormat) {
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+ addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8);
+ break;
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+#endif
+ addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4);
+ break;
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
+ addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4);
+ break;
+#endif
+ default:
+ _mesa_problem(NULL, "bad mesaFormat in _mesa_compressed_image_address");
+ addr = NULL;
+ }
+
+ return addr;
+}
diff --git a/mesalib/src/mesa/main/texcompress.h b/mesalib/src/mesa/main/texcompress.h
new file mode 100644
index 000000000..44f333822
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress.h
@@ -0,0 +1,74 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 TEXCOMPRESS_H
+#define TEXCOMPRESS_H
+
+#include "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern GLuint
+_mesa_get_compressed_formats(GLcontext *ctx, GLint *formats, GLboolean all);
+
+extern GLuint
+_mesa_compressed_texture_size( GLcontext *ctx,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLuint mesaFormat );
+
+extern GLuint
+_mesa_compressed_texture_size_glenum(GLcontext *ctx,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLenum glformat);
+
+extern GLint
+_mesa_compressed_row_stride(GLuint mesaFormat, GLsizei width);
+
+
+extern GLubyte *
+_mesa_compressed_image_address(GLint col, GLint row, GLint img,
+ GLuint mesaFormat,
+ GLsizei width, const GLubyte *image);
+
+
+extern void
+_mesa_init_texture_s3tc( GLcontext *ctx );
+
+extern void
+_mesa_init_texture_fxt1( GLcontext *ctx );
+
+
+#else /* _HAVE_FULL_GL */
+
+/* no-op macros */
+#define _mesa_get_compressed_formats( c, f ) 0
+#define _mesa_compressed_texture_size( c, w, h, d, f ) 0
+#define _mesa_compressed_texture_size_glenum( c, w, h, d, f ) 0
+#define _mesa_compressed_row_stride( f, w) 0
+#define _mesa_compressed_image_address(c, r, i, f, w, i2 ) 0
+#define _mesa_compress_teximage( c, w, h, sF, s, sRS, dF, d, drs ) ((void)0)
+
+#endif /* _HAVE_FULL_GL */
+
+#endif /* TEXCOMPRESS_H */
diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c
new file mode 100644
index 000000000..fc151605c
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_fxt1.c
@@ -0,0 +1,1724 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file texcompress_fxt1.c
+ * GL_EXT_texture_compression_fxt1 support.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "convolve.h"
+#include "image.h"
+#include "mipmap.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texstore.h"
+
+
+static void
+fxt1_encode (GLuint width, GLuint height, GLint comps,
+ const void *source, GLint srcRowStride,
+ void *dest, GLint destRowStride);
+
+void
+fxt1_decode_1 (const void *texture, GLint stride,
+ GLint i, GLint j, GLchan *rgba);
+
+
+/**
+ * Called during context initialization.
+ */
+void
+_mesa_init_texture_fxt1( GLcontext *ctx )
+{
+ (void) ctx;
+}
+
+
+/**
+ * Called via TexFormat->StoreImage to store an RGB_FXT1 texture.
+ */
+static GLboolean
+texstore_rgb_fxt1(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ const GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgb_fxt1);
+ ASSERT(dstXoffset % 8 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGB ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGB/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 3 * srcWidth;
+ srcFormat = GL_RGB;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+
+ fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride,
+ dst, dstRowStride);
+
+ if (tempImage)
+ _mesa_free((void*) tempImage);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via TexFormat->StoreImage to store an RGBA_FXT1 texture.
+ */
+static GLboolean
+texstore_rgba_fxt1(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_fxt1);
+ ASSERT(dstXoffset % 8 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGBA ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGBA/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 4 * srcWidth;
+ srcFormat = GL_RGBA;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+
+ fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride,
+ dst, dstRowStride);
+
+ if (tempImage)
+ _mesa_free((void*) tempImage);
+
+ return GL_TRUE;
+}
+
+
+static void
+fetch_texel_2d_rgba_fxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel);
+}
+
+
+static void
+fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ (void) k;
+ fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+
+static void
+fetch_texel_2d_rgb_fxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel);
+ texel[ACOMP] = 255;
+}
+
+
+static void
+fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ (void) k;
+ fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = 1.0F;
+}
+
+
+
+const struct gl_texture_format _mesa_texformat_rgb_fxt1 = {
+ MESA_FORMAT_RGB_FXT1, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgb_fxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgb_fxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb_fxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
+ MESA_FORMAT_RGBA_FXT1, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 1, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_fxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_fxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_fxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+
+/***************************************************************************\
+ * FXT1 encoder
+ *
+ * The encoder was built by reversing the decoder,
+ * and is vaguely based on Texus2 by 3dfx. Note that this code
+ * is merely a proof of concept, since it is highly UNoptimized;
+ * moreover, it is sub-optimal due to initial conditions passed
+ * to Lloyd's algorithm (the interpolation modes are even worse).
+\***************************************************************************/
+
+
+#define MAX_COMP 4 /* ever needed maximum number of components in texel */
+#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
+#define N_TEXELS 32 /* number of texels in a block (always 32) */
+#define LL_N_REP 50 /* number of iterations in lloyd's vq */
+#define LL_RMS_D 10 /* fault tolerance (maximum delta) */
+#define LL_RMS_E 255 /* fault tolerance (maximum error) */
+#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
+#define ISTBLACK(v) (*((GLuint *)(v)) == 0)
+
+
+/*
+ * Define a 64-bit unsigned integer type and macros
+ */
+#if 1
+
+#define FX64_NATIVE 1
+
+typedef uint64_t Fx64;
+
+#define FX64_MOV32(a, b) a = b
+#define FX64_OR32(a, b) a |= b
+#define FX64_SHL(a, c) a <<= c
+
+#else
+
+#define FX64_NATIVE 0
+
+typedef struct {
+ GLuint lo, hi;
+} Fx64;
+
+#define FX64_MOV32(a, b) a.lo = b
+#define FX64_OR32(a, b) a.lo |= b
+
+#define FX64_SHL(a, c) \
+ do { \
+ if ((c) >= 32) { \
+ a.hi = a.lo << ((c) - 32); \
+ a.lo = 0; \
+ } else { \
+ a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
+ a.lo <<= (c); \
+ } \
+ } while (0)
+
+#endif
+
+
+#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
+#define SAFECDOT 1 /* for paranoids */
+
+#define MAKEIVEC(NV, NC, IV, B, V0, V1) \
+ do { \
+ /* compute interpolation vector */ \
+ GLfloat d2 = 0.0F; \
+ GLfloat rd2; \
+ \
+ for (i = 0; i < NC; i++) { \
+ IV[i] = (V1[i] - V0[i]) * F(i); \
+ d2 += IV[i] * IV[i]; \
+ } \
+ rd2 = (GLfloat)NV / d2; \
+ B = 0; \
+ for (i = 0; i < NC; i++) { \
+ IV[i] *= F(i); \
+ B -= IV[i] * V0[i]; \
+ IV[i] *= rd2; \
+ } \
+ B = B * rd2 + 0.5f; \
+ } while (0)
+
+#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
+ do { \
+ GLfloat dot = 0.0F; \
+ for (i = 0; i < NC; i++) { \
+ dot += V[i] * IV[i]; \
+ } \
+ TEXEL = (GLint)(dot + B); \
+ if (SAFECDOT) { \
+ if (TEXEL < 0) { \
+ TEXEL = 0; \
+ } else if (TEXEL > NV) { \
+ TEXEL = NV; \
+ } \
+ } \
+ } while (0)
+
+
+static GLint
+fxt1_bestcol (GLfloat vec[][MAX_COMP], GLint nv,
+ GLubyte input[MAX_COMP], GLint nc)
+{
+ GLint i, j, best = -1;
+ GLfloat err = 1e9; /* big enough */
+
+ for (j = 0; j < nv; j++) {
+ GLfloat e = 0.0F;
+ for (i = 0; i < nc; i++) {
+ e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]);
+ }
+ if (e < err) {
+ err = e;
+ best = j;
+ }
+ }
+
+ return best;
+}
+
+
+static GLint
+fxt1_worst (GLfloat vec[MAX_COMP],
+ GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
+{
+ GLint i, k, worst = -1;
+ GLfloat err = -1.0F; /* small enough */
+
+ for (k = 0; k < n; k++) {
+ GLfloat e = 0.0F;
+ for (i = 0; i < nc; i++) {
+ e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]);
+ }
+ if (e > err) {
+ err = e;
+ worst = k;
+ }
+ }
+
+ return worst;
+}
+
+
+static GLint
+fxt1_variance (GLdouble variance[MAX_COMP],
+ GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
+{
+ GLint i, k, best = 0;
+ GLint sx, sx2;
+ GLdouble var, maxvar = -1; /* small enough */
+ GLdouble teenth = 1.0 / n;
+
+ for (i = 0; i < nc; i++) {
+ sx = sx2 = 0;
+ for (k = 0; k < n; k++) {
+ GLint t = input[k][i];
+ sx += t;
+ sx2 += t * t;
+ }
+ var = sx2 * teenth - sx * sx * teenth * teenth;
+ if (maxvar < var) {
+ maxvar = var;
+ best = i;
+ }
+ if (variance) {
+ variance[i] = var;
+ }
+ }
+
+ return best;
+}
+
+
+static GLint
+fxt1_choose (GLfloat vec[][MAX_COMP], GLint nv,
+ GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
+{
+#if 0
+ /* Choose colors from a grid.
+ */
+ GLint i, j;
+
+ for (j = 0; j < nv; j++) {
+ GLint m = j * (n - 1) / (nv - 1);
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = input[m][i];
+ }
+ }
+#else
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 8x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ GLint i, j, k;
+ GLint minSum = 2000; /* big enough */
+ GLint maxSum = -1; /* small enough */
+ GLint minCol = 0; /* phoudoin: silent compiler! */
+ GLint maxCol = 0; /* phoudoin: silent compiler! */
+
+ struct {
+ GLint flag;
+ GLint key;
+ GLint freq;
+ GLint idx;
+ } hist[N_TEXELS];
+ GLint lenh = 0;
+
+ _mesa_memset(hist, 0, sizeof(hist));
+
+ for (k = 0; k < n; k++) {
+ GLint l;
+ GLint key = 0;
+ GLint sum = 0;
+ for (i = 0; i < nc; i++) {
+ key <<= 8;
+ key |= input[k][i];
+ sum += input[k][i];
+ }
+ for (l = 0; l < n; l++) {
+ if (!hist[l].flag) {
+ /* alloc new slot */
+ hist[l].flag = !0;
+ hist[l].key = key;
+ hist[l].freq = 1;
+ hist[l].idx = k;
+ lenh = l + 1;
+ break;
+ } else if (hist[l].key == key) {
+ hist[l].freq++;
+ break;
+ }
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ }
+
+ if (lenh <= nv) {
+ for (j = 0; j < lenh; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = (GLfloat)input[hist[j].idx][i];
+ }
+ }
+ for (; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = vec[0][i];
+ }
+ }
+ return 0;
+ }
+
+ for (j = 0; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (GLfloat)(nv - 1);
+ }
+ }
+#endif
+
+ return !0;
+}
+
+
+static GLint
+fxt1_lloyd (GLfloat vec[][MAX_COMP], GLint nv,
+ GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
+{
+ /* Use the generalized lloyd's algorithm for VQ:
+ * find 4 color vectors.
+ *
+ * for each sample color
+ * sort to nearest vector.
+ *
+ * replace each vector with the centroid of it's matching colors.
+ *
+ * repeat until RMS doesn't improve.
+ *
+ * if a color vector has no samples, or becomes the same as another
+ * vector, replace it with the color which is farthest from a sample.
+ *
+ * vec[][MAX_COMP] initial vectors and resulting colors
+ * nv number of resulting colors required
+ * input[N_TEXELS][MAX_COMP] input texels
+ * nc number of components in input / vec
+ * n number of input samples
+ */
+
+ GLint sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
+ GLint cnt[MAX_VECT]; /* how many times a certain vector was chosen */
+ GLfloat error, lasterror = 1e9;
+
+ GLint i, j, k, rep;
+
+ /* the quantizer */
+ for (rep = 0; rep < LL_N_REP; rep++) {
+ /* reset sums & counters */
+ for (j = 0; j < nv; j++) {
+ for (i = 0; i < nc; i++) {
+ sum[j][i] = 0;
+ }
+ cnt[j] = 0;
+ }
+ error = 0;
+
+ /* scan whole block */
+ for (k = 0; k < n; k++) {
+#if 1
+ GLint best = -1;
+ GLfloat err = 1e9; /* big enough */
+ /* determine best vector */
+ for (j = 0; j < nv; j++) {
+ GLfloat e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
+ (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
+ (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
+ if (nc == 4) {
+ e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
+ }
+ if (e < err) {
+ err = e;
+ best = j;
+ }
+ }
+#else
+ GLint best = fxt1_bestcol(vec, nv, input[k], nc, &err);
+#endif
+ /* add in closest color */
+ for (i = 0; i < nc; i++) {
+ sum[best][i] += input[k][i];
+ }
+ /* mark this vector as used */
+ cnt[best]++;
+ /* accumulate error */
+ error += err;
+ }
+
+ /* check RMS */
+ if ((error < LL_RMS_E) ||
+ ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
+ return !0; /* good match */
+ }
+ lasterror = error;
+
+ /* move each vector to the barycenter of its closest colors */
+ for (j = 0; j < nv; j++) {
+ if (cnt[j]) {
+ GLfloat div = 1.0F / cnt[j];
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = div * sum[j][i];
+ }
+ } else {
+ /* this vec has no samples or is identical with a previous vec */
+ GLint worst = fxt1_worst(vec[j], input, nc, n);
+ for (i = 0; i < nc; i++) {
+ vec[j][i] = input[worst][i];
+ }
+ }
+ }
+ }
+
+ return 0; /* could not converge fast enough */
+}
+
+
+static void
+fxt1_quantize_CHROMA (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP])
+{
+ const GLint n_vect = 4; /* 4 base vectors to find */
+ const GLint n_comp = 3; /* 3 components: R, G, B */
+ GLfloat vec[MAX_VECT][MAX_COMP];
+ GLint i, j, k;
+ Fx64 hi; /* high quadword */
+ GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
+ fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
+ }
+
+ FX64_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
+ }
+ }
+ ((Fx64 *)cc)[1] = hi;
+
+ lohi = lolo = 0;
+ /* right microtile */
+ for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
+ lohi <<= 2;
+ lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+ }
+ /* left microtile */
+ for (; k >= 0; k--) {
+ lolo <<= 2;
+ lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+ }
+ cc[1] = lohi;
+ cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA0 (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP],
+ GLubyte reord[N_TEXELS][MAX_COMP], GLint n)
+{
+ const GLint n_vect = 3; /* 3 base vectors to find */
+ const GLint n_comp = 4; /* 4 components: R, G, B, A */
+ GLfloat vec[MAX_VECT][MAX_COMP];
+ GLint i, j, k;
+ Fx64 hi; /* high quadword */
+ GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ /* the last vector indicates zero */
+ for (i = 0; i < n_comp; i++) {
+ vec[n_vect][i] = 0;
+ }
+
+ /* the first n texels in reord are guaranteed to be non-zero */
+ if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
+ fxt1_lloyd(vec, n_vect, reord, n_comp, n);
+ }
+
+ FX64_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
+ for (j = n_vect - 1; j >= 0; j--) {
+ /* add in alphas */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F));
+ }
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp - 1; i++) {
+ /* add in colors */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
+ }
+ }
+ ((Fx64 *)cc)[1] = hi;
+
+ lohi = lolo = 0;
+ /* right microtile */
+ for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
+ lohi <<= 2;
+ lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+ }
+ /* left microtile */
+ for (; k >= 0; k--) {
+ lolo <<= 2;
+ lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+ }
+ cc[1] = lohi;
+ cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA1 (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP])
+{
+ const GLint n_vect = 3; /* highest vector number in each microtile */
+ const GLint n_comp = 4; /* 4 components: R, G, B, A */
+ GLfloat vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
+ GLfloat b, iv[MAX_COMP]; /* interpolation vector */
+ GLint i, j, k;
+ Fx64 hi; /* high quadword */
+ GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ GLint minSum;
+ GLint maxSum;
+ GLint minColL = 0, maxColL = 0;
+ GLint minColR = 0, maxColR = 0;
+ GLint sumL = 0, sumR = 0;
+ GLint nn_comp;
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ nn_comp = n_comp;
+ while ((minColL == maxColL) && nn_comp) {
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ GLint sum = 0;
+ for (i = 0; i < nn_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ sumL += sum;
+ }
+
+ nn_comp--;
+ }
+
+ nn_comp = n_comp;
+ while ((minColR == maxColR) && nn_comp) {
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = N_TEXELS / 2; k < N_TEXELS; k++) {
+ GLint sum = 0;
+ for (i = 0; i < nn_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ sumR += sum;
+ }
+
+ nn_comp--;
+ }
+
+ /* choose the common vector (yuck!) */
+ {
+ GLint j1, j2;
+ GLint v1 = 0, v2 = 0;
+ GLfloat err = 1e9; /* big enough */
+ GLfloat tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ for (i = 0; i < n_comp; i++) {
+ tv[0][i] = input[minColL][i];
+ tv[1][i] = input[maxColL][i];
+ tv[2][i] = input[minColR][i];
+ tv[3][i] = input[maxColR][i];
+ }
+ for (j1 = 0; j1 < 2; j1++) {
+ for (j2 = 2; j2 < 4; j2++) {
+ GLfloat e = 0.0F;
+ for (i = 0; i < n_comp; i++) {
+ e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
+ }
+ if (e < err) {
+ err = e;
+ v1 = j1;
+ v2 = j2;
+ }
+ }
+ }
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = tv[1 - v1][i];
+ vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
+ vec[2][i] = tv[5 - v2][i];
+ }
+ }
+
+ /* left microtile */
+ cc[0] = 0;
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ GLint texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+
+ cc[0] = lolo;
+ }
+
+ /* right microtile */
+ cc[1] = 0;
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ GLint texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+
+ cc[1] = lohi;
+ }
+
+ FX64_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */
+ for (j = n_vect - 1; j >= 0; j--) {
+ /* add in alphas */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F));
+ }
+ for (j = n_vect - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp - 1; i++) {
+ /* add in colors */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
+ }
+ }
+ ((Fx64 *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_HI (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP],
+ GLubyte reord[N_TEXELS][MAX_COMP], GLint n)
+{
+ const GLint n_vect = 6; /* highest vector number */
+ const GLint n_comp = 3; /* 3 components: R, G, B */
+ GLfloat b = 0.0F; /* phoudoin: silent compiler! */
+ GLfloat iv[MAX_COMP]; /* interpolation vector */
+ GLint i, k;
+ GLuint hihi; /* high quadword: hi dword */
+
+ GLint minSum = 2000; /* big enough */
+ GLint maxSum = -1; /* small enough */
+ GLint minCol = 0; /* phoudoin: silent compiler! */
+ GLint maxCol = 0; /* phoudoin: silent compiler! */
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 8x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ for (k = 0; k < n; k++) {
+ GLint sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += reord[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minCol = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxCol = k;
+ }
+ }
+
+ hihi = 0; /* cc-hi = "00" */
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ hihi <<= 5;
+ hihi |= reord[maxCol][i] >> 3;
+ }
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ hihi <<= 5;
+ hihi |= reord[minCol][i] >> 3;
+ }
+ cc[3] = hihi;
+ cc[0] = cc[1] = cc[2] = 0;
+
+ /* compute interpolation vector */
+ if (minCol != maxCol) {
+ MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
+ }
+
+ /* add in texels */
+ for (k = N_TEXELS - 1; k >= 0; k--) {
+ GLint t = k * 3;
+ GLuint *kk = (GLuint *)((char *)cc + t / 8);
+ GLint texel = n_vect + 1; /* transparent black */
+
+ if (!ISTBLACK(input[k])) {
+ if (minCol != maxCol) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ kk[0] |= texel << (t & 7);
+ }
+ } else {
+ /* add in texel */
+ kk[0] |= texel << (t & 7);
+ }
+ }
+}
+
+
+static void
+fxt1_quantize_MIXED1 (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP])
+{
+ const GLint n_vect = 2; /* highest vector number in each microtile */
+ const GLint n_comp = 3; /* 3 components: R, G, B */
+ GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ GLfloat b, iv[MAX_COMP]; /* interpolation vector */
+ GLint i, j, k;
+ Fx64 hi; /* high quadword */
+ GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ GLint minSum;
+ GLint maxSum;
+ GLint minColL = 0, maxColL = -1;
+ GLint minColR = 0, maxColR = -1;
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ if (!ISTBLACK(input[k])) {
+ GLint sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ }
+ }
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ if (!ISTBLACK(input[k])) {
+ GLint sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ }
+ }
+
+ /* left microtile */
+ if (maxColL == -1) {
+ /* all transparent black */
+ cc[0] = ~0u;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = 0;
+ vec[1][i] = 0;
+ }
+ } else {
+ cc[0] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = input[minColL][i];
+ vec[1][i] = input[maxColL][i];
+ }
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ GLint texel = n_vect + 1; /* transparent black */
+ if (!ISTBLACK(input[k])) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ }
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+ cc[0] = lolo;
+ }
+ }
+
+ /* right microtile */
+ if (maxColR == -1) {
+ /* all transparent black */
+ cc[1] = ~0u;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = 0;
+ vec[3][i] = 0;
+ }
+ } else {
+ cc[1] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = input[minColR][i];
+ vec[3][i] = input[maxColR][i];
+ }
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ GLint texel = n_vect + 1; /* transparent black */
+ if (!ISTBLACK(input[k])) {
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ }
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+ cc[1] = lohi;
+ }
+ }
+
+ FX64_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+ for (j = 2 * 2 - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, vec[j][i] >> 3);
+ }
+ }
+ ((Fx64 *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_MIXED0 (GLuint *cc,
+ GLubyte input[N_TEXELS][MAX_COMP])
+{
+ const GLint n_vect = 3; /* highest vector number in each microtile */
+ const GLint n_comp = 3; /* 3 components: R, G, B */
+ GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+ GLfloat b, iv[MAX_COMP]; /* interpolation vector */
+ GLint i, j, k;
+ Fx64 hi; /* high quadword */
+ GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
+
+ GLint minColL = 0, maxColL = 0;
+ GLint minColR = 0, maxColR = 0;
+#if 0
+ GLint minSum;
+ GLint maxSum;
+
+ /* Our solution here is to find the darkest and brightest colors in
+ * the 4x4 tile and use those as the two representative colors.
+ * There are probably better algorithms to use (histogram-based).
+ */
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ GLint sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColL = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColL = k;
+ }
+ }
+ minSum = 2000; /* big enough */
+ maxSum = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ GLint sum = 0;
+ for (i = 0; i < n_comp; i++) {
+ sum += input[k][i];
+ }
+ if (minSum > sum) {
+ minSum = sum;
+ minColR = k;
+ }
+ if (maxSum < sum) {
+ maxSum = sum;
+ maxColR = k;
+ }
+ }
+#else
+ GLint minVal;
+ GLint maxVal;
+ GLint maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2);
+ GLint maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2);
+
+ /* Scan the channel with max variance for lo & hi
+ * and use those as the two representative colors.
+ */
+ minVal = 2000; /* big enough */
+ maxVal = -1; /* small enough */
+ for (k = 0; k < N_TEXELS / 2; k++) {
+ GLint t = input[k][maxVarL];
+ if (minVal > t) {
+ minVal = t;
+ minColL = k;
+ }
+ if (maxVal < t) {
+ maxVal = t;
+ maxColL = k;
+ }
+ }
+ minVal = 2000; /* big enough */
+ maxVal = -1; /* small enough */
+ for (; k < N_TEXELS; k++) {
+ GLint t = input[k][maxVarR];
+ if (minVal > t) {
+ minVal = t;
+ minColR = k;
+ }
+ if (maxVal < t) {
+ maxVal = t;
+ maxColR = k;
+ }
+ }
+#endif
+
+ /* left microtile */
+ cc[0] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[0][i] = input[minColL][i];
+ vec[1][i] = input[maxColL][i];
+ }
+ if (minColL != maxColL) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+ /* add in texels */
+ lolo = 0;
+ for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+ GLint texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lolo <<= 2;
+ lolo |= texel;
+ }
+
+ /* funky encoding for LSB of green */
+ if ((GLint)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) {
+ for (i = 0; i < n_comp; i++) {
+ vec[1][i] = input[minColL][i];
+ vec[0][i] = input[maxColL][i];
+ }
+ lolo = ~lolo;
+ }
+
+ cc[0] = lolo;
+ }
+
+ /* right microtile */
+ cc[1] = 0;
+ for (i = 0; i < n_comp; i++) {
+ vec[2][i] = input[minColR][i];
+ vec[3][i] = input[maxColR][i];
+ }
+ if (minColR != maxColR) {
+ /* compute interpolation vector */
+ MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+ /* add in texels */
+ lohi = 0;
+ for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+ GLint texel;
+ /* interpolate color */
+ CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+ /* add in texel */
+ lohi <<= 2;
+ lohi |= texel;
+ }
+
+ /* funky encoding for LSB of green */
+ if ((GLint)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) {
+ for (i = 0; i < n_comp; i++) {
+ vec[3][i] = input[minColR][i];
+ vec[2][i] = input[maxColR][i];
+ }
+ lohi = ~lohi;
+ }
+
+ cc[1] = lohi;
+ }
+
+ FX64_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+ for (j = 2 * 2 - 1; j >= 0; j--) {
+ for (i = 0; i < n_comp; i++) {
+ /* add in colors */
+ FX64_SHL(hi, 5);
+ FX64_OR32(hi, vec[j][i] >> 3);
+ }
+ }
+ ((Fx64 *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps)
+{
+ GLint trualpha;
+ GLubyte reord[N_TEXELS][MAX_COMP];
+
+ GLubyte input[N_TEXELS][MAX_COMP];
+ GLint i, k, l;
+
+ if (comps == 3) {
+ /* make the whole block opaque */
+ _mesa_memset(input, -1, sizeof(input));
+ }
+
+ /* 8 texels each line */
+ for (l = 0; l < 4; l++) {
+ for (k = 0; k < 4; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4][i] = *lines[l]++;
+ }
+ }
+ for (; k < 8; k++) {
+ for (i = 0; i < comps; i++) {
+ input[k + l * 4 + 12][i] = *lines[l]++;
+ }
+ }
+ }
+
+ /* block layout:
+ * 00, 01, 02, 03, 08, 09, 0a, 0b
+ * 10, 11, 12, 13, 18, 19, 1a, 1b
+ * 04, 05, 06, 07, 0c, 0d, 0e, 0f
+ * 14, 15, 16, 17, 1c, 1d, 1e, 1f
+ */
+
+ /* [dBorca]
+ * stupidity flows forth from this
+ */
+ l = N_TEXELS;
+ trualpha = 0;
+ if (comps == 4) {
+ /* skip all transparent black texels */
+ l = 0;
+ for (k = 0; k < N_TEXELS; k++) {
+ /* test all components against 0 */
+ if (!ISTBLACK(input[k])) {
+ /* texel is not transparent black */
+ COPY_4UBV(reord[l], input[k]);
+ if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
+ /* non-opaque texel */
+ trualpha = !0;
+ }
+ l++;
+ }
+ }
+ }
+
+#if 0
+ if (trualpha) {
+ fxt1_quantize_ALPHA0(cc, input, reord, l);
+ } else if (l == 0) {
+ cc[0] = cc[1] = cc[2] = -1;
+ cc[3] = 0;
+ } else if (l < N_TEXELS) {
+ fxt1_quantize_HI(cc, input, reord, l);
+ } else {
+ fxt1_quantize_CHROMA(cc, input);
+ }
+ (void)fxt1_quantize_ALPHA1;
+ (void)fxt1_quantize_MIXED1;
+ (void)fxt1_quantize_MIXED0;
+#else
+ if (trualpha) {
+ fxt1_quantize_ALPHA1(cc, input);
+ } else if (l == 0) {
+ cc[0] = cc[1] = cc[2] = ~0u;
+ cc[3] = 0;
+ } else if (l < N_TEXELS) {
+ fxt1_quantize_MIXED1(cc, input);
+ } else {
+ fxt1_quantize_MIXED0(cc, input);
+ }
+ (void)fxt1_quantize_ALPHA0;
+ (void)fxt1_quantize_HI;
+ (void)fxt1_quantize_CHROMA;
+#endif
+}
+
+
+static void
+fxt1_encode (GLuint width, GLuint height, GLint comps,
+ const void *source, GLint srcRowStride,
+ void *dest, GLint destRowStride)
+{
+ GLuint x, y;
+ const GLubyte *data;
+ GLuint *encoded = (GLuint *)dest;
+ void *newSource = NULL;
+
+ assert(comps == 3 || comps == 4);
+
+ /* Replicate image if width is not M8 or height is not M4 */
+ if ((width & 7) | (height & 3)) {
+ GLint newWidth = (width + 7) & ~7;
+ GLint newHeight = (height + 3) & ~3;
+ newSource = _mesa_malloc(comps * newWidth * newHeight * sizeof(GLchan));
+ if (!newSource) {
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression");
+ goto cleanUp;
+ }
+ _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
+ comps, (const GLchan *) source,
+ srcRowStride, (GLchan *) newSource);
+ source = newSource;
+ width = newWidth;
+ height = newHeight;
+ srcRowStride = comps * newWidth;
+ }
+
+ /* convert from 16/32-bit channels to GLubyte if needed */
+ if (CHAN_TYPE != GL_UNSIGNED_BYTE) {
+ const GLuint n = width * height * comps;
+ const GLchan *src = (const GLchan *) source;
+ GLubyte *dest = (GLubyte *) _mesa_malloc(n * sizeof(GLubyte));
+ GLuint i;
+ if (!dest) {
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression");
+ goto cleanUp;
+ }
+ for (i = 0; i < n; i++) {
+ dest[i] = CHAN_TO_UBYTE(src[i]);
+ }
+ if (newSource != NULL) {
+ _mesa_free(newSource);
+ }
+ newSource = dest; /* we'll free this buffer before returning */
+ source = dest; /* the new, GLubyte incoming image */
+ }
+
+ data = (const GLubyte *) source;
+ destRowStride = (destRowStride - width * 2) / 4;
+ for (y = 0; y < height; y += 4) {
+ GLuint offs = 0 + (y + 0) * srcRowStride;
+ for (x = 0; x < width; x += 8) {
+ const GLubyte *lines[4];
+ lines[0] = &data[offs];
+ lines[1] = lines[0] + srcRowStride;
+ lines[2] = lines[1] + srcRowStride;
+ lines[3] = lines[2] + srcRowStride;
+ offs += 8 * comps;
+ fxt1_quantize(encoded, lines, comps);
+ /* 128 bits per 8x4 block */
+ encoded += 4;
+ }
+ encoded += destRowStride;
+ }
+
+ cleanUp:
+ if (newSource != NULL) {
+ _mesa_free(newSource);
+ }
+}
+
+
+/***************************************************************************\
+ * FXT1 decoder
+ *
+ * The decoder is based on GL_3DFX_texture_compression_FXT1
+ * specification and serves as a concept for the encoder.
+\***************************************************************************/
+
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static const GLubyte _rgb_scale_5[] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static const GLubyte _rgb_scale_6[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 45, 49, 53, 57, 61,
+ 65, 69, 73, 77, 81, 85, 89, 93,
+ 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158,
+ 162, 166, 170, 174, 178, 182, 186, 190,
+ 194, 198, 202, 206, 210, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+#define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
+#define UP5(c) _rgb_scale_5[(c) & 31]
+#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
+#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
+
+
+static void
+fxt1_decode_1HI (const GLubyte *code, GLint t, GLchan *rgba)
+{
+ const GLuint *cc;
+
+ t *= 3;
+ cc = (const GLuint *)(code + t / 8);
+ t = (cc[0] >> (t & 7)) & 7;
+
+ if (t == 7) {
+ rgba[RCOMP] = rgba[GCOMP] = rgba[BCOMP] = rgba[ACOMP] = 0;
+ } else {
+ GLubyte r, g, b;
+ cc = (const GLuint *)(code + 12);
+ if (t == 0) {
+ b = UP5(CC_SEL(cc, 0));
+ g = UP5(CC_SEL(cc, 5));
+ r = UP5(CC_SEL(cc, 10));
+ } else if (t == 6) {
+ b = UP5(CC_SEL(cc, 15));
+ g = UP5(CC_SEL(cc, 20));
+ r = UP5(CC_SEL(cc, 25));
+ } else {
+ b = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
+ g = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
+ r = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
+ }
+ rgba[RCOMP] = UBYTE_TO_CHAN(r);
+ rgba[GCOMP] = UBYTE_TO_CHAN(g);
+ rgba[BCOMP] = UBYTE_TO_CHAN(b);
+ rgba[ACOMP] = CHAN_MAX;
+ }
+}
+
+
+static void
+fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLchan *rgba)
+{
+ const GLuint *cc;
+ GLuint kk;
+
+ cc = (const GLuint *)code;
+ if (t & 16) {
+ cc++;
+ t &= 15;
+ }
+ t = (cc[0] >> (t * 2)) & 3;
+
+ t *= 15;
+ cc = (const GLuint *)(code + 8 + t / 8);
+ kk = cc[0] >> (t & 7);
+ rgba[BCOMP] = UBYTE_TO_CHAN( UP5(kk) );
+ rgba[GCOMP] = UBYTE_TO_CHAN( UP5(kk >> 5) );
+ rgba[RCOMP] = UBYTE_TO_CHAN( UP5(kk >> 10) );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+
+static void
+fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLchan *rgba)
+{
+ const GLuint *cc;
+ GLuint col[2][3];
+ GLint glsb, selb;
+
+ cc = (const GLuint *)code;
+ if (t & 16) {
+ t &= 15;
+ t = (cc[1] >> (t * 2)) & 3;
+ /* col 2 */
+ col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
+ col[0][GCOMP] = CC_SEL(cc, 99);
+ col[0][RCOMP] = CC_SEL(cc, 104);
+ /* col 3 */
+ col[1][BCOMP] = CC_SEL(cc, 109);
+ col[1][GCOMP] = CC_SEL(cc, 114);
+ col[1][RCOMP] = CC_SEL(cc, 119);
+ glsb = CC_SEL(cc, 126);
+ selb = CC_SEL(cc, 33);
+ } else {
+ t = (cc[0] >> (t * 2)) & 3;
+ /* col 0 */
+ col[0][BCOMP] = CC_SEL(cc, 64);
+ col[0][GCOMP] = CC_SEL(cc, 69);
+ col[0][RCOMP] = CC_SEL(cc, 74);
+ /* col 1 */
+ col[1][BCOMP] = CC_SEL(cc, 79);
+ col[1][GCOMP] = CC_SEL(cc, 84);
+ col[1][RCOMP] = CC_SEL(cc, 89);
+ glsb = CC_SEL(cc, 125);
+ selb = CC_SEL(cc, 1);
+ }
+
+ if (CC_SEL(cc, 124) & 1) {
+ /* alpha[0] == 1 */
+
+ if (t == 3) {
+ /* zero */
+ rgba[RCOMP] = rgba[BCOMP] = rgba[GCOMP] = rgba[ACOMP] = 0;
+ } else {
+ GLubyte r, g, b;
+ if (t == 0) {
+ b = UP5(col[0][BCOMP]);
+ g = UP5(col[0][GCOMP]);
+ r = UP5(col[0][RCOMP]);
+ } else if (t == 2) {
+ b = UP5(col[1][BCOMP]);
+ g = UP6(col[1][GCOMP], glsb);
+ r = UP5(col[1][RCOMP]);
+ } else {
+ b = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
+ g = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
+ r = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
+ }
+ rgba[RCOMP] = UBYTE_TO_CHAN(r);
+ rgba[GCOMP] = UBYTE_TO_CHAN(g);
+ rgba[BCOMP] = UBYTE_TO_CHAN(b);
+ rgba[ACOMP] = CHAN_MAX;
+ }
+ } else {
+ /* alpha[0] == 0 */
+ GLubyte r, g, b;
+ if (t == 0) {
+ b = UP5(col[0][BCOMP]);
+ g = UP6(col[0][GCOMP], glsb ^ selb);
+ r = UP5(col[0][RCOMP]);
+ } else if (t == 3) {
+ b = UP5(col[1][BCOMP]);
+ g = UP6(col[1][GCOMP], glsb);
+ r = UP5(col[1][RCOMP]);
+ } else {
+ b = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
+ g = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
+ UP6(col[1][GCOMP], glsb));
+ r = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
+ }
+ rgba[RCOMP] = UBYTE_TO_CHAN(r);
+ rgba[GCOMP] = UBYTE_TO_CHAN(g);
+ rgba[BCOMP] = UBYTE_TO_CHAN(b);
+ rgba[ACOMP] = CHAN_MAX;
+ }
+}
+
+
+static void
+fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLchan *rgba)
+{
+ const GLuint *cc;
+ GLubyte r, g, b, a;
+
+ cc = (const GLuint *)code;
+ if (CC_SEL(cc, 124) & 1) {
+ /* lerp == 1 */
+ GLuint col0[4];
+
+ if (t & 16) {
+ t &= 15;
+ t = (cc[1] >> (t * 2)) & 3;
+ /* col 2 */
+ col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
+ col0[GCOMP] = CC_SEL(cc, 99);
+ col0[RCOMP] = CC_SEL(cc, 104);
+ col0[ACOMP] = CC_SEL(cc, 119);
+ } else {
+ t = (cc[0] >> (t * 2)) & 3;
+ /* col 0 */
+ col0[BCOMP] = CC_SEL(cc, 64);
+ col0[GCOMP] = CC_SEL(cc, 69);
+ col0[RCOMP] = CC_SEL(cc, 74);
+ col0[ACOMP] = CC_SEL(cc, 109);
+ }
+
+ if (t == 0) {
+ b = UP5(col0[BCOMP]);
+ g = UP5(col0[GCOMP]);
+ r = UP5(col0[RCOMP]);
+ a = UP5(col0[ACOMP]);
+ } else if (t == 3) {
+ b = UP5(CC_SEL(cc, 79));
+ g = UP5(CC_SEL(cc, 84));
+ r = UP5(CC_SEL(cc, 89));
+ a = UP5(CC_SEL(cc, 114));
+ } else {
+ b = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
+ g = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
+ r = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
+ a = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
+ }
+ } else {
+ /* lerp == 0 */
+
+ if (t & 16) {
+ cc++;
+ t &= 15;
+ }
+ t = (cc[0] >> (t * 2)) & 3;
+
+ if (t == 3) {
+ /* zero */
+ r = g = b = a = 0;
+ } else {
+ GLuint kk;
+ cc = (const GLuint *)code;
+ a = UP5(cc[3] >> (t * 5 + 13));
+ t *= 15;
+ cc = (const GLuint *)(code + 8 + t / 8);
+ kk = cc[0] >> (t & 7);
+ b = UP5(kk);
+ g = UP5(kk >> 5);
+ r = UP5(kk >> 10);
+ }
+ }
+ rgba[RCOMP] = UBYTE_TO_CHAN(r);
+ rgba[GCOMP] = UBYTE_TO_CHAN(g);
+ rgba[BCOMP] = UBYTE_TO_CHAN(b);
+ rgba[ACOMP] = UBYTE_TO_CHAN(a);
+}
+
+
+void
+fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */
+ GLint i, GLint j, GLchan *rgba)
+{
+ static void (*decode_1[]) (const GLubyte *, GLint, GLchan *) = {
+ fxt1_decode_1HI, /* cc-high = "00?" */
+ fxt1_decode_1HI, /* cc-high = "00?" */
+ fxt1_decode_1CHROMA, /* cc-chroma = "010" */
+ fxt1_decode_1ALPHA, /* alpha = "011" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED, /* mixed = "1??" */
+ fxt1_decode_1MIXED /* mixed = "1??" */
+ };
+
+ const GLubyte *code = (const GLubyte *)texture +
+ ((j / 4) * (stride / 8) + (i / 8)) * 16;
+ GLint mode = CC_SEL(code, 125);
+ GLint t = i & 7;
+
+ if (t & 4) {
+ t += 12;
+ }
+ t += (j & 3) * 4;
+
+ decode_1[mode](code, t, rgba);
+}
diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c
new file mode 100644
index 000000000..a1c0f18f3
--- /dev/null
+++ b/mesalib/src/mesa/main/texcompress_s3tc.c
@@ -0,0 +1,761 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texcompress_s3tc.c
+ * GL_EXT_texture_compression_s3tc support.
+ */
+
+#ifndef USE_EXTERNAL_DXTN_LIB
+#define USE_EXTERNAL_DXTN_LIB 1
+#endif
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "convolve.h"
+#include "dlopen.h"
+#include "image.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texstore.h"
+
+#ifdef __MINGW32__
+#define DXTN_LIBNAME "dxtn.dll"
+#define RTLD_LAZY 0
+#define RTLD_GLOBAL 0
+#elif defined(__DJGPP__)
+#define DXTN_LIBNAME "dxtn.dxe"
+#else
+#define DXTN_LIBNAME "libtxc_dxtn.so"
+#endif
+
+#if FEATURE_EXT_texture_sRGB
+/**
+ * Convert an 8-bit sRGB value from non-linear space to a
+ * linear RGB value in [0, 1].
+ * Implemented with a 256-entry lookup table.
+ */
+static INLINE GLfloat
+nonlinear_to_linear(GLubyte cs8)
+{
+ static GLfloat table[256];
+ static GLboolean tableReady = GL_FALSE;
+ if (!tableReady) {
+ /* compute lookup table now */
+ GLuint i;
+ for (i = 0; i < 256; i++) {
+ const GLfloat cs = UBYTE_TO_FLOAT(i);
+ if (cs <= 0.04045) {
+ table[i] = cs / 12.92f;
+ }
+ else {
+ table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4);
+ }
+ }
+ tableReady = GL_TRUE;
+ }
+ return table[cs8];
+}
+#endif /* FEATURE_EXT_texture_sRGB */
+
+typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
+
+dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL;
+dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL;
+
+typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width,
+ GLint height, const GLchan *srcPixData,
+ GLenum destformat, GLubyte *dest,
+ GLint dstRowStride);
+
+static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL;
+
+static void *dxtlibhandle = NULL;
+
+
+void
+_mesa_init_texture_s3tc( GLcontext *ctx )
+{
+ /* called during context initialization */
+ ctx->Mesa_DXTn = GL_FALSE;
+#if USE_EXTERNAL_DXTN_LIB
+ if (!dxtlibhandle) {
+ dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
+ if (!dxtlibhandle) {
+ _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn "
+ "compression/decompression unavailable");
+ }
+ else {
+ /* the fetch functions are not per context! Might be problematic... */
+ fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt)
+ _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
+ fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt)
+ _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
+ fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt)
+ _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
+ fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt)
+ _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
+ ext_tx_compress_dxtn = (dxtCompressTexFuncExt)
+ _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn");
+
+ if (!fetch_ext_rgb_dxt1 ||
+ !fetch_ext_rgba_dxt1 ||
+ !fetch_ext_rgba_dxt3 ||
+ !fetch_ext_rgba_dxt5 ||
+ !ext_tx_compress_dxtn) {
+ _mesa_warning(ctx, "couldn't reference all symbols in "
+ DXTN_LIBNAME ", software DXTn compression/decompression "
+ "unavailable");
+ fetch_ext_rgb_dxt1 = NULL;
+ fetch_ext_rgba_dxt1 = NULL;
+ fetch_ext_rgba_dxt3 = NULL;
+ fetch_ext_rgba_dxt5 = NULL;
+ ext_tx_compress_dxtn = NULL;
+ _mesa_dlclose(dxtlibhandle);
+ dxtlibhandle = NULL;
+ }
+ }
+ }
+ if (dxtlibhandle) {
+ ctx->Mesa_DXTn = GL_TRUE;
+ _mesa_warning(ctx, "software DXTn compression/decompression available");
+ }
+#else
+ (void) ctx;
+#endif
+}
+
+/**
+ * Called via TexFormat->StoreImage to store an RGB_DXT1 texture.
+ */
+static GLboolean
+texstore_rgb_dxt1(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgb_dxt1);
+ ASSERT(dstXoffset % 4 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset % 4 == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGB ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGB/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 3 * srcWidth;
+ srcFormat = GL_RGB;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+
+ if (ext_tx_compress_dxtn) {
+ (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ dst, dstRowStride);
+ }
+ else {
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
+ }
+
+ if (tempImage)
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via TexFormat->StoreImage to store an RGBA_DXT1 texture.
+ */
+static GLboolean
+texstore_rgba_dxt1(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_dxt1);
+ ASSERT(dstXoffset % 4 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset % 4 == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGBA ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGBA/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 4 * srcWidth;
+ srcFormat = GL_RGBA;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+ if (ext_tx_compress_dxtn) {
+ (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ dst, dstRowStride);
+ }
+ else {
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
+ }
+
+ if (tempImage)
+ _mesa_free((void*) tempImage);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via TexFormat->StoreImage to store an RGBA_DXT3 texture.
+ */
+static GLboolean
+texstore_rgba_dxt3(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_dxt3);
+ ASSERT(dstXoffset % 4 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset % 4 == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGBA ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGBA/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 4 * srcWidth;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+ if (ext_tx_compress_dxtn) {
+ (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ dst, dstRowStride);
+ }
+ else {
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3");
+ }
+
+ if (tempImage)
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via TexFormat->StoreImage to store an RGBA_DXT5 texture.
+ */
+static GLboolean
+texstore_rgba_dxt5(TEXSTORE_PARAMS)
+{
+ const GLchan *pixels;
+ GLint srcRowStride;
+ GLubyte *dst;
+ const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */
+ const GLchan *tempImage = NULL;
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_dxt5);
+ ASSERT(dstXoffset % 4 == 0);
+ ASSERT(dstYoffset % 4 == 0);
+ ASSERT(dstZoffset % 4 == 0);
+ (void) dstZoffset;
+ (void) dstImageOffsets;
+
+ if (srcFormat != GL_RGBA ||
+ srcType != CHAN_TYPE ||
+ ctx->_ImageTransferState ||
+ srcPacking->SwapBytes) {
+ /* convert image to RGBA/GLchan */
+ tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ if (!tempImage)
+ return GL_FALSE; /* out of memory */
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ pixels = tempImage;
+ srcRowStride = 4 * srcWidth;
+ }
+ else {
+ pixels = (const GLchan *) srcAddr;
+ srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
+ srcType) / sizeof(GLchan);
+ }
+
+ dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
+ dstFormat->MesaFormat,
+ texWidth, (GLubyte *) dstAddr);
+ if (ext_tx_compress_dxtn) {
+ (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ dst, dstRowStride);
+ }
+ else {
+ _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5");
+ }
+
+ if (tempImage)
+ _mesa_free((void *) tempImage);
+
+ return GL_TRUE;
+}
+
+
+static void
+fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ if (fetch_ext_rgb_dxt1) {
+ ASSERT (sizeof(GLchan) == sizeof(GLubyte));
+ fetch_ext_rgb_dxt1(texImage->RowStride,
+ (GLubyte *)(texImage)->Data, i, j, texel);
+ }
+ else
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgb_dxt1");
+}
+
+
+static void
+fetch_texel_2d_f_rgb_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+
+static void
+fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ if (fetch_ext_rgba_dxt1) {
+ fetch_ext_rgba_dxt1(texImage->RowStride,
+ (GLubyte *)(texImage)->Data, i, j, texel);
+ }
+ else
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt1\n");
+}
+
+
+static void
+fetch_texel_2d_f_rgba_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+
+static void
+fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ if (fetch_ext_rgba_dxt3) {
+ ASSERT (sizeof(GLchan) == sizeof(GLubyte));
+ fetch_ext_rgba_dxt3(texImage->RowStride, (GLubyte *)(texImage)->Data,
+ i, j, texel);
+ }
+ else
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt3\n");
+}
+
+
+static void
+fetch_texel_2d_f_rgba_dxt3( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+
+static void
+fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) k;
+ if (fetch_ext_rgba_dxt5) {
+ fetch_ext_rgba_dxt5(texImage->RowStride, (GLubyte *)(texImage)->Data,
+ i, j, texel);
+ }
+ else
+ _mesa_debug(NULL, "attempted to decode s3tc texture without library available: fetch_texel_2d_rgba_dxt5\n");
+}
+
+
+static void
+fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba);
+ texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
+ texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
+ texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+#if FEATURE_EXT_texture_sRGB
+static void
+fetch_texel_2d_f_srgb_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt1( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt3( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+
+static void
+fetch_texel_2d_f_srgba_dxt5( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* just sample as GLchan and convert to float here */
+ GLchan rgba[4];
+ fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba);
+ texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]);
+ texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]);
+ texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]);
+ texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
+}
+#endif
+
+const struct gl_texture_format _mesa_texformat_rgb_dxt1 = {
+ MESA_FORMAT_RGB_DXT1, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgb_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt1 = {
+ MESA_FORMAT_RGBA_DXT1, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 1, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt3 = {
+ MESA_FORMAT_RGBA_DXT3, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 4, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt3, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_dxt5 = {
+ MESA_FORMAT_RGBA_DXT5, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4,/*approx*/ /* RedBits */
+ 4,/*approx*/ /* GreenBits */
+ 4,/*approx*/ /* BlueBits */
+ 4,/*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt5, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+#if FEATURE_EXT_texture_sRGB
+const struct gl_texture_format _mesa_texformat_srgb_dxt1 = {
+ MESA_FORMAT_SRGB_DXT1, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgb_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_srgb_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_srgba_dxt1 = {
+ MESA_FORMAT_SRGBA_DXT1, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 1, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt1, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_srgba_dxt1, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_srgba_dxt3 = {
+ MESA_FORMAT_SRGBA_DXT3, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /*approx*/ /* RedBits */
+ 4, /*approx*/ /* GreenBits */
+ 4, /*approx*/ /* BlueBits */
+ 4, /*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt3, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_srgba_dxt3, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_srgba_dxt5 = {
+ MESA_FORMAT_SRGBA_DXT5, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4,/*approx*/ /* RedBits */
+ 4,/*approx*/ /* GreenBits */
+ 4,/*approx*/ /* BlueBits */
+ 4,/*approx*/ /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ texstore_rgba_dxt5, /* StoreTexImageFunc */
+ NULL, /*impossible*/ /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /*impossible*/ /* FetchTexel3D */
+ NULL, /*impossible*/ /* FetchTexel1Df */
+ fetch_texel_2d_f_srgba_dxt5, /* FetchTexel2Df */
+ NULL, /*impossible*/ /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+#endif
diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c
new file mode 100644
index 000000000..6d86a4275
--- /dev/null
+++ b/mesalib/src/mesa/main/texenv.c
@@ -0,0 +1,1078 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file texenv.c
+ *
+ * glTexEnv-related functions
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/texenv.h"
+#include "main/texstate.h"
+
+
+#define TE_ERROR(errCode, msg, value) \
+ _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
+
+
+/** Set texture env mode */
+static void
+set_env_mode(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum mode)
+{
+ GLboolean legal;
+
+ if (texUnit->EnvMode == mode)
+ return;
+
+ switch (mode) {
+ case GL_MODULATE:
+ case GL_BLEND:
+ case GL_DECAL:
+ case GL_REPLACE:
+ legal = GL_TRUE;
+ break;
+ case GL_REPLACE_EXT:
+ mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
+ legal = GL_TRUE;
+ break;
+ case GL_ADD:
+ legal = ctx->Extensions.EXT_texture_env_add;
+ break;
+ case GL_COMBINE:
+ legal = (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine);
+ break;
+ case GL_COMBINE4_NV:
+ legal = ctx->Extensions.NV_texture_env_combine4;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (legal) {
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->EnvMode = mode;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
+ }
+}
+
+
+static void
+set_env_color(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ const GLfloat *color)
+{
+ GLfloat tmp[4];
+ tmp[0] = CLAMP(color[0], 0.0F, 1.0F);
+ tmp[1] = CLAMP(color[1], 0.0F, 1.0F);
+ tmp[2] = CLAMP(color[2], 0.0F, 1.0F);
+ tmp[3] = CLAMP(color[3], 0.0F, 1.0F);
+ if (TEST_EQ_4V(tmp, texUnit->EnvColor))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texUnit->EnvColor, tmp);
+}
+
+
+/** Set an RGB or A combiner mode/function */
+static void
+set_combiner_mode(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum mode)
+{
+ GLboolean legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ switch (mode) {
+ case GL_REPLACE:
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_INTERPOLATE:
+ legal = GL_TRUE;
+ break;
+ case GL_SUBTRACT:
+ legal = ctx->Extensions.ARB_texture_env_combine;
+ break;
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ legal = (ctx->Extensions.EXT_texture_env_dot3 &&
+ pname == GL_COMBINE_RGB);
+ break;
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ legal = (ctx->Extensions.ARB_texture_env_dot3 &&
+ pname == GL_COMBINE_RGB);
+ break;
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ legal = ctx->Extensions.ATI_texture_env_combine3;
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ legal = (ctx->Extensions.ATI_envmap_bumpmap &&
+ pname == GL_COMBINE_RGB);
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
+ return;
+ }
+
+ switch (pname) {
+ case GL_COMBINE_RGB:
+ if (texUnit->Combine.ModeRGB == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ModeRGB = mode;
+ break;
+
+ case GL_COMBINE_ALPHA:
+ if (texUnit->Combine.ModeA == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ModeA = mode;
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ }
+}
+
+
+
+/** Set an RGB or A combiner source term */
+static void
+set_combiner_source(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum param)
+{
+ GLuint term;
+ GLboolean alpha, legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ /*
+ * Translate pname to (term, alpha).
+ */
+ switch (pname) {
+ case GL_SOURCE0_RGB:
+ term = 0;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE1_RGB:
+ term = 1;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE2_RGB:
+ term = 2;
+ alpha = GL_FALSE;
+ break;
+ case GL_SOURCE3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_SOURCE0_ALPHA:
+ term = 0;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE1_ALPHA:
+ term = 1;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE2_ALPHA:
+ term = 2;
+ alpha = GL_TRUE;
+ break;
+ case GL_SOURCE3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+
+ assert(term < MAX_COMBINER_TERMS);
+
+ /*
+ * Error-check param (the source term)
+ */
+ switch (param) {
+ case GL_TEXTURE:
+ case GL_CONSTANT:
+ case GL_PRIMARY_COLOR:
+ case GL_PREVIOUS:
+ legal = GL_TRUE;
+ break;
+ case GL_TEXTURE0:
+ case GL_TEXTURE1:
+ case GL_TEXTURE2:
+ case GL_TEXTURE3:
+ case GL_TEXTURE4:
+ case GL_TEXTURE5:
+ case GL_TEXTURE6:
+ case GL_TEXTURE7:
+ legal = (ctx->Extensions.ARB_texture_env_crossbar &&
+ param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
+ break;
+ case GL_ZERO:
+ legal = (ctx->Extensions.ATI_texture_env_combine3 ||
+ ctx->Extensions.NV_texture_env_combine4);
+ break;
+ case GL_ONE:
+ legal = ctx->Extensions.ATI_texture_env_combine3;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ if (alpha)
+ texUnit->Combine.SourceA[term] = param;
+ else
+ texUnit->Combine.SourceRGB[term] = param;
+}
+
+
+/** Set an RGB or A combiner operand term */
+static void
+set_combiner_operand(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLenum param)
+{
+ GLuint term;
+ GLboolean alpha, legal;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_OPERAND0_RGB:
+ term = 0;
+ alpha = GL_FALSE;
+ break;
+ case GL_OPERAND1_RGB:
+ term = 1;
+ alpha = GL_FALSE;
+ break;
+ case GL_OPERAND2_RGB:
+ if (ctx->Extensions.ARB_texture_env_combine) {
+ term = 2;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_FALSE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND0_ALPHA:
+ term = 0;
+ alpha = GL_TRUE;
+ break;
+ case GL_OPERAND1_ALPHA:
+ term = 1;
+ alpha = GL_TRUE;
+ break;
+ case GL_OPERAND2_ALPHA:
+ if (ctx->Extensions.ARB_texture_env_combine) {
+ term = 2;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ case GL_OPERAND3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ term = 3;
+ alpha = GL_TRUE;
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+
+ assert(term < MAX_COMBINER_TERMS);
+
+ /*
+ * Error-check param (the source operand)
+ */
+ switch (param) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ legal = !alpha;
+ break;
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ legal = GL_TRUE;
+ break;
+ default:
+ legal = GL_FALSE;
+ }
+
+ if (!legal) {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ if (alpha)
+ texUnit->Combine.OperandA[term] = param;
+ else
+ texUnit->Combine.OperandRGB[term] = param;
+}
+
+
+static void
+set_combiner_scale(GLcontext *ctx,
+ struct gl_texture_unit *texUnit,
+ GLenum pname, GLfloat scale)
+{
+ GLuint shift;
+
+ if (!ctx->Extensions.EXT_texture_env_combine &&
+ !ctx->Extensions.ARB_texture_env_combine) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
+ return;
+ }
+
+ if (scale == 1.0F) {
+ shift = 0;
+ }
+ else if (scale == 2.0F) {
+ shift = 1;
+ }
+ else if (scale == 4.0F) {
+ shift = 2;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_RGB_SCALE:
+ if (texUnit->Combine.ScaleShiftRGB == shift)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ScaleShiftRGB = shift;
+ break;
+ case GL_ALPHA_SCALE:
+ if (texUnit->Combine.ScaleShiftA == shift)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Combine.ScaleShiftA = shift;
+ break;
+ default:
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
+{
+ GLuint maxUnit;
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+ ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+ if (ctx->Texture.CurrentUnit >= maxUnit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (target == GL_TEXTURE_ENV) {
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]);
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ set_env_color(ctx, texUnit, param);
+ break;
+ case GL_COMBINE_RGB:
+ case GL_COMBINE_ALPHA:
+ set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ break;
+ case GL_SOURCE0_RGB:
+ case GL_SOURCE1_RGB:
+ case GL_SOURCE2_RGB:
+ case GL_SOURCE3_RGB_NV:
+ case GL_SOURCE0_ALPHA:
+ case GL_SOURCE1_ALPHA:
+ case GL_SOURCE2_ALPHA:
+ case GL_SOURCE3_ALPHA_NV:
+ set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ break;
+ case GL_OPERAND0_RGB:
+ case GL_OPERAND1_RGB:
+ case GL_OPERAND2_RGB:
+ case GL_OPERAND3_RGB_NV:
+ case GL_OPERAND0_ALPHA:
+ case GL_OPERAND1_ALPHA:
+ case GL_OPERAND2_ALPHA:
+ case GL_OPERAND3_ALPHA_NV:
+ set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ break;
+ case GL_RGB_SCALE:
+ case GL_ALPHA_SCALE:
+ set_combiner_scale(ctx, texUnit, pname, param[0]);
+ break;
+ case GL_BUMP_TARGET_ATI:
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
+ return;
+ }
+ if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
+ ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
+ /* spec doesn't say this but it seems logical */
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
+ return;
+ }
+ if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
+ return;
+ }
+ else {
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->BumpTarget = (GLenum) (GLint) param[0];
+ }
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
+ return;
+ }
+ }
+ else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ /* GL_EXT_texture_lod_bias */
+ if (!ctx->Extensions.EXT_texture_lod_bias) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
+ return;
+ }
+ if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
+ if (texUnit->LodBias == param[0])
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->LodBias = param[0];
+ }
+ else {
+ TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
+ return;
+ }
+ }
+ else if (target == GL_POINT_SPRITE_NV) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
+ return;
+ }
+ if (pname == GL_COORD_REPLACE_NV) {
+ const GLenum value = (GLenum) param[0];
+ if (value == GL_TRUE || value == GL_FALSE) {
+ /* It's kind of weird to set point state via glTexEnv,
+ * but that's what the spec calls for.
+ */
+ const GLboolean state = (GLboolean) value;
+ if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
+ return;
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
+ return;
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(pname),
+ *param,
+ _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
+
+ /* Tell device driver about the new texture environment */
+ if (ctx->Driver.TexEnv) {
+ (*ctx->Driver.TexEnv)( ctx, target, pname, param );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
+{
+ _mesa_TexEnvfv( target, pname, &param );
+}
+
+
+
+void GLAPIENTRY
+_mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) param;
+ p[1] = p[2] = p[3] = 0.0;
+ _mesa_TexEnvfv( target, pname, p );
+}
+
+
+void GLAPIENTRY
+_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
+{
+ GLfloat p[4];
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ p[0] = INT_TO_FLOAT( param[0] );
+ p[1] = INT_TO_FLOAT( param[1] );
+ p[2] = INT_TO_FLOAT( param[2] );
+ p[3] = INT_TO_FLOAT( param[3] );
+ }
+ else {
+ p[0] = (GLfloat) param[0];
+ p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
+ }
+ _mesa_TexEnvfv( target, pname, p );
+}
+
+
+
+/**
+ * Helper for glGetTexEnvi/f()
+ * \return value of queried pname or -1 if error.
+ */
+static GLint
+get_texenvi(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+ GLenum pname)
+{
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ return texUnit->EnvMode;
+ break;
+ case GL_COMBINE_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return texUnit->Combine.ModeRGB;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_COMBINE_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return texUnit->Combine.ModeA;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE0_RGB:
+ case GL_SOURCE1_RGB:
+ case GL_SOURCE2_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
+ return texUnit->Combine.SourceRGB[rgb_idx];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.SourceRGB[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE0_ALPHA:
+ case GL_SOURCE1_ALPHA:
+ case GL_SOURCE2_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
+ return texUnit->Combine.SourceA[alpha_idx];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_SOURCE3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.SourceA[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND0_RGB:
+ case GL_OPERAND1_RGB:
+ case GL_OPERAND2_RGB:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned op_rgb = pname - GL_OPERAND0_RGB;
+ return texUnit->Combine.OperandRGB[op_rgb];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND3_RGB_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.OperandRGB[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND0_ALPHA:
+ case GL_OPERAND1_ALPHA:
+ case GL_OPERAND2_ALPHA:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
+ return texUnit->Combine.OperandA[op_alpha];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_OPERAND3_ALPHA_NV:
+ if (ctx->Extensions.NV_texture_env_combine4) {
+ return texUnit->Combine.OperandA[3];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_RGB_SCALE:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return 1 << texUnit->Combine.ScaleShiftRGB;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_ALPHA_SCALE:
+ if (ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine) {
+ return 1 << texUnit->Combine.ScaleShiftA;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+ case GL_BUMP_TARGET_ATI:
+ /* spec doesn't say so, but I think this should be queryable */
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ return texUnit->BumpTarget;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return -1; /* error */
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
+{
+ GLuint maxUnit;
+ const struct gl_texture_unit *texUnit;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+ ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+ if (ctx->Texture.CurrentUnit >= maxUnit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (target == GL_TEXTURE_ENV) {
+ if (pname == GL_TEXTURE_ENV_COLOR) {
+ COPY_4FV( params, texUnit->EnvColor );
+ }
+ else {
+ GLint val = get_texenvi(ctx, texUnit, pname);
+ if (val >= 0) {
+ *params = (GLfloat) val;
+ }
+ }
+ }
+ else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ /* GL_EXT_texture_lod_bias */
+ if (!ctx->Extensions.EXT_texture_lod_bias) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
+ return;
+ }
+ if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
+ *params = texUnit->LodBias;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
+ return;
+ }
+ }
+ else if (target == GL_POINT_SPRITE_NV) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
+ return;
+ }
+ if (pname == GL_COORD_REPLACE_NV) {
+ *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
+ return;
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
+{
+ GLuint maxUnit;
+ const struct gl_texture_unit *texUnit;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
+ ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
+ if (ctx->Texture.CurrentUnit >= maxUnit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (target == GL_TEXTURE_ENV) {
+ if (pname == 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] );
+ }
+ else {
+ GLint val = get_texenvi(ctx, texUnit, pname);
+ if (val >= 0) {
+ *params = val;
+ }
+ }
+ }
+ else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
+ /* GL_EXT_texture_lod_bias */
+ if (!ctx->Extensions.EXT_texture_lod_bias) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
+ return;
+ }
+ if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
+ *params = (GLint) texUnit->LodBias;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
+ return;
+ }
+ }
+ else if (target == GL_POINT_SPRITE_NV) {
+ /* GL_ARB_point_sprite / GL_NV_point_sprite */
+ if (!ctx->Extensions.NV_point_sprite
+ && !ctx->Extensions.ARB_point_sprite) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
+ return;
+ }
+ if (pname == GL_COORD_REPLACE_NV) {
+ *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
+ return;
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
+ return;
+ }
+}
+
+
+/**
+ * Why does ATI_envmap_bumpmap require new entrypoints? Should just
+ * reuse TexEnv ones...
+ */
+void GLAPIENTRY
+_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
+{
+ GLfloat p[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ /* This isn't an "official" error case, but let's tell the user
+ * that something's wrong.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterivATI");
+ return;
+ }
+
+ if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ /* hope that conversion is correct here */
+ p[0] = INT_TO_FLOAT( param[0] );
+ p[1] = INT_TO_FLOAT( param[1] );
+ p[2] = INT_TO_FLOAT( param[2] );
+ p[3] = INT_TO_FLOAT( param[3] );
+ }
+ else {
+ p[0] = (GLfloat) param[0];
+ p[1] = p[2] = p[3] = 0.0F; /* init to zero, just to be safe */
+ }
+ _mesa_TexBumpParameterfvATI( pname, p );
+}
+
+
+void GLAPIENTRY
+_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
+{
+ struct gl_texture_unit *texUnit;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterfvATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ if (TEST_EQ_4V(param, texUnit->RotMatrix))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texUnit->RotMatrix, param);
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
+ return;
+ }
+ /* Drivers might want to know about this, instead of dedicated function
+ just shove it into TexEnv where it really belongs anyway */
+ if (ctx->Driver.TexEnv) {
+ (*ctx->Driver.TexEnv)( ctx, 0, pname, param );
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
+{
+ const struct gl_texture_unit *texUnit;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterivATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
+ /* spec leaves open to support larger matrices.
+ Don't think anyone would ever want to use it
+ (and apps almost certainly would not understand it and
+ thus fail to submit matrices correctly) so hardcode this. */
+ *param = 4;
+ }
+ else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ /* hope that conversion is correct here */
+ param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
+ param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
+ param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
+ param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
+ }
+ else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
+ GLint count = 0;
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ count++;
+ }
+ }
+ *param = count;
+ }
+ else if (pname == GL_BUMP_TEX_UNITS_ATI) {
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ *param++ = i + GL_TEXTURE0;
+ }
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
+{
+ const struct gl_texture_unit *texUnit;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterfvATI");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
+ /* spec leaves open to support larger matrices.
+ Don't think anyone would ever want to use it
+ (and apps might not understand it) so hardcode this. */
+ *param = 4.0F;
+ }
+ else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
+ param[0] = texUnit->RotMatrix[0];
+ param[1] = texUnit->RotMatrix[1];
+ param[2] = texUnit->RotMatrix[2];
+ param[3] = texUnit->RotMatrix[3];
+ }
+ else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
+ GLint count = 0;
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ count++;
+ }
+ }
+ *param = (GLfloat) count;
+ }
+ else if (pname == GL_BUMP_TEX_UNITS_ATI) {
+ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (ctx->Const.SupportedBumpUnits & (1 << i)) {
+ *param++ = (GLfloat) (i + GL_TEXTURE0);
+ }
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
+ return;
+ }
+}
diff --git a/mesalib/src/mesa/main/texenv.h b/mesalib/src/mesa/main/texenv.h
new file mode 100644
index 000000000..1e9c5faed
--- /dev/null
+++ b/mesalib/src/mesa/main/texenv.h
@@ -0,0 +1,63 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 TEXENV_H
+#define TEXENV_H
+
+
+#include "main/glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params );
+
+extern void GLAPIENTRY
+_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param );
+
+extern void GLAPIENTRY
+_mesa_TexEnvi( GLenum target, GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param );
+
+extern void GLAPIENTRY
+_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param );
+
+extern void GLAPIENTRY
+_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param );
+
+extern void GLAPIENTRY
+_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param );
+
+extern void GLAPIENTRY
+_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param );
+
+#endif /* TEXENV_H */
diff --git a/mesalib/src/mesa/main/texenvprogram.c b/mesalib/src/mesa/main/texenvprogram.c
new file mode 100644
index 000000000..d7e77e759
--- /dev/null
+++ b/mesalib/src/mesa/main/texenvprogram.c
@@ -0,0 +1,1579 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * Copyright 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "glheader.h"
+#include "imports.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_cache.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "shader/programopt.h"
+#include "texenvprogram.h"
+
+
+/*
+ * Note on texture units:
+ *
+ * The number of texture units supported by fixed-function fragment
+ * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
+ * That's because there's a one-to-one correspondence between texture
+ * coordinates and samplers in fixed-function processing.
+ *
+ * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
+ * sets of texcoords, so is fixed-function fragment processing.
+ *
+ * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
+ */
+
+
+struct texenvprog_cache_item
+{
+ GLuint hash;
+ void *key;
+ struct gl_fragment_program *data;
+ struct texenvprog_cache_item *next;
+};
+
+static GLboolean
+texenv_doing_secondary_color(GLcontext *ctx)
+{
+ if (ctx->Light.Enabled &&
+ (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
+ return GL_TRUE;
+
+ if (ctx->Fog.ColorSumEnabled)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+/**
+ * Up to nine instructions per tex unit, plus fog, specular color.
+ */
+#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
+
+#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
+
+struct mode_opt {
+#ifdef __GNUC__
+ __extension__ GLubyte Source:4; /**< SRC_x */
+ __extension__ GLubyte Operand:3; /**< OPR_x */
+#else
+ GLubyte Source; /**< SRC_x */
+ GLubyte Operand; /**< OPR_x */
+#endif
+};
+
+struct state_key {
+ GLuint nr_enabled_units:8;
+ GLuint enabled_units:8;
+ GLuint separate_specular:1;
+ GLuint fog_enabled:1;
+ GLuint fog_mode:2; /**< FOG_x */
+ GLuint inputs_available:12;
+
+ /* NOTE: This array of structs must be last! (see "keySize" below) */
+ struct {
+ GLuint enabled:1;
+ GLuint source_index:3; /**< TEXTURE_x_INDEX */
+ GLuint shadow:1;
+ GLuint ScaleShiftRGB:2;
+ GLuint ScaleShiftA:2;
+
+ GLuint NumArgsRGB:3; /**< up to MAX_COMBINER_TERMS */
+ GLuint ModeRGB:5; /**< MODE_x */
+
+ GLuint NumArgsA:3; /**< up to MAX_COMBINER_TERMS */
+ GLuint ModeA:5; /**< MODE_x */
+
+ struct mode_opt OptRGB[MAX_COMBINER_TERMS];
+ struct mode_opt OptA[MAX_COMBINER_TERMS];
+ } unit[MAX_TEXTURE_UNITS];
+};
+
+#define FOG_LINEAR 0
+#define FOG_EXP 1
+#define FOG_EXP2 2
+#define FOG_UNKNOWN 3
+
+static GLuint translate_fog_mode( GLenum mode )
+{
+ switch (mode) {
+ case GL_LINEAR: return FOG_LINEAR;
+ case GL_EXP: return FOG_EXP;
+ case GL_EXP2: return FOG_EXP2;
+ default: return FOG_UNKNOWN;
+ }
+}
+
+#define OPR_SRC_COLOR 0
+#define OPR_ONE_MINUS_SRC_COLOR 1
+#define OPR_SRC_ALPHA 2
+#define OPR_ONE_MINUS_SRC_ALPHA 3
+#define OPR_ZERO 4
+#define OPR_ONE 5
+#define OPR_UNKNOWN 7
+
+static GLuint translate_operand( GLenum operand )
+{
+ switch (operand) {
+ case GL_SRC_COLOR: return OPR_SRC_COLOR;
+ case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
+ case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
+ case GL_ZERO: return OPR_ZERO;
+ case GL_ONE: return OPR_ONE;
+ default:
+ assert(0);
+ return OPR_UNKNOWN;
+ }
+}
+
+#define SRC_TEXTURE 0
+#define SRC_TEXTURE0 1
+#define SRC_TEXTURE1 2
+#define SRC_TEXTURE2 3
+#define SRC_TEXTURE3 4
+#define SRC_TEXTURE4 5
+#define SRC_TEXTURE5 6
+#define SRC_TEXTURE6 7
+#define SRC_TEXTURE7 8
+#define SRC_CONSTANT 9
+#define SRC_PRIMARY_COLOR 10
+#define SRC_PREVIOUS 11
+#define SRC_ZERO 12
+#define SRC_UNKNOWN 15
+
+static GLuint translate_source( GLenum src )
+{
+ switch (src) {
+ case GL_TEXTURE: return SRC_TEXTURE;
+ case GL_TEXTURE0:
+ case GL_TEXTURE1:
+ case GL_TEXTURE2:
+ case GL_TEXTURE3:
+ case GL_TEXTURE4:
+ case GL_TEXTURE5:
+ case GL_TEXTURE6:
+ case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
+ case GL_CONSTANT: return SRC_CONSTANT;
+ case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
+ case GL_PREVIOUS: return SRC_PREVIOUS;
+ case GL_ZERO:
+ return SRC_ZERO;
+ default:
+ assert(0);
+ return SRC_UNKNOWN;
+ }
+}
+
+#define MODE_REPLACE 0 /* r = a0 */
+#define MODE_MODULATE 1 /* r = a0 * a1 */
+#define MODE_ADD 2 /* r = a0 + a1 */
+#define MODE_ADD_SIGNED 3 /* r = a0 + a1 - 0.5 */
+#define MODE_INTERPOLATE 4 /* r = a0 * a2 + a1 * (1 - a2) */
+#define MODE_SUBTRACT 5 /* r = a0 - a1 */
+#define MODE_DOT3_RGB 6 /* r = a0 . a1 */
+#define MODE_DOT3_RGB_EXT 7 /* r = a0 . a1 */
+#define MODE_DOT3_RGBA 8 /* r = a0 . a1 */
+#define MODE_DOT3_RGBA_EXT 9 /* r = a0 . a1 */
+#define MODE_MODULATE_ADD_ATI 10 /* r = a0 * a2 + a1 */
+#define MODE_MODULATE_SIGNED_ADD_ATI 11 /* r = a0 * a2 + a1 - 0.5 */
+#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */
+#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */
+#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */
+#define MODE_BUMP_ENVMAP_ATI 15 /* special */
+#define MODE_UNKNOWN 16
+
+/**
+ * Translate GL combiner state into a MODE_x value
+ */
+static GLuint translate_mode( GLenum envMode, GLenum mode )
+{
+ switch (mode) {
+ case GL_REPLACE: return MODE_REPLACE;
+ case GL_MODULATE: return MODE_MODULATE;
+ case GL_ADD:
+ if (envMode == GL_COMBINE4_NV)
+ return MODE_ADD_PRODUCTS;
+ else
+ return MODE_ADD;
+ case GL_ADD_SIGNED:
+ if (envMode == GL_COMBINE4_NV)
+ return MODE_ADD_PRODUCTS_SIGNED;
+ else
+ return MODE_ADD_SIGNED;
+ case GL_INTERPOLATE: return MODE_INTERPOLATE;
+ case GL_SUBTRACT: return MODE_SUBTRACT;
+ case GL_DOT3_RGB: return MODE_DOT3_RGB;
+ case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
+ case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
+ case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
+ case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
+ case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
+ case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
+ case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
+ default:
+ assert(0);
+ return MODE_UNKNOWN;
+ }
+}
+
+
+/**
+ * Do we need to clamp the results of the given texture env/combine mode?
+ * If the inputs to the mode are in [0,1] we don't always have to clamp
+ * the results.
+ */
+static GLboolean
+need_saturate( GLuint mode )
+{
+ switch (mode) {
+ case MODE_REPLACE:
+ case MODE_MODULATE:
+ case MODE_INTERPOLATE:
+ return GL_FALSE;
+ case MODE_ADD:
+ case MODE_ADD_SIGNED:
+ case MODE_SUBTRACT:
+ case MODE_DOT3_RGB:
+ case MODE_DOT3_RGB_EXT:
+ case MODE_DOT3_RGBA:
+ case MODE_DOT3_RGBA_EXT:
+ case MODE_MODULATE_ADD_ATI:
+ case MODE_MODULATE_SIGNED_ADD_ATI:
+ case MODE_MODULATE_SUBTRACT_ATI:
+ case MODE_ADD_PRODUCTS:
+ case MODE_ADD_PRODUCTS_SIGNED:
+ case MODE_BUMP_ENVMAP_ATI:
+ return GL_TRUE;
+ default:
+ assert(0);
+ return GL_FALSE;
+ }
+}
+
+
+
+/**
+ * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
+ */
+static GLuint translate_tex_src_bit( GLbitfield bit )
+{
+ ASSERT(bit);
+ return _mesa_ffs(bit) - 1;
+}
+
+
+#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0)
+#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
+
+/**
+ * Identify all possible varying inputs. The fragment program will
+ * never reference non-varying inputs, but will track them via state
+ * constants instead.
+ *
+ * This function figures out all the inputs that the fragment program
+ * has access to. The bitmask is later reduced to just those which
+ * are actually referenced.
+ */
+static GLbitfield get_fp_input_mask( GLcontext *ctx )
+{
+ /* _NEW_PROGRAM */
+ const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus &&
+ ctx->Shader.CurrentProgram->VertexProgram);
+ const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
+ GLbitfield fp_inputs = 0x0;
+
+ if (ctx->VertexProgram._Overriden) {
+ /* Somebody's messing with the vertex program and we don't have
+ * a clue what's happening. Assume that it could be producing
+ * all possible outputs.
+ */
+ fp_inputs = ~0;
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ /* _NEW_RENDERMODE */
+ fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
+ }
+ else if (!(vertexProgram || vertexShader) ||
+ !ctx->VertexProgram._Current) {
+ /* Fixed function vertex logic */
+ /* _NEW_ARRAY */
+ GLbitfield varying_inputs = ctx->varying_vp_inputs;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ /* _NEW_POINT */
+ if (ctx->Point.PointSprite)
+ varying_inputs |= FRAG_BITS_TEX_ANY;
+
+ /* First look at what values may be computed by the generated
+ * vertex program:
+ */
+ /* _NEW_LIGHT */
+ if (ctx->Light.Enabled) {
+ fp_inputs |= FRAG_BIT_COL0;
+
+ if (texenv_doing_secondary_color(ctx))
+ fp_inputs |= FRAG_BIT_COL1;
+ }
+
+ /* _NEW_TEXTURE */
+ fp_inputs |= (ctx->Texture._TexGenEnabled |
+ ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
+
+ /* Then look at what might be varying as a result of enabled
+ * arrays, etc:
+ */
+ if (varying_inputs & VERT_BIT_COLOR0)
+ fp_inputs |= FRAG_BIT_COL0;
+ if (varying_inputs & VERT_BIT_COLOR1)
+ fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
+ << FRAG_ATTRIB_TEX0);
+
+ }
+ else {
+ /* calculate from vp->outputs */
+ struct gl_vertex_program *vprog;
+ GLbitfield vp_outputs;
+
+ /* Choose GLSL vertex shader over ARB vertex program. Need this
+ * since vertex shader state validation comes after fragment state
+ * validation (see additional comments in state.c).
+ */
+ if (vertexShader)
+ vprog = ctx->Shader.CurrentProgram->VertexProgram;
+ else
+ vprog = ctx->VertexProgram.Current;
+
+ vp_outputs = vprog->Base.OutputsWritten;
+
+ /* These get generated in the setup routine regardless of the
+ * vertex program:
+ */
+ /* _NEW_POINT */
+ if (ctx->Point.PointSprite)
+ vp_outputs |= FRAG_BITS_TEX_ANY;
+
+ if (vp_outputs & (1 << VERT_RESULT_COL0))
+ fp_inputs |= FRAG_BIT_COL0;
+ if (vp_outputs & (1 << VERT_RESULT_COL1))
+ fp_inputs |= FRAG_BIT_COL1;
+
+ fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
+ << FRAG_ATTRIB_TEX0);
+ }
+
+ return fp_inputs;
+}
+
+
+/**
+ * Examine current texture environment state and generate a unique
+ * key to identify it.
+ */
+static GLuint make_state_key( GLcontext *ctx, struct state_key *key )
+{
+ GLuint i, j;
+ GLbitfield inputs_referenced = FRAG_BIT_COL0;
+ const GLbitfield inputs_available = get_fp_input_mask( ctx );
+ GLuint keySize;
+
+ memset(key, 0, sizeof(*key));
+
+ /* _NEW_TEXTURE */
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+ const struct gl_texture_object *texObj = texUnit->_Current;
+ const struct gl_tex_env_combine_state *comb = texUnit->_CurrentCombine;
+ GLenum format;
+
+ if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
+ continue;
+
+ format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+
+ key->unit[i].enabled = 1;
+ key->enabled_units |= (1<<i);
+ key->nr_enabled_units = i + 1;
+ inputs_referenced |= FRAG_BIT_TEX(i);
+
+ key->unit[i].source_index =
+ translate_tex_src_bit(texUnit->_ReallyEnabled);
+
+ key->unit[i].shadow = ((texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
+ ((format == GL_DEPTH_COMPONENT) ||
+ (format == GL_DEPTH_STENCIL_EXT)));
+
+ key->unit[i].NumArgsRGB = comb->_NumArgsRGB;
+ key->unit[i].NumArgsA = comb->_NumArgsA;
+
+ key->unit[i].ModeRGB =
+ translate_mode(texUnit->EnvMode, comb->ModeRGB);
+ key->unit[i].ModeA =
+ translate_mode(texUnit->EnvMode, comb->ModeA);
+
+ key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
+ key->unit[i].ScaleShiftA = comb->ScaleShiftA;
+
+ for (j = 0; j < MAX_COMBINER_TERMS; j++) {
+ key->unit[i].OptRGB[j].Operand = translate_operand(comb->OperandRGB[j]);
+ key->unit[i].OptA[j].Operand = translate_operand(comb->OperandA[j]);
+ key->unit[i].OptRGB[j].Source = translate_source(comb->SourceRGB[j]);
+ key->unit[i].OptA[j].Source = translate_source(comb->SourceA[j]);
+ }
+
+ if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ /* requires some special translation */
+ key->unit[i].NumArgsRGB = 2;
+ key->unit[i].ScaleShiftRGB = 0;
+ key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
+ key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
+ key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
+ key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
+ }
+ }
+
+ /* _NEW_LIGHT | _NEW_FOG */
+ if (texenv_doing_secondary_color(ctx)) {
+ key->separate_specular = 1;
+ inputs_referenced |= FRAG_BIT_COL1;
+ }
+
+ /* _NEW_FOG */
+ if (ctx->Fog.Enabled) {
+ key->fog_enabled = 1;
+ key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
+ inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
+ }
+
+ key->inputs_available = (inputs_available & inputs_referenced);
+
+ /* compute size of state key, ignoring unused texture units */
+ keySize = sizeof(*key) - sizeof(key->unit)
+ + key->nr_enabled_units * sizeof(key->unit[0]);
+
+ return keySize;
+}
+
+
+/**
+ * Use uregs to represent registers internally, translate to Mesa's
+ * expected formats on emit.
+ *
+ * NOTE: These are passed by value extensively in this file rather
+ * than as usual by pointer reference. If this disturbs you, try
+ * remembering they are just 32bits in size.
+ *
+ * GCC is smart enough to deal with these dword-sized structures in
+ * much the same way as if I had defined them as dwords and was using
+ * macros to access and set the fields. This is much nicer and easier
+ * to evolve.
+ */
+struct ureg {
+ GLuint file:4;
+ GLuint idx:8;
+ GLuint negatebase:1;
+ GLuint swz:12;
+ GLuint pad:7;
+};
+
+static const struct ureg undef = {
+ PROGRAM_UNDEFINED,
+ ~0,
+ 0,
+ 0,
+ 0
+};
+
+
+/** State used to build the fragment program:
+ */
+struct texenv_fragment_program {
+ struct gl_fragment_program *program;
+ struct state_key *state;
+
+ GLbitfield alu_temps; /**< Track texture indirections, see spec. */
+ GLbitfield temps_output; /**< Track texture indirections, see spec. */
+ GLbitfield temp_in_use; /**< Tracks temporary regs which are in use. */
+ GLboolean error;
+
+ struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
+ /* Reg containing each texture unit's sampled texture color,
+ * else undef.
+ */
+
+ struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
+ /* Reg containing texcoord for a texture unit,
+ * needed for bump mapping, else undef.
+ */
+
+ struct ureg src_previous; /**< Reg containing color from previous
+ * stage. May need to be decl'd.
+ */
+
+ GLuint last_tex_stage; /**< Number of last enabled texture unit */
+
+ struct ureg half;
+ struct ureg one;
+ struct ureg zero;
+};
+
+
+
+static struct ureg make_ureg(GLuint file, GLuint idx)
+{
+ struct ureg reg;
+ reg.file = file;
+ reg.idx = idx;
+ reg.negatebase = 0;
+ reg.swz = SWIZZLE_NOOP;
+ reg.pad = 0;
+ return reg;
+}
+
+static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
+{
+ reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
+ GET_SWZ(reg.swz, y),
+ GET_SWZ(reg.swz, z),
+ GET_SWZ(reg.swz, w));
+
+ return reg;
+}
+
+static struct ureg swizzle1( struct ureg reg, int x )
+{
+ return swizzle(reg, x, x, x, x);
+}
+
+static struct ureg negate( struct ureg reg )
+{
+ reg.negatebase ^= 1;
+ return reg;
+}
+
+static GLboolean is_undef( struct ureg reg )
+{
+ return reg.file == PROGRAM_UNDEFINED;
+}
+
+
+static struct ureg get_temp( struct texenv_fragment_program *p )
+{
+ GLint bit;
+
+ /* First try and reuse temps which have been used already:
+ */
+ bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
+
+ /* Then any unused temporary:
+ */
+ if (!bit)
+ bit = _mesa_ffs( ~p->temp_in_use );
+
+ if (!bit) {
+ _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
+ _mesa_exit(1);
+ }
+
+ if ((GLuint) bit > p->program->Base.NumTemporaries)
+ p->program->Base.NumTemporaries = bit;
+
+ p->temp_in_use |= 1<<(bit-1);
+ return make_ureg(PROGRAM_TEMPORARY, (bit-1));
+}
+
+static struct ureg get_tex_temp( struct texenv_fragment_program *p )
+{
+ int bit;
+
+ /* First try to find available temp not previously used (to avoid
+ * starting a new texture indirection). According to the spec, the
+ * ~p->temps_output isn't necessary, but will keep it there for
+ * now:
+ */
+ bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
+
+ /* Then any unused temporary:
+ */
+ if (!bit)
+ bit = _mesa_ffs( ~p->temp_in_use );
+
+ if (!bit) {
+ _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
+ _mesa_exit(1);
+ }
+
+ if ((GLuint) bit > p->program->Base.NumTemporaries)
+ p->program->Base.NumTemporaries = bit;
+
+ p->temp_in_use |= 1<<(bit-1);
+ return make_ureg(PROGRAM_TEMPORARY, (bit-1));
+}
+
+
+/** Mark a temp reg as being no longer allocatable. */
+static void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
+{
+ if (r.file == PROGRAM_TEMPORARY)
+ p->temps_output |= (1 << r.idx);
+}
+
+
+static void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
+{
+ GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
+
+ /* KW: To support tex_env_crossbar, don't release the registers in
+ * temps_output.
+ */
+ if (max_temp >= sizeof(int) * 8)
+ p->temp_in_use = p->temps_output;
+ else
+ p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
+}
+
+
+static struct ureg register_param5( struct texenv_fragment_program *p,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4)
+{
+ gl_state_index tokens[STATE_LENGTH];
+ GLuint idx;
+ tokens[0] = s0;
+ tokens[1] = s1;
+ tokens[2] = s2;
+ tokens[3] = s3;
+ tokens[4] = s4;
+ idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
+ return make_ureg(PROGRAM_STATE_VAR, idx);
+}
+
+
+#define register_param1(p,s0) register_param5(p,s0,0,0,0,0)
+#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0)
+#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
+
+static GLuint frag_to_vert_attrib( GLuint attrib )
+{
+ switch (attrib) {
+ case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
+ case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
+ default:
+ assert(attrib >= FRAG_ATTRIB_TEX0);
+ assert(attrib <= FRAG_ATTRIB_TEX7);
+ return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
+ }
+}
+
+
+static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
+{
+ if (p->state->inputs_available & (1<<input)) {
+ p->program->Base.InputsRead |= (1 << input);
+ return make_ureg(PROGRAM_INPUT, input);
+ }
+ else {
+ GLuint idx = frag_to_vert_attrib( input );
+ return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
+ }
+}
+
+
+static void emit_arg( struct prog_src_register *reg,
+ struct ureg ureg )
+{
+ reg->File = ureg.file;
+ reg->Index = ureg.idx;
+ reg->Swizzle = ureg.swz;
+ reg->Negate = ureg.negatebase ? NEGATE_XYZW : NEGATE_NONE;
+ reg->Abs = GL_FALSE;
+}
+
+static void emit_dst( struct prog_dst_register *dst,
+ struct ureg ureg, GLuint mask )
+{
+ dst->File = ureg.file;
+ dst->Index = ureg.idx;
+ dst->WriteMask = mask;
+ dst->CondMask = COND_TR; /* always pass cond test */
+ dst->CondSwizzle = SWIZZLE_NOOP;
+}
+
+static struct prog_instruction *
+emit_op(struct texenv_fragment_program *p,
+ enum prog_opcode op,
+ struct ureg dest,
+ GLuint mask,
+ GLboolean saturate,
+ struct ureg src0,
+ struct ureg src1,
+ struct ureg src2 )
+{
+ const GLuint nr = p->program->Base.NumInstructions++;
+ struct prog_instruction *inst = &p->program->Base.Instructions[nr];
+
+ assert(nr < MAX_INSTRUCTIONS);
+
+ _mesa_init_instructions(inst, 1);
+ inst->Opcode = op;
+
+ emit_arg( &inst->SrcReg[0], src0 );
+ emit_arg( &inst->SrcReg[1], src1 );
+ emit_arg( &inst->SrcReg[2], src2 );
+
+ inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
+
+ emit_dst( &inst->DstReg, dest, mask );
+
+#if 0
+ /* Accounting for indirection tracking:
+ */
+ if (dest.file == PROGRAM_TEMPORARY)
+ p->temps_output |= 1 << dest.idx;
+#endif
+
+ return inst;
+}
+
+
+static struct ureg emit_arith( struct texenv_fragment_program *p,
+ enum prog_opcode op,
+ struct ureg dest,
+ GLuint mask,
+ GLboolean saturate,
+ struct ureg src0,
+ struct ureg src1,
+ struct ureg src2 )
+{
+ emit_op(p, op, dest, mask, saturate, src0, src1, src2);
+
+ /* Accounting for indirection tracking:
+ */
+ if (src0.file == PROGRAM_TEMPORARY)
+ p->alu_temps |= 1 << src0.idx;
+
+ if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
+ p->alu_temps |= 1 << src1.idx;
+
+ if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
+ p->alu_temps |= 1 << src2.idx;
+
+ if (dest.file == PROGRAM_TEMPORARY)
+ p->alu_temps |= 1 << dest.idx;
+
+ p->program->Base.NumAluInstructions++;
+ return dest;
+}
+
+static struct ureg emit_texld( struct texenv_fragment_program *p,
+ enum prog_opcode op,
+ struct ureg dest,
+ GLuint destmask,
+ GLuint tex_unit,
+ GLuint tex_idx,
+ GLuint tex_shadow,
+ struct ureg coord )
+{
+ struct prog_instruction *inst = emit_op( p, op,
+ dest, destmask,
+ GL_FALSE, /* don't saturate? */
+ coord, /* arg 0? */
+ undef,
+ undef);
+
+ inst->TexSrcTarget = tex_idx;
+ inst->TexSrcUnit = tex_unit;
+ inst->TexShadow = tex_shadow;
+
+ p->program->Base.NumTexInstructions++;
+
+ /* Accounting for indirection tracking:
+ */
+ reserve_temp(p, dest);
+
+#if 0
+ /* Is this a texture indirection?
+ */
+ if ((coord.file == PROGRAM_TEMPORARY &&
+ (p->temps_output & (1<<coord.idx))) ||
+ (dest.file == PROGRAM_TEMPORARY &&
+ (p->alu_temps & (1<<dest.idx)))) {
+ p->program->Base.NumTexIndirections++;
+ p->temps_output = 1<<coord.idx;
+ p->alu_temps = 0;
+ assert(0); /* KW: texture env crossbar */
+ }
+#endif
+
+ return dest;
+}
+
+
+static struct ureg register_const4f( struct texenv_fragment_program *p,
+ GLfloat s0,
+ GLfloat s1,
+ GLfloat s2,
+ GLfloat s3)
+{
+ GLfloat values[4];
+ GLuint idx, swizzle;
+ struct ureg r;
+ values[0] = s0;
+ values[1] = s1;
+ values[2] = s2;
+ values[3] = s3;
+ idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
+ &swizzle );
+ r = make_ureg(PROGRAM_CONSTANT, idx);
+ r.swz = swizzle;
+ return r;
+}
+
+#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
+#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
+#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
+#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
+
+
+static struct ureg get_one( struct texenv_fragment_program *p )
+{
+ if (is_undef(p->one))
+ p->one = register_scalar_const(p, 1.0);
+ return p->one;
+}
+
+static struct ureg get_half( struct texenv_fragment_program *p )
+{
+ if (is_undef(p->half))
+ p->half = register_scalar_const(p, 0.5);
+ return p->half;
+}
+
+static struct ureg get_zero( struct texenv_fragment_program *p )
+{
+ if (is_undef(p->zero))
+ p->zero = register_scalar_const(p, 0.0);
+ return p->zero;
+}
+
+
+static void program_error( struct texenv_fragment_program *p, const char *msg )
+{
+ _mesa_problem(NULL, msg);
+ p->error = 1;
+}
+
+static struct ureg get_source( struct texenv_fragment_program *p,
+ GLuint src, GLuint unit )
+{
+ switch (src) {
+ case SRC_TEXTURE:
+ assert(!is_undef(p->src_texture[unit]));
+ return p->src_texture[unit];
+
+ case SRC_TEXTURE0:
+ case SRC_TEXTURE1:
+ case SRC_TEXTURE2:
+ case SRC_TEXTURE3:
+ case SRC_TEXTURE4:
+ case SRC_TEXTURE5:
+ case SRC_TEXTURE6:
+ case SRC_TEXTURE7:
+ assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
+ return p->src_texture[src - SRC_TEXTURE0];
+
+ case SRC_CONSTANT:
+ return register_param2(p, STATE_TEXENV_COLOR, unit);
+
+ case SRC_PRIMARY_COLOR:
+ return register_input(p, FRAG_ATTRIB_COL0);
+
+ case SRC_ZERO:
+ return get_zero(p);
+
+ case SRC_PREVIOUS:
+ if (is_undef(p->src_previous))
+ return register_input(p, FRAG_ATTRIB_COL0);
+ else
+ return p->src_previous;
+
+ default:
+ assert(0);
+ return undef;
+ }
+}
+
+static struct ureg emit_combine_source( struct texenv_fragment_program *p,
+ GLuint mask,
+ GLuint unit,
+ GLuint source,
+ GLuint operand )
+{
+ struct ureg arg, src, one;
+
+ src = get_source(p, source, unit);
+
+ switch (operand) {
+ case OPR_ONE_MINUS_SRC_COLOR:
+ /* Get unused tmp,
+ * Emit tmp = 1.0 - arg.xyzw
+ */
+ arg = get_temp( p );
+ one = get_one( p );
+ return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
+
+ case OPR_SRC_ALPHA:
+ if (mask == WRITEMASK_W)
+ return src;
+ else
+ return swizzle1( src, SWIZZLE_W );
+ case OPR_ONE_MINUS_SRC_ALPHA:
+ /* Get unused tmp,
+ * Emit tmp = 1.0 - arg.wwww
+ */
+ arg = get_temp(p);
+ one = get_one(p);
+ return emit_arith(p, OPCODE_SUB, arg, mask, 0,
+ one, swizzle1(src, SWIZZLE_W), undef);
+ case OPR_ZERO:
+ return get_zero(p);
+ case OPR_ONE:
+ return get_one(p);
+ case OPR_SRC_COLOR:
+ return src;
+ default:
+ assert(0);
+ return src;
+ }
+}
+
+/**
+ * Check if the RGB and Alpha sources and operands match for the given
+ * texture unit's combinder state. When the RGB and A sources and
+ * operands match, we can emit fewer instructions.
+ */
+static GLboolean args_match( const struct state_key *key, GLuint unit )
+{
+ GLuint i, numArgs = key->unit[unit].NumArgsRGB;
+
+ for (i = 0; i < numArgs; i++) {
+ if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
+ return GL_FALSE;
+
+ switch (key->unit[unit].OptA[i].Operand) {
+ case OPR_SRC_ALPHA:
+ switch (key->unit[unit].OptRGB[i].Operand) {
+ case OPR_SRC_COLOR:
+ case OPR_SRC_ALPHA:
+ break;
+ default:
+ return GL_FALSE;
+ }
+ break;
+ case OPR_ONE_MINUS_SRC_ALPHA:
+ switch (key->unit[unit].OptRGB[i].Operand) {
+ case OPR_ONE_MINUS_SRC_COLOR:
+ case OPR_ONE_MINUS_SRC_ALPHA:
+ break;
+ default:
+ return GL_FALSE;
+ }
+ break;
+ default:
+ return GL_FALSE; /* impossible */
+ }
+ }
+
+ return GL_TRUE;
+}
+
+static struct ureg emit_combine( struct texenv_fragment_program *p,
+ struct ureg dest,
+ GLuint mask,
+ GLboolean saturate,
+ GLuint unit,
+ GLuint nr,
+ GLuint mode,
+ const struct mode_opt *opt)
+{
+ struct ureg src[MAX_COMBINER_TERMS];
+ struct ureg tmp, half;
+ GLuint i;
+
+ assert(nr <= MAX_COMBINER_TERMS);
+
+ tmp = undef; /* silence warning (bug 5318) */
+
+ for (i = 0; i < nr; i++)
+ src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
+
+ switch (mode) {
+ case MODE_REPLACE:
+ if (mask == WRITEMASK_XYZW && !saturate)
+ return src[0];
+ else
+ return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
+ case MODE_MODULATE:
+ return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
+ src[0], src[1], undef );
+ case MODE_ADD:
+ return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
+ src[0], src[1], undef );
+ case MODE_ADD_SIGNED:
+ /* tmp = arg0 + arg1
+ * result = tmp - .5
+ */
+ half = get_half(p);
+ tmp = get_temp( p );
+ emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
+ emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
+ return dest;
+ case MODE_INTERPOLATE:
+ /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
+ */
+ return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
+
+ case MODE_SUBTRACT:
+ return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
+
+ case MODE_DOT3_RGBA:
+ case MODE_DOT3_RGBA_EXT:
+ case MODE_DOT3_RGB_EXT:
+ case MODE_DOT3_RGB: {
+ struct ureg tmp0 = get_temp( p );
+ struct ureg tmp1 = get_temp( p );
+ struct ureg neg1 = register_scalar_const(p, -1);
+ struct ureg two = register_scalar_const(p, 2);
+
+ /* tmp0 = 2*src0 - 1
+ * tmp1 = 2*src1 - 1
+ *
+ * dst = tmp0 dot3 tmp1
+ */
+ emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
+ two, src[0], neg1);
+
+ if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
+ tmp1 = tmp0;
+ else
+ emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
+ two, src[1], neg1);
+ emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
+ return dest;
+ }
+ case MODE_MODULATE_ADD_ATI:
+ /* Arg0 * Arg2 + Arg1 */
+ return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
+ src[0], src[2], src[1] );
+ case MODE_MODULATE_SIGNED_ADD_ATI: {
+ /* Arg0 * Arg2 + Arg1 - 0.5 */
+ struct ureg tmp0 = get_temp(p);
+ half = get_half(p);
+ emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
+ emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
+ return dest;
+ }
+ case MODE_MODULATE_SUBTRACT_ATI:
+ /* Arg0 * Arg2 - Arg1 */
+ emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
+ return dest;
+ case MODE_ADD_PRODUCTS:
+ /* Arg0 * Arg1 + Arg2 * Arg3 */
+ {
+ struct ureg tmp0 = get_temp(p);
+ emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
+ emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 );
+ }
+ return dest;
+ case MODE_ADD_PRODUCTS_SIGNED:
+ /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */
+ {
+ struct ureg tmp0 = get_temp(p);
+ half = get_half(p);
+ emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
+ emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 );
+ emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
+ }
+ return dest;
+ case MODE_BUMP_ENVMAP_ATI:
+ /* special - not handled here */
+ assert(0);
+ return src[0];
+ default:
+ assert(0);
+ return src[0];
+ }
+}
+
+
+/**
+ * Generate instructions for one texture unit's env/combiner mode.
+ */
+static struct ureg
+emit_texenv(struct texenv_fragment_program *p, GLuint unit)
+{
+ const struct state_key *key = p->state;
+ GLboolean rgb_saturate, alpha_saturate;
+ GLuint rgb_shift, alpha_shift;
+ struct ureg out, dest;
+
+ if (!key->unit[unit].enabled) {
+ return get_source(p, SRC_PREVIOUS, 0);
+ }
+ if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ /* this isn't really a env stage delivering a color and handled elsewhere */
+ return get_source(p, SRC_PREVIOUS, 0);
+ }
+
+ switch (key->unit[unit].ModeRGB) {
+ case MODE_DOT3_RGB_EXT:
+ alpha_shift = key->unit[unit].ScaleShiftA;
+ rgb_shift = 0;
+ break;
+ case MODE_DOT3_RGBA_EXT:
+ alpha_shift = 0;
+ rgb_shift = 0;
+ break;
+ default:
+ rgb_shift = key->unit[unit].ScaleShiftRGB;
+ alpha_shift = key->unit[unit].ScaleShiftA;
+ break;
+ }
+
+ /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
+ * We don't want to clamp twice.
+ */
+ if (rgb_shift)
+ rgb_saturate = GL_FALSE; /* saturate after rgb shift */
+ else if (need_saturate(key->unit[unit].ModeRGB))
+ rgb_saturate = GL_TRUE;
+ else
+ rgb_saturate = GL_FALSE;
+
+ if (alpha_shift)
+ alpha_saturate = GL_FALSE; /* saturate after alpha shift */
+ else if (need_saturate(key->unit[unit].ModeA))
+ alpha_saturate = GL_TRUE;
+ else
+ alpha_saturate = GL_FALSE;
+
+ /* If this is the very last calculation, emit direct to output reg:
+ */
+ if (key->separate_specular ||
+ unit != p->last_tex_stage ||
+ alpha_shift ||
+ rgb_shift)
+ dest = get_temp( p );
+ else
+ dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
+
+ /* Emit the RGB and A combine ops
+ */
+ if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
+ args_match(key, unit)) {
+ out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
+ unit,
+ key->unit[unit].NumArgsRGB,
+ key->unit[unit].ModeRGB,
+ key->unit[unit].OptRGB);
+ }
+ else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
+ key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
+ out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
+ unit,
+ key->unit[unit].NumArgsRGB,
+ key->unit[unit].ModeRGB,
+ key->unit[unit].OptRGB);
+ }
+ else {
+ /* Need to do something to stop from re-emitting identical
+ * argument calculations here:
+ */
+ out = emit_combine( p, dest, WRITEMASK_XYZ, rgb_saturate,
+ unit,
+ key->unit[unit].NumArgsRGB,
+ key->unit[unit].ModeRGB,
+ key->unit[unit].OptRGB);
+ out = emit_combine( p, dest, WRITEMASK_W, alpha_saturate,
+ unit,
+ key->unit[unit].NumArgsA,
+ key->unit[unit].ModeA,
+ key->unit[unit].OptA);
+ }
+
+ /* Deal with the final shift:
+ */
+ if (alpha_shift || rgb_shift) {
+ struct ureg shift;
+ GLboolean saturate = GL_TRUE; /* always saturate at this point */
+
+ if (rgb_shift == alpha_shift) {
+ shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
+ }
+ else {
+ shift = register_const4f(p,
+ (GLfloat)(1<<rgb_shift),
+ (GLfloat)(1<<rgb_shift),
+ (GLfloat)(1<<rgb_shift),
+ (GLfloat)(1<<alpha_shift));
+ }
+ return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
+ saturate, out, shift, undef );
+ }
+ else
+ return out;
+}
+
+
+/**
+ * Generate instruction for getting a texture source term.
+ */
+static void load_texture( struct texenv_fragment_program *p, GLuint unit )
+{
+ if (is_undef(p->src_texture[unit])) {
+ const GLuint texTarget = p->state->unit[unit].source_index;
+ struct ureg texcoord;
+ struct ureg tmp = get_tex_temp( p );
+
+ if (is_undef(p->texcoord_tex[unit])) {
+ texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
+ }
+ else {
+ /* might want to reuse this reg for tex output actually */
+ texcoord = p->texcoord_tex[unit];
+ }
+
+ /* TODO: Use D0_MASK_XY where possible.
+ */
+ if (p->state->unit[unit].enabled) {
+ GLboolean shadow = GL_FALSE;
+
+ if (p->state->unit[unit].shadow) {
+ p->program->Base.ShadowSamplers |= 1 << unit;
+ shadow = GL_TRUE;
+ }
+
+ p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
+ tmp, WRITEMASK_XYZW,
+ unit, texTarget, shadow,
+ texcoord );
+
+ p->program->Base.SamplersUsed |= (1 << unit);
+ /* This identity mapping should already be in place
+ * (see _mesa_init_program_struct()) but let's be safe.
+ */
+ p->program->Base.SamplerUnits[unit] = unit;
+ }
+ else
+ p->src_texture[unit] = get_zero(p);
+ }
+}
+
+static GLboolean load_texenv_source( struct texenv_fragment_program *p,
+ GLuint src, GLuint unit )
+{
+ switch (src) {
+ case SRC_TEXTURE:
+ load_texture(p, unit);
+ break;
+
+ case SRC_TEXTURE0:
+ case SRC_TEXTURE1:
+ case SRC_TEXTURE2:
+ case SRC_TEXTURE3:
+ case SRC_TEXTURE4:
+ case SRC_TEXTURE5:
+ case SRC_TEXTURE6:
+ case SRC_TEXTURE7:
+ load_texture(p, src - SRC_TEXTURE0);
+ break;
+
+ default:
+ /* not a texture src - do nothing */
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Generate instructions for loading all texture source terms.
+ */
+static GLboolean
+load_texunit_sources( struct texenv_fragment_program *p, GLuint unit )
+{
+ const struct state_key *key = p->state;
+ GLuint i;
+
+ for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
+ load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
+ }
+
+ for (i = 0; i < key->unit[unit].NumArgsA; i++) {
+ load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
+ }
+
+ return GL_TRUE;
+}
+
+/**
+ * Generate instructions for loading bump map textures.
+ */
+static GLboolean
+load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit )
+{
+ const struct state_key *key = p->state;
+ GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
+ struct ureg texcDst, bumpMapRes;
+ struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
+ struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
+ struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
+ struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
+
+ load_texenv_source( p, unit + SRC_TEXTURE0, unit );
+
+ bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
+ texcDst = get_tex_temp( p );
+ p->texcoord_tex[bumpedUnitNr] = texcDst;
+
+ /* Apply rot matrix and add coords to be available in next phase.
+ * dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1)
+ * note only 2 coords are affected the rest are left unchanged (mul by 0)
+ */
+ emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
+ swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
+ emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
+ swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
+
+ /* Move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
+ * enough to access this later, should optimize away.
+ */
+ emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0,
+ constdudvcolor, undef, undef );
+
+ return GL_TRUE;
+}
+
+/**
+ * Generate a new fragment program which implements the context's
+ * current texture env/combine mode.
+ */
+static void
+create_new_program(GLcontext *ctx, struct state_key *key,
+ struct gl_fragment_program *program)
+{
+ struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
+ struct texenv_fragment_program p;
+ GLuint unit;
+ struct ureg cf, out;
+
+ _mesa_memset(&p, 0, sizeof(p));
+ p.state = key;
+ p.program = program;
+
+ /* During code generation, use locally-allocated instruction buffer,
+ * then alloc dynamic storage below.
+ */
+ p.program->Base.Instructions = instBuffer;
+ p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
+ p.program->Base.String = NULL;
+ p.program->Base.NumTexIndirections = 1; /* is this right? */
+ p.program->Base.NumTexInstructions = 0;
+ p.program->Base.NumAluInstructions = 0;
+ p.program->Base.NumInstructions = 0;
+ p.program->Base.NumTemporaries = 0;
+ p.program->Base.NumParameters = 0;
+ p.program->Base.NumAttributes = 0;
+ p.program->Base.NumAddressRegs = 0;
+ p.program->Base.Parameters = _mesa_new_parameter_list();
+ p.program->Base.InputsRead = 0x0;
+ p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
+
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ p.src_texture[unit] = undef;
+ p.texcoord_tex[unit] = undef;
+ }
+
+ p.src_previous = undef;
+ p.half = undef;
+ p.zero = undef;
+ p.one = undef;
+
+ p.last_tex_stage = 0;
+ release_temps(ctx, &p);
+
+ if (key->enabled_units) {
+ GLboolean needbumpstage = GL_FALSE;
+
+ /* Zeroth pass - bump map textures first */
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
+ if (key->unit[unit].enabled &&
+ key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
+ needbumpstage = GL_TRUE;
+ load_texunit_bumpmap( &p, unit );
+ }
+ if (needbumpstage)
+ p.program->Base.NumTexIndirections++;
+
+ /* First pass - to support texture_env_crossbar, first identify
+ * all referenced texture sources and emit texld instructions
+ * for each:
+ */
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
+ if (key->unit[unit].enabled) {
+ load_texunit_sources( &p, unit );
+ p.last_tex_stage = unit;
+ }
+
+ /* Second pass - emit combine instructions to build final color:
+ */
+ for (unit = 0; unit < key->nr_enabled_units; unit++)
+ if (key->unit[unit].enabled) {
+ p.src_previous = emit_texenv( &p, unit );
+ reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
+ release_temps(ctx, &p); /* release all temps */
+ }
+ }
+
+ cf = get_source( &p, SRC_PREVIOUS, 0 );
+ out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLOR );
+
+ if (key->separate_specular) {
+ /* Emit specular add.
+ */
+ struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
+ emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
+ emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
+ }
+ else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
+ /* Will wind up in here if no texture enabled or a couple of
+ * other scenarios (GL_REPLACE for instance).
+ */
+ emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
+ }
+
+ /* Finish up:
+ */
+ emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
+
+ if (key->fog_enabled) {
+ /* Pull fog mode from GLcontext, the value in the state key is
+ * a reduced value and not what is expected in FogOption
+ */
+ p.program->FogOption = ctx->Fog.Mode;
+ p.program->Base.InputsRead |= FRAG_BIT_FOGC;
+ }
+ else {
+ p.program->FogOption = GL_NONE;
+ }
+
+ if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
+ program_error(&p, "Exceeded max nr indirect texture lookups");
+
+ if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
+ program_error(&p, "Exceeded max TEX instructions");
+
+ if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
+ program_error(&p, "Exceeded max ALU instructions");
+
+ ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
+
+ /* Allocate final instruction array */
+ p.program->Base.Instructions
+ = _mesa_alloc_instructions(p.program->Base.NumInstructions);
+ if (!p.program->Base.Instructions) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "generating tex env program");
+ return;
+ }
+ _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
+ p.program->Base.NumInstructions);
+
+ if (p.program->FogOption) {
+ _mesa_append_fog_code(ctx, p.program);
+ p.program->FogOption = GL_NONE;
+ }
+
+
+ /* Notify driver the fragment program has (actually) changed.
+ */
+ if (ctx->Driver.ProgramStringNotify) {
+ ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
+ &p.program->Base );
+ }
+
+ if (DISASSEM) {
+ _mesa_print_program(&p.program->Base);
+ _mesa_printf("\n");
+ }
+}
+
+
+/**
+ * Return a fragment program which implements the current
+ * fixed-function texture, fog and color-sum operations.
+ */
+struct gl_fragment_program *
+_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
+{
+ struct gl_fragment_program *prog;
+ struct state_key key;
+ GLuint keySize;
+
+ keySize = make_state_key(ctx, &key);
+
+ prog = (struct gl_fragment_program *)
+ _mesa_search_program_cache(ctx->FragmentProgram.Cache,
+ &key, keySize);
+
+ if (!prog) {
+ prog = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+
+ create_new_program(ctx, &key, prog);
+
+ _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
+ &key, keySize, &prog->Base);
+ }
+
+ return prog;
+}
diff --git a/mesalib/src/mesa/main/texenvprogram.h b/mesalib/src/mesa/main/texenvprogram.h
new file mode 100644
index 000000000..0a162d2e7
--- /dev/null
+++ b/mesalib/src/mesa/main/texenvprogram.h
@@ -0,0 +1,35 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 TEXENVPROGRAM_H
+#define TEXENVPROGRAM_H
+
+
+#include "mtypes.h"
+
+extern struct gl_fragment_program *
+_mesa_get_fixed_func_fragment_program(GLcontext *ctx);
+
+#endif
diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c
new file mode 100644
index 000000000..c70900478
--- /dev/null
+++ b/mesalib/src/mesa/main/texformat.c
@@ -0,0 +1,1989 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texformat.c
+ * Texture formats.
+ *
+ * \author Gareth Hughes
+ */
+
+
+#include "colormac.h"
+#include "context.h"
+#include "texformat.h"
+#include "texstore.h"
+
+
+#if FEATURE_EXT_texture_sRGB
+
+/**
+ * Convert an 8-bit sRGB value from non-linear space to a
+ * linear RGB value in [0, 1].
+ * Implemented with a 256-entry lookup table.
+ */
+static INLINE GLfloat
+nonlinear_to_linear(GLubyte cs8)
+{
+ static GLfloat table[256];
+ static GLboolean tableReady = GL_FALSE;
+ if (!tableReady) {
+ /* compute lookup table now */
+ GLuint i;
+ for (i = 0; i < 256; i++) {
+ const GLfloat cs = UBYTE_TO_FLOAT(i);
+ if (cs <= 0.04045) {
+ table[i] = cs / 12.92f;
+ }
+ else {
+ table[i] = (GLfloat) _mesa_pow((cs + 0.055) / 1.055, 2.4);
+ }
+ }
+ tableReady = GL_TRUE;
+ }
+ return table[cs8];
+}
+
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/* Texel fetch routines for all supported formats
+ */
+#define DIM 1
+#include "texformat_tmp.h"
+
+#define DIM 2
+#include "texformat_tmp.h"
+
+#define DIM 3
+#include "texformat_tmp.h"
+
+/**
+ * Null texel fetch function.
+ *
+ * Have to have this so the FetchTexel function pointer is never NULL.
+ */
+static void fetch_null_texel( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ (void) texImage; (void) i; (void) j; (void) k;
+ texel[RCOMP] = 0;
+ texel[GCOMP] = 0;
+ texel[BCOMP] = 0;
+ texel[ACOMP] = 0;
+ _mesa_warning(NULL, "fetch_null_texel() called!");
+}
+
+static void fetch_null_texelf( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ (void) texImage; (void) i; (void) j; (void) k;
+ texel[RCOMP] = 0.0;
+ texel[GCOMP] = 0.0;
+ texel[BCOMP] = 0.0;
+ texel[ACOMP] = 0.0;
+ _mesa_warning(NULL, "fetch_null_texelf() called!");
+}
+
+static void store_null_texel(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ (void) texImage;
+ (void) i;
+ (void) j;
+ (void) k;
+ (void) texel;
+ /* no-op */
+}
+
+
+/**
+ * Notes about the predefined gl_texture_formats:
+ *
+ * 1. There are 1D, 2D and 3D functions for fetching texels from texture
+ * images, returning both GLchan values and GLfloat values. (six
+ * functions in total)
+ * You don't have to provide both the GLchan and GLfloat functions;
+ * just one or the other is OK. Mesa will use an "adaptor" to convert
+ * between GLchan/GLfloat when needed.
+ * Since the adaptors have small performance penalty, we provide both
+ * GLchan and GLfloat functions for some common formats like RGB, RGBA.
+ */
+
+
+/***************************************************************/
+/** \name Default GLchan-based formats */
+/*@{*/
+
+const struct gl_texture_format _mesa_texformat_rgba = {
+ MESA_FORMAT_RGBA, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ CHAN_BITS, /* RedBits */
+ CHAN_BITS, /* GreenBits */
+ CHAN_BITS, /* BlueBits */
+ CHAN_BITS, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4 * sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba, /* FetchTexel3Df */
+ store_texel_rgba /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb = {
+ MESA_FORMAT_RGB, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ CHAN_BITS, /* RedBits */
+ CHAN_BITS, /* GreenBits */
+ CHAN_BITS, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3 * sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb, /* FetchTexel3Df */
+ store_texel_rgb /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_alpha = {
+ MESA_FORMAT_ALPHA, /* MesaFormat */
+ GL_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ CHAN_BITS, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_alpha, /* FetchTexel1Df */
+ fetch_texel_2d_f_alpha, /* FetchTexel2Df */
+ fetch_texel_3d_f_alpha, /* FetchTexel3Df */
+ store_texel_alpha /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance = {
+ MESA_FORMAT_LUMINANCE, /* MesaFormat */
+ GL_LUMINANCE, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ CHAN_BITS, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance, /* FetchTexel3Df */
+ store_texel_luminance /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance_alpha = {
+ MESA_FORMAT_LUMINANCE_ALPHA, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ CHAN_BITS, /* AlphaBits */
+ CHAN_BITS, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2 * sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_alpha, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_alpha, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_alpha, /* FetchTexel3Df */
+ store_texel_luminance_alpha /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_intensity = {
+ MESA_FORMAT_INTENSITY, /* MesaFormat */
+ GL_INTENSITY, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ CHAN_BITS, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ sizeof(GLchan), /* TexelBytes */
+ _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_intensity, /* FetchTexel1Df */
+ fetch_texel_2d_f_intensity, /* FetchTexel2Df */
+ fetch_texel_3d_f_intensity, /* FetchTexel3Df */
+ store_texel_intensity /* StoreTexel */
+};
+
+
+#if FEATURE_EXT_texture_sRGB
+
+const struct gl_texture_format _mesa_texformat_srgb8 = {
+ MESA_FORMAT_SRGB8, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3, /* TexelBytes */
+ _mesa_texstore_srgb8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_srgb8, /* FetchTexel1Df */
+ fetch_texel_2d_srgb8, /* FetchTexel2Df */
+ fetch_texel_3d_srgb8, /* FetchTexel3Df */
+ store_texel_srgb8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_srgba8 = {
+ MESA_FORMAT_SRGBA8, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_srgba8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_srgba8, /* FetchTexel1Df */
+ fetch_texel_2d_srgba8, /* FetchTexel2Df */
+ fetch_texel_3d_srgba8, /* FetchTexel3Df */
+ store_texel_srgba8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_sargb8 = {
+ MESA_FORMAT_SARGB8, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_sargb8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_sargb8, /* FetchTexel1Df */
+ fetch_texel_2d_sargb8, /* FetchTexel2Df */
+ fetch_texel_3d_sargb8, /* FetchTexel3Df */
+ store_texel_sargb8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_sl8 = {
+ MESA_FORMAT_SL8, /* MesaFormat */
+ GL_LUMINANCE, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_sl8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_sl8, /* FetchTexel1Df */
+ fetch_texel_2d_sl8, /* FetchTexel2Df */
+ fetch_texel_3d_sl8, /* FetchTexel3Df */
+ store_texel_sl8 /* StoreTexel */
+};
+
+/* Note: this format name looks like a misnomer, make it sal8? */
+const struct gl_texture_format _mesa_texformat_sla8 = {
+ MESA_FORMAT_SLA8, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_sla8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_sla8, /* FetchTexel1Df */
+ fetch_texel_2d_sla8, /* FetchTexel2Df */
+ fetch_texel_3d_sla8, /* FetchTexel3Df */
+ store_texel_sla8 /* StoreTexel */
+};
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+const struct gl_texture_format _mesa_texformat_rgba_float32 = {
+ MESA_FORMAT_RGBA_FLOAT32, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 8 * sizeof(GLfloat), /* RedBits */
+ 8 * sizeof(GLfloat), /* GreenBits */
+ 8 * sizeof(GLfloat), /* BlueBits */
+ 8 * sizeof(GLfloat), /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_rgba_f32, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_f32, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba_f32, /* FetchTexel3Df */
+ store_texel_rgba_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba_float16 = {
+ MESA_FORMAT_RGBA_FLOAT16, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 8 * sizeof(GLhalfARB), /* RedBits */
+ 8 * sizeof(GLhalfARB), /* GreenBits */
+ 8 * sizeof(GLhalfARB), /* BlueBits */
+ 8 * sizeof(GLhalfARB), /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_rgba_f16, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba_f16, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba_f16, /* FetchTexel3Df */
+ store_texel_rgba_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb_float32 = {
+ MESA_FORMAT_RGB_FLOAT32, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 8 * sizeof(GLfloat), /* RedBits */
+ 8 * sizeof(GLfloat), /* GreenBits */
+ 8 * sizeof(GLfloat), /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_rgb_f32, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb_f32, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb_f32, /* FetchTexel3Df */
+ store_texel_rgb_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb_float16 = {
+ MESA_FORMAT_RGB_FLOAT16, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 8 * sizeof(GLhalfARB), /* RedBits */
+ 8 * sizeof(GLhalfARB), /* GreenBits */
+ 8 * sizeof(GLhalfARB), /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_rgb_f16, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb_f16, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb_f16, /* FetchTexel3Df */
+ store_texel_rgb_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_alpha_float32 = {
+ MESA_FORMAT_ALPHA_FLOAT32, /* MesaFormat */
+ GL_ALPHA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8 * sizeof(GLfloat), /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_alpha_f32, /* FetchTexel1Df */
+ fetch_texel_2d_f_alpha_f32, /* FetchTexel2Df */
+ fetch_texel_3d_f_alpha_f32, /* FetchTexel3Df */
+ store_texel_alpha_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_alpha_float16 = {
+ MESA_FORMAT_ALPHA_FLOAT16, /* MesaFormat */
+ GL_ALPHA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8 * sizeof(GLhalfARB), /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_alpha_f16, /* FetchTexel1Df */
+ fetch_texel_2d_f_alpha_f16, /* FetchTexel2Df */
+ fetch_texel_3d_f_alpha_f16, /* FetchTexel3Df */
+ store_texel_alpha_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance_float32 = {
+ MESA_FORMAT_LUMINANCE_FLOAT32, /* MesaFormat */
+ GL_LUMINANCE, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 8 * sizeof(GLfloat), /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_f32, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_f32, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_f32, /* FetchTexel3Df */
+ store_texel_luminance_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance_float16 = {
+ MESA_FORMAT_LUMINANCE_FLOAT16, /* MesaFormat */
+ GL_LUMINANCE, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 8 * sizeof(GLhalfARB), /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_f16, /* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_f16, /* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_f16, /* FetchTexel3Df */
+ store_texel_luminance_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance_alpha_float32 = {
+ MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8 * sizeof(GLfloat), /* AlphaBits */
+ 8 * sizeof(GLfloat), /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_alpha_f32,/* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_alpha_f32,/* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_alpha_f32,/* FetchTexel3Df */
+ store_texel_luminance_alpha_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_luminance_alpha_float16 = {
+ MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8 * sizeof(GLhalfARB), /* AlphaBits */
+ 8 * sizeof(GLhalfARB), /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_luminance_alpha_f16,/* FetchTexel1Df */
+ fetch_texel_2d_f_luminance_alpha_f16,/* FetchTexel2Df */
+ fetch_texel_3d_f_luminance_alpha_f16,/* FetchTexel3Df */
+ store_texel_luminance_alpha_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_intensity_float32 = {
+ MESA_FORMAT_INTENSITY_FLOAT32, /* MesaFormat */
+ GL_INTENSITY, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 8 * sizeof(GLfloat), /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLfloat), /* TexelBytes */
+ _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_intensity_f32, /* FetchTexel1Df */
+ fetch_texel_2d_f_intensity_f32, /* FetchTexel2Df */
+ fetch_texel_3d_f_intensity_f32, /* FetchTexel3Df */
+ store_texel_intensity_f32 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_intensity_float16 = {
+ MESA_FORMAT_INTENSITY_FLOAT16, /* MesaFormat */
+ GL_INTENSITY, /* BaseFormat */
+ GL_FLOAT, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 8 * sizeof(GLhalfARB), /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1 * sizeof(GLhalfARB), /* TexelBytes */
+ _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_intensity_f16, /* FetchTexel1Df */
+ fetch_texel_2d_f_intensity_f16, /* FetchTexel2Df */
+ fetch_texel_3d_f_intensity_f16, /* FetchTexel3Df */
+ store_texel_intensity_f16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_dudv8 = {
+ MESA_FORMAT_DUDV8, /* MesaFormat */
+ GL_DUDV_ATI, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ /* maybe should add dudvBits field, but spec seems to be
+ lacking the ability to query with GetTexLevelParameter anyway */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_dudv8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_dudv8, /* FetchTexel1Df */
+ fetch_texel_2d_dudv8, /* FetchTexel2Df */
+ fetch_texel_3d_dudv8, /* FetchTexel3Df */
+ NULL /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_signed_rgba8888 = {
+ MESA_FORMAT_SIGNED_RGBA8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_signed_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_signed_rgba8888, /* FetchTexel1Df */
+ fetch_texel_2d_signed_rgba8888, /* FetchTexel2Df */
+ fetch_texel_3d_signed_rgba8888, /* FetchTexel3Df */
+ store_texel_signed_rgba8888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_signed_rgba8888_rev = {
+ MESA_FORMAT_SIGNED_RGBA8888_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_SIGNED_NORMALIZED, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_signed_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_signed_rgba8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_signed_rgba8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_signed_rgba8888_rev, /* FetchTexel3Df */
+ store_texel_signed_rgba8888_rev /* StoreTexel */
+};
+
+/*@}*/
+
+
+/***************************************************************/
+/** \name Hardware formats */
+/*@{*/
+
+const struct gl_texture_format _mesa_texformat_rgba8888 = {
+ MESA_FORMAT_RGBA8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba8888, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba8888, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba8888, /* FetchTexel3Df */
+ store_texel_rgba8888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba8888_rev = {
+ MESA_FORMAT_RGBA8888_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_rgba8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba8888_rev, /* FetchTexel3Df */
+ store_texel_rgba8888_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb8888 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb8888, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb8888, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb8888, /* FetchTexel3Df */
+ store_texel_argb8888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb8888_rev = {
+ MESA_FORMAT_ARGB8888_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb8888_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb8888_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb8888_rev, /* FetchTexel3Df */
+ store_texel_argb8888_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb888 = {
+ MESA_FORMAT_RGB888, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3, /* TexelBytes */
+ _mesa_texstore_rgb888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb888, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb888, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb888, /* FetchTexel3Df */
+ store_texel_rgb888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_bgr888 = {
+ MESA_FORMAT_BGR888, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 3, /* TexelBytes */
+ _mesa_texstore_bgr888, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_bgr888, /* FetchTexel1Df */
+ fetch_texel_2d_f_bgr888, /* FetchTexel2Df */
+ fetch_texel_3d_f_bgr888, /* FetchTexel3Df */
+ store_texel_bgr888 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb565 = {
+ MESA_FORMAT_RGB565, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 6, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_rgb565, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb565, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb565, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb565, /* FetchTexel3Df */
+ store_texel_rgb565 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb565_rev = {
+ MESA_FORMAT_RGB565_REV, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 6, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_rgb565, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb565_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb565_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb565_rev, /* FetchTexel3Df */
+ store_texel_rgb565_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba4444 = {
+ MESA_FORMAT_RGBA4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_rgba4444, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba4444, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba4444, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba4444, /* FetchTexel3Df */
+ store_texel_rgba4444 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb4444 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb4444, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb4444, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb4444, /* FetchTexel3Df */
+ store_texel_argb4444 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb4444_rev = {
+ MESA_FORMAT_ARGB4444_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb4444_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb4444_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb4444_rev, /* FetchTexel3Df */
+ store_texel_argb4444_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgba5551 = {
+ MESA_FORMAT_RGBA5551, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 1, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_rgba5551, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgba5551, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgba5551, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgba5551, /* FetchTexel3Df */
+ store_texel_rgba5551 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb1555 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 1, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb1555, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb1555, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb1555, /* FetchTexel3Df */
+ store_texel_argb1555 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_argb1555_rev = {
+ MESA_FORMAT_ARGB1555_REV, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 1, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_argb1555_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_argb1555_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_argb1555_rev, /* FetchTexel3Df */
+ store_texel_argb1555_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_al88 = {
+ MESA_FORMAT_AL88, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_al88, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_al88, /* FetchTexel1Df */
+ fetch_texel_2d_f_al88, /* FetchTexel2Df */
+ fetch_texel_3d_f_al88, /* FetchTexel3Df */
+ store_texel_al88 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_al88_rev = {
+ MESA_FORMAT_AL88_REV, /* MesaFormat */
+ GL_LUMINANCE_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_al88, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_al88_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_al88_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_al88_rev, /* FetchTexel3Df */
+ store_texel_al88_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_rgb332 = {
+ MESA_FORMAT_RGB332, /* MesaFormat */
+ GL_RGB, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 3, /* RedBits */
+ 3, /* GreenBits */
+ 2, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_rgb332, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_rgb332, /* FetchTexel1Df */
+ fetch_texel_2d_f_rgb332, /* FetchTexel2Df */
+ fetch_texel_3d_f_rgb332, /* FetchTexel3Df */
+ store_texel_rgb332 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_a8 = {
+ MESA_FORMAT_A8, /* MesaFormat */
+ GL_ALPHA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_a8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_a8, /* FetchTexel1Df */
+ fetch_texel_2d_f_a8, /* FetchTexel2Df */
+ fetch_texel_3d_f_a8, /* FetchTexel3Df */
+ store_texel_a8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_l8 = {
+ MESA_FORMAT_L8, /* MesaFormat */
+ GL_LUMINANCE, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 8, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_l8, /* FetchTexel1Df */
+ fetch_texel_2d_f_l8, /* FetchTexel2Df */
+ fetch_texel_3d_f_l8, /* FetchTexel3Df */
+ store_texel_l8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_i8 = {
+ MESA_FORMAT_I8, /* MesaFormat */
+ GL_INTENSITY, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 8, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_i8, /* FetchTexel1Df */
+ fetch_texel_2d_f_i8, /* FetchTexel2Df */
+ fetch_texel_3d_f_i8, /* FetchTexel3Df */
+ store_texel_i8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_ci8 = {
+ MESA_FORMAT_CI8, /* MesaFormat */
+ GL_COLOR_INDEX, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 8, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 1, /* TexelBytes */
+ _mesa_texstore_ci8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ci8, /* FetchTexel1Df */
+ fetch_texel_2d_f_ci8, /* FetchTexel2Df */
+ fetch_texel_3d_f_ci8, /* FetchTexel3Df */
+ store_texel_ci8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_ycbcr = {
+ MESA_FORMAT_YCBCR, /* MesaFormat */
+ GL_YCBCR_MESA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_ycbcr, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ycbcr, /* FetchTexel1Df */
+ fetch_texel_2d_f_ycbcr, /* FetchTexel2Df */
+ fetch_texel_3d_f_ycbcr, /* FetchTexel3Df */
+ store_texel_ycbcr /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_ycbcr_rev = {
+ MESA_FORMAT_YCBCR_REV, /* MesaFormat */
+ GL_YCBCR_MESA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_ycbcr, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_ycbcr_rev, /* FetchTexel1Df */
+ fetch_texel_2d_f_ycbcr_rev, /* FetchTexel2Df */
+ fetch_texel_3d_f_ycbcr_rev, /* FetchTexel3Df */
+ store_texel_ycbcr_rev /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_z24_s8 = {
+ MESA_FORMAT_Z24_S8, /* MesaFormat */
+ GL_DEPTH_STENCIL_EXT, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 24, /* DepthBits */
+ 8, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_z24_s8, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_z24_s8, /* FetchTexel1Df */
+ fetch_texel_2d_f_z24_s8, /* FetchTexel2Df */
+ fetch_texel_3d_f_z24_s8, /* FetchTexel3Df */
+ store_texel_z24_s8 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_s8_z24 = {
+ MESA_FORMAT_S8_Z24, /* MesaFormat */
+ GL_DEPTH_STENCIL_EXT, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 24, /* DepthBits */
+ 8, /* StencilBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_s8_z24, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel2D */
+ NULL, /* FetchTexel3D */
+ fetch_texel_1d_f_s8_z24, /* FetchTexel1Df */
+ fetch_texel_2d_f_s8_z24, /* FetchTexel2Df */
+ fetch_texel_3d_f_s8_z24, /* FetchTexel3Df */
+ store_texel_s8_z24 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_z16 = {
+ MESA_FORMAT_Z16, /* MesaFormat */
+ GL_DEPTH_COMPONENT, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ sizeof(GLushort) * 8, /* DepthBits */
+ 0, /* StencilBits */
+ sizeof(GLushort), /* TexelBytes */
+ _mesa_texstore_z16, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_z16, /* FetchTexel1Df */
+ fetch_texel_2d_f_z16, /* FetchTexel2Df */
+ fetch_texel_3d_f_z16, /* FetchTexel3Df */
+ store_texel_z16 /* StoreTexel */
+};
+
+const struct gl_texture_format _mesa_texformat_z32 = {
+ MESA_FORMAT_Z32, /* MesaFormat */
+ GL_DEPTH_COMPONENT, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ sizeof(GLuint) * 8, /* DepthBits */
+ 0, /* StencilBits */
+ sizeof(GLuint), /* TexelBytes */
+ _mesa_texstore_z32, /* StoreTexImageFunc */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ NULL, /* FetchTexel1D */
+ fetch_texel_1d_f_z32, /* FetchTexel1Df */
+ fetch_texel_2d_f_z32, /* FetchTexel2Df */
+ fetch_texel_3d_f_z32, /* FetchTexel3Df */
+ store_texel_z32 /* StoreTexel */
+};
+
+/*@}*/
+
+
+/***************************************************************/
+/** \name Null format (useful for proxy textures) */
+/*@{*/
+
+const struct gl_texture_format _mesa_null_texformat = {
+ -1, /* MesaFormat */
+ 0, /* BaseFormat */
+ GL_NONE, /* DataType */
+ 0, /* RedBits */
+ 0, /* GreenBits */
+ 0, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 0, /* TexelBytes */
+ NULL, /* StoreTexImageFunc */
+ fetch_null_texel, /* FetchTexel1D */
+ fetch_null_texel, /* FetchTexel2D */
+ fetch_null_texel, /* FetchTexel3D */
+ fetch_null_texelf, /* FetchTexel1Df */
+ fetch_null_texelf, /* FetchTexel2Df */
+ fetch_null_texelf, /* FetchTexel3Df */
+ store_null_texel /* StoreTexel */
+};
+
+/*@}*/
+
+
+/**
+ * Choose an appropriate texture format given the format, type and
+ * internalFormat parameters passed to glTexImage().
+ *
+ * \param ctx the GL context.
+ * \param internalFormat user's prefered internal texture format.
+ * \param format incoming image pixel format.
+ * \param type incoming image data type.
+ *
+ * \return a pointer to a gl_texture_format object which describes the
+ * choosen texture format, or NULL on failure.
+ *
+ * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers
+ * will typically override this function with a specialized version.
+ */
+const struct gl_texture_format *
+_mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ (void) format;
+ (void) type;
+
+ switch (internalFormat) {
+ /* RGBA formats */
+ case 4:
+ case GL_RGBA:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_rgba;
+ case GL_RGBA8:
+ return &_mesa_texformat_rgba8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444_rev; /* just to test another format*/
+ case GL_RGBA4:
+ return &_mesa_texformat_argb4444;
+
+ /* RGB formats */
+ case 3:
+ case GL_RGB:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb;
+ case GL_RGB8:
+ return &_mesa_texformat_rgb888;
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332;
+ case GL_RGB4:
+ return &_mesa_texformat_rgb565_rev; /* just to test another format */
+ case GL_RGB5:
+ return &_mesa_texformat_rgb565;
+
+ /* Alpha formats */
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_alpha;
+ case GL_ALPHA8:
+ return &_mesa_texformat_a8;
+
+ /* Luminance formats */
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_luminance;
+ case GL_LUMINANCE8:
+ return &_mesa_texformat_l8;
+
+ /* Luminance/Alpha formats */
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_luminance_alpha;
+ case GL_LUMINANCE8_ALPHA8:
+ return &_mesa_texformat_al88;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_intensity;
+ case GL_INTENSITY8:
+ return &_mesa_texformat_i8;
+
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ return &_mesa_texformat_ci8;
+
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.ARB_depth_texture) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return &_mesa_texformat_z32;
+ case GL_DEPTH_COMPONENT16:
+ return &_mesa_texformat_z16;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA_ARB:
+ return &_mesa_texformat_alpha;
+ case GL_COMPRESSED_LUMINANCE_ARB:
+ return &_mesa_texformat_luminance;
+ case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
+ return &_mesa_texformat_luminance_alpha;
+ case GL_COMPRESSED_INTENSITY_ARB:
+ return &_mesa_texformat_intensity;
+ case GL_COMPRESSED_RGB_ARB:
+#if FEATURE_texture_fxt1
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ return &_mesa_texformat_rgb_fxt1;
+#endif
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ return &_mesa_texformat_rgb_dxt1;
+#endif
+ return &_mesa_texformat_rgb;
+ case GL_COMPRESSED_RGBA_ARB:
+#if FEATURE_texture_fxt1
+ if (ctx->Extensions.TDFX_texture_compression_FXT1)
+ return &_mesa_texformat_rgba_fxt1;
+#endif
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc ||
+ ctx->Extensions.S3_s3tc)
+ return &_mesa_texformat_rgba_dxt3; /* Not rgba_dxt1, see spec */
+#endif
+ return &_mesa_texformat_rgba;
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.MESA_ycbcr_texture) {
+ if (internalFormat == GL_YCBCR_MESA) {
+ if (type == GL_UNSIGNED_SHORT_8_8_MESA)
+ return &_mesa_texformat_ycbcr;
+ else
+ return &_mesa_texformat_ycbcr_rev;
+ }
+ }
+
+#if FEATURE_texture_fxt1
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return &_mesa_texformat_rgb_fxt1;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return &_mesa_texformat_rgba_fxt1;
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif
+
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgb_dxt1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgba_dxt1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return &_mesa_texformat_rgba_dxt3;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return &_mesa_texformat_rgba_dxt5;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.S3_s3tc) {
+ switch (internalFormat) {
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ return &_mesa_texformat_rgb_dxt1;
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ return &_mesa_texformat_rgba_dxt3;
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif
+
+ if (ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_ALPHA16F_ARB:
+ return &_mesa_texformat_alpha_float16;
+ case GL_ALPHA32F_ARB:
+ return &_mesa_texformat_alpha_float32;
+ case GL_LUMINANCE16F_ARB:
+ return &_mesa_texformat_luminance_float16;
+ case GL_LUMINANCE32F_ARB:
+ return &_mesa_texformat_luminance_float32;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ return &_mesa_texformat_luminance_alpha_float16;
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return &_mesa_texformat_luminance_alpha_float32;
+ case GL_INTENSITY16F_ARB:
+ return &_mesa_texformat_intensity_float16;
+ case GL_INTENSITY32F_ARB:
+ return &_mesa_texformat_intensity_float32;
+ case GL_RGB16F_ARB:
+ return &_mesa_texformat_rgb_float16;
+ case GL_RGB32F_ARB:
+ return &_mesa_texformat_rgb_float32;
+ case GL_RGBA16F_ARB:
+ return &_mesa_texformat_rgba_float16;
+ case GL_RGBA32F_ARB:
+ return &_mesa_texformat_rgba_float32;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ switch (internalFormat) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return &_mesa_texformat_z24_s8;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return &_mesa_texformat_dudv8;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return &_mesa_texformat_signed_rgba8888;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+
+#if FEATURE_EXT_texture_sRGB
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ switch (internalFormat) {
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ return &_mesa_texformat_srgb8;
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ return &_mesa_texformat_srgba8;
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ return &_mesa_texformat_sl8;
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ return &_mesa_texformat_sla8;
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ return &_mesa_texformat_sl8;
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ return &_mesa_texformat_sla8;
+ case GL_COMPRESSED_SRGB_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+#endif
+ return &_mesa_texformat_srgb8;
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+#if FEATURE_texture_s3tc
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3; /* Not srgba_dxt1, see spec */
+#endif
+ return &_mesa_texformat_srgba8;
+#if FEATURE_texture_s3tc
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgb_dxt1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt1;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt3;
+ break;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ if (ctx->Extensions.EXT_texture_compression_s3tc)
+ return &_mesa_texformat_srgba_dxt5;
+ break;
+#endif
+ default:
+ ; /* fallthrough */
+ }
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+
+ _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()");
+ return NULL;
+}
+
+
+
+/**
+ * Return datatype and number of components per texel for the
+ * given gl_texture_format.
+ */
+void
+_mesa_format_to_type_and_comps(const struct gl_texture_format *format,
+ GLenum *datatype, GLuint *comps)
+{
+ switch (format->MesaFormat) {
+ case MESA_FORMAT_RGBA8888:
+ case MESA_FORMAT_RGBA8888_REV:
+ case MESA_FORMAT_ARGB8888:
+ case MESA_FORMAT_ARGB8888_REV:
+ *datatype = CHAN_TYPE;
+ *comps = 4;
+ return;
+ case MESA_FORMAT_RGB888:
+ case MESA_FORMAT_BGR888:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 3;
+ return;
+ case MESA_FORMAT_RGB565:
+ case MESA_FORMAT_RGB565_REV:
+ *datatype = GL_UNSIGNED_SHORT_5_6_5;
+ *comps = 3;
+ return;
+
+ case MESA_FORMAT_ARGB4444:
+ case MESA_FORMAT_ARGB4444_REV:
+ *datatype = GL_UNSIGNED_SHORT_4_4_4_4;
+ *comps = 4;
+ return;
+
+ case MESA_FORMAT_ARGB1555:
+ case MESA_FORMAT_ARGB1555_REV:
+ *datatype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ *comps = 4;
+ return;
+
+ case MESA_FORMAT_AL88:
+ case MESA_FORMAT_AL88_REV:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 2;
+ return;
+ case MESA_FORMAT_RGB332:
+ *datatype = GL_UNSIGNED_BYTE_3_3_2;
+ *comps = 3;
+ return;
+
+ case MESA_FORMAT_A8:
+ case MESA_FORMAT_L8:
+ case MESA_FORMAT_I8:
+ case MESA_FORMAT_CI8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 1;
+ return;
+
+ case MESA_FORMAT_YCBCR:
+ case MESA_FORMAT_YCBCR_REV:
+ *datatype = GL_UNSIGNED_SHORT;
+ *comps = 2;
+ return;
+
+ case MESA_FORMAT_Z24_S8:
+ *datatype = GL_UNSIGNED_INT;
+ *comps = 1; /* XXX OK? */
+ return;
+
+ case MESA_FORMAT_S8_Z24:
+ *datatype = GL_UNSIGNED_INT;
+ *comps = 1; /* XXX OK? */
+ return;
+
+ case MESA_FORMAT_Z16:
+ *datatype = GL_UNSIGNED_SHORT;
+ *comps = 1;
+ return;
+
+ case MESA_FORMAT_Z32:
+ *datatype = GL_UNSIGNED_INT;
+ *comps = 1;
+ return;
+
+ case MESA_FORMAT_DUDV8:
+ *datatype = GL_BYTE;
+ *comps = 2;
+ return;
+
+ case MESA_FORMAT_SIGNED_RGBA8888:
+ case MESA_FORMAT_SIGNED_RGBA8888_REV:
+ *datatype = GL_BYTE;
+ *comps = 4;
+ return;
+
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 3;
+ return;
+ case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 4;
+ return;
+ case MESA_FORMAT_SL8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 1;
+ return;
+ case MESA_FORMAT_SLA8:
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 2;
+ return;
+#endif
+
+#if FEATURE_texture_fxt1
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+#endif
+#if FEATURE_texture_s3tc
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ case MESA_FORMAT_RGBA_DXT3:
+ case MESA_FORMAT_RGBA_DXT5:
+#if FEATURE_EXT_texture_sRGB
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+#endif
+ /* XXX generate error instead? */
+ *datatype = GL_UNSIGNED_BYTE;
+ *comps = 0;
+ return;
+#endif
+
+ case MESA_FORMAT_RGBA:
+ *datatype = CHAN_TYPE;
+ *comps = 4;
+ return;
+ case MESA_FORMAT_RGB:
+ *datatype = CHAN_TYPE;
+ *comps = 3;
+ return;
+ case MESA_FORMAT_LUMINANCE_ALPHA:
+ *datatype = CHAN_TYPE;
+ *comps = 2;
+ return;
+ case MESA_FORMAT_ALPHA:
+ case MESA_FORMAT_LUMINANCE:
+ case MESA_FORMAT_INTENSITY:
+ *datatype = CHAN_TYPE;
+ *comps = 1;
+ return;
+
+ case MESA_FORMAT_RGBA_FLOAT32:
+ *datatype = GL_FLOAT;
+ *comps = 4;
+ return;
+ case MESA_FORMAT_RGBA_FLOAT16:
+ *datatype = GL_HALF_FLOAT_ARB;
+ *comps = 4;
+ return;
+ case MESA_FORMAT_RGB_FLOAT32:
+ *datatype = GL_FLOAT;
+ *comps = 3;
+ return;
+ case MESA_FORMAT_RGB_FLOAT16:
+ *datatype = GL_HALF_FLOAT_ARB;
+ *comps = 3;
+ return;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
+ *datatype = GL_FLOAT;
+ *comps = 2;
+ return;
+ case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
+ *datatype = GL_HALF_FLOAT_ARB;
+ *comps = 2;
+ return;
+ case MESA_FORMAT_ALPHA_FLOAT32:
+ case MESA_FORMAT_LUMINANCE_FLOAT32:
+ case MESA_FORMAT_INTENSITY_FLOAT32:
+ *datatype = GL_FLOAT;
+ *comps = 1;
+ return;
+ case MESA_FORMAT_ALPHA_FLOAT16:
+ case MESA_FORMAT_LUMINANCE_FLOAT16:
+ case MESA_FORMAT_INTENSITY_FLOAT16:
+ *datatype = GL_HALF_FLOAT_ARB;
+ *comps = 1;
+ return;
+
+ default:
+ _mesa_problem(NULL, "bad format in _mesa_format_to_type_and_comps");
+ *datatype = 0;
+ *comps = 1;
+ }
+}
diff --git a/mesalib/src/mesa/main/texformat.h b/mesalib/src/mesa/main/texformat.h
new file mode 100644
index 000000000..5aa1d756c
--- /dev/null
+++ b/mesalib/src/mesa/main/texformat.h
@@ -0,0 +1,293 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texformat.h
+ * Texture formats definitions.
+ *
+ * \author Gareth Hughes
+ */
+
+
+#ifndef TEXFORMAT_H
+#define TEXFORMAT_H
+
+
+#include "mtypes.h"
+
+
+/**
+ * Mesa internal texture image formats.
+ * All texture images are stored in one of these formats.
+ *
+ * NOTE: when you add a new format, be sure to update the do_row()
+ * function in texstore.c used for auto mipmap generation.
+ */
+enum _format {
+ /**
+ * \name Hardware-friendly formats.
+ *
+ * Drivers can override the default formats and convert texture images to
+ * one of these as required. The driver's
+ * dd_function_table::ChooseTextureFormat function will choose one of these
+ * formats.
+ *
+ * \note In the default case, some of these formats will be duplicates of
+ * the generic formats listed below. However, these formats guarantee their
+ * internal component sizes, while GLchan may vary between GLubyte, GLushort
+ * and GLfloat.
+ */
+ /*@{*/
+ /* msb <------ TEXEL BITS -----------> lsb */
+ /* ---- ---- ---- ---- ---- ---- ---- ---- */
+ MESA_FORMAT_RGBA8888, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */
+ MESA_FORMAT_RGBA8888_REV, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */
+ MESA_FORMAT_ARGB8888, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */
+ MESA_FORMAT_ARGB8888_REV, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */
+ MESA_FORMAT_RGB888, /* RRRR RRRR GGGG GGGG BBBB BBBB */
+ MESA_FORMAT_BGR888, /* BBBB BBBB GGGG GGGG RRRR RRRR */
+ MESA_FORMAT_RGB565, /* RRRR RGGG GGGB BBBB */
+ MESA_FORMAT_RGB565_REV, /* GGGB BBBB RRRR RGGG */
+ MESA_FORMAT_RGBA4444, /* RRRR GGGG BBBB AAAA */
+ MESA_FORMAT_ARGB4444, /* AAAA RRRR GGGG BBBB */
+ MESA_FORMAT_ARGB4444_REV, /* GGGG BBBB AAAA RRRR */
+ MESA_FORMAT_RGBA5551, /* RRRR RGGG GGBB BBBA */
+ MESA_FORMAT_ARGB1555, /* ARRR RRGG GGGB BBBB */
+ MESA_FORMAT_ARGB1555_REV, /* GGGB BBBB ARRR RRGG */
+ MESA_FORMAT_AL88, /* AAAA AAAA LLLL LLLL */
+ MESA_FORMAT_AL88_REV, /* LLLL LLLL AAAA AAAA */
+ MESA_FORMAT_RGB332, /* RRRG GGBB */
+ MESA_FORMAT_A8, /* AAAA AAAA */
+ MESA_FORMAT_L8, /* LLLL LLLL */
+ MESA_FORMAT_I8, /* IIII IIII */
+ MESA_FORMAT_CI8, /* CCCC CCCC */
+ MESA_FORMAT_YCBCR, /* YYYY YYYY UorV UorV */
+ MESA_FORMAT_YCBCR_REV, /* UorV UorV YYYY YYYY */
+ MESA_FORMAT_Z24_S8, /* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ SSSS SSSS */
+ MESA_FORMAT_S8_Z24, /* SSSS SSSS ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */
+ MESA_FORMAT_Z16, /* ZZZZ ZZZZ ZZZZ ZZZZ */
+ MESA_FORMAT_Z32, /* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */
+ /*@}*/
+
+#if FEATURE_EXT_texture_sRGB
+ /**
+ * \name 8-bit/channel sRGB formats
+ */
+ /*@{*/
+ MESA_FORMAT_SRGB8,
+ MESA_FORMAT_SRGBA8,
+ MESA_FORMAT_SARGB8,
+ MESA_FORMAT_SL8,
+ MESA_FORMAT_SLA8,
+#if FEATURE_texture_s3tc
+ MESA_FORMAT_SRGB_DXT1,
+ MESA_FORMAT_SRGBA_DXT1,
+ MESA_FORMAT_SRGBA_DXT3,
+ MESA_FORMAT_SRGBA_DXT5,
+#endif
+ /*@}*/
+#endif
+
+ /**
+ * \name Compressed texture formats.
+ */
+ /*@{*/
+#if FEATURE_texture_fxt1
+ MESA_FORMAT_RGB_FXT1,
+ MESA_FORMAT_RGBA_FXT1,
+#endif
+#if FEATURE_texture_s3tc
+ MESA_FORMAT_RGB_DXT1,
+ MESA_FORMAT_RGBA_DXT1,
+ MESA_FORMAT_RGBA_DXT3,
+ MESA_FORMAT_RGBA_DXT5,
+#endif
+ /*@}*/
+
+ /**
+ * \name Generic GLchan-based formats.
+ *
+ * Software-oriented texture formats. Texels are arrays of GLchan
+ * values so there are no byte order issues.
+ *
+ * \note Because these are based on the GLchan data type, one cannot assume
+ * 8 bits per channel with these formats. If you require GLubyte channels,
+ * use one of the hardware formats above.
+ */
+ /*@{*/
+ MESA_FORMAT_RGBA,
+ MESA_FORMAT_RGB,
+ MESA_FORMAT_ALPHA,
+ MESA_FORMAT_LUMINANCE,
+ MESA_FORMAT_LUMINANCE_ALPHA,
+ MESA_FORMAT_INTENSITY,
+ /*@}*/
+
+ /**
+ * \name Floating point texture formats.
+ */
+ /*@{*/
+ MESA_FORMAT_RGBA_FLOAT32,
+ MESA_FORMAT_RGBA_FLOAT16,
+ MESA_FORMAT_RGB_FLOAT32,
+ MESA_FORMAT_RGB_FLOAT16,
+ MESA_FORMAT_ALPHA_FLOAT32,
+ MESA_FORMAT_ALPHA_FLOAT16,
+ MESA_FORMAT_LUMINANCE_FLOAT32,
+ MESA_FORMAT_LUMINANCE_FLOAT16,
+ MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
+ MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
+ MESA_FORMAT_INTENSITY_FLOAT32,
+ MESA_FORMAT_INTENSITY_FLOAT16,
+ /*@}*/
+
+ /**
+ * \name Signed fixed point texture formats.
+ */
+ /*@{*/
+ MESA_FORMAT_DUDV8,
+ MESA_FORMAT_SIGNED_RGBA8888,
+ MESA_FORMAT_SIGNED_RGBA8888_REV
+ /*@}*/
+};
+
+
+/** GLchan-valued formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_rgba;
+extern const struct gl_texture_format _mesa_texformat_rgb;
+extern const struct gl_texture_format _mesa_texformat_alpha;
+extern const struct gl_texture_format _mesa_texformat_luminance;
+extern const struct gl_texture_format _mesa_texformat_luminance_alpha;
+extern const struct gl_texture_format _mesa_texformat_intensity;
+/*@}*/
+
+#if FEATURE_EXT_texture_sRGB
+/** sRGB (nonlinear) formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_srgb8;
+extern const struct gl_texture_format _mesa_texformat_srgba8;
+extern const struct gl_texture_format _mesa_texformat_sargb8;
+extern const struct gl_texture_format _mesa_texformat_sl8;
+extern const struct gl_texture_format _mesa_texformat_sla8;
+#if FEATURE_texture_s3tc
+extern const struct gl_texture_format _mesa_texformat_srgb_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt1;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt3;
+extern const struct gl_texture_format _mesa_texformat_srgba_dxt5;
+#endif
+/*@}*/
+#endif
+
+/** Floating point texture formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_rgba_float32;
+extern const struct gl_texture_format _mesa_texformat_rgba_float16;
+extern const struct gl_texture_format _mesa_texformat_rgb_float32;
+extern const struct gl_texture_format _mesa_texformat_rgb_float16;
+extern const struct gl_texture_format _mesa_texformat_alpha_float32;
+extern const struct gl_texture_format _mesa_texformat_alpha_float16;
+extern const struct gl_texture_format _mesa_texformat_luminance_float32;
+extern const struct gl_texture_format _mesa_texformat_luminance_float16;
+extern const struct gl_texture_format _mesa_texformat_luminance_alpha_float32;
+extern const struct gl_texture_format _mesa_texformat_luminance_alpha_float16;
+extern const struct gl_texture_format _mesa_texformat_intensity_float32;
+extern const struct gl_texture_format _mesa_texformat_intensity_float16;
+/*@}*/
+
+/** Signed fixed point texture formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_dudv8;
+extern const struct gl_texture_format _mesa_texformat_signed_rgba8888;
+extern const struct gl_texture_format _mesa_texformat_signed_rgba8888_rev;
+/*@}*/
+
+/** \name Assorted hardware-friendly formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_rgba8888;
+extern const struct gl_texture_format _mesa_texformat_rgba8888_rev;
+extern const struct gl_texture_format _mesa_texformat_argb8888;
+extern const struct gl_texture_format _mesa_texformat_argb8888_rev;
+extern const struct gl_texture_format _mesa_texformat_rgb888;
+extern const struct gl_texture_format _mesa_texformat_bgr888;
+extern const struct gl_texture_format _mesa_texformat_rgb565;
+extern const struct gl_texture_format _mesa_texformat_rgb565_rev;
+extern const struct gl_texture_format _mesa_texformat_rgba4444;
+extern const struct gl_texture_format _mesa_texformat_argb4444;
+extern const struct gl_texture_format _mesa_texformat_argb4444_rev;
+extern const struct gl_texture_format _mesa_texformat_argb1555;
+extern const struct gl_texture_format _mesa_texformat_argb1555_rev;
+extern const struct gl_texture_format _mesa_texformat_rgba5551;
+extern const struct gl_texture_format _mesa_texformat_al88;
+extern const struct gl_texture_format _mesa_texformat_al88_rev;
+extern const struct gl_texture_format _mesa_texformat_rgb332;
+extern const struct gl_texture_format _mesa_texformat_a8;
+extern const struct gl_texture_format _mesa_texformat_l8;
+extern const struct gl_texture_format _mesa_texformat_i8;
+extern const struct gl_texture_format _mesa_texformat_ci8;
+extern const struct gl_texture_format _mesa_texformat_z24_s8;
+extern const struct gl_texture_format _mesa_texformat_s8_z24;
+extern const struct gl_texture_format _mesa_texformat_z16;
+extern const struct gl_texture_format _mesa_texformat_z32;
+/*@}*/
+
+/** \name YCbCr formats */
+/*@{*/
+extern const struct gl_texture_format _mesa_texformat_ycbcr;
+extern const struct gl_texture_format _mesa_texformat_ycbcr_rev;
+/*@}*/
+
+/** \name Compressed formats */
+/*@{*/
+#if FEATURE_texture_fxt1
+extern const struct gl_texture_format _mesa_texformat_rgb_fxt1;
+extern const struct gl_texture_format _mesa_texformat_rgba_fxt1;
+#endif
+#if FEATURE_texture_s3tc
+extern const struct gl_texture_format _mesa_texformat_rgb_dxt1;
+extern const struct gl_texture_format _mesa_texformat_rgba_dxt1;
+extern const struct gl_texture_format _mesa_texformat_rgba_dxt3;
+extern const struct gl_texture_format _mesa_texformat_rgba_dxt5;
+#endif
+/*@}*/
+
+/** \name The null format */
+/*@{*/
+extern const struct gl_texture_format _mesa_null_texformat;
+/*@}*/
+
+
+extern const struct gl_texture_format *
+_mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type );
+
+
+extern void
+_mesa_format_to_type_and_comps(const struct gl_texture_format *format,
+ GLenum *datatype, GLuint *comps);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/texformat_tmp.h b/mesalib/src/mesa/main/texformat_tmp.h
new file mode 100644
index 000000000..eb160deff
--- /dev/null
+++ b/mesalib/src/mesa/main/texformat_tmp.h
@@ -0,0 +1,1474 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texformat_tmp.h
+ * Texel fetch functions template.
+ *
+ * This template file is used by texformat.c to generate texel fetch functions
+ * for 1-D, 2-D and 3-D texture images.
+ *
+ * It should be expanded by defining \p DIM as the number texture dimensions
+ * (1, 2 or 3). According to the value of \p DIM a series of macros is defined
+ * for the texel lookup in the gl_texture_image::Data.
+ *
+ * \sa texformat.c and FetchTexel.
+ *
+ * \author Gareth Hughes
+ * \author Brian Paul
+ */
+
+
+#if DIM == 1
+
+#define TEXEL_ADDR( type, image, i, j, k, size ) \
+ ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size)))
+
+#define FETCH(x) fetch_texel_1d_##x
+
+#elif DIM == 2
+
+#define TEXEL_ADDR( type, image, i, j, k, size ) \
+ ((void) (k), \
+ ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size)))
+
+#define FETCH(x) fetch_texel_2d_##x
+
+#elif DIM == 3
+
+#define TEXEL_ADDR( type, image, i, j, k, size ) \
+ ((type *)(image)->Data + ((image)->ImageOffsets[k] \
+ + (image)->RowStride * (j) + (i)) * (size))
+
+#define FETCH(x) fetch_texel_3d_##x
+
+#else
+#error illegal number of texture dimensions
+#endif
+
+
+/* MESA_FORMAT_RGBA **********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGBA texture, returning 4 GLfloats */
+static void FETCH(f_rgba)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 4);
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = CHAN_TO_FLOAT(src[3]);
+}
+
+#if DIM == 3
+/* Store a GLchan RGBA texel */
+static void store_texel_rgba(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 4);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[GCOMP];
+ dst[2] = rgba[BCOMP];
+ dst[3] = rgba[ACOMP];
+}
+#endif
+
+/* MESA_FORMAT_RGB ***********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGB texture, returning 4 GLfloats */
+static void FETCH(f_rgb)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 3);
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 3);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[GCOMP];
+ dst[2] = rgba[BCOMP];
+}
+#endif
+
+/* MESA_FORMAT_ALPHA *********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D ALPHA texture, returning 4 GLchans */
+static void FETCH(f_alpha)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = CHAN_TO_FLOAT(src[0]);
+}
+
+#if DIM == 3
+static void store_texel_alpha(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ dst[0] = rgba[ACOMP];
+}
+#endif
+
+/* MESA_FORMAT_LUMINANCE *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D LUMIN texture, returning 4 GLchans */
+static void FETCH(f_luminance)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_luminance(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+/* MESA_FORMAT_LUMINANCE_ALPHA ***********************************************/
+
+/* Fetch texel from 1D, 2D or 3D L_A texture, returning 4 GLchans */
+static void FETCH(f_luminance_alpha)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel)
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 2);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[ACOMP] = CHAN_TO_FLOAT(src[1]);
+}
+
+#if DIM == 3
+static void store_texel_luminance_alpha(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 2);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[ACOMP];
+}
+#endif
+
+/* MESA_FORMAT_INTENSITY *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D INT. texture, returning 4 GLchans */
+static void FETCH(f_intensity)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = CHAN_TO_FLOAT(src[0]);
+}
+
+#if DIM == 3
+static void store_texel_intensity(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLchan *rgba = (const GLchan *) texel;
+ GLchan *dst = TEXEL_ADDR(GLchan, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_Z32 ***********************************************************/
+
+/* Fetch depth texel from 1D, 2D or 3D 32-bit depth texture,
+ * returning 1 GLfloat.
+ * Note: no GLchan version of this function.
+ */
+static void FETCH(f_z32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[0] = src[0] * (1.0F / 0xffffffff);
+}
+
+#if DIM == 3
+static void store_texel_z32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLuint *depth = (const GLuint *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ dst[0] = *depth;
+}
+#endif
+
+
+/* MESA_FORMAT_Z16 ***********************************************************/
+
+/* Fetch depth texel from 1D, 2D or 3D 16-bit depth texture,
+ * returning 1 GLfloat.
+ * Note: no GLchan version of this function.
+ */
+static void FETCH(f_z16)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ texel[0] = src[0] * (1.0F / 65535.0F);
+}
+
+#if DIM == 3
+static void store_texel_z16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLushort *depth = (const GLushort *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ dst[0] = *depth;
+}
+#endif
+
+
+/* MESA_FORMAT_RGBA_F32 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats.
+ */
+static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4);
+ texel[RCOMP] = src[0];
+ texel[GCOMP] = src[1];
+ texel[BCOMP] = src[2];
+ texel[ACOMP] = src[3];
+}
+
+#if DIM == 3
+static void store_texel_rgba_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *depth = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = depth[RCOMP];
+ dst[1] = depth[GCOMP];
+ dst[2] = depth[BCOMP];
+ dst[3] = depth[ACOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_RGBA_F16 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4);
+ texel[RCOMP] = _mesa_half_to_float(src[0]);
+ texel[GCOMP] = _mesa_half_to_float(src[1]);
+ texel[BCOMP] = _mesa_half_to_float(src[2]);
+ texel[ACOMP] = _mesa_half_to_float(src[3]);
+}
+
+#if DIM == 3
+static void store_texel_rgba_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *depth = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(*depth);
+}
+#endif
+
+/* MESA_FORMAT_RGB_F32 *******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3);
+ texel[RCOMP] = src[0];
+ texel[GCOMP] = src[1];
+ texel[BCOMP] = src[2];
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *depth = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = *depth;
+}
+#endif
+
+
+/* MESA_FORMAT_RGB_F16 *******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3);
+ texel[RCOMP] = _mesa_half_to_float(src[0]);
+ texel[GCOMP] = _mesa_half_to_float(src[1]);
+ texel[BCOMP] = _mesa_half_to_float(src[2]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *depth = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(*depth);
+}
+#endif
+
+
+/* MESA_FORMAT_ALPHA_F32 *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = src[0];
+}
+
+#if DIM == 3
+static void store_texel_alpha_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = rgba[ACOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_ALPHA_F32 *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = _mesa_half_to_float(src[0]);
+}
+
+#if DIM == 3
+static void store_texel_alpha_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_LUMINANCE_F32 *************************************************/
+
+/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = src[0];
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_luminance_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_LUMINANCE_F16 *************************************************/
+
+/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = _mesa_half_to_float(src[0]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_luminance_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(rgba[RCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/
+
+/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = src[0];
+ texel[ACOMP] = src[1];
+}
+
+#if DIM == 3
+static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[ACOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/
+
+/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = _mesa_half_to_float(src[0]);
+ texel[ACOMP] = _mesa_half_to_float(src[1]);
+}
+
+#if DIM == 3
+static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2);
+ dst[0] = _mesa_float_to_half(rgba[RCOMP]);
+ dst[1] = _mesa_float_to_half(rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_INTENSITY_F32 *************************************************/
+
+/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = src[0];
+}
+
+#if DIM == 3
+static void store_texel_intensity_f32(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_INTENSITY_F16 *************************************************/
+
+/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture,
+ * returning 4 GLfloats.
+ */
+static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = _mesa_half_to_float(src[0]);
+}
+
+#if DIM == 3
+static void store_texel_intensity_f16(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLfloat *rgba = (const GLfloat *) texel;
+ GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1);
+ dst[0] = _mesa_float_to_half(rgba[RCOMP]);
+}
+#endif
+
+
+
+
+/*
+ * Begin Hardware formats
+ */
+
+/* MESA_FORMAT_RGBA8888 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */
+static void FETCH(f_rgba8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+}
+
+
+
+#if DIM == 3
+static void store_texel_rgba8888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_RGBA888_REV ***************************************************/
+
+/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */
+static void FETCH(f_rgba8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+}
+
+#if DIM == 3
+static void store_texel_rgba8888_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_ARGB8888 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */
+static void FETCH(f_argb8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+}
+
+#if DIM == 3
+static void store_texel_argb8888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_ARGB8888_REV **************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */
+static void FETCH(f_argb8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff );
+ texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff );
+ texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff );
+}
+
+#if DIM == 3
+static void store_texel_argb8888_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_RGB888 ********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */
+static void FETCH(f_rgb888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ texel[RCOMP] = UBYTE_TO_FLOAT( src[2] );
+ texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ dst[0] = rgba[BCOMP];
+ dst[1] = rgba[GCOMP];
+ dst[2] = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_BGR888 ********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */
+static void FETCH(f_bgr888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ texel[RCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[GCOMP] = UBYTE_TO_FLOAT( src[1] );
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[2] );
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_bgr888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[GCOMP];
+ dst[2] = rgba[BCOMP];
+}
+#endif
+
+
+/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding)
+ instead of slow (g << 2) * 255 / 252 (always rounds down) */
+
+/* MESA_FORMAT_RGB565 ********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */
+static void FETCH(f_rgb565)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = *src;
+ texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F);
+ texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb565(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_RGB565_REV ****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */
+static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb565_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]);
+}
+#endif
+
+/* MESA_FORMAT_RGBA4444 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */
+static void FETCH(f_rgba4444)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = *src;
+ texel[RCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
+}
+
+#if DIM == 3
+static void store_texel_rgba4444(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_4444(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_ARGB4444 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */
+static void FETCH(f_argb4444)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = *src;
+ texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
+}
+
+#if DIM == 3
+static void store_texel_argb4444(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_ARGB4444_REV **************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */
+static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F);
+ texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F);
+ texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F);
+ texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F);
+}
+
+#if DIM == 3
+static void store_texel_argb4444_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]);
+}
+#endif
+
+/* MESA_FORMAT_RGBA5551 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
+static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = *src;
+ texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F);
+ texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = ((s ) & 0x01) * 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgba5551(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_5551(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+/* MESA_FORMAT_ARGB1555 ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */
+static void FETCH(f_argb1555)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = *src;
+ texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F);
+ texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F);
+ texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F);
+ texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_argb1555(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_ARGB1555_REV **************************************************/
+
+/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */
+static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) );
+ texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 );
+}
+
+#if DIM == 3
+static void store_texel_argb1555_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_AL88 **********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */
+static void FETCH(f_al88)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 );
+}
+
+#if DIM == 3
+static void store_texel_al88(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_AL88_REV ******************************************************/
+
+/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */
+static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 );
+ texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff );
+}
+
+#if DIM == 3
+static void store_texel_al88_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_RGB332 ********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */
+static void FETCH(f_rgb332)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ const GLubyte s = *src;
+ texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F);
+ texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F);
+ texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_rgb332(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+
+/* MESA_FORMAT_A8 ************************************************************/
+
+/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */
+static void FETCH(f_a8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
+}
+
+#if DIM == 3
+static void store_texel_a8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ *dst = rgba[ACOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_L8 ************************************************************/
+
+/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */
+static void FETCH(f_l8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = UBYTE_TO_FLOAT( src[0] );
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_l8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ *dst = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_I8 ************************************************************/
+
+/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */
+static void FETCH(f_i8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = UBYTE_TO_FLOAT( src[0] );
+}
+
+#if DIM == 3
+static void store_texel_i8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ *dst = rgba[RCOMP];
+}
+#endif
+
+
+/* MESA_FORMAT_CI8 ***********************************************************/
+
+/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a
+ * color table, and return 4 GLchans.
+ */
+static void FETCH(f_ci8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ const struct gl_color_table *palette;
+ GLuint index;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->Texture.SharedPalette) {
+ palette = &ctx->Texture.Palette;
+ }
+ else {
+ palette = &texImage->TexObject->Palette;
+ }
+ if (palette->Size == 0)
+ return; /* undefined results */
+
+ /* Mask the index against size of palette to avoid going out of bounds */
+ index = (*src) & (palette->Size - 1);
+
+ {
+ const GLfloat *table = palette->TableF;
+ switch (palette->_BaseFormat) {
+ case GL_ALPHA:
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = 0.0F;
+ texel[ACOMP] = table[index];
+ break;
+ case GL_LUMINANCE:
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = table[index];
+ texel[ACOMP] = 1.0F;
+ break;
+ case GL_INTENSITY:
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] =
+ texel[ACOMP] = table[index];
+ break;
+ case GL_LUMINANCE_ALPHA:
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = table[index * 2 + 0];
+ texel[ACOMP] = table[index * 2 + 1];
+ break;
+ case GL_RGB:
+ texel[RCOMP] = table[index * 3 + 0];
+ texel[GCOMP] = table[index * 3 + 1];
+ texel[BCOMP] = table[index * 3 + 2];
+ texel[ACOMP] = 1.0F;
+ break;
+ case GL_RGBA:
+ texel[RCOMP] = table[index * 4 + 0];
+ texel[GCOMP] = table[index * 4 + 1];
+ texel[BCOMP] = table[index * 4 + 2];
+ texel[ACOMP] = table[index * 4 + 3];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad palette format in fetch_texel_ci8");
+ return;
+ }
+ }
+}
+
+#if DIM == 3
+static void store_texel_ci8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *index = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ *dst = *index;
+}
+#endif
+
+
+#if FEATURE_EXT_texture_sRGB
+
+/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */
+/* Note: component order is same as for MESA_FORMAT_RGB888 */
+static void FETCH(srgb8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ texel[RCOMP] = nonlinear_to_linear(src[2]);
+ texel[GCOMP] = nonlinear_to_linear(src[1]);
+ texel[BCOMP] = nonlinear_to_linear(src[0]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_srgb8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3);
+ dst[0] = rgba[BCOMP]; /* no conversion */
+ dst[1] = rgba[GCOMP];
+ dst[2] = rgba[RCOMP];
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D srgba8 texture, return 4 GLfloats */
+static void FETCH(srgba8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = nonlinear_to_linear( (s >> 24) );
+ texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
+ texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */
+}
+
+#if DIM == 3
+static void store_texel_srgba8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */
+static void FETCH(sargb8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = nonlinear_to_linear( (s >> 16) & 0xff );
+ texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff );
+ texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff );
+ texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */
+}
+
+#if DIM == 3
+static void store_texel_sargb8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]);
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D sl8 texture, return 4 GLfloats */
+static void FETCH(sl8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = nonlinear_to_linear(src[0]);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_sl8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1);
+ dst[0] = rgba[RCOMP];
+}
+#endif
+
+/* Fetch texel from 1D, 2D or 3D sla8 texture, return 4 GLfloats */
+static void FETCH(sla8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2);
+ texel[RCOMP] =
+ texel[GCOMP] =
+ texel[BCOMP] = nonlinear_to_linear(src[0]);
+ texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */
+}
+
+#if DIM == 3
+static void store_texel_sla8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2);
+ dst[0] = rgba[RCOMP];
+ dst[1] = rgba[ACOMP];
+}
+#endif
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/* MESA_FORMAT_DUDV8 ********************************************************/
+
+/* this format by definition produces 0,0,0,1 as rgba values,
+ however we'll return the dudv values as rg and fix up elsewhere */
+static void FETCH(dudv8)(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2);
+ texel[RCOMP] = BYTE_TO_FLOAT(src[0]);
+ texel[GCOMP] = BYTE_TO_FLOAT(src[1]);
+ texel[BCOMP] = 0;
+ texel[ACOMP] = 0;
+}
+
+/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/
+
+static void FETCH(signed_rgba8888)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = BYTE_TO_FLOAT_TEX( (s >> 24) );
+ texel[GCOMP] = BYTE_TO_FLOAT_TEX( (s >> 16) & 0xff );
+ texel[BCOMP] = BYTE_TO_FLOAT_TEX( (s >> 8) & 0xff );
+ texel[ACOMP] = BYTE_TO_FLOAT_TEX( (s ) & 0xff );
+}
+
+#if DIM == 3
+static void store_texel_signed_rgba8888(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLbyte *rgba = (const GLbyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+static void FETCH(signed_rgba8888_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ texel[RCOMP] = BYTE_TO_FLOAT_TEX( (s ) & 0xff );
+ texel[GCOMP] = BYTE_TO_FLOAT_TEX( (s >> 8) & 0xff );
+ texel[BCOMP] = BYTE_TO_FLOAT_TEX( (s >> 16) & 0xff );
+ texel[ACOMP] = BYTE_TO_FLOAT_TEX( (s >> 24) );
+}
+
+#if DIM == 3
+static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ const GLubyte *rgba = (const GLubyte *) texel;
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
+
+
+/* MESA_FORMAT_YCBCR *********************************************************/
+
+/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats.
+ * We convert YCbCr to RGB here.
+ */
+static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
+ const GLushort *src1 = src0 + 1; /* odd */
+ const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */
+ const GLubyte cb = *src0 & 0xff; /* chroma U */
+ const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */
+ const GLubyte cr = *src1 & 0xff; /* chroma V */
+ const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
+ GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
+ GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
+ GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
+ r *= (1.0F / 255.0F);
+ g *= (1.0F / 255.0F);
+ b *= (1.0F / 255.0F);
+ texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
+ texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
+ texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_ycbcr(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ (void) texImage;
+ (void) i;
+ (void) j;
+ (void) k;
+ (void) texel;
+ /* XXX to do */
+}
+#endif
+
+
+/* MESA_FORMAT_YCBCR_REV *****************************************************/
+
+/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats.
+ * We convert YCbCr to RGB here.
+ */
+static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */
+ const GLushort *src1 = src0 + 1; /* odd */
+ const GLubyte y0 = *src0 & 0xff; /* luminance */
+ const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */
+ const GLubyte y1 = *src1 & 0xff; /* luminance */
+ const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */
+ const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */
+ GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128);
+ GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128);
+ GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128);
+ r *= (1.0F / 255.0F);
+ g *= (1.0F / 255.0F);
+ b *= (1.0F / 255.0F);
+ texel[RCOMP] = CLAMP(r, 0.0F, 1.0F);
+ texel[GCOMP] = CLAMP(g, 0.0F, 1.0F);
+ texel[BCOMP] = CLAMP(b, 0.0F, 1.0F);
+ texel[ACOMP] = 1.0F;
+}
+
+#if DIM == 3
+static void store_texel_ycbcr_rev(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ (void) texImage;
+ (void) i;
+ (void) j;
+ (void) k;
+ (void) texel;
+ /* XXX to do */
+}
+#endif
+
+
+/* MESA_TEXFORMAT_Z24_S8 ***************************************************/
+
+static void FETCH(f_z24_s8)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* only return Z, not stencil data */
+ const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ const GLfloat scale = 1.0F / (GLfloat) 0xffffff;
+ texel[0] = ((*src) >> 8) * scale;
+ ASSERT(texImage->TexFormat->MesaFormat == MESA_FORMAT_Z24_S8);
+ ASSERT(texel[0] >= 0.0F);
+ ASSERT(texel[0] <= 1.0F);
+}
+
+#if DIM == 3
+static void store_texel_z24_s8(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ /* only store Z, not stencil */
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ GLfloat depth = *((GLfloat *) texel);
+ GLuint zi = ((GLuint) (depth * 0xffffff)) << 8;
+ *dst = zi | (*dst & 0xff);
+}
+#endif
+
+
+/* MESA_TEXFORMAT_S8_Z24 ***************************************************/
+
+static void FETCH(f_s8_z24)( const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ /* only return Z, not stencil data */
+ const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ const GLfloat scale = 1.0F / (GLfloat) 0xffffff;
+ texel[0] = ((*src) & 0x00ffffff) * scale;
+ ASSERT(texImage->TexFormat->MesaFormat == MESA_FORMAT_S8_Z24);
+ ASSERT(texel[0] >= 0.0F);
+ ASSERT(texel[0] <= 1.0F);
+}
+
+#if DIM == 3
+static void store_texel_s8_z24(struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, const void *texel)
+{
+ /* only store Z, not stencil */
+ GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+ GLfloat depth = *((GLfloat *) texel);
+ GLuint zi = (GLuint) (depth * 0xffffff);
+ *dst = zi | (*dst & 0xff000000);
+}
+#endif
+
+
+#undef TEXEL_ADDR
+#undef DIM
+#undef FETCH
diff --git a/mesalib/src/mesa/main/texgen.c b/mesalib/src/mesa/main/texgen.c
new file mode 100644
index 000000000..e3feb024c
--- /dev/null
+++ b/mesalib/src/mesa/main/texgen.c
@@ -0,0 +1,339 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file texgen.c
+ *
+ * glTexGen-related functions
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/texgen.h"
+#include "math/m_matrix.h"
+
+
+/**
+ * Return texgen state for given coordinate
+ */
+static struct gl_texgen *
+get_texgen(struct gl_texture_unit *texUnit, GLenum coord)
+{
+ switch (coord) {
+ case GL_S:
+ return &texUnit->GenS;
+ case GL_T:
+ return &texUnit->GenT;
+ case GL_R:
+ return &texUnit->GenR;
+ case GL_Q:
+ return &texUnit->GenQ;
+ default:
+ return NULL;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n",
+ _mesa_lookup_enum_by_nr(coord),
+ _mesa_lookup_enum_by_nr(pname),
+ *params,
+ _mesa_lookup_enum_by_nr((GLenum) (GLint) *params));
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexGen(current unit)");
+ return;
+ }
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexGen(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ {
+ GLenum mode = (GLenum) (GLint) params[0];
+ GLbitfield bit = 0x0;
+ if (texgen->Mode == mode)
+ return;
+ switch (mode) {
+ case GL_OBJECT_LINEAR:
+ bit = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_EYE_LINEAR:
+ bit = TEXGEN_EYE_LINEAR;
+ break;
+ case GL_SPHERE_MAP:
+ if (coord == GL_S || coord == GL_T)
+ bit = TEXGEN_SPHERE_MAP;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ if (coord != GL_Q)
+ bit = TEXGEN_REFLECTION_MAP_NV;
+ break;
+ case GL_NORMAL_MAP_NV:
+ if (coord != GL_Q)
+ bit = TEXGEN_NORMAL_MAP_NV;
+ break;
+ default:
+ ; /* nop */
+ }
+ if (!bit) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texgen->Mode = mode;
+ texgen->_ModeBit = bit;
+ }
+ break;
+
+ case GL_OBJECT_PLANE:
+ {
+ if (TEST_EQ_4V(texgen->ObjectPlane, params))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texgen->ObjectPlane, params);
+ }
+ break;
+
+ case GL_EYE_PLANE:
+ {
+ GLfloat tmp[4];
+ /* Transform plane equation by the inverse modelview matrix */
+ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
+ _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
+ }
+ _mesa_transform_vector(tmp, params,
+ ctx->ModelviewMatrixStack.Top->inv);
+ if (TEST_EQ_4V(texgen->EyePlane, tmp))
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ COPY_4FV(texgen->EyePlane, tmp);
+ }
+ break;
+
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
+ }
+
+ if (ctx->Driver.TexGen)
+ ctx->Driver.TexGen( ctx, coord, pname, params );
+}
+
+
+void GLAPIENTRY
+_mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params )
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) params[0];
+ if (pname == GL_TEXTURE_GEN_MODE) {
+ p[1] = p[2] = p[3] = 0.0F;
+ }
+ else {
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ }
+ _mesa_TexGenfv(coord, pname, p);
+}
+
+
+void GLAPIENTRY
+_mesa_TexGend(GLenum coord, GLenum pname, GLdouble param )
+{
+ GLfloat p = (GLfloat) param;
+ _mesa_TexGenfv( coord, pname, &p );
+}
+
+
+void GLAPIENTRY
+_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params )
+{
+ GLfloat p[4];
+ p[0] = (GLfloat) params[0];
+ if (pname == GL_TEXTURE_GEN_MODE) {
+ p[1] = p[2] = p[3] = 0.0F;
+ }
+ else {
+ p[1] = (GLfloat) params[1];
+ p[2] = (GLfloat) params[2];
+ p[3] = (GLfloat) params[3];
+ }
+ _mesa_TexGenfv( coord, pname, p );
+}
+
+
+void GLAPIENTRY
+_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param )
+{
+ _mesa_TexGenfv(coord, pname, &param);
+}
+
+
+void GLAPIENTRY
+_mesa_TexGeni( GLenum coord, GLenum pname, GLint param )
+{
+ _mesa_TexGeniv( coord, pname, &param );
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGendv(current unit)");
+ return;
+ }
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = ENUM_TO_DOUBLE(texgen->Mode);
+ break;
+ case GL_OBJECT_PLANE:
+ COPY_4V(params, texgen->ObjectPlane);
+ break;
+ case GL_EYE_PLANE:
+ COPY_4V(params, texgen->EyePlane);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGenfv(current unit)");
+ return;
+ }
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = ENUM_TO_FLOAT(texgen->Mode);
+ break;
+ case GL_OBJECT_PLANE:
+ COPY_4V(params, texgen->ObjectPlane);
+ break;
+ case GL_EYE_PLANE:
+ COPY_4V(params, texgen->EyePlane);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
+ }
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texgen *texgen;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexGeniv(current unit)");
+ return;
+ }
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
+ texgen = get_texgen(texUnit, coord);
+ if (!texgen) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_GEN_MODE:
+ params[0] = texgen->Mode;
+ break;
+ case GL_OBJECT_PLANE:
+ params[0] = (GLint) texgen->ObjectPlane[0];
+ params[1] = (GLint) texgen->ObjectPlane[1];
+ params[2] = (GLint) texgen->ObjectPlane[2];
+ params[3] = (GLint) texgen->ObjectPlane[3];
+ break;
+ case GL_EYE_PLANE:
+ params[0] = (GLint) texgen->EyePlane[0];
+ params[1] = (GLint) texgen->EyePlane[1];
+ params[2] = (GLint) texgen->EyePlane[2];
+ params[3] = (GLint) texgen->EyePlane[3];
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
+ }
+}
+
+
diff --git a/mesalib/src/mesa/main/texgen.h b/mesalib/src/mesa/main/texgen.h
new file mode 100644
index 000000000..073588efc
--- /dev/null
+++ b/mesalib/src/mesa/main/texgen.h
@@ -0,0 +1,62 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 TEXGEN_H
+#define TEXGEN_H
+
+
+#include "main/glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params );
+
+extern void GLAPIENTRY
+_mesa_TexGend( GLenum coord, GLenum pname, GLdouble param );
+
+extern void GLAPIENTRY
+_mesa_TexGendv( GLenum coord, GLenum pname, const GLdouble *params );
+
+extern void GLAPIENTRY
+_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param );
+
+extern void GLAPIENTRY
+_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_TexGeni( GLenum coord, GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_TexGeniv( GLenum coord, GLenum pname, const GLint *params );
+
+
+
+#endif /* TEXGEN_H */
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
new file mode 100644
index 000000000..14d6fc765
--- /dev/null
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -0,0 +1,581 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * Code for glGetTexImage() and glGetCompressedTexImage().
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "image.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texgetimage.h"
+#include "teximage.h"
+#include "texstate.h"
+
+
+
+#if FEATURE_EXT_texture_sRGB
+
+/**
+ * Test if given texture image is an sRGB format.
+ */
+static GLboolean
+is_srgb_teximage(const struct gl_texture_image *texImage)
+{
+ switch (texImage->TexFormat->MesaFormat) {
+ case MESA_FORMAT_SRGB8:
+ case MESA_FORMAT_SRGBA8:
+ case MESA_FORMAT_SARGB8:
+ case MESA_FORMAT_SL8:
+ case MESA_FORMAT_SLA8:
+ case MESA_FORMAT_SRGB_DXT1:
+ case MESA_FORMAT_SRGBA_DXT1:
+ case MESA_FORMAT_SRGBA_DXT3:
+ case MESA_FORMAT_SRGBA_DXT5:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Convert a float value from linear space to a
+ * non-linear sRGB value in [0, 255].
+ * Not terribly efficient.
+ */
+static INLINE GLfloat
+linear_to_nonlinear(GLfloat cl)
+{
+ /* can't have values outside [0, 1] */
+ GLfloat cs;
+ if (cl < 0.0031308f) {
+ cs = 12.92f * cl;
+ }
+ else {
+ cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055);
+ }
+ return cs;
+}
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/**
+ * Can the given type represent negative values?
+ */
+static INLINE GLboolean
+type_with_negative_values(GLenum type)
+{
+ switch (type) {
+ case GL_BYTE:
+ case GL_SHORT:
+ case GL_INT:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_ARB:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * This is the software fallback for Driver.GetTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* Packing texture image into a PBO.
+ * Map the (potentially) VRAM-based buffer into our process space so
+ * we can write into it with the code below.
+ * A hardware driver might use a sophisticated blit to move the
+ * texture data to the PBO if the PBO is in VRAM along with the texture.
+ */
+ GLubyte *buf = (GLubyte *)
+ ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
+ return;
+ }
+ /* <pixels> was an offset into the PBO.
+ * Now make it a real, client-side pointer inside the mapped region.
+ */
+ pixels = ADD_POINTERS(buf, pixels);
+ }
+ else if (!pixels) {
+ /* not an error */
+ return;
+ }
+
+ {
+ const GLint width = texImage->Width;
+ const GLint height = texImage->Height;
+ const GLint depth = texImage->Depth;
+ GLint img, row;
+ for (img = 0; img < depth; img++) {
+ for (row = 0; row < height; row++) {
+ /* compute destination address in client memory */
+ GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ img, row, 0);
+ assert(dest);
+
+ if (format == GL_COLOR_INDEX) {
+ GLuint indexRow[MAX_WIDTH];
+ GLint col;
+ /* Can't use FetchTexel here because that returns RGBA */
+ if (texImage->TexFormat->IndexBits == 8) {
+ const GLubyte *src = (const GLubyte *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else if (texImage->TexFormat->IndexBits == 16) {
+ const GLushort *src = (const GLushort *) texImage->Data;
+ src += width * (img * texImage->Height + row);
+ for (col = 0; col < width; col++) {
+ indexRow[col] = src[col];
+ }
+ }
+ else {
+ _mesa_problem(ctx,
+ "Color index problem in _mesa_GetTexImage");
+ }
+ _mesa_pack_index_span(ctx, width, type, dest,
+ indexRow, &ctx->Pack,
+ 0 /* no image transfer */);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ GLfloat depthRow[MAX_WIDTH];
+ GLint col;
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img,
+ depthRow + col);
+ }
+ _mesa_pack_depth_span(ctx, width, dest, type,
+ depthRow, &ctx->Pack);
+ }
+ else if (format == GL_DEPTH_STENCIL_EXT) {
+ /* XXX Note: we're bypassing texImage->FetchTexel()! */
+ const GLuint *src = (const GLuint *) texImage->Data;
+ src += width * row + width * height * img;
+ _mesa_memcpy(dest, src, width * sizeof(GLuint));
+ if (ctx->Pack.SwapBytes) {
+ _mesa_swap4((GLuint *) dest, width);
+ }
+ }
+ else if (format == GL_YCBCR_MESA) {
+ /* No pixel transfer */
+ const GLint rowstride = texImage->RowStride;
+ MEMCPY(dest,
+ (const GLushort *) texImage->Data + row * rowstride,
+ width * sizeof(GLushort));
+ /* check for byte swapping */
+ if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
+ && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
+ (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
+ && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
+ if (!ctx->Pack.SwapBytes)
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ else if (ctx->Pack.SwapBytes) {
+ _mesa_swap2((GLushort *) dest, width);
+ }
+ }
+#if FEATURE_EXT_texture_sRGB
+ else if (is_srgb_teximage(texImage)) {
+ /* special case this since need to backconvert values */
+ /* convert row to RGBA format */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLint col;
+ GLbitfield transferOps = 0x0;
+
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_RGB ||
+ texImage->_BaseFormat == GL_RGBA) {
+ rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
+ rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
+ rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ }
+#endif /* FEATURE_EXT_texture_sRGB */
+ else {
+ /* general case: convert row to RGBA format */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLint col;
+ GLbitfield transferOps = 0x0;
+
+ /* clamp does not apply to GetTexImage (final conversion)?
+ * Looks like we need clamp though when going from format
+ * containing negative values to unsigned format.
+ */
+ if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
+ transferOps |= IMAGE_CLAMP_BIT;
+ else if (!type_with_negative_values(type) &&
+ (texImage->TexFormat->DataType == GL_FLOAT ||
+ texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
+ transferOps |= IMAGE_CLAMP_BIT;
+
+ for (col = 0; col < width; col++) {
+ (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
+ if (texImage->_BaseFormat == GL_ALPHA) {
+ rgba[col][RCOMP] = 0.0;
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ rgba[col][ACOMP] = 1.0;
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ }
+ else if (texImage->_BaseFormat == GL_INTENSITY) {
+ rgba[col][GCOMP] = 0.0;
+ rgba[col][BCOMP] = 0.0;
+ rgba[col][ACOMP] = 1.0;
+ }
+ }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
+ format, type, dest,
+ &ctx->Pack, transferOps);
+ } /* format */
+ } /* row */
+ } /* img */
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.GetCompressedTexImage().
+ * All error checking will have been done before this routine is called.
+ */
+void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLuint size;
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* pack texture image into a PBO */
+ GLubyte *buf;
+ if ((const GLubyte *) img + texImage->CompressedSize >
+ (const GLubyte *) ctx->Pack.BufferObj->Size) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(invalid PBO access)");
+ return;
+ }
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ GL_WRITE_ONLY_ARB,
+ ctx->Pack.BufferObj);
+ if (!buf) {
+ /* buffer is already mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImage(PBO is mapped)");
+ return;
+ }
+ img = ADD_POINTERS(buf, img);
+ }
+ else if (!img) {
+ /* not an error */
+ return;
+ }
+
+ /* don't use texImage->CompressedSize since that may be padded out */
+ size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height,
+ texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+
+ /* just memcpy, no pixelstore or pixel transfer */
+ _mesa_memcpy(img, texImage->Data, size);
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+ ctx->Pack.BufferObj);
+ }
+}
+
+
+
+/**
+ * Do error checking for a glGetTexImage() call.
+ * \return GL_TRUE if any error, GL_FALSE if no errors.
+ */
+static GLboolean
+getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
+
+ if (maxLevels == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
+ return GL_TRUE;
+ }
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_sizeof_packed_type(type) <= 0) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
+ return GL_TRUE;
+ }
+
+ if (_mesa_components_in_format(format) <= 0 ||
+ format == GL_STENCIL_INDEX) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.EXT_packed_depth_stencil
+ && _mesa_is_depthstencil_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ if (!ctx->Extensions.ATI_envmap_bumpmap
+ && _mesa_is_dudv_format(format)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
+ return GL_TRUE;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ if (!texObj || _mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
+ return GL_TRUE;
+ }
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ /* out of memory */
+ return GL_TRUE;
+ }
+
+ /* Make sure the requested image format is compatible with the
+ * texture's format. Note that a color index texture can be converted
+ * to RGBA so that combo is allowed.
+ */
+ if (_mesa_is_color_format(format)
+ && !_mesa_is_color_format(texImage->TexFormat->BaseFormat)
+ && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_index_format(format)
+ && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depth_format(format)
+ && !_mesa_is_depth_format(texImage->TexFormat->BaseFormat)
+ && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_ycbcr_format(format)
+ && !_mesa_is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_depthstencil_format(format)
+ && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+ else if (_mesa_is_dudv_format(format)
+ && !_mesa_is_dudv_format(texImage->TexFormat->BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+ return GL_TRUE;
+ }
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ /* packing texture image into a PBO */
+ const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+ if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+ texImage->Height, texImage->Depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexImage(invalid PBO access)");
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+
+/**
+ * Get texture image. Called by glGetTexImage.
+ *
+ * \param target texture target.
+ * \param level image level.
+ * \param format pixel data format for returned image.
+ * \param type pixel data type for returned image.
+ * \param pixels returned pixel data.
+ */
+void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid *pixels )
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ struct gl_texture_image *texImage =
+ _mesa_select_tex_image(ctx, texObj, target, level);
+
+ /* typically, this will call _mesa_get_teximage() */
+ ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
+ texObj, texImage);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLint maxLevels;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (!texObj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB");
+ return;
+ }
+
+ maxLevels = _mesa_max_texture_levels(ctx, target);
+ ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
+ return;
+ }
+
+ if (_mesa_is_proxy_texture(target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
+ return;
+ }
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (texImage) {
+ if (texImage->IsCompressed) {
+ /* this typically calls _mesa_get_compressed_teximage() */
+ ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
+ texObj, texImage);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetCompressedTexImageARB");
+ }
+ }
+ else {
+ /* probably invalid mipmap level */
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetCompressedTexImageARB(level)");
+ }
+ }
+ _mesa_unlock_texture(ctx, texObj);
+}
diff --git a/mesalib/src/mesa/main/texgetimage.h b/mesalib/src/mesa/main/texgetimage.h
new file mode 100644
index 000000000..088d27c7e
--- /dev/null
+++ b/mesalib/src/mesa/main/texgetimage.h
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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 TEXGETIMAGE_H
+#define TEXGETIMAGE_H
+
+
+extern void
+_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLvoid *img,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+
+extern void GLAPIENTRY
+_mesa_GetTexImage( GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img);
+
+
+#endif /* TEXGETIMAGE_H */
diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c
new file mode 100644
index 000000000..a8160c273
--- /dev/null
+++ b/mesalib/src/mesa/main/teximage.c
@@ -0,0 +1,3660 @@
+/*
+ * mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file teximage.c
+ * Texture image-related functions.
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "context.h"
+#if FEATURE_convolve
+#include "convolve.h"
+#endif
+#include "enums.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "hash.h"
+#include "image.h"
+#include "imports.h"
+#include "macros.h"
+#include "state.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "texstore.h"
+#include "mtypes.h"
+
+
+/**
+ * State changes which we care about for glCopyTex[Sub]Image() calls.
+ * In particular, we care about pixel transfer state and buffer state
+ * (such as glReadBuffer to make sure we read from the right renderbuffer).
+ */
+#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
+ _NEW_BUFFERS | \
+ _NEW_PIXEL)
+
+
+
+/**
+ * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
+ * elsewhere.
+ */
+void *
+_mesa_alloc_texmemory(GLsizei bytes)
+{
+ return _mesa_align_malloc(bytes, 512);
+}
+
+
+/**
+ * Free texture memory allocated with _mesa_alloc_texmemory()
+ */
+void
+_mesa_free_texmemory(void *m)
+{
+ _mesa_align_free(m);
+}
+
+
+
+
+#if 0
+static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img)
+{
+#if CHAN_TYPE != GL_UNSIGNED_BYTE
+ _mesa_problem(NULL, "PrintTexture not supported");
+#else
+ GLuint i, j, c;
+ const GLubyte *data = (const GLubyte *) img->Data;
+
+ if (!data) {
+ _mesa_printf("No texture data\n");
+ return;
+ }
+
+ switch (img->Format) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_INTENSITY:
+ case GL_COLOR_INDEX:
+ c = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ c = 2;
+ break;
+ case GL_RGB:
+ c = 3;
+ break;
+ case GL_RGBA:
+ c = 4;
+ break;
+ default:
+ _mesa_problem(NULL, "error in PrintTexture\n");
+ return;
+ }
+
+ for (i = 0; i < img->Height; i++) {
+ for (j = 0; j < img->Width; j++) {
+ if (c==1)
+ _mesa_printf("%02x ", data[0]);
+ else if (c==2)
+ _mesa_printf("%02x%02x ", data[0], data[1]);
+ else if (c==3)
+ _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]);
+ else if (c==4)
+ _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
+ data += (img->RowStride - img->Width) * c;
+ }
+ /* XXX use img->ImageStride here */
+ _mesa_printf("\n");
+ }
+#endif
+}
+#endif
+
+
+/*
+ * Compute floor(log_base_2(n)).
+ * If n < 0 return -1.
+ */
+static int
+logbase2( int n )
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n < 0)
+ return -1;
+
+ if (n == 0)
+ return 0;
+
+ while ( n > i ) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return log2 - 1;
+ }
+ else {
+ return log2;
+ }
+}
+
+
+
+/**
+ * Return the simple base format for a given internal texture format.
+ * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
+ *
+ * \param ctx GL context.
+ * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
+ *
+ * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
+ *
+ * This is the format which is used during texture application (i.e. the
+ * texture format and env mode determine the arithmetic used.
+ *
+ * XXX this could be static
+ */
+GLint
+_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
+{
+ switch (internalFormat) {
+ 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:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.EXT_paletted_texture) {
+ switch (internalFormat) {
+ 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:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ARB_depth_texture) {
+ switch (internalFormat) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_DEPTH_COMPONENT;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_ALPHA:
+ return GL_ALPHA;
+ case GL_COMPRESSED_LUMINANCE:
+ return GL_LUMINANCE;
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return GL_LUMINANCE_ALPHA;
+ case GL_COMPRESSED_INTENSITY:
+ return GL_INTENSITY;
+ case GL_COMPRESSED_RGB:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+
+ if (ctx->Extensions.TDFX_texture_compression_FXT1) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_texture_compression_s3tc) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return GL_RGB;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.S3_s3tc) {
+ switch (internalFormat) {
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ return GL_RGB;
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_ycbcr_texture) {
+ if (internalFormat == GL_YCBCR_MESA)
+ return GL_YCBCR_MESA;
+ }
+
+ if (ctx->Extensions.ARB_texture_float) {
+ switch (internalFormat) {
+ case GL_ALPHA16F_ARB:
+ case GL_ALPHA32F_ARB:
+ return GL_ALPHA;
+ case GL_RGBA16F_ARB:
+ case GL_RGBA32F_ARB:
+ return GL_RGBA;
+ case GL_RGB16F_ARB:
+ case GL_RGB32F_ARB:
+ return GL_RGB;
+ case GL_INTENSITY16F_ARB:
+ case GL_INTENSITY32F_ARB:
+ return GL_INTENSITY;
+ case GL_LUMINANCE16F_ARB:
+ case GL_LUMINANCE32F_ARB:
+ return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA16F_ARB:
+ case GL_LUMINANCE_ALPHA32F_ARB:
+ return GL_LUMINANCE_ALPHA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.ATI_envmap_bumpmap) {
+ switch (internalFormat) {
+ case GL_DUDV_ATI:
+ case GL_DU8DV8_ATI:
+ return GL_DUDV_ATI;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.MESA_texture_signed_rgba) {
+ switch (internalFormat) {
+ case GL_RGBA_SNORM:
+ case GL_RGBA8_SNORM:
+ return GL_RGBA;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+ if (ctx->Extensions.EXT_packed_depth_stencil) {
+ switch (internalFormat) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_DEPTH_STENCIL_EXT;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+#if FEATURE_EXT_texture_sRGB
+ if (ctx->Extensions.EXT_texture_sRGB) {
+ switch (internalFormat) {
+ case GL_SRGB_EXT:
+ case GL_SRGB8_EXT:
+ case GL_COMPRESSED_SRGB_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return GL_RGB;
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return GL_RGBA;
+ case GL_SLUMINANCE_ALPHA_EXT:
+ case GL_SLUMINANCE8_ALPHA8_EXT:
+ case GL_COMPRESSED_SLUMINANCE_EXT:
+ case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
+ return GL_LUMINANCE_ALPHA;
+ case GL_SLUMINANCE_EXT:
+ case GL_SLUMINANCE8_EXT:
+ return GL_LUMINANCE;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+ return -1; /* error */
+}
+
+
+/**
+ * Test if it is a supported compressed format.
+ *
+ * \param internalFormat the internal format token provided by the user.
+ *
+ * \ret GL_TRUE if \p internalFormat is a supported compressed format, or
+ * GL_FALSE otherwise.
+ *
+ * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX
+ * are supported.
+ */
+static GLboolean
+is_compressed_format(GLcontext *ctx, GLenum internalFormat)
+{
+ GLint supported[100]; /* 100 should be plenty */
+ GLuint i, n;
+
+ n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE);
+ ASSERT(n < 100);
+ for (i = 0; i < n; i++) {
+ if ((GLint) internalFormat == supported[i]) {
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * For cube map faces, return a face index in [0,5].
+ * For other targets return 0;
+ */
+GLuint
+_mesa_tex_target_to_face(GLenum target)
+{
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
+ return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ else
+ return 0;
+}
+
+
+
+/**
+ * Store a gl_texture_image pointer in a gl_texture_object structure
+ * according to the target and level parameters.
+ *
+ * \param tObj texture object.
+ * \param target texture target.
+ * \param level image level.
+ * \param texImage texture image.
+ *
+ * This was basically prompted by the introduction of cube maps.
+ */
+void
+_mesa_set_tex_image(struct gl_texture_object *tObj,
+ GLenum target, GLint level,
+ struct gl_texture_image *texImage)
+{
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ ASSERT(tObj);
+ ASSERT(texImage);
+ ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
+
+ tObj->Image[face][level] = texImage;
+
+ /* Set the 'back' pointer */
+ texImage->TexObject = tObj;
+}
+
+
+/**
+ * Allocate a texture image structure.
+ *
+ * Called via ctx->Driver.NewTextureImage() unless overriden by a device
+ * driver.
+ *
+ * \return a pointer to gl_texture_image struct with all fields initialized to
+ * zero.
+ */
+struct gl_texture_image *
+_mesa_new_texture_image( GLcontext *ctx )
+{
+ (void) ctx;
+ return CALLOC_STRUCT(gl_texture_image);
+}
+
+
+/**
+ * Free texture image data.
+ * This function is a fallback called via ctx->Driver.FreeTexImageData().
+ *
+ * \param texImage texture image.
+ *
+ * Free the texture image data if it's not marked as client data.
+ */
+void
+_mesa_free_texture_image_data(GLcontext *ctx,
+ struct gl_texture_image *texImage)
+{
+ (void) ctx;
+
+ if (texImage->Data && !texImage->IsClientData) {
+ /* free the old texture data */
+ _mesa_free_texmemory(texImage->Data);
+ }
+
+ texImage->Data = NULL;
+}
+
+
+/**
+ * Free texture image.
+ *
+ * \param texImage texture image.
+ *
+ * Free the texture image structure and the associated image data.
+ */
+void
+_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
+{
+ /* Free texImage->Data and/or any other driver-specific texture
+ * image storage.
+ */
+ ASSERT(ctx->Driver.FreeTexImageData);
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+
+ ASSERT(texImage->Data == NULL);
+ if (texImage->ImageOffsets)
+ _mesa_free(texImage->ImageOffsets);
+ _mesa_free(texImage);
+}
+
+
+/**
+ * Test if a target is a proxy target.
+ *
+ * \param target texture target.
+ *
+ * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
+ */
+GLboolean
+_mesa_is_proxy_texture(GLenum target)
+{
+ /* NUM_TEXTURE_TARGETS should match number of terms below */
+ assert(NUM_TEXTURE_TARGETS == 7);
+
+ return (target == GL_PROXY_TEXTURE_1D ||
+ target == GL_PROXY_TEXTURE_2D ||
+ target == GL_PROXY_TEXTURE_3D ||
+ target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
+ target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
+}
+
+
+/**
+ * Get the texture object that corresponds to the target of the given texture unit.
+ *
+ * \param ctx GL context.
+ * \param texUnit texture unit.
+ * \param target texture target.
+ *
+ * \return pointer to the texture object on success, or NULL on failure.
+ *
+ * \sa gl_texture_unit.
+ */
+struct gl_texture_object *
+_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+ GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return texUnit->CurrentTex[TEXTURE_1D_INDEX];
+ case GL_PROXY_TEXTURE_1D:
+ return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
+ case GL_TEXTURE_2D:
+ return texUnit->CurrentTex[TEXTURE_2D_INDEX];
+ case GL_PROXY_TEXTURE_2D:
+ return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
+ case GL_TEXTURE_3D:
+ return texUnit->CurrentTex[TEXTURE_3D_INDEX];
+ case GL_PROXY_TEXTURE_3D:
+ return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle
+ ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle
+ ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
+ default:
+ _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
+ return NULL;
+ }
+}
+
+
+/**
+ * Get a texture image pointer from a texture object, given a texture
+ * target and mipmap level. The target and level parameters should
+ * have already been error-checked.
+ *
+ * \param ctx GL context.
+ * \param texObj texture unit.
+ * \param target texture target.
+ * \param level image level.
+ *
+ * \return pointer to the texture image structure, or NULL on failure.
+ */
+struct gl_texture_image *
+_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
+ GLenum target, GLint level)
+{
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ ASSERT(texObj);
+ ASSERT(level >= 0);
+ ASSERT(level < MAX_TEXTURE_LEVELS);
+
+ return texObj->Image[face][level];
+}
+
+
+/**
+ * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
+ * it and install it. Only return NULL if passed a bad parameter or run
+ * out of memory.
+ */
+struct gl_texture_image *
+_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLenum target, GLint level)
+{
+ struct gl_texture_image *texImage;
+
+ if (!texObj)
+ return NULL;
+
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
+ return NULL;
+ }
+
+ _mesa_set_tex_image(texObj, target, level, texImage);
+ }
+
+ return texImage;
+}
+
+
+/**
+ * Return pointer to the specified proxy texture image.
+ * Note that proxy textures are per-context, not per-texture unit.
+ * \return pointer to texture image or NULL if invalid target, invalid
+ * level, or out of memory.
+ */
+struct gl_texture_image *
+_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
+{
+ struct gl_texture_image *texImage;
+ GLuint texIndex;
+
+ if (level < 0 )
+ return NULL;
+
+ switch (target) {
+ case GL_PROXY_TEXTURE_1D:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_1D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_2D:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_2D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_3D:
+ if (level >= ctx->Const.Max3DTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_3D_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_CUBE_MAP:
+ if (level >= ctx->Const.MaxCubeTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_CUBE_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ if (level > 0)
+ return NULL;
+ texIndex = TEXTURE_RECT_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_1D_ARRAY_INDEX;
+ break;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ if (level >= ctx->Const.MaxTextureLevels)
+ return NULL;
+ texIndex = TEXTURE_2D_ARRAY_INDEX;
+ break;
+ default:
+ return NULL;
+ }
+
+ texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
+ if (!texImage) {
+ texImage = ctx->Driver.NewTextureImage(ctx);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
+ return NULL;
+ }
+ ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
+ /* Set the 'back' pointer */
+ texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
+ }
+ return texImage;
+}
+
+
+/**
+ * Get the maximum number of allowed mipmap levels.
+ *
+ * \param ctx GL context.
+ * \param target texture target.
+ *
+ * \return the maximum number of allowed mipmap levels for the given
+ * texture target, or zero if passed a bad target.
+ *
+ * \sa gl_constants.
+ */
+GLint
+_mesa_max_texture_levels(GLcontext *ctx, GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_PROXY_TEXTURE_2D:
+ return ctx->Const.MaxTextureLevels;
+ case GL_TEXTURE_3D:
+ case GL_PROXY_TEXTURE_3D:
+ return ctx->Const.Max3DTextureLevels;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ return ctx->Extensions.ARB_texture_cube_map
+ ? ctx->Const.MaxCubeTextureLevels : 0;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ return ctx->Extensions.MESA_texture_array
+ ? ctx->Const.MaxTextureLevels : 0;
+ default:
+ return 0; /* bad target */
+ }
+}
+
+
+
+#if 000 /* not used anymore */
+/*
+ * 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 GLubyte *
+make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
+{
+ const GLint components = _mesa_components_in_format(format);
+ const GLint numPixels = width * height * depth;
+ GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
+
+#ifdef DEBUG
+ /*
+ * 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 (data) {
+ static const 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 = data;
+ GLint h, i, j, k;
+ for (h = 0; h < depth; h++) {
+ 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;
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return data;
+}
+#endif
+
+
+
+/**
+ * Reset the fields of a gl_texture_image struct to zero.
+ *
+ * \param img texture image structure.
+ *
+ * This is called when a proxy texture test fails, we set all the
+ * image members (except DriverData) to zero.
+ * It's also used in glTexImage[123]D as a safeguard to be sure all
+ * required fields get initialized properly by the Driver.TexImage[123]D
+ * functions.
+ */
+static void
+clear_teximage_fields(struct gl_texture_image *img)
+{
+ ASSERT(img);
+ img->_BaseFormat = 0;
+ img->InternalFormat = 0;
+ img->Border = 0;
+ img->Width = 0;
+ img->Height = 0;
+ img->Depth = 0;
+ img->RowStride = 0;
+ if (img->ImageOffsets) {
+ _mesa_free(img->ImageOffsets);
+ img->ImageOffsets = NULL;
+ }
+ img->Width2 = 0;
+ img->Height2 = 0;
+ img->Depth2 = 0;
+ img->WidthLog2 = 0;
+ img->HeightLog2 = 0;
+ img->DepthLog2 = 0;
+ img->Data = NULL;
+ img->TexFormat = &_mesa_null_texformat;
+ img->FetchTexelc = NULL;
+ img->FetchTexelf = NULL;
+ img->IsCompressed = 0;
+ img->CompressedSize = 0;
+}
+
+
+/**
+ * Initialize basic fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
+ * \param img texture image structure to be initialized.
+ * \param width image width.
+ * \param height image height.
+ * \param depth image depth.
+ * \param border image border.
+ * \param internalFormat internal format.
+ *
+ * Fills in the fields of \p img with the given information.
+ * Note: width, height and depth include the border.
+ */
+void
+_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
+ struct gl_texture_image *img,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum internalFormat)
+{
+ GLint i;
+
+ ASSERT(img);
+ ASSERT(width >= 0);
+ ASSERT(height >= 0);
+ ASSERT(depth >= 0);
+
+ img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
+ ASSERT(img->_BaseFormat > 0);
+ img->InternalFormat = internalFormat;
+ img->Border = border;
+ img->Width = width;
+ img->Height = height;
+ img->Depth = depth;
+
+ img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
+ img->WidthLog2 = logbase2(img->Width2);
+
+ if (height == 1) { /* 1-D texture */
+ img->Height2 = 1;
+ img->HeightLog2 = 0;
+ }
+ else {
+ img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
+ img->HeightLog2 = logbase2(img->Height2);
+ }
+
+ if (depth == 1) { /* 2-D texture */
+ img->Depth2 = 1;
+ img->DepthLog2 = 0;
+ }
+ else {
+ img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
+ img->DepthLog2 = logbase2(img->Depth2);
+ }
+
+ img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
+
+ img->IsCompressed = GL_FALSE;
+ img->CompressedSize = 0;
+
+ if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
+ (height == 1 || _mesa_is_pow_two(img->Height2)) &&
+ (depth == 1 || _mesa_is_pow_two(img->Depth2)))
+ img->_IsPowerOfTwo = GL_TRUE;
+ else
+ img->_IsPowerOfTwo = GL_FALSE;
+
+ /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
+ img->RowStride = width;
+ /* Allocate the ImageOffsets array and initialize to typical values.
+ * We allocate the array for 1D/2D textures too in order to avoid special-
+ * case code in the texstore routines.
+ */
+ if (img->ImageOffsets)
+ _mesa_free(img->ImageOffsets);
+ img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint));
+ for (i = 0; i < depth; i++) {
+ img->ImageOffsets[i] = i * width * height;
+ }
+
+ /* Compute Width/Height/DepthScale for mipmap lod computation */
+ if (target == GL_TEXTURE_RECTANGLE_NV) {
+ /* scale = 1.0 since texture coords directly map to texels */
+ img->WidthScale = 1.0;
+ img->HeightScale = 1.0;
+ img->DepthScale = 1.0;
+ }
+ else {
+ img->WidthScale = (GLfloat) img->Width;
+ img->HeightScale = (GLfloat) img->Height;
+ img->DepthScale = (GLfloat) img->Depth;
+ }
+}
+
+
+/**
+ * Free and clear fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param texImage texture image structure to be cleared.
+ *
+ * After the call, \p texImage will have no data associated with it. Its
+ * fields are cleared so that its parent object will test incomplete.
+ */
+void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
+{
+ ctx->Driver.FreeTexImageData(ctx, texImage);
+ clear_teximage_fields(texImage);
+}
+
+
+/**
+ * This is the fallback for Driver.TestProxyTexImage(). Test the texture
+ * level, width, height and depth against the ctx->Const limits for textures.
+ *
+ * A hardware driver might override this function if, for example, the
+ * max 3D texture size is 512x512x64 (i.e. not a cube).
+ *
+ * Note that width, height, depth == 0 is not an error. However, a
+ * texture with zero width/height/depth will be considered "incomplete"
+ * and texturing will effectively be disabled.
+ *
+ * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
+ * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
+ * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
+ * \param level as passed to glTexImage
+ * \param internalFormat as passed to glTexImage
+ * \param format as passed to glTexImage
+ * \param type as passed to glTexImage
+ * \param width as passed to glTexImage
+ * \param height as passed to glTexImage
+ * \param depth as passed to glTexImage
+ * \param border as passed to glTexImage
+ * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
+ */
+GLboolean
+_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint width, GLint height, GLint depth, GLint border)
+{
+ GLint maxSize;
+
+ (void) internalFormat;
+ (void) format;
+ (void) type;
+
+ switch (target) {
+ case GL_PROXY_TEXTURE_1D:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or level */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_2D:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ height < 2 * border || height > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or height or level */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_3D:
+ maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ height < 2 * border || height > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
+ depth < 2 * border || depth > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
+ level >= ctx->Const.Max3DTextureLevels) {
+ /* bad width or height or depth or level */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_RECTANGLE_NV:
+ if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
+ height < 0 || height > ctx->Const.MaxTextureRectSize ||
+ level != 0) {
+ /* bad width or height or level */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
+ maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ height < 2 * border || height > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
+ level >= ctx->Const.MaxCubeTextureLevels) {
+ /* bad width or height */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or level */
+ return GL_FALSE;
+ }
+
+ if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+ maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
+ if (width < 2 * border || width > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
+ height < 2 * border || height > 2 + maxSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
+ level >= ctx->Const.MaxTextureLevels) {
+ /* bad width or height or level */
+ return GL_FALSE;
+ }
+ if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ default:
+ _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Helper function to determine whether a target supports compressed textures
+ */
+static GLboolean
+target_can_be_compressed(GLcontext *ctx, GLenum target)
+{
+ return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
+ || ((ctx->Extensions.ARB_texture_cube_map &&
+ (target == GL_PROXY_TEXTURE_CUBE_MAP ||
+ (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
+ || ((ctx->Extensions.MESA_texture_array &&
+ ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
+ (target == GL_TEXTURE_2D_ARRAY_EXT)))));
+}
+
+
+/**
+ * Test the glTexImage[123]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param internalFormat internal format given by the user.
+ * \param format pixel data format given by the user.
+ * \param type pixel data type given by the user.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param depth image depth given by the user.
+ * \param border image border given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __GLcontextRec::Const and the supported extensions, and according to the
+ * OpenGL specification.
+ */
+static GLboolean
+texture_error_check( GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLuint dimensions,
+ GLint width, GLint height,
+ GLint depth, GLint border )
+{
+ const GLboolean isProxy = _mesa_is_proxy_texture(target);
+ GLboolean sizeOK = GL_TRUE;
+ GLboolean colorFormat, indexFormat;
+ GLenum proxy_target;
+
+ /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(level=%d)", dimensions, level);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check border */
+ if (border < 0 || border > 1 ||
+ ((target == GL_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(border=%d)", dimensions, border);
+ }
+ return GL_TRUE;
+ }
+
+ if (width < 0 || height < 0 || depth < 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(width, height or depth < 0)", dimensions);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check target and call ctx->Driver.TestProxyTexImage() to check the
+ * level, width, height and depth.
+ */
+ if (dimensions == 1) {
+ if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
+ proxy_target = GL_PROXY_TEXTURE_1D;
+ height = 1;
+ depth = 1;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 2) {
+ depth = 1;
+ if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
+ proxy_target = GL_PROXY_TEXTURE_2D;
+ }
+ else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
+ (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
+ if (!ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
+ return GL_TRUE;
+ }
+ proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
+ sizeOK = (width == height);
+ }
+ else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
+ target == GL_TEXTURE_RECTANGLE_NV) {
+ if (!ctx->Extensions.NV_texture_rectangle) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
+ return GL_TRUE;
+ }
+ proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
+ }
+ else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
+ target == GL_TEXTURE_1D_ARRAY_EXT) {
+ proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 3) {
+ if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
+ proxy_target = GL_PROXY_TEXTURE_3D;
+ }
+ else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
+ target == GL_TEXTURE_2D_ARRAY_EXT) {
+ proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_problem( ctx, "bad dims in texture_error_check" );
+ return GL_TRUE;
+ }
+
+ sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
+ internalFormat, format,
+ type, width, height,
+ depth, border);
+ if (!sizeOK) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
+ dimensions, level, width, height, depth);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check internalFormat */
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexImage%dD(internalFormat=0x%x)",
+ dimensions, internalFormat);
+ }
+ return GL_TRUE;
+ }
+
+ /* Check incoming image format and type */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
+ * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
+ */
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
+ }
+ return GL_TRUE;
+ }
+
+ /* make sure internal format and format basically agree */
+ colorFormat = _mesa_is_color_format(format);
+ indexFormat = _mesa_is_index_format(format);
+ if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
+ (_mesa_is_index_format(internalFormat) && !indexFormat) ||
+ (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
+ (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
+ (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
+ (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
+ dimensions, internalFormat, format);
+ return GL_TRUE;
+ }
+
+ /* additional checks for ycbcr textures */
+ if (internalFormat == GL_YCBCR_MESA) {
+ ASSERT(ctx->Extensions.MESA_ycbcr_texture);
+ if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
+ type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
+ char message[100];
+ _mesa_sprintf(message,
+ "glTexImage%d(format/type YCBCR mismatch", dimensions);
+ _mesa_error(ctx, GL_INVALID_ENUM, message);
+ return GL_TRUE; /* error */
+ }
+ if (target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D &&
+ target != GL_TEXTURE_RECTANGLE_NV &&
+ target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ if (!isProxy) {
+ char message[100];
+ _mesa_sprintf(message,
+ "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
+ dimensions, border);
+ _mesa_error(ctx, GL_INVALID_VALUE, message);
+ }
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for depth textures */
+ if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
+ /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
+ if (target != GL_TEXTURE_1D &&
+ target != GL_PROXY_TEXTURE_1D &&
+ target != GL_TEXTURE_2D &&
+ target != GL_PROXY_TEXTURE_2D &&
+ target != GL_TEXTURE_RECTANGLE_ARB &&
+ target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
+ if (!isProxy)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage(target/internalFormat)");
+ return GL_TRUE;
+ }
+ }
+
+ /* additional checks for compressed textures */
+ if (is_compressed_format(ctx, internalFormat)) {
+ if (!target_can_be_compressed(ctx, target) && !isProxy) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexImage%d(target)", dimensions);
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ if (!isProxy) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%D(border!=0)", dimensions);
+ }
+ return GL_TRUE;
+ }
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glTexSubImage[123]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param xoffset sub-image x offset given by the user.
+ * \param yoffset sub-image y offset given by the user.
+ * \param zoffset sub-image z offset given by the user.
+ * \param format pixel data format given by the user.
+ * \param type pixel data type given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param depth image depth given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __GLcontextRec::Const and the supported extensions, and according to the
+ * OpenGL specification.
+ */
+static GLboolean
+subtexture_error_check( GLcontext *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type )
+{
+ /* Check target */
+ if (dimensions == 1) {
+ if (target != GL_TEXTURE_1D) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 2) {
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_TEXTURE_RECTANGLE_NV) {
+ if (!ctx->Extensions.NV_texture_rectangle) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
+ if (!ctx->Extensions.MESA_texture_array) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target != GL_TEXTURE_2D) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 3) {
+ if (target == GL_TEXTURE_2D_ARRAY_EXT) {
+ if (!ctx->Extensions.MESA_texture_array) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target != GL_TEXTURE_3D) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_problem( ctx, "invalid dims in texture_error_check" );
+ return GL_TRUE;
+ }
+
+ /* Basic level check */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
+ return GL_TRUE;
+ }
+
+ if (width < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(width=%d)", dimensions, width);
+ return GL_TRUE;
+ }
+ if (height < 0 && dimensions > 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(height=%d)", dimensions, height);
+ return GL_TRUE;
+ }
+ if (depth < 0 && dimensions > 2) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexSubImage%dD(depth=%d)", dimensions, depth);
+ return GL_TRUE;
+ }
+
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
+ dimensions, format, type);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+static GLboolean
+subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type,
+ const struct gl_texture_image *destTex )
+{
+ if (!destTex) {
+ /* undefined image level */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
+ return GL_TRUE;
+ }
+
+ if (xoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (dimensions > 1) {
+ if (yoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
+ dimensions);
+ return GL_TRUE;
+ }
+ if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+ if (dimensions > 2) {
+ if (zoffset < -((GLint)destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
+ return GL_TRUE;
+ }
+ if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
+ return GL_TRUE;
+ }
+ }
+
+#if FEATURE_EXT_texture_sRGB
+ if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
+ destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
+ destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
+ destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
+ if ((width & 0x3) || (height & 0x3) ||
+ (xoffset & 0x3) || (yoffset & 0x3))
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%dD(size or offset not multiple of 4)",
+ dimensions);
+ return GL_TRUE;
+ }
+#endif
+
+ if (destTex->IsCompressed) {
+ if (!target_can_be_compressed(ctx, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexSubImage%D(target)", dimensions);
+ return GL_TRUE;
+ }
+ /* offset must be multiple of 4 */
+ if ((xoffset & 3) || (yoffset & 3)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%D(xoffset or yoffset)", dimensions);
+ return GL_TRUE;
+ }
+ /* size must be multiple of 4 or equal to whole texture size */
+ if ((width & 3) && (GLuint) width != destTex->Width) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%D(width)", dimensions);
+ return GL_TRUE;
+ }
+ if ((height & 3) && (GLuint) height != destTex->Height) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%D(width)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glCopyTexImage[12]D() parameters for errors.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ * \param internalFormat internal format given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ * \param border texture border.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ *
+ * Verifies each of the parameters against the constants specified in
+ * __GLcontextRec::Const and the supported extensions, and according to the
+ * OpenGL specification.
+ */
+static GLboolean
+copytexture_error_check( GLcontext *ctx, GLuint dimensions,
+ GLenum target, GLint level, GLint internalFormat,
+ GLint width, GLint height, GLint border )
+{
+ GLenum type;
+ GLboolean sizeOK;
+ GLint format;
+
+ /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%dD(level=%d)", dimensions, level);
+ return GL_TRUE;
+ }
+
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* Check border */
+ if (border < 0 || border > 1 ||
+ ((target == GL_TEXTURE_RECTANGLE_NV ||
+ target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
+ return GL_TRUE;
+ }
+
+ format = _mesa_base_tex_format(ctx, internalFormat);
+ if (format < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage%dD(internalFormat)", dimensions);
+ return GL_TRUE;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(missing readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+
+ /* NOTE: the format and type aren't really significant for
+ * TestProxyTexImage(). Only the internalformat really matters.
+ */
+ type = GL_FLOAT;
+
+ /* Check target and call ctx->Driver.TestProxyTexImage() to check the
+ * level, width, height and depth.
+ */
+ if (dimensions == 1) {
+ if (target == GL_TEXTURE_1D) {
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
+ level, internalFormat,
+ format, type,
+ width, 1, 1, border);
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 2) {
+ if (target == GL_TEXTURE_2D) {
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
+ level, internalFormat,
+ format, type,
+ width, height, 1, border);
+ }
+ else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
+ return GL_TRUE;
+ }
+ sizeOK = (width == height) &&
+ ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
+ level, internalFormat, format, type,
+ width, height, 1, border);
+ }
+ else if (target == GL_TEXTURE_RECTANGLE_NV) {
+ if (!ctx->Extensions.NV_texture_rectangle) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
+ return GL_TRUE;
+ }
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx,
+ GL_PROXY_TEXTURE_RECTANGLE_NV,
+ level, internalFormat,
+ format, type,
+ width, height, 1, border);
+ }
+ else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
+ if (!ctx->Extensions.MESA_texture_array) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
+ return GL_TRUE;
+ }
+ sizeOK = ctx->Driver.TestProxyTexImage(ctx,
+ GL_PROXY_TEXTURE_1D_ARRAY_EXT,
+ level, internalFormat,
+ format, type,
+ width, height, 1, border);
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
+ return GL_TRUE;
+ }
+
+ if (!sizeOK) {
+ if (dimensions == 1) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage1D(width=%d)", width);
+ }
+ else {
+ ASSERT(dimensions == 2);
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexImage2D(width=%d, height=%d)", width, height);
+ }
+ return GL_TRUE;
+ }
+
+ if (is_compressed_format(ctx, internalFormat)) {
+ if (!target_can_be_compressed(ctx, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyTexImage%d(target)", dimensions);
+ return GL_TRUE;
+ }
+ if (border != 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%D(border!=0)", dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depth_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%D(no depth)", dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (_mesa_is_depthstencil_format(internalFormat)) {
+ /* make sure we have depth/stencil buffers */
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%D(no depth/stencil buffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/**
+ * Test glCopyTexSubImage[12]D() parameters for errors.
+ * Note that this is the first part of error checking.
+ * See also copytexsubimage_error_check2() below for the second part.
+ *
+ * \param ctx GL context.
+ * \param dimensions texture image dimensions (must be 1, 2 or 3).
+ * \param target texture target given by the user.
+ * \param level image level given by the user.
+ *
+ * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
+ */
+static GLboolean
+copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
+ GLenum target, GLint level)
+{
+ /* Check that the source buffer is complete */
+ if (ctx->ReadBuffer->Name) {
+ _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glCopyTexImage%dD(invalid readbuffer)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* Check target */
+ if (dimensions == 1) {
+ if (target != GL_TEXTURE_1D) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 2) {
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_TEXTURE_RECTANGLE_NV) {
+ if (!ctx->Extensions.NV_texture_rectangle) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
+ if (!ctx->Extensions.MESA_texture_array) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (target != GL_TEXTURE_2D) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 3) {
+ if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
+ (!ctx->Extensions.MESA_texture_array))
+ && (target != GL_TEXTURE_3D)) {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
+ return GL_TRUE;
+ }
+ }
+
+ /* Check level */
+ if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(level=%d)", dimensions, level);
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Second part of error checking for glCopyTexSubImage[12]D().
+ * \param xoffset sub-image x offset given by the user.
+ * \param yoffset sub-image y offset given by the user.
+ * \param zoffset sub-image z offset given by the user.
+ * \param width image width given by the user.
+ * \param height image height given by the user.
+ */
+static GLboolean
+copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height,
+ const struct gl_texture_image *teximage )
+{
+ /* check that dest tex image exists */
+ if (!teximage) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(undefined texture level: %d)",
+ dimensions, level);
+ return GL_TRUE;
+ }
+
+ /* Check size */
+ if (width < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(width=%d)", dimensions, width);
+ return GL_TRUE;
+ }
+ if (dimensions > 1 && height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(height=%d)", dimensions, height);
+ return GL_TRUE;
+ }
+
+ /* check x/y offsets */
+ if (xoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
+ return GL_TRUE;
+ }
+ if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(xoffset+width)", dimensions);
+ return GL_TRUE;
+ }
+ if (dimensions > 1) {
+ if (yoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
+ return GL_TRUE;
+ }
+ /* NOTE: we're adding the border here, not subtracting! */
+ if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(yoffset+height)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* check z offset */
+ if (dimensions > 2) {
+ if (zoffset < -((GLint)teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(zoffset)", dimensions);
+ return GL_TRUE;
+ }
+ if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ if (teximage->IsCompressed) {
+ if (!target_can_be_compressed(ctx, target)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glCopyTexSubImage%d(target)", dimensions);
+ return GL_TRUE;
+ }
+ /* offset must be multiple of 4 */
+ if ((xoffset & 3) || (yoffset & 3)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%D(xoffset or yoffset)", dimensions);
+ return GL_TRUE;
+ }
+ /* size must be multiple of 4 */
+ if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%D(width)", dimensions);
+ return GL_TRUE;
+ }
+ if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage%D(height)", dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ if (teximage->InternalFormat == GL_YCBCR_MESA) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
+ return GL_TRUE;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
+ dimensions, teximage->_BaseFormat);
+ return GL_TRUE;
+ }
+
+ if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ if (!ctx->ReadBuffer->_DepthBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%D(no depth buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+ else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%D(no depth/stencil buffer)",
+ dimensions);
+ return GL_TRUE;
+ }
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+/** Callback info for walking over FBO hash table */
+struct cb_info
+{
+ GLcontext *ctx;
+ struct gl_texture_object *texObj;
+ GLuint level, face;
+};
+
+
+/**
+ * Check render to texture callback. Called from _mesa_HashWalk().
+ */
+static void
+check_rtt_cb(GLuint key, void *data, void *userData)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ const struct cb_info *info = (struct cb_info *) userData;
+ GLcontext *ctx = info->ctx;
+ const struct gl_texture_object *texObj = info->texObj;
+ const GLuint level = info->level, face = info->face;
+
+ /* If this is a user-created FBO */
+ if (fb->Name) {
+ GLuint i;
+ /* check if any of the FBO's attachments point to 'texObj' */
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ if (att->Type == GL_TEXTURE &&
+ att->Texture == texObj &&
+ att->TextureLevel == level &&
+ att->CubeMapFace == face) {
+ ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
+ /* Tell driver about the new renderbuffer texture */
+ ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
+ /* Mark fb status as indeterminate to force re-validation */
+ fb->_Status = 0;
+ }
+ }
+ }
+}
+
+
+/**
+ * When a texture image is specified we have to check if it's bound to
+ * any framebuffer objects (render to texture) in order to detect changes
+ * in size or format since that effects FBO completeness.
+ * Any FBOs rendering into the texture must be re-validated.
+ */
+static void
+update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
+{
+ /* Only check this texture if it's been marked as RenderToTexture */
+ if (texObj->_RenderToTexture) {
+ struct cb_info info;
+ info.ctx = ctx;
+ info.texObj = texObj;
+ info.level = level;
+ info.face = face;
+ _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
+ }
+}
+
+
+/** Debug helper: override the user-requested internal format */
+static GLenum
+override_internal_format(GLenum internalFormat, GLint width, GLint height)
+{
+#if 0
+ if (internalFormat == GL_RGBA16F_ARB ||
+ internalFormat == GL_RGBA32F_ARB) {
+ printf("Convert rgba float tex to int %d x %d\n", width, height);
+ return GL_RGBA;
+ }
+ else if (internalFormat == GL_RGB16F_ARB ||
+ internalFormat == GL_RGB32F_ARB) {
+ printf("Convert rgb float tex to int %d x %d\n", width, height);
+ return GL_RGB;
+ }
+ else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
+ internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE_ALPHA;
+ }
+ else if (internalFormat == GL_LUMINANCE16F_ARB ||
+ internalFormat == GL_LUMINANCE32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_LUMINANCE;
+ }
+ else if (internalFormat == GL_ALPHA16F_ARB ||
+ internalFormat == GL_ALPHA32F_ARB) {
+ printf("Convert luminance float tex to int %d x %d\n", width, height);
+ return GL_ALPHA;
+ }
+ /*
+ else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
+ internalFormat = GL_RGBA;
+ }
+ */
+ else {
+ return internalFormat;
+ }
+#else
+ return internalFormat;
+#endif
+}
+
+
+/*
+ * Called from the API. Note that width includes the border.
+ */
+void GLAPIENTRY
+_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, const GLvoid *pixels )
+{
+ GLsizei postConvWidth = width;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat), width, border,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ internalFormat = override_internal_format(internalFormat, width, 1);
+
+#if FEATURE_convolve
+ if (_mesa_is_color_format(internalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
+ }
+#endif
+
+ if (target == GL_TEXTURE_1D) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ if (texture_error_check(ctx, target, level, internalFormat,
+ format, type, 1, postConvWidth, 1, 1, border)) {
+ return; /* error was recorded */
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+
+ clear_teximage_fields(texImage); /* not really needed, but helpful */
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ postConvWidth, 1, 1,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.TexImage1D);
+
+ /* Give the texture to the driver! <pixels> may be null! */
+ (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
+ width, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ ASSERT(texImage->TexFormat);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_1D) {
+ /* Proxy texture: check for errors and update proxy state */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texture_error_check(ctx, target, level, internalFormat,
+ format, type, 1, postConvWidth, 1, 1, border)) {
+ /* when error, clear all proxy texture image parameters */
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error, set the tex image parameters */
+ ASSERT(texImage);
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ postConvWidth, 1, 1,
+ border, internalFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GLsizei postConvWidth = width, postConvHeight = height;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat), width, height,
+ border, _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ internalFormat = override_internal_format(internalFormat, width, height);
+
+#if FEATURE_convolve
+ if (_mesa_is_color_format(internalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
+ &postConvHeight);
+ }
+#endif
+
+ if (target == GL_TEXTURE_2D ||
+ (ctx->Extensions.ARB_texture_cube_map &&
+ target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
+ (ctx->Extensions.NV_texture_rectangle &&
+ target == GL_TEXTURE_RECTANGLE_NV) ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_TEXTURE_1D_ARRAY_EXT)) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ if (texture_error_check(ctx, target, level, internalFormat,
+ format, type, 2, postConvWidth, postConvHeight,
+ 1, border)) {
+ return; /* error was recorded */
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+ clear_teximage_fields(texImage); /* not really needed, but helpful */
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ postConvWidth, postConvHeight, 1,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.TexImage2D);
+
+ /* Give the texture to the driver! <pixels> may be null! */
+ (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ ASSERT(texImage->TexFormat);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_2D ||
+ (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
+ ctx->Extensions.ARB_texture_cube_map) ||
+ (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
+ ctx->Extensions.NV_texture_rectangle) ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
+ /* Proxy texture: check for errors and update proxy state */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texture_error_check(ctx, target, level, internalFormat,
+ format, type, 2, postConvWidth, postConvHeight,
+ 1, border)) {
+ /* when error, clear all proxy texture image parameters */
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error, set the tex image parameters */
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ postConvWidth, postConvHeight, 1,
+ border, internalFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ }
+ }
+ else {
+ _mesa_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 GLAPIENTRY
+_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat), width, height,
+ depth, border, _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ internalFormat = override_internal_format(internalFormat, width, height);
+
+ if (target == GL_TEXTURE_3D ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_TEXTURE_2D_ARRAY_EXT)) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ const GLuint face = _mesa_tex_target_to_face(target);
+
+ if (texture_error_check(ctx, target, level, (GLint) internalFormat,
+ format, type, 3, width, height, depth, border)) {
+ return; /* error was recorded */
+ }
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+ clear_teximage_fields(texImage); /* not really needed, but helpful */
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ width, height, depth,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.TexImage3D);
+
+ /* Give the texture to the driver! <pixels> may be null! */
+ (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
+ width, height, depth, border, format, type,
+ pixels, &ctx->Unpack, texObj, texImage);
+
+ ASSERT(texImage->TexFormat);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_3D ||
+ (ctx->Extensions.MESA_texture_array &&
+ target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
+ /* Proxy texture: check for errors and update proxy state */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texture_error_check(ctx, target, level, internalFormat,
+ format, type, 3, width, height, depth, border)) {
+ /* when error, clear all proxy texture image parameters */
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* no error, set the tex image parameters */
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ }
+ }
+ else {
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
+ depth, border, format, type, pixels);
+}
+
+
+
+void GLAPIENTRY
+_mesa_TexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GLsizei postConvWidth = width;
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ xoffset, width, _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+#if FEATURE_convolve
+ /* XXX should test internal format */
+ if (_mesa_is_color_format(format)) {
+ _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
+ }
+#endif
+
+ if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
+ postConvWidth, 1, 1, format, type)) {
+ return; /* error was detected */
+ }
+
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ assert(texObj);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
+ postConvWidth, 1, 1, format, type, texImage)) {
+ goto out; /* error was detected */
+ }
+
+ if (width == 0)
+ goto out; /* no-op, not an error */
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+
+ ASSERT(ctx->Driver.TexSubImage1D);
+ (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
+ format, type, pixels, &ctx->Unpack,
+ texObj, texImage);
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_TexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GLsizei postConvWidth = width, postConvHeight = height;
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ xoffset, yoffset, width, height,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+#if FEATURE_convolve
+ /* XXX should test internal format */
+ if (_mesa_is_color_format(format)) {
+ _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
+ &postConvHeight);
+ }
+#endif
+
+ if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
+ postConvWidth, postConvHeight, 1, format, type)) {
+ return; /* error was detected */
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
+ postConvWidth, postConvHeight, 1, format, type,
+ texImage)) {
+ goto out; /* error was detected */
+ }
+
+ if (width == 0 || height == 0)
+ goto out; /* no-op, not an error */
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+ yoffset += texImage->Border;
+
+ ASSERT(ctx->Driver.TexSubImage2D);
+ (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
+ width, height, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_TexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ xoffset, yoffset, zoffset, width, height, depth,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type), pixels);
+
+ if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ _mesa_update_state(ctx);
+
+ if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type)) {
+ return; /* error was detected */
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+ if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type, texImage)) {
+ goto out; /* error was detected */
+ }
+
+ if (width == 0 || height == 0 || height == 0)
+ goto out; /* no-op, not an error */
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+ yoffset += texImage->Border;
+ zoffset += texImage->Border;
+
+ ASSERT(ctx->Driver.TexSubImage3D);
+ (*ctx->Driver.TexSubImage3D)(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, type, pixels,
+ &ctx->Unpack, texObj, texImage );
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexImage1D( GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLsizei postConvWidth = width;
+ const GLuint face = _mesa_tex_target_to_face(target);
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ x, y, width, border);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+#if FEATURE_convolve
+ if (_mesa_is_color_format(internalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
+ }
+#endif
+
+ if (copytexture_error_check(ctx, 1, target, level, internalFormat,
+ postConvWidth, 1, border))
+ return;
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+
+ clear_teximage_fields(texImage); /* not really needed, but helpful */
+ _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
+ border, internalFormat);
+
+
+ ASSERT(ctx->Driver.CopyTexImage1D);
+ (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
+ x, y, width, border);
+
+ ASSERT(texImage->TexFormat);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLsizei postConvWidth = width, postConvHeight = height;
+ const GLuint face = _mesa_tex_target_to_face(target);
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ x, y, width, height, border);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+#if FEATURE_convolve
+ if (_mesa_is_color_format(internalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
+ &postConvHeight);
+ }
+#endif
+
+ if (copytexture_error_check(ctx, 2, target, level, internalFormat,
+ postConvWidth, postConvHeight, border))
+ return;
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+
+ ASSERT(texImage->Data == NULL);
+
+ clear_teximage_fields(texImage); /* not really needed, but helpful */
+ _mesa_init_teximage_fields(ctx, target, texImage,
+ postConvWidth, postConvHeight, 1,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.CopyTexImage2D);
+ (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
+ x, y, width, height, border);
+
+ ASSERT(texImage->TexFormat);
+
+ update_fbo_texture(ctx, texObj, face, level);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLsizei postConvWidth = width;
+ GLint yoffset = 0;
+ GLsizei height = 1;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, x, y, width);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+ if (copytexsubimage_error_check1(ctx, 1, target, level))
+ return;
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+#if FEATURE_convolve
+ if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
+ }
+#endif
+
+ if (copytexsubimage_error_check2(ctx, 1, target, level,
+ xoffset, 0, 0, postConvWidth, 1,
+ texImage))
+ goto out;
+
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+
+ if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
+ &width, &height)) {
+ ASSERT(ctx->Driver.CopyTexSubImage1D);
+ ctx->Driver.CopyTexSubImage1D(ctx, target, level,
+ xoffset, x, y, width);
+ }
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLsizei postConvWidth = width, postConvHeight = height;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, yoffset, x, y, width, height);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+ if (copytexsubimage_error_check1(ctx, 2, target, level))
+ return;
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+#if FEATURE_convolve
+ if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 2,
+ &postConvWidth, &postConvHeight);
+ }
+#endif
+
+ if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
+ postConvWidth, postConvHeight, texImage))
+ goto out;
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+ yoffset += texImage->Border;
+
+ if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
+ &width, &height)) {
+ ASSERT(ctx->Driver.CopyTexSubImage2D);
+ ctx->Driver.CopyTexSubImage2D(ctx, target, level,
+ xoffset, yoffset, x, y, width, height);
+ }
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_CopyTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLsizei postConvWidth = width, postConvHeight = height;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
+ _mesa_lookup_enum_by_nr(target),
+ level, xoffset, yoffset, zoffset, x, y, width, height);
+
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
+ _mesa_update_state(ctx);
+
+ if (copytexsubimage_error_check1(ctx, 3, target, level))
+ return;
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+#if FEATURE_convolve
+ if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
+ _mesa_adjust_image_for_convolution(ctx, 2,
+ &postConvWidth, &postConvHeight);
+ }
+#endif
+
+ if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
+ zoffset, postConvWidth, postConvHeight,
+ texImage))
+ goto out;
+
+ /* If we have a border, xoffset=-1 is legal. Bias by border width */
+ xoffset += texImage->Border;
+ yoffset += texImage->Border;
+ zoffset += texImage->Border;
+
+ if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
+ &width, &height)) {
+ ASSERT(ctx->Driver.CopyTexSubImage3D);
+ ctx->Driver.CopyTexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ x, y, width, height);
+ }
+
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+
+/**********************************************************************/
+/****** Compressed Textures ******/
+/**********************************************************************/
+
+
+/**
+ * Error checking for glCompressedTexImage[123]D().
+ * \return error code or GL_NO_ERROR.
+ */
+static GLenum
+compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
+ GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize)
+{
+ GLint expectedSize, maxLevels = 0, maxTextureSize;
+
+ if (dimensions == 1) {
+ /* 1D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+ else if (dimensions == 2) {
+ if (target == GL_PROXY_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else {
+ return GL_INVALID_ENUM; /*target*/
+ }
+ }
+ else if (dimensions == 3) {
+ /* 3D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+
+ maxTextureSize = 1 << (maxLevels - 1);
+
+ /* This will detect any invalid internalFormat value */
+ if (!is_compressed_format(ctx, internalFormat))
+ return GL_INVALID_ENUM;
+
+ /* This should really never fail */
+ if (_mesa_base_tex_format(ctx, internalFormat) < 0)
+ return GL_INVALID_ENUM;
+
+ if (border != 0)
+ return GL_INVALID_VALUE;
+
+ /*
+ * XXX We should probably use the proxy texture error check function here.
+ */
+ if (width < 1 || width > maxTextureSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
+ return GL_INVALID_VALUE;
+
+ if ((height < 1 || height > maxTextureSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
+ && dimensions > 1)
+ return GL_INVALID_VALUE;
+
+ if ((depth < 1 || depth > maxTextureSize ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
+ && dimensions > 2)
+ return GL_INVALID_VALUE;
+
+ /* For cube map, width must equal height */
+ if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
+ return GL_INVALID_VALUE;
+
+ if (level < 0 || level >= maxLevels)
+ return GL_INVALID_VALUE;
+
+ expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
+ depth, internalFormat);
+ if (expectedSize != imageSize)
+ return GL_INVALID_VALUE;
+
+#if FEATURE_EXT_texture_sRGB
+ if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
+ internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
+ internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
+ internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
+ && border != 0) {
+ return GL_INVALID_OPERATION;
+ }
+#endif
+
+ return GL_NO_ERROR;
+}
+
+
+/**
+ * Error checking for glCompressedTexSubImage[123]D().
+ * \warning There are some bad assumptions here about the size of compressed
+ * texture tiles (multiple of 4) used to test the validity of the
+ * offset and size parameters.
+ * \return error code or GL_NO_ERROR.
+ */
+static GLenum
+compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize)
+{
+ GLint expectedSize, maxLevels = 0, maxTextureSize;
+ (void) zoffset;
+
+ if (dimensions == 1) {
+ /* 1D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+ else if (dimensions == 2) {
+ if (target == GL_PROXY_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_TEXTURE_2D) {
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
+ if (!ctx->Extensions.ARB_texture_cube_map)
+ return GL_INVALID_ENUM; /*target*/
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else {
+ return GL_INVALID_ENUM; /*target*/
+ }
+ }
+ else if (dimensions == 3) {
+ /* 3D compressed textures not allowed */
+ return GL_INVALID_ENUM;
+ }
+
+ maxTextureSize = 1 << (maxLevels - 1);
+
+ /* this will catch any invalid compressed format token */
+ if (!is_compressed_format(ctx, format))
+ return GL_INVALID_ENUM;
+
+ if (width < 1 || width > maxTextureSize)
+ return GL_INVALID_VALUE;
+
+ if ((height < 1 || height > maxTextureSize)
+ && dimensions > 1)
+ return GL_INVALID_VALUE;
+
+ if (level < 0 || level >= maxLevels)
+ return GL_INVALID_VALUE;
+
+ /* XXX these tests are specific to the compressed format.
+ * this code should be generalized in some way.
+ */
+ if ((xoffset & 3) != 0 || (yoffset & 3) != 0)
+ return GL_INVALID_VALUE;
+
+ if ((width & 3) != 0 && width != 2 && width != 1)
+ return GL_INVALID_VALUE;
+
+ if ((height & 3) != 0 && height != 2 && height != 1)
+ return GL_INVALID_VALUE;
+
+ expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height,
+ depth, format);
+ if (expectedSize != imageSize)
+ return GL_INVALID_VALUE;
+
+ return GL_NO_ERROR;
+}
+
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, border, imageSize, data);
+
+ if (target == GL_TEXTURE_1D) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error = compressed_texture_error_check(ctx, 1, target, level,
+ internalFormat, width, 1, 1, border, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexImage1D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+ ASSERT(texImage->Data == NULL);
+
+ _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.CompressedTexImage1D);
+ (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
+ internalFormat, width, border,
+ imageSize, data,
+ texObj, texImage);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_1D) {
+ /* Proxy texture: check for errors and update proxy state */
+ GLenum error = compressed_texture_error_check(ctx, 1, target, level,
+ internalFormat, width, 1, 1, border, imageSize);
+ if (!error) {
+ ASSERT(ctx->Driver.TestProxyTexImage);
+ error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
+ internalFormat, GL_NONE, GL_NONE,
+ width, 1, 1, border);
+ }
+ if (error) {
+ /* if error, clear all proxy texture image parameters */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* store the teximage parameters */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+ border, internalFormat);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, border, imageSize, data);
+
+ if (target == GL_TEXTURE_2D ||
+ (ctx->Extensions.ARB_texture_cube_map &&
+ target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
+ target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error = compressed_texture_error_check(ctx, 2, target, level,
+ internalFormat, width, height, 1, border, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexImage2D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+ ASSERT(texImage->Data == NULL);
+
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.CompressedTexImage2D);
+ (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
+ internalFormat, width, height,
+ border, imageSize, data,
+ texObj, texImage);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_2D ||
+ (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
+ ctx->Extensions.ARB_texture_cube_map)) {
+ /* Proxy texture: check for errors and update proxy state */
+ GLenum error = compressed_texture_error_check(ctx, 2, target, level,
+ internalFormat, width, height, 1, border, imageSize);
+ if (!error) {
+ ASSERT(ctx->Driver.TestProxyTexImage);
+ error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
+ internalFormat, GL_NONE, GL_NONE,
+ width, height, 1, border);
+ }
+ if (error) {
+ /* if error, clear all proxy texture image parameters */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* store the teximage parameters */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+ border, internalFormat);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *data)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
+ _mesa_lookup_enum_by_nr(target), level,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, depth, border, imageSize, data);
+
+ if (target == GL_TEXTURE_3D) {
+ /* non-proxy target */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error = compressed_texture_error_check(ctx, 3, target, level,
+ internalFormat, width, height, depth, border, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexImage3D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
+ goto out;
+ }
+
+ if (texImage->Data) {
+ ctx->Driver.FreeTexImageData( ctx, texImage );
+ }
+ ASSERT(texImage->Data == NULL);
+
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
+ border, internalFormat);
+
+ ASSERT(ctx->Driver.CompressedTexImage3D);
+ (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
+ internalFormat,
+ width, height, depth,
+ border, imageSize, data,
+ texObj, texImage);
+
+ /* state update */
+ texObj->_Complete = GL_FALSE;
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ else if (target == GL_PROXY_TEXTURE_3D) {
+ /* Proxy texture: check for errors and update proxy state */
+ GLenum error = compressed_texture_error_check(ctx, 3, target, level,
+ internalFormat, width, height, depth, border, imageSize);
+ if (!error) {
+ ASSERT(ctx->Driver.TestProxyTexImage);
+ error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
+ internalFormat, GL_NONE, GL_NONE,
+ width, height, depth, border);
+ }
+ if (error) {
+ /* if error, clear all proxy texture image parameters */
+ struct gl_texture_image *texImage;
+ texImage = _mesa_get_proxy_tex_image(ctx, target, level);
+ if (texImage)
+ clear_teximage_fields(texImage);
+ }
+ else {
+ /* store the teximage parameters */
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ depth, border, internalFormat);
+ }
+ _mesa_unlock_texture(ctx, texObj);
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid *data)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ error = compressed_subtexture_error_check(ctx, 1, target, level,
+ xoffset, 0, 0, /* pos */
+ width, 1, 1, /* size */
+ format, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexSubImage1D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ assert(texImage);
+
+ if ((GLint) format != texImage->InternalFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTexSubImage1D(format)");
+ goto out;
+ }
+
+ if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
+ goto out;
+ }
+
+ if (width == 0)
+ goto out; /* no-op, not an error */
+
+ if (ctx->Driver.CompressedTexSubImage1D) {
+ (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
+ xoffset, width,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid *data)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ error = compressed_subtexture_error_check(ctx, 2, target, level,
+ xoffset, yoffset, 0, /* pos */
+ width, height, 1, /* size */
+ format, imageSize);
+ if (error) {
+ /* XXX proxy target? */
+ _mesa_error(ctx, error, "glCompressedTexSubImage2D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ assert(texImage);
+
+ if ((GLint) format != texImage->InternalFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTexSubImage2D(format)");
+ goto out;
+ }
+
+ if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
+ ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
+ goto out;
+ }
+
+ if (width == 0 || height == 0)
+ goto out; /* no-op, not an error */
+
+ if (ctx->Driver.CompressedTexSubImage2D) {
+ (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
+ xoffset, yoffset, width, height,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+void GLAPIENTRY
+_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum format,
+ GLsizei imageSize, const GLvoid *data)
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLenum error;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ error = compressed_subtexture_error_check(ctx, 3, target, level,
+ xoffset, yoffset, zoffset,/*pos*/
+ width, height, depth, /*size*/
+ format, imageSize);
+ if (error) {
+ _mesa_error(ctx, error, "glCompressedTexSubImage3D");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+ {
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ assert(texImage);
+
+ if ((GLint) format != texImage->InternalFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTexSubImage3D(format)");
+ goto out;
+ }
+
+ if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
+ ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
+ ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
+ goto out;
+ }
+
+ if (width == 0 || height == 0 || depth == 0)
+ goto out; /* no-op, not an error */
+
+ if (ctx->Driver.CompressedTexSubImage3D) {
+ (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
+ xoffset, yoffset, zoffset,
+ width, height, depth,
+ format, imageSize, data,
+ texObj, texImage);
+ }
+ ctx->NewState |= _NEW_TEXTURE;
+ }
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h
new file mode 100644
index 000000000..094177da7
--- /dev/null
+++ b/mesalib/src/mesa/main/teximage.h
@@ -0,0 +1,260 @@
+/**
+ * \file teximage.h
+ * Texture images manipulation functions.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 "mtypes.h"
+
+
+extern void *
+_mesa_alloc_texmemory(GLsizei bytes);
+
+extern void
+_mesa_free_texmemory(void *m);
+
+
+/** \name Internal functions */
+/*@{*/
+
+extern GLint
+_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat );
+
+
+extern GLboolean
+_mesa_is_proxy_texture(GLenum target);
+
+
+extern struct gl_texture_image *
+_mesa_new_texture_image( GLcontext *ctx );
+
+
+extern void
+_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *teximage );
+
+extern void
+_mesa_free_texture_image_data( GLcontext *ctx,
+ struct gl_texture_image *texImage );
+
+
+extern void
+_mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
+ struct gl_texture_image *img,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum internalFormat);
+
+
+extern void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_set_tex_image(struct gl_texture_object *tObj,
+ GLenum target, GLint level,
+ struct gl_texture_image *texImage);
+
+
+extern struct gl_texture_object *
+_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+ GLenum target);
+
+
+extern struct gl_texture_image *
+_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
+ GLenum target, GLint level);
+
+
+extern struct gl_texture_image *
+_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLenum target, GLint level);
+
+
+extern struct gl_texture_image *
+_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level);
+
+
+extern GLint
+_mesa_max_texture_levels(GLcontext *ctx, GLenum target);
+
+
+extern GLboolean
+_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint width, GLint height, GLint depth, GLint border);
+
+
+extern GLuint
+_mesa_tex_target_to_face(GLenum target);
+
+
+/**
+ * Lock a texture for updating. See also _mesa_lock_context_textures().
+ */
+static INLINE void
+_mesa_lock_texture(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
+ ctx->Shared->TextureStateStamp++;
+ (void) texObj;
+}
+
+static INLINE void
+_mesa_unlock_texture(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
+}
+
+/*@}*/
+
+
+/** \name API entry point functions */
+/*@{*/
+
+extern void GLAPIENTRY
+_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexImage2D( GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexImage3D( GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_TexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+extern void GLAPIENTRY
+_mesa_CopyTexImage1D( GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLint border );
+
+
+extern void GLAPIENTRY
+_mesa_CopyTexImage2D( GLenum target, GLint level,
+ GLenum internalformat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border );
+
+
+extern void GLAPIENTRY
+_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset,
+ GLint x, GLint y, GLsizei width );
+
+
+extern void GLAPIENTRY
+_mesa_CopyTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+extern void GLAPIENTRY
+_mesa_CopyTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+
+extern void GLAPIENTRY
+_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
+ GLenum internalformat, GLsizei width,
+ GLint border, GLsizei imageSize,
+ const GLvoid *data);
+
+extern void GLAPIENTRY
+_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
+ GLenum internalformat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid *data);
+
+extern void GLAPIENTRY
+_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
+ GLenum internalformat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *data);
+
+#ifdef VMS
+#define _mesa_CompressedTexSubImage1DARB _mesa_CompressedTexSubImage1DAR
+#define _mesa_CompressedTexSubImage2DARB _mesa_CompressedTexSubImage2DAR
+#define _mesa_CompressedTexSubImage3DARB _mesa_CompressedTexSubImage3DAR
+#endif
+extern void GLAPIENTRY
+_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid *data);
+
+extern void GLAPIENTRY
+_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid *data);
+
+extern void GLAPIENTRY
+_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum format,
+ GLsizei imageSize, const GLvoid *data);
+
+/*@}*/
+
+#endif
diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c
new file mode 100644
index 000000000..d09c43925
--- /dev/null
+++ b/mesalib/src/mesa/main/texobj.c
@@ -0,0 +1,1237 @@
+/**
+ * \file texobj.c
+ * Texture object management.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "mfeatures.h"
+#if FEATURE_colortable
+#include "colortab.h"
+#endif
+#include "context.h"
+#include "enums.h"
+#include "fbobject.h"
+#include "hash.h"
+#include "imports.h"
+#include "macros.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "texobj.h"
+#include "mtypes.h"
+#include "shader/prog_instruction.h"
+
+
+
+/**********************************************************************/
+/** \name Internal functions */
+/*@{*/
+
+
+/**
+ * Return the gl_texture_object for a given ID.
+ */
+struct gl_texture_object *
+_mesa_lookup_texture(GLcontext *ctx, GLuint id)
+{
+ return (struct gl_texture_object *)
+ _mesa_HashLookup(ctx->Shared->TexObjects, id);
+}
+
+
+
+/**
+ * Allocate and initialize a new texture object. But don't put it into the
+ * texture object hash table.
+ *
+ * Called via ctx->Driver.NewTextureObject, unless overridden by a device
+ * driver.
+ *
+ * \param shared the shared GL state structure to contain the texture object
+ * \param name integer name for the texture object
+ * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
+ * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV. zero is ok for the sake
+ * of GenTextures()
+ *
+ * \return pointer to new texture object.
+ */
+struct gl_texture_object *
+_mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct gl_texture_object *obj;
+ (void) ctx;
+ obj = MALLOC_STRUCT(gl_texture_object);
+ _mesa_initialize_texture_object(obj, name, target);
+ return obj;
+}
+
+
+/**
+ * Initialize a new texture object to default values.
+ * \param obj the texture object
+ * \param name the texture name
+ * \param target the texture target
+ */
+void
+_mesa_initialize_texture_object( struct gl_texture_object *obj,
+ GLuint name, GLenum target )
+{
+ ASSERT(target == 0 ||
+ target == GL_TEXTURE_1D ||
+ target == GL_TEXTURE_2D ||
+ target == GL_TEXTURE_3D ||
+ target == GL_TEXTURE_CUBE_MAP_ARB ||
+ target == GL_TEXTURE_RECTANGLE_NV ||
+ target == GL_TEXTURE_1D_ARRAY_EXT ||
+ target == GL_TEXTURE_2D_ARRAY_EXT);
+
+ _mesa_bzero(obj, sizeof(*obj));
+ /* init the non-zero fields */
+ _glthread_INIT_MUTEX(obj->Mutex);
+ obj->RefCount = 1;
+ obj->Name = name;
+ obj->Target = target;
+ obj->Priority = 1.0F;
+ if (target == GL_TEXTURE_RECTANGLE_NV) {
+ obj->WrapS = GL_CLAMP_TO_EDGE;
+ obj->WrapT = GL_CLAMP_TO_EDGE;
+ obj->WrapR = GL_CLAMP_TO_EDGE;
+ obj->MinFilter = GL_LINEAR;
+ }
+ else {
+ obj->WrapS = GL_REPEAT;
+ obj->WrapT = GL_REPEAT;
+ obj->WrapR = GL_REPEAT;
+ obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
+ }
+ obj->MagFilter = GL_LINEAR;
+ obj->MinLod = -1000.0;
+ obj->MaxLod = 1000.0;
+ obj->LodBias = 0.0;
+ obj->BaseLevel = 0;
+ obj->MaxLevel = 1000;
+ obj->MaxAnisotropy = 1.0;
+ obj->CompareMode = GL_NONE; /* ARB_shadow */
+ obj->CompareFunc = GL_LEQUAL; /* ARB_shadow */
+ obj->CompareFailValue = 0.0F; /* ARB_shadow_ambient */
+ obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */
+ obj->Swizzle[0] = GL_RED;
+ obj->Swizzle[1] = GL_GREEN;
+ obj->Swizzle[2] = GL_BLUE;
+ obj->Swizzle[3] = GL_ALPHA;
+ obj->_Swizzle = SWIZZLE_NOOP;
+}
+
+
+/**
+ * Some texture initialization can't be finished until we know which
+ * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
+ */
+static void
+finish_texture_init(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *obj)
+{
+ assert(obj->Target == 0);
+
+ if (target == GL_TEXTURE_RECTANGLE_NV) {
+ /* have to init wrap and filter state here - kind of klunky */
+ obj->WrapS = GL_CLAMP_TO_EDGE;
+ obj->WrapT = GL_CLAMP_TO_EDGE;
+ obj->WrapR = GL_CLAMP_TO_EDGE;
+ obj->MinFilter = GL_LINEAR;
+ if (ctx->Driver.TexParameter) {
+ static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
+ static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR};
+ ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
+ ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
+ ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
+ ctx->Driver.TexParameter(ctx, target, obj, GL_TEXTURE_MIN_FILTER, fparam_filter);
+ }
+ }
+}
+
+
+/**
+ * Deallocate a texture object struct. It should have already been
+ * removed from the texture object pool.
+ * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
+ *
+ * \param shared the shared GL state to which the object belongs.
+ * \param texObj the texture object to delete.
+ */
+void
+_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj )
+{
+ GLuint i, face;
+
+ (void) ctx;
+
+ /* Set Target to an invalid value. With some assertions elsewhere
+ * we can try to detect possible use of deleted textures.
+ */
+ texObj->Target = 0x99;
+
+#if FEATURE_colortable
+ _mesa_free_colortable_data(&texObj->Palette);
+#endif
+
+ /* free the texture images */
+ for (face = 0; face < 6; face++) {
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ if (texObj->Image[face][i]) {
+ _mesa_delete_texture_image( ctx, texObj->Image[face][i] );
+ }
+ }
+ }
+
+ /* destroy the mutex -- it may have allocated memory (eg on bsd) */
+ _glthread_DESTROY_MUTEX(texObj->Mutex);
+
+ /* free this object */
+ _mesa_free(texObj);
+}
+
+
+
+
+/**
+ * Copy texture object state from one texture object to another.
+ * Use for glPush/PopAttrib.
+ *
+ * \param dest destination texture object.
+ * \param src source texture object.
+ */
+void
+_mesa_copy_texture_object( struct gl_texture_object *dest,
+ const struct gl_texture_object *src )
+{
+ dest->Target = src->Target;
+ dest->Name = src->Name;
+ 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->LodBias = src->LodBias;
+ dest->BaseLevel = src->BaseLevel;
+ dest->MaxLevel = src->MaxLevel;
+ dest->MaxAnisotropy = src->MaxAnisotropy;
+ dest->CompareMode = src->CompareMode;
+ dest->CompareFunc = src->CompareFunc;
+ dest->CompareFailValue = src->CompareFailValue;
+ dest->DepthMode = src->DepthMode;
+ dest->_MaxLevel = src->_MaxLevel;
+ dest->_MaxLambda = src->_MaxLambda;
+ dest->GenerateMipmap = src->GenerateMipmap;
+ dest->Palette = src->Palette;
+ dest->_Complete = src->_Complete;
+ COPY_4V(dest->Swizzle, src->Swizzle);
+ dest->_Swizzle = src->_Swizzle;
+}
+
+
+/**
+ * Clear all texture images of the given texture object.
+ *
+ * \param ctx GL context.
+ * \param t texture object.
+ *
+ * \sa _mesa_clear_texture_image().
+ */
+void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ GLuint i, j;
+
+ if (texObj->Target == 0)
+ return;
+
+ for (i = 0; i < MAX_FACES; i++) {
+ for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
+ struct gl_texture_image *texImage = texObj->Image[i][j];
+ if (texImage)
+ _mesa_clear_texture_image(ctx, texImage);
+ }
+ }
+}
+
+
+/**
+ * Check if the given texture object is valid by examining its Target field.
+ * For debugging only.
+ */
+static GLboolean
+valid_texture_object(const struct gl_texture_object *tex)
+{
+ switch (tex->Target) {
+ case 0:
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return GL_TRUE;
+ case 0x99:
+ _mesa_problem(NULL, "invalid reference to a deleted texture object");
+ return GL_FALSE;
+ default:
+ _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
+ tex->Target, tex->Name);
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Reference (or unreference) a texture object.
+ * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
+ * If 'tex' is non-null, increment its refcount.
+ */
+void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+ struct gl_texture_object *tex)
+{
+ assert(ptr);
+ if (*ptr == tex) {
+ /* no change */
+ return;
+ }
+
+ if (*ptr) {
+ /* Unreference the old texture */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_texture_object *oldTex = *ptr;
+
+ ASSERT(valid_texture_object(oldTex));
+
+ _glthread_LOCK_MUTEX(oldTex->Mutex);
+ ASSERT(oldTex->RefCount > 0);
+ oldTex->RefCount--;
+
+ deleteFlag = (oldTex->RefCount == 0);
+ _glthread_UNLOCK_MUTEX(oldTex->Mutex);
+
+ if (deleteFlag) {
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx)
+ ctx->Driver.DeleteTexture(ctx, oldTex);
+ else
+ _mesa_problem(NULL, "Unable to delete texture, no context");
+ }
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (tex) {
+ /* reference new texture */
+ ASSERT(valid_texture_object(tex));
+ _glthread_LOCK_MUTEX(tex->Mutex);
+ if (tex->RefCount == 0) {
+ /* this texture's being deleted (look just above) */
+ /* Not sure this can every really happen. Warn if it does. */
+ _mesa_problem(NULL, "referencing deleted texture object");
+ *ptr = NULL;
+ }
+ else {
+ tex->RefCount++;
+ *ptr = tex;
+ }
+ _glthread_UNLOCK_MUTEX(tex->Mutex);
+ }
+}
+
+
+
+/**
+ * Report why a texture object is incomplete.
+ *
+ * \param t texture object.
+ * \param why string describing why it's incomplete.
+ *
+ * \note For debug purposes only.
+ */
+#if 0
+static void
+incomplete(const struct gl_texture_object *t, const char *why)
+{
+ _mesa_printf("Texture Obj %d incomplete because: %s\n", t->Name, why);
+}
+#else
+#define incomplete(t, why)
+#endif
+
+
+/**
+ * Examine a texture object to determine if it is complete.
+ *
+ * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
+ * accordingly.
+ *
+ * \param ctx GL context.
+ * \param t texture object.
+ *
+ * According to the texture target, verifies that each of the mipmaps is
+ * present and has the expected size.
+ */
+void
+_mesa_test_texobj_completeness( const GLcontext *ctx,
+ struct gl_texture_object *t )
+{
+ const GLint baseLevel = t->BaseLevel;
+ GLint maxLog2 = 0, maxLevels = 0;
+
+ t->_Complete = GL_TRUE; /* be optimistic */
+
+ /* Detect cases where the application set the base level to an invalid
+ * value.
+ */
+ if ((baseLevel < 0) || (baseLevel > MAX_TEXTURE_LEVELS)) {
+ char s[100];
+ _mesa_sprintf(s, "base level = %d is invalid", baseLevel);
+ incomplete(t, s);
+ t->_Complete = GL_FALSE;
+ return;
+ }
+
+ /* Always need the base level image */
+ if (!t->Image[0][baseLevel]) {
+ char s[100];
+ _mesa_sprintf(s, "Image[baseLevel=%d] == NULL", baseLevel);
+ incomplete(t, s);
+ t->_Complete = GL_FALSE;
+ return;
+ }
+
+ /* Check width/height/depth for zero */
+ if (t->Image[0][baseLevel]->Width == 0 ||
+ t->Image[0][baseLevel]->Height == 0 ||
+ t->Image[0][baseLevel]->Depth == 0) {
+ incomplete(t, "texture width = 0");
+ t->_Complete = GL_FALSE;
+ return;
+ }
+
+ /* Compute _MaxLevel */
+ if ((t->Target == GL_TEXTURE_1D) ||
+ (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
+ maxLog2 = t->Image[0][baseLevel]->WidthLog2;
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if ((t->Target == GL_TEXTURE_2D) ||
+ (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
+ maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
+ t->Image[0][baseLevel]->HeightLog2);
+ maxLevels = ctx->Const.MaxTextureLevels;
+ }
+ else if (t->Target == GL_TEXTURE_3D) {
+ GLint max = MAX2(t->Image[0][baseLevel]->WidthLog2,
+ t->Image[0][baseLevel]->HeightLog2);
+ maxLog2 = MAX2(max, (GLint)(t->Image[0][baseLevel]->DepthLog2));
+ maxLevels = ctx->Const.Max3DTextureLevels;
+ }
+ else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
+ maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2,
+ t->Image[0][baseLevel]->HeightLog2);
+ maxLevels = ctx->Const.MaxCubeTextureLevels;
+ }
+ else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
+ maxLog2 = 0; /* not applicable */
+ maxLevels = 1; /* no mipmapping */
+ }
+ else {
+ _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
+ return;
+ }
+
+ ASSERT(maxLevels > 0);
+
+ t->_MaxLevel = baseLevel + maxLog2;
+ t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel);
+ t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1);
+
+ /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */
+ t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel);
+
+ if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
+ /* make sure that all six cube map level 0 images are the same size */
+ const GLuint w = t->Image[0][baseLevel]->Width2;
+ const GLuint h = t->Image[0][baseLevel]->Height2;
+ GLuint face;
+ for (face = 1; face < 6; face++) {
+ if (t->Image[face][baseLevel] == NULL ||
+ t->Image[face][baseLevel]->Width2 != w ||
+ t->Image[face][baseLevel]->Height2 != h) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "Non-quare cubemap image");
+ return;
+ }
+ }
+ }
+
+ /* extra checking for mipmaps */
+ if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) {
+ /*
+ * Mipmapping: determine if we have a complete set of mipmaps
+ */
+ GLint i;
+ GLint minLevel = baseLevel;
+ GLint maxLevel = t->_MaxLevel;
+
+ if (minLevel > maxLevel) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "minLevel > maxLevel");
+ return;
+ }
+
+ /* Test dimension-independent attributes */
+ for (i = minLevel; i <= maxLevel; i++) {
+ if (t->Image[0][i]) {
+ if (t->Image[0][i]->TexFormat != t->Image[0][baseLevel]->TexFormat) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "Format[i] != Format[baseLevel]");
+ return;
+ }
+ if (t->Image[0][i]->Border != t->Image[0][baseLevel]->Border) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "Border[i] != Border[baseLevel]");
+ return;
+ }
+ }
+ }
+
+ /* Test things which depend on number of texture image dimensions */
+ if ((t->Target == GL_TEXTURE_1D) ||
+ (t->Target == GL_TEXTURE_1D_ARRAY_EXT)) {
+ /* Test 1-D mipmaps */
+ GLuint width = t->Image[0][baseLevel]->Width2;
+ for (i = baseLevel + 1; i < maxLevels; i++) {
+ if (width > 1) {
+ width /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[0][i]) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "1D Image[0][i] == NULL");
+ return;
+ }
+ if (t->Image[0][i]->Width2 != width ) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "1D Image[0][i] bad width");
+ return;
+ }
+ }
+ if (width == 1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ else if ((t->Target == GL_TEXTURE_2D) ||
+ (t->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
+ /* Test 2-D mipmaps */
+ GLuint width = t->Image[0][baseLevel]->Width2;
+ GLuint height = t->Image[0][baseLevel]->Height2;
+ for (i = baseLevel + 1; i < maxLevels; i++) {
+ if (width > 1) {
+ width /= 2;
+ }
+ if (height > 1) {
+ height /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[0][i]) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "2D Image[0][i] == NULL");
+ return;
+ }
+ if (t->Image[0][i]->Width2 != width) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "2D Image[0][i] bad width");
+ return;
+ }
+ if (t->Image[0][i]->Height2 != height) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "2D Image[0][i] bad height");
+ return;
+ }
+ if (width==1 && height==1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ }
+ else if (t->Target == GL_TEXTURE_3D) {
+ /* Test 3-D mipmaps */
+ GLuint width = t->Image[0][baseLevel]->Width2;
+ GLuint height = t->Image[0][baseLevel]->Height2;
+ GLuint depth = t->Image[0][baseLevel]->Depth2;
+ for (i = baseLevel + 1; i < maxLevels; i++) {
+ if (width > 1) {
+ width /= 2;
+ }
+ if (height > 1) {
+ height /= 2;
+ }
+ if (depth > 1) {
+ depth /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[0][i]) {
+ incomplete(t, "3D Image[0][i] == NULL");
+ t->_Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[0][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
+ return;
+ }
+ if (t->Image[0][i]->Width2 != width) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "3D Image[0][i] bad width");
+ return;
+ }
+ if (t->Image[0][i]->Height2 != height) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "3D Image[0][i] bad height");
+ return;
+ }
+ if (t->Image[0][i]->Depth2 != depth) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "3D Image[0][i] bad depth");
+ return;
+ }
+ }
+ if (width == 1 && height == 1 && depth == 1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
+ /* make sure 6 cube faces are consistant */
+ GLuint width = t->Image[0][baseLevel]->Width2;
+ GLuint height = t->Image[0][baseLevel]->Height2;
+ for (i = baseLevel + 1; i < maxLevels; i++) {
+ if (width > 1) {
+ width /= 2;
+ }
+ if (height > 1) {
+ height /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ GLuint face;
+ for (face = 0; face < 6; face++) {
+ /* check that we have images defined */
+ if (!t->Image[face][i]) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "CubeMap Image[n][i] == NULL");
+ return;
+ }
+ /* Don't support GL_DEPTH_COMPONENT for cube maps */
+ if (t->Image[face][i]->_BaseFormat == GL_DEPTH_COMPONENT) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex");
+ return;
+ }
+ /* check that all six images have same size */
+ if (t->Image[face][i]->Width2!=width ||
+ t->Image[face][i]->Height2!=height) {
+ t->_Complete = GL_FALSE;
+ incomplete(t, "CubeMap Image[n][i] bad size");
+ return;
+ }
+ }
+ }
+ if (width == 1 && height == 1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ else if (t->Target == GL_TEXTURE_RECTANGLE_NV) {
+ /* XXX special checking? */
+ }
+ else {
+ /* Target = ??? */
+ _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n");
+ }
+ }
+}
+
+
+/**
+ * Mark a texture object dirty. It forces the object to be incomplete
+ * and optionally forces the context to re-validate its state.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object.
+ * \param invalidate_state also invalidate context state.
+ */
+void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLboolean invalidate_state)
+{
+ texObj->_Complete = GL_FALSE;
+ if (invalidate_state)
+ ctx->NewState |= _NEW_TEXTURE;
+}
+
+
+/**
+ * Return pointer to a default/fallback texture.
+ * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
+ * That's the value a sampler should get when sampling from an
+ * incomplete texture.
+ */
+struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx)
+{
+ if (!ctx->Shared->FallbackTex) {
+ /* create fallback texture now */
+ static GLubyte texels[8 * 8][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLuint i;
+
+ for (i = 0; i < 8 * 8; i++) {
+ texels[i][0] =
+ texels[i][1] =
+ texels[i][2] = 0x0;
+ texels[i][3] = 0xff;
+ }
+
+ /* create texture object */
+ texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
+ assert(texObj->RefCount == 1);
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+
+ /* create level[0] texture image */
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
+
+ /* init the image fields */
+ _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
+ 8, 8, 1, 0, GL_RGBA);
+
+ /* set image data */
+ ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
+ 8, 8, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texels,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ _mesa_test_texobj_completeness(ctx, texObj);
+ assert(texObj->_Complete);
+
+ ctx->Shared->FallbackTex = texObj;
+ }
+ return ctx->Shared->FallbackTex;
+}
+
+
+/*@}*/
+
+
+/***********************************************************************/
+/** \name API functions */
+/*@{*/
+
+
+/**
+ * Generate texture names.
+ *
+ * \param n number of texture names to be generated.
+ * \param textures an array in which will hold the generated texture names.
+ *
+ * \sa glGenTextures().
+ *
+ * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
+ * IDs which are stored in \p textures. Corresponding empty texture
+ * objects are also generated.
+ */
+void GLAPIENTRY
+_mesa_GenTextures( GLsizei n, GLuint *textures )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint first;
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
+ return;
+ }
+
+ if (!textures)
+ return;
+
+ /*
+ * This must be atomic (generation and allocation of texture IDs)
+ */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
+
+ /* Allocate new, empty texture objects */
+ for (i = 0; i < n; i++) {
+ struct gl_texture_object *texObj;
+ GLuint name = first + i;
+ GLenum target = 0;
+ texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target);
+ if (!texObj) {
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures");
+ return;
+ }
+
+ /* insert into hash table */
+ _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
+
+ textures[i] = name;
+ }
+
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+}
+
+
+/**
+ * Check if the given texture object is bound to the current draw or
+ * read framebuffer. If so, Unbind it.
+ */
+static void
+unbind_texobj_from_fbo(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2;
+ GLuint i;
+
+ for (i = 0; i < n; i++) {
+ struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer;
+ if (fb->Name) {
+ GLuint j;
+ for (j = 0; j < BUFFER_COUNT; j++) {
+ if (fb->Attachment[j].Type == GL_TEXTURE &&
+ fb->Attachment[j].Texture == texObj) {
+ _mesa_remove_attachment(ctx, fb->Attachment + j);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Check if the given texture object is bound to any texture image units and
+ * unbind it if so (revert to default textures).
+ */
+static void
+unbind_texobj_from_texunits(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ GLuint u, tex;
+
+ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
+ struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ if (texObj == unit->CurrentTex[tex]) {
+ _mesa_reference_texobj(&unit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]);
+ ASSERT(unit->CurrentTex[tex]);
+ break;
+ }
+ }
+ }
+}
+
+
+/**
+ * Delete named textures.
+ *
+ * \param n number of textures to be deleted.
+ * \param textures array of texture IDs to be deleted.
+ *
+ * \sa glDeleteTextures().
+ *
+ * If we're about to delete a texture that's currently bound to any
+ * texture unit, unbind the texture first. Decrement the reference
+ * count on the texture object and delete it if it's zero.
+ * Recall that texture objects can be shared among several rendering
+ * contexts.
+ */
+void GLAPIENTRY
+_mesa_DeleteTextures( GLsizei n, const GLuint *textures)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */
+
+ if (!textures)
+ return;
+
+ for (i = 0; i < n; i++) {
+ if (textures[i] > 0) {
+ struct gl_texture_object *delObj
+ = _mesa_lookup_texture(ctx, textures[i]);
+
+ if (delObj) {
+ _mesa_lock_texture(ctx, delObj);
+
+ /* Check if texture is bound to any framebuffer objects.
+ * If so, unbind.
+ * See section 4.4.2.3 of GL_EXT_framebuffer_object.
+ */
+ unbind_texobj_from_fbo(ctx, delObj);
+
+ /* Check if this texture is currently bound to any texture units.
+ * If so, unbind it.
+ */
+ unbind_texobj_from_texunits(ctx, delObj);
+
+ _mesa_unlock_texture(ctx, delObj);
+
+ ctx->NewState |= _NEW_TEXTURE;
+
+ /* The texture _name_ is now free for re-use.
+ * Remove it from the hash table now.
+ */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ /* Unreference the texobj. If refcount hits zero, the texture
+ * will be deleted.
+ */
+ _mesa_reference_texobj(&delObj, NULL);
+ }
+ }
+ }
+}
+
+
+/**
+ * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
+ * into the corresponding Mesa texture target index.
+ * Return -1 if target is invalid.
+ */
+static GLint
+target_enum_to_index(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return TEXTURE_1D_INDEX;
+ case GL_TEXTURE_2D:
+ return TEXTURE_2D_INDEX;
+ case GL_TEXTURE_3D:
+ return TEXTURE_3D_INDEX;
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ return TEXTURE_CUBE_INDEX;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return TEXTURE_RECT_INDEX;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ return TEXTURE_1D_ARRAY_INDEX;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return TEXTURE_2D_ARRAY_INDEX;
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Bind a named texture to a texturing target.
+ *
+ * \param target texture target.
+ * \param texName texture name.
+ *
+ * \sa glBindTexture().
+ *
+ * Determines the old texture object bound and returns immediately if rebinding
+ * the same texture. Get the current texture which is either a default texture
+ * if name is null, a named texture from the hash, or a new texture if the
+ * given texture name is new. Increments its reference count, binds it, and
+ * calls dd_function_table::BindTexture. Decrements the old texture reference
+ * count and deletes it if it reaches zero.
+ */
+void GLAPIENTRY
+_mesa_BindTexture( GLenum target, GLuint texName )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *newTexObj = NULL, *defaultTexObj = NULL;
+ GLint targetIndex;
+ GLboolean early_out = GL_FALSE;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glBindTexture %s %d\n",
+ _mesa_lookup_enum_by_nr(target), (GLint) texName);
+
+ targetIndex = target_enum_to_index(target);
+ if (targetIndex < 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
+ return;
+ }
+ assert(targetIndex < NUM_TEXTURE_TARGETS);
+ defaultTexObj = ctx->Shared->DefaultTex[targetIndex];
+
+ /*
+ * Get pointer to new texture object (newTexObj)
+ */
+ if (texName == 0) {
+ newTexObj = defaultTexObj;
+ }
+ else {
+ /* non-default texture object */
+ newTexObj = _mesa_lookup_texture(ctx, texName);
+ if (newTexObj) {
+ /* error checking */
+ if (newTexObj->Target != 0 && newTexObj->Target != target) {
+ /* the named texture object's target doesn't match the given target */
+ _mesa_error( ctx, GL_INVALID_OPERATION,
+ "glBindTexture(target mismatch)" );
+ return;
+ }
+ if (newTexObj->Target == 0) {
+ finish_texture_init(ctx, target, newTexObj);
+ }
+ }
+ else {
+ /* if this is a new texture id, allocate a texture object now */
+ newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target);
+ if (!newTexObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
+ return;
+ }
+
+ /* and insert it into hash table */
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+ newTexObj->Target = target;
+ }
+
+ assert(valid_texture_object(newTexObj));
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ if ((ctx->Shared->RefCount == 1)
+ && (newTexObj == texUnit->CurrentTex[targetIndex])) {
+ early_out = GL_TRUE;
+ }
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ if (early_out) {
+ return;
+ }
+
+ /* flush before changing binding */
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ /* Do the actual binding. The refcount on the previously bound
+ * texture object will be decremented. It'll be deleted if the
+ * count hits zero.
+ */
+ _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
+ ASSERT(texUnit->CurrentTex[targetIndex]);
+
+ /* Pass BindTexture call to device driver */
+ if (ctx->Driver.BindTexture)
+ (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
+}
+
+
+/**
+ * Set texture priorities.
+ *
+ * \param n number of textures.
+ * \param texName texture names.
+ * \param priorities corresponding texture priorities.
+ *
+ * \sa glPrioritizeTextures().
+ *
+ * Looks up each texture in the hash, clamps the corresponding priority between
+ * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
+ */
+void GLAPIENTRY
+_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
+ const GLclampf *priorities )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (n < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
+ return;
+ }
+
+ if (!priorities)
+ return;
+
+ for (i = 0; i < n; i++) {
+ if (texName[i] > 0) {
+ struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
+ if (t) {
+ t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
+ if (ctx->Driver.PrioritizeTexture)
+ ctx->Driver.PrioritizeTexture( ctx, t, t->Priority );
+ }
+ }
+ }
+
+ ctx->NewState |= _NEW_TEXTURE;
+}
+
+/**
+ * See if textures are loaded in texture memory.
+ *
+ * \param n number of textures to query.
+ * \param texName array with the texture names.
+ * \param residences array which will hold the residence status.
+ *
+ * \return GL_TRUE if all textures are resident and \p residences is left unchanged,
+ *
+ * \sa glAreTexturesResident().
+ *
+ * Looks up each texture in the hash and calls
+ * dd_function_table::IsTextureResident.
+ */
+GLboolean GLAPIENTRY
+_mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
+ GLboolean *residences)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLboolean allResident = GL_TRUE;
+ GLint i, j;
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
+ return GL_FALSE;
+ }
+
+ if (!texName || !residences)
+ return GL_FALSE;
+
+ for (i = 0; i < n; i++) {
+ struct gl_texture_object *t;
+ if (texName[i] == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
+ return GL_FALSE;
+ }
+ t = _mesa_lookup_texture(ctx, texName[i]);
+ if (!t) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
+ return GL_FALSE;
+ }
+ if (!ctx->Driver.IsTextureResident ||
+ ctx->Driver.IsTextureResident(ctx, t)) {
+ /* The texture is resident */
+ if (!allResident)
+ residences[i] = GL_TRUE;
+ }
+ else {
+ /* The texture is not resident */
+ if (allResident) {
+ allResident = GL_FALSE;
+ for (j = 0; j < i; j++)
+ residences[j] = GL_TRUE;
+ }
+ residences[i] = GL_FALSE;
+ }
+ }
+
+ return allResident;
+}
+
+/**
+ * See if a name corresponds to a texture.
+ *
+ * \param texture texture name.
+ *
+ * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
+ * otherwise.
+ *
+ * \sa glIsTexture().
+ *
+ * Calls _mesa_HashLookup().
+ */
+GLboolean GLAPIENTRY
+_mesa_IsTexture( GLuint texture )
+{
+ struct gl_texture_object *t;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (!texture)
+ return GL_FALSE;
+
+ t = _mesa_lookup_texture(ctx, texture);
+
+ /* IsTexture is true only after object has been bound once. */
+ return t && t->Target;
+}
+
+
+/**
+ * Simplest implementation of texture locking: grab the shared tex
+ * mutex. Examine the shared context state timestamp and if there has
+ * been a change, set the appropriate bits in ctx->NewState.
+ *
+ * This is used to deal with synchronizing things when a texture object
+ * is used/modified by different contexts (or threads) which are sharing
+ * the texture.
+ *
+ * See also _mesa_lock/unlock_texture() in teximage.h
+ */
+void
+_mesa_lock_context_textures( GLcontext *ctx )
+{
+ _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
+
+ if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
+ ctx->NewState |= _NEW_TEXTURE;
+ ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
+ }
+}
+
+
+void
+_mesa_unlock_context_textures( GLcontext *ctx )
+{
+ assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
+}
+
+/*@}*/
+
+
diff --git a/mesalib/src/mesa/main/texobj.h b/mesalib/src/mesa/main/texobj.h
new file mode 100644
index 000000000..9bfebd45c
--- /dev/null
+++ b/mesalib/src/mesa/main/texobj.h
@@ -0,0 +1,118 @@
+/**
+ * \file texobj.h
+ * Texture object management.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 "mtypes.h"
+
+
+/**
+ * \name Internal functions
+ */
+/*@{*/
+
+extern struct gl_texture_object *
+_mesa_lookup_texture(GLcontext *ctx, GLuint id);
+
+extern struct gl_texture_object *
+_mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target );
+
+extern void
+_mesa_initialize_texture_object( struct gl_texture_object *obj,
+ GLuint name, GLenum target );
+
+extern void
+_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *obj );
+
+extern void
+_mesa_copy_texture_object( struct gl_texture_object *dest,
+ const struct gl_texture_object *src );
+
+extern void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *obj);
+
+extern void
+_mesa_reference_texobj(struct gl_texture_object **ptr,
+ struct gl_texture_object *tex);
+
+extern void
+_mesa_test_texobj_completeness( const GLcontext *ctx,
+ struct gl_texture_object *obj );
+
+extern void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+ GLboolean invalidate_state);
+
+extern struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx);
+
+extern void
+_mesa_unlock_context_textures( GLcontext *ctx );
+
+extern void
+_mesa_lock_context_textures( GLcontext *ctx );
+
+/*@}*/
+
+/**
+ * \name API functions
+ */
+/*@{*/
+
+extern void GLAPIENTRY
+_mesa_GenTextures( GLsizei n, GLuint *textures );
+
+
+extern void GLAPIENTRY
+_mesa_DeleteTextures( GLsizei n, const GLuint *textures );
+
+
+extern void GLAPIENTRY
+_mesa_BindTexture( GLenum target, GLuint texture );
+
+
+extern void GLAPIENTRY
+_mesa_PrioritizeTextures( GLsizei n, const GLuint *textures,
+ const GLclampf *priorities );
+
+
+extern GLboolean GLAPIENTRY
+_mesa_AreTexturesResident( GLsizei n, const GLuint *textures,
+ GLboolean *residences );
+
+extern GLboolean GLAPIENTRY
+_mesa_IsTexture( GLuint texture );
+
+/*@}*/
+
+
+#endif
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
new file mode 100644
index 000000000..b2fbe2205
--- /dev/null
+++ b/mesalib/src/mesa/main/texparam.c
@@ -0,0 +1,1285 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file texparam.c
+ *
+ * glTexParameter-related functions
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/texcompress.h"
+#include "main/texparam.h"
+#include "main/teximage.h"
+#include "main/texstate.h"
+#include "shader/prog_instruction.h"
+
+
+/**
+ * Check if a coordinate wrap mode is supported for the texture target.
+ * \return GL_TRUE if legal, GL_FALSE otherwise
+ */
+static GLboolean
+validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
+{
+ const struct gl_extensions * const e = & ctx->Extensions;
+
+ if (wrap == GL_CLAMP || wrap == GL_CLAMP_TO_EDGE ||
+ (wrap == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
+ /* any texture target */
+ return GL_TRUE;
+ }
+ else if (target != GL_TEXTURE_RECTANGLE_NV &&
+ (wrap == GL_REPEAT ||
+ (wrap == GL_MIRRORED_REPEAT &&
+ e->ARB_texture_mirrored_repeat) ||
+ (wrap == GL_MIRROR_CLAMP_EXT &&
+ (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+ (wrap == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
+ (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
+ (wrap == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
+ (e->EXT_texture_mirror_clamp)))) {
+ /* non-rectangle texture */
+ return GL_TRUE;
+ }
+
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)", wrap );
+ return GL_FALSE;
+}
+
+
+/**
+ * Get current texture object for given target.
+ * Return NULL if any error.
+ */
+static struct gl_texture_object *
+get_texobj(GLcontext *ctx, GLenum target)
+{
+ struct gl_texture_unit *texUnit;
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(current unit)");
+ return NULL;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ return texUnit->CurrentTex[TEXTURE_1D_INDEX];
+ case GL_TEXTURE_2D:
+ return texUnit->CurrentTex[TEXTURE_2D_INDEX];
+ case GL_TEXTURE_3D:
+ return texUnit->CurrentTex[TEXTURE_3D_INDEX];
+ case GL_TEXTURE_CUBE_MAP:
+ if (ctx->Extensions.ARB_texture_cube_map) {
+ return texUnit->CurrentTex[TEXTURE_CUBE_INDEX];
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (ctx->Extensions.NV_texture_rectangle) {
+ return texUnit->CurrentTex[TEXTURE_RECT_INDEX];
+ }
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ if (ctx->Extensions.MESA_texture_array) {
+ return texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX];
+ }
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ if (ctx->Extensions.MESA_texture_array) {
+ return texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX];
+ }
+ break;
+ default:
+ ;
+ }
+
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(target)");
+ return NULL;
+}
+
+
+/**
+ * Convert GL_RED/GREEN/BLUE/ALPHA/ZERO/ONE to SWIZZLE_X/Y/Z/W/ZERO/ONE.
+ * \return -1 if error.
+ */
+static GLint
+comp_to_swizzle(GLenum comp)
+{
+ switch (comp) {
+ case GL_RED:
+ return SWIZZLE_X;
+ case GL_GREEN:
+ return SWIZZLE_Y;
+ case GL_BLUE:
+ return SWIZZLE_Z;
+ case GL_ALPHA:
+ return SWIZZLE_W;
+ case GL_ZERO:
+ return SWIZZLE_ZERO;
+ case GL_ONE:
+ return SWIZZLE_ONE;
+ default:
+ return -1;
+ }
+}
+
+
+static void
+set_swizzle_component(GLuint *swizzle, GLuint comp, GLuint swz)
+{
+ ASSERT(comp < 4);
+ ASSERT(swz <= SWIZZLE_NIL);
+ {
+ GLuint mask = 0x7 << (3 * comp);
+ GLuint s = (*swizzle & ~mask) | (swz << (3 * comp));
+ *swizzle = s;
+ }
+}
+
+
+/**
+ * This is called just prior to changing any texture object state.
+ * Any pending rendering will be flushed out, we'll set the _NEW_TEXTURE
+ * state flag and then mark the texture object as 'incomplete' so that any
+ * per-texture derived state gets recomputed.
+ */
+static INLINE void
+flush(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texObj->_Complete = GL_FALSE;
+}
+
+
+/**
+ * Set an integer-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
+set_tex_parameteri(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLint *params)
+{
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ if (texObj->MinFilter == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ flush(ctx, texObj);
+ texObj->MinFilter = params[0];
+ return GL_TRUE;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
+ flush(ctx, texObj);
+ texObj->MinFilter = params[0];
+ return GL_TRUE;
+ }
+ /* fall-through */
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)",
+ params[0] );
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (texObj->MagFilter == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ flush(ctx, texObj);
+ texObj->MagFilter = params[0];
+ return GL_TRUE;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(param=0x%x)",
+ params[0]);
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_S:
+ if (texObj->WrapS == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapS = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_T:
+ if (texObj->WrapT == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapT = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_WRAP_R:
+ if (texObj->WrapR == params[0])
+ return GL_FALSE;
+ if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) {
+ flush(ctx, texObj);
+ texObj->WrapR = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ if (texObj->BaseLevel == params[0])
+ return GL_FALSE;
+ if (params[0] < 0 ||
+ (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexParameter(param=%d)", params[0]);
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ texObj->BaseLevel = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_LEVEL:
+ if (texObj->MaxLevel == params[0])
+ return GL_FALSE;
+ if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(param=%d)", params[0]);
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ texObj->MaxLevel = params[0];
+ return GL_TRUE;
+
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (ctx->Extensions.SGIS_generate_mipmap) {
+ if (texObj->GenerateMipmap != params[0]) {
+ flush(ctx, texObj);
+ texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (ctx->Extensions.ARB_shadow &&
+ (params[0] == GL_NONE ||
+ params[0] == GL_COMPARE_R_TO_TEXTURE_ARB)) {
+ if (texObj->CompareMode != params[0]) {
+ flush(ctx, texObj);
+ texObj->CompareMode = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(GL_TEXTURE_COMPARE_MODE_ARB)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ if (texObj->CompareFunc == params[0])
+ return GL_FALSE;
+ switch (params[0]) {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ flush(ctx, texObj);
+ texObj->CompareFunc = params[0];
+ return GL_TRUE;
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ if (ctx->Extensions.EXT_shadow_funcs) {
+ flush(ctx, texObj);
+ texObj->CompareFunc = params[0];
+ return GL_TRUE;
+ }
+ /* fall-through */
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(GL_TEXTURE_COMPARE_FUNC_ARB)");
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ }
+ return GL_FALSE;
+
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (ctx->Extensions.ARB_depth_texture &&
+ (params[0] == GL_LUMINANCE ||
+ params[0] == GL_INTENSITY ||
+ params[0] == GL_ALPHA)) {
+ if (texObj->DepthMode != params[0]) {
+ flush(ctx, texObj);
+ texObj->DepthMode = params[0];
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(GL_DEPTH_TEXTURE_MODE_ARB)");
+ }
+ return GL_FALSE;
+
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ texObj->CropRect[0] = params[0];
+ texObj->CropRect[1] = params[1];
+ texObj->CropRect[2] = params[2];
+ texObj->CropRect[3] = params[3];
+ return GL_TRUE;
+#endif
+
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ const GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ const GLint swz = comp_to_swizzle(params[0]);
+ if (swz < 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(swizzle 0x%x)", params[0]);
+ return GL_FALSE;
+ }
+ ASSERT(comp < 4);
+ if (swz >= 0) {
+ flush(ctx, texObj);
+ texObj->Swizzle[comp] = params[0];
+ set_swizzle_component(&texObj->_Swizzle, comp, swz);
+ return GL_TRUE;
+ }
+ }
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ return GL_FALSE;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp;
+ flush(ctx, texObj);
+ for (comp = 0; comp < 4; comp++) {
+ const GLint swz = comp_to_swizzle(params[comp]);
+ if (swz >= 0) {
+ texObj->Swizzle[comp] = params[comp];
+ set_swizzle_component(&texObj->_Swizzle, comp, swz);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(swizzle 0x%x)", params[comp]);
+ return GL_FALSE;
+ }
+ }
+ return GL_TRUE;
+ }
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ return GL_FALSE;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Set a float-valued texture parameter
+ * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise
+ */
+static GLboolean
+set_tex_parameterf(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLenum pname, const GLfloat *params)
+{
+ switch (pname) {
+ case GL_TEXTURE_MIN_LOD:
+ if (texObj->MinLod == params[0])
+ return GL_FALSE;
+ flush(ctx, texObj);
+ texObj->MinLod = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_LOD:
+ if (texObj->MaxLod == params[0])
+ return GL_FALSE;
+ flush(ctx, texObj);
+ texObj->MaxLod = params[0];
+ return GL_TRUE;
+
+ case GL_TEXTURE_PRIORITY:
+ flush(ctx, texObj);
+ texObj->Priority = CLAMP(params[0], 0.0F, 1.0F);
+ return GL_TRUE;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ if (texObj->MaxAnisotropy == params[0])
+ return GL_FALSE;
+ if (params[0] < 1.0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return GL_FALSE;
+ }
+ flush(ctx, texObj);
+ /* clamp to max, that's what NVIDIA does */
+ texObj->MaxAnisotropy = MIN2(params[0],
+ ctx->Const.MaxTextureMaxAnisotropy);
+ return GL_TRUE;
+ }
+ else {
+ static GLuint count = 0;
+ if (count++ < 10)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ if (texObj->CompareFailValue != params[0]) {
+ flush(ctx, texObj);
+ texObj->CompareFailValue = CLAMP(params[0], 0.0F, 1.0F);
+ return GL_TRUE;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(pname=GL_TEXTURE_COMPARE_FAIL_VALUE_ARB)");
+ }
+ return GL_FALSE;
+
+ case GL_TEXTURE_LOD_BIAS:
+ /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias */
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ if (texObj->LodBias != params[0]) {
+ flush(ctx, texObj);
+ texObj->LodBias = params[0];
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ flush(ctx, texObj);
+ texObj->BorderColor[RCOMP] = params[0];
+ texObj->BorderColor[GCOMP] = params[1];
+ texObj->BorderColor[BCOMP] = params[2];
+ texObj->BorderColor[ACOMP] = params[3];
+ return GL_TRUE;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
+ }
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_GENERATE_MIPMAP_SGIS:
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ {
+ /* convert float param to int */
+ GLint p = (GLint) param;
+ need_update = set_tex_parameteri(ctx, texObj, pname, &p);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameterf(ctx, texObj, pname, &param);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, &param);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_GENERATE_MIPMAP_SGIS:
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ {
+ /* convert float param to int */
+ GLint p = (GLint) params[0];
+ need_update = set_tex_parameteri(ctx, texObj, pname, &p);
+ }
+ break;
+
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ {
+ /* convert float params to int */
+ GLint iparams[4];
+ iparams[0] = (GLint) params[0];
+ iparams[1] = (GLint) params[1];
+ iparams[2] = (GLint) params[2];
+ iparams[3] = (GLint) params[3];
+ need_update = set_tex_parameteri(ctx, target, iparams);
+ }
+ break;
+#endif
+
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameterf(ctx, texObj, pname, params);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, params);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_PRIORITY:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ case GL_TEXTURE_LOD_BIAS:
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ {
+ GLfloat fparam = (GLfloat) param;
+ /* convert int param to float */
+ need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameteri(ctx, texObj, pname, &param);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ GLfloat fparam = (GLfloat) param;
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, &fparam);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ GLboolean need_update;
+ struct gl_texture_object *texObj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ texObj = get_texobj(ctx, target);
+ if (!texObj)
+ return;
+
+ switch (pname) {
+ case GL_TEXTURE_BORDER_COLOR:
+ {
+ /* convert int params to float */
+ GLfloat fparams[4];
+ fparams[0] = INT_TO_FLOAT(params[0]);
+ fparams[1] = INT_TO_FLOAT(params[1]);
+ fparams[2] = INT_TO_FLOAT(params[2]);
+ fparams[3] = INT_TO_FLOAT(params[3]);
+ need_update = set_tex_parameterf(ctx, texObj, pname, fparams);
+ }
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_PRIORITY:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ case GL_TEXTURE_LOD_BIAS:
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ {
+ /* convert int param to float */
+ GLfloat fparam = (GLfloat) params[0];
+ need_update = set_tex_parameterf(ctx, texObj, pname, &fparam);
+ }
+ break;
+ default:
+ /* this will generate an error if pname is illegal */
+ need_update = set_tex_parameteri(ctx, texObj, pname, params);
+ }
+
+ if (ctx->Driver.TexParameter && need_update) {
+ GLfloat fparams[4];
+ fparams[0] = INT_TO_FLOAT(params[0]);
+ if (pname == GL_TEXTURE_BORDER_COLOR ||
+ pname == GL_TEXTURE_CROP_RECT_OES) {
+ fparams[1] = INT_TO_FLOAT(params[1]);
+ fparams[2] = INT_TO_FLOAT(params[2]);
+ fparams[3] = INT_TO_FLOAT(params[3]);
+ }
+ ctx->Driver.TexParameter(ctx, target, texObj, pname, fparams);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
+ GLenum pname, GLfloat *params )
+{
+ GLint iparam;
+ _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
+ *params = (GLfloat) iparam;
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
+ GLenum pname, GLint *params )
+{
+ const struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ const struct gl_texture_image *img = NULL;
+ GLboolean isProxy;
+ GLint maxLevels;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexLevelParameteriv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ /* this will catch bad target values */
+ maxLevels = _mesa_max_texture_levels(ctx, target);
+ if (maxLevels == 0) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(target=0x%x)", target);
+ return;
+ }
+
+ if (level < 0 || level >= maxLevels) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
+ return;
+ }
+
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ _mesa_lock_texture(ctx, texObj);
+
+ img = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!img || !img->TexFormat) {
+ /* undefined texture image */
+ if (pname == GL_TEXTURE_COMPONENTS)
+ *params = 1;
+ else
+ *params = 0;
+ goto out;
+ }
+
+ isProxy = _mesa_is_proxy_texture(target);
+
+ switch (pname) {
+ case GL_TEXTURE_WIDTH:
+ *params = img->Width;
+ break;
+ case GL_TEXTURE_HEIGHT:
+ *params = img->Height;
+ break;
+ case GL_TEXTURE_DEPTH:
+ *params = img->Depth;
+ break;
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ *params = img->InternalFormat;
+ break;
+ case GL_TEXTURE_BORDER:
+ *params = img->Border;
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
+ *params = img->TexFormat->RedBits;
+ else
+ *params = 0;
+ break;
+ case GL_TEXTURE_GREEN_SIZE:
+ if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
+ *params = img->TexFormat->GreenBits;
+ else
+ *params = 0;
+ break;
+ case GL_TEXTURE_BLUE_SIZE:
+ if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
+ *params = img->TexFormat->BlueBits;
+ else
+ *params = 0;
+ break;
+ case GL_TEXTURE_ALPHA_SIZE:
+ if (img->_BaseFormat == GL_ALPHA ||
+ img->_BaseFormat == GL_LUMINANCE_ALPHA ||
+ img->_BaseFormat == GL_RGBA)
+ *params = img->TexFormat->AlphaBits;
+ else
+ *params = 0;
+ break;
+ case GL_TEXTURE_INTENSITY_SIZE:
+ if (img->_BaseFormat != GL_INTENSITY)
+ *params = 0;
+ else if (img->TexFormat->IntensityBits > 0)
+ *params = img->TexFormat->IntensityBits;
+ else /* intensity probably stored as rgb texture */
+ *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
+ break;
+ case GL_TEXTURE_LUMINANCE_SIZE:
+ if (img->_BaseFormat != GL_LUMINANCE &&
+ img->_BaseFormat != GL_LUMINANCE_ALPHA)
+ *params = 0;
+ else if (img->TexFormat->LuminanceBits > 0)
+ *params = img->TexFormat->LuminanceBits;
+ else /* luminance probably stored as rgb texture */
+ *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
+ break;
+ case GL_TEXTURE_INDEX_SIZE_EXT:
+ if (img->_BaseFormat == GL_COLOR_INDEX)
+ *params = img->TexFormat->IndexBits;
+ else
+ *params = 0;
+ break;
+ case GL_TEXTURE_DEPTH_SIZE_ARB:
+ if (ctx->Extensions.ARB_depth_texture)
+ *params = img->TexFormat->DepthBits;
+ else
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ break;
+ case GL_TEXTURE_STENCIL_SIZE_EXT:
+ if (ctx->Extensions.EXT_packed_depth_stencil ||
+ ctx->Extensions.ARB_framebuffer_object) {
+ *params = img->TexFormat->StencilBits;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+
+ /* GL_ARB_texture_compression */
+ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
+ if (img->IsCompressed && !isProxy) {
+ /* Don't use ctx->Driver.CompressedTextureSize() since that
+ * may returned a padded hardware size.
+ */
+ *params = _mesa_compressed_texture_size(ctx, img->Width,
+ img->Height, img->Depth,
+ img->TexFormat->MesaFormat);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_COMPRESSED:
+ *params = (GLint) img->IsCompressed;
+ break;
+
+ /* GL_ARB_texture_float */
+ case GL_TEXTURE_RED_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_GREEN_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_BLUE_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_ALPHA_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_LUMINANCE_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_INTENSITY_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+ case GL_TEXTURE_DEPTH_TYPE_ARB:
+ if (ctx->Extensions.ARB_texture_float) {
+ *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+ break;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)");
+ }
+
+ out:
+ _mesa_unlock_texture(ctx, texObj);
+}
+
+
+
+void GLAPIENTRY
+_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *obj;
+ GLboolean error = GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexParameterfv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ obj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (!obj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
+ return;
+ }
+
+ _mesa_lock_texture(ctx, obj);
+ 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:
+ *params = ENUM_TO_FLOAT(obj->WrapR);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
+ params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
+ params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
+ params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
+ break;
+ case GL_TEXTURE_RESIDENT:
+ {
+ GLboolean resident;
+ if (ctx->Driver.IsTextureResident)
+ resident = ctx->Driver.IsTextureResident(ctx, obj);
+ else
+ resident = GL_TRUE;
+ *params = ENUM_TO_FLOAT(resident);
+ }
+ 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 = (GLfloat) obj->BaseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = (GLfloat) obj->MaxLevel;
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ *params = obj->MaxAnisotropy;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ *params = obj->CompareFailValue;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (ctx->Extensions.SGIS_generate_mipmap) {
+ *params = (GLfloat) obj->GenerateMipmap;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ *params = (GLfloat) obj->CompareMode;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ *params = (GLfloat) obj->CompareFunc;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (ctx->Extensions.ARB_depth_texture) {
+ *params = (GLfloat) obj->DepthMode;
+ }
+ else
+ error = GL_TRUE;
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ *params = obj->LodBias;
+ }
+ else
+ error = GL_TRUE;
+ break;
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ params[0] = obj->CropRect[0];
+ params[1] = obj->CropRect[1];
+ params[2] = obj->CropRect[2];
+ params[3] = obj->CropRect[3];
+ break;
+#endif
+
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ *params = (GLfloat) obj->Swizzle[comp];
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp;
+ for (comp = 0; comp < 4; comp++) {
+ params[comp] = (GLfloat) obj->Swizzle[comp];
+ }
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ default:
+ error = GL_TRUE;
+ break;
+ }
+
+ if (error)
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
+ pname);
+
+ _mesa_unlock_texture(ctx, obj);
+}
+
+
+void GLAPIENTRY
+_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *obj;
+ GLboolean error = GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetTexParameteriv(current unit)");
+ return;
+ }
+
+ texUnit = _mesa_get_current_tex_unit(ctx);
+
+ obj = _mesa_select_tex_object(ctx, texUnit, target);
+ if (!obj) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(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:
+ *params = (GLint) obj->WrapR;
+ break;;
+ case GL_TEXTURE_BORDER_COLOR:
+ {
+ GLfloat b[4];
+ b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
+ b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
+ b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
+ b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
+ params[0] = FLOAT_TO_INT(b[0]);
+ params[1] = FLOAT_TO_INT(b[1]);
+ params[2] = FLOAT_TO_INT(b[2]);
+ params[3] = FLOAT_TO_INT(b[3]);
+ }
+ break;;
+ case GL_TEXTURE_RESIDENT:
+ {
+ GLboolean resident;
+ if (ctx->Driver.IsTextureResident)
+ resident = ctx->Driver.IsTextureResident(ctx, obj);
+ else
+ resident = GL_TRUE;
+ *params = (GLint) resident;
+ }
+ break;;
+ case GL_TEXTURE_PRIORITY:
+ *params = FLOAT_TO_INT(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;;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (ctx->Extensions.EXT_texture_filter_anisotropic) {
+ *params = (GLint) obj->MaxAnisotropy;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB:
+ if (ctx->Extensions.ARB_shadow_ambient) {
+ *params = (GLint) FLOAT_TO_INT(obj->CompareFailValue);
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_GENERATE_MIPMAP_SGIS:
+ if (ctx->Extensions.SGIS_generate_mipmap) {
+ *params = (GLint) obj->GenerateMipmap;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_COMPARE_MODE_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ *params = (GLint) obj->CompareMode;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC_ARB:
+ if (ctx->Extensions.ARB_shadow) {
+ *params = (GLint) obj->CompareFunc;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_TEXTURE_MODE_ARB:
+ if (ctx->Extensions.ARB_depth_texture) {
+ *params = (GLint) obj->DepthMode;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+ case GL_TEXTURE_LOD_BIAS:
+ if (ctx->Extensions.EXT_texture_lod_bias) {
+ *params = (GLint) obj->LodBias;
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+#ifdef FEATURE_OES_draw_texture
+ case GL_TEXTURE_CROP_RECT_OES:
+ params[0] = obj->CropRect[0];
+ params[1] = obj->CropRect[1];
+ params[2] = obj->CropRect[2];
+ params[3] = obj->CropRect[3];
+ break;
+#endif
+ case GL_TEXTURE_SWIZZLE_R_EXT:
+ case GL_TEXTURE_SWIZZLE_G_EXT:
+ case GL_TEXTURE_SWIZZLE_B_EXT:
+ case GL_TEXTURE_SWIZZLE_A_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ GLuint comp = pname - GL_TEXTURE_SWIZZLE_R_EXT;
+ *params = obj->Swizzle[comp];
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_RGBA_EXT:
+ if (ctx->Extensions.EXT_texture_swizzle) {
+ COPY_4V(params, obj->Swizzle);
+ }
+ else {
+ error = GL_TRUE;
+ }
+ break;
+
+ default:
+ ; /* silence warnings */
+ }
+
+ if (error)
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)",
+ pname);
+
+ _mesa_unlock_texture(ctx, obj);
+}
diff --git a/mesalib/src/mesa/main/texparam.h b/mesalib/src/mesa/main/texparam.h
new file mode 100644
index 000000000..454b96350
--- /dev/null
+++ b/mesalib/src/mesa/main/texparam.h
@@ -0,0 +1,63 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 TEXPARAM_H
+#define TEXPARAM_H
+
+
+#include "main/glheader.h"
+
+
+extern void GLAPIENTRY
+_mesa_GetTexLevelParameterfv( GLenum target, GLint level,
+ GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
+ GLenum pname, GLint *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params );
+
+
+
+extern void GLAPIENTRY
+_mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params );
+
+extern void GLAPIENTRY
+_mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param );
+
+
+extern void GLAPIENTRY
+_mesa_TexParameteri( GLenum target, GLenum pname, GLint param );
+
+extern void GLAPIENTRY
+_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params );
+
+
+#endif /* TEXPARAM_H */
diff --git a/mesalib/src/mesa/main/texrender.c b/mesalib/src/mesa/main/texrender.c
new file mode 100644
index 000000000..53be83b05
--- /dev/null
+++ b/mesalib/src/mesa/main/texrender.c
@@ -0,0 +1,567 @@
+
+#include "context.h"
+#include "fbobject.h"
+#include "texformat.h"
+#include "texrender.h"
+#include "renderbuffer.h"
+
+
+/*
+ * Render-to-texture code for GL_EXT_framebuffer_object
+ */
+
+
+/**
+ * Derived from gl_renderbuffer class
+ */
+struct texture_renderbuffer
+{
+ struct gl_renderbuffer Base; /**< Base class object */
+ struct gl_texture_image *TexImage;
+ StoreTexelFunc Store;
+ GLint Yoffset; /**< Layer for 1D array textures. */
+ GLint Zoffset; /**< Layer for 2D array textures, or slice
+ * for 3D textures
+ */
+};
+
+
+/**
+ * Get row of values from the renderbuffer that wraps a texture image.
+ */
+static void
+texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, void *values)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ ASSERT(trb->TexImage->Width == rb->Width);
+ ASSERT(trb->TexImage->Height == rb->Height);
+
+ y += trb->Yoffset;
+
+ if (rb->DataType == CHAN_TYPE) {
+ GLchan *rgbaOut = (GLchan *) values;
+ for (i = 0; i < count; i++) {
+ trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i);
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zValues = (GLushort *) values;
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
+ zValues[i] = (GLushort) (flt * 0xffff);
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ GLuint *zValues = (GLuint *) values;
+ /*
+ const GLdouble scale = (GLdouble) 0xffffffff;
+ */
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
+#if 0
+ /* this should work, but doesn't (overflow due to low precision) */
+ zValues[i] = (GLuint) (flt * scale);
+#else
+ /* temporary hack */
+ zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ GLuint *zValues = (GLuint *) values;
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
+ zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_get_row");
+ }
+}
+
+
+static void
+texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], void *values)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ if (rb->DataType == CHAN_TYPE) {
+ GLchan *rgbaOut = (GLchan *) values;
+ for (i = 0; i < count; i++) {
+ trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i] + trb->Yoffset,
+ z, rgbaOut + 4 * i);
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zValues = (GLushort *) values;
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+ z, &flt);
+ zValues[i] = (GLushort) (flt * 0xffff);
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ GLuint *zValues = (GLuint *) values;
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+ z, &flt);
+#if 0
+ zValues[i] = (GLuint) (flt * 0xffffffff);
+#else
+ zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ GLuint *zValues = (GLuint *) values;
+ for (i = 0; i < count; i++) {
+ GLfloat flt;
+ trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+ z, &flt);
+ zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_get_values");
+ }
+}
+
+
+/**
+ * Put row of values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ y += trb->Yoffset;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgba = (const GLchan *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, rgba);
+ }
+ rgba += 4;
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort *zValues = (const GLushort *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+ trb->Store(trb->TexImage, x + i, y, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+ }
+}
+
+/**
+ * Put row of RGB values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row_rgb(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ y += trb->Yoffset;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgb = (const GLchan *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, rgb);
+ }
+ rgb += 3;
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort *zValues = (const GLushort *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+ trb->Store(trb->TexImage, x + i, y, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+ }
+}
+
+
+static void
+texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ y += trb->Yoffset;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgba = (const GLchan *) value;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, rgba);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort zValue = *((const GLushort *) value);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, &zValue);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint zValue = *((const GLuint *) value);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, &zValue);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint zValue = *((const GLuint *) value);
+ const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x + i, y, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row");
+ }
+}
+
+
+static void
+texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+ const GLint x[], const GLint y[], const void *values,
+ const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgba = (const GLchan *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
+ }
+ rgba += 4;
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort *zValues = (const GLushort *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint *zValues = (const GLuint *) values;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_values");
+ }
+}
+
+
+static void
+texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte *mask)
+{
+ const struct texture_renderbuffer *trb
+ = (const struct texture_renderbuffer *) rb;
+ const GLint z = trb->Zoffset;
+ GLuint i;
+
+ if (rb->DataType == CHAN_TYPE) {
+ const GLchan *rgba = (const GLchan *) value;
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ const GLuint zValue = *((const GLuint *) value);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLushort zValue = *((const GLushort *) value);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+ const GLuint zValue = *((const GLuint *) value);
+ const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+ trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values");
+ }
+}
+
+
+static void
+store_nop(struct gl_texture_image *texImage,
+ GLint col, GLint row, GLint img,
+ const void *texel)
+{
+}
+
+
+static void
+delete_texture_wrapper(struct gl_renderbuffer *rb)
+{
+ ASSERT(rb->RefCount == 0);
+ _mesa_free(rb);
+}
+
+
+/**
+ * This function creates a renderbuffer object which wraps a texture image.
+ * The new renderbuffer is plugged into the given attachment point.
+ * This allows rendering into the texture as if it were a renderbuffer.
+ */
+static void
+wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
+{
+ struct texture_renderbuffer *trb;
+ const GLuint name = 0;
+
+ ASSERT(att->Type == GL_TEXTURE);
+ ASSERT(att->Renderbuffer == NULL);
+
+ trb = CALLOC_STRUCT(texture_renderbuffer);
+ if (!trb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
+ return;
+ }
+
+ /* init base gl_renderbuffer fields */
+ _mesa_init_renderbuffer(&trb->Base, name);
+ /* plug in our texture_renderbuffer-specific functions */
+ trb->Base.Delete = delete_texture_wrapper;
+ trb->Base.AllocStorage = NULL; /* illegal! */
+ trb->Base.GetRow = texture_get_row;
+ trb->Base.GetValues = texture_get_values;
+ trb->Base.PutRow = texture_put_row;
+ trb->Base.PutRowRGB = texture_put_row_rgb;
+ trb->Base.PutMonoRow = texture_put_mono_row;
+ trb->Base.PutValues = texture_put_values;
+ trb->Base.PutMonoValues = texture_put_mono_values;
+
+ /* update attachment point */
+ _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
+}
+
+
+
+/**
+ * Update the renderbuffer wrapper for rendering to a texture.
+ * For example, update the width, height of the RB based on the texture size,
+ * update the internal format info, etc.
+ */
+static void
+update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
+{
+ struct texture_renderbuffer *trb
+ = (struct texture_renderbuffer *) att->Renderbuffer;
+
+ (void) ctx;
+ ASSERT(trb);
+
+ trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ ASSERT(trb->TexImage);
+
+ trb->Store = trb->TexImage->TexFormat->StoreTexel;
+ if (!trb->Store) {
+ /* we'll never draw into some textures (compressed formats) */
+ trb->Store = store_nop;
+ }
+
+ if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
+ trb->Yoffset = att->Zoffset;
+ trb->Zoffset = 0;
+ }
+ else {
+ trb->Yoffset = 0;
+ trb->Zoffset = att->Zoffset;
+ }
+
+ trb->Base.Width = trb->TexImage->Width;
+ trb->Base.Height = trb->TexImage->Height;
+ trb->Base.InternalFormat = trb->TexImage->InternalFormat;
+ /* XXX may need more special cases here */
+ if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z24_S8) {
+ trb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+ trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ }
+ else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z16) {
+ trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
+ trb->Base.DataType = GL_UNSIGNED_SHORT;
+ }
+ else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z32) {
+ trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
+ trb->Base.DataType = GL_UNSIGNED_INT;
+ }
+ else {
+ trb->Base._ActualFormat = trb->TexImage->InternalFormat;
+ trb->Base.DataType = CHAN_TYPE;
+ }
+ trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat;
+#if 0
+ /* fix/avoid this assertion someday */
+ ASSERT(trb->Base._BaseFormat == GL_RGB ||
+ trb->Base._BaseFormat == GL_RGBA ||
+ trb->Base._BaseFormat == GL_DEPTH_COMPONENT);
+#endif
+ trb->Base.Data = trb->TexImage->Data;
+
+ trb->Base.RedBits = trb->TexImage->TexFormat->RedBits;
+ trb->Base.GreenBits = trb->TexImage->TexFormat->GreenBits;
+ trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits;
+ trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits;
+ trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits;
+ trb->Base.StencilBits = trb->TexImage->TexFormat->StencilBits;
+}
+
+
+
+/**
+ * Called when rendering to a texture image begins, or when changing
+ * the dest mipmap level, cube face, etc.
+ * This is a fallback routine for software render-to-texture.
+ *
+ * Called via the glRenderbufferTexture1D/2D/3D() functions
+ * and elsewhere (such as glTexImage2D).
+ *
+ * The image we're rendering into is
+ * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ * It'll never be NULL.
+ *
+ * \param fb the framebuffer object the texture is being bound to
+ * \param att the fb attachment point of the texture
+ *
+ * \sa _mesa_framebuffer_renderbuffer
+ */
+void
+_mesa_render_texture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att)
+{
+ (void) fb;
+
+ if (!att->Renderbuffer) {
+ wrap_texture(ctx, att);
+ }
+ update_wrapper(ctx, att);
+}
+
+
+void
+_mesa_finish_render_texture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att)
+{
+ /* do nothing */
+ /* The renderbuffer texture wrapper will get deleted by the
+ * normal mechanism for deleting renderbuffers.
+ */
+ (void) ctx;
+ (void) att;
+}
diff --git a/mesalib/src/mesa/main/texrender.h b/mesalib/src/mesa/main/texrender.h
new file mode 100644
index 000000000..7c3fb0871
--- /dev/null
+++ b/mesalib/src/mesa/main/texrender.h
@@ -0,0 +1,15 @@
+#ifndef TEXRENDER_H
+#define TEXRENDER_H
+
+
+extern void
+_mesa_render_texture(GLcontext *ctx,
+ struct gl_framebuffer *fb,
+ struct gl_renderbuffer_attachment *att);
+
+extern void
+_mesa_finish_render_texture(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att);
+
+
+#endif /* TEXRENDER_H */
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
new file mode 100644
index 000000000..861c5f37c
--- /dev/null
+++ b/mesalib/src/mesa/main/texstate.c
@@ -0,0 +1,823 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file texstate.c
+ *
+ * Texture state handling.
+ */
+
+#include "glheader.h"
+#include "mfeatures.h"
+#include "colormac.h"
+#if FEATURE_colortable
+#include "colortab.h"
+#endif
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "texcompress.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "texenvprogram.h"
+#include "mtypes.h"
+
+
+
+/**
+ * Default texture combine environment state. This is used to initialize
+ * a context's texture units and as the basis for converting "classic"
+ * texture environmnets to ARB_texture_env_combine style values.
+ */
+static const struct gl_tex_env_combine_state default_combine_state = {
+ GL_MODULATE, GL_MODULATE,
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
+ { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
+ 0, 0,
+ 2, 2
+};
+
+
+
+/**
+ * Used by glXCopyContext to copy texture state from one context to another.
+ */
+void
+_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
+{
+ GLuint u, tex;
+
+ ASSERT(src);
+ ASSERT(dst);
+
+ dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
+ dst->Texture._GenFlags = src->Texture._GenFlags;
+ dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
+ dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
+ dst->Texture.SharedPalette = src->Texture.SharedPalette;
+
+ /* per-unit state */
+ for (u = 0; u < src->Const.MaxTextureImageUnits; u++) {
+ dst->Texture.Unit[u].Enabled = src->Texture.Unit[u].Enabled;
+ dst->Texture.Unit[u].EnvMode = src->Texture.Unit[u].EnvMode;
+ COPY_4V(dst->Texture.Unit[u].EnvColor, src->Texture.Unit[u].EnvColor);
+ dst->Texture.Unit[u].TexGenEnabled = src->Texture.Unit[u].TexGenEnabled;
+ dst->Texture.Unit[u].GenS = src->Texture.Unit[u].GenS;
+ dst->Texture.Unit[u].GenT = src->Texture.Unit[u].GenT;
+ dst->Texture.Unit[u].GenR = src->Texture.Unit[u].GenR;
+ dst->Texture.Unit[u].GenQ = src->Texture.Unit[u].GenQ;
+ dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias;
+
+ /* GL_EXT_texture_env_combine */
+ dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
+
+ /* GL_ATI_envmap_bumpmap - need this? */
+ dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
+ COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
+
+
+ /* copy texture object bindings, not contents of texture objects */
+ _mesa_lock_context_textures(dst);
+
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&dst->Texture.Unit[u].CurrentTex[tex],
+ src->Texture.Unit[u].CurrentTex[tex]);
+ }
+
+ _mesa_unlock_context_textures(dst);
+ }
+}
+
+
+/*
+ * For debugging
+ */
+void
+_mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
+{
+ const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
+ _mesa_printf("Texture Unit %d\n", unit);
+ _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
+ _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+ _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+ _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
+ _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
+ _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
+ _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
+ _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
+ _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
+ _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
+ _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
+ _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
+ _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
+ _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
+ _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
+ _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
+ _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
+ _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
+}
+
+
+
+/**********************************************************************/
+/* Texture Environment */
+/**********************************************************************/
+
+/**
+ * Convert "classic" texture environment to ARB_texture_env_combine style
+ * environments.
+ *
+ * \param state texture_env_combine state vector to be filled-in.
+ * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
+ * \c GL_BLEND, \c GL_DECAL, etc.).
+ * \param texBaseFormat Base format of the texture associated with the
+ * texture unit.
+ */
+static void
+calculate_derived_texenv( struct gl_tex_env_combine_state *state,
+ GLenum mode, GLenum texBaseFormat )
+{
+ GLenum mode_rgb;
+ GLenum mode_a;
+
+ *state = default_combine_state;
+
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_RGBA:
+ break;
+
+ case GL_LUMINANCE:
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ state->SourceA[0] = GL_PREVIOUS;
+ break;
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid texBaseFormat 0x%x in calculate_derived_texenv",
+ texBaseFormat);
+ return;
+ }
+
+ if (mode == GL_REPLACE_EXT)
+ mode = GL_REPLACE;
+
+ switch (mode) {
+ case GL_REPLACE:
+ case GL_MODULATE:
+ mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
+ mode_a = mode;
+ break;
+
+ case GL_DECAL:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_REPLACE;
+
+ state->SourceA[0] = GL_PREVIOUS;
+
+ /* Having alpha / luminance / intensity textures replace using the
+ * incoming fragment color matches the definition in NV_texture_shader.
+ * The 1.5 spec simply marks these as "undefined".
+ */
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ state->SourceRGB[0] = GL_PREVIOUS;
+ break;
+ case GL_RGB:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_RGBA:
+ state->SourceRGB[2] = GL_TEXTURE;
+ break;
+ }
+ break;
+
+ case GL_BLEND:
+ mode_rgb = GL_INTERPOLATE;
+ mode_a = GL_MODULATE;
+
+ switch (texBaseFormat) {
+ case GL_ALPHA:
+ mode_rgb = GL_REPLACE;
+ break;
+ case GL_INTENSITY:
+ mode_a = GL_INTERPOLATE;
+ state->SourceA[0] = GL_CONSTANT;
+ state->OperandA[2] = GL_SRC_ALPHA;
+ /* FALLTHROUGH */
+ case GL_LUMINANCE:
+ case GL_RGB:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ case GL_YCBCR_MESA:
+ case GL_DUDV_ATI:
+ state->SourceRGB[2] = GL_TEXTURE;
+ state->SourceA[2] = GL_TEXTURE;
+ state->SourceRGB[0] = GL_CONSTANT;
+ state->OperandRGB[2] = GL_SRC_COLOR;
+ break;
+ }
+ break;
+
+ case GL_ADD:
+ mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
+ mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
+ break;
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid texture env mode 0x%x in calculate_derived_texenv",
+ mode);
+ return;
+ }
+
+ state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
+ ? mode_rgb : GL_REPLACE;
+ state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
+ ? mode_a : GL_REPLACE;
+}
+
+
+
+
+/* GL_ARB_multitexture */
+void GLAPIENTRY
+_mesa_ActiveTextureARB(GLenum texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint texUnit = texture - GL_TEXTURE0;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ _mesa_debug(ctx, "glActiveTexture %s\n",
+ _mesa_lookup_enum_by_nr(texture));
+
+ if (texUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
+ return;
+ }
+
+ if (ctx->Texture.CurrentUnit == texUnit)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+
+ ctx->Texture.CurrentUnit = texUnit;
+ if (ctx->Transform.MatrixMode == GL_TEXTURE) {
+ /* update current stack pointer */
+ ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
+ }
+
+ if (ctx->Driver.ActiveTexture) {
+ (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
+ }
+}
+
+
+/* GL_ARB_multitexture */
+void GLAPIENTRY
+_mesa_ClientActiveTextureARB(GLenum texture)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLuint texUnit = texture - GL_TEXTURE0;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.ActiveTexture = texUnit;
+}
+
+
+
+/**********************************************************************/
+/***** State management *****/
+/**********************************************************************/
+
+
+/**
+ * \note This routine refers to derived texture attribute values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_textures(), below.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_matrices( GLcontext *ctx )
+{
+ GLuint u;
+
+ ctx->Texture._TexMatEnabled = 0x0;
+
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ if (_math_matrix_is_dirty(ctx->TextureMatrixStack[u].Top)) {
+ _math_matrix_analyse( ctx->TextureMatrixStack[u].Top );
+
+ if (ctx->Texture.Unit[u]._ReallyEnabled &&
+ ctx->TextureMatrixStack[u].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(u);
+
+ if (ctx->Driver.TextureMatrix)
+ ctx->Driver.TextureMatrix( ctx, u, ctx->TextureMatrixStack[u].Top);
+ }
+ }
+}
+
+
+/**
+ * Examine texture unit's combine/env state to update derived state.
+ */
+static void
+update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
+{
+ struct gl_tex_env_combine_state *combine;
+
+ /* Set the texUnit->_CurrentCombine field to point to the user's combiner
+ * state, or the combiner state which is derived from traditional texenv
+ * mode.
+ */
+ if (texUnit->EnvMode == GL_COMBINE ||
+ texUnit->EnvMode == GL_COMBINE4_NV) {
+ texUnit->_CurrentCombine = & texUnit->Combine;
+ }
+ else {
+ const struct gl_texture_object *texObj = texUnit->_Current;
+ GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
+ if (format == GL_COLOR_INDEX) {
+ format = GL_RGBA; /* a bit of a hack */
+ }
+ else if (format == GL_DEPTH_COMPONENT ||
+ format == GL_DEPTH_STENCIL_EXT) {
+ format = texObj->DepthMode;
+ }
+ calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ }
+
+ combine = texUnit->_CurrentCombine;
+
+ /* Determine number of source RGB terms in the combiner function */
+ switch (combine->ModeRGB) {
+ case GL_REPLACE:
+ combine->_NumArgsRGB = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsRGB = 4;
+ else
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ combine->_NumArgsRGB = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsRGB = 3;
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ /* no real arguments for this case */
+ combine->_NumArgsRGB = 0;
+ break;
+ default:
+ combine->_NumArgsRGB = 0;
+ _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
+ return;
+ }
+
+ /* Determine number of source Alpha terms in the combiner function */
+ switch (combine->ModeA) {
+ case GL_REPLACE:
+ combine->_NumArgsA = 1;
+ break;
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ if (texUnit->EnvMode == GL_COMBINE4_NV)
+ combine->_NumArgsA = 4;
+ else
+ combine->_NumArgsA = 2;
+ break;
+ case GL_MODULATE:
+ case GL_SUBTRACT:
+ combine->_NumArgsA = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ combine->_NumArgsA = 3;
+ break;
+ default:
+ combine->_NumArgsA = 0;
+ _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
+ break;
+ }
+}
+
+
+/**
+ * \note This routine refers to derived texture matrix values to
+ * compute the ENABLE_TEXMAT flags, but is only called on
+ * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
+ * flags are updated by _mesa_update_texture_matrices, above.
+ *
+ * \param ctx GL context.
+ */
+static void
+update_texture_state( GLcontext *ctx )
+{
+ GLuint unit;
+ struct gl_fragment_program *fprog = NULL;
+ struct gl_vertex_program *vprog = NULL;
+ GLbitfield enabledFragUnits = 0x0;
+
+ if (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->LinkStatus) {
+ fprog = ctx->Shader.CurrentProgram->FragmentProgram;
+ vprog = ctx->Shader.CurrentProgram->VertexProgram;
+ }
+ else {
+ if (ctx->FragmentProgram._Enabled) {
+ fprog = ctx->FragmentProgram.Current;
+ }
+ if (ctx->VertexProgram._Enabled) {
+ /* XXX enable this if/when non-shader vertex programs get
+ * texture fetches:
+ vprog = ctx->VertexProgram.Current;
+ */
+ }
+ }
+
+ /* TODO: only set this if there are actual changes */
+ ctx->NewState |= _NEW_TEXTURE;
+
+ ctx->Texture._EnabledUnits = 0x0;
+ ctx->Texture._GenFlags = 0x0;
+ ctx->Texture._TexMatEnabled = 0x0;
+ ctx->Texture._TexGenEnabled = 0x0;
+
+ /*
+ * Update texture unit state.
+ */
+ for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLbitfield enabledVertTargets = 0x0;
+ GLbitfield enabledFragTargets = 0x0;
+ GLbitfield enabledTargets = 0x0;
+ GLuint texIndex;
+
+ /* Get the bitmask of texture target enables.
+ * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
+ * which texture targets are enabled (fixed function) or referenced
+ * by a fragment shader/program. When multiple flags are set, we'll
+ * settle on the one with highest priority (see below).
+ */
+ if (vprog) {
+ enabledVertTargets |= vprog->Base.TexturesUsed[unit];
+ }
+
+ if (fprog) {
+ enabledFragTargets |= fprog->Base.TexturesUsed[unit];
+ }
+ else {
+ /* fixed-function fragment program */
+ enabledFragTargets |= texUnit->Enabled;
+ }
+
+ enabledTargets = enabledVertTargets | enabledFragTargets;
+
+ texUnit->_ReallyEnabled = 0x0;
+
+ if (enabledTargets == 0x0) {
+ /* neither vertex nor fragment processing uses this unit */
+ continue;
+ }
+
+ /* Look for the highest priority texture target that's enabled (or used
+ * by the vert/frag shaders) and "complete". That's the one we'll use
+ * for texturing. If we're using vert/frag program we're guaranteed
+ * that bitcount(enabledBits) <= 1.
+ * Note that the TEXTURE_x_INDEX values are in high to low priority.
+ */
+ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
+ if (enabledTargets & (1 << texIndex)) {
+ struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex];
+ if (!texObj->_Complete) {
+ _mesa_test_texobj_completeness(ctx, texObj);
+ }
+ if (texObj->_Complete) {
+ texUnit->_ReallyEnabled = 1 << texIndex;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ break;
+ }
+ }
+ }
+
+ if (!texUnit->_ReallyEnabled) {
+ if (fprog) {
+ /* If we get here it means the shader is expecting a texture
+ * object, but there isn't one (or it's incomplete). Use the
+ * fallback texture.
+ */
+ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+ texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ }
+ else {
+ /* fixed-function: texture unit is really disabled */
+ continue;
+ }
+ }
+
+ /* if we get here, we know this texture unit is enabled */
+
+ ctx->Texture._EnabledUnits |= (1 << unit);
+
+ if (enabledFragTargets)
+ enabledFragUnits |= (1 << unit);
+
+ update_tex_combine(ctx, texUnit);
+ }
+
+
+ /* Determine which texture coordinate sets are actually needed */
+ if (fprog) {
+ const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
+ ctx->Texture._EnabledCoordUnits
+ = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
+ }
+ else {
+ ctx->Texture._EnabledCoordUnits = enabledFragUnits;
+ }
+
+ /* Setup texgen for those texture coordinate sets that are in use */
+ for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ texUnit->_GenFlags = 0x0;
+
+ if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
+ continue;
+
+ if (texUnit->TexGenEnabled) {
+ if (texUnit->TexGenEnabled & S_BIT) {
+ texUnit->_GenFlags |= texUnit->GenS._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & T_BIT) {
+ texUnit->_GenFlags |= texUnit->GenT._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & R_BIT) {
+ texUnit->_GenFlags |= texUnit->GenR._ModeBit;
+ }
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
+ }
+
+ ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
+ ctx->Texture._GenFlags |= texUnit->_GenFlags;
+ }
+
+ if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
+ ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
+ }
+}
+
+
+/**
+ * Update texture-related derived state.
+ */
+void
+_mesa_update_texture( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & _NEW_TEXTURE_MATRIX)
+ update_texture_matrices( ctx );
+
+ if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
+ update_texture_state( ctx );
+}
+
+
+/**********************************************************************/
+/***** Initialization *****/
+/**********************************************************************/
+
+/**
+ * Allocate the proxy textures for the given context.
+ *
+ * \param ctx the context to allocate proxies for.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure
+ *
+ * If run out of memory part way through the allocations, clean up and return
+ * GL_FALSE.
+ */
+static GLboolean
+alloc_proxy_textures( GLcontext *ctx )
+{
+ static const GLenum targets[] = {
+ GL_TEXTURE_1D,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_3D,
+ GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_RECTANGLE_NV,
+ GL_TEXTURE_1D_ARRAY_EXT,
+ GL_TEXTURE_2D_ARRAY_EXT
+ };
+ GLint tgt;
+
+ ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
+
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ if (!(ctx->Texture.ProxyTex[tgt]
+ = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
+ /* out of memory, free what we did allocate */
+ while (--tgt >= 0) {
+ ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
+ }
+ return GL_FALSE;
+ }
+ }
+
+ assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
+ return GL_TRUE;
+}
+
+
+/**
+ * Initialize a texture unit.
+ *
+ * \param ctx GL context.
+ * \param unit texture unit number to be initialized.
+ */
+static void
+init_texture_unit( GLcontext *ctx, GLuint unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLuint tex;
+
+ texUnit->EnvMode = GL_MODULATE;
+ ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->Combine = default_combine_state;
+ texUnit->_EnvMode = default_combine_state;
+ texUnit->_CurrentCombine = & texUnit->_EnvMode;
+ texUnit->BumpTarget = GL_TEXTURE0;
+
+ texUnit->TexGenEnabled = 0x0;
+ texUnit->GenS.Mode = GL_EYE_LINEAR;
+ texUnit->GenT.Mode = GL_EYE_LINEAR;
+ texUnit->GenR.Mode = GL_EYE_LINEAR;
+ texUnit->GenQ.Mode = GL_EYE_LINEAR;
+ texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
+ texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
+
+ /* Yes, these plane coefficients are correct! */
+ ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
+
+ /* no mention of this in spec, but maybe id matrix expected? */
+ ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
+
+ /* initialize current texture object ptrs to the shared default objects */
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
+}
+
+
+/**
+ * Initialize texture state for the given context.
+ */
+GLboolean
+_mesa_init_texture(GLcontext *ctx)
+{
+ GLuint u;
+
+ /* Texture group */
+ ctx->Texture.CurrentUnit = 0; /* multitexture */
+ ctx->Texture._EnabledUnits = 0x0;
+ ctx->Texture.SharedPalette = GL_FALSE;
+#if FEATURE_colortable
+ _mesa_init_colortable(&ctx->Texture.Palette);
+#endif
+
+ for (u = 0; u < MAX_TEXTURE_UNITS; u++)
+ init_texture_unit(ctx, u);
+
+ /* After we're done initializing the context's texture state the default
+ * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
+ */
+ assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
+ >= MAX_TEXTURE_UNITS + 1);
+
+ /* Allocate proxy textures */
+ if (!alloc_proxy_textures( ctx ))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Free dynamically-allocted texture data attached to the given context.
+ */
+void
+_mesa_free_texture_data(GLcontext *ctx)
+{
+ GLuint u, tgt;
+
+ /* unreference current textures */
+ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
+ /* The _Current texture could account for another reference */
+ _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
+
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
+ _mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
+ }
+ }
+
+ /* Free proxy texture objects */
+ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
+ ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
+
+#if FEATURE_colortable
+ for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++)
+ _mesa_free_colortable_data(&ctx->Texture.Unit[u].ColorTable);
+#endif
+}
+
+
+/**
+ * Update the default texture objects in the given context to reference those
+ * specified in the shared state and release those referencing the old
+ * shared state.
+ */
+void
+_mesa_update_default_objects_texture(GLcontext *ctx)
+{
+ GLuint u, tex;
+
+ for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
+ for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
+ _mesa_reference_texobj(&texUnit->CurrentTex[tex],
+ ctx->Shared->DefaultTex[tex]);
+ }
+ }
+}
diff --git a/mesalib/src/mesa/main/texstate.h b/mesalib/src/mesa/main/texstate.h
new file mode 100644
index 000000000..17ac68000
--- /dev/null
+++ b/mesalib/src/mesa/main/texstate.h
@@ -0,0 +1,91 @@
+/**
+ * \file texstate.h
+ * Texture state management.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "mtypes.h"
+
+
+/**
+ * Return pointer to current texture unit.
+ * This the texture unit set by glActiveTexture(), not glClientActiveTexture().
+ */
+static INLINE struct gl_texture_unit *
+_mesa_get_current_tex_unit(GLcontext *ctx)
+{
+ ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit));
+ return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
+}
+
+
+extern void
+_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst );
+
+extern void
+_mesa_print_texunit_state( GLcontext *ctx, GLuint unit );
+
+
+
+/**
+ * \name Called from API
+ */
+/*@{*/
+
+extern void GLAPIENTRY
+_mesa_ActiveTextureARB( GLenum target );
+
+extern void GLAPIENTRY
+_mesa_ClientActiveTextureARB( GLenum target );
+
+/*@}*/
+
+
+/**
+ * \name Initialization, state maintenance
+ */
+/*@{*/
+
+extern void
+_mesa_update_texture( GLcontext *ctx, GLuint new_state );
+
+extern GLboolean
+_mesa_init_texture( GLcontext *ctx );
+
+extern void
+_mesa_free_texture_data( GLcontext *ctx );
+
+extern void
+_mesa_update_default_objects_texture(GLcontext *ctx);
+
+/*@}*/
+
+#endif
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
new file mode 100644
index 000000000..a22db628d
--- /dev/null
+++ b/mesalib/src/mesa/main/texstore.c
@@ -0,0 +1,3925 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008-2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Brian Paul
+ */
+
+/**
+ * The GL texture image functions in teximage.c basically just do
+ * error checking and data structure allocation. They in turn call
+ * device driver functions which actually copy/convert/store the user's
+ * texture image data.
+ *
+ * However, most device drivers will be able to use the fallback functions
+ * in this file. That is, most drivers will have the following bit of
+ * code:
+ * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+ * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
+ * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ * etc...
+ *
+ * Texture image processing is actually kind of complicated. We have to do:
+ * Format/type conversions
+ * pixel unpacking
+ * pixel transfer (scale, bais, lookup, convolution!, etc)
+ *
+ * These functions can handle most everything, including processing full
+ * images and sub-images.
+ */
+
+
+#include "glheader.h"
+#include "bufferobj.h"
+#include "colormac.h"
+#include "context.h"
+#if FEATURE_convolve
+#include "convolve.h"
+#endif
+#include "image.h"
+#include "macros.h"
+#include "mipmap.h"
+#include "imports.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "enums.h"
+
+
+enum {
+ ZERO = 4,
+ ONE = 5
+};
+
+
+/**
+ * Return GL_TRUE if the given image format is one that be converted
+ * to another format by swizzling.
+ */
+static GLboolean
+can_swizzle(GLenum logicalBaseFormat)
+{
+ switch (logicalBaseFormat) {
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_BGR:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+
+enum {
+ IDX_LUMINANCE = 0,
+ IDX_ALPHA,
+ IDX_INTENSITY,
+ IDX_LUMINANCE_ALPHA,
+ IDX_RGB,
+ IDX_RGBA,
+ IDX_RED,
+ IDX_GREEN,
+ IDX_BLUE,
+ IDX_BGR,
+ IDX_BGRA,
+ IDX_ABGR,
+ MAX_IDX
+};
+
+#define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
+#define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
+#define MAP3(x,y,z) MAP4(x, y, z, ZERO)
+#define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
+
+
+static const struct {
+ GLubyte format_idx;
+ GLubyte to_rgba[6];
+ GLubyte from_rgba[6];
+} mappings[MAX_IDX] =
+{
+ {
+ IDX_LUMINANCE,
+ MAP4(0,0,0,ONE),
+ MAP1(0)
+ },
+
+ {
+ IDX_ALPHA,
+ MAP4(ZERO, ZERO, ZERO, 0),
+ MAP1(3)
+ },
+
+ {
+ IDX_INTENSITY,
+ MAP4(0, 0, 0, 0),
+ MAP1(0),
+ },
+
+ {
+ IDX_LUMINANCE_ALPHA,
+ MAP4(0,0,0,1),
+ MAP2(0,3)
+ },
+
+ {
+ IDX_RGB,
+ MAP4(0,1,2,ONE),
+ MAP3(0,1,2)
+ },
+
+ {
+ IDX_RGBA,
+ MAP4(0,1,2,3),
+ MAP4(0,1,2,3),
+ },
+
+
+ {
+ IDX_RED,
+ MAP4(0, ZERO, ZERO, ONE),
+ MAP1(0),
+ },
+
+ {
+ IDX_GREEN,
+ MAP4(ZERO, 0, ZERO, ONE),
+ MAP1(1),
+ },
+
+ {
+ IDX_BLUE,
+ MAP4(ZERO, ZERO, 0, ONE),
+ MAP1(2),
+ },
+
+ {
+ IDX_BGR,
+ MAP4(2,1,0,ONE),
+ MAP3(2,1,0)
+ },
+
+ {
+ IDX_BGRA,
+ MAP4(2,1,0,3),
+ MAP4(2,1,0,3)
+ },
+
+ {
+ IDX_ABGR,
+ MAP4(3,2,1,0),
+ MAP4(3,2,1,0)
+ },
+};
+
+
+
+/**
+ * Convert a GL image format enum to an IDX_* value (see above).
+ */
+static int
+get_map_idx(GLenum value)
+{
+ switch (value) {
+ case GL_LUMINANCE: return IDX_LUMINANCE;
+ case GL_ALPHA: return IDX_ALPHA;
+ case GL_INTENSITY: return IDX_INTENSITY;
+ case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA;
+ case GL_RGB: return IDX_RGB;
+ case GL_RGBA: return IDX_RGBA;
+ case GL_RED: return IDX_RED;
+ case GL_GREEN: return IDX_GREEN;
+ case GL_BLUE: return IDX_BLUE;
+ case GL_BGR: return IDX_BGR;
+ case GL_BGRA: return IDX_BGRA;
+ case GL_ABGR_EXT: return IDX_ABGR;
+ default:
+ _mesa_problem(NULL, "Unexpected inFormat");
+ return 0;
+ }
+}
+
+
+/**
+ * When promoting texture formats (see below) we need to compute the
+ * mapping of dest components back to source components.
+ * This function does that.
+ * \param inFormat the incoming format of the texture
+ * \param outFormat the final texture format
+ * \return map[6] a full 6-component map
+ */
+static void
+compute_component_mapping(GLenum inFormat, GLenum outFormat,
+ GLubyte *map)
+{
+ const int inFmt = get_map_idx(inFormat);
+ const int outFmt = get_map_idx(outFormat);
+ const GLubyte *in2rgba = mappings[inFmt].to_rgba;
+ const GLubyte *rgba2out = mappings[outFmt].from_rgba;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ map[i] = in2rgba[rgba2out[i]];
+
+ map[ZERO] = ZERO;
+ map[ONE] = ONE;
+
+/*
+ _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
+ inFormat, _mesa_lookup_enum_by_nr(inFormat),
+ outFormat, _mesa_lookup_enum_by_nr(outFormat),
+ map[0],
+ map[1],
+ map[2],
+ map[3],
+ map[4],
+ map[5]);
+*/
+}
+
+
+#if !FEATURE_convolve
+static void
+_mesa_adjust_image_for_convolution(GLcontext *ctx, GLuint dims,
+ GLsizei *srcWidth, GLsizei *srcHeight)
+{
+ /* no-op */
+}
+#endif
+
+
+/**
+ * Make a temporary (color) texture image with GLfloat components.
+ * Apply all needed pixel unpacking and pixel transfer operations.
+ * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
+ * Suppose the user specifies GL_LUMINANCE as the internal texture format
+ * but the graphics hardware doesn't support luminance textures. So, might
+ * use an RGB hardware format instead.
+ * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
+ *
+ * \param ctx the rendering context
+ * \param dims image dimensions: 1, 2 or 3
+ * \param logicalBaseFormat basic texture derived from the user's
+ * internal texture format value
+ * \param textureBaseFormat the actual basic format of the texture
+ * \param srcWidth source image width
+ * \param srcHeight source image height
+ * \param srcDepth source image depth
+ * \param srcFormat source image format
+ * \param srcType source image type
+ * \param srcAddr source image address
+ * \param srcPacking source image pixel packing
+ * \return resulting image with format = textureBaseFormat and type = GLfloat.
+ */
+static GLfloat *
+make_temp_float_image(GLcontext *ctx, GLuint dims,
+ GLenum logicalBaseFormat,
+ GLenum textureBaseFormat,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking)
+{
+ GLuint transferOps = ctx->_ImageTransferState;
+ GLfloat *tempImage;
+
+ ASSERT(dims >= 1 && dims <= 3);
+
+ ASSERT(logicalBaseFormat == GL_RGBA ||
+ logicalBaseFormat == GL_RGB ||
+ logicalBaseFormat == GL_LUMINANCE_ALPHA ||
+ logicalBaseFormat == GL_LUMINANCE ||
+ logicalBaseFormat == GL_ALPHA ||
+ logicalBaseFormat == GL_INTENSITY ||
+ logicalBaseFormat == GL_COLOR_INDEX ||
+ logicalBaseFormat == GL_DEPTH_COMPONENT);
+
+ ASSERT(textureBaseFormat == GL_RGBA ||
+ textureBaseFormat == GL_RGB ||
+ textureBaseFormat == GL_LUMINANCE_ALPHA ||
+ textureBaseFormat == GL_LUMINANCE ||
+ textureBaseFormat == GL_ALPHA ||
+ textureBaseFormat == GL_INTENSITY ||
+ textureBaseFormat == GL_COLOR_INDEX ||
+ textureBaseFormat == GL_DEPTH_COMPONENT);
+
+ /* conventional color image */
+
+ if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
+ (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
+ (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
+ /* need image convolution */
+ const GLuint preConvTransferOps
+ = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
+ const GLuint postConvTransferOps
+ = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
+ GLint img, row;
+ GLint convWidth, convHeight;
+ GLfloat *convImage;
+
+ /* pre-convolution image buffer (3D) */
+ tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * 4 * sizeof(GLfloat));
+ if (!tempImage)
+ return NULL;
+
+ /* post-convolution image buffer (2D) */
+ convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
+ * 4 * sizeof(GLfloat));
+ if (!convImage) {
+ _mesa_free(tempImage);
+ return NULL;
+ }
+
+ /* loop over 3D image slices */
+ for (img = 0; img < srcDepth; img++) {
+ GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
+
+ /* unpack and do transfer ops up to convolution */
+ for (row = 0; row < srcHeight; row++) {
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, img, row, 0);
+ _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
+ srcFormat, srcType, src,
+ srcPacking,
+ preConvTransferOps);
+ dst += srcWidth * 4;
+ }
+
+ /* size after optional convolution */
+ convWidth = srcWidth;
+ convHeight = srcHeight;
+
+#if FEATURE_convolve
+ /* do convolution */
+ {
+ GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
+ if (dims == 1) {
+ ASSERT(ctx->Pixel.Convolution1DEnabled);
+ _mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
+ }
+ else {
+ if (ctx->Pixel.Convolution2DEnabled) {
+ _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
+ src, convImage);
+ }
+ else {
+ ASSERT(ctx->Pixel.Separable2DEnabled);
+ _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
+ src, convImage);
+ }
+ }
+ }
+#endif
+ /* do post-convolution transfer and pack into tempImage */
+ {
+ const GLint logComponents
+ = _mesa_components_in_format(logicalBaseFormat);
+ const GLfloat *src = convImage;
+ GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
+ for (row = 0; row < convHeight; row++) {
+ _mesa_pack_rgba_span_float(ctx, convWidth,
+ (GLfloat (*)[4]) src,
+ logicalBaseFormat, GL_FLOAT,
+ dst, &ctx->DefaultPacking,
+ postConvTransferOps);
+ src += convWidth * 4;
+ dst += convWidth * logComponents;
+ }
+ }
+ } /* loop over 3D image slices */
+
+ _mesa_free(convImage);
+
+ /* might need these below */
+ srcWidth = convWidth;
+ srcHeight = convHeight;
+ }
+ else {
+ /* no convolution */
+ const GLint components = _mesa_components_in_format(logicalBaseFormat);
+ const GLint srcStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLfloat *dst;
+ GLint img, row;
+
+ tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * components * sizeof(GLfloat));
+ if (!tempImage)
+ return NULL;
+
+ dst = tempImage;
+ for (img = 0; img < srcDepth; img++) {
+ const GLubyte *src
+ = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
+ dst, srcFormat, srcType, src,
+ srcPacking, transferOps);
+ dst += srcWidth * components;
+ src += srcStride;
+ }
+ }
+ }
+
+ if (logicalBaseFormat != textureBaseFormat) {
+ /* more work */
+ GLint texComponents = _mesa_components_in_format(textureBaseFormat);
+ GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
+ GLfloat *newImage;
+ GLint i, n;
+ GLubyte map[6];
+
+ /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
+ ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
+ textureBaseFormat == GL_LUMINANCE_ALPHA);
+
+ /* The actual texture format should have at least as many components
+ * as the logical texture format.
+ */
+ ASSERT(texComponents >= logComponents);
+
+ newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * texComponents * sizeof(GLfloat));
+ if (!newImage) {
+ _mesa_free(tempImage);
+ return NULL;
+ }
+
+ compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
+
+ n = srcWidth * srcHeight * srcDepth;
+ for (i = 0; i < n; i++) {
+ GLint k;
+ for (k = 0; k < texComponents; k++) {
+ GLint j = map[k];
+ if (j == ZERO)
+ newImage[i * texComponents + k] = 0.0F;
+ else if (j == ONE)
+ newImage[i * texComponents + k] = 1.0F;
+ else
+ newImage[i * texComponents + k] = tempImage[i * logComponents + j];
+ }
+ }
+
+ _mesa_free(tempImage);
+ tempImage = newImage;
+ }
+
+ return tempImage;
+}
+
+
+/**
+ * Make a temporary (color) texture image with GLchan components.
+ * Apply all needed pixel unpacking and pixel transfer operations.
+ * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
+ * Suppose the user specifies GL_LUMINANCE as the internal texture format
+ * but the graphics hardware doesn't support luminance textures. So, might
+ * use an RGB hardware format instead.
+ * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
+ *
+ * \param ctx the rendering context
+ * \param dims image dimensions: 1, 2 or 3
+ * \param logicalBaseFormat basic texture derived from the user's
+ * internal texture format value
+ * \param textureBaseFormat the actual basic format of the texture
+ * \param srcWidth source image width
+ * \param srcHeight source image height
+ * \param srcDepth source image depth
+ * \param srcFormat source image format
+ * \param srcType source image type
+ * \param srcAddr source image address
+ * \param srcPacking source image pixel packing
+ * \return resulting image with format = textureBaseFormat and type = GLchan.
+ */
+GLchan *
+_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
+ GLenum logicalBaseFormat,
+ GLenum textureBaseFormat,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking)
+{
+ GLuint transferOps = ctx->_ImageTransferState;
+ const GLint components = _mesa_components_in_format(logicalBaseFormat);
+ GLboolean freeSrcImage = GL_FALSE;
+ GLint img, row;
+ GLchan *tempImage, *dst;
+
+ ASSERT(dims >= 1 && dims <= 3);
+
+ ASSERT(logicalBaseFormat == GL_RGBA ||
+ logicalBaseFormat == GL_RGB ||
+ logicalBaseFormat == GL_LUMINANCE_ALPHA ||
+ logicalBaseFormat == GL_LUMINANCE ||
+ logicalBaseFormat == GL_ALPHA ||
+ logicalBaseFormat == GL_INTENSITY);
+
+ ASSERT(textureBaseFormat == GL_RGBA ||
+ textureBaseFormat == GL_RGB ||
+ textureBaseFormat == GL_LUMINANCE_ALPHA ||
+ textureBaseFormat == GL_LUMINANCE ||
+ textureBaseFormat == GL_ALPHA ||
+ textureBaseFormat == GL_INTENSITY);
+
+#if FEATURE_convolve
+ if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
+ (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
+ (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
+ /* get convolved image */
+ GLfloat *convImage = make_temp_float_image(ctx, dims,
+ logicalBaseFormat,
+ logicalBaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ if (!convImage)
+ return NULL;
+ /* the convolved image is our new source image */
+ srcAddr = convImage;
+ srcFormat = logicalBaseFormat;
+ srcType = GL_FLOAT;
+ srcPacking = &ctx->DefaultPacking;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ transferOps = 0;
+ freeSrcImage = GL_TRUE;
+ }
+#endif
+
+ /* unpack and transfer the source image */
+ tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * components * sizeof(GLchan));
+ if (!tempImage)
+ return NULL;
+
+ dst = tempImage;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat,
+ srcType);
+ const GLubyte *src
+ = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
+ srcFormat, srcType, src, srcPacking,
+ transferOps);
+ dst += srcWidth * components;
+ src += srcStride;
+ }
+ }
+
+ /* If we made a temporary image for convolution, free it here */
+ if (freeSrcImage) {
+ _mesa_free((void *) srcAddr);
+ }
+
+ if (logicalBaseFormat != textureBaseFormat) {
+ /* one more conversion step */
+ GLint texComponents = _mesa_components_in_format(textureBaseFormat);
+ GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
+ GLchan *newImage;
+ GLint i, n;
+ GLubyte map[6];
+
+ /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
+ ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
+ textureBaseFormat == GL_LUMINANCE_ALPHA);
+
+ /* The actual texture format should have at least as many components
+ * as the logical texture format.
+ */
+ ASSERT(texComponents >= logComponents);
+
+ newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * texComponents * sizeof(GLchan));
+ if (!newImage) {
+ _mesa_free(tempImage);
+ return NULL;
+ }
+
+ compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
+
+ n = srcWidth * srcHeight * srcDepth;
+ for (i = 0; i < n; i++) {
+ GLint k;
+ for (k = 0; k < texComponents; k++) {
+ GLint j = map[k];
+ if (j == ZERO)
+ newImage[i * texComponents + k] = 0;
+ else if (j == ONE)
+ newImage[i * texComponents + k] = CHAN_MAX;
+ else
+ newImage[i * texComponents + k] = tempImage[i * logComponents + j];
+ }
+ }
+
+ _mesa_free(tempImage);
+ tempImage = newImage;
+ }
+
+ return tempImage;
+}
+
+
+/**
+ * Copy GLubyte pixels from <src> to <dst> with swizzling.
+ * \param dst destination pixels
+ * \param dstComponents number of color components in destination pixels
+ * \param src source pixels
+ * \param srcComponents number of color components in source pixels
+ * \param map the swizzle mapping. map[X] says where to find the X component
+ * in the source image's pixels. For example, if the source image
+ * is GL_BGRA and X = red, map[0] yields 2.
+ * \param count number of pixels to copy/swizzle.
+ */
+static void
+swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
+ GLuint srcComponents, const GLubyte *map, GLuint count)
+{
+#define SWZ_CPY(dst, src, count, dstComps, srcComps) \
+ do { \
+ GLuint i; \
+ for (i = 0; i < count; i++) { \
+ GLuint j; \
+ if (srcComps == 4) { \
+ COPY_4UBV(tmp, src); \
+ } \
+ else { \
+ for (j = 0; j < srcComps; j++) { \
+ tmp[j] = src[j]; \
+ } \
+ } \
+ src += srcComps; \
+ for (j = 0; j < dstComps; j++) { \
+ dst[j] = tmp[map[j]]; \
+ } \
+ dst += dstComps; \
+ } \
+ } while (0)
+
+ GLubyte tmp[6];
+
+ tmp[ZERO] = 0x0;
+ tmp[ONE] = 0xff;
+
+ ASSERT(srcComponents <= 4);
+ ASSERT(dstComponents <= 4);
+
+ switch (dstComponents) {
+ case 4:
+ switch (srcComponents) {
+ case 4:
+ SWZ_CPY(dst, src, count, 4, 4);
+ break;
+ case 3:
+ SWZ_CPY(dst, src, count, 4, 3);
+ break;
+ case 2:
+ SWZ_CPY(dst, src, count, 4, 2);
+ break;
+ case 1:
+ SWZ_CPY(dst, src, count, 4, 1);
+ break;
+ default:
+ ;
+ }
+ break;
+ case 3:
+ switch (srcComponents) {
+ case 4:
+ SWZ_CPY(dst, src, count, 3, 4);
+ break;
+ case 3:
+ SWZ_CPY(dst, src, count, 3, 3);
+ break;
+ case 2:
+ SWZ_CPY(dst, src, count, 3, 2);
+ break;
+ case 1:
+ SWZ_CPY(dst, src, count, 3, 1);
+ break;
+ default:
+ ;
+ }
+ break;
+ case 2:
+ switch (srcComponents) {
+ case 4:
+ SWZ_CPY(dst, src, count, 2, 4);
+ break;
+ case 3:
+ SWZ_CPY(dst, src, count, 2, 3);
+ break;
+ case 2:
+ SWZ_CPY(dst, src, count, 2, 2);
+ break;
+ case 1:
+ SWZ_CPY(dst, src, count, 2, 1);
+ break;
+ default:
+ ;
+ }
+ break;
+ case 1:
+ switch (srcComponents) {
+ case 4:
+ SWZ_CPY(dst, src, count, 1, 4);
+ break;
+ case 3:
+ SWZ_CPY(dst, src, count, 1, 3);
+ break;
+ case 2:
+ SWZ_CPY(dst, src, count, 1, 2);
+ break;
+ case 1:
+ SWZ_CPY(dst, src, count, 1, 1);
+ break;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+#undef SWZ_CPY
+}
+
+
+
+static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE };
+static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE };
+
+/* Deal with the _REV input types:
+ */
+static const GLubyte *
+type_mapping( GLenum srcType )
+{
+ switch (srcType) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return map_identity;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ return _mesa_little_endian() ? map_3210 : map_identity;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ return _mesa_little_endian() ? map_identity : map_3210;
+ default:
+ return NULL;
+ }
+}
+
+/* Mapping required if input type is
+ */
+static const GLubyte *
+byteswap_mapping( GLboolean swapBytes,
+ GLenum srcType )
+{
+ if (!swapBytes)
+ return map_identity;
+
+ switch (srcType) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return map_identity;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ return map_3210;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/**
+ * Transfer a GLubyte texture image with component swizzling.
+ */
+static void
+_mesa_swizzle_ubyte_image(GLcontext *ctx,
+ GLuint dimensions,
+ GLenum srcFormat,
+ GLenum srcType,
+
+ GLenum baseInternalFormat,
+
+ const GLubyte *rgba2dst,
+ GLuint dstComponents,
+
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride,
+ const GLuint *dstImageOffsets,
+
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking )
+{
+ GLint srcComponents = _mesa_components_in_format(srcFormat);
+ const GLubyte *srctype2ubyte, *swap;
+ GLubyte map[4], src2base[6], base2rgba[6];
+ GLint i;
+ const GLint srcRowStride =
+ _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, GL_UNSIGNED_BYTE);
+ const GLint srcImageStride
+ = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
+ GL_UNSIGNED_BYTE);
+ const GLubyte *srcImage
+ = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
+ srcWidth, srcHeight, srcFormat,
+ GL_UNSIGNED_BYTE, 0, 0, 0);
+
+ (void) ctx;
+
+ /* Translate from src->baseInternal->GL_RGBA->dst. This will
+ * correctly deal with RGBA->RGB->RGBA conversions where the final
+ * A value must be 0xff regardless of the incoming alpha values.
+ */
+ compute_component_mapping(srcFormat, baseInternalFormat, src2base);
+ compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba);
+ swap = byteswap_mapping(srcPacking->SwapBytes, srcType);
+ srctype2ubyte = type_mapping(srcType);
+
+
+ for (i = 0; i < 4; i++)
+ map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]];
+
+/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
+
+ if (srcComponents == dstComponents &&
+ srcRowStride == dstRowStride &&
+ srcRowStride == srcWidth * srcComponents &&
+ dimensions < 3) {
+ /* 1 and 2D images only */
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstComponents;
+ swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
+ srcWidth * srcHeight);
+ }
+ else {
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ const GLubyte *srcRow = srcImage;
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstComponents
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstComponents;
+ for (row = 0; row < srcHeight; row++) {
+ swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ srcImage += srcImageStride;
+ }
+ }
+}
+
+
+/**
+ * Teximage storage routine for when a simple memcpy will do.
+ * No pixel transfer operations or special texel encodings allowed.
+ * 1D, 2D and 3D images supported.
+ */
+static void
+memcpy_texture(GLcontext *ctx,
+ GLuint dimensions,
+ const struct gl_texture_format *dstFormat,
+ GLvoid *dstAddr,
+ GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
+ GLint dstRowStride,
+ const GLuint *dstImageOffsets,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking)
+{
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, srcType);
+ const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
+ srcWidth, srcHeight, srcFormat, srcType);
+ const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
+ srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
+ const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
+
+#if 0
+ /* XXX update/re-enable for dstImageOffsets array */
+ const GLint bytesPerImage = srcHeight * bytesPerRow;
+ const GLint bytesPerTexture = srcDepth * bytesPerImage;
+ GLubyte *dstImage = (GLubyte *) dstAddr
+ + dstZoffset * dstImageStride
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+
+ if (dstRowStride == srcRowStride &&
+ dstRowStride == bytesPerRow &&
+ ((dstImageStride == srcImageStride &&
+ dstImageStride == bytesPerImage) ||
+ (srcDepth == 1))) {
+ /* one big memcpy */
+ ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
+ }
+ else
+ {
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ const GLubyte *srcRow = srcImage;
+ GLubyte *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ srcImage += srcImageStride;
+ dstImage += dstImageStride;
+ }
+ }
+#endif
+
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ const GLubyte *srcRow = srcImage;
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ srcImage += srcImageStride;
+ }
+}
+
+
+
+/**
+ * Store an image in any of the formats:
+ * _mesa_texformat_rgba
+ * _mesa_texformat_rgb
+ * _mesa_texformat_alpha
+ * _mesa_texformat_luminance
+ * _mesa_texformat_luminance_alpha
+ * _mesa_texformat_intensity
+ *
+ */
+GLboolean
+_mesa_texstore_rgba(TEXSTORE_PARAMS)
+{
+ const GLint components = _mesa_components_in_format(baseInternalFormat);
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba ||
+ dstFormat == &_mesa_texformat_rgb ||
+ dstFormat == &_mesa_texformat_alpha ||
+ dstFormat == &_mesa_texformat_luminance ||
+ dstFormat == &_mesa_texformat_luminance_alpha ||
+ dstFormat == &_mesa_texformat_intensity);
+ ASSERT(baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB ||
+ baseInternalFormat == GL_ALPHA ||
+ baseInternalFormat == GL_LUMINANCE ||
+ baseInternalFormat == GL_LUMINANCE_ALPHA ||
+ baseInternalFormat == GL_INTENSITY);
+ ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == CHAN_TYPE) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgb &&
+ srcFormat == GL_RGBA &&
+ srcType == CHAN_TYPE) {
+ /* extract RGB from RGBA */
+ GLint img, row, col;
+ for (img = 0; img < srcDepth; img++) {
+ GLchan *dstImage = (GLchan *)
+ ((GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes);
+
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLchan *dstRow = dstImage;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
+ dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
+ }
+ dstRow += dstRowStride / sizeof(GLchan);
+ srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ CHAN_TYPE == GL_UNSIGNED_BYTE &&
+ (srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ const GLubyte *dstmap;
+ GLuint components;
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if (dstFormat == &_mesa_texformat_rgba) {
+ dstmap = mappings[IDX_RGBA].from_rgba;
+ components = 4;
+ }
+ else if (dstFormat == &_mesa_texformat_rgb) {
+ dstmap = mappings[IDX_RGB].from_rgba;
+ components = 3;
+ }
+ else if (dstFormat == &_mesa_texformat_alpha) {
+ dstmap = mappings[IDX_ALPHA].from_rgba;
+ components = 1;
+ }
+ else if (dstFormat == &_mesa_texformat_luminance) {
+ dstmap = mappings[IDX_LUMINANCE].from_rgba;
+ components = 1;
+ }
+ else if (dstFormat == &_mesa_texformat_luminance_alpha) {
+ dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba;
+ components = 2;
+ }
+ else if (dstFormat == &_mesa_texformat_intensity) {
+ dstmap = mappings[IDX_INTENSITY].from_rgba;
+ components = 1;
+ }
+ else {
+ _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba");
+ return GL_FALSE;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, components,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint bytesPerRow;
+ GLint img, row;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ bytesPerRow = srcWidth * components * sizeof(GLchan);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_memcpy(dstRow, src, bytesPerRow);
+ dstRow += dstRowStride;
+ src += srcWidth * components;
+ }
+ }
+
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store a 32-bit integer depth component texture image.
+ */
+GLboolean
+_mesa_texstore_z32(TEXSTORE_PARAMS)
+{
+ const GLuint depthScale = 0xffffffff;
+ (void) dims;
+ ASSERT(dstFormat == &_mesa_texformat_z32);
+ ASSERT(dstFormat->TexelBytes == sizeof(GLuint));
+
+ if (ctx->Pixel.DepthScale == 1.0f &&
+ ctx->Pixel.DepthBias == 0.0f &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_DEPTH_COMPONENT &&
+ srcFormat == GL_DEPTH_COMPONENT &&
+ srcType == GL_UNSIGNED_INT) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, (GLuint *) dstRow,
+ depthScale, srcType, src, srcPacking);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+#define STRIDE_3D 0
+
+/**
+ * Store a 16-bit integer depth component texture image.
+ */
+GLboolean
+_mesa_texstore_z16(TEXSTORE_PARAMS)
+{
+ const GLuint depthScale = 0xffff;
+ (void) dims;
+ ASSERT(dstFormat == &_mesa_texformat_z16);
+ ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
+
+ if (ctx->Pixel.DepthScale == 1.0f &&
+ ctx->Pixel.DepthBias == 0.0f &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_DEPTH_COMPONENT &&
+ srcFormat == GL_DEPTH_COMPONENT &&
+ srcType == GL_UNSIGNED_SHORT) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
+ GLushort *dst16 = (GLushort *) dstRow;
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_SHORT, dst16, depthScale,
+ srcType, src, srcPacking);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store an rgb565 or rgb565_rev texture image.
+ */
+GLboolean
+_mesa_texstore_rgb565(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
+ dstFormat == &_mesa_texformat_rgb565_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgb565 &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_SHORT_5_6_5) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_BYTE &&
+ dims == 2) {
+ /* do optimized tex store */
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
+ srcFormat, srcType);
+ const GLubyte *src = (const GLubyte *)
+ _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
+ srcFormat, srcType, 0, 0, 0);
+ GLubyte *dst = (GLubyte *) dstAddr
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ GLint row, col;
+ for (row = 0; row < srcHeight; row++) {
+ const GLubyte *srcUB = (const GLubyte *) src;
+ GLushort *dstUS = (GLushort *) dst;
+ /* check for byteswapped format */
+ if (dstFormat == &_mesa_texformat_rgb565) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
+ srcUB += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
+ srcUB += 3;
+ }
+ }
+ dst += dstRowStride;
+ src += srcRowStride;
+ }
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ /* check for byteswapped format */
+ if (dstFormat == &_mesa_texformat_rgb565) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
+ */
+GLboolean
+_mesa_texstore_rgba8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
+ dstFormat == &_mesa_texformat_rgba8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba8888 &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
+ (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) {
+ dstmap[3] = 0;
+ dstmap[2] = 1;
+ dstmap[1] = 2;
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[3] = 3;
+ dstmap[2] = 2;
+ dstmap[1] = 1;
+ dstmap[0] = 0;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_rgba8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_argb8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
+ dstFormat == &_mesa_texformat_argb8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
+ /* simple memcpy path (little endian) */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8)) {
+ /* simple memcpy path (big endian) */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGB &&
+ (baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB) &&
+ srcType == GL_UNSIGNED_BYTE) {
+ int img, row, col;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *d4 = (GLuint *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ d4[col] = PACK_COLOR_8888(0xff,
+ srcRow[col * 3 + RCOMP],
+ srcRow[col * 3 + GCOMP],
+ srcRow[col * 3 + BCOMP]);
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb8888 &&
+ srcFormat == GL_RGBA &&
+ baseInternalFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* same as above case, but src data has alpha too */
+ GLint img, row, col;
+ /* For some reason, streaming copies to write-combined regions
+ * are extremely sensitive to the characteristics of how the
+ * source data is retrieved. By reordering the source reads to
+ * be in-order, the speed of this operation increases by half.
+ * Strangely the same isn't required for the RGB path, above.
+ */
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *d4 = (GLuint *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ d4[col] = PACK_COLOR_8888(srcRow[col * 4 + ACOMP],
+ srcRow[col * 4 + RCOMP],
+ srcRow[col * 4 + GCOMP],
+ srcRow[col * 4 + BCOMP]);
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_UNSIGNED_BYTE ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8 ||
+ srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) {
+ dstmap[3] = 3; /* alpha */
+ dstmap[2] = 0; /* red */
+ dstmap[1] = 1; /* green */
+ dstmap[0] = 2; /* blue */
+ }
+ else {
+ assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_argb8888));
+ dstmap[3] = 2;
+ dstmap[2] = 1;
+ dstmap[1] = 0;
+ dstmap[0] = 3;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_rgb888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_rgb888);
+ ASSERT(dstFormat->TexelBytes == 3);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_BGR &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* extract RGB from RGBA */
+ GLint img, row, col;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
+ dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ dstmap[0] = 2;
+ dstmap[1] = 1;
+ dstmap[2] = 0;
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 3,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = (const GLchan *) tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+#if 0
+ if (littleEndian) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+ srcUB += 3;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcUB[BCOMP];
+ dstRow[col * 3 + 1] = srcUB[GCOMP];
+ dstRow[col * 3 + 2] = srcUB[RCOMP];
+ srcUB += 3;
+ }
+ }
+#else
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
+ src += 3;
+ }
+#endif
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_bgr888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_bgr888);
+ ASSERT(dstFormat->TexelBytes == 3);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* extract BGR from RGBA */
+ int img, row, col;
+ for (img = 0; img < srcDepth; img++) {
+ const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
+ dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
+ dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
+ }
+ dstRow += dstRowStride;
+ srcRow += srcRowStride;
+ }
+ }
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ dstmap[0] = 0;
+ dstmap[1] = 1;
+ dstmap[2] = 2;
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 3,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = (const GLchan *) tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
+ dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
+ dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
+ src += 3;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_rgba4444(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgba4444);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba4444 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4){
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_argb4444(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
+ dstFormat == &_mesa_texformat_argb4444_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb4444 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb4444) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_rgba5551(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgba5551);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_rgba5551 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_RGBA &&
+ srcType == GL_UNSIGNED_SHORT_5_5_5_1) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src =tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_5551( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]),
+ CHAN_TO_UBYTE(src[ACOMP]) );
+ src += 4;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_argb1555(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
+ dstFormat == &_mesa_texformat_argb1555_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_argb1555 &&
+ baseInternalFormat == GL_RGBA &&
+ srcFormat == GL_BGRA &&
+ srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src =tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_argb1555) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
+ CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_al88(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_al88 ||
+ dstFormat == &_mesa_texformat_al88_rev);
+ ASSERT(dstFormat->TexelBytes == 2);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_al88 &&
+ baseInternalFormat == GL_LUMINANCE_ALPHA &&
+ srcFormat == GL_LUMINANCE_ALPHA &&
+ srcType == GL_UNSIGNED_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ littleEndian &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_al88) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) {
+ dstmap[0] = 0;
+ dstmap[1] = 3;
+ }
+ else {
+ dstmap[0] = 3;
+ dstmap[1] = 0;
+ }
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 2,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLushort *dstUS = (GLushort *) dstRow;
+ if (dstFormat == &_mesa_texformat_al88) {
+ for (col = 0; col < srcWidth; col++) {
+ /* src[0] is luminance, src[1] is alpha */
+ dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
+ CHAN_TO_UBYTE(src[0]) );
+ src += 2;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ /* src[0] is luminance, src[1] is alpha */
+ dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
+ CHAN_TO_UBYTE(src[0]) );
+ src += 2;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean
+_mesa_texstore_rgb332(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_rgb332);
+ ASSERT(dstFormat->TexelBytes == 1);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == GL_RGB &&
+ srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
+ CHAN_TO_UBYTE(src[GCOMP]),
+ CHAN_TO_UBYTE(src[BCOMP]) );
+ src += 3;
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
+ */
+GLboolean
+_mesa_texstore_a8(TEXSTORE_PARAMS)
+{
+ ASSERT(dstFormat == &_mesa_texformat_a8 ||
+ dstFormat == &_mesa_texformat_l8 ||
+ dstFormat == &_mesa_texformat_i8);
+ ASSERT(dstFormat->TexelBytes == 1);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ srcType == GL_UNSIGNED_BYTE &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if (dstFormat == &_mesa_texformat_a8) {
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[0] = 0;
+ }
+ dstmap[1] = ZERO; /* ? */
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 1,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLchan *src = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ for (col = 0; col < srcWidth; col++) {
+ dstRow[col] = CHAN_TO_UBYTE(src[col]);
+ }
+ dstRow += dstRowStride;
+ src += srcWidth;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+
+GLboolean
+_mesa_texstore_ci8(TEXSTORE_PARAMS)
+{
+ (void) dims; (void) baseInternalFormat;
+ ASSERT(dstFormat == &_mesa_texformat_ci8);
+ ASSERT(dstFormat->TexelBytes == 1);
+ ASSERT(baseInternalFormat == GL_COLOR_INDEX);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ srcFormat == GL_COLOR_INDEX &&
+ srcType == GL_UNSIGNED_BYTE) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ const GLvoid *src = _mesa_image_address(dims, srcPacking,
+ srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
+ _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
+ srcType, src, srcPacking,
+ ctx->_ImageTransferState);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
+ */
+GLboolean
+_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+ (void) ctx; (void) dims; (void) baseInternalFormat;
+
+ ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
+ (dstFormat == &_mesa_texformat_ycbcr_rev));
+ ASSERT(dstFormat->TexelBytes == 2);
+ ASSERT(ctx->Extensions.MESA_ycbcr_texture);
+ ASSERT(srcFormat == GL_YCBCR_MESA);
+ ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
+ (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
+ ASSERT(baseInternalFormat == GL_YCBCR_MESA);
+
+ /* always just memcpy since no pixel transfer ops apply */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+
+ /* Check if we need byte swapping */
+ /* XXX the logic here _might_ be wrong */
+ if (srcPacking->SwapBytes ^
+ (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
+ (dstFormat == &_mesa_texformat_ycbcr_rev) ^
+ !littleEndian) {
+ GLint img, row;
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_swap2((GLushort *) dstRow, srcWidth);
+ dstRow += dstRowStride;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+_mesa_texstore_dudv8(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_dudv8);
+ ASSERT(dstFormat->TexelBytes == 2);
+ ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
+ ASSERT((srcFormat == GL_DU8DV8_ATI) ||
+ (srcFormat == GL_DUDV_ATI));
+ ASSERT(baseInternalFormat == GL_DUDV_ATI);
+
+ if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
+ littleEndian) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (srcType == GL_BYTE) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if (littleEndian) {
+ dstmap[0] = 0;
+ dstmap[1] = 3;
+ }
+ else {
+ dstmap[0] = 3;
+ dstmap[1] = 0;
+ }
+ dstmap[2] = ZERO; /* ? */
+ dstmap[3] = ONE; /* ? */
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ GL_LUMINANCE_ALPHA, /* hack */
+ GL_UNSIGNED_BYTE, /* hack */
+ GL_LUMINANCE_ALPHA, /* hack */
+ dstmap, 2,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path - note this is defined for 2d textures only */
+ const GLint components = _mesa_components_in_format(baseInternalFormat);
+ const GLint srcStride = _mesa_image_row_stride(srcPacking,
+ srcWidth, srcFormat, srcType);
+ GLbyte *tempImage, *dst, *src;
+ GLint row;
+
+ tempImage = (GLbyte *) _mesa_malloc(srcWidth * srcHeight * srcDepth
+ * components * sizeof(GLbyte));
+ if (!tempImage)
+ return GL_FALSE;
+
+ src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ 0, 0, 0);
+
+ dst = tempImage;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
+ dst, srcFormat, srcType, src,
+ srcPacking, 0);
+ dst += srcWidth * components;
+ src += srcStride;
+ }
+
+ src = tempImage;
+ dst = (GLbyte *) dstAddr
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ memcpy(dst, src, srcWidth * dstFormat->TexelBytes);
+ dst += dstRowStride;
+ src += srcWidth * dstFormat->TexelBytes;
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+/**
+ * Store a texture in MESA_FORMAT_SIGNED_RGBA8888 or MESA_FORMAT_SIGNED_RGBA8888_REV
+ */
+GLboolean
+_mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
+{
+ const GLboolean littleEndian = _mesa_little_endian();
+
+ ASSERT(dstFormat == &_mesa_texformat_signed_rgba8888 ||
+ dstFormat == &_mesa_texformat_signed_rgba8888_rev);
+ ASSERT(dstFormat->TexelBytes == 4);
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_signed_rgba8888 &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ dstFormat == &_mesa_texformat_signed_rgba8888_rev &&
+ baseInternalFormat == GL_RGBA &&
+ ((srcFormat == GL_RGBA && srcType == GL_BYTE && littleEndian) ||
+ (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && !littleEndian))) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else if (!ctx->_ImageTransferState &&
+ (srcType == GL_BYTE) &&
+ can_swizzle(baseInternalFormat) &&
+ can_swizzle(srcFormat)) {
+
+ GLubyte dstmap[4];
+
+ /* dstmap - how to swizzle from RGBA to dst format:
+ */
+ if ((littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888) ||
+ (!littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888_rev)) {
+ dstmap[3] = 0;
+ dstmap[2] = 1;
+ dstmap[1] = 2;
+ dstmap[0] = 3;
+ }
+ else {
+ dstmap[3] = 3;
+ dstmap[2] = 2;
+ dstmap[1] = 1;
+ dstmap[0] = 0;
+ }
+
+ _mesa_swizzle_ubyte_image(ctx, dims,
+ srcFormat,
+ srcType,
+ baseInternalFormat,
+ dstmap, 4,
+ dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcAddr,
+ srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *srcRow = tempImage;
+ GLint img, row, col;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLuint *dstUI = (GLuint *) dstRow;
+ if (dstFormat == &_mesa_texformat_signed_rgba8888) {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+ srcRow += 4;
+ }
+ }
+ else {
+ for (col = 0; col < srcWidth; col++) {
+ dstUI[col] = PACK_COLOR_8888_REV( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
+ FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+ srcRow += 4;
+ }
+ }
+ dstRow += dstRowStride;
+ }
+ }
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+/**
+ * Store a combined depth/stencil texture image.
+ */
+GLboolean
+_mesa_texstore_z24_s8(TEXSTORE_PARAMS)
+{
+ const GLfloat depthScale = (GLfloat) 0xffffff;
+ const GLint srcRowStride
+ = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+ / sizeof(GLuint);
+ GLint img, row;
+
+ ASSERT(dstFormat == &_mesa_texformat_z24_s8);
+ ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
+ ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
+
+ /* In case we only upload depth we need to preserve the stencil */
+ if (srcFormat == GL_DEPTH_COMPONENT) {
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLuint depth[MAX_WIDTH];
+ GLint i;
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, /* dst type */
+ depth, /* dst addr */
+ depthScale,
+ srcType, src, srcPacking);
+
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF);
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ else if (ctx->Pixel.DepthScale == 1.0f &&
+ ctx->Pixel.DepthBias == 0.0f &&
+ !srcPacking->SwapBytes) {
+ /* simple path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLint srcRowStride
+ = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+ / sizeof(GLuint);
+ GLint img, row;
+
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLubyte stencil[MAX_WIDTH];
+ GLint i;
+ /* the 24 depth bits will be in the high position: */
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT_24_8_EXT, /* dst type */
+ dstRow, /* dst addr */
+ (GLuint) depthScale,
+ srcType, src, srcPacking);
+ /* get the 8-bit stencil values */
+ _mesa_unpack_stencil_span(ctx, srcWidth,
+ GL_UNSIGNED_BYTE, /* dst type */
+ stencil, /* dst addr */
+ srcType, src, srcPacking,
+ ctx->_ImageTransferState);
+ /* merge stencil values into depth values */
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] |= stencil[i];
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Store a combined depth/stencil texture image.
+ */
+GLboolean
+_mesa_texstore_s8_z24(TEXSTORE_PARAMS)
+{
+ const GLuint depthScale = 0xffffff;
+ const GLint srcRowStride
+ = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
+ / sizeof(GLuint);
+ GLint img, row;
+
+ ASSERT(dstFormat == &_mesa_texformat_s8_z24);
+ ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT);
+ ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT);
+
+ /* In case we only upload depth we need to preserve the stencil */
+ if (srcFormat == GL_DEPTH_COMPONENT) {
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLuint depth[MAX_WIDTH];
+ GLint i;
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, /* dst type */
+ depth, /* dst addr */
+ depthScale,
+ srcType, src, srcPacking);
+
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ else {
+ for (img = 0; img < srcDepth; img++) {
+ GLuint *dstRow = (GLuint *) dstAddr
+ + dstImageOffsets[dstZoffset + img]
+ + dstYoffset * dstRowStride / sizeof(GLuint)
+ + dstXoffset;
+ const GLuint *src
+ = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
+ srcWidth, srcHeight,
+ srcFormat, srcType,
+ img, 0, 0);
+ for (row = 0; row < srcHeight; row++) {
+ GLubyte stencil[MAX_WIDTH];
+ GLint i;
+ /* the 24 depth bits will be in the low position: */
+ _mesa_unpack_depth_span(ctx, srcWidth,
+ GL_UNSIGNED_INT, /* dst type */
+ dstRow, /* dst addr */
+ depthScale,
+ srcType, src, srcPacking);
+ /* get the 8-bit stencil values */
+ _mesa_unpack_stencil_span(ctx, srcWidth,
+ GL_UNSIGNED_BYTE, /* dst type */
+ stencil, /* dst addr */
+ srcType, src, srcPacking,
+ ctx->_ImageTransferState);
+ /* merge stencil values into depth values */
+ for (i = 0; i < srcWidth; i++)
+ dstRow[i] |= stencil[i] << 24;
+
+ src += srcRowStride;
+ dstRow += dstRowStride / sizeof(GLuint);
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
+/**
+ * Store an image in any of the formats:
+ * _mesa_texformat_rgba_float32
+ * _mesa_texformat_rgb_float32
+ * _mesa_texformat_alpha_float32
+ * _mesa_texformat_luminance_float32
+ * _mesa_texformat_luminance_alpha_float32
+ * _mesa_texformat_intensity_float32
+ */
+GLboolean
+_mesa_texstore_rgba_float32(TEXSTORE_PARAMS)
+{
+ const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
+ dstFormat == &_mesa_texformat_rgb_float32 ||
+ dstFormat == &_mesa_texformat_alpha_float32 ||
+ dstFormat == &_mesa_texformat_luminance_float32 ||
+ dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
+ dstFormat == &_mesa_texformat_intensity_float32);
+ ASSERT(baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB ||
+ baseInternalFormat == GL_ALPHA ||
+ baseInternalFormat == GL_LUMINANCE ||
+ baseInternalFormat == GL_LUMINANCE_ALPHA ||
+ baseInternalFormat == GL_INTENSITY);
+ ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_FLOAT) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *srcRow = tempImage;
+ GLint bytesPerRow;
+ GLint img, row;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ bytesPerRow = srcWidth * components * sizeof(GLfloat);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ _mesa_memcpy(dstRow, srcRow, bytesPerRow);
+ dstRow += dstRowStride;
+ srcRow += srcWidth * components;
+ }
+ }
+
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * As above, but store 16-bit floats.
+ */
+GLboolean
+_mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
+{
+ const GLint components = _mesa_components_in_format(dstFormat->BaseFormat);
+
+ ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
+ dstFormat == &_mesa_texformat_rgb_float16 ||
+ dstFormat == &_mesa_texformat_alpha_float16 ||
+ dstFormat == &_mesa_texformat_luminance_float16 ||
+ dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
+ dstFormat == &_mesa_texformat_intensity_float16);
+ ASSERT(baseInternalFormat == GL_RGBA ||
+ baseInternalFormat == GL_RGB ||
+ baseInternalFormat == GL_ALPHA ||
+ baseInternalFormat == GL_LUMINANCE ||
+ baseInternalFormat == GL_LUMINANCE_ALPHA ||
+ baseInternalFormat == GL_INTENSITY);
+ ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
+
+ if (!ctx->_ImageTransferState &&
+ !srcPacking->SwapBytes &&
+ baseInternalFormat == srcFormat &&
+ srcType == GL_HALF_FLOAT_ARB) {
+ /* simple memcpy path */
+ memcpy_texture(ctx, dims,
+ dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride,
+ dstImageOffsets,
+ srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+ srcAddr, srcPacking);
+ }
+ else {
+ /* general path */
+ const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+ baseInternalFormat,
+ dstFormat->BaseFormat,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType, srcAddr,
+ srcPacking);
+ const GLfloat *src = tempImage;
+ GLint img, row;
+ if (!tempImage)
+ return GL_FALSE;
+ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+ for (img = 0; img < srcDepth; img++) {
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
+ for (row = 0; row < srcHeight; row++) {
+ GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
+ GLint i;
+ for (i = 0; i < srcWidth * components; i++) {
+ dstTexel[i] = _mesa_float_to_half(src[i]);
+ }
+ dstRow += dstRowStride;
+ src += srcWidth * components;
+ }
+ }
+
+ _mesa_free((void *) tempImage);
+ }
+ return GL_TRUE;
+}
+
+
+#if FEATURE_EXT_texture_sRGB
+GLboolean
+_mesa_texstore_srgb8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ StoreTexImageFunc store;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_srgb8);
+
+ /* reuse normal rgb texstore code */
+ newDstFormat = &_mesa_texformat_rgb888;
+ store = _mesa_texstore_rgb888;
+
+ k = store(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_srgba8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_srgba8);
+
+ /* reuse normal rgba texstore code */
+ newDstFormat = &_mesa_texformat_rgba8888;
+
+ k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_sargb8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sargb8);
+
+ /* reuse normal rgba texstore code */
+ newDstFormat = &_mesa_texformat_argb8888;
+
+ k = _mesa_texstore_argb8888(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_sl8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sl8);
+
+ newDstFormat = &_mesa_texformat_l8;
+
+ /* _mesa_textore_a8 handles luminance8 too */
+ k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+
+GLboolean
+_mesa_texstore_sla8(TEXSTORE_PARAMS)
+{
+ const struct gl_texture_format *newDstFormat;
+ GLboolean k;
+
+ ASSERT(dstFormat == &_mesa_texformat_sla8);
+
+ /* reuse normal luminance/alpha texstore code */
+ newDstFormat = &_mesa_texformat_al88;
+
+ k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
+ newDstFormat, dstAddr,
+ dstXoffset, dstYoffset, dstZoffset,
+ dstRowStride, dstImageOffsets,
+ srcWidth, srcHeight, srcDepth,
+ srcFormat, srcType,
+ srcAddr, srcPacking);
+ return k;
+}
+
+#endif /* FEATURE_EXT_texture_sRGB */
+
+
+/**
+ * Check if an unpack PBO is active prior to fetching a texture image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
+ */
+const GLvoid *
+_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ const char *funcName)
+{
+ GLubyte *buf;
+
+ if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+ /* no PBO */
+ return pixels;
+ }
+ if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
+ return NULL;
+ }
+
+ buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, unpack->BufferObj);
+ if (!buf) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+ return NULL;
+ }
+
+ return ADD_POINTERS(buf, pixels);
+}
+
+
+/**
+ * Check if an unpack PBO is active prior to fetching a compressed texture
+ * image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call _mesa_unmap_teximage_pbo() too!
+ */
+const GLvoid *
+_mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
+ GLsizei imageSize, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ const char *funcName)
+{
+ GLubyte *buf;
+
+ if (!_mesa_is_bufferobj(packing->BufferObj)) {
+ /* not using a PBO - return pointer unchanged */
+ return pixels;
+ }
+ if ((const GLubyte *) pixels + imageSize >
+ ((const GLubyte *) 0) + packing->BufferObj->Size) {
+ /* out of bounds read! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
+ return NULL;
+ }
+
+ buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ GL_READ_ONLY_ARB, packing->BufferObj);
+ if (!buf) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+ return NULL;
+ }
+
+ return ADD_POINTERS(buf, pixels);
+}
+
+
+/**
+ * This function must be called after either of the validate_pbo_*_teximage()
+ * functions. It unmaps the PBO buffer if it was mapped earlier.
+ */
+void
+_mesa_unmap_teximage_pbo(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack)
+{
+ if (_mesa_is_bufferobj(unpack->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+ unpack->BufferObj);
+ }
+}
+
+
+
+/**
+ * Adaptor for fetching a GLchan texel from a float-valued texture.
+ */
+static void
+fetch_texel_float_to_chan(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texelOut)
+{
+ GLfloat temp[4];
+ ASSERT(texImage->FetchTexelf);
+ texImage->FetchTexelf(texImage, i, j, k, temp);
+ if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
+ texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* just one channel */
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
+ }
+ else {
+ /* four channels */
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
+ }
+}
+
+
+/**
+ * Adaptor for fetching a float texel from a GLchan-valued texture.
+ */
+static void
+fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texelOut)
+{
+ GLchan temp[4];
+ ASSERT(texImage->FetchTexelc);
+ texImage->FetchTexelc(texImage, i, j, k, temp);
+ if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
+ texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* just one channel */
+ texelOut[0] = CHAN_TO_FLOAT(temp[0]);
+ }
+ else {
+ /* four channels */
+ texelOut[0] = CHAN_TO_FLOAT(temp[0]);
+ texelOut[1] = CHAN_TO_FLOAT(temp[1]);
+ texelOut[2] = CHAN_TO_FLOAT(temp[2]);
+ texelOut[3] = CHAN_TO_FLOAT(temp[3]);
+ }
+}
+
+
+/**
+ * Initialize the texture image's FetchTexelc and FetchTexelf methods.
+ */
+void
+_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
+{
+ ASSERT(dims == 1 || dims == 2 || dims == 3);
+ ASSERT(texImage->TexFormat);
+
+ switch (dims) {
+ case 1:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
+ break;
+ case 2:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
+ break;
+ case 3:
+ texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
+ texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
+ break;
+ default:
+ ;
+ }
+
+ /* now check if we need to use a float/chan adaptor */
+ if (!texImage->FetchTexelc) {
+ texImage->FetchTexelc = fetch_texel_float_to_chan;
+ }
+ else if (!texImage->FetchTexelf) {
+ texImage->FetchTexelf = fetch_texel_chan_to_float;
+ }
+
+
+ ASSERT(texImage->FetchTexelc);
+ ASSERT(texImage->FetchTexelf);
+}
+
+
+/**
+ * Choose the actual storage format for a new texture image.
+ * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function.
+ * Also set some other texImage fields related to texture compression, etc.
+ * \param ctx rendering context
+ * \param texImage the gl_texture_image
+ * \param dims texture dimensions (1, 2 or 3)
+ * \param format the user-specified format parameter
+ * \param type the user-specified type parameter
+ * \param internalFormat the user-specified internal format hint
+ */
+static void
+choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage,
+ GLuint dims,
+ GLenum format, GLenum type, GLint internalFormat)
+{
+ ASSERT(dims == 1 || dims == 2 || dims == 3);
+ ASSERT(ctx->Driver.ChooseTextureFormat);
+
+ texImage->TexFormat
+ = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
+
+ ASSERT(texImage->TexFormat);
+
+ _mesa_set_fetch_functions(texImage, dims);
+
+ if (texImage->TexFormat->TexelBytes == 0) {
+ /* must be a compressed format */
+ texImage->IsCompressed = GL_TRUE;
+ texImage->CompressedSize =
+ ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+ texImage->Height, texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+ }
+ else {
+ /* non-compressed format */
+ texImage->IsCompressed = GL_FALSE;
+ texImage->CompressedSize = 0;
+ }
+}
+
+
+
+/**
+ * This is the software fallback for Driver.TexImage1D()
+ * and Driver.CopyTexImage1D().
+ * \sa _mesa_store_teximage2d()
+ * Note that the width may not be the actual texture width since it may
+ * be changed by convolution w/ GL_REDUCE. The texImage->Width field will
+ * have the actual texture size.
+ */
+void
+_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLint sizeInBytes;
+ (void) border;
+
+ choose_texture_format(ctx, texImage, 1, format, type, internalFormat);
+
+ /* allocate memory */
+ if (texImage->IsCompressed)
+ sizeInBytes = texImage->CompressedSize;
+ else
+ sizeInBytes = texImage->Width * texImage->TexFormat->TexelBytes;
+ texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ return;
+ }
+
+ pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
+ pixels, packing, "glTexImage1D");
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
+ return;
+ }
+ else {
+ const GLint dstRowStride = 0;
+ GLboolean success;
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, 1, 1,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+/**
+ * This is the software fallback for Driver.TexImage2D()
+ * and Driver.CopyTexImage2D().
+ *
+ * This function is oriented toward storing images in main memory, rather
+ * than VRAM. Device driver's can easily plug in their own replacement.
+ *
+ * Note: width and height may be pre-convolved dimensions, but
+ * texImage->Width and texImage->Height will be post-convolved dimensions.
+ */
+void
+_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLint texelBytes, sizeInBytes;
+ (void) border;
+
+ choose_texture_format(ctx, texImage, 2, format, type, internalFormat);
+
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ /* allocate memory */
+ if (texImage->IsCompressed)
+ sizeInBytes = texImage->CompressedSize;
+ else
+ sizeInBytes = texImage->Width * texImage->Height * texelBytes;
+ texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+
+ pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+ pixels, packing, "glTexImage2D");
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
+ return;
+ }
+ else {
+ GLint dstRowStride;
+ GLboolean success;
+ if (texImage->IsCompressed) {
+ dstRowStride
+ = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ }
+ else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+
+/**
+ * This is the software fallback for Driver.TexImage3D()
+ * and Driver.CopyTexImage3D().
+ * \sa _mesa_store_teximage2d()
+ */
+void
+_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth, GLint border,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLint texelBytes, sizeInBytes;
+ (void) border;
+
+ choose_texture_format(ctx, texImage, 3, format, type, internalFormat);
+
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ /* allocate memory */
+ if (texImage->IsCompressed)
+ sizeInBytes = texImage->CompressedSize;
+ else
+ sizeInBytes = width * height * depth * texelBytes;
+ texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+ return;
+ }
+
+ pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
+ type, pixels, packing, "glTexImage3D");
+ if (!pixels) {
+ /* Note: we check for a NULL image pointer here, _after_ we allocated
+ * memory for the texture. That's what the GL spec calls for.
+ */
+ return;
+ }
+ else {
+ GLint dstRowStride;
+ GLboolean success;
+ if (texImage->IsCompressed) {
+ dstRowStride
+ = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+ }
+ else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, depth,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+
+
+/*
+ * This is the software fallback for Driver.TexSubImage1D()
+ * and Driver.CopyTexSubImage1D().
+ */
+void
+_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint width,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* get pointer to src pixels (may be in a pbo which we'll map here) */
+ pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
+ pixels, packing, "glTexSubImage1D");
+ if (!pixels)
+ return;
+
+ {
+ const GLint dstRowStride = 0;
+ GLboolean success;
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ xoffset, 0, 0, /* offsets */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, 1, 1,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+
+/**
+ * This is the software fallback for Driver.TexSubImage2D()
+ * and Driver.CopyTexSubImage2D().
+ */
+void
+_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint width, GLint height,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* get pointer to src pixels (may be in a pbo which we'll map here) */
+ pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
+ pixels, packing, "glTexSubImage2D");
+ if (!pixels)
+ return;
+
+ {
+ GLint dstRowStride = 0;
+ GLboolean success;
+ if (texImage->IsCompressed) {
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
+ texImage->Width);
+ }
+ else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ xoffset, yoffset, 0,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+/*
+ * This is the software fallback for Driver.TexSubImage3D().
+ * and Driver.CopyTexSubImage3D().
+ */
+void
+_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, const void *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* get pointer to src pixels (may be in a pbo which we'll map here) */
+ pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
+ type, pixels, packing,
+ "glTexSubImage3D");
+ if (!pixels)
+ return;
+
+ {
+ GLint dstRowStride;
+ GLboolean success;
+ if (texImage->IsCompressed) {
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat,
+ texImage->Width);
+ }
+ else {
+ dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
+ }
+ ASSERT(texImage->TexFormat->StoreImage);
+ success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
+ texImage->TexFormat,
+ texImage->Data,
+ xoffset, yoffset, zoffset,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, depth,
+ format, type, pixels, packing);
+ if (!success) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
+ }
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, packing);
+}
+
+
+/*
+ * Fallback for Driver.CompressedTexImage1D()
+ */
+void
+_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* this space intentionally left blank */
+ (void) ctx;
+ (void) target; (void) level;
+ (void) internalFormat;
+ (void) width; (void) border;
+ (void) imageSize; (void) data;
+ (void) texObj;
+ (void) texImage;
+}
+
+
+
+/**
+ * Fallback for Driver.CompressedTexImage2D()
+ */
+void
+_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ (void) width; (void) height; (void) border;
+
+ /* This is pretty simple, basically just do a memcpy without worrying
+ * about the usual image unpacking or image transfer operations.
+ */
+ ASSERT(texObj);
+ ASSERT(texImage);
+ ASSERT(texImage->Width > 0);
+ ASSERT(texImage->Height > 0);
+ ASSERT(texImage->Depth == 1);
+ ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
+
+ choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat);
+
+ /* allocate storage */
+ texImage->Data = _mesa_alloc_texmemory(imageSize);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
+ return;
+ }
+
+ data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
+ &ctx->Unpack,
+ "glCompressedTexImage2D");
+ if (!data)
+ return;
+
+ /* copy the data */
+ ASSERT(texImage->CompressedSize == (GLuint) imageSize);
+ MEMCPY(texImage->Data, data, imageSize);
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
+}
+
+
+
+/*
+ * Fallback for Driver.CompressedTexImage3D()
+ */
+void
+_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* this space intentionally left blank */
+ (void) ctx;
+ (void) target; (void) level;
+ (void) internalFormat;
+ (void) width; (void) height; (void) depth;
+ (void) border;
+ (void) imageSize; (void) data;
+ (void) texObj;
+ (void) texImage;
+}
+
+
+
+/**
+ * Fallback for Driver.CompressedTexSubImage1D()
+ */
+void
+_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* there are no compressed 1D texture formats yet */
+ (void) ctx;
+ (void) target; (void) level;
+ (void) xoffset; (void) width;
+ (void) format;
+ (void) imageSize; (void) data;
+ (void) texObj;
+ (void) texImage;
+}
+
+
+/**
+ * Fallback for Driver.CompressedTexSubImage2D()
+ */
+void
+_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ GLint bytesPerRow, destRowStride, srcRowStride;
+ GLint i, rows;
+ GLubyte *dest;
+ const GLubyte *src;
+ const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
+
+ (void) format;
+
+ /* these should have been caught sooner */
+ ASSERT((width & 3) == 0 || width == 2 || width == 1);
+ ASSERT((height & 3) == 0 || height == 2 || height == 1);
+ ASSERT((xoffset & 3) == 0);
+ ASSERT((yoffset & 3) == 0);
+
+ /* get pointer to src pixels (may be in a pbo which we'll map here) */
+ data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
+ &ctx->Unpack,
+ "glCompressedTexSubImage2D");
+ if (!data)
+ return;
+
+ srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
+ src = (const GLubyte *) data;
+
+ destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
+ dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
+ texImage->TexFormat->MesaFormat,
+ texImage->Width,
+ (GLubyte *) texImage->Data);
+
+ bytesPerRow = srcRowStride;
+ rows = height / 4;
+
+ for (i = 0; i < rows; i++) {
+ MEMCPY(dest, src, bytesPerRow);
+ dest += destRowStride;
+ src += srcRowStride;
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+
+ _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
+}
+
+
+/**
+ * Fallback for Driver.CompressedTexSubImage3D()
+ */
+void
+_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ /* there are no compressed 3D texture formats yet */
+ (void) ctx;
+ (void) target; (void) level;
+ (void) xoffset; (void) yoffset; (void) zoffset;
+ (void) width; (void) height; (void) depth;
+ (void) format;
+ (void) imageSize; (void) data;
+ (void) texObj;
+ (void) texImage;
+}
diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h
new file mode 100644
index 000000000..313f2d6a5
--- /dev/null
+++ b/mesalib/src/mesa/main/texstore.h
@@ -0,0 +1,231 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to 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.
+ */
+
+
+/**
+ * \file texstore.h
+ * Texture image storage routines.
+ *
+ * \author Brian Paul
+ */
+
+
+#ifndef TEXSTORE_H
+#define TEXSTORE_H
+
+
+#include "mtypes.h"
+
+
+extern GLboolean _mesa_texstore_rgba(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_color_index(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba8888(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_argb8888(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb888(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_bgr888(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb565(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb565_rev(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba4444(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_argb4444(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_argb4444_rev(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba5551(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_argb1555(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_argb1555_rev(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_al88(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_al88_rev(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb332(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_a8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_ci8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_ycbcr(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_z24_s8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_s8_z24(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_z16(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_z32(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_float32(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_float16(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS);
+#if FEATURE_EXT_texture_sRGB
+extern GLboolean _mesa_texstore_srgb8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_srgba8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_sargb8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
+#endif
+extern GLboolean _mesa_texstore_dudv8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS);
+
+extern GLchan *
+_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
+ GLenum logicalBaseFormat,
+ GLenum textureBaseFormat,
+ GLint srcWidth, GLint srcHeight, GLint srcDepth,
+ GLenum srcFormat, GLenum srcType,
+ const GLvoid *srcAddr,
+ const struct gl_pixelstore_attrib *srcPacking);
+
+
+extern void
+_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims);
+
+
+extern void
+_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint width,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint width, GLint height,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+extern void
+_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+extern void
+_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint depth,
+ GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern void
+_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+extern void
+_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+extern void
+_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+
+extern const GLvoid *
+_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *unpack,
+ const char *funcName);
+
+extern const GLvoid *
+_mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
+ GLsizei imageSize, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ const char *funcName);
+
+extern void
+_mesa_unmap_teximage_pbo(GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
new file mode 100644
index 000000000..6cd2a2f4f
--- /dev/null
+++ b/mesalib/src/mesa/main/varray.c
@@ -0,0 +1,1187 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "enable.h"
+#include "enums.h"
+#include "hash.h"
+#include "mtypes.h"
+#include "varray.h"
+#include "arrayobj.h"
+#include "glapi/dispatch.h"
+
+
+/**
+ * Set the fields of a vertex array.
+ * Also do an error check for GL_ARB_vertex_array_object: check that
+ * all arrays reside in VBOs when using a vertex array object.
+ *
+ * \param array the array to update
+ * \param dirtyBit which bit to set in ctx->Array.NewState for this array
+ * \param elementSize size of each array element, in bytes
+ * \param size components per element (1, 2, 3 or 4)
+ * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
+ * \param format either GL_RGBA or GL_BGRA
+ * \param stride stride between elements, in elements
+ * \param normalized are integer types converted to floats in [-1, 1]?
+ * \param ptr the address (or offset inside VBO) of the array data
+ * \return GL_TRUE if no error, GL_FALSE if error
+ */
+static GLboolean
+update_array(GLcontext *ctx, struct gl_client_array *array,
+ GLbitfield dirtyBit, GLsizei elementSize,
+ GLint size, GLenum type, GLenum format,
+ GLsizei stride, GLboolean normalized, const GLvoid *ptr)
+{
+ ASSERT(format == GL_RGBA || format == GL_BGRA);
+
+ if (ctx->Array.ArrayObj->VBOonly &&
+ ctx->Array.ArrayBufferObj->Name == 0) {
+ /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
+ * Generate GL_INVALID_OPERATION if that's not true.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glVertex/Normal/EtcPointer(non-VBO array)");
+ return GL_FALSE;
+ }
+
+ array->Size = size;
+ array->Type = type;
+ array->Format = format;
+ array->Stride = stride;
+ array->StrideB = stride ? stride : elementSize;
+ array->Normalized = normalized;
+ array->Ptr = (const GLubyte *) ptr;
+ array->_ElementSize = elementSize;
+
+ _mesa_reference_buffer_object(ctx, &array->BufferObj,
+ ctx->Array.ArrayBufferObj);
+
+ ctx->NewState |= _NEW_ARRAY;
+ ctx->Array.NewState |= dirtyBit;
+
+ return GL_TRUE;
+}
+
+
+void GLAPIENTRY
+_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (size < 2 || size > 4) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
+ return;
+ }
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
+ _mesa_lookup_enum_by_nr( type ), stride);
+
+ /* always need to check that <type> is legal */
+ switch (type) {
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_INT:
+ elementSize = size * sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = size * sizeof(GLfixed);
+ break;
+#endif
+#if FEATURE_vertex_array_byte
+ case GL_BYTE:
+ elementSize = size * sizeof(GLbyte);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
+ elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
+
+ if (ctx->Driver.VertexPointer)
+ ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
+{
+ GLsizei elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
+ _mesa_lookup_enum_by_nr( type ), stride);
+
+ switch (type) {
+ case GL_BYTE:
+ elementSize = 3 * sizeof(GLbyte);
+ break;
+ case GL_SHORT:
+ elementSize = 3 * sizeof(GLshort);
+ break;
+ case GL_INT:
+ elementSize = 3 * sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ elementSize = 3 * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = 3 * sizeof(GLdouble);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = 3 * sizeof(GLfixed);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
+ elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr))
+ return;
+
+ if (ctx->Driver.NormalPointer)
+ ctx->Driver.NormalPointer( ctx, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GLenum format;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (size < 3 || size > 4) {
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
+ return;
+ }
+ }
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
+ _mesa_lookup_enum_by_nr( type ), stride);
+
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
+ return;
+ }
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
+ switch (type) {
+ case GL_BYTE:
+ elementSize = size * sizeof(GLbyte);
+ break;
+ case GL_UNSIGNED_BYTE:
+ elementSize = size * sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_UNSIGNED_SHORT:
+ elementSize = size * sizeof(GLushort);
+ break;
+ case GL_INT:
+ elementSize = size * sizeof(GLint);
+ break;
+ case GL_UNSIGNED_INT:
+ elementSize = size * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = size * sizeof(GLfixed);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
+ elementSize, size, type, format, stride, GL_TRUE, ptr))
+ return;
+
+ if (ctx->Driver.ColorPointer)
+ ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GLint elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
+ return;
+ }
+
+ switch (type) {
+ case GL_FLOAT:
+ elementSize = sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = sizeof(GLdouble);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
+
+ if (ctx->Driver.FogCoordPointer)
+ ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
+ return;
+ }
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ elementSize = sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ elementSize = sizeof(GLshort);
+ break;
+ case GL_INT:
+ elementSize = sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ elementSize = sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = sizeof(GLdouble);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
+
+ if (ctx->Driver.IndexPointer)
+ ctx->Driver.IndexPointer( ctx, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GLenum format;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (size != 3 && size != 4) {
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
+ return;
+ }
+ }
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
+ size, _mesa_lookup_enum_by_nr( type ), stride);
+
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
+ return;
+ }
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
+ switch (type) {
+ case GL_BYTE:
+ elementSize = size * sizeof(GLbyte);
+ break;
+ case GL_UNSIGNED_BYTE:
+ elementSize = size * sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_UNSIGNED_SHORT:
+ elementSize = size * sizeof(GLushort);
+ break;
+ case GL_INT:
+ elementSize = size * sizeof(GLint);
+ break;
+ case GL_UNSIGNED_INT:
+ elementSize = size * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor,
+ _NEW_ARRAY_COLOR1, elementSize, size, type,
+ format, stride, GL_TRUE, ptr))
+ return;
+
+ if (ctx->Driver.SecondaryColorPointer)
+ ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr)
+{
+ GLint elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint unit = ctx->Array.ActiveTexture;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (size < 1 || size > 4) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
+ return;
+ }
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
+ unit, size, _mesa_lookup_enum_by_nr( type ), stride);
+
+ /* always need to check that <type> is legal */
+ switch (type) {
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_INT:
+ elementSize = size * sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = size * sizeof(GLfixed);
+ break;
+#endif
+#if FEATURE_vertex_array_byte
+ case GL_BYTE:
+ elementSize = size * sizeof(GLbyte);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
+ _NEW_ARRAY_TEXCOORD(unit),
+ elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr))
+ return;
+
+ if (ctx->Driver.TexCoordPointer)
+ ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
+ sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
+ stride, GL_FALSE, ptr))
+ return;
+
+ if (ctx->Driver.EdgeFlagPointer)
+ ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
+}
+
+
+void GLAPIENTRY
+_mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (stride < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
+ return;
+ }
+
+ switch (type) {
+ case GL_FLOAT:
+ elementSize = sizeof(GLfloat);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = sizeof(GLfixed);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
+ return;
+ }
+
+ update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
+ elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
+}
+
+
+#if FEATURE_NV_vertex_program
+/**
+ * Set a vertex attribute array.
+ * Note that these arrays DO alias the conventional GL vertex arrays
+ * (position, normal, color, fog, texcoord, etc).
+ * The generic attribute slots at #16 and above are not touched.
+ */
+void GLAPIENTRY
+_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr)
+{
+ GLboolean normalized = GL_FALSE;
+ GLsizei elementSize;
+ GLenum format;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
+ return;
+ }
+
+ if (size < 1 || size > 4) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
+ return;
+ }
+
+ if (stride < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
+ return;
+ }
+
+ if (type == GL_UNSIGNED_BYTE && size != 4) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
+ return;
+ }
+
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerNV(GL_BGRA/type)");
+ return;
+ }
+
+ format = GL_BGRA;
+ size = 4;
+ normalized = GL_TRUE;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
+ /* check for valid 'type' and compute StrideB right away */
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ normalized = GL_TRUE;
+ elementSize = size * sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
+ _mesa_lookup_enum_by_nr(type));
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+ _NEW_ARRAY_ATTRIB(index),
+ elementSize, size, type, format, stride, normalized, ptr))
+ return;
+
+ if (ctx->Driver.VertexAttribPointer)
+ ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
+}
+#endif
+
+
+#if FEATURE_ARB_vertex_program
+/**
+ * Set a generic vertex attribute array.
+ * Note that these arrays DO NOT alias the conventional GL vertex arrays
+ * (position, normal, color, fog, texcoord, etc).
+ */
+void GLAPIENTRY
+_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
+ GLboolean normalized,
+ GLsizei stride, const GLvoid *ptr)
+{
+ GLsizei elementSize;
+ GLenum format;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
+ return;
+ }
+
+ if (size < 1 || size > 4) {
+ if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
+ return;
+ }
+ }
+
+ if (stride < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
+ return;
+ }
+
+ if (size == GL_BGRA) {
+ if (type != GL_UNSIGNED_BYTE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerARB(GL_BGRA/type)");
+ return;
+ }
+ if (normalized != GL_TRUE) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glVertexAttribPointerARB(GL_BGRA/normalized)");
+ return;
+ }
+
+ format = GL_BGRA;
+ size = 4;
+ }
+ else {
+ format = GL_RGBA;
+ }
+
+ /* check for valid 'type' and compute StrideB right away */
+ /* NOTE: more types are supported here than in the NV extension */
+ switch (type) {
+ case GL_BYTE:
+ elementSize = size * sizeof(GLbyte);
+ break;
+ case GL_UNSIGNED_BYTE:
+ elementSize = size * sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ elementSize = size * sizeof(GLshort);
+ break;
+ case GL_UNSIGNED_SHORT:
+ elementSize = size * sizeof(GLushort);
+ break;
+ case GL_INT:
+ elementSize = size * sizeof(GLint);
+ break;
+ case GL_UNSIGNED_INT:
+ elementSize = size * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ elementSize = size * sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ elementSize = size * sizeof(GLdouble);
+ break;
+#if FEATURE_fixedpt
+ case GL_FIXED:
+ elementSize = size * sizeof(GLfixed);
+ break;
+#endif
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
+ return;
+ }
+
+ if (!update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
+ _NEW_ARRAY_ATTRIB(index),
+ elementSize, size, type, format, stride, normalized, ptr))
+ return;
+
+ if (ctx->Driver.VertexAttribPointer)
+ ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
+}
+#endif
+
+
+void GLAPIENTRY
+_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr)
+{
+ (void) count;
+ _mesa_VertexPointer(size, type, stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr)
+{
+ (void) count;
+ _mesa_NormalPointer(type, stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr)
+{
+ (void) count;
+ _mesa_ColorPointer(size, type, stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr)
+{
+ (void) count;
+ _mesa_IndexPointer(type, stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr)
+{
+ (void) count;
+ _mesa_TexCoordPointer(size, type, stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
+{
+ (void) count;
+ _mesa_EdgeFlagPointer(stride, ptr);
+}
+
+
+void GLAPIENTRY
+_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLboolean tflag, cflag, nflag; /* enable/disable flags */
+ GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
+ GLenum ctype = 0; /* color type */
+ GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
+ const GLint toffset = 0; /* always zero */
+ GLint defstride; /* default stride */
+ GLint c, f;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ f = sizeof(GLfloat);
+ c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
+
+ if (stride < 0) {
+ _mesa_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:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
+ return;
+ }
+
+ if (stride==0) {
+ stride = defstride;
+ }
+
+ _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
+ _mesa_DisableClientState( GL_INDEX_ARRAY );
+ /* XXX also disable secondary color and generic arrays? */
+
+ /* Texcoords */
+ if (tflag) {
+ _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
+ _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
+ (GLubyte *) pointer + toffset );
+ }
+ else {
+ _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
+ }
+
+ /* Color */
+ if (cflag) {
+ _mesa_EnableClientState( GL_COLOR_ARRAY );
+ _mesa_ColorPointer( ccomps, ctype, stride,
+ (GLubyte *) pointer + coffset );
+ }
+ else {
+ _mesa_DisableClientState( GL_COLOR_ARRAY );
+ }
+
+
+ /* Normals */
+ if (nflag) {
+ _mesa_EnableClientState( GL_NORMAL_ARRAY );
+ _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
+ }
+ else {
+ _mesa_DisableClientState( GL_NORMAL_ARRAY );
+ }
+
+ /* Vertices */
+ _mesa_EnableClientState( GL_VERTEX_ARRAY );
+ _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
+ (GLubyte *) pointer + voffset );
+}
+
+
+void GLAPIENTRY
+_mesa_LockArraysEXT(GLint first, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
+
+ if (first < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
+ return;
+ }
+ if (count <= 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
+ return;
+ }
+ if (ctx->Array.LockCount != 0) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
+ return;
+ }
+
+ ctx->Array.LockFirst = first;
+ ctx->Array.LockCount = count;
+
+ ctx->NewState |= _NEW_ARRAY;
+ ctx->Array.NewState |= _NEW_ARRAY_ALL;
+
+ if (ctx->Driver.LockArraysEXT)
+ ctx->Driver.LockArraysEXT( ctx, first, count );
+}
+
+
+void GLAPIENTRY
+_mesa_UnlockArraysEXT( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glUnlockArrays\n");
+
+ if (ctx->Array.LockCount == 0) {
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
+ return;
+ }
+
+ ctx->Array.LockFirst = 0;
+ ctx->Array.LockCount = 0;
+ ctx->NewState |= _NEW_ARRAY;
+ ctx->Array.NewState |= _NEW_ARRAY_ALL;
+
+ if (ctx->Driver.UnlockArraysEXT)
+ ctx->Driver.UnlockArraysEXT( ctx );
+}
+
+
+/* GL_EXT_multi_draw_arrays */
+/* Somebody forgot to spec the first and count parameters as const! <sigh> */
+void GLAPIENTRY
+_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
+ GLsizei *count, GLsizei primcount )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
+ }
+ }
+}
+
+
+/* GL_IBM_multimode_draw_arrays */
+void GLAPIENTRY
+_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
+ const GLsizei * count,
+ GLsizei primcount, GLint modestride )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for ( i = 0 ; i < primcount ; i++ ) {
+ if ( count[i] > 0 ) {
+ GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
+ CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
+ }
+ }
+}
+
+
+/* GL_IBM_multimode_draw_arrays */
+void GLAPIENTRY
+_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
+ GLenum type, const GLvoid * const * indices,
+ GLsizei primcount, GLint modestride )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ /* XXX not sure about ARB_vertex_buffer_object handling here */
+
+ for ( i = 0 ; i < primcount ; i++ ) {
+ if ( count[i] > 0 ) {
+ GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
+ CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
+ }
+ }
+}
+
+
+/**
+ * Copy one client vertex array to another.
+ */
+void
+_mesa_copy_client_array(GLcontext *ctx,
+ struct gl_client_array *dst,
+ struct gl_client_array *src)
+{
+ dst->Size = src->Size;
+ dst->Type = src->Type;
+ dst->Format = src->Format;
+ dst->Stride = src->Stride;
+ dst->StrideB = src->StrideB;
+ dst->Ptr = src->Ptr;
+ dst->Enabled = src->Enabled;
+ dst->Normalized = src->Normalized;
+ dst->_ElementSize = src->_ElementSize;
+ _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
+ dst->_MaxElement = src->_MaxElement;
+}
+
+
+
+/**
+ * Print vertex array's fields.
+ */
+static void
+print_array(const char *name, GLint index, const struct gl_client_array *array)
+{
+ if (index >= 0)
+ _mesa_printf(" %s[%d]: ", name, index);
+ else
+ _mesa_printf(" %s: ", name);
+ _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
+ array->Ptr, array->Type, array->Size,
+ array->_ElementSize, array->StrideB,
+ array->BufferObj->Name, array->BufferObj->Size,
+ array->_MaxElement);
+}
+
+
+/**
+ * Print current vertex object/array info. For debug.
+ */
+void
+_mesa_print_arrays(GLcontext *ctx)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i;
+
+ _mesa_update_array_object_max_element(ctx, arrayObj);
+
+ _mesa_printf("Array Object %u\n", arrayObj->Name);
+ if (arrayObj->Vertex.Enabled)
+ print_array("Vertex", -1, &arrayObj->Vertex);
+ if (arrayObj->Normal.Enabled)
+ print_array("Normal", -1, &arrayObj->Normal);
+ if (arrayObj->Color.Enabled)
+ print_array("Color", -1, &arrayObj->Color);
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ if (arrayObj->TexCoord[i].Enabled)
+ print_array("TexCoord", i, &arrayObj->TexCoord[i]);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ if (arrayObj->VertexAttrib[i].Enabled)
+ print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
+ _mesa_printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
+}
+
+
+/**
+ * Initialize vertex array state for given context.
+ */
+void
+_mesa_init_varray(GLcontext *ctx)
+{
+ ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
+ ctx->Array.DefaultArrayObj);
+ ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
+
+ ctx->Array.Objects = _mesa_NewHashTable();
+}
+
+
+/**
+ * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
+ */
+static void
+delete_arrayobj_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_array_object *arrayObj = (struct gl_array_object *) data;
+ GLcontext *ctx = (GLcontext *) userData;
+ _mesa_delete_array_object(ctx, arrayObj);
+}
+
+
+/**
+ * Free vertex array state for given context.
+ */
+void
+_mesa_free_varray_data(GLcontext *ctx)
+{
+ _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
+ _mesa_DeleteHashTable(ctx->Array.Objects);
+}
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
new file mode 100644
index 000000000..becc67c29
--- /dev/null
+++ b/mesalib/src/mesa/main/varray.h
@@ -0,0 +1,186 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "mtypes.h"
+
+#if _HAVE_FULL_GL
+
+extern void GLAPIENTRY
+_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr);
+
+extern void GLAPIENTRY
+_mesa_UnlockArraysEXT( void );
+
+extern void GLAPIENTRY
+_mesa_LockArraysEXT(GLint first, GLsizei count);
+
+
+extern void GLAPIENTRY
+_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
+ const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
+ GLsizei count, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr);
+
+
+extern void GLAPIENTRY
+_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid *pointer);
+
+
+extern void GLAPIENTRY
+_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
+ GLboolean normalized, GLsizei stride,
+ const GLvoid *pointer);
+
+
+extern void GLAPIENTRY
+_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer);
+
+
+extern void GLAPIENTRY
+_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
+ GLsizei *count, GLsizei primcount );
+
+extern void GLAPIENTRY
+_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount );
+
+
+extern void GLAPIENTRY
+_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
+ const GLsizei * count,
+ GLsizei primcount, GLint modestride );
+
+
+extern void GLAPIENTRY
+_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
+ GLenum type, const GLvoid * const * indices,
+ GLsizei primcount, GLint modestride );
+
+extern void GLAPIENTRY
+_mesa_LockArraysEXT(GLint first, GLsizei count);
+
+extern void GLAPIENTRY
+_mesa_UnlockArraysEXT( void );
+
+
+extern void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count);
+
+extern void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices);
+
+extern void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices);
+
+
+extern void
+_mesa_copy_client_array(GLcontext *ctx,
+ struct gl_client_array *dst,
+ struct gl_client_array *src);
+
+
+extern void
+_mesa_print_arrays(GLcontext *ctx);
+
+extern void
+_mesa_init_varray( GLcontext * ctx );
+
+extern void
+_mesa_free_varray_data(GLcontext *ctx);
+
+#else
+
+/** No-op */
+#define _mesa_init_varray( c ) ((void)0)
+#define _mesa_free_varray_data( c ) ((void)0)
+
+#endif
+
+#endif
diff --git a/mesalib/src/mesa/main/version.h b/mesalib/src/mesa/main/version.h
new file mode 100644
index 000000000..0ccdbf94a
--- /dev/null
+++ b/mesalib/src/mesa/main/version.h
@@ -0,0 +1,53 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 VERSION_H
+#define VERSION_H
+
+
+/* Mesa version */
+#define MESA_MAJOR 7
+#define MESA_MINOR 6
+#define MESA_PATCH 0
+#define MESA_VERSION_STRING "7.6"
+
+/* To make version comparison easy */
+#define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define MESA_VERSION_CODE MESA_VERSION(MESA_MAJOR, MESA_MINOR, MESA_PATCH)
+
+
+/* OpenGL API version */
+#define OPENGL_MAJOR 2
+#define OPENGL_MINOR 1
+#define OPENGL_PATCH 0
+#define OPENGL_VERSION_STRING "2.1"
+
+/* To make version comparison easy */
+#define OPENGL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define OPENGL_VERSION_CODE OPENGL_VERSION(OPENGL_MAJOR, OPENGL_MINOR, OPENGL_PATCH)
+
+
+#endif /* VERSION_H */
diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c
new file mode 100644
index 000000000..309308c98
--- /dev/null
+++ b/mesalib/src/mesa/main/viewport.c
@@ -0,0 +1,180 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file viewport.c
+ * glViewport and glDepthRange functions.
+ */
+
+
+#include "context.h"
+#include "macros.h"
+#include "viewport.h"
+
+
+/**
+ * Set the viewport.
+ * \sa Called via glViewport() or display list execution.
+ *
+ * Flushes the vertices and calls _mesa_set_viewport() with the given
+ * parameters.
+ */
+void GLAPIENTRY
+_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ _mesa_set_viewport(ctx, x, y, width, height);
+}
+
+
+/**
+ * Set new viewport parameters and update derived state (the _WindowMap
+ * matrix). Usually called from _mesa_Viewport().
+ *
+ * \param ctx GL context.
+ * \param x, y coordinates of the lower left corner of the viewport rectangle.
+ * \param width width of the viewport rectangle.
+ * \param height height of the viewport rectangle.
+ */
+void
+_mesa_set_viewport(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
+
+ if (width < 0 || height < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glViewport(%d, %d, %d, %d)", x, y, width, height);
+ return;
+ }
+
+ /* clamp width and height to the implementation dependent range */
+ width = MIN2(width, (GLsizei) ctx->Const.MaxViewportWidth);
+ height = MIN2(height, (GLsizei) ctx->Const.MaxViewportHeight);
+
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+ ctx->NewState |= _NEW_VIEWPORT;
+
+#if 1
+ /* XXX remove this someday. Currently the DRI drivers rely on
+ * the WindowMap matrix being up to date in the driver's Viewport
+ * and DepthRange functions.
+ */
+ _math_matrix_viewport(&ctx->Viewport._WindowMap,
+ ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height,
+ ctx->Viewport.Near, ctx->Viewport.Far,
+ ctx->DrawBuffer->_DepthMaxF);
+#endif
+
+ if (ctx->Driver.Viewport) {
+ /* Many drivers will use this call to check for window size changes
+ * and reallocate the z/stencil/accum/etc buffers if needed.
+ */
+ ctx->Driver.Viewport(ctx, x, y, width, height);
+ }
+}
+
+
+/**
+ * Called by glDepthRange
+ *
+ * \param nearval specifies the Z buffer value which should correspond to
+ * the near clip plane
+ * \param farval specifies the Z buffer value which should correspond to
+ * the far clip plane
+ */
+void GLAPIENTRY
+_mesa_DepthRange(GLclampd nearval, GLclampd farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
+
+ if (ctx->Viewport.Near == nearval &&
+ ctx->Viewport.Far == farval)
+ return;
+
+ ctx->Viewport.Near = (GLfloat) CLAMP(nearval, 0.0, 1.0);
+ ctx->Viewport.Far = (GLfloat) CLAMP(farval, 0.0, 1.0);
+ ctx->NewState |= _NEW_VIEWPORT;
+
+#if 1
+ /* XXX remove this someday. Currently the DRI drivers rely on
+ * the WindowMap matrix being up to date in the driver's Viewport
+ * and DepthRange functions.
+ */
+ _math_matrix_viewport(&ctx->Viewport._WindowMap,
+ ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height,
+ ctx->Viewport.Near, ctx->Viewport.Far,
+ ctx->DrawBuffer->_DepthMaxF);
+#endif
+
+ if (ctx->Driver.DepthRange) {
+ ctx->Driver.DepthRange(ctx, nearval, farval);
+ }
+}
+
+
+
+/**
+ * Initialize the context viewport attribute group.
+ * \param ctx the GL context.
+ */
+void _mesa_init_viewport(GLcontext *ctx)
+{
+ GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
+
+ /* 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;
+ _math_matrix_ctr(&ctx->Viewport._WindowMap);
+
+ _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0,
+ 0.0F, 1.0F, depthMax);
+}
+
+
+/**
+ * Free the context viewport attribute group data.
+ * \param ctx the GL context.
+ */
+void _mesa_free_viewport_data(GLcontext *ctx)
+{
+ _math_matrix_dtr(&ctx->Viewport._WindowMap);
+}
+
diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h
new file mode 100644
index 000000000..f08fef279
--- /dev/null
+++ b/mesalib/src/mesa/main/viewport.h
@@ -0,0 +1,52 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 VIEWPORT_H
+#define VIEWPORT_H
+
+
+extern void GLAPIENTRY
+_mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+extern void
+_mesa_set_viewport(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height);
+
+
+extern void GLAPIENTRY
+_mesa_DepthRange(GLclampd nearval, GLclampd farval);
+
+
+extern void
+_mesa_init_viewport(GLcontext *ctx);
+
+
+extern void
+_mesa_free_viewport_data(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/main/vsnprintf.c b/mesalib/src/mesa/main/vsnprintf.c
new file mode 100644
index 000000000..ab6c740d7
--- /dev/null
+++ b/mesalib/src/mesa/main/vsnprintf.c
@@ -0,0 +1,165 @@
+/*
+ * Revision 12: http://theos.com/~deraadt/snprintf.c
+ *
+ * Copyright (c) 1997 Theo de Raadt
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __VMS
+# include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#include <stdlib.h>
+#else
+#include <varargs.h>
+#endif
+#include <setjmp.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#endif
+
+#ifdef __sgi
+#define size_t ssize_t
+#endif
+
+static int pgsize;
+static char *curobj;
+static int caught;
+static sigjmp_buf bail;
+
+#define EXTRABYTES 2 /* XXX: why 2? you don't want to know */
+
+static char *
+msetup(str, n)
+ char *str;
+ size_t n;
+{
+ char *e;
+
+ if (n == 0)
+ return NULL;
+ if (pgsize == 0)
+ pgsize = getpagesize();
+ curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2);
+ if (curobj == NULL)
+ return NULL;
+ e = curobj + n + EXTRABYTES;
+ e = (char *)roundup((unsigned long)e, pgsize);
+ if (mprotect(e, pgsize, PROT_NONE) == -1) {
+ free(curobj);
+ curobj = NULL;
+ return NULL;
+ }
+ e = e - n - EXTRABYTES;
+ *e = '\0';
+ return (e);
+}
+
+static void
+ mcatch( int a )
+{
+ siglongjmp(bail, 1);
+}
+
+static void
+mcleanup(str, n, p)
+ char *str;
+ size_t n;
+ char *p;
+{
+ strncpy(str, p, n-1);
+ str[n-1] = '\0';
+ if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+ PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
+ mprotect((caddr_t)(p + n + EXTRABYTES), pgsize,
+ PROT_READ|PROT_WRITE);
+ free(curobj);
+}
+
+int
+#if __STDC__
+vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
+#else
+vsnprintf(str, n, fmt, ap)
+ char *str;
+ size_t n;
+ char *fmt;
+ char *ap;
+#endif
+{
+ struct sigaction osa, nsa;
+ char *p;
+ int ret = n + 1; /* if we bail, indicated we overflowed */
+
+ memset(&nsa, 0, sizeof nsa);
+ nsa.sa_handler = mcatch;
+ sigemptyset(&nsa.sa_mask);
+
+ p = msetup(str, n);
+ if (p == NULL) {
+ *str = '\0';
+ return 0;
+ }
+ if (sigsetjmp(bail, 1) == 0) {
+ if (sigaction(SIGSEGV, &nsa, &osa) == -1) {
+ mcleanup(str, n, p);
+ return (0);
+ }
+ ret = vsprintf(p, fmt, ap);
+ }
+ mcleanup(str, n, p);
+ (void) sigaction(SIGSEGV, &osa, NULL);
+ return (ret);
+}
+
+int
+#if __STDC__
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+ char *str;
+ size_t n;
+ char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+
+ return (vsnprintf(str, n, fmt, ap));
+ va_end(ap);
+}
+
+
+
diff --git a/mesalib/src/mesa/main/vtxfmt.c b/mesalib/src/mesa/main/vtxfmt.c
new file mode 100644
index 000000000..8d6f560a8
--- /dev/null
+++ b/mesalib/src/mesa/main/vtxfmt.c
@@ -0,0 +1,195 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Gareth Hughes
+ */
+
+#include "glheader.h"
+#include "api_loopback.h"
+#include "context.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+#include "vtxfmt.h"
+
+
+/* The neutral vertex format. This wraps all tnl module functions,
+ * verifying that the currently-installed module is valid and then
+ * installing the function pointers in a lazy fashion. It records the
+ * function pointers that have been swapped out, which allows a fast
+ * restoration of the neutral module in almost all cases -- a typical
+ * app might only require 4-6 functions to be modified from the neutral
+ * baseline, and only restoring these is certainly preferable to doing
+ * the entire module's 60 or so function pointers.
+ */
+
+#define PRE_LOOPBACK( FUNC ) \
+{ \
+ GET_CURRENT_CONTEXT(ctx); \
+ struct gl_tnl_module * const tnl = &(ctx->TnlModule); \
+ const int tmp_offset = _gloffset_ ## FUNC ; \
+ \
+ ASSERT( tnl->Current ); \
+ ASSERT( tnl->SwapCount < NUM_VERTEX_FORMAT_ENTRIES ); \
+ ASSERT( tmp_offset >= 0 ); \
+ \
+ if (tnl->SwapCount == 0) \
+ ctx->Driver.BeginVertices( ctx ); \
+ \
+ /* Save the swapped function's dispatch entry so it can be */ \
+ /* restored later. */ \
+ tnl->Swapped[tnl->SwapCount].location = & (((_glapi_proc *)ctx->Exec)[tmp_offset]); \
+ tnl->Swapped[tnl->SwapCount].function = (_glapi_proc)TAG(FUNC); \
+ tnl->SwapCount++; \
+ \
+ if ( 0 ) \
+ _mesa_debug(ctx, " swapping gl" #FUNC"...\n" ); \
+ \
+ /* Install the tnl function pointer. */ \
+ SET_ ## FUNC(ctx->Exec, tnl->Current->FUNC); \
+}
+
+#define TAG(x) neutral_##x
+#include "vtxfmt_tmp.h"
+
+
+/**
+ * Use the per-vertex functions found in <vfmt> to initialze the given
+ * API dispatch table.
+ */
+static void
+install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt )
+{
+ SET_ArrayElement(tab, vfmt->ArrayElement);
+ SET_Color3f(tab, vfmt->Color3f);
+ SET_Color3fv(tab, vfmt->Color3fv);
+ SET_Color4f(tab, vfmt->Color4f);
+ SET_Color4fv(tab, vfmt->Color4fv);
+ SET_EdgeFlag(tab, vfmt->EdgeFlag);
+ SET_EvalCoord1f(tab, vfmt->EvalCoord1f);
+ SET_EvalCoord1fv(tab, vfmt->EvalCoord1fv);
+ SET_EvalCoord2f(tab, vfmt->EvalCoord2f);
+ SET_EvalCoord2fv(tab, vfmt->EvalCoord2fv);
+ SET_EvalPoint1(tab, vfmt->EvalPoint1);
+ SET_EvalPoint2(tab, vfmt->EvalPoint2);
+ SET_FogCoordfEXT(tab, vfmt->FogCoordfEXT);
+ SET_FogCoordfvEXT(tab, vfmt->FogCoordfvEXT);
+ SET_Indexf(tab, vfmt->Indexf);
+ SET_Indexfv(tab, vfmt->Indexfv);
+ SET_Materialfv(tab, vfmt->Materialfv);
+ SET_MultiTexCoord1fARB(tab, vfmt->MultiTexCoord1fARB);
+ SET_MultiTexCoord1fvARB(tab, vfmt->MultiTexCoord1fvARB);
+ SET_MultiTexCoord2fARB(tab, vfmt->MultiTexCoord2fARB);
+ SET_MultiTexCoord2fvARB(tab, vfmt->MultiTexCoord2fvARB);
+ SET_MultiTexCoord3fARB(tab, vfmt->MultiTexCoord3fARB);
+ SET_MultiTexCoord3fvARB(tab, vfmt->MultiTexCoord3fvARB);
+ SET_MultiTexCoord4fARB(tab, vfmt->MultiTexCoord4fARB);
+ SET_MultiTexCoord4fvARB(tab, vfmt->MultiTexCoord4fvARB);
+ SET_Normal3f(tab, vfmt->Normal3f);
+ SET_Normal3fv(tab, vfmt->Normal3fv);
+ SET_SecondaryColor3fEXT(tab, vfmt->SecondaryColor3fEXT);
+ SET_SecondaryColor3fvEXT(tab, vfmt->SecondaryColor3fvEXT);
+ SET_TexCoord1f(tab, vfmt->TexCoord1f);
+ SET_TexCoord1fv(tab, vfmt->TexCoord1fv);
+ SET_TexCoord2f(tab, vfmt->TexCoord2f);
+ SET_TexCoord2fv(tab, vfmt->TexCoord2fv);
+ SET_TexCoord3f(tab, vfmt->TexCoord3f);
+ SET_TexCoord3fv(tab, vfmt->TexCoord3fv);
+ SET_TexCoord4f(tab, vfmt->TexCoord4f);
+ SET_TexCoord4fv(tab, vfmt->TexCoord4fv);
+ SET_Vertex2f(tab, vfmt->Vertex2f);
+ SET_Vertex2fv(tab, vfmt->Vertex2fv);
+ SET_Vertex3f(tab, vfmt->Vertex3f);
+ SET_Vertex3fv(tab, vfmt->Vertex3fv);
+ SET_Vertex4f(tab, vfmt->Vertex4f);
+ SET_Vertex4fv(tab, vfmt->Vertex4fv);
+ SET_CallList(tab, vfmt->CallList);
+ SET_CallLists(tab, vfmt->CallLists);
+ SET_Begin(tab, vfmt->Begin);
+ SET_End(tab, vfmt->End);
+ SET_Rectf(tab, vfmt->Rectf);
+ SET_DrawArrays(tab, vfmt->DrawArrays);
+ SET_DrawElements(tab, vfmt->DrawElements);
+ SET_DrawRangeElements(tab, vfmt->DrawRangeElements);
+ SET_MultiDrawElementsEXT(tab, vfmt->MultiDrawElementsEXT);
+ SET_EvalMesh1(tab, vfmt->EvalMesh1);
+ SET_EvalMesh2(tab, vfmt->EvalMesh2);
+ ASSERT(tab->EvalMesh2);
+
+ /* GL_NV_vertex_program */
+ SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV);
+ SET_VertexAttrib1fvNV(tab, vfmt->VertexAttrib1fvNV);
+ SET_VertexAttrib2fNV(tab, vfmt->VertexAttrib2fNV);
+ SET_VertexAttrib2fvNV(tab, vfmt->VertexAttrib2fvNV);
+ SET_VertexAttrib3fNV(tab, vfmt->VertexAttrib3fNV);
+ SET_VertexAttrib3fvNV(tab, vfmt->VertexAttrib3fvNV);
+ SET_VertexAttrib4fNV(tab, vfmt->VertexAttrib4fNV);
+ SET_VertexAttrib4fvNV(tab, vfmt->VertexAttrib4fvNV);
+#if FEATURE_ARB_vertex_program
+ SET_VertexAttrib1fARB(tab, vfmt->VertexAttrib1fARB);
+ SET_VertexAttrib1fvARB(tab, vfmt->VertexAttrib1fvARB);
+ SET_VertexAttrib2fARB(tab, vfmt->VertexAttrib2fARB);
+ SET_VertexAttrib2fvARB(tab, vfmt->VertexAttrib2fvARB);
+ SET_VertexAttrib3fARB(tab, vfmt->VertexAttrib3fARB);
+ SET_VertexAttrib3fvARB(tab, vfmt->VertexAttrib3fvARB);
+ SET_VertexAttrib4fARB(tab, vfmt->VertexAttrib4fARB);
+ SET_VertexAttrib4fvARB(tab, vfmt->VertexAttrib4fvARB);
+#endif
+}
+
+
+void _mesa_init_exec_vtxfmt( GLcontext *ctx )
+{
+ install_vtxfmt( ctx->Exec, &neutral_vtxfmt );
+ ctx->TnlModule.SwapCount = 0;
+}
+
+
+void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
+{
+ ctx->TnlModule.Current = vfmt;
+ _mesa_restore_exec_vtxfmt( ctx );
+}
+
+
+void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt )
+{
+ install_vtxfmt( ctx->Save, vfmt );
+}
+
+
+void _mesa_restore_exec_vtxfmt( GLcontext *ctx )
+{
+ struct gl_tnl_module *tnl = &(ctx->TnlModule);
+ GLuint i;
+
+ /* Restore the neutral tnl module wrapper.
+ */
+ for ( i = 0 ; i < tnl->SwapCount ; i++ ) {
+ *(tnl->Swapped[i].location) = tnl->Swapped[i].function;
+ }
+
+ tnl->SwapCount = 0;
+}
diff --git a/mesalib/src/mesa/main/vtxfmt.h b/mesalib/src/mesa/main/vtxfmt.h
new file mode 100644
index 000000000..76f108e02
--- /dev/null
+++ b/mesalib/src/mesa/main/vtxfmt.h
@@ -0,0 +1,43 @@
+/**
+ * \file vtxfmt.h
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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 _VTXFMT_H_
+#define _VTXFMT_H_
+
+extern void _mesa_init_exec_vtxfmt( GLcontext *ctx );
+
+extern void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt );
+extern void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt );
+
+extern void _mesa_restore_exec_vtxfmt( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/main/vtxfmt_tmp.h b/mesalib/src/mesa/main/vtxfmt_tmp.h
new file mode 100644
index 000000000..1308d0aa4
--- /dev/null
+++ b/mesalib/src/mesa/main/vtxfmt_tmp.h
@@ -0,0 +1,542 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes
+ */
+
+#ifndef PRE_LOOPBACK
+#define PRE_LOOPBACK( FUNC )
+#endif
+
+#include "glapi/dispatch.h"
+#include "glapi/glapioffsets.h"
+
+static void GLAPIENTRY TAG(ArrayElement)( GLint i )
+{
+ PRE_LOOPBACK( ArrayElement );
+ CALL_ArrayElement(GET_DISPATCH(), ( i ));
+}
+
+static void GLAPIENTRY TAG(Color3f)( GLfloat r, GLfloat g, GLfloat b )
+{
+ PRE_LOOPBACK( Color3f );
+ CALL_Color3f(GET_DISPATCH(), ( r, g, b ));
+}
+
+static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Color3fv );
+ CALL_Color3fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+ PRE_LOOPBACK( Color4f );
+ CALL_Color4f(GET_DISPATCH(), ( r, g, b, a ));
+}
+
+static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Color4fv );
+ CALL_Color4fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(EdgeFlag)( GLboolean e )
+{
+ PRE_LOOPBACK( EdgeFlag );
+ CALL_EdgeFlag(GET_DISPATCH(), ( e ));
+}
+
+static void GLAPIENTRY TAG(EvalCoord1f)( GLfloat s )
+{
+ PRE_LOOPBACK( EvalCoord1f );
+ CALL_EvalCoord1f(GET_DISPATCH(), ( s ));
+}
+
+static void GLAPIENTRY TAG(EvalCoord1fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( EvalCoord1fv );
+ CALL_EvalCoord1fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(EvalCoord2f)( GLfloat s, GLfloat t )
+{
+ PRE_LOOPBACK( EvalCoord2f );
+ CALL_EvalCoord2f(GET_DISPATCH(), ( s, t ));
+}
+
+static void GLAPIENTRY TAG(EvalCoord2fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( EvalCoord2fv );
+ CALL_EvalCoord2fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(EvalPoint1)( GLint i )
+{
+ PRE_LOOPBACK( EvalPoint1 );
+ CALL_EvalPoint1(GET_DISPATCH(), ( i ));
+}
+
+static void GLAPIENTRY TAG(EvalPoint2)( GLint i, GLint j )
+{
+ PRE_LOOPBACK( EvalPoint2 );
+ CALL_EvalPoint2(GET_DISPATCH(), ( i, j ));
+}
+
+static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat f )
+{
+ PRE_LOOPBACK( FogCoordfEXT );
+ CALL_FogCoordfEXT(GET_DISPATCH(), ( f ));
+}
+
+static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v )
+{
+ PRE_LOOPBACK( FogCoordfvEXT );
+ CALL_FogCoordfvEXT(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(Indexf)( GLfloat f )
+{
+ PRE_LOOPBACK( Indexf );
+ CALL_Indexf(GET_DISPATCH(), ( f ));
+}
+
+static void GLAPIENTRY TAG(Indexfv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Indexfv );
+ CALL_Indexfv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname, const GLfloat *v )
+{
+ PRE_LOOPBACK( Materialfv );
+ CALL_Materialfv(GET_DISPATCH(), ( face, pname, v ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord1fARB)( GLenum target, GLfloat a )
+{
+ PRE_LOOPBACK( MultiTexCoord1fARB );
+ CALL_MultiTexCoord1fARB(GET_DISPATCH(), ( target, a ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord1fvARB)( GLenum target, const GLfloat *tc )
+{
+ PRE_LOOPBACK( MultiTexCoord1fvARB );
+ CALL_MultiTexCoord1fvARB(GET_DISPATCH(), ( target, tc ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord2fARB)( GLenum target, GLfloat s, GLfloat t )
+{
+ PRE_LOOPBACK( MultiTexCoord2fARB );
+ CALL_MultiTexCoord2fARB(GET_DISPATCH(), ( target, s, t ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord2fvARB)( GLenum target, const GLfloat *tc )
+{
+ PRE_LOOPBACK( MultiTexCoord2fvARB );
+ CALL_MultiTexCoord2fvARB(GET_DISPATCH(), ( target, tc ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord3fARB)( GLenum target, GLfloat s,
+ GLfloat t, GLfloat r )
+{
+ PRE_LOOPBACK( MultiTexCoord3fARB );
+ CALL_MultiTexCoord3fARB(GET_DISPATCH(), ( target, s, t, r ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord3fvARB)( GLenum target, const GLfloat *tc )
+{
+ PRE_LOOPBACK( MultiTexCoord3fvARB );
+ CALL_MultiTexCoord3fvARB(GET_DISPATCH(), ( target, tc ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord4fARB)( GLenum target, GLfloat s,
+ GLfloat t, GLfloat r, GLfloat q )
+{
+ PRE_LOOPBACK( MultiTexCoord4fARB );
+ CALL_MultiTexCoord4fARB(GET_DISPATCH(), ( target, s, t, r, q ));
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord4fvARB)( GLenum target, const GLfloat *tc )
+{
+ PRE_LOOPBACK( MultiTexCoord4fvARB );
+ CALL_MultiTexCoord4fvARB(GET_DISPATCH(), ( target, tc ));
+}
+
+static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ PRE_LOOPBACK( Normal3f );
+ CALL_Normal3f(GET_DISPATCH(), ( x, y, z ));
+}
+
+static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Normal3fv );
+ CALL_Normal3fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat r, GLfloat g, GLfloat b )
+{
+ PRE_LOOPBACK( SecondaryColor3fEXT );
+ CALL_SecondaryColor3fEXT(GET_DISPATCH(), ( r, g, b ));
+}
+
+static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v )
+{
+ PRE_LOOPBACK( SecondaryColor3fvEXT );
+ CALL_SecondaryColor3fvEXT(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(TexCoord1f)( GLfloat s )
+{
+ PRE_LOOPBACK( TexCoord1f );
+ CALL_TexCoord1f(GET_DISPATCH(), ( s ));
+}
+
+static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *tc )
+{
+ PRE_LOOPBACK( TexCoord1fv );
+ CALL_TexCoord1fv(GET_DISPATCH(), ( tc ));
+}
+
+static void GLAPIENTRY TAG(TexCoord2f)( GLfloat s, GLfloat t )
+{
+ PRE_LOOPBACK( TexCoord2f );
+ CALL_TexCoord2f(GET_DISPATCH(), ( s, t ));
+}
+
+static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *tc )
+{
+ PRE_LOOPBACK( TexCoord2fv );
+ CALL_TexCoord2fv(GET_DISPATCH(), ( tc ));
+}
+
+static void GLAPIENTRY TAG(TexCoord3f)( GLfloat s, GLfloat t, GLfloat r )
+{
+ PRE_LOOPBACK( TexCoord3f );
+ CALL_TexCoord3f(GET_DISPATCH(), ( s, t, r ));
+}
+
+static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *tc )
+{
+ PRE_LOOPBACK( TexCoord3fv );
+ CALL_TexCoord3fv(GET_DISPATCH(), ( tc ));
+}
+
+static void GLAPIENTRY TAG(TexCoord4f)( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+{
+ PRE_LOOPBACK( TexCoord4f );
+ CALL_TexCoord4f(GET_DISPATCH(), ( s, t, r, q ));
+}
+
+static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *tc )
+{
+ PRE_LOOPBACK( TexCoord4fv );
+ CALL_TexCoord4fv(GET_DISPATCH(), ( tc ));
+}
+
+static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y )
+{
+ PRE_LOOPBACK( Vertex2f );
+ CALL_Vertex2f(GET_DISPATCH(), ( x, y ));
+}
+
+static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Vertex2fv );
+ CALL_Vertex2fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ PRE_LOOPBACK( Vertex3f );
+ CALL_Vertex3f(GET_DISPATCH(), ( x, y, z ));
+}
+
+static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Vertex3fv );
+ CALL_Vertex3fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ PRE_LOOPBACK( Vertex4f );
+ CALL_Vertex4f(GET_DISPATCH(), ( x, y, z, w ));
+}
+
+static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v )
+{
+ PRE_LOOPBACK( Vertex4fv );
+ CALL_Vertex4fv(GET_DISPATCH(), ( v ));
+}
+
+static void GLAPIENTRY TAG(CallList)( GLuint i )
+{
+ PRE_LOOPBACK( CallList );
+ CALL_CallList(GET_DISPATCH(), ( i ));
+}
+
+static void GLAPIENTRY TAG(CallLists)( GLsizei sz, GLenum type, const GLvoid *v )
+{
+ PRE_LOOPBACK( CallLists );
+ CALL_CallLists(GET_DISPATCH(), ( sz, type, v ));
+}
+
+static void GLAPIENTRY TAG(Begin)( GLenum mode )
+{
+ PRE_LOOPBACK( Begin );
+ CALL_Begin(GET_DISPATCH(), ( mode ));
+}
+
+static void GLAPIENTRY TAG(End)( void )
+{
+ PRE_LOOPBACK( End );
+ CALL_End(GET_DISPATCH(), ());
+}
+
+static void GLAPIENTRY TAG(Rectf)( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ PRE_LOOPBACK( Rectf );
+ CALL_Rectf(GET_DISPATCH(), ( x1, y1, x2, y2 ));
+}
+
+static void GLAPIENTRY TAG(DrawArrays)( GLenum mode, GLint start, GLsizei count )
+{
+ PRE_LOOPBACK( DrawArrays );
+ CALL_DrawArrays(GET_DISPATCH(), ( mode, start, count ));
+}
+
+static void GLAPIENTRY TAG(DrawElements)( GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices )
+{
+ PRE_LOOPBACK( DrawElements );
+ CALL_DrawElements(GET_DISPATCH(), ( mode, count, type, indices ));
+}
+
+static void GLAPIENTRY TAG(MultiDrawElementsEXT)( GLenum mode,
+ const GLsizei *count,
+ GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount)
+{
+ PRE_LOOPBACK( MultiDrawElementsEXT );
+ CALL_MultiDrawElementsEXT(GET_DISPATCH(), ( mode, count, type, indices,
+ primcount ));
+}
+
+static void GLAPIENTRY TAG(DrawRangeElements)( GLenum mode, GLuint start,
+ GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices )
+{
+ PRE_LOOPBACK( DrawRangeElements );
+ CALL_DrawRangeElements(GET_DISPATCH(), ( mode, start, end, count, type, indices ));
+}
+
+static void GLAPIENTRY TAG(EvalMesh1)( GLenum mode, GLint i1, GLint i2 )
+{
+ PRE_LOOPBACK( EvalMesh1 );
+ CALL_EvalMesh1(GET_DISPATCH(), ( mode, i1, i2 ));
+}
+
+static void GLAPIENTRY TAG(EvalMesh2)( GLenum mode, GLint i1, GLint i2,
+ GLint j1, GLint j2 )
+{
+ PRE_LOOPBACK( EvalMesh2 );
+ CALL_EvalMesh2(GET_DISPATCH(), ( mode, i1, i2, j1, j2 ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x )
+{
+ PRE_LOOPBACK( VertexAttrib1fNV );
+ CALL_VertexAttrib1fNV(GET_DISPATCH(), ( index, x ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib1fvNV );
+ CALL_VertexAttrib1fvNV(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y )
+{
+ PRE_LOOPBACK( VertexAttrib2fNV );
+ CALL_VertexAttrib2fNV(GET_DISPATCH(), ( index, x, y ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib2fvNV );
+ CALL_VertexAttrib2fvNV(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z )
+{
+ PRE_LOOPBACK( VertexAttrib3fNV );
+ CALL_VertexAttrib3fNV(GET_DISPATCH(), ( index, x, y, z ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib3fvNV );
+ CALL_VertexAttrib3fvNV(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ PRE_LOOPBACK( VertexAttrib4fNV );
+ CALL_VertexAttrib4fNV(GET_DISPATCH(), ( index, x, y, z, w ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib4fvNV );
+ CALL_VertexAttrib4fvNV(GET_DISPATCH(), ( index, v ));
+}
+
+
+static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x )
+{
+ PRE_LOOPBACK( VertexAttrib1fARB );
+ CALL_VertexAttrib1fARB(GET_DISPATCH(), ( index, x ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib1fvARB );
+ CALL_VertexAttrib1fvARB(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x, GLfloat y )
+{
+ PRE_LOOPBACK( VertexAttrib2fARB );
+ CALL_VertexAttrib2fARB(GET_DISPATCH(), ( index, x, y ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib2fvARB );
+ CALL_VertexAttrib2fvARB(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z )
+{
+ PRE_LOOPBACK( VertexAttrib3fARB );
+ CALL_VertexAttrib3fARB(GET_DISPATCH(), ( index, x, y, z ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib3fvARB );
+ CALL_VertexAttrib3fvARB(GET_DISPATCH(), ( index, v ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ PRE_LOOPBACK( VertexAttrib4fARB );
+ CALL_VertexAttrib4fARB(GET_DISPATCH(), ( index, x, y, z, w ));
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index, const GLfloat *v )
+{
+ PRE_LOOPBACK( VertexAttrib4fvARB );
+ CALL_VertexAttrib4fvARB(GET_DISPATCH(), ( index, v ));
+}
+
+
+static GLvertexformat TAG(vtxfmt) = {
+ TAG(ArrayElement),
+ TAG(Color3f),
+ TAG(Color3fv),
+ TAG(Color4f),
+ TAG(Color4fv),
+ TAG(EdgeFlag),
+ TAG(EvalCoord1f),
+ TAG(EvalCoord1fv),
+ TAG(EvalCoord2f),
+ TAG(EvalCoord2fv),
+ TAG(EvalPoint1),
+ TAG(EvalPoint2),
+ TAG(FogCoordfEXT),
+ TAG(FogCoordfvEXT),
+ TAG(Indexf),
+ TAG(Indexfv),
+ TAG(Materialfv),
+ TAG(MultiTexCoord1fARB),
+ TAG(MultiTexCoord1fvARB),
+ TAG(MultiTexCoord2fARB),
+ TAG(MultiTexCoord2fvARB),
+ TAG(MultiTexCoord3fARB),
+ TAG(MultiTexCoord3fvARB),
+ TAG(MultiTexCoord4fARB),
+ TAG(MultiTexCoord4fvARB),
+ TAG(Normal3f),
+ TAG(Normal3fv),
+ TAG(SecondaryColor3fEXT),
+ TAG(SecondaryColor3fvEXT),
+ TAG(TexCoord1f),
+ TAG(TexCoord1fv),
+ TAG(TexCoord2f),
+ TAG(TexCoord2fv),
+ TAG(TexCoord3f),
+ TAG(TexCoord3fv),
+ TAG(TexCoord4f),
+ TAG(TexCoord4fv),
+ TAG(Vertex2f),
+ TAG(Vertex2fv),
+ TAG(Vertex3f),
+ TAG(Vertex3fv),
+ TAG(Vertex4f),
+ TAG(Vertex4fv),
+ TAG(CallList),
+ TAG(CallLists),
+ TAG(Begin),
+ TAG(End),
+ TAG(VertexAttrib1fNV),
+ TAG(VertexAttrib1fvNV),
+ TAG(VertexAttrib2fNV),
+ TAG(VertexAttrib2fvNV),
+ TAG(VertexAttrib3fNV),
+ TAG(VertexAttrib3fvNV),
+ TAG(VertexAttrib4fNV),
+ TAG(VertexAttrib4fvNV),
+ TAG(VertexAttrib1fARB),
+ TAG(VertexAttrib1fvARB),
+ TAG(VertexAttrib2fARB),
+ TAG(VertexAttrib2fvARB),
+ TAG(VertexAttrib3fARB),
+ TAG(VertexAttrib3fvARB),
+ TAG(VertexAttrib4fARB),
+ TAG(VertexAttrib4fvARB),
+ TAG(Rectf),
+ TAG(DrawArrays),
+ TAG(DrawElements),
+ TAG(DrawRangeElements),
+ TAG(MultiDrawElementsEXT),
+ TAG(EvalMesh1),
+ TAG(EvalMesh2)
+};
+
+#undef TAG
+#undef PRE_LOOPBACK
diff --git a/mesalib/src/mesa/math/descrip.mms b/mesalib/src/mesa/math/descrip.mms
new file mode 100644
index 000000000..3aaa6eb8b
--- /dev/null
+++ b/mesalib/src/mesa/math/descrip.mms
@@ -0,0 +1,47 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define glapi [-.glapi]
+ define main [-.main]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.main],[-.glapi]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = m_debug_clip.c m_debug_norm.c m_debug_xform.c m_eval.c m_matrix.c\
+ m_translate.c m_vector.c m_xform.c
+
+OBJECTS = m_debug_clip.obj,m_debug_norm.obj,m_debug_xform.obj,m_eval.obj,\
+ m_matrix.obj,m_translate.obj,m_vector.obj,m_xform.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+m_debug_clip.obj : m_debug_clip.c
+m_debug_norm.obj : m_debug_norm.c
+m_debug_xform.obj : m_debug_xform.c
+m_eval.obj : m_eval.c
+m_matrix.obj : m_matrix.c
+m_translate.obj : m_translate.c
+m_vector.obj : m_vector.c
+m_xform.obj : m_xform.c
diff --git a/mesalib/src/mesa/math/m_clip_tmp.h b/mesalib/src/mesa/math/m_clip_tmp.h
new file mode 100644
index 000000000..f3a589be0
--- /dev/null
+++ b/mesalib/src/mesa/math/m_clip_tmp.h
@@ -0,0 +1,243 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+/* KW: a clever asm implementation would nestle integer versions
+ * of the outcode calculation underneath the division. Gcc won't
+ * do this, strangely enough, so I only do the divide in
+ * the case where the cliptest passes. This isn't essential,
+ * and an asm implementation needn't replicate that behaviour.
+ *
+ * \param clip_vec vector of incoming clip-space coords
+ * \param proj_vec vector of resultant NDC-space projected coords
+ * \param clipMask resulting array of clip flags
+ * \param orMask bitwise-OR of clipMask values
+ * \param andMask bitwise-AND of clipMask values
+ * \return proj_vec pointer
+ */
+static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ const GLuint count = clip_vec->count;
+ GLuint c = 0;
+ GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
+ GLubyte tmpAndMask = *andMask;
+ GLubyte tmpOrMask = *orMask;
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat cx = from[0];
+ const GLfloat cy = from[1];
+ const GLfloat cz = from[2];
+ const GLfloat cw = from[3];
+#if defined(macintosh) || defined(__powerpc__)
+ /* on powerpc cliptest is 17% faster in this way. */
+ GLuint mask;
+ mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
+ mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
+ mask |= (((cw < cy) << CLIP_TOP_SHIFT));
+ mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
+ mask |= (((cw < cz) << CLIP_FAR_SHIFT));
+ mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+#else /* !defined(macintosh)) */
+ GLubyte mask = 0;
+ if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
+ if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
+ if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
+ if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
+ if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+#endif /* defined(macintosh) */
+
+ clipMask[i] = mask;
+ if (mask) {
+ c++;
+ tmpAndMask &= mask;
+ tmpOrMask |= mask;
+ vProj[i][0] = 0;
+ vProj[i][1] = 0;
+ vProj[i][2] = 0;
+ vProj[i][3] = 1;
+ } else {
+ GLfloat oow = 1.0F / cw;
+ vProj[i][0] = cx * oow;
+ vProj[i][1] = cy * oow;
+ vProj[i][2] = cz * oow;
+ vProj[i][3] = oow;
+ }
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
+
+ proj_vec->flags |= VEC_SIZE_4;
+ proj_vec->size = 4;
+ proj_vec->count = clip_vec->count;
+ return proj_vec;
+}
+
+
+
+/*
+ * \param clip_vec vector of incoming clip-space coords
+ * \param proj_vec vector of resultant NDC-space projected coords
+ * \param clipMask resulting array of clip flags
+ * \param orMask bitwise-OR of clipMask values
+ * \param andMask bitwise-AND of clipMask values
+ * \return clip_vec pointer
+ */
+static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ GLuint c = 0;
+ GLubyte tmpAndMask = *andMask;
+ GLubyte tmpOrMask = *orMask;
+ GLuint i;
+ (void) proj_vec;
+ STRIDE_LOOP {
+ const GLfloat cx = from[0];
+ const GLfloat cy = from[1];
+ const GLfloat cz = from[2];
+ const GLfloat cw = from[3];
+#if defined(macintosh) || defined(__powerpc__)
+ /* on powerpc cliptest is 17% faster in this way. */
+ GLuint mask;
+ mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
+ mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
+ mask |= (((cw < cy) << CLIP_TOP_SHIFT));
+ mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
+ mask |= (((cw < cz) << CLIP_FAR_SHIFT));
+ mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+#else /* !defined(macintosh)) */
+ GLubyte mask = 0;
+ if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
+ if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
+ if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
+ if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
+ if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+#endif /* defined(macintosh) */
+
+ clipMask[i] = mask;
+ if (mask) {
+ c++;
+ tmpAndMask &= mask;
+ tmpOrMask |= mask;
+ }
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
+ return clip_vec;
+}
+
+
+static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ GLubyte tmpOrMask = *orMask;
+ GLubyte tmpAndMask = *andMask;
+ GLuint i;
+ (void) proj_vec;
+ STRIDE_LOOP {
+ const GLfloat cx = from[0], cy = from[1], cz = from[2];
+ GLubyte mask = 0;
+ if (cx > 1.0) mask |= CLIP_RIGHT_BIT;
+ else if (cx < -1.0) mask |= CLIP_LEFT_BIT;
+ if (cy > 1.0) mask |= CLIP_TOP_BIT;
+ else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT;
+ if (cz > 1.0) mask |= CLIP_FAR_BIT;
+ else if (cz < -1.0) mask |= CLIP_NEAR_BIT;
+ clipMask[i] = mask;
+ tmpOrMask |= mask;
+ tmpAndMask &= mask;
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = tmpAndMask;
+ return clip_vec;
+}
+
+
+static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ GLubyte tmpOrMask = *orMask;
+ GLubyte tmpAndMask = *andMask;
+ GLuint i;
+ (void) proj_vec;
+ STRIDE_LOOP {
+ const GLfloat cx = from[0], cy = from[1];
+ GLubyte mask = 0;
+ if (cx > 1.0) mask |= CLIP_RIGHT_BIT;
+ else if (cx < -1.0) mask |= CLIP_LEFT_BIT;
+ if (cy > 1.0) mask |= CLIP_TOP_BIT;
+ else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT;
+ clipMask[i] = mask;
+ tmpOrMask |= mask;
+ tmpAndMask &= mask;
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = tmpAndMask;
+ return clip_vec;
+}
+
+
+static void TAG(init_c_cliptest)( void )
+{
+ _mesa_clip_tab[4] = TAG(cliptest_points4);
+ _mesa_clip_tab[3] = TAG(cliptest_points3);
+ _mesa_clip_tab[2] = TAG(cliptest_points2);
+
+ _mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
+ _mesa_clip_np_tab[3] = TAG(cliptest_points3);
+ _mesa_clip_np_tab[2] = TAG(cliptest_points2);
+}
diff --git a/mesalib/src/mesa/math/m_copy_tmp.h b/mesalib/src/mesa/math/m_copy_tmp.h
new file mode 100644
index 000000000..07ab1f7b2
--- /dev/null
+++ b/mesalib/src/mesa/math/m_copy_tmp.h
@@ -0,0 +1,86 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+#define COPY_FUNC( BITS ) \
+static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \
+{ \
+ GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \
+ GLfloat *from = f->start; \
+ GLuint stride = f->stride; \
+ GLuint count = to->count; \
+ GLuint i; \
+ \
+ if (BITS) \
+ STRIDE_LOOP { \
+ if (BITS&1) t[i][0] = from[0]; \
+ if (BITS&2) t[i][1] = from[1]; \
+ if (BITS&4) t[i][2] = from[2]; \
+ if (BITS&8) t[i][3] = from[3]; \
+ } \
+}
+
+/* We got them all here:
+ */
+COPY_FUNC( 0x0 ) /* noop */
+COPY_FUNC( 0x1 )
+COPY_FUNC( 0x2 )
+COPY_FUNC( 0x3 )
+COPY_FUNC( 0x4 )
+COPY_FUNC( 0x5 )
+COPY_FUNC( 0x6 )
+COPY_FUNC( 0x7 )
+COPY_FUNC( 0x8 )
+COPY_FUNC( 0x9 )
+COPY_FUNC( 0xa )
+COPY_FUNC( 0xb )
+COPY_FUNC( 0xc )
+COPY_FUNC( 0xd )
+COPY_FUNC( 0xe )
+COPY_FUNC( 0xf )
+
+static void TAG2(init_copy, 0)( void )
+{
+ _mesa_copy_tab[0x0] = TAG2(copy, 0x0);
+ _mesa_copy_tab[0x1] = TAG2(copy, 0x1);
+ _mesa_copy_tab[0x2] = TAG2(copy, 0x2);
+ _mesa_copy_tab[0x3] = TAG2(copy, 0x3);
+ _mesa_copy_tab[0x4] = TAG2(copy, 0x4);
+ _mesa_copy_tab[0x5] = TAG2(copy, 0x5);
+ _mesa_copy_tab[0x6] = TAG2(copy, 0x6);
+ _mesa_copy_tab[0x7] = TAG2(copy, 0x7);
+ _mesa_copy_tab[0x8] = TAG2(copy, 0x8);
+ _mesa_copy_tab[0x9] = TAG2(copy, 0x9);
+ _mesa_copy_tab[0xa] = TAG2(copy, 0xa);
+ _mesa_copy_tab[0xb] = TAG2(copy, 0xb);
+ _mesa_copy_tab[0xc] = TAG2(copy, 0xc);
+ _mesa_copy_tab[0xd] = TAG2(copy, 0xd);
+ _mesa_copy_tab[0xe] = TAG2(copy, 0xe);
+ _mesa_copy_tab[0xf] = TAG2(copy, 0xf);
+}
diff --git a/mesalib/src/mesa/math/m_debug.h b/mesalib/src/mesa/math/m_debug.h
new file mode 100644
index 000000000..6476b6de2
--- /dev/null
+++ b/mesalib/src/mesa/math/m_debug.h
@@ -0,0 +1,42 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes
+ */
+
+#ifndef __M_DEBUG_H__
+#define __M_DEBUG_H__
+
+extern void _math_test_all_transform_functions( char *description );
+extern void _math_test_all_normal_transform_functions( char *description );
+extern void _math_test_all_cliptest_functions( char *description );
+
+/* Deprecated?
+ */
+extern void _math_test_all_vertex_functions( char *description );
+
+extern char *mesa_profile;
+
+#endif
diff --git a/mesalib/src/mesa/math/m_debug_clip.c b/mesalib/src/mesa/math/m_debug_clip.c
new file mode 100644
index 000000000..460fed4a7
--- /dev/null
+++ b/mesalib/src/mesa/math/m_debug_clip.c
@@ -0,0 +1,371 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+
+#include "m_matrix.h"
+#include "m_xform.h"
+
+#include "m_debug.h"
+#include "m_debug_util.h"
+
+#ifdef __UNIXOS2__
+/* The linker doesn't like empty files */
+static char dummy;
+#endif
+
+#ifdef DEBUG_MATH /* This code only used for debugging */
+
+static clip_func *clip_tab[2] = {
+ _mesa_clip_tab,
+ _mesa_clip_np_tab
+};
+static char *cnames[2] = {
+ "_mesa_clip_tab",
+ "_mesa_clip_np_tab"
+};
+#ifdef RUN_DEBUG_BENCHMARK
+static char *cstrings[2] = {
+ "clip, perspective divide",
+ "clip, no divide"
+};
+#endif
+
+
+/* =============================================================
+ * Reference cliptests
+ */
+
+static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ GLuint c = 0;
+ GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
+ GLubyte tmpAndMask = *andMask;
+ GLubyte tmpOrMask = *orMask;
+ GLuint i;
+ for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
+ const GLfloat cx = from[0];
+ const GLfloat cy = from[1];
+ const GLfloat cz = from[2];
+ const GLfloat cw = from[3];
+ GLubyte mask = 0;
+ if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT;
+ if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT;
+ if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT;
+ if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT;
+ if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT;
+ if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT;
+ clipMask[i] = mask;
+ if ( mask ) {
+ c++;
+ tmpAndMask &= mask;
+ tmpOrMask |= mask;
+ vProj[i][0] = 0;
+ vProj[i][1] = 0;
+ vProj[i][2] = 0;
+ vProj[i][3] = 1;
+ } else {
+ GLfloat oow = 1.0F / cw;
+ vProj[i][0] = cx * oow;
+ vProj[i][1] = cy * oow;
+ vProj[i][2] = cz * oow;
+ vProj[i][3] = oow;
+ }
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
+
+ proj_vec->flags |= VEC_SIZE_4;
+ proj_vec->size = 4;
+ proj_vec->count = clip_vec->count;
+ return proj_vec;
+}
+
+/* Keep these here for now, even though we don't use them...
+ */
+static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+
+ GLubyte tmpOrMask = *orMask;
+ GLubyte tmpAndMask = *andMask;
+ GLuint i;
+ for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
+ const GLfloat cx = from[0], cy = from[1], cz = from[2];
+ GLubyte mask = 0;
+ if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT;
+ else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT;
+ if ( cy > 1.0 ) mask |= CLIP_TOP_BIT;
+ else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT;
+ if ( cz > 1.0 ) mask |= CLIP_FAR_BIT;
+ else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT;
+ clipMask[i] = mask;
+ tmpOrMask |= mask;
+ tmpAndMask &= mask;
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = tmpAndMask;
+ return clip_vec;
+}
+
+static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask )
+{
+ const GLuint stride = clip_vec->stride;
+ const GLuint count = clip_vec->count;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+
+ GLubyte tmpOrMask = *orMask;
+ GLubyte tmpAndMask = *andMask;
+ GLuint i;
+ for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
+ const GLfloat cx = from[0], cy = from[1];
+ GLubyte mask = 0;
+ if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT;
+ else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT;
+ if ( cy > 1.0 ) mask |= CLIP_TOP_BIT;
+ else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT;
+ clipMask[i] = mask;
+ tmpOrMask |= mask;
+ tmpAndMask &= mask;
+ }
+
+ *orMask = tmpOrMask;
+ *andMask = tmpAndMask;
+ return clip_vec;
+}
+
+static clip_func ref_cliptest[5] = {
+ 0,
+ 0,
+ ref_cliptest_points2,
+ ref_cliptest_points3,
+ ref_cliptest_points4
+};
+
+
+/* =============================================================
+ * Cliptest tests
+ */
+
+ALIGN16(static GLfloat, s[TEST_COUNT][4]);
+ALIGN16(static GLfloat, d[TEST_COUNT][4]);
+ALIGN16(static GLfloat, r[TEST_COUNT][4]);
+
+
+static int test_cliptest_function( clip_func func, int np,
+ int psize, long *cycles )
+{
+ GLvector4f source[1], dest[1], ref[1];
+ GLubyte dm[TEST_COUNT], dco, dca;
+ GLubyte rm[TEST_COUNT], rco, rca;
+ int i, j;
+#ifdef RUN_DEBUG_BENCHMARK
+ int cycle_i; /* the counter for the benchmarks we run */
+#endif
+
+ (void) cycles;
+
+ if ( psize > 4 ) {
+ _mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" );
+ return 0;
+ }
+
+ for ( i = 0 ; i < TEST_COUNT ; i++) {
+ ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 );
+ for ( j = 0 ; j < psize ; j++ )
+ s[i][j] = rnd();
+ }
+
+ source->data = (GLfloat(*)[4])s;
+ source->start = (GLfloat *)s;
+ source->count = TEST_COUNT;
+ source->stride = sizeof(s[0]);
+ source->size = 4;
+ source->flags = 0;
+
+ dest->data = (GLfloat(*)[4])d;
+ dest->start = (GLfloat *)d;
+ dest->count = TEST_COUNT;
+ dest->stride = sizeof(float[4]);
+ dest->size = 0;
+ dest->flags = 0;
+
+ ref->data = (GLfloat(*)[4])r;
+ ref->start = (GLfloat *)r;
+ ref->count = TEST_COUNT;
+ ref->stride = sizeof(float[4]);
+ ref->size = 0;
+ ref->flags = 0;
+
+ dco = rco = 0;
+ dca = rca = CLIP_FRUSTUM_BITS;
+
+ ref_cliptest[psize]( source, ref, rm, &rco, &rca );
+
+ if ( mesa_profile ) {
+ BEGIN_RACE( *cycles );
+ func( source, dest, dm, &dco, &dca );
+ END_RACE( *cycles );
+ }
+ else {
+ func( source, dest, dm, &dco, &dca );
+ }
+
+ if ( dco != rco ) {
+ _mesa_printf( "\n-----------------------------\n" );
+ _mesa_printf( "dco = 0x%02x rco = 0x%02x\n", dco, rco );
+ return 0;
+ }
+ if ( dca != rca ) {
+ _mesa_printf( "\n-----------------------------\n" );
+ _mesa_printf( "dca = 0x%02x rca = 0x%02x\n", dca, rca );
+ return 0;
+ }
+ for ( i = 0 ; i < TEST_COUNT ; i++ ) {
+ if ( dm[i] != rm[i] ) {
+ _mesa_printf( "\n-----------------------------\n" );
+ _mesa_printf( "(i = %i)\n", i );
+ _mesa_printf( "dm = 0x%02x rm = 0x%02x\n", dm[i], rm[i] );
+ return 0;
+ }
+ }
+
+ /* Only verify output on projected points4 case. FIXME: Do we need
+ * to test other cases?
+ */
+ if ( np || psize < 4 )
+ return 1;
+
+ for ( i = 0 ; i < TEST_COUNT ; i++ ) {
+ for ( j = 0 ; j < 4 ; j++ ) {
+ if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
+ _mesa_printf( "\n-----------------------------\n" );
+ _mesa_printf( "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n",
+ i, j, dm[i], rm[i] );
+ _mesa_printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][0], r[i][0], r[i][0]-d[i][0],
+ MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
+ _mesa_printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][1], r[i][1], r[i][1]-d[i][1],
+ MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
+ _mesa_printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][2], r[i][2], r[i][2]-d[i][2],
+ MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
+ _mesa_printf( "%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][3], r[i][3], r[i][3]-d[i][3],
+ MAX_PRECISION - significand_match( d[i][3], r[i][3] ) );
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+void _math_test_all_cliptest_functions( char *description )
+{
+ int np, psize;
+ long benchmark_tab[2][4];
+ static int first_time = 1;
+
+ if ( first_time ) {
+ first_time = 0;
+ mesa_profile = _mesa_getenv( "MESA_PROFILE" );
+ }
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ if ( !counter_overhead ) {
+ INIT_COUNTER();
+ _mesa_printf( "counter overhead: %ld cycles\n\n", counter_overhead );
+ }
+ _mesa_printf( "cliptest results after hooking in %s functions:\n", description );
+ }
+#endif
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ _mesa_printf( "\n\t" );
+ for ( psize = 2 ; psize <= 4 ; psize++ ) {
+ _mesa_printf( " p%d\t", psize );
+ }
+ _mesa_printf( "\n--------------------------------------------------------\n\t" );
+ }
+#endif
+
+ for ( np = 0 ; np < 2 ; np++ ) {
+ for ( psize = 2 ; psize <= 4 ; psize++ ) {
+ clip_func func = clip_tab[np][psize];
+ long *cycles = &(benchmark_tab[np][psize-1]);
+
+ if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) {
+ char buf[100];
+ _mesa_sprintf( buf, "%s[%d] failed test (%s)",
+ cnames[np], psize, description );
+ _mesa_problem( NULL, buf );
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf( " %li\t", benchmark_tab[np][psize-1] );
+#endif
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf( " | [%s]\n\t", cstrings[np] );
+#endif
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf( "\n" );
+#endif
+}
+
+
+#endif /* DEBUG_MATH */
diff --git a/mesalib/src/mesa/math/m_debug_norm.c b/mesalib/src/mesa/math/m_debug_norm.c
new file mode 100644
index 000000000..89c632e7d
--- /dev/null
+++ b/mesalib/src/mesa/math/m_debug_norm.c
@@ -0,0 +1,383 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+
+#include "m_matrix.h"
+#include "m_xform.h"
+
+#include "m_debug.h"
+#include "m_debug_util.h"
+
+
+#ifdef __UNIXOS2__
+/* The linker doesn't like empty files */
+static char dummy;
+#endif
+
+#ifdef DEBUG_MATH /* This code only used for debugging */
+
+
+static int m_norm_identity[16] = {
+ ONE, NIL, NIL, NIL,
+ NIL, ONE, NIL, NIL,
+ NIL, NIL, ONE, NIL,
+ NIL, NIL, NIL, NIL
+};
+static int m_norm_general[16] = {
+ VAR, VAR, VAR, NIL,
+ VAR, VAR, VAR, NIL,
+ VAR, VAR, VAR, NIL,
+ NIL, NIL, NIL, NIL
+};
+static int m_norm_no_rot[16] = {
+ VAR, NIL, NIL, NIL,
+ NIL, VAR, NIL, NIL,
+ NIL, NIL, VAR, NIL,
+ NIL, NIL, NIL, NIL
+};
+static int *norm_templates[8] = {
+ m_norm_no_rot,
+ m_norm_no_rot,
+ m_norm_no_rot,
+ m_norm_general,
+ m_norm_general,
+ m_norm_general,
+ m_norm_identity,
+ m_norm_identity
+};
+static int norm_types[8] = {
+ NORM_TRANSFORM_NO_ROT,
+ NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
+ NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
+ NORM_TRANSFORM,
+ NORM_TRANSFORM | NORM_RESCALE,
+ NORM_TRANSFORM | NORM_NORMALIZE,
+ NORM_RESCALE,
+ NORM_NORMALIZE
+};
+static int norm_scale_types[8] = { /* rescale factor */
+ NIL, /* NIL disables rescaling */
+ VAR,
+ NIL,
+ NIL,
+ VAR,
+ NIL,
+ VAR,
+ NIL
+};
+static int norm_normalize_types[8] = { /* normalizing ?? (no = 0) */
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 1
+};
+static char *norm_strings[8] = {
+ "NORM_TRANSFORM_NO_ROT",
+ "NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
+ "NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
+ "NORM_TRANSFORM",
+ "NORM_TRANSFORM | NORM_RESCALE",
+ "NORM_TRANSFORM | NORM_NORMALIZE",
+ "NORM_RESCALE",
+ "NORM_NORMALIZE"
+};
+
+
+/* =============================================================
+ * Reference transformations
+ */
+
+static void ref_norm_transform_rescale( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLuint i;
+ const GLfloat *s = in->start;
+ const GLfloat *m = mat->inv;
+ GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
+
+ (void) lengths;
+
+ for ( i = 0 ; i < in->count ; i++ ) {
+ GLfloat t[3];
+
+ TRANSFORM_NORMAL( t, s, m );
+ SCALE_SCALAR_3V( out[i], scale, t );
+
+ s = (GLfloat *)((char *)s + in->stride);
+ }
+}
+
+static void ref_norm_transform_normalize( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLuint i;
+ const GLfloat *s = in->start;
+ const GLfloat *m = mat->inv;
+ GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
+
+ for ( i = 0 ; i < in->count ; i++ ) {
+ GLfloat t[3];
+
+ TRANSFORM_NORMAL( t, s, m );
+
+ if ( !lengths ) {
+ GLfloat len = LEN_SQUARED_3FV( t );
+ if ( len > 1e-20 ) {
+ /* Hmmm, don't know how we could test the precalculated
+ * length case...
+ */
+ scale = 1.0 / SQRTF( len );
+ SCALE_SCALAR_3V( out[i], scale, t );
+ } else {
+ out[i][0] = out[i][1] = out[i][2] = 0;
+ }
+ } else {
+ scale = lengths[i];;
+ SCALE_SCALAR_3V( out[i], scale, t );
+ }
+
+ s = (GLfloat *)((char *)s + in->stride);
+ }
+}
+
+
+/* =============================================================
+ * Normal transformation tests
+ */
+
+static void init_matrix( GLfloat *m )
+{
+ m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
+ m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0;
+ m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0;
+ m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0;
+}
+
+
+static int test_norm_function( normal_func func, int mtype, long *cycles )
+{
+ GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1];
+ GLmatrix mat[1];
+ GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
+ GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT];
+ GLfloat scale;
+ GLfloat *m;
+ int i, j;
+#ifdef RUN_DEBUG_BENCHMARK
+ int cycle_i; /* the counter for the benchmarks we run */
+#endif
+
+ (void) cycles;
+
+ mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+ mat->inv = m = mat->m;
+
+ init_matrix( m );
+
+ scale = 1.0F + rnd () * norm_scale_types[mtype];
+
+ for ( i = 0 ; i < 4 ; i++ ) {
+ for ( j = 0 ; j < 4 ; j++ ) {
+ switch ( norm_templates[mtype][i * 4 + j] ) {
+ case NIL:
+ m[j * 4 + i] = 0.0;
+ break;
+ case ONE:
+ m[j * 4 + i] = 1.0;
+ break;
+ case NEG:
+ m[j * 4 + i] = -1.0;
+ break;
+ case VAR:
+ break;
+ default:
+ _mesa_exit(1);
+ }
+ }
+ }
+
+ for ( i = 0 ; i < TEST_COUNT ; i++ ) {
+ ASSIGN_3V( d[i], 0.0, 0.0, 0.0 );
+ ASSIGN_3V( s[i], 0.0, 0.0, 0.0 );
+ ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 );
+ for ( j = 0 ; j < 3 ; j++ )
+ s[i][j] = rnd();
+ length[i] = 1 / SQRTF( LEN_SQUARED_3FV( s[i] ) );
+ }
+
+ source->data = (GLfloat(*)[4]) s;
+ source->start = (GLfloat *) s;
+ source->count = TEST_COUNT;
+ source->stride = sizeof(s[0]);
+ source->flags = 0;
+
+ dest->data = d;
+ dest->start = (GLfloat *) d;
+ dest->count = TEST_COUNT;
+ dest->stride = sizeof(float[4]);
+ dest->flags = 0;
+
+ dest2->data = d2;
+ dest2->start = (GLfloat *) d2;
+ dest2->count = TEST_COUNT;
+ dest2->stride = sizeof(float[4]);
+ dest2->flags = 0;
+
+ ref->data = r;
+ ref->start = (GLfloat *) r;
+ ref->count = TEST_COUNT;
+ ref->stride = sizeof(float[4]);
+ ref->flags = 0;
+
+ ref2->data = r2;
+ ref2->start = (GLfloat *) r2;
+ ref2->count = TEST_COUNT;
+ ref2->stride = sizeof(float[4]);
+ ref2->flags = 0;
+
+ if ( norm_normalize_types[mtype] == 0 ) {
+ ref_norm_transform_rescale( mat, scale, source, NULL, ref );
+ } else {
+ ref_norm_transform_normalize( mat, scale, source, NULL, ref );
+ ref_norm_transform_normalize( mat, scale, source, length, ref2 );
+ }
+
+ if ( mesa_profile ) {
+ BEGIN_RACE( *cycles );
+ func( mat, scale, source, NULL, dest );
+ END_RACE( *cycles );
+ func( mat, scale, source, length, dest2 );
+ } else {
+ func( mat, scale, source, NULL, dest );
+ func( mat, scale, source, length, dest2 );
+ }
+
+ for ( i = 0 ; i < TEST_COUNT ; i++ ) {
+ for ( j = 0 ; j < 3 ; j++ ) {
+ if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
+ _mesa_printf( "-----------------------------\n" );
+ _mesa_printf( "(i = %i, j = %i)\n", i, j );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d[i][0], r[i][0], r[i][0]/d[i][0],
+ MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d[i][1], r[i][1], r[i][1]/d[i][1],
+ MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d[i][2], r[i][2], r[i][2]/d[i][2],
+ MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
+ return 0;
+ }
+
+ if ( norm_normalize_types[mtype] != 0 ) {
+ if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) {
+ _mesa_printf( "------------------- precalculated length case ------\n" );
+ _mesa_printf( "(i = %i, j = %i)\n", i, j );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
+ MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d2[i][1], r2[i][1], r2[i][1]/d2[i][1],
+ MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) );
+ _mesa_printf( "%f \t %f \t [ratio = %e - %i bit missed]\n",
+ d2[i][2], r2[i][2], r2[i][2]/d2[i][2],
+ MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) );
+ return 0;
+ }
+ }
+ }
+ }
+
+ ALIGN_FREE( mat->m );
+ return 1;
+}
+
+void _math_test_all_normal_transform_functions( char *description )
+{
+ int mtype;
+ long benchmark_tab[0xf];
+ static int first_time = 1;
+
+ if ( first_time ) {
+ first_time = 0;
+ mesa_profile = _mesa_getenv( "MESA_PROFILE" );
+ }
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ if ( !counter_overhead ) {
+ INIT_COUNTER();
+ _mesa_printf( "counter overhead: %ld cycles\n\n", counter_overhead );
+ }
+ _mesa_printf( "normal transform results after hooking in %s functions:\n",
+ description );
+ _mesa_printf( "\n-------------------------------------------------------\n" );
+ }
+#endif
+
+ for ( mtype = 0 ; mtype < 8 ; mtype++ ) {
+ normal_func func = _mesa_normal_tab[norm_types[mtype]];
+ long *cycles = &benchmark_tab[mtype];
+
+ if ( test_norm_function( func, mtype, cycles ) == 0 ) {
+ char buf[100];
+ _mesa_sprintf( buf, "_mesa_normal_tab[0][%s] failed test (%s)",
+ norm_strings[mtype], description );
+ _mesa_problem( NULL, buf );
+ }
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ _mesa_printf( " %li\t", benchmark_tab[mtype] );
+ _mesa_printf( " | [%s]\n", norm_strings[mtype] );
+ }
+#endif
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ _mesa_printf( "\n" );
+ }
+#endif
+}
+
+
+#endif /* DEBUG_MATH */
diff --git a/mesalib/src/mesa/math/m_debug_util.h b/mesalib/src/mesa/math/m_debug_util.h
new file mode 100644
index 000000000..2e67db8e5
--- /dev/null
+++ b/mesalib/src/mesa/math/m_debug_util.h
@@ -0,0 +1,320 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes
+ */
+
+#ifndef __M_DEBUG_UTIL_H__
+#define __M_DEBUG_UTIL_H__
+
+
+#ifdef DEBUG_MATH /* This code only used for debugging */
+
+
+/* Comment this out to deactivate the cycle counter.
+ * NOTE: it works only on CPUs which know the 'rdtsc' command (586 or higher)
+ * (hope, you don't try to debug Mesa on a 386 ;)
+ */
+#if defined(__GNUC__) && \
+ ((defined(__i386__) && defined(USE_X86_ASM)) || \
+ (defined(__sparc__) && defined(USE_SPARC_ASM)))
+#define RUN_DEBUG_BENCHMARK
+#endif
+
+#define TEST_COUNT 128 /* size of the tested vector array */
+
+#define REQUIRED_PRECISION 10 /* allow 4 bits to miss */
+#define MAX_PRECISION 24 /* max. precision possible */
+
+
+#ifdef RUN_DEBUG_BENCHMARK
+/* Overhead of profiling counter in cycles. Automatically adjusted to
+ * your machine at run time - counter initialization should give very
+ * consistent results.
+ */
+extern long counter_overhead;
+
+/* This is the value of the environment variable MESA_PROFILE, and is
+ * used to determine if we should benchmark the functions as well as
+ * verify their correctness.
+ */
+extern char *mesa_profile;
+
+/* Modify the the number of tests if you like.
+ * We take the minimum of all results, because every error should be
+ * positive (time used by other processes, task switches etc).
+ * It is assumed that all calculations are done in the cache.
+ */
+
+#if defined(__i386__)
+
+#if 1 /* PPro, PII, PIII version */
+
+/* Profiling on the P6 architecture requires a little more work, due to
+ * the internal out-of-order execution. We must perform a serializing
+ * 'cpuid' instruction before and after the 'rdtsc' instructions to make
+ * sure no other uops are executed when we sample the timestamp counter.
+ */
+#define INIT_COUNTER() \
+ do { \
+ int cycle_i; \
+ counter_overhead = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 8 ; cycle_i++ ) { \
+ long cycle_tmp1 = 0, cycle_tmp2 = 0; \
+ __asm__ __volatile__ ( "push %%ebx \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "rdtsc \n" \
+ "mov %%eax, %0 \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "pop %%ebx \n" \
+ "push %%ebx \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "rdtsc \n" \
+ "mov %%eax, %1 \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "pop %%ebx \n" \
+ : "=m" (cycle_tmp1), "=m" (cycle_tmp2) \
+ : : "eax", "ecx", "edx" ); \
+ if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \
+ counter_overhead = cycle_tmp2 - cycle_tmp1; \
+ } \
+ } \
+ } while (0)
+
+#define BEGIN_RACE(x) \
+ x = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \
+ long cycle_tmp1 = 0, cycle_tmp2 = 0; \
+ __asm__ __volatile__ ( "push %%ebx \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "rdtsc \n" \
+ "mov %%eax, %0 \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "pop %%ebx \n" \
+ : "=m" (cycle_tmp1) \
+ : : "eax", "ecx", "edx" );
+
+#define END_RACE(x) \
+ __asm__ __volatile__ ( "push %%ebx \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "rdtsc \n" \
+ "mov %%eax, %0 \n" \
+ "xor %%eax, %%eax \n" \
+ "cpuid \n" \
+ "pop %%ebx \n" \
+ : "=m" (cycle_tmp2) \
+ : : "eax", "ecx", "edx" ); \
+ if ( x > (cycle_tmp2 - cycle_tmp1) ) { \
+ x = cycle_tmp2 - cycle_tmp1; \
+ } \
+ } \
+ x -= counter_overhead;
+
+#else /* PPlain, PMMX version */
+
+/* To ensure accurate results, we stall the pipelines with the
+ * non-pairable 'cdq' instruction. This ensures all the code being
+ * profiled is complete when the 'rdtsc' instruction executes.
+ */
+#define INIT_COUNTER(x) \
+ do { \
+ int cycle_i; \
+ x = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 32 ; cycle_i++ ) { \
+ long cycle_tmp1, cycle_tmp2, dummy; \
+ __asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \
+ __asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \
+ if ( x > (cycle_tmp2 - cycle_tmp1) ) \
+ x = cycle_tmp2 - cycle_tmp1; \
+ } \
+ } while (0)
+
+#define BEGIN_RACE(x) \
+ x = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \
+ long cycle_tmp1, cycle_tmp2, dummy; \
+ __asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \
+ __asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) );
+
+
+#define END_RACE(x) \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "cdq" ); \
+ __asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \
+ if ( x > (cycle_tmp2 - cycle_tmp1) ) \
+ x = cycle_tmp2 - cycle_tmp1; \
+ } \
+ x -= counter_overhead;
+
+#endif
+
+#elif defined(__x86_64__)
+
+#define rdtscll(val) do { \
+ unsigned int a,d; \
+ __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); \
+ (val) = ((unsigned long)a) | (((unsigned long)d)<<32); \
+} while(0)
+
+/* Copied from i386 PIII version */
+#define INIT_COUNTER() \
+ do { \
+ int cycle_i; \
+ counter_overhead = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \
+ unsigned long cycle_tmp1, cycle_tmp2; \
+ rdtscll(cycle_tmp1); \
+ rdtscll(cycle_tmp2); \
+ if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \
+ counter_overhead = cycle_tmp2 - cycle_tmp1; \
+ } \
+ } \
+ } while (0)
+
+
+#define BEGIN_RACE(x) \
+ x = LONG_MAX; \
+ for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \
+ unsigned long cycle_tmp1, cycle_tmp2; \
+ rdtscll(cycle_tmp1); \
+
+#define END_RACE(x) \
+ rdtscll(cycle_tmp2); \
+ if ( x > (cycle_tmp2 - cycle_tmp1) ) { \
+ x = cycle_tmp2 - cycle_tmp1; \
+ } \
+ } \
+ x -= counter_overhead;
+
+#elif defined(__sparc__)
+
+#define INIT_COUNTER() \
+ do { counter_overhead = 5; } while(0)
+
+#define BEGIN_RACE(x) \
+x = LONG_MAX; \
+for (cycle_i = 0; cycle_i <10; cycle_i++) { \
+ register long cycle_tmp1 __asm__("l0"); \
+ register long cycle_tmp2 __asm__("l1"); \
+ /* rd %tick, %l0 */ \
+ __asm__ __volatile__ (".word 0xa1410000" : "=r" (cycle_tmp1)); /* save timestamp */
+
+#define END_RACE(x) \
+ /* rd %tick, %l1 */ \
+ __asm__ __volatile__ (".word 0xa3410000" : "=r" (cycle_tmp2)); \
+ if (x > (cycle_tmp2-cycle_tmp1)) x = cycle_tmp2 - cycle_tmp1; \
+} \
+x -= counter_overhead;
+
+#else
+#error Your processor is not supported for RUN_XFORM_BENCHMARK
+#endif
+
+#else
+
+#define BEGIN_RACE(x)
+#define END_RACE(x)
+
+#endif
+
+
+/* =============================================================
+ * Helper functions
+ */
+
+static GLfloat rnd( void )
+{
+ GLfloat f = (GLfloat)rand() / (GLfloat)RAND_MAX;
+ GLfloat gran = (GLfloat)(1 << 13);
+
+ f = (GLfloat)(GLint)(f * gran) / gran;
+
+ return f * 2.0 - 1.0;
+}
+
+static int significand_match( GLfloat a, GLfloat b )
+{
+ GLfloat d = a - b;
+ int a_ex, b_ex, d_ex;
+
+ if ( d == 0.0F ) {
+ return MAX_PRECISION; /* Exact match */
+ }
+
+ if ( a == 0.0F || b == 0.0F ) {
+ /* It would probably be better to check if the
+ * non-zero number is denormalized and return
+ * the index of the highest set bit here.
+ */
+ return 0;
+ }
+
+ FREXPF( a, &a_ex );
+ FREXPF( b, &b_ex );
+ FREXPF( d, &d_ex );
+
+ if ( a_ex < b_ex ) {
+ return a_ex - d_ex;
+ } else {
+ return b_ex - d_ex;
+ }
+}
+
+enum { NIL = 0, ONE = 1, NEG = -1, VAR = 2 };
+
+/* Ensure our arrays are correctly aligned.
+ */
+#if defined(__GNUC__)
+# define ALIGN16(type, array) type array __attribute__ ((aligned (16)))
+#elif defined(_MSC_VER)
+# define ALIGN16(type, array) type array __declspec(align(16)) /* GH: Does this work? */
+#elif defined(__WATCOMC__)
+# define ALIGN16(type, array) /* Watcom does not support this */
+#elif defined(__xlC__)
+# define ALIGN16(type, array) type __align (16) array
+#else
+# warning "ALIGN16 will not 16-byte align!\n"
+# define ALIGN16
+#endif
+
+
+#endif /* DEBUG_MATH */
+
+#endif /* __M_DEBUG_UTIL_H__ */
diff --git a/mesalib/src/mesa/math/m_debug_xform.c b/mesalib/src/mesa/math/m_debug_xform.c
new file mode 100644
index 000000000..df8cc066b
--- /dev/null
+++ b/mesalib/src/mesa/math/m_debug_xform.c
@@ -0,0 +1,339 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/*
+ * Updated for P6 architecture by Gareth Hughes.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+
+#include "m_matrix.h"
+#include "m_xform.h"
+
+#include "m_debug.h"
+#include "m_debug_util.h"
+
+#ifdef __UNIXOS2__
+/* The linker doesn't like empty files */
+static char dummy;
+#endif
+
+#ifdef DEBUG_MATH /* This code only used for debugging */
+
+
+/* Overhead of profiling counter in cycles. Automatically adjusted to
+ * your machine at run time - counter initialization should give very
+ * consistent results.
+ */
+long counter_overhead = 0;
+
+/* This is the value of the environment variable MESA_PROFILE, and is
+ * used to determine if we should benchmark the functions as well as
+ * verify their correctness.
+ */
+char *mesa_profile = NULL;
+
+
+static int m_general[16] = {
+ VAR, VAR, VAR, VAR,
+ VAR, VAR, VAR, VAR,
+ VAR, VAR, VAR, VAR,
+ VAR, VAR, VAR, VAR
+};
+static int m_identity[16] = {
+ ONE, NIL, NIL, NIL,
+ NIL, ONE, NIL, NIL,
+ NIL, NIL, ONE, NIL,
+ NIL, NIL, NIL, ONE
+};
+static int m_2d[16] = {
+ VAR, VAR, NIL, VAR,
+ VAR, VAR, NIL, VAR,
+ NIL, NIL, ONE, NIL,
+ NIL, NIL, NIL, ONE
+};
+static int m_2d_no_rot[16] = {
+ VAR, NIL, NIL, VAR,
+ NIL, VAR, NIL, VAR,
+ NIL, NIL, ONE, NIL,
+ NIL, NIL, NIL, ONE
+};
+static int m_3d[16] = {
+ VAR, VAR, VAR, VAR,
+ VAR, VAR, VAR, VAR,
+ VAR, VAR, VAR, VAR,
+ NIL, NIL, NIL, ONE
+};
+static int m_3d_no_rot[16] = {
+ VAR, NIL, NIL, VAR,
+ NIL, VAR, NIL, VAR,
+ NIL, NIL, VAR, VAR,
+ NIL, NIL, NIL, ONE
+};
+static int m_perspective[16] = {
+ VAR, NIL, VAR, NIL,
+ NIL, VAR, VAR, NIL,
+ NIL, NIL, VAR, VAR,
+ NIL, NIL, NEG, NIL
+};
+static int *templates[7] = {
+ m_general,
+ m_identity,
+ m_3d_no_rot,
+ m_perspective,
+ m_2d,
+ m_2d_no_rot,
+ m_3d
+};
+static enum GLmatrixtype mtypes[7] = {
+ MATRIX_GENERAL,
+ MATRIX_IDENTITY,
+ MATRIX_3D_NO_ROT,
+ MATRIX_PERSPECTIVE,
+ MATRIX_2D,
+ MATRIX_2D_NO_ROT,
+ MATRIX_3D
+};
+static char *mstrings[7] = {
+ "MATRIX_GENERAL",
+ "MATRIX_IDENTITY",
+ "MATRIX_3D_NO_ROT",
+ "MATRIX_PERSPECTIVE",
+ "MATRIX_2D",
+ "MATRIX_2D_NO_ROT",
+ "MATRIX_3D"
+};
+
+
+/* =============================================================
+ * Reference transformations
+ */
+
+static void ref_transform( GLvector4f *dst,
+ const GLmatrix *mat,
+ const GLvector4f *src )
+{
+ GLuint i;
+ GLfloat *s = (GLfloat *)src->start;
+ GLfloat (*d)[4] = (GLfloat (*)[4])dst->start;
+ const GLfloat *m = mat->m;
+
+ for ( i = 0 ; i < src->count ; i++ ) {
+ TRANSFORM_POINT( d[i], m, s );
+ s = (GLfloat *)((char *)s + src->stride);
+ }
+}
+
+
+/* =============================================================
+ * Vertex transformation tests
+ */
+
+static void init_matrix( GLfloat *m )
+{
+ m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
+ m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0;
+ m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0;
+ m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0;
+}
+
+ALIGN16(static GLfloat, s[TEST_COUNT][4]);
+ALIGN16(static GLfloat, d[TEST_COUNT][4]);
+ALIGN16(static GLfloat, r[TEST_COUNT][4]);
+
+static int test_transform_function( transform_func func, int psize,
+ int mtype, unsigned long *cycles )
+{
+ GLvector4f source[1], dest[1], ref[1];
+ GLmatrix mat[1];
+ GLfloat *m;
+ int i, j;
+#ifdef RUN_DEBUG_BENCHMARK
+ int cycle_i; /* the counter for the benchmarks we run */
+#endif
+
+ (void) cycles;
+
+ if ( psize > 4 ) {
+ _mesa_problem( NULL, "test_transform_function called with psize > 4\n" );
+ return 0;
+ }
+
+ mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+ mat->type = mtypes[mtype];
+
+ m = mat->m;
+ ASSERT( ((long)m & 15) == 0 );
+
+ init_matrix( m );
+
+ for ( i = 0 ; i < 4 ; i++ ) {
+ for ( j = 0 ; j < 4 ; j++ ) {
+ switch ( templates[mtype][i * 4 + j] ) {
+ case NIL:
+ m[j * 4 + i] = 0.0;
+ break;
+ case ONE:
+ m[j * 4 + i] = 1.0;
+ break;
+ case NEG:
+ m[j * 4 + i] = -1.0;
+ break;
+ case VAR:
+ break;
+ default:
+ ASSERT(0);
+ return 0;
+ }
+ }
+ }
+
+ for ( i = 0 ; i < TEST_COUNT ; i++) {
+ ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 );
+ for ( j = 0 ; j < psize ; j++ )
+ s[i][j] = rnd();
+ }
+
+ source->data = (GLfloat(*)[4])s;
+ source->start = (GLfloat *)s;
+ source->count = TEST_COUNT;
+ source->stride = sizeof(s[0]);
+ source->size = 4;
+ source->flags = 0;
+
+ dest->data = (GLfloat(*)[4])d;
+ dest->start = (GLfloat *)d;
+ dest->count = TEST_COUNT;
+ dest->stride = sizeof(float[4]);
+ dest->size = 0;
+ dest->flags = 0;
+
+ ref->data = (GLfloat(*)[4])r;
+ ref->start = (GLfloat *)r;
+ ref->count = TEST_COUNT;
+ ref->stride = sizeof(float[4]);
+ ref->size = 0;
+ ref->flags = 0;
+
+ ref_transform( ref, mat, source );
+
+ if ( mesa_profile ) {
+ BEGIN_RACE( *cycles );
+ func( dest, mat->m, source );
+ END_RACE( *cycles );
+ }
+ else {
+ func( dest, mat->m, source );
+ }
+
+ for ( i = 0 ; i < TEST_COUNT ; i++ ) {
+ for ( j = 0 ; j < 4 ; j++ ) {
+ if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
+ _mesa_printf("-----------------------------\n" );
+ _mesa_printf("(i = %i, j = %i)\n", i, j );
+ _mesa_printf("%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][0], r[i][0], r[i][0]-d[i][0],
+ MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
+ _mesa_printf("%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][1], r[i][1], r[i][1]-d[i][1],
+ MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
+ _mesa_printf("%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][2], r[i][2], r[i][2]-d[i][2],
+ MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
+ _mesa_printf("%f \t %f \t [diff = %e - %i bit missed]\n",
+ d[i][3], r[i][3], r[i][3]-d[i][3],
+ MAX_PRECISION - significand_match( d[i][3], r[i][3] ) );
+ return 0;
+ }
+ }
+ }
+
+ ALIGN_FREE( mat->m );
+ return 1;
+}
+
+void _math_test_all_transform_functions( char *description )
+{
+ int psize, mtype;
+ unsigned long benchmark_tab[4][7];
+ static int first_time = 1;
+
+ if ( first_time ) {
+ first_time = 0;
+ mesa_profile = _mesa_getenv( "MESA_PROFILE" );
+ }
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ if ( !counter_overhead ) {
+ INIT_COUNTER();
+ _mesa_printf("counter overhead: %lu cycles\n\n", counter_overhead );
+ }
+ _mesa_printf("transform results after hooking in %s functions:\n", description );
+ }
+#endif
+
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile ) {
+ _mesa_printf("\n" );
+ for ( psize = 1 ; psize <= 4 ; psize++ ) {
+ _mesa_printf(" p%d\t", psize );
+ }
+ _mesa_printf("\n--------------------------------------------------------\n" );
+ }
+#endif
+
+ for ( mtype = 0 ; mtype < 7 ; mtype++ ) {
+ for ( psize = 1 ; psize <= 4 ; psize++ ) {
+ transform_func func = _mesa_transform_tab[psize][mtypes[mtype]];
+ unsigned long *cycles = &(benchmark_tab[psize-1][mtype]);
+
+ if ( test_transform_function( func, psize, mtype, cycles ) == 0 ) {
+ char buf[100];
+ _mesa_sprintf(buf, "_mesa_transform_tab[0][%d][%s] failed test (%s)",
+ psize, mstrings[mtype], description );
+ _mesa_problem( NULL, buf );
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf(" %li\t", benchmark_tab[psize-1][mtype] );
+#endif
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf(" | [%s]\n", mstrings[mtype] );
+#endif
+ }
+#ifdef RUN_DEBUG_BENCHMARK
+ if ( mesa_profile )
+ _mesa_printf( "\n" );
+#endif
+}
+
+
+#endif /* DEBUG_MATH */
diff --git a/mesalib/src/mesa/math/m_dotprod_tmp.h b/mesalib/src/mesa/math/m_dotprod_tmp.h
new file mode 100644
index 000000000..03e65af6c
--- /dev/null
+++ b/mesalib/src/mesa/math/m_dotprod_tmp.h
@@ -0,0 +1,102 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+/* Note - respects the stride of the output vector.
+ */
+static void TAG(dotprod_vec2)( GLfloat *out,
+ GLuint outstride,
+ const GLvector4f *coord_vec,
+ const GLfloat plane[4] )
+{
+ GLuint stride = coord_vec->stride;
+ GLfloat *coord = coord_vec->start;
+ GLuint count = coord_vec->count;
+
+ GLuint i;
+
+ const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3];
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
+ *out = (coord[0] * plane0 +
+ coord[1] * plane1 +
+ plane3);
+ }
+}
+
+static void TAG(dotprod_vec3)( GLfloat *out,
+ GLuint outstride,
+ const GLvector4f *coord_vec,
+ const GLfloat plane[4] )
+{
+ GLuint stride = coord_vec->stride;
+ GLfloat *coord = coord_vec->start;
+ GLuint count = coord_vec->count;
+
+ GLuint i;
+
+ const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
+ const GLfloat plane3 = plane[3];
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
+ *out = (coord[0] * plane0 +
+ coord[1] * plane1 +
+ coord[2] * plane2 +
+ plane3);
+ }
+}
+
+static void TAG(dotprod_vec4)( GLfloat *out,
+ GLuint outstride,
+ const GLvector4f *coord_vec,
+ const GLfloat plane[4] )
+{
+ GLuint stride = coord_vec->stride;
+ GLfloat *coord = coord_vec->start;
+ GLuint count = coord_vec->count;
+ GLuint i;
+
+ const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
+ const GLfloat plane3 = plane[3];
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
+ *out = (coord[0] * plane0 +
+ coord[1] * plane1 +
+ coord[2] * plane2 +
+ coord[3] * plane3);
+ }
+}
+
+
+static void TAG(init_dotprod)( void )
+{
+ _mesa_dotprod_tab[2] = TAG(dotprod_vec2);
+ _mesa_dotprod_tab[3] = TAG(dotprod_vec3);
+ _mesa_dotprod_tab[4] = TAG(dotprod_vec4);
+}
diff --git a/mesalib/src/mesa/math/m_eval.c b/mesalib/src/mesa/math/m_eval.c
new file mode 100644
index 000000000..d324673c5
--- /dev/null
+++ b/mesalib/src/mesa/math/m_eval.c
@@ -0,0 +1,461 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * 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!
+ */
+
+
+#include "main/glheader.h"
+#include "main/config.h"
+#include "m_eval.h"
+
+static GLfloat inv_tab[MAX_EVAL_ORDER];
+
+
+
+/*
+ * 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
+ */
+
+
+void
+_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t,
+ GLuint dim, GLuint order)
+{
+ GLfloat s, powert, bincoeff;
+ GLuint i, k;
+
+ if (order >= 2) {
+ bincoeff = (GLfloat) (order - 1);
+ s = 1.0F - 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 *= (GLfloat) (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.
+ */
+
+void
+_math_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, bincoeff;
+ GLuint j, k;
+
+ /* 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 = (GLfloat) (uorder - 1);
+ s = 1.0F - 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 *= (GLfloat) (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 */
+ _math_horner_bezier_curve(cp, out, v, dim, vorder);
+ }
+ else /* uorder=1 -> cn defines a curve in v */
+ _math_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 */
+
+ _math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder);
+ }
+
+ /* Evaluate curve point in u */
+ _math_horner_bezier_curve(cp, out, u, dim, uorder);
+ }
+ else /* vorder=1 -> cn defines a curve in u */
+ _math_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.
+ */
+
+void
+_math_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.0F - u, vs = 1.0F - 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
+}
+
+
+/*
+ * Do one-time initialization for evaluators.
+ */
+void
+_math_init_eval(void)
+{
+ GLuint i;
+
+ /* KW: precompute 1/x for useful x.
+ */
+ for (i = 1; i < MAX_EVAL_ORDER; i++)
+ inv_tab[i] = 1.0F / i;
+}
diff --git a/mesalib/src/mesa/math/m_eval.h b/mesalib/src/mesa/math/m_eval.h
new file mode 100644
index 000000000..d73ecaafb
--- /dev/null
+++ b/mesalib/src/mesa/math/m_eval.h
@@ -0,0 +1,103 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _M_EVAL_H
+#define _M_EVAL_H
+
+#include "main/glheader.h"
+
+void _math_init_eval( void );
+
+
+/*
+ * 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
+ */
+
+
+void
+_math_horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t,
+ GLuint dim, GLuint order);
+
+
+/*
+ * 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.
+ */
+
+void
+_math_horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v,
+ GLuint dim, GLuint uorder, GLuint vorder);
+
+
+/*
+ * 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.
+ */
+
+void
+_math_de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv,
+ GLfloat u, GLfloat v, GLuint dim,
+ GLuint uorder, GLuint vorder);
+
+
+#endif
diff --git a/mesalib/src/mesa/math/m_matrix.c b/mesalib/src/mesa/math/m_matrix.c
new file mode 100644
index 000000000..da6956efe
--- /dev/null
+++ b/mesalib/src/mesa/math/m_matrix.c
@@ -0,0 +1,1642 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+
+/**
+ * \file m_matrix.c
+ * Matrix operations.
+ *
+ * \note
+ * -# 4x4 transformation matrices are stored in memory in column major order.
+ * -# Points/vertices are to be thought of as column vectors.
+ * -# Transformation of a point p by a matrix M is: p' = M * p
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/imports.h"
+
+#include "m_matrix.h"
+
+
+/**
+ * \defgroup MatFlags MAT_FLAG_XXX-flags
+ *
+ * Bitmasks to indicate different kinds of 4x4 matrices in GLmatrix::flags
+ * It would be nice to make all these flags private to m_matrix.c
+ */
+/*@{*/
+#define MAT_FLAG_IDENTITY 0 /**< is an identity matrix flag.
+ * (Not actually used - the identity
+ * matrix is identified by the absense
+ * of all other flags.)
+ */
+#define MAT_FLAG_GENERAL 0x1 /**< is a general matrix flag */
+#define MAT_FLAG_ROTATION 0x2 /**< is a rotation matrix flag */
+#define MAT_FLAG_TRANSLATION 0x4 /**< is a translation matrix flag */
+#define MAT_FLAG_UNIFORM_SCALE 0x8 /**< is an uniform scaling matrix flag */
+#define MAT_FLAG_GENERAL_SCALE 0x10 /**< is a general scaling matrix flag */
+#define MAT_FLAG_GENERAL_3D 0x20 /**< general 3D matrix flag */
+#define MAT_FLAG_PERSPECTIVE 0x40 /**< is a perspective proj matrix flag */
+#define MAT_FLAG_SINGULAR 0x80 /**< is a singular matrix flag */
+#define MAT_DIRTY_TYPE 0x100 /**< matrix type is dirty */
+#define MAT_DIRTY_FLAGS 0x200 /**< matrix flags are dirty */
+#define MAT_DIRTY_INVERSE 0x400 /**< matrix inverse is dirty */
+
+/** angle preserving matrix flags mask */
+#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \
+ MAT_FLAG_TRANSLATION | \
+ MAT_FLAG_UNIFORM_SCALE)
+
+/** geometry related matrix flags mask */
+#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \
+ MAT_FLAG_ROTATION | \
+ MAT_FLAG_TRANSLATION | \
+ MAT_FLAG_UNIFORM_SCALE | \
+ MAT_FLAG_GENERAL_SCALE | \
+ MAT_FLAG_GENERAL_3D | \
+ MAT_FLAG_PERSPECTIVE | \
+ MAT_FLAG_SINGULAR)
+
+/** length preserving matrix flags mask */
+#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \
+ MAT_FLAG_TRANSLATION)
+
+
+/** 3D (non-perspective) matrix flags mask */
+#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \
+ MAT_FLAG_TRANSLATION | \
+ MAT_FLAG_UNIFORM_SCALE | \
+ MAT_FLAG_GENERAL_SCALE | \
+ MAT_FLAG_GENERAL_3D)
+
+/** dirty matrix flags mask */
+#define MAT_DIRTY (MAT_DIRTY_TYPE | \
+ MAT_DIRTY_FLAGS | \
+ MAT_DIRTY_INVERSE)
+
+/*@}*/
+
+
+/**
+ * Test geometry related matrix flags.
+ *
+ * \param mat a pointer to a GLmatrix structure.
+ * \param a flags mask.
+ *
+ * \returns non-zero if all geometry related matrix flags are contained within
+ * the mask, or zero otherwise.
+ */
+#define TEST_MAT_FLAGS(mat, a) \
+ ((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0)
+
+
+
+/**
+ * Names of the corresponding GLmatrixtype values.
+ */
+static const char *types[] = {
+ "MATRIX_GENERAL",
+ "MATRIX_IDENTITY",
+ "MATRIX_3D_NO_ROT",
+ "MATRIX_PERSPECTIVE",
+ "MATRIX_2D",
+ "MATRIX_2D_NO_ROT",
+ "MATRIX_3D"
+};
+
+
+/**
+ * Identity matrix.
+ */
+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
+};
+
+
+
+/**********************************************************************/
+/** \name Matrix multiplication */
+/*@{*/
+
+#define A(row,col) a[(col<<2)+row]
+#define B(row,col) b[(col<<2)+row]
+#define P(row,col) product[(col<<2)+row]
+
+/**
+ * Perform a full 4x4 matrix multiplication.
+ *
+ * \param a matrix.
+ * \param b matrix.
+ * \param product will receive the product of \p a and \p b.
+ *
+ * \warning Is assumed that \p product != \p b. \p product == \p a is allowed.
+ *
+ * \note KW: 4*16 = 64 multiplications
+ *
+ * \author This \c matmul was contributed by Thomas Malik
+ */
+static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
+{
+ GLint i;
+ for (i = 0; i < 4; i++) {
+ const 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 model matrices, and orthogonal matrices.
+ *
+ * \param a matrix.
+ * \param b matrix.
+ * \param product will receive the product of \p a and \p b.
+ */
+static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
+{
+ GLint i;
+ for (i = 0; i < 3; i++) {
+ const 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;
+}
+
+#undef A
+#undef B
+#undef P
+
+/**
+ * Multiply a matrix by an array of floats with known properties.
+ *
+ * \param mat pointer to a GLmatrix structure containing the left multiplication
+ * matrix, and that will receive the product result.
+ * \param m right multiplication matrix array.
+ * \param flags flags of the matrix \p m.
+ *
+ * Joins both flags and marks the type and inverse as dirty. Calls matmul34()
+ * if both matrices are 3D, or matmul4() otherwise.
+ */
+static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags )
+{
+ mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
+
+ if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
+ matmul34( mat->m, mat->m, m );
+ else
+ matmul4( mat->m, mat->m, m );
+}
+
+/**
+ * Matrix multiplication.
+ *
+ * \param dest destination matrix.
+ * \param a left matrix.
+ * \param b right matrix.
+ *
+ * Joins both flags and marks the type and inverse as dirty. Calls matmul34()
+ * if both matrices are 3D, or matmul4() otherwise.
+ */
+void
+_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
+{
+ dest->flags = (a->flags |
+ b->flags |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE);
+
+ if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
+ matmul34( dest->m, a->m, b->m );
+ else
+ matmul4( dest->m, a->m, b->m );
+}
+
+/**
+ * Matrix multiplication.
+ *
+ * \param dest left and destination matrix.
+ * \param m right matrix array.
+ *
+ * Marks the matrix flags with general flag, and type and inverse dirty flags.
+ * Calls matmul4() for the multiplication.
+ */
+void
+_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m )
+{
+ dest->flags |= (MAT_FLAG_GENERAL |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_FLAGS);
+
+ matmul4( dest->m, dest->m, m );
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Matrix output */
+/*@{*/
+
+/**
+ * Print a matrix array.
+ *
+ * \param m matrix array.
+ *
+ * Called by _math_matrix_print() to print a matrix or its inverse.
+ */
+static void print_matrix_floats( const GLfloat m[16] )
+{
+ int i;
+ for (i=0;i<4;i++) {
+ _mesa_debug(NULL,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
+ }
+}
+
+/**
+ * Dumps the contents of a GLmatrix structure.
+ *
+ * \param m pointer to the GLmatrix structure.
+ */
+void
+_math_matrix_print( const GLmatrix *m )
+{
+ _mesa_debug(NULL, "Matrix type: %s, flags: %x\n", types[m->type], m->flags);
+ print_matrix_floats(m->m);
+ _mesa_debug(NULL, "Inverse: \n");
+ if (m->inv) {
+ GLfloat prod[16];
+ print_matrix_floats(m->inv);
+ matmul4(prod, m->m, m->inv);
+ _mesa_debug(NULL, "Mat * Inverse:\n");
+ print_matrix_floats(prod);
+ }
+ else {
+ _mesa_debug(NULL, " - not available\n");
+ }
+}
+
+/*@}*/
+
+
+/**
+ * References an element of 4x4 matrix.
+ *
+ * \param m matrix array.
+ * \param c column of the desired element.
+ * \param r row of the desired element.
+ *
+ * \return value of the desired element.
+ *
+ * Calculate the linear storage index of the element and references it.
+ */
+#define MAT(m,r,c) (m)[(c)*4+(r)]
+
+
+/**********************************************************************/
+/** \name Matrix inversion */
+/*@{*/
+
+/**
+ * Swaps the values of two floating pointer variables.
+ *
+ * Used by invert_matrix_general() to swap the row pointers.
+ */
+#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; }
+
+/**
+ * Compute inverse of 4x4 transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * \author
+ * Code contributed by Jacques Leroy jle@star.be
+ *
+ * Calculates the inverse matrix by performing the gaussian matrix reduction
+ * with partial pivoting followed by back/substitution with the loops manually
+ * unrolled.
+ */
+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 (FABSF(r3[0])>FABSF(r2[0])) SWAP_ROWS(r3, r2);
+ if (FABSF(r2[0])>FABSF(r1[0])) SWAP_ROWS(r2, r1);
+ if (FABSF(r1[0])>FABSF(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 (FABSF(r3[1])>FABSF(r2[1])) SWAP_ROWS(r3, r2);
+ if (FABSF(r2[1])>FABSF(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 (FABSF(r3[2])>FABSF(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.0F/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.0F/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.0F/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.0F/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
+
+/**
+ * Compute inverse of a general 3d transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * \author Adapted from graphics gems II.
+ *
+ * Calculates the inverse of the upper left by first calculating its
+ * determinant and multiplying it to the symmetric adjust matrix of each
+ * element. Finally deals with the translation part by transforming the
+ * original translation vector using by the calculated submatrix inverse.
+ */
+static 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.0F / 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;
+}
+
+/**
+ * Compute inverse of a 3d transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * If the matrix is not an angle preserving matrix then calls
+ * invert_matrix_3d_general for the actual calculation. Otherwise calculates
+ * the inverse matrix analyzing and inverting each of the scaling, rotation and
+ * translation parts.
+ */
+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.0F / 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;
+}
+
+/**
+ * Compute inverse of an identity transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return always GL_TRUE.
+ *
+ * Simply copies Identity into GLmatrix::inv.
+ */
+static GLboolean invert_matrix_identity( GLmatrix *mat )
+{
+ MEMCPY( mat->inv, Identity, sizeof(Identity) );
+ return GL_TRUE;
+}
+
+/**
+ * Compute inverse of a no-rotation 3d transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * Calculates the
+ */
+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.0F / MAT(in,0,0);
+ MAT(out,1,1) = 1.0F / MAT(in,1,1);
+ MAT(out,2,2) = 1.0F / 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;
+}
+
+/**
+ * Compute inverse of a no-rotation 2d transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * Calculates the inverse matrix by applying the inverse scaling and
+ * translation to the identity matrix.
+ */
+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.0F / MAT(in,0,0);
+ MAT(out,1,1) = 1.0F / 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;
+}
+
+#if 0
+/* broken */
+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.0F / MAT(in,0,0);
+ MAT(out,1,1) = 1.0F / 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.0F / MAT(in,2,3);
+ MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2);
+
+ return GL_TRUE;
+}
+#endif
+
+/**
+ * Matrix inversion function pointer type.
+ */
+typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
+
+/**
+ * Table of the matrix inversion functions according to the matrix type.
+ */
+static inv_mat_func inv_mat_tab[7] = {
+ invert_matrix_general,
+ invert_matrix_identity,
+ invert_matrix_3d_no_rot,
+#if 0
+ /* Don't use this function for now - it fails when the projection matrix
+ * is premultiplied by a translation (ala Chromium's tilesort SPU).
+ */
+ invert_matrix_perspective,
+#else
+ invert_matrix_general,
+#endif
+ invert_matrix_3d, /* lazy! */
+ invert_matrix_2d_no_rot,
+ invert_matrix_3d
+};
+
+/**
+ * Compute inverse of a transformation matrix.
+ *
+ * \param mat pointer to a GLmatrix structure. The matrix inverse will be
+ * stored in the GLmatrix::inv attribute.
+ *
+ * \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix).
+ *
+ * Calls the matrix inversion function in inv_mat_tab corresponding to the
+ * given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag,
+ * and copies the identity matrix into GLmatrix::inv.
+ */
+static GLboolean matrix_invert( GLmatrix *mat )
+{
+ if (inv_mat_tab[mat->type](mat)) {
+ mat->flags &= ~MAT_FLAG_SINGULAR;
+ return GL_TRUE;
+ } else {
+ mat->flags |= MAT_FLAG_SINGULAR;
+ MEMCPY( mat->inv, Identity, sizeof(Identity) );
+ return GL_FALSE;
+ }
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Matrix generation */
+/*@{*/
+
+/**
+ * Generate a 4x4 transformation matrix from glRotate parameters, and
+ * post-multiply the input matrix by it.
+ *
+ * \author
+ * This function was contributed by Erich Boleyn (erich@uruk.org).
+ * Optimizations contributed by Rudolf Opalla (rudi@khm.de).
+ */
+void
+_math_matrix_rotate( GLmatrix *mat,
+ GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
+ GLfloat m[16];
+ GLboolean optimized;
+
+ s = (GLfloat) _mesa_sin( angle * DEG2RAD );
+ c = (GLfloat) _mesa_cos( angle * DEG2RAD );
+
+ MEMCPY(m, Identity, sizeof(GLfloat)*16);
+ optimized = GL_FALSE;
+
+#define M(row,col) m[col*4+row]
+
+ if (x == 0.0F) {
+ if (y == 0.0F) {
+ if (z != 0.0F) {
+ optimized = GL_TRUE;
+ /* rotate only around z-axis */
+ M(0,0) = c;
+ M(1,1) = c;
+ if (z < 0.0F) {
+ M(0,1) = s;
+ M(1,0) = -s;
+ }
+ else {
+ M(0,1) = -s;
+ M(1,0) = s;
+ }
+ }
+ }
+ else if (z == 0.0F) {
+ optimized = GL_TRUE;
+ /* rotate only around y-axis */
+ M(0,0) = c;
+ M(2,2) = c;
+ if (y < 0.0F) {
+ M(0,2) = -s;
+ M(2,0) = s;
+ }
+ else {
+ M(0,2) = s;
+ M(2,0) = -s;
+ }
+ }
+ }
+ else if (y == 0.0F) {
+ if (z == 0.0F) {
+ optimized = GL_TRUE;
+ /* rotate only around x-axis */
+ M(1,1) = c;
+ M(2,2) = c;
+ if (x < 0.0F) {
+ M(1,2) = s;
+ M(2,1) = -s;
+ }
+ else {
+ M(1,2) = -s;
+ M(2,1) = s;
+ }
+ }
+ }
+
+ if (!optimized) {
+ const GLfloat mag = SQRTF(x * x + y * y + z * z);
+
+ if (mag <= 1.0e-4) {
+ /* no rotation, leave mat as-is */
+ return;
+ }
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+
+ /*
+ * 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;
+
+ /* We already hold the identity-matrix so we can skip some statements */
+ 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
+
+ matrix_multf( mat, m, MAT_FLAG_ROTATION );
+}
+
+/**
+ * Apply a perspective projection matrix.
+ *
+ * \param mat matrix to apply the projection.
+ * \param left left clipping plane coordinate.
+ * \param right right clipping plane coordinate.
+ * \param bottom bottom clipping plane coordinate.
+ * \param top top clipping plane coordinate.
+ * \param nearval distance to the near clipping plane.
+ * \param farval distance to the far clipping plane.
+ *
+ * Creates the projection matrix and multiplies it with \p mat, marking the
+ * MAT_FLAG_PERSPECTIVE flag.
+ */
+void
+_math_matrix_frustum( GLmatrix *mat,
+ GLfloat left, GLfloat right,
+ GLfloat bottom, GLfloat top,
+ GLfloat nearval, GLfloat farval )
+{
+ GLfloat x, y, a, b, c, d;
+ GLfloat m[16];
+
+ x = (2.0F*nearval) / (right-left);
+ y = (2.0F*nearval) / (top-bottom);
+ a = (right+left) / (right-left);
+ b = (top+bottom) / (top-bottom);
+ c = -(farval+nearval) / ( farval-nearval);
+ d = -(2.0F*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
+
+ matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );
+}
+
+/**
+ * Apply an orthographic projection matrix.
+ *
+ * \param mat matrix to apply the projection.
+ * \param left left clipping plane coordinate.
+ * \param right right clipping plane coordinate.
+ * \param bottom bottom clipping plane coordinate.
+ * \param top top clipping plane coordinate.
+ * \param nearval distance to the near clipping plane.
+ * \param farval distance to the far clipping plane.
+ *
+ * Creates the projection matrix and multiplies it with \p mat, marking the
+ * MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags.
+ */
+void
+_math_matrix_ortho( GLmatrix *mat,
+ GLfloat left, GLfloat right,
+ GLfloat bottom, GLfloat top,
+ GLfloat nearval, GLfloat farval )
+{
+ GLfloat m[16];
+
+#define M(row,col) m[col*4+row]
+ M(0,0) = 2.0F / (right-left);
+ M(0,1) = 0.0F;
+ M(0,2) = 0.0F;
+ M(0,3) = -(right+left) / (right-left);
+
+ M(1,0) = 0.0F;
+ M(1,1) = 2.0F / (top-bottom);
+ M(1,2) = 0.0F;
+ M(1,3) = -(top+bottom) / (top-bottom);
+
+ M(2,0) = 0.0F;
+ M(2,1) = 0.0F;
+ M(2,2) = -2.0F / (farval-nearval);
+ M(2,3) = -(farval+nearval) / (farval-nearval);
+
+ M(3,0) = 0.0F;
+ M(3,1) = 0.0F;
+ M(3,2) = 0.0F;
+ M(3,3) = 1.0F;
+#undef M
+
+ matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
+}
+
+/**
+ * Multiply a matrix with a general scaling matrix.
+ *
+ * \param mat matrix.
+ * \param x x axis scale factor.
+ * \param y y axis scale factor.
+ * \param z z axis scale factor.
+ *
+ * Multiplies in-place the elements of \p mat by the scale factors. Checks if
+ * the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE
+ * flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and
+ * MAT_DIRTY_INVERSE dirty flags.
+ */
+void
+_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLfloat *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 (FABSF(x - y) < 1e-8 && FABSF(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);
+}
+
+/**
+ * Multiply a matrix with a translation matrix.
+ *
+ * \param mat matrix.
+ * \param x translation vector x coordinate.
+ * \param y translation vector y coordinate.
+ * \param z translation vector z coordinate.
+ *
+ * Adds the translation coordinates to the elements of \p mat in-place. Marks
+ * the MAT_FLAG_TRANSLATION flag, and the MAT_DIRTY_TYPE and MAT_DIRTY_INVERSE
+ * dirty flags.
+ */
+void
+_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLfloat *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);
+}
+
+
+/**
+ * Set matrix to do viewport and depthrange mapping.
+ * Transforms Normalized Device Coords to window/Z values.
+ */
+void
+_math_matrix_viewport(GLmatrix *m, GLint x, GLint y, GLint width, GLint height,
+ GLfloat zNear, GLfloat zFar, GLfloat depthMax)
+{
+ m->m[MAT_SX] = (GLfloat) width / 2.0F;
+ m->m[MAT_TX] = m->m[MAT_SX] + x;
+ m->m[MAT_SY] = (GLfloat) height / 2.0F;
+ m->m[MAT_TY] = m->m[MAT_SY] + y;
+ m->m[MAT_SZ] = depthMax * ((zFar - zNear) / 2.0F);
+ m->m[MAT_TZ] = depthMax * ((zFar - zNear) / 2.0F + zNear);
+ m->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION;
+ m->type = MATRIX_3D_NO_ROT;
+}
+
+
+/**
+ * Set a matrix to the identity matrix.
+ *
+ * \param mat matrix.
+ *
+ * Copies ::Identity into \p GLmatrix::m, and into GLmatrix::inv if not NULL.
+ * Sets the matrix type to identity, and clear the dirty flags.
+ */
+void
+_math_matrix_set_identity( GLmatrix *mat )
+{
+ MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) );
+
+ if (mat->inv)
+ MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) );
+
+ mat->type = MATRIX_IDENTITY;
+ mat->flags &= ~(MAT_DIRTY_FLAGS|
+ MAT_DIRTY_TYPE|
+ MAT_DIRTY_INVERSE);
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Matrix analysis */
+/*@{*/
+
+#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.
+ *
+ * \param mat matrix.
+ *
+ * This is expensive enough to only want to do it once.
+ */
+static void analyse_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 == (GLuint) MASK_IDENTITY) {
+ mat->type = MATRIX_IDENTITY;
+ }
+ else if ((mask & MASK_2D_NO_ROT) == (GLuint) 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) == (GLuint) 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) == (GLuint) 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) == (GLuint) 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;
+ }
+}
+
+/**
+ * Analyze a matrix given that its flags are accurate.
+ *
+ * This is the more common operation, hopefully.
+ */
+static void analyse_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;
+ }
+}
+
+/**
+ * Analyze and update a matrix.
+ *
+ * \param mat matrix.
+ *
+ * If the matrix type is dirty then calls either analyse_from_scratch() or
+ * analyse_from_flags() to determine its type, according to whether the flags
+ * are dirty or not, respectively. If the matrix has an inverse and it's dirty
+ * then calls matrix_invert(). Finally clears the dirty flags.
+ */
+void
+_math_matrix_analyse( GLmatrix *mat )
+{
+ if (mat->flags & MAT_DIRTY_TYPE) {
+ if (mat->flags & MAT_DIRTY_FLAGS)
+ analyse_from_scratch( mat );
+ else
+ analyse_from_flags( mat );
+ }
+
+ if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
+ matrix_invert( mat );
+ mat->flags &= ~MAT_DIRTY_INVERSE;
+ }
+
+ mat->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE);
+}
+
+/*@}*/
+
+
+/**
+ * Test if the given matrix preserves vector lengths.
+ */
+GLboolean
+_math_matrix_is_length_preserving( const GLmatrix *m )
+{
+ return TEST_MAT_FLAGS( m, MAT_FLAGS_LENGTH_PRESERVING);
+}
+
+
+/**
+ * Test if the given matrix does any rotation.
+ * (or perhaps if the upper-left 3x3 is non-identity)
+ */
+GLboolean
+_math_matrix_has_rotation( const GLmatrix *m )
+{
+ if (m->flags & (MAT_FLAG_GENERAL |
+ MAT_FLAG_ROTATION |
+ MAT_FLAG_GENERAL_3D |
+ MAT_FLAG_PERSPECTIVE))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+GLboolean
+_math_matrix_is_general_scale( const GLmatrix *m )
+{
+ return (m->flags & MAT_FLAG_GENERAL_SCALE) ? GL_TRUE : GL_FALSE;
+}
+
+
+GLboolean
+_math_matrix_is_dirty( const GLmatrix *m )
+{
+ return (m->flags & MAT_DIRTY) ? GL_TRUE : GL_FALSE;
+}
+
+
+/**********************************************************************/
+/** \name Matrix setup */
+/*@{*/
+
+/**
+ * Copy a matrix.
+ *
+ * \param to destination matrix.
+ * \param from source matrix.
+ *
+ * Copies all fields in GLmatrix, creating an inverse array if necessary.
+ */
+void
+_math_matrix_copy( GLmatrix *to, const GLmatrix *from )
+{
+ MEMCPY( to->m, from->m, sizeof(Identity) );
+ to->flags = from->flags;
+ to->type = from->type;
+
+ if (to->inv != 0) {
+ if (from->inv == 0) {
+ matrix_invert( to );
+ }
+ else {
+ MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
+ }
+ }
+}
+
+/**
+ * Loads a matrix array into GLmatrix.
+ *
+ * \param m matrix array.
+ * \param mat matrix.
+ *
+ * Copies \p m into GLmatrix::m and marks the MAT_FLAG_GENERAL and MAT_DIRTY
+ * flags.
+ */
+void
+_math_matrix_loadf( GLmatrix *mat, const GLfloat *m )
+{
+ MEMCPY( mat->m, m, 16*sizeof(GLfloat) );
+ mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY);
+}
+
+/**
+ * Matrix constructor.
+ *
+ * \param m matrix.
+ *
+ * Initialize the GLmatrix fields.
+ */
+void
+_math_matrix_ctr( GLmatrix *m )
+{
+ m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+ if (m->m)
+ MEMCPY( m->m, Identity, sizeof(Identity) );
+ m->inv = NULL;
+ m->type = MATRIX_IDENTITY;
+ m->flags = 0;
+}
+
+/**
+ * Matrix destructor.
+ *
+ * \param m matrix.
+ *
+ * Frees the data in a GLmatrix.
+ */
+void
+_math_matrix_dtr( GLmatrix *m )
+{
+ if (m->m) {
+ ALIGN_FREE( m->m );
+ m->m = NULL;
+ }
+ if (m->inv) {
+ ALIGN_FREE( m->inv );
+ m->inv = NULL;
+ }
+}
+
+/**
+ * Allocate a matrix inverse.
+ *
+ * \param m matrix.
+ *
+ * Allocates the matrix inverse, GLmatrix::inv, and sets it to Identity.
+ */
+void
+_math_matrix_alloc_inv( GLmatrix *m )
+{
+ if (!m->inv) {
+ m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
+ if (m->inv)
+ MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
+ }
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Matrix transpose */
+/*@{*/
+
+/**
+ * Transpose a GLfloat matrix.
+ *
+ * \param to destination array.
+ * \param from source array.
+ */
+void
+_math_transposef( GLfloat to[16], const GLfloat from[16] )
+{
+ to[0] = from[0];
+ to[1] = from[4];
+ to[2] = from[8];
+ to[3] = from[12];
+ to[4] = from[1];
+ to[5] = from[5];
+ to[6] = from[9];
+ to[7] = from[13];
+ to[8] = from[2];
+ to[9] = from[6];
+ to[10] = from[10];
+ to[11] = from[14];
+ to[12] = from[3];
+ to[13] = from[7];
+ to[14] = from[11];
+ to[15] = from[15];
+}
+
+/**
+ * Transpose a GLdouble matrix.
+ *
+ * \param to destination array.
+ * \param from source array.
+ */
+void
+_math_transposed( GLdouble to[16], const GLdouble from[16] )
+{
+ to[0] = from[0];
+ to[1] = from[4];
+ to[2] = from[8];
+ to[3] = from[12];
+ to[4] = from[1];
+ to[5] = from[5];
+ to[6] = from[9];
+ to[7] = from[13];
+ to[8] = from[2];
+ to[9] = from[6];
+ to[10] = from[10];
+ to[11] = from[14];
+ to[12] = from[3];
+ to[13] = from[7];
+ to[14] = from[11];
+ to[15] = from[15];
+}
+
+/**
+ * Transpose a GLdouble matrix and convert to GLfloat.
+ *
+ * \param to destination array.
+ * \param from source array.
+ */
+void
+_math_transposefd( GLfloat to[16], const GLdouble from[16] )
+{
+ to[0] = (GLfloat) from[0];
+ to[1] = (GLfloat) from[4];
+ to[2] = (GLfloat) from[8];
+ to[3] = (GLfloat) from[12];
+ to[4] = (GLfloat) from[1];
+ to[5] = (GLfloat) from[5];
+ to[6] = (GLfloat) from[9];
+ to[7] = (GLfloat) from[13];
+ to[8] = (GLfloat) from[2];
+ to[9] = (GLfloat) from[6];
+ to[10] = (GLfloat) from[10];
+ to[11] = (GLfloat) from[14];
+ to[12] = (GLfloat) from[3];
+ to[13] = (GLfloat) from[7];
+ to[14] = (GLfloat) from[11];
+ to[15] = (GLfloat) from[15];
+}
+
+/*@}*/
+
+
+/**
+ * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
+ * function is used for transforming clipping plane equations and spotlight
+ * directions.
+ * Mathematically, u = v * m.
+ * Input: v - input vector
+ * m - transformation matrix
+ * Output: u - transformed vector
+ */
+void
+_mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
+{
+ const GLfloat v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
+#define M(row,col) m[row + col*4]
+ u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
+ u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
+ u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
+ u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
+#undef M
+}
diff --git a/mesalib/src/mesa/math/m_matrix.h b/mesalib/src/mesa/math/m_matrix.h
new file mode 100644
index 000000000..3bc5de6cd
--- /dev/null
+++ b/mesalib/src/mesa/math/m_matrix.h
@@ -0,0 +1,210 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+
+/**
+ * \file math/m_matrix.h
+ * Defines basic structures for matrix-handling.
+ */
+
+#ifndef _M_MATRIX_H
+#define _M_MATRIX_H
+
+
+
+/**
+ * \name Symbolic names to some of the entries in the matrix
+ *
+ * These are handy for the viewport mapping, which is expressed as a matrix.
+ */
+/*@{*/
+#define MAT_SX 0
+#define MAT_SY 5
+#define MAT_SZ 10
+#define MAT_TX 12
+#define MAT_TY 13
+#define MAT_TZ 14
+/*@}*/
+
+
+/**
+ * Different kinds of 4x4 transformation matrices.
+ * We use these to select specific optimized vertex transformation routines.
+ */
+enum GLmatrixtype {
+ MATRIX_GENERAL, /**< general 4x4 matrix */
+ MATRIX_IDENTITY, /**< identity matrix */
+ MATRIX_3D_NO_ROT, /**< orthogonal projection and others... */
+ MATRIX_PERSPECTIVE, /**< perspective projection matrix */
+ MATRIX_2D, /**< 2-D transformation */
+ MATRIX_2D_NO_ROT, /**< 2-D scale & translate only */
+ MATRIX_3D /**< 3-D transformation */
+} ;
+
+/**
+ * Matrix type to represent 4x4 transformation matrices.
+ */
+typedef struct {
+ GLfloat *m; /**< 16 matrix elements (16-byte aligned) */
+ GLfloat *inv; /**< optional 16-element inverse (16-byte aligned) */
+ GLuint flags; /**< possible values determined by (of \link
+ * MatFlags MAT_FLAG_* flags\endlink)
+ */
+ enum GLmatrixtype type;
+} GLmatrix;
+
+
+
+
+extern void
+_math_matrix_ctr( GLmatrix *m );
+
+extern void
+_math_matrix_dtr( GLmatrix *m );
+
+extern void
+_math_matrix_alloc_inv( GLmatrix *m );
+
+extern void
+_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b );
+
+extern void
+_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *b );
+
+extern void
+_math_matrix_loadf( GLmatrix *mat, const GLfloat *m );
+
+extern void
+_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z );
+
+extern void
+_math_matrix_rotate( GLmatrix *m, GLfloat angle,
+ GLfloat x, GLfloat y, GLfloat z );
+
+extern void
+_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z );
+
+extern void
+_math_matrix_ortho( GLmatrix *mat,
+ GLfloat left, GLfloat right,
+ GLfloat bottom, GLfloat top,
+ GLfloat nearval, GLfloat farval );
+
+extern void
+_math_matrix_frustum( GLmatrix *mat,
+ GLfloat left, GLfloat right,
+ GLfloat bottom, GLfloat top,
+ GLfloat nearval, GLfloat farval );
+
+extern void
+_math_matrix_viewport(GLmatrix *m, GLint x, GLint y, GLint width, GLint height,
+ GLfloat zNear, GLfloat zFar, GLfloat depthMax);
+
+extern void
+_math_matrix_set_identity( GLmatrix *dest );
+
+extern void
+_math_matrix_copy( GLmatrix *to, const GLmatrix *from );
+
+extern void
+_math_matrix_analyse( GLmatrix *mat );
+
+extern void
+_math_matrix_print( const GLmatrix *m );
+
+extern GLboolean
+_math_matrix_is_length_preserving( const GLmatrix *m );
+
+extern GLboolean
+_math_matrix_has_rotation( const GLmatrix *m );
+
+extern GLboolean
+_math_matrix_is_general_scale( const GLmatrix *m );
+
+extern GLboolean
+_math_matrix_is_dirty( const GLmatrix *m );
+
+
+/**
+ * \name Related functions that don't actually operate on GLmatrix structs
+ */
+/*@{*/
+
+extern void
+_math_transposef( GLfloat to[16], const GLfloat from[16] );
+
+extern void
+_math_transposed( GLdouble to[16], const GLdouble from[16] );
+
+extern void
+_math_transposefd( GLfloat to[16], const GLdouble from[16] );
+
+
+/*
+ * Transform a point (column vector) by a matrix: Q = M * P
+ */
+#define TRANSFORM_POINT( Q, M, P ) \
+ Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \
+ Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \
+ Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \
+ Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
+
+
+#define TRANSFORM_POINT3( Q, M, P ) \
+ Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \
+ Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \
+ Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \
+ Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
+
+
+/*
+ * Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT
+ */
+#define TRANSFORM_NORMAL( TO, N, MAT ) \
+do { \
+ TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \
+ TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \
+ TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \
+} while (0)
+
+
+/**
+ * Transform a direction by a matrix.
+ */
+#define TRANSFORM_DIRECTION( TO, DIR, MAT ) \
+do { \
+ TO[0] = DIR[0] * MAT[0] + DIR[1] * MAT[4] + DIR[2] * MAT[8]; \
+ TO[1] = DIR[0] * MAT[1] + DIR[1] * MAT[5] + DIR[2] * MAT[9]; \
+ TO[2] = DIR[0] * MAT[2] + DIR[1] * MAT[6] + DIR[2] * MAT[10];\
+} while (0)
+
+
+extern void
+_mesa_transform_vector(GLfloat u[4], const GLfloat v[4], const GLfloat m[16]);
+
+
+/*@}*/
+
+
+#endif
diff --git a/mesalib/src/mesa/math/m_norm_tmp.h b/mesalib/src/mesa/math/m_norm_tmp.h
new file mode 100644
index 000000000..a20cb0501
--- /dev/null
+++ b/mesalib/src/mesa/math/m_norm_tmp.h
@@ -0,0 +1,390 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+/* Functions to tranform a vector of normals. This includes applying
+ * the transformation matrix, rescaling and normalization.
+ */
+
+/*
+ * mat - the 4x4 transformation matrix
+ * scale - uniform scale factor of the transformation matrix (not always used)
+ * in - the source vector of normals
+ * lengths - length of each incoming normal (may be NULL) (a display list
+ * optimization)
+ * dest - the destination vector of normals
+ */
+static void _XFORMAPI
+TAG(transform_normalize_normals)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ const GLfloat *m = mat->inv;
+ GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
+ GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
+ GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
+ GLuint i;
+
+ if (!lengths) {
+ STRIDE_LOOP {
+ GLfloat tx, ty, tz;
+ {
+ const GLfloat ux = from[0], uy = from[1], uz = from[2];
+ tx = ux * m0 + uy * m1 + uz * m2;
+ ty = ux * m4 + uy * m5 + uz * m6;
+ tz = ux * m8 + uy * m9 + uz * m10;
+ }
+ {
+ GLdouble len = tx*tx + ty*ty + tz*tz;
+ if (len > 1e-20) {
+ GLfloat scale = INV_SQRTF(len);
+ out[i][0] = tx * scale;
+ out[i][1] = ty * scale;
+ out[i][2] = tz * scale;
+ }
+ else {
+ out[i][0] = out[i][1] = out[i][2] = 0;
+ }
+ }
+ }
+ }
+ else {
+ if (scale != 1.0) {
+ m0 *= scale, m4 *= scale, m8 *= scale;
+ m1 *= scale, m5 *= scale, m9 *= scale;
+ m2 *= scale, m6 *= scale, m10 *= scale;
+ }
+
+ STRIDE_LOOP {
+ GLfloat tx, ty, tz;
+ {
+ const GLfloat ux = from[0], uy = from[1], uz = from[2];
+ tx = ux * m0 + uy * m1 + uz * m2;
+ ty = ux * m4 + uy * m5 + uz * m6;
+ tz = ux * m8 + uy * m9 + uz * m10;
+ }
+ {
+ GLfloat len = lengths[i];
+ out[i][0] = tx * len;
+ out[i][1] = ty * len;
+ out[i][2] = tz * len;
+ }
+ }
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ const GLfloat *m = mat->inv;
+ GLfloat m0 = m[0];
+ GLfloat m5 = m[5];
+ GLfloat m10 = m[10];
+ GLuint i;
+
+ if (!lengths) {
+ STRIDE_LOOP {
+ GLfloat tx, ty, tz;
+ {
+ const GLfloat ux = from[0], uy = from[1], uz = from[2];
+ tx = ux * m0 ;
+ ty = uy * m5 ;
+ tz = uz * m10;
+ }
+ {
+ GLdouble len = tx*tx + ty*ty + tz*tz;
+ if (len > 1e-20) {
+ GLfloat scale = INV_SQRTF(len);
+ out[i][0] = tx * scale;
+ out[i][1] = ty * scale;
+ out[i][2] = tz * scale;
+ }
+ else {
+ out[i][0] = out[i][1] = out[i][2] = 0;
+ }
+ }
+ }
+ }
+ else {
+ m0 *= scale;
+ m5 *= scale;
+ m10 *= scale;
+
+ STRIDE_LOOP {
+ GLfloat tx, ty, tz;
+ {
+ const GLfloat ux = from[0], uy = from[1], uz = from[2];
+ tx = ux * m0 ;
+ ty = uy * m5 ;
+ tz = uz * m10;
+ }
+ {
+ GLfloat len = lengths[i];
+ out[i][0] = tx * len;
+ out[i][1] = ty * len;
+ out[i][2] = tz * len;
+ }
+ }
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ const GLfloat *m = mat->inv;
+ const GLfloat m0 = scale*m[0];
+ const GLfloat m5 = scale*m[5];
+ const GLfloat m10 = scale*m[10];
+ GLuint i;
+
+ (void) lengths;
+
+ STRIDE_LOOP {
+ GLfloat ux = from[0], uy = from[1], uz = from[2];
+ out[i][0] = ux * m0;
+ out[i][1] = uy * m5;
+ out[i][2] = uz * m10;
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_rescale_normals)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ /* Since we are unlikely to have < 3 vertices in the buffer,
+ * it makes sense to pre-multiply by scale.
+ */
+ const GLfloat *m = mat->inv;
+ const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
+ const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
+ const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
+ GLuint i;
+
+ (void) lengths;
+
+ STRIDE_LOOP {
+ GLfloat ux = from[0], uy = from[1], uz = from[2];
+ out[i][0] = ux * m0 + uy * m1 + uz * m2;
+ out[i][1] = ux * m4 + uy * m5 + uz * m6;
+ out[i][2] = ux * m8 + uy * m9 + uz * m10;
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_normals_no_rot)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ const GLfloat *m = mat->inv;
+ const GLfloat m0 = m[0];
+ const GLfloat m5 = m[5];
+ const GLfloat m10 = m[10];
+ GLuint i;
+
+ (void) scale;
+ (void) lengths;
+
+ STRIDE_LOOP {
+ GLfloat ux = from[0], uy = from[1], uz = from[2];
+ out[i][0] = ux * m0;
+ out[i][1] = uy * m5;
+ out[i][2] = uz * m10;
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_normals)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ const GLfloat *m = mat->inv;
+ const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
+ const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
+ const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
+ GLuint i;
+
+ (void) scale;
+ (void) lengths;
+
+ STRIDE_LOOP {
+ GLfloat ux = from[0], uy = from[1], uz = from[2];
+ out[i][0] = ux * m0 + uy * m1 + uz * m2;
+ out[i][1] = ux * m4 + uy * m5 + uz * m6;
+ out[i][2] = ux * m8 + uy * m9 + uz * m10;
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(normalize_normals)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ GLuint i;
+
+ (void) mat;
+ (void) scale;
+
+ if (lengths) {
+ STRIDE_LOOP {
+ const GLfloat x = from[0], y = from[1], z = from[2];
+ GLfloat invlen = lengths[i];
+ out[i][0] = x * invlen;
+ out[i][1] = y * invlen;
+ out[i][2] = z * invlen;
+ }
+ }
+ else {
+ STRIDE_LOOP {
+ const GLfloat x = from[0], y = from[1], z = from[2];
+ GLdouble len = x * x + y * y + z * z;
+ if (len > 1e-50) {
+ len = INV_SQRTF(len);
+ out[i][0] = (GLfloat)(x * len);
+ out[i][1] = (GLfloat)(y * len);
+ out[i][2] = (GLfloat)(z * len);
+ }
+ else {
+ out[i][0] = x;
+ out[i][1] = y;
+ out[i][2] = z;
+ }
+ }
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(rescale_normals)( const GLmatrix *mat,
+ GLfloat scale,
+ const GLvector4f *in,
+ const GLfloat *lengths,
+ GLvector4f *dest )
+{
+ GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
+ const GLfloat *from = in->start;
+ const GLuint stride = in->stride;
+ const GLuint count = in->count;
+ GLuint i;
+
+ (void) mat;
+ (void) lengths;
+
+ STRIDE_LOOP {
+ SCALE_SCALAR_3V( out[i], scale, from );
+ }
+ dest->count = in->count;
+}
+
+
+static void _XFORMAPI
+TAG(init_c_norm_transform)( void )
+{
+ _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
+ TAG(transform_normals_no_rot);
+
+ _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
+ TAG(transform_rescale_normals_no_rot);
+
+ _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
+ TAG(transform_normalize_normals_no_rot);
+
+ _mesa_normal_tab[NORM_TRANSFORM] =
+ TAG(transform_normals);
+
+ _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
+ TAG(transform_rescale_normals);
+
+ _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
+ TAG(transform_normalize_normals);
+
+ _mesa_normal_tab[NORM_RESCALE] =
+ TAG(rescale_normals);
+
+ _mesa_normal_tab[NORM_NORMALIZE] =
+ TAG(normalize_normals);
+}
diff --git a/mesalib/src/mesa/math/m_trans_tmp.h b/mesalib/src/mesa/math/m_trans_tmp.h
new file mode 100644
index 000000000..08fb4d1e9
--- /dev/null
+++ b/mesalib/src/mesa/math/m_trans_tmp.h
@@ -0,0 +1,281 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \brief Templates for vector conversions.
+ * \author Keith Whitwell.
+ */
+
+#ifdef DEST_4F
+static void DEST_4F( GLfloat (*t)[4],
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+
+ (void) first;
+ (void) start;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ if (SZ >= 1) t[i][0] = TRX_4F(f, 0);
+ if (SZ >= 2) t[i][1] = TRX_4F(f, 1);
+ if (SZ >= 3) t[i][2] = TRX_4F(f, 2);
+ if (SZ == 4) t[i][3] = TRX_4F(f, 3); else t[i][3] = 1.0;
+ }
+ }
+}
+#endif
+
+
+
+#ifdef DEST_4FN
+static void DEST_4FN( GLfloat (*t)[4],
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+
+ (void) first;
+ (void) start;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ if (SZ >= 1) t[i][0] = TRX_4FN(f, 0);
+ if (SZ >= 2) t[i][1] = TRX_4FN(f, 1);
+ if (SZ >= 3) t[i][2] = TRX_4FN(f, 2);
+ if (SZ == 4) t[i][3] = TRX_4FN(f, 3); else t[i][3] = 1.0;
+ }
+ }
+}
+#endif
+
+
+#ifdef DEST_3FN
+static void DEST_3FN( GLfloat (*t)[3],
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+ (void) first;
+ (void) start;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ t[i][0] = TRX_3FN(f, 0);
+ t[i][1] = TRX_3FN(f, 1);
+ t[i][2] = TRX_3FN(f, 2);
+ }
+ }
+}
+#endif
+
+#ifdef DEST_1F
+static void DEST_1F( GLfloat *t,
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+ (void) first;
+ (void) start;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ t[i] = TRX_1F(f, 0);
+ }
+ }
+}
+#endif
+
+#ifdef DEST_4UB
+static void DEST_4UB( GLubyte (*t)[4],
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+ (void) start;
+ (void) first;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ if (SZ >= 1) TRX_UB(t[i][0], f, 0);
+ if (SZ >= 2) TRX_UB(t[i][1], f, 1);
+ if (SZ >= 3) TRX_UB(t[i][2], f, 2);
+ if (SZ == 4) TRX_UB(t[i][3], f, 3); else t[i][3] = 255;
+ }
+ }
+}
+#endif
+
+
+#ifdef DEST_4US
+static void DEST_4US( GLushort (*t)[4],
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ((GLubyte *) ptr + SRC_START * stride);
+ const GLubyte *first = f;
+ GLuint i;
+ (void) start;
+ (void) first;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ if (SZ >= 1) TRX_US(t[i][0], f, 0);
+ if (SZ >= 2) TRX_US(t[i][1], f, 1);
+ if (SZ >= 3) TRX_US(t[i][2], f, 2);
+ if (SZ == 4) TRX_US(t[i][3], f, 3); else t[i][3] = 65535;
+ }
+ }
+}
+#endif
+
+
+#ifdef DEST_1UB
+static void DEST_1UB( GLubyte *t,
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+ (void) start;
+ (void) first;
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ TRX_UB(t[i], f, 0);
+ }
+ }
+}
+#endif
+
+
+#ifdef DEST_1UI
+static void DEST_1UI( GLuint *t,
+ CONST void *ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
+ const GLubyte *first = f;
+ GLuint i;
+ (void) start;
+ (void) first;
+
+ for (i = DST_START ; i < n ; i++, NEXT_F) {
+ CHECK {
+ NEXT_F2;
+ t[i] = TRX_UI(f, 0);
+ }
+ }
+}
+#endif
+
+
+static void INIT(void)
+{
+#ifdef DEST_1UI
+ ASSERT(SZ == 1);
+ TAB(_1ui)[SRC_IDX] = DEST_1UI;
+#endif
+#ifdef DEST_1UB
+ ASSERT(SZ == 1);
+ TAB(_1ub)[SRC_IDX] = DEST_1UB;
+#endif
+#ifdef DEST_1F
+ ASSERT(SZ == 1);
+ TAB(_1f)[SRC_IDX] = DEST_1F;
+#endif
+#ifdef DEST_3FN
+ ASSERT(SZ == 3);
+ TAB(_3fn)[SRC_IDX] = DEST_3FN;
+#endif
+#ifdef DEST_4UB
+ TAB(_4ub)[SZ][SRC_IDX] = DEST_4UB;
+#endif
+#ifdef DEST_4US
+ TAB(_4us)[SZ][SRC_IDX] = DEST_4US;
+#endif
+#ifdef DEST_4F
+ TAB(_4f)[SZ][SRC_IDX] = DEST_4F;
+#endif
+#ifdef DEST_4FN
+ TAB(_4fn)[SZ][SRC_IDX] = DEST_4FN;
+#endif
+
+}
+
+
+#ifdef INIT
+#undef INIT
+#endif
+#ifdef DEST_1UI
+#undef DEST_1UI
+#endif
+#ifdef DEST_1UB
+#undef DEST_1UB
+#endif
+#ifdef DEST_4UB
+#undef DEST_4UB
+#endif
+#ifdef DEST_4US
+#undef DEST_4US
+#endif
+#ifdef DEST_3FN
+#undef DEST_3FN
+#endif
+#ifdef DEST_4F
+#undef DEST_4F
+#endif
+#ifdef DEST_4FN
+#undef DEST_4FN
+#endif
+#ifdef DEST_1F
+#undef DEST_1F
+#endif
+#ifdef SZ
+#undef SZ
+#endif
+#ifdef TAG
+#undef TAG
+#endif
+
diff --git a/mesalib/src/mesa/math/m_translate.c b/mesalib/src/mesa/math/m_translate.c
new file mode 100644
index 000000000..4a20f45ee
--- /dev/null
+++ b/mesalib/src/mesa/math/m_translate.c
@@ -0,0 +1,751 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \brief Translate vectors of numbers between various types.
+ * \author Keith Whitwell.
+ */
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h" /* GLchan hack */
+#include "main/colormac.h"
+
+#include "m_translate.h"
+
+
+
+typedef void (*trans_1f_func)(GLfloat *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_1ui_func)(GLuint *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_1ub_func)(GLubyte *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_4ub_func)(GLubyte (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_4us_func)(GLushort (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_4f_func)(GLfloat (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+typedef void (*trans_3fn_func)(GLfloat (*to)[3],
+ CONST void *ptr,
+ GLuint stride,
+ GLuint start,
+ GLuint n );
+
+
+
+
+#define TYPE_IDX(t) ((t) & 0xf)
+#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
+
+
+/* This macro is used on other systems, so undefine it for this module */
+
+#undef CHECK
+
+static trans_1f_func _math_trans_1f_tab[MAX_TYPES];
+static trans_1ui_func _math_trans_1ui_tab[MAX_TYPES];
+static trans_1ub_func _math_trans_1ub_tab[MAX_TYPES];
+static trans_3fn_func _math_trans_3fn_tab[MAX_TYPES];
+static trans_4ub_func _math_trans_4ub_tab[5][MAX_TYPES];
+static trans_4us_func _math_trans_4us_tab[5][MAX_TYPES];
+static trans_4f_func _math_trans_4f_tab[5][MAX_TYPES];
+static trans_4f_func _math_trans_4fn_tab[5][MAX_TYPES];
+
+
+#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt])
+
+
+#define TAB(x) _math_trans##x##_tab
+#define ARGS GLuint start, GLuint n
+#define SRC_START start
+#define DST_START 0
+#define STRIDE stride
+#define NEXT_F f += stride
+#define NEXT_F2
+#define CHECK
+
+
+
+
+/**
+ * Translate from GL_BYTE.
+ */
+#define SRC GLbyte
+#define SRC_IDX TYPE_IDX(GL_BYTE)
+#define TRX_3FN(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
+#if 1
+#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
+#else
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#endif
+#define TRX_4FN(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) )
+#define TRX_US(ch, f,n) ch = BYTE_TO_USHORT( PTR_ELT(f,n) )
+#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
+
+
+#define SZ 4
+#define INIT init_trans_4_GLbyte_raw
+#define DEST_4F trans_4_GLbyte_4f_raw
+#define DEST_4FN trans_4_GLbyte_4fn_raw
+#define DEST_4UB trans_4_GLbyte_4ub_raw
+#define DEST_4US trans_4_GLbyte_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLbyte_raw
+#define DEST_4F trans_3_GLbyte_4f_raw
+#define DEST_4FN trans_3_GLbyte_4fn_raw
+#define DEST_4UB trans_3_GLbyte_4ub_raw
+#define DEST_4US trans_3_GLbyte_4us_raw
+#define DEST_3FN trans_3_GLbyte_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLbyte_raw
+#define DEST_4F trans_2_GLbyte_4f_raw
+#define DEST_4FN trans_2_GLbyte_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLbyte_raw
+#define DEST_4F trans_1_GLbyte_4f_raw
+#define DEST_4FN trans_1_GLbyte_4fn_raw
+#define DEST_1UB trans_1_GLbyte_1ub_raw
+#define DEST_1UI trans_1_GLbyte_1ui_raw
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+#undef SRC_IDX
+
+
+/**
+ * Translate from GL_UNSIGNED_BYTE.
+ */
+#define SRC GLubyte
+#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE)
+#define TRX_3FN(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n))
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#define TRX_4FN(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n))
+#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n)
+#define TRX_US(us, f,n) us = UBYTE_TO_USHORT(PTR_ELT(f,n))
+#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n)
+
+/* 4ub->4ub handled in special case below.
+ */
+#define SZ 4
+#define INIT init_trans_4_GLubyte_raw
+#define DEST_4F trans_4_GLubyte_4f_raw
+#define DEST_4FN trans_4_GLubyte_4fn_raw
+#define DEST_4US trans_4_GLubyte_4us_raw
+#include "m_trans_tmp.h"
+
+
+#define SZ 3
+#define INIT init_trans_3_GLubyte_raw
+#define DEST_4UB trans_3_GLubyte_4ub_raw
+#define DEST_4US trans_3_GLubyte_4us_raw
+#define DEST_3FN trans_3_GLubyte_3fn_raw
+#define DEST_4F trans_3_GLubyte_4f_raw
+#define DEST_4FN trans_3_GLubyte_4fn_raw
+#include "m_trans_tmp.h"
+
+
+#define SZ 1
+#define INIT init_trans_1_GLubyte_raw
+#define DEST_1UI trans_1_GLubyte_1ui_raw
+#define DEST_1UB trans_1_GLubyte_1ub_raw
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+/* GL_SHORT
+ */
+#define SRC GLshort
+#define SRC_IDX TYPE_IDX(GL_SHORT)
+#define TRX_3FN(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#define TRX_4FN(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n))
+#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n))
+#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
+
+
+#define SZ 4
+#define INIT init_trans_4_GLshort_raw
+#define DEST_4F trans_4_GLshort_4f_raw
+#define DEST_4FN trans_4_GLshort_4fn_raw
+#define DEST_4UB trans_4_GLshort_4ub_raw
+#define DEST_4US trans_4_GLshort_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLshort_raw
+#define DEST_4F trans_3_GLshort_4f_raw
+#define DEST_4FN trans_3_GLshort_4fn_raw
+#define DEST_4UB trans_3_GLshort_4ub_raw
+#define DEST_4US trans_3_GLshort_4us_raw
+#define DEST_3FN trans_3_GLshort_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLshort_raw
+#define DEST_4F trans_2_GLshort_4f_raw
+#define DEST_4FN trans_2_GLshort_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLshort_raw
+#define DEST_4F trans_1_GLshort_4f_raw
+#define DEST_4FN trans_1_GLshort_4fn_raw
+#define DEST_1UB trans_1_GLshort_1ub_raw
+#define DEST_1UI trans_1_GLshort_1ui_raw
+#include "m_trans_tmp.h"
+
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+/* GL_UNSIGNED_SHORT
+ */
+#define SRC GLushort
+#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT)
+#define TRX_3FN(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#define TRX_4FN(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8)
+#define TRX_US(us,f,n) us = PTR_ELT(f,n)
+#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n)
+
+
+#define SZ 4
+#define INIT init_trans_4_GLushort_raw
+#define DEST_4F trans_4_GLushort_4f_raw
+#define DEST_4FN trans_4_GLushort_4fn_raw
+#define DEST_4UB trans_4_GLushort_4ub_raw
+#define DEST_4US trans_4_GLushort_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLushort_raw
+#define DEST_4F trans_3_GLushort_4f_raw
+#define DEST_4FN trans_3_GLushort_4fn_raw
+#define DEST_4UB trans_3_GLushort_4ub_raw
+#define DEST_4US trans_3_GLushort_4us_raw
+#define DEST_3FN trans_3_GLushort_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLushort_raw
+#define DEST_4F trans_2_GLushort_4f_raw
+#define DEST_4FN trans_2_GLushort_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLushort_raw
+#define DEST_4F trans_1_GLushort_4f_raw
+#define DEST_4FN trans_1_GLushort_4fn_raw
+#define DEST_1UB trans_1_GLushort_1ub_raw
+#define DEST_1UI trans_1_GLushort_1ui_raw
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+/* GL_INT
+ */
+#define SRC GLint
+#define SRC_IDX TYPE_IDX(GL_INT)
+#define TRX_3FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#define TRX_4FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n))
+#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n))
+#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
+
+
+#define SZ 4
+#define INIT init_trans_4_GLint_raw
+#define DEST_4F trans_4_GLint_4f_raw
+#define DEST_4FN trans_4_GLint_4fn_raw
+#define DEST_4UB trans_4_GLint_4ub_raw
+#define DEST_4US trans_4_GLint_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLint_raw
+#define DEST_4F trans_3_GLint_4f_raw
+#define DEST_4FN trans_3_GLint_4fn_raw
+#define DEST_4UB trans_3_GLint_4ub_raw
+#define DEST_4US trans_3_GLint_4us_raw
+#define DEST_3FN trans_3_GLint_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLint_raw
+#define DEST_4F trans_2_GLint_4f_raw
+#define DEST_4FN trans_2_GLint_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLint_raw
+#define DEST_4F trans_1_GLint_4f_raw
+#define DEST_4FN trans_1_GLint_4fn_raw
+#define DEST_1UB trans_1_GLint_1ub_raw
+#define DEST_1UI trans_1_GLint_1ui_raw
+#include "m_trans_tmp.h"
+
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+/* GL_UNSIGNED_INT
+ */
+#define SRC GLuint
+#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT)
+#define TRX_3FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
+#define TRX_4FN(f,n) UINT_TO_FLOAT( PTR_ELT(f,n) )
+#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24)
+#define TRX_US(us, f,n) us = (GLshort) (PTR_ELT(f,n) >> 16)
+#define TRX_UI(f,n) PTR_ELT(f,n)
+
+
+#define SZ 4
+#define INIT init_trans_4_GLuint_raw
+#define DEST_4F trans_4_GLuint_4f_raw
+#define DEST_4FN trans_4_GLuint_4fn_raw
+#define DEST_4UB trans_4_GLuint_4ub_raw
+#define DEST_4US trans_4_GLuint_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLuint_raw
+#define DEST_4F trans_3_GLuint_4f_raw
+#define DEST_4FN trans_3_GLuint_4fn_raw
+#define DEST_4UB trans_3_GLuint_4ub_raw
+#define DEST_4US trans_3_GLuint_4us_raw
+#define DEST_3FN trans_3_GLuint_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLuint_raw
+#define DEST_4F trans_2_GLuint_4f_raw
+#define DEST_4FN trans_2_GLuint_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLuint_raw
+#define DEST_4F trans_1_GLuint_4f_raw
+#define DEST_4FN trans_1_GLuint_4fn_raw
+#define DEST_1UB trans_1_GLuint_1ub_raw
+#define DEST_1UI trans_1_GLuint_1ui_raw
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+/* GL_DOUBLE
+ */
+#define SRC GLdouble
+#define SRC_IDX TYPE_IDX(GL_DOUBLE)
+#define TRX_3FN(f,n) (GLfloat) PTR_ELT(f,n)
+#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n)
+#define TRX_4FN(f,n) (GLfloat) PTR_ELT(f,n)
+#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n))
+#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n))
+#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n)
+#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n)
+
+
+#define SZ 4
+#define INIT init_trans_4_GLdouble_raw
+#define DEST_4F trans_4_GLdouble_4f_raw
+#define DEST_4FN trans_4_GLdouble_4fn_raw
+#define DEST_4UB trans_4_GLdouble_4ub_raw
+#define DEST_4US trans_4_GLdouble_4us_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLdouble_raw
+#define DEST_4F trans_3_GLdouble_4f_raw
+#define DEST_4FN trans_3_GLdouble_4fn_raw
+#define DEST_4UB trans_3_GLdouble_4ub_raw
+#define DEST_4US trans_3_GLdouble_4us_raw
+#define DEST_3FN trans_3_GLdouble_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLdouble_raw
+#define DEST_4F trans_2_GLdouble_4f_raw
+#define DEST_4FN trans_2_GLdouble_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLdouble_raw
+#define DEST_4F trans_1_GLdouble_4f_raw
+#define DEST_4FN trans_1_GLdouble_4fn_raw
+#define DEST_1UB trans_1_GLdouble_1ub_raw
+#define DEST_1UI trans_1_GLdouble_1ui_raw
+#define DEST_1F trans_1_GLdouble_1f_raw
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef SRC_IDX
+
+/* GL_FLOAT
+ */
+#define SRC GLfloat
+#define SRC_IDX TYPE_IDX(GL_FLOAT)
+#define SZ 4
+#define INIT init_trans_4_GLfloat_raw
+#define DEST_4UB trans_4_GLfloat_4ub_raw
+#define DEST_4US trans_4_GLfloat_4us_raw
+#define DEST_4F trans_4_GLfloat_4f_raw
+#define DEST_4FN trans_4_GLfloat_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 3
+#define INIT init_trans_3_GLfloat_raw
+#define DEST_4F trans_3_GLfloat_4f_raw
+#define DEST_4FN trans_3_GLfloat_4fn_raw
+#define DEST_4UB trans_3_GLfloat_4ub_raw
+#define DEST_4US trans_3_GLfloat_4us_raw
+#define DEST_3FN trans_3_GLfloat_3fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 2
+#define INIT init_trans_2_GLfloat_raw
+#define DEST_4F trans_2_GLfloat_4f_raw
+#define DEST_4FN trans_2_GLfloat_4fn_raw
+#include "m_trans_tmp.h"
+
+#define SZ 1
+#define INIT init_trans_1_GLfloat_raw
+#define DEST_4F trans_1_GLfloat_4f_raw
+#define DEST_4FN trans_1_GLfloat_4fn_raw
+#define DEST_1UB trans_1_GLfloat_1ub_raw
+#define DEST_1UI trans_1_GLfloat_1ui_raw
+#define DEST_1F trans_1_GLfloat_1f_raw
+
+#include "m_trans_tmp.h"
+
+#undef SRC
+#undef SRC_IDX
+#undef TRX_3FN
+#undef TRX_4F
+#undef TRX_4FN
+#undef TRX_UB
+#undef TRX_US
+#undef TRX_UI
+
+
+static void trans_4_GLubyte_4ub_raw(GLubyte (*t)[4],
+ CONST void *Ptr,
+ GLuint stride,
+ ARGS )
+{
+ const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride;
+ GLuint i;
+
+ if (((((uintptr_t) f | (uintptr_t) stride)) & 3L) == 0L) {
+ /* Aligned.
+ */
+ for (i = DST_START ; i < n ; i++, f += stride) {
+ COPY_4UBV( t[i], f );
+ }
+ } else {
+ for (i = DST_START ; i < n ; i++, f += stride) {
+ t[i][0] = f[0];
+ t[i][1] = f[1];
+ t[i][2] = f[2];
+ t[i][3] = f[3];
+ }
+ }
+}
+
+
+static void init_translate_raw(void)
+{
+ MEMSET( TAB(_1ui), 0, sizeof(TAB(_1ui)) );
+ MEMSET( TAB(_1ub), 0, sizeof(TAB(_1ub)) );
+ MEMSET( TAB(_3fn), 0, sizeof(TAB(_3fn)) );
+ MEMSET( TAB(_4ub), 0, sizeof(TAB(_4ub)) );
+ MEMSET( TAB(_4us), 0, sizeof(TAB(_4us)) );
+ MEMSET( TAB(_4f), 0, sizeof(TAB(_4f)) );
+ MEMSET( TAB(_4fn), 0, sizeof(TAB(_4fn)) );
+
+ init_trans_4_GLbyte_raw();
+ init_trans_3_GLbyte_raw();
+ init_trans_2_GLbyte_raw();
+ init_trans_1_GLbyte_raw();
+ init_trans_1_GLubyte_raw();
+ init_trans_3_GLubyte_raw();
+ init_trans_4_GLubyte_raw();
+ init_trans_4_GLshort_raw();
+ init_trans_3_GLshort_raw();
+ init_trans_2_GLshort_raw();
+ init_trans_1_GLshort_raw();
+ init_trans_4_GLushort_raw();
+ init_trans_3_GLushort_raw();
+ init_trans_2_GLushort_raw();
+ init_trans_1_GLushort_raw();
+ init_trans_4_GLint_raw();
+ init_trans_3_GLint_raw();
+ init_trans_2_GLint_raw();
+ init_trans_1_GLint_raw();
+ init_trans_4_GLuint_raw();
+ init_trans_3_GLuint_raw();
+ init_trans_2_GLuint_raw();
+ init_trans_1_GLuint_raw();
+ init_trans_4_GLdouble_raw();
+ init_trans_3_GLdouble_raw();
+ init_trans_2_GLdouble_raw();
+ init_trans_1_GLdouble_raw();
+ init_trans_4_GLfloat_raw();
+ init_trans_3_GLfloat_raw();
+ init_trans_2_GLfloat_raw();
+ init_trans_1_GLfloat_raw();
+
+ TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub_raw;
+}
+
+
+#undef TAB
+#ifdef CLASS
+#undef CLASS
+#endif
+#undef ARGS
+#undef CHECK
+#undef SRC_START
+#undef DST_START
+#undef NEXT_F
+#undef NEXT_F2
+
+
+
+
+
+void _math_init_translate( void )
+{
+ init_translate_raw();
+}
+
+
+/**
+ * Translate vector of values to GLfloat [1].
+ */
+void _math_trans_1f(GLfloat *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_1f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLuint [1].
+ */
+void _math_trans_1ui(GLuint *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_1ui_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLubyte [1].
+ */
+void _math_trans_1ub(GLubyte *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_1ub_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+
+/**
+ * Translate vector of values to GLubyte [4].
+ */
+void _math_trans_4ub(GLubyte (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_4ub_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLchan [4].
+ */
+void _math_trans_4chan( GLchan (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n )
+{
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ _math_trans_4ub( to, ptr, stride, type, size, start, n );
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+ _math_trans_4us( to, ptr, stride, type, size, start, n );
+#elif CHAN_TYPE == GL_FLOAT
+ _math_trans_4fn( to, ptr, stride, type, size, start, n );
+#endif
+}
+
+/**
+ * Translate vector of values to GLushort [4].
+ */
+void _math_trans_4us(GLushort (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_4us_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLfloat [4].
+ */
+void _math_trans_4f(GLfloat (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_4f_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLfloat[4], normalized to [-1, 1].
+ */
+void _math_trans_4fn(GLfloat (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_4fn_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
+
+/**
+ * Translate vector of values to GLfloat[3], normalized to [-1, 1].
+ */
+void _math_trans_3fn(GLfloat (*to)[3],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n )
+{
+ _math_trans_3fn_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
+}
diff --git a/mesalib/src/mesa/math/m_translate.h b/mesalib/src/mesa/math/m_translate.h
new file mode 100644
index 000000000..c677682d5
--- /dev/null
+++ b/mesalib/src/mesa/math/m_translate.h
@@ -0,0 +1,122 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 _M_TRANSLATE_H_
+#define _M_TRANSLATE_H_
+
+#include "main/config.h"
+#include "main/mtypes.h" /* hack for GLchan */
+
+
+/**
+ * Array translation.
+ * For example, convert array of GLushort[3] to GLfloat[4].
+ * The function name specifies the destination format/size.
+ * \param to the destination address
+ * \param ptr the source address
+ * \param stride the source stride (in bytes) between elements
+ * \param type the source datatype (GL_SHORT, GL_UNSIGNED_INT, etc)
+ * \param size number of values per element in source array (1,2,3 or 4)
+ * \param start first element in source array to convert
+ * \param n number of elements to convert
+ *
+ * Note: "element" means a tuple like GLfloat[3] or GLubyte[4].
+ */
+
+
+extern void _math_trans_1f(GLfloat *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_1ui(GLuint *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_1ub(GLubyte *to,
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_4ub(GLubyte (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_4chan( GLchan (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_4us(GLushort (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n );
+
+/** Convert to floats w/out normalization (i.e. just cast) */
+extern void _math_trans_4f(GLfloat (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n );
+
+/** Convert to normalized floats in [0,1] or [-1, 1] */
+extern void _math_trans_4fn(GLfloat (*to)[4],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint size,
+ GLuint start,
+ GLuint n );
+
+extern void _math_trans_3fn(GLfloat (*to)[3],
+ CONST void *ptr,
+ GLuint stride,
+ GLenum type,
+ GLuint start,
+ GLuint n );
+
+extern void _math_init_translate( void );
+
+
+#endif
diff --git a/mesalib/src/mesa/math/m_vector.c b/mesalib/src/mesa/math/m_vector.c
new file mode 100644
index 000000000..4cbab11a3
--- /dev/null
+++ b/mesalib/src/mesa/math/m_vector.c
@@ -0,0 +1,185 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/imports.h"
+
+#include "m_vector.h"
+
+
+
+/**
+ * Given a vector [count][4] of floats, set all the [][elt] values
+ * to 0 (if elt = 0, 1, 2) or 1.0 (if elt = 3).
+ */
+void
+_mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt )
+{
+ static const GLubyte elem_bits[4] = {
+ VEC_DIRTY_0,
+ VEC_DIRTY_1,
+ VEC_DIRTY_2,
+ VEC_DIRTY_3
+ };
+ static const GLfloat clean[4] = { 0, 0, 0, 1 };
+ const GLfloat v = clean[elt];
+ GLfloat (*data)[4] = (GLfloat (*)[4])vec->start;
+ GLuint i;
+
+ for (i = 0; i < count; i++)
+ data[i][elt] = v;
+
+ vec->flags &= ~elem_bits[elt];
+}
+
+
+static const GLubyte size_bits[5] = {
+ 0,
+ VEC_SIZE_1,
+ VEC_SIZE_2,
+ VEC_SIZE_3,
+ VEC_SIZE_4,
+};
+
+
+/**
+ * Initialize GLvector objects.
+ * \param v the vector object to initialize.
+ * \param flags bitwise-OR of VEC_* flags
+ * \param storage pointer to storage for the vector's data
+ */
+void
+_mesa_vector4f_init( GLvector4f *v, GLbitfield flags, GLfloat (*storage)[4] )
+{
+ v->stride = 4 * sizeof(GLfloat);
+ v->size = 2; /* may change: 2-4 for vertices and 1-4 for texcoords */
+ v->data = storage;
+ v->start = (GLfloat *) storage;
+ v->count = 0;
+ v->flags = size_bits[4] | flags;
+}
+
+
+/**
+ * Initialize GLvector objects and allocate storage.
+ * \param v the vector object
+ * \param flags bitwise-OR of VEC_* flags
+ * \param count number of elements to allocate in vector
+ * \param alignment desired memory alignment for the data (in bytes)
+ */
+void
+_mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags, GLuint count,
+ GLuint alignment )
+{
+ v->stride = 4 * sizeof(GLfloat);
+ v->size = 2;
+ v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLfloat), alignment );
+ v->storage_count = count;
+ v->start = (GLfloat *) v->storage;
+ v->data = (GLfloat (*)[4]) v->storage;
+ v->count = 0;
+ v->flags = size_bits[4] | flags | VEC_MALLOC;
+}
+
+
+/**
+ * Vector deallocation. Free whatever memory is pointed to by the
+ * vector's storage field if the VEC_MALLOC flag is set.
+ * DO NOT free the GLvector object itself, though.
+ */
+void
+_mesa_vector4f_free( GLvector4f *v )
+{
+ if (v->flags & VEC_MALLOC) {
+ ALIGN_FREE( v->storage );
+ v->data = NULL;
+ v->start = NULL;
+ v->storage = NULL;
+ v->flags &= ~VEC_MALLOC;
+ }
+}
+
+
+/**
+ * For debugging
+ */
+void
+_mesa_vector4f_print( const GLvector4f *v, const GLubyte *cullmask,
+ GLboolean culling )
+{
+ static const GLfloat c[4] = { 0, 0, 0, 1 };
+ static const char *templates[5] = {
+ "%d:\t0, 0, 0, 1\n",
+ "%d:\t%f, 0, 0, 1\n",
+ "%d:\t%f, %f, 0, 1\n",
+ "%d:\t%f, %f, %f, 1\n",
+ "%d:\t%f, %f, %f, %f\n"
+ };
+
+ const char *t = templates[v->size];
+ GLfloat *d = (GLfloat *)v->data;
+ GLuint j, i = 0, count;
+
+ _mesa_printf("data-start\n");
+ for (; d != v->start; STRIDE_F(d, v->stride), i++)
+ _mesa_printf(t, i, d[0], d[1], d[2], d[3]);
+
+ _mesa_printf("start-count(%u)\n", v->count);
+ count = i + v->count;
+
+ if (culling) {
+ for (; i < count; STRIDE_F(d, v->stride), i++)
+ if (cullmask[i])
+ _mesa_printf(t, i, d[0], d[1], d[2], d[3]);
+ }
+ else {
+ for (; i < count; STRIDE_F(d, v->stride), i++)
+ _mesa_printf(t, i, d[0], d[1], d[2], d[3]);
+ }
+
+ for (j = v->size; j < 4; j++) {
+ if ((v->flags & (1<<j)) == 0) {
+
+ _mesa_printf("checking col %u is clean as advertised ", j);
+
+ for (i = 0, d = (GLfloat *) v->data;
+ i < count && d[j] == c[j];
+ i++, STRIDE_F(d, v->stride)) {
+ /* no-op */
+ }
+
+ if (i == count)
+ _mesa_printf(" --> ok\n");
+ else
+ _mesa_printf(" --> Failed at %u ******\n", i);
+ }
+ }
+}
diff --git a/mesalib/src/mesa/math/m_vector.h b/mesalib/src/mesa/math/m_vector.h
new file mode 100644
index 000000000..71281d575
--- /dev/null
+++ b/mesalib/src/mesa/math/m_vector.h
@@ -0,0 +1,92 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+#ifndef _M_VECTOR_H_
+#define _M_VECTOR_H_
+
+#include "main/glheader.h"
+
+
+#define VEC_DIRTY_0 0x1
+#define VEC_DIRTY_1 0x2
+#define VEC_DIRTY_2 0x4
+#define VEC_DIRTY_3 0x8
+#define VEC_MALLOC 0x10 /* storage field points to self-allocated mem*/
+#define VEC_NOT_WRITEABLE 0x40 /* writable elements to hold clipped data */
+#define VEC_BAD_STRIDE 0x100 /* matches tnl's prefered stride */
+
+
+#define VEC_SIZE_1 VEC_DIRTY_0
+#define VEC_SIZE_2 (VEC_DIRTY_0|VEC_DIRTY_1)
+#define VEC_SIZE_3 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2)
+#define VEC_SIZE_4 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2|VEC_DIRTY_3)
+
+
+
+/**
+ * Wrap all the information about vectors up in a struct. Has
+ * additional fields compared to the other vectors to help us track of
+ * different vertex sizes, and whether we need to clean columns out
+ * because they contain non-(0,0,0,1) values.
+ *
+ * The start field is used to reserve data for copied vertices at the
+ * end of _mesa_transform_vb, and avoids the need for a multiplication in
+ * the transformation routines.
+ */
+typedef struct {
+ GLfloat (*data)[4]; /**< may be malloc'd or point to client data */
+ GLfloat *start; /**< points somewhere inside of <data> */
+ GLuint count; /**< size of the vector (in elements) */
+ GLuint stride; /**< stride from one element to the next (in bytes) */
+ GLuint size; /**< 2-4 for vertices and 1-4 for texcoords */
+ GLbitfield flags; /**< bitmask of VEC_x flags */
+ void *storage; /**< self-allocated storage */
+ GLuint storage_count; /**< storage size in elements */
+} GLvector4f;
+
+
+extern void _mesa_vector4f_init( GLvector4f *v, GLbitfield flags,
+ GLfloat (*storage)[4] );
+extern void _mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags,
+ GLuint count, GLuint alignment );
+extern void _mesa_vector4f_free( GLvector4f *v );
+extern void _mesa_vector4f_print( const GLvector4f *v, const GLubyte *, GLboolean );
+extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt );
+
+
+/**
+ * Given vector <v>, return a pointer (cast to <type *> to the <i>-th element.
+ *
+ * End up doing a lot of slow imuls if not careful.
+ */
+#define VEC_ELT( v, type, i ) \
+ ( (type *) ( ((GLbyte *) ((v)->data)) + (i) * (v)->stride) )
+
+
+#endif
diff --git a/mesalib/src/mesa/math/m_xform.c b/mesalib/src/mesa/math/m_xform.c
new file mode 100644
index 000000000..369f2c6e9
--- /dev/null
+++ b/mesalib/src/mesa/math/m_xform.c
@@ -0,0 +1,128 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/*
+ * Matrix/vertex/vector transformation stuff
+ *
+ *
+ * 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
+ */
+
+#include "main/glheader.h"
+#include "main/macros.h"
+
+#include "m_eval.h"
+#include "m_matrix.h"
+#include "m_translate.h"
+#include "m_xform.h"
+
+
+#ifdef DEBUG_MATH
+#include "m_debug.h"
+#endif
+
+#ifdef USE_X86_ASM
+#include "x86/common_x86_asm.h"
+#endif
+
+#ifdef USE_X86_64_ASM
+#include "x86-64/x86-64.h"
+#endif
+
+#ifdef USE_SPARC_ASM
+#include "sparc/sparc.h"
+#endif
+
+#ifdef USE_PPC_ASM
+#include "ppc/common_ppc_features.h"
+#endif
+
+clip_func _mesa_clip_tab[5];
+clip_func _mesa_clip_np_tab[5];
+dotprod_func _mesa_dotprod_tab[5];
+vec_copy_func _mesa_copy_tab[0x10];
+normal_func _mesa_normal_tab[0xf];
+transform_func *_mesa_transform_tab[5];
+
+
+/* Raw data format used for:
+ * - Object-to-eye transform prior to culling, although this too
+ * could be culled under some circumstances.
+ * - Eye-to-clip transform (via the function above).
+ * - Cliptesting
+ * - And everything else too, if culling happens to be disabled.
+ *
+ * GH: It's used for everything now, as clipping/culling is done
+ * elsewhere (most often by the driver itself).
+ */
+#define TAG(x) x
+#define TAG2(x,y) x##y
+#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) )
+#define LOOP for ( i = 0 ; i < n ; i++ )
+#define ARGS
+#include "m_xform_tmp.h"
+#include "m_clip_tmp.h"
+#include "m_norm_tmp.h"
+#include "m_dotprod_tmp.h"
+#include "m_copy_tmp.h"
+#undef TAG
+#undef TAG2
+#undef LOOP
+#undef ARGS
+
+
+/*
+ * This is called only once. It initializes several tables with pointers
+ * to optimized transformation functions. This is where we can test for
+ * AMD 3Dnow! capability, Intel SSE, etc. and hook in the right code.
+ */
+void
+_math_init_transformation( void )
+{
+ init_c_transformations();
+ init_c_norm_transform();
+ init_c_cliptest();
+ init_copy0();
+ init_dotprod();
+
+#ifdef DEBUG_MATH
+ _math_test_all_transform_functions( "default" );
+ _math_test_all_normal_transform_functions( "default" );
+ _math_test_all_cliptest_functions( "default" );
+#endif
+
+#ifdef USE_X86_ASM
+ _mesa_init_all_x86_transform_asm();
+#elif defined( USE_SPARC_ASM )
+ _mesa_init_all_sparc_transform_asm();
+#elif defined( USE_PPC_ASM )
+ _mesa_init_all_ppc_transform_asm();
+#elif defined( USE_X86_64_ASM )
+ _mesa_init_all_x86_64_transform_asm();
+#endif
+}
diff --git a/mesalib/src/mesa/math/m_xform.h b/mesalib/src/mesa/math/m_xform.h
new file mode 100644
index 000000000..7ef76e0b9
--- /dev/null
+++ b/mesalib/src/mesa/math/m_xform.h
@@ -0,0 +1,166 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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 _M_XFORM_H
+#define _M_XFORM_H
+
+
+#include "main/glheader.h"
+#include "main/config.h"
+#include "math/m_vector.h"
+#include "math/m_matrix.h"
+
+#ifdef USE_X86_ASM
+#define _XFORMAPI _ASMAPI
+#define _XFORMAPIP _ASMAPIP
+#else
+#define _XFORMAPI
+#define _XFORMAPIP *
+#endif
+
+
+extern void
+_math_init_transformation(void);
+
+
+/* KW: Clip functions now do projective divide as well. The projected
+ * coordinates are very useful to us because they let us cull
+ * backfaces and eliminate vertices from lighting, fogging, etc
+ * calculations. Despite the fact that this divide could be done one
+ * day in hardware, we would still have a reason to want to do it here
+ * as long as those other calculations remain in software.
+ *
+ * Clipping is a convenient place to do the divide on x86 as it should be
+ * possible to overlap with integer outcode calculations.
+ *
+ * There are two cases where we wouldn't want to do the divide in cliptest:
+ * - When we aren't clipping. We still might want to cull backfaces
+ * so the divide should be done elsewhere. This currently never
+ * happens.
+ *
+ * - When culling isn't likely to help us, such as when the GL culling
+ * is disabled and we not lighting or are only lighting
+ * one-sided. In this situation, backface determination provides
+ * us with no useful information. A tricky case to detect is when
+ * all input data is already culled, although hopefully the
+ * application wouldn't turn on culling in such cases.
+ *
+ * We supply a buffer to hold the [x/w,y/w,z/w,1/w] values which
+ * are the result of the projection. This is only used in the
+ * 4-vector case - in other cases, we just use the clip coordinates
+ * as the projected coordinates - they are identical.
+ *
+ * This is doubly convenient because it means the Win[] array is now
+ * of the same stride as all the others, so I can now turn map_vertices
+ * into a straight-forward matrix transformation, with asm acceleration
+ * automatically available.
+ */
+
+/* Vertex buffer clipping flags
+ */
+#define CLIP_RIGHT_SHIFT 0
+#define CLIP_LEFT_SHIFT 1
+#define CLIP_TOP_SHIFT 2
+#define CLIP_BOTTOM_SHIFT 3
+#define CLIP_NEAR_SHIFT 4
+#define CLIP_FAR_SHIFT 5
+
+#define CLIP_RIGHT_BIT 0x01
+#define CLIP_LEFT_BIT 0x02
+#define CLIP_TOP_BIT 0x04
+#define CLIP_BOTTOM_BIT 0x08
+#define CLIP_NEAR_BIT 0x10
+#define CLIP_FAR_BIT 0x20
+#define CLIP_USER_BIT 0x40
+#define CLIP_CULL_BIT 0x80
+#define CLIP_FRUSTUM_BITS 0x3f
+
+
+typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip,
+ GLvector4f *vProj,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask );
+
+typedef void (*dotprod_func)( GLfloat *out,
+ GLuint out_stride,
+ CONST GLvector4f *coord_vec,
+ CONST GLfloat plane[4] );
+
+typedef void (*vec_copy_func)( GLvector4f *to,
+ CONST GLvector4f *from );
+
+
+
+/*
+ * Functions for transformation of normals in the VB.
+ */
+typedef void (_NORMAPIP normal_func)( CONST GLmatrix *mat,
+ GLfloat scale,
+ CONST GLvector4f *in,
+ CONST GLfloat lengths[],
+ GLvector4f *dest );
+
+
+/* Flags for selecting a normal transformation function.
+ */
+#define NORM_RESCALE 0x1 /* apply the scale factor */
+#define NORM_NORMALIZE 0x2 /* normalize */
+#define NORM_TRANSFORM 0x4 /* apply the transformation matrix */
+#define NORM_TRANSFORM_NO_ROT 0x8 /* apply the transformation matrix */
+
+
+
+
+/* KW: New versions of the transform function allow a mask array
+ * specifying that individual vector transform should be skipped
+ * when the mask byte is zero. This is always present as a
+ * parameter, to allow a unified interface.
+ */
+typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec,
+ CONST GLfloat m[16],
+ CONST GLvector4f *from_vec );
+
+
+extern dotprod_func _mesa_dotprod_tab[5];
+extern vec_copy_func _mesa_copy_tab[0x10];
+extern vec_copy_func _mesa_copy_clean_tab[5];
+extern clip_func _mesa_clip_tab[5];
+extern clip_func _mesa_clip_np_tab[5];
+extern normal_func _mesa_normal_tab[0xf];
+
+/* Use of 2 layers of linked 1-dimensional arrays to reduce
+ * cost of lookup.
+ */
+extern transform_func *_mesa_transform_tab[5];
+
+
+
+#define TransformRaw( to, mat, from ) \
+ ( _mesa_transform_tab[(from)->size][(mat)->type]( to, (mat)->m, from ), \
+ (to) )
+
+
+#endif
diff --git a/mesalib/src/mesa/math/m_xform_tmp.h b/mesalib/src/mesa/math/m_xform_tmp.h
new file mode 100644
index 000000000..e93837725
--- /dev/null
+++ b/mesalib/src/mesa/math/m_xform_tmp.h
@@ -0,0 +1,810 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * New (3.1) transformation code written by Keith Whitwell.
+ */
+
+
+/*----------------------------------------------------------------------
+ * Begin Keith's new code
+ *
+ *----------------------------------------------------------------------
+ */
+
+/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride.
+ */
+
+/* KW: These are now parameterized to produce two versions, one
+ * which transforms all incoming points, and a second which
+ * takes notice of a cullmask array, and only transforms
+ * unculled vertices.
+ */
+
+/* KW: 1-vectors can sneak into the texture pipeline via the array
+ * interface. These functions are here because I want consistant
+ * treatment of the vertex sizes and a lazy strategy for
+ * cleaning unused parts of the vector, and so as not to exclude
+ * them from the vertex array interface.
+ *
+ * Under our current analysis of matrices, there is no way that
+ * the product of a matrix and a 1-vector can remain a 1-vector,
+ * with the exception of the identity transform.
+ */
+
+/* KW: No longer zero-pad outgoing vectors. Now that external
+ * vectors can get into the pipeline we cannot ever assume
+ * that there is more to a vector than indicated by its
+ * size.
+ */
+
+/* KW: Now uses clipmask and a flag to allow us to skip both/either
+ * cliped and/or culled vertices.
+ */
+
+/* GH: Not any more -- it's easier (and faster) to just process the
+ * entire vector. Clipping and culling are handled further down
+ * the pipe, most often during or after the conversion to some
+ * driver-specific vertex format.
+ */
+
+static void _XFORMAPI
+TAG(transform_points1_general)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m12 = m[12];
+ const GLfloat m1 = m[1], m13 = m[13];
+ const GLfloat m2 = m[2], m14 = m[14];
+ const GLfloat m3 = m[3], m15 = m[15];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m1 * ox + m13;
+ to[i][2] = m2 * ox + m14;
+ to[i][3] = m3 * ox + m15;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points1_identity)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLuint count = from_vec->count;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint i;
+ (void) m;
+ if (to_vec == from_vec) return;
+ STRIDE_LOOP {
+ to[i][0] = from[0];
+ }
+ to_vec->size = 1;
+ to_vec->flags |= VEC_SIZE_1;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points1_2d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1];
+ const GLfloat m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m1 * ox + m13;
+ }
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m13;
+ }
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points1_3d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m2 = m[2];
+ const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m1 * ox + m13;
+ to[i][2] = m2 * ox + m14;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0];
+ const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m13;
+ to[i][2] = m14;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points1_perspective)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0];
+ to[i][0] = m0 * ox ;
+ to[i][1] = 0 ;
+ to[i][2] = m14;
+ to[i][3] = 0;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+
+
+
+/* 2-vectors, which are a lot more relevant than 1-vectors, are
+ * present early in the geometry pipeline and throughout the
+ * texture pipeline.
+ */
+static void _XFORMAPI
+TAG(transform_points2_general)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m4 = m[4], m12 = m[12];
+ const GLfloat m1 = m[1], m5 = m[5], m13 = m[13];
+ const GLfloat m2 = m[2], m6 = m[6], m14 = m[14];
+ const GLfloat m3 = m[3], m7 = m[7], m15 = m[15];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox + m4 * oy + m12;
+ to[i][1] = m1 * ox + m5 * oy + m13;
+ to[i][2] = m2 * ox + m6 * oy + m14;
+ to[i][3] = m3 * ox + m7 * oy + m15;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points2_identity)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ GLuint i;
+ (void) m;
+ if (to_vec == from_vec) return;
+ STRIDE_LOOP {
+ to[i][0] = from[0];
+ to[i][1] = from[1];
+ }
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points2_2d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
+ const GLfloat m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox + m4 * oy + m12;
+ to[i][1] = m1 * ox + m5 * oy + m13;
+ }
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m5 * oy + m13;
+ }
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points2_3d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
+ const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox + m4 * oy + m12;
+ to[i][1] = m1 * ox + m5 * oy + m13;
+ to[i][2] = m2 * ox + m6 * oy + m14;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+
+/* I would actually say this was a fairly important function, from
+ * a texture transformation point of view.
+ */
+static void _XFORMAPI
+TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5];
+ const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox + m12;
+ to[i][1] = m5 * oy + m13;
+ to[i][2] = m14;
+ }
+ if (m14 == 0) {
+ to_vec->size = 2;
+ to_vec->flags |= VEC_SIZE_2;
+ } else {
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ }
+ to_vec->count = from_vec->count;
+}
+
+
+static void _XFORMAPI
+TAG(transform_points2_perspective)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1];
+ to[i][0] = m0 * ox ;
+ to[i][1] = m5 * oy ;
+ to[i][2] = m14;
+ to[i][3] = 0;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+
+
+static void _XFORMAPI
+TAG(transform_points3_general)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
+ const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
+ const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
+ const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12;
+ to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13;
+ to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
+ to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points3_identity)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ GLuint i;
+ (void) m;
+ if (to_vec == from_vec) return;
+ STRIDE_LOOP {
+ to[i][0] = from[0];
+ to[i][1] = from[1];
+ to[i][2] = from[2];
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points3_2d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
+ const GLfloat m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m4 * oy + m12 ;
+ to[i][1] = m1 * ox + m5 * oy + m13 ;
+ to[i][2] = + oz ;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m12 ;
+ to[i][1] = m5 * oy + m13 ;
+ to[i][2] = + oz ;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points3_3d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
+ const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
+ const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ;
+ to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ;
+ to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+/* previously known as ortho...
+ */
+static void _XFORMAPI
+TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5];
+ const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m12 ;
+ to[i][1] = m5 * oy + m13 ;
+ to[i][2] = m10 * oz + m14 ;
+ }
+ to_vec->size = 3;
+ to_vec->flags |= VEC_SIZE_3;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points3_perspective)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
+ const GLfloat m10 = m[10], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2];
+ to[i][0] = m0 * ox + m8 * oz ;
+ to[i][1] = m5 * oy + m9 * oz ;
+ to[i][2] = m10 * oz + m14 ;
+ to[i][3] = -oz ;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+
+
+static void _XFORMAPI
+TAG(transform_points4_general)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
+ const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
+ const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
+ const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
+ to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
+ to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
+ to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_identity)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ GLuint i;
+ (void) m;
+ if (to_vec == from_vec) return;
+ STRIDE_LOOP {
+ to[i][0] = from[0];
+ to[i][1] = from[1];
+ to[i][2] = from[2];
+ to[i][3] = from[3];
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_2d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
+ const GLfloat m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m4 * oy + m12 * ow;
+ to[i][1] = m1 * ox + m5 * oy + m13 * ow;
+ to[i][2] = + oz ;
+ to[i][3] = ow;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m12 * ow;
+ to[i][1] = m5 * oy + m13 * ow;
+ to[i][2] = + oz ;
+ to[i][3] = ow;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_3d)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
+ const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
+ const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
+ to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
+ to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
+ to[i][3] = ow;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5];
+ const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m12 * ow;
+ to[i][1] = m5 * oy + m13 * ow;
+ to[i][2] = m10 * oz + m14 * ow;
+ to[i][3] = ow;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static void _XFORMAPI
+TAG(transform_points4_perspective)( GLvector4f *to_vec,
+ const GLfloat m[16],
+ const GLvector4f *from_vec )
+{
+ const GLuint stride = from_vec->stride;
+ GLfloat *from = from_vec->start;
+ GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
+ GLuint count = from_vec->count;
+ const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
+ const GLfloat m10 = m[10], m14 = m[14];
+ GLuint i;
+ STRIDE_LOOP {
+ const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
+ to[i][0] = m0 * ox + m8 * oz ;
+ to[i][1] = m5 * oy + m9 * oz ;
+ to[i][2] = m10 * oz + m14 * ow ;
+ to[i][3] = -oz ;
+ }
+ to_vec->size = 4;
+ to_vec->flags |= VEC_SIZE_4;
+ to_vec->count = from_vec->count;
+}
+
+static transform_func TAG(transform_tab_1)[7];
+static transform_func TAG(transform_tab_2)[7];
+static transform_func TAG(transform_tab_3)[7];
+static transform_func TAG(transform_tab_4)[7];
+
+/* Similar functions could be called several times, with more highly
+ * optimized routines overwriting the arrays. This only occurs during
+ * startup.
+ */
+static void _XFORMAPI TAG(init_c_transformations)( void )
+{
+#define TAG_TAB _mesa_transform_tab
+#define TAG_TAB_1 TAG(transform_tab_1)
+#define TAG_TAB_2 TAG(transform_tab_2)
+#define TAG_TAB_3 TAG(transform_tab_3)
+#define TAG_TAB_4 TAG(transform_tab_4)
+
+ TAG_TAB[1] = TAG_TAB_1;
+ TAG_TAB[2] = TAG_TAB_2;
+ TAG_TAB[3] = TAG_TAB_3;
+ TAG_TAB[4] = TAG_TAB_4;
+
+ /* 1-D points (ie texcoords) */
+ TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general);
+ TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity);
+ TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot);
+ TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective);
+ TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d);
+ TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot);
+ TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d);
+
+ /* 2-D points */
+ TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general);
+ TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity);
+ TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot);
+ TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective);
+ TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d);
+ TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot);
+ TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d);
+
+ /* 3-D points */
+ TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general);
+ TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity);
+ TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot);
+ TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective);
+ TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d);
+ TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot);
+ TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d);
+
+ /* 4-D points */
+ TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general);
+ TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity);
+ TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot);
+ TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective);
+ TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d);
+ TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot);
+ TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d);
+
+#undef TAG_TAB
+#undef TAG_TAB_1
+#undef TAG_TAB_2
+#undef TAG_TAB_3
+#undef TAG_TAB_4
+}
diff --git a/mesalib/src/mesa/osmesa.pc.in b/mesalib/src/mesa/osmesa.pc.in
new file mode 100644
index 000000000..05327f40a
--- /dev/null
+++ b/mesalib/src/mesa/osmesa.pc.in
@@ -0,0 +1,12 @@
+prefix=@INSTALL_DIR@
+exec_prefix=${prefix}
+libdir=@INSTALL_LIB_DIR@
+includedir=@INSTALL_INC_DIR@
+
+Name: osmesa
+Description: Mesa Off-screen Rendering library
+Requires: @OSMESA_PC_REQ@
+Version: @VERSION@
+Libs: -L${libdir} -l@OSMESA_LIB@
+Libs.private: @OSMESA_PC_LIB_PRIV@
+Cflags: -I${includedir}
diff --git a/mesalib/src/mesa/shader/Makefile b/mesalib/src/mesa/shader/Makefile
new file mode 100644
index 000000000..400a543bd
--- /dev/null
+++ b/mesalib/src/mesa/shader/Makefile
@@ -0,0 +1,7 @@
+all: program_parse.tab.c lex.yy.c
+
+program_parse.tab.c program_parse.tab.h: program_parse.y
+ bison -v -d $<
+
+lex.yy.c: program_lexer.l
+ flex --never-interactive $<
diff --git a/mesalib/src/mesa/shader/arbprogparse.c b/mesalib/src/mesa/shader/arbprogparse.c
new file mode 100644
index 000000000..05ee4f563
--- /dev/null
+++ b/mesalib/src/mesa/shader/arbprogparse.c
@@ -0,0 +1,212 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+#define DEBUG_PARSING 0
+
+/**
+ * \file arbprogparse.c
+ * ARB_*_program parser core
+ * \author Karl Rasche
+ */
+
+/**
+Notes on program parameters, etc.
+
+The instructions we emit will use six kinds of source registers:
+
+ PROGRAM_INPUT - input registers
+ PROGRAM_TEMPORARY - temp registers
+ PROGRAM_ADDRESS - address/indirect register
+ PROGRAM_SAMPLER - texture sampler
+ PROGRAM_CONSTANT - indexes into program->Parameters, a known constant/literal
+ PROGRAM_STATE_VAR - indexes into program->Parameters, and may actually be:
+ + a state variable, like "state.fog.color", or
+ + a pointer to a "program.local[k]" parameter, or
+ + a pointer to a "program.env[k]" parameter
+
+Basically, all the program.local[] and program.env[] values will get mapped
+into the unified gl_program->Parameters array. This solves the problem of
+having three separate program parameter arrays.
+*/
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "shader/grammar/grammar_mesa.h"
+#include "arbprogparse.h"
+#include "program.h"
+#include "programopt.h"
+#include "prog_parameter.h"
+#include "prog_statevars.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+
+void
+_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct gl_fragment_program *program)
+{
+ struct gl_program prog;
+ struct asm_parser_state state;
+ GLuint i;
+
+ ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
+
+ memset(&prog, 0, sizeof(prog));
+ memset(&state, 0, sizeof(state));
+ state.prog = &prog;
+
+ if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len,
+ &state)) {
+ /* Error in the program. Just return. */
+ return;
+ }
+
+ /* Copy the relevant contents of the arb_program struct into the
+ * fragment_program struct.
+ */
+ program->Base.String = prog.String;
+ program->Base.NumInstructions = prog.NumInstructions;
+ program->Base.NumTemporaries = prog.NumTemporaries;
+ program->Base.NumParameters = prog.NumParameters;
+ program->Base.NumAttributes = prog.NumAttributes;
+ program->Base.NumAddressRegs = prog.NumAddressRegs;
+ program->Base.NumNativeInstructions = prog.NumNativeInstructions;
+ program->Base.NumNativeTemporaries = prog.NumNativeTemporaries;
+ program->Base.NumNativeParameters = prog.NumNativeParameters;
+ program->Base.NumNativeAttributes = prog.NumNativeAttributes;
+ program->Base.NumNativeAddressRegs = prog.NumNativeAddressRegs;
+ program->Base.NumAluInstructions = prog.NumAluInstructions;
+ program->Base.NumTexInstructions = prog.NumTexInstructions;
+ program->Base.NumTexIndirections = prog.NumTexIndirections;
+ program->Base.NumNativeAluInstructions = prog.NumAluInstructions;
+ program->Base.NumNativeTexInstructions = prog.NumTexInstructions;
+ program->Base.NumNativeTexIndirections = prog.NumTexIndirections;
+ program->Base.InputsRead = prog.InputsRead;
+ program->Base.OutputsWritten = prog.OutputsWritten;
+ for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
+ program->Base.TexturesUsed[i] = prog.TexturesUsed[i];
+ if (prog.TexturesUsed[i])
+ program->Base.SamplersUsed |= (1 << i);
+ }
+ program->Base.ShadowSamplers = prog.ShadowSamplers;
+ switch (state.option.Fog) {
+ case OPTION_FOG_EXP: program->FogOption = GL_EXP; break;
+ case OPTION_FOG_EXP2: program->FogOption = GL_EXP2; break;
+ case OPTION_FOG_LINEAR: program->FogOption = GL_LINEAR; break;
+ default: program->FogOption = GL_NONE; break;
+ }
+
+ program->UsesKill = state.fragment.UsesKill;
+
+ if (program->FogOption)
+ program->Base.InputsRead |= FRAG_BIT_FOGC;
+
+ if (program->Base.Instructions)
+ _mesa_free(program->Base.Instructions);
+ program->Base.Instructions = prog.Instructions;
+
+ if (program->Base.Parameters)
+ _mesa_free_parameter_list(program->Base.Parameters);
+ program->Base.Parameters = prog.Parameters;
+
+ /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
+ * or similar. We used to leave this up to drivers, but it appears
+ * there's no hardware that wants to do fog in a discrete stage separate
+ * from the fragment shader.
+ */
+ if (program->FogOption != GL_NONE) {
+ _mesa_append_fog_code(ctx, program);
+ program->FogOption = GL_NONE;
+ }
+
+#if DEBUG_FP
+ _mesa_printf("____________Fragment program %u ________\n", program->Base.Id);
+ _mesa_print_program(&program->Base);
+#endif
+}
+
+
+
+/**
+ * Parse the vertex program string. If success, update the given
+ * vertex_program object with the new program. Else, leave the vertex_program
+ * object unchanged.
+ */
+void
+_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct gl_vertex_program *program)
+{
+ struct gl_program prog;
+ struct asm_parser_state state;
+
+ ASSERT(target == GL_VERTEX_PROGRAM_ARB);
+
+ memset(&prog, 0, sizeof(prog));
+ memset(&state, 0, sizeof(state));
+ state.prog = &prog;
+
+ if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len,
+ &state)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramString(bad program)");
+ return;
+ }
+
+ /* Copy the relevant contents of the arb_program struct into the
+ * vertex_program struct.
+ */
+ program->Base.String = prog.String;
+ program->Base.NumInstructions = prog.NumInstructions;
+ program->Base.NumTemporaries = prog.NumTemporaries;
+ program->Base.NumParameters = prog.NumParameters;
+ program->Base.NumAttributes = prog.NumAttributes;
+ program->Base.NumAddressRegs = prog.NumAddressRegs;
+ program->Base.NumNativeInstructions = prog.NumNativeInstructions;
+ program->Base.NumNativeTemporaries = prog.NumNativeTemporaries;
+ program->Base.NumNativeParameters = prog.NumNativeParameters;
+ program->Base.NumNativeAttributes = prog.NumNativeAttributes;
+ program->Base.NumNativeAddressRegs = prog.NumNativeAddressRegs;
+ program->Base.InputsRead = prog.InputsRead;
+ program->Base.OutputsWritten = prog.OutputsWritten;
+ program->IsPositionInvariant = (state.option.PositionInvariant)
+ ? GL_TRUE : GL_FALSE;
+
+ if (program->Base.Instructions)
+ _mesa_free(program->Base.Instructions);
+ program->Base.Instructions = prog.Instructions;
+
+ if (program->Base.Parameters)
+ _mesa_free_parameter_list(program->Base.Parameters);
+ program->Base.Parameters = prog.Parameters;
+
+#if DEBUG_VP
+ _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
+ _mesa_print_program(&program->Base);
+#endif
+}
diff --git a/mesalib/src/mesa/shader/arbprogparse.h b/mesalib/src/mesa/shader/arbprogparse.h
new file mode 100644
index 000000000..980d39fb9
--- /dev/null
+++ b/mesalib/src/mesa/shader/arbprogparse.h
@@ -0,0 +1,41 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 ARBPROGPARSE_H
+#define ARBPROGPARSE_H
+
+#include "main/mtypes.h"
+
+extern void
+_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct gl_vertex_program *program);
+
+extern void
+_mesa_parse_arb_fragment_program(GLcontext *ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct gl_fragment_program *program);
+
+#endif
diff --git a/mesalib/src/mesa/shader/arbprogram.c b/mesalib/src/mesa/shader/arbprogram.c
new file mode 100644
index 000000000..4d8cff070
--- /dev/null
+++ b/mesalib/src/mesa/shader/arbprogram.c
@@ -0,0 +1,1042 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file arbprogram.c
+ * ARB_vertex/fragment_program state management functions.
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "arbprogram.h"
+#include "arbprogparse.h"
+#include "program.h"
+
+
+
+/**
+ * Mixing ARB and NV vertex/fragment programs can be tricky.
+ * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
+ * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
+ * The two different fragment program targets are supposed to be compatible
+ * to some extent (see GL_ARB_fragment_program spec).
+ * This function does the compatibility check.
+ */
+static GLboolean
+compatible_program_targets(GLenum t1, GLenum t2)
+{
+ if (t1 == t2)
+ return GL_TRUE;
+ if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
+ return GL_TRUE;
+ if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
+
+/**
+ * Bind a program (make it current)
+ * \note Called from the GL API dispatcher by both glBindProgramNV
+ * and glBindProgramARB.
+ */
+void GLAPIENTRY
+_mesa_BindProgram(GLenum target, GLuint id)
+{
+ struct gl_program *curProg, *newProg;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ /* Error-check target and get curProg */
+ if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
+ (ctx->Extensions.NV_vertex_program ||
+ ctx->Extensions.ARB_vertex_program)) {
+ curProg = &ctx->VertexProgram.Current->Base;
+ }
+ else if ((target == GL_FRAGMENT_PROGRAM_NV
+ && ctx->Extensions.NV_fragment_program) ||
+ (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program)) {
+ curProg = &ctx->FragmentProgram.Current->Base;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
+ return;
+ }
+
+ /*
+ * Get pointer to new program to bind.
+ * NOTE: binding to a non-existant program is not an error.
+ * That's supposed to be caught in glBegin.
+ */
+ if (id == 0) {
+ /* Bind a default program */
+ newProg = NULL;
+ if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
+ newProg = &ctx->Shared->DefaultVertexProgram->Base;
+ else
+ newProg = &ctx->Shared->DefaultFragmentProgram->Base;
+ }
+ else {
+ /* Bind a user program */
+ newProg = _mesa_lookup_program(ctx, id);
+ if (!newProg || newProg == &_mesa_DummyProgram) {
+ /* allocate a new program now */
+ newProg = ctx->Driver.NewProgram(ctx, target, id);
+ if (!newProg) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
+ }
+ else if (!compatible_program_targets(newProg->Target, target)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindProgramNV/ARB(target mismatch)");
+ return;
+ }
+ }
+
+ /** All error checking is complete now **/
+
+ if (curProg->Id == id) {
+ /* binding same program - no change */
+ return;
+ }
+
+ /* signal new program (and its new constants) */
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
+ /* bind newProg */
+ if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ (struct gl_vertex_program *) newProg);
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_NV ||
+ target == GL_FRAGMENT_PROGRAM_ARB) {
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ (struct gl_fragment_program *) newProg);
+ }
+
+ /* Never null pointers */
+ ASSERT(ctx->VertexProgram.Current);
+ ASSERT(ctx->FragmentProgram.Current);
+
+ if (ctx->Driver.BindProgram)
+ ctx->Driver.BindProgram(ctx, target, newProg);
+}
+
+
+/**
+ * Delete a list of programs.
+ * \note Not compiled into display lists.
+ * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
+ */
+void GLAPIENTRY
+_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ if (n < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (ids[i] != 0) {
+ struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
+ if (prog == &_mesa_DummyProgram) {
+ _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+ }
+ else if (prog) {
+ /* Unbind program if necessary */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
+ prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
+ if (ctx->VertexProgram.Current &&
+ ctx->VertexProgram.Current->Base.Id == ids[i]) {
+ /* unbind this currently bound program */
+ _mesa_BindProgram(prog->Target, 0);
+ }
+ }
+ else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
+ prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ if (ctx->FragmentProgram.Current &&
+ ctx->FragmentProgram.Current->Base.Id == ids[i]) {
+ /* unbind this currently bound program */
+ _mesa_BindProgram(prog->Target, 0);
+ }
+ }
+ else {
+ _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
+ return;
+ }
+ /* The ID is immediately available for re-use now */
+ _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
+ _mesa_reference_program(ctx, &prog, NULL);
+ }
+ }
+ }
+}
+
+
+/**
+ * Generate a list of new program identifiers.
+ * \note Not compiled into display lists.
+ * \note Called by both glGenProgramsNV and glGenProgramsARB.
+ */
+void GLAPIENTRY
+_mesa_GenPrograms(GLsizei n, GLuint *ids)
+{
+ GLuint first;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
+ return;
+ }
+
+ if (!ids)
+ return;
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
+
+ /* Insert pointer to dummy program as placeholder */
+ for (i = 0; i < (GLuint) n; i++) {
+ _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
+ }
+
+ /* Return the program names */
+ for (i = 0; i < (GLuint) n; i++) {
+ ids[i] = first + i;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_EnableVertexAttribArrayARB(GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glEnableVertexAttribArrayARB(index)");
+ return;
+ }
+
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
+ ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
+ ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
+}
+
+
+void GLAPIENTRY
+_mesa_DisableVertexAttribArrayARB(GLuint index)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glEnableVertexAttribArrayARB(index)");
+ return;
+ }
+
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
+ ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
+ ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
+{
+ GLfloat fparams[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_GetVertexAttribfvARB(index, pname, fparams);
+ if (ctx->ErrorValue == GL_NO_ERROR) {
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ COPY_4V(params, fparams);
+ }
+ else {
+ params[0] = fparams[0];
+ }
+ }
+}
+
+
+/**
+ * Return info for a generic vertex attribute array (no alias with
+ * legacy vertex attributes (pos, normal, color, etc)).
+ */
+void GLAPIENTRY
+_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
+{
+ const struct gl_client_array *array;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
+ return;
+ }
+
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
+ switch (pname) {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
+ params[0] = (GLfloat) array->Enabled;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
+ params[0] = (GLfloat) array->Size;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
+ params[0] = (GLfloat) array->Stride;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
+ params[0] = (GLfloat) array->Type;
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
+ params[0] = array->Normalized;
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB_ARB:
+ if (index == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexAttribfvARB(index==0)");
+ return;
+ }
+ FLUSH_CURRENT(ctx, 0);
+ COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = (GLfloat) array->BufferObj->Name;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
+{
+ GLfloat fparams[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_GetVertexAttribfvARB(index, pname, fparams);
+ if (ctx->ErrorValue == GL_NO_ERROR) {
+ if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
+ COPY_4V_CAST(params, fparams, GLint); /* float to int */
+ }
+ else {
+ params[0] = (GLint) fparams[0];
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
+ return;
+ }
+
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
+ return;
+ }
+
+ ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
+
+ *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
+}
+
+
+/**
+ * Determine if id names a vertex or fragment program.
+ * \note Not compiled into display lists.
+ * \note Called from both glIsProgramNV and glIsProgramARB.
+ * \param id is the program identifier
+ * \return GL_TRUE if id is a program, else GL_FALSE.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsProgramARB(GLuint id)
+{
+ struct gl_program *prog = NULL;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (id == 0)
+ return GL_FALSE;
+
+ prog = _mesa_lookup_program(ctx, id);
+ if (prog && (prog != &_mesa_DummyProgram))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
+ const GLvoid *string)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
+ return;
+ }
+
+ if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ struct gl_vertex_program *prog = ctx->VertexProgram.Current;
+ _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
+
+ if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
+ _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
+
+ if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
+ return;
+ }
+}
+
+
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ * Note, this function is also used by the GL_NV_vertex_program extension
+ * (alias to ProgramParameterdNV)
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
+}
+
+
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ * Note, this function is also used by the GL_NV_vertex_program extension
+ * (alias to ProgramParameterdvNV)
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
+{
+ _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
+ (GLfloat) params[1], (GLfloat) params[2],
+ (GLfloat) params[3]);
+}
+
+
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ * Note, this function is also used by the GL_NV_vertex_program extension
+ * (alias to ProgramParameterfNV)
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
+ return;
+ }
+ ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */
+ && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) {
+ if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
+ return;
+ }
+ ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
+ return;
+ }
+}
+
+/**
+ * Set a program env parameter register.
+ * \note Called from the GL API dispatcher.
+ * Note, this function is also used by the GL_NV_vertex_program extension
+ * (alias to ProgramParameterfvNV)
+ */
+void GLAPIENTRY
+_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
+{
+ _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
+ params[2], params[3]);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+ GLfloat * dest;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ if (count <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
+ return;
+ }
+ dest = ctx->FragmentProgram.Parameters[index];
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
+ return;
+ }
+ dest = ctx->VertexProgram.Parameters[index];
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
+ return;
+ }
+
+ for ( i = 0 ; i < count ; i++ ) {
+ COPY_4V(dest, params);
+ params += 4;
+ dest += 4;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
+ GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat fparams[4];
+
+ _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
+ if (ctx->ErrorValue == GL_NO_ERROR) {
+ params[0] = fparams[0];
+ params[1] = fparams[1];
+ params[2] = fparams[2];
+ params[3] = fparams[3];
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
+ return;
+ }
+ COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
+ return;
+ }
+ COPY_4V(params, ctx->VertexProgram.Parameters[index]);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
+ return;
+ }
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_program *prog;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ if ((target == GL_FRAGMENT_PROGRAM_NV
+ && ctx->Extensions.NV_fragment_program) ||
+ (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program)) {
+ if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
+ return;
+ }
+ prog = &(ctx->FragmentProgram.Current->Base);
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
+ return;
+ }
+ prog = &(ctx->VertexProgram.Current->Base);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
+ return;
+ }
+
+ ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
+ prog->LocalParams[index][0] = x;
+ prog->LocalParams[index][1] = y;
+ prog->LocalParams[index][2] = z;
+ prog->LocalParams[index][3] = w;
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params)
+{
+ _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
+ params[2], params[3]);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_program *prog;
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ if (count <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
+ }
+
+ if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
+ return;
+ }
+ prog = &(ctx->FragmentProgram.Current->Base);
+ }
+ else if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
+ return;
+ }
+ prog = &(ctx->VertexProgram.Current->Base);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
+ COPY_4V(prog->LocalParams[index + i], params);
+ params += 4;
+ }
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y,
+ GLdouble z, GLdouble w)
+{
+ _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
+ (GLfloat) z, (GLfloat) w);
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params)
+{
+ _mesa_ProgramLocalParameter4fARB(target, index,
+ (GLfloat) params[0], (GLfloat) params[1],
+ (GLfloat) params[2], (GLfloat) params[3]);
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params)
+{
+ const struct gl_program *prog;
+ GLuint maxParams;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ prog = &(ctx->VertexProgram.Current->Base);
+ maxParams = ctx->Const.VertexProgram.MaxLocalParams;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ prog = &(ctx->FragmentProgram.Current->Base);
+ maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_NV
+ && ctx->Extensions.NV_fragment_program) {
+ prog = &(ctx->FragmentProgram.Current->Base);
+ maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetProgramLocalParameterARB(target)");
+ return;
+ }
+
+ if (index >= maxParams) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramLocalParameterARB(index)");
+ return;
+ }
+
+ ASSERT(prog);
+ ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
+ COPY_4V(params, prog->LocalParams[index]);
+}
+
+
+/**
+ * Note, this function is also used by the GL_NV_fragment_program extension.
+ */
+void GLAPIENTRY
+_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
+ GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLfloat floatParams[4];
+ ASSIGN_4V(floatParams, 0.0F, 0.0F, 0.0F, 0.0F);
+ _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
+ if (ctx->ErrorValue == GL_NO_ERROR) {
+ COPY_4V(params, floatParams);
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
+{
+ const struct gl_program_constants *limits;
+ struct gl_program *prog;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_ARB
+ && ctx->Extensions.ARB_vertex_program) {
+ prog = &(ctx->VertexProgram.Current->Base);
+ limits = &ctx->Const.VertexProgram;
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB
+ && ctx->Extensions.ARB_fragment_program) {
+ prog = &(ctx->FragmentProgram.Current->Base);
+ limits = &ctx->Const.FragmentProgram;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
+ return;
+ }
+
+ ASSERT(prog);
+ ASSERT(limits);
+
+ /* Queries supported for both vertex and fragment programs */
+ switch (pname) {
+ case GL_PROGRAM_LENGTH_ARB:
+ *params
+ = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
+ return;
+ case GL_PROGRAM_FORMAT_ARB:
+ *params = prog->Format;
+ return;
+ case GL_PROGRAM_BINDING_ARB:
+ *params = prog->Id;
+ return;
+ case GL_PROGRAM_INSTRUCTIONS_ARB:
+ *params = prog->NumInstructions;
+ return;
+ case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
+ *params = limits->MaxInstructions;
+ return;
+ case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
+ *params = prog->NumNativeInstructions;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
+ *params = limits->MaxNativeInstructions;
+ return;
+ case GL_PROGRAM_TEMPORARIES_ARB:
+ *params = prog->NumTemporaries;
+ return;
+ case GL_MAX_PROGRAM_TEMPORARIES_ARB:
+ *params = limits->MaxTemps;
+ return;
+ case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
+ *params = prog->NumNativeTemporaries;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
+ *params = limits->MaxNativeTemps;
+ return;
+ case GL_PROGRAM_PARAMETERS_ARB:
+ *params = prog->NumParameters;
+ return;
+ case GL_MAX_PROGRAM_PARAMETERS_ARB:
+ *params = limits->MaxParameters;
+ return;
+ case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
+ *params = prog->NumNativeParameters;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
+ *params = limits->MaxNativeParameters;
+ return;
+ case GL_PROGRAM_ATTRIBS_ARB:
+ *params = prog->NumAttributes;
+ return;
+ case GL_MAX_PROGRAM_ATTRIBS_ARB:
+ *params = limits->MaxAttribs;
+ return;
+ case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
+ *params = prog->NumNativeAttributes;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
+ *params = limits->MaxNativeAttribs;
+ return;
+ case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
+ *params = prog->NumAddressRegs;
+ return;
+ case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
+ *params = limits->MaxAddressRegs;
+ return;
+ case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
+ *params = prog->NumNativeAddressRegs;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
+ *params = limits->MaxNativeAddressRegs;
+ return;
+ case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
+ *params = limits->MaxLocalParams;
+ return;
+ case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
+ *params = limits->MaxEnvParams;
+ return;
+ case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
+ /*
+ * XXX we may not really need a driver callback here.
+ * If the number of native instructions, registers, etc. used
+ * are all below the maximums, we could return true.
+ * The spec says that even if this query returns true, there's
+ * no guarantee that the program will run in hardware.
+ */
+ if (prog->Id == 0) {
+ /* default/null program */
+ *params = GL_FALSE;
+ }
+ else if (ctx->Driver.IsProgramNative) {
+ /* ask the driver */
+ *params = ctx->Driver.IsProgramNative( ctx, target, prog );
+ }
+ else {
+ /* probably running in software */
+ *params = GL_TRUE;
+ }
+ return;
+ default:
+ /* continue with fragment-program only queries below */
+ break;
+ }
+
+ /*
+ * The following apply to fragment programs only (at this time)
+ */
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
+ switch (pname) {
+ case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
+ *params = fp->Base.NumNativeAluInstructions;
+ return;
+ case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
+ *params = fp->Base.NumAluInstructions;
+ return;
+ case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
+ *params = fp->Base.NumTexInstructions;
+ return;
+ case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
+ *params = fp->Base.NumNativeTexInstructions;
+ return;
+ case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
+ *params = fp->Base.NumTexIndirections;
+ return;
+ case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
+ *params = fp->Base.NumNativeTexIndirections;
+ return;
+ case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
+ *params = limits->MaxAluInstructions;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
+ *params = limits->MaxNativeAluInstructions;
+ return;
+ case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
+ *params = limits->MaxTexInstructions;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
+ *params = limits->MaxNativeTexInstructions;
+ return;
+ case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
+ *params = limits->MaxTexIndirections;
+ return;
+ case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
+ *params = limits->MaxNativeTexIndirections;
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
+ return;
+ }
+ } else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
+{
+ const struct gl_program *prog;
+ char *dst = (char *) string;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ prog = &(ctx->VertexProgram.Current->Base);
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ prog = &(ctx->FragmentProgram.Current->Base);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
+ return;
+ }
+
+ ASSERT(prog);
+
+ if (pname != GL_PROGRAM_STRING_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
+ return;
+ }
+
+ if (prog->String)
+ _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
+ else
+ *dst = '\0';
+}
diff --git a/mesalib/src/mesa/shader/arbprogram.h b/mesalib/src/mesa/shader/arbprogram.h
new file mode 100644
index 000000000..6fe76267b
--- /dev/null
+++ b/mesalib/src/mesa/shader/arbprogram.h
@@ -0,0 +1,152 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 ARBPROGRAM_H
+#define ARBPROGRAM_H
+
+
+extern void GLAPIENTRY
+_mesa_BindProgram(GLenum target, GLuint id);
+
+extern void GLAPIENTRY
+_mesa_DeletePrograms(GLsizei n, const GLuint *ids);
+
+extern void GLAPIENTRY
+_mesa_GenPrograms(GLsizei n, GLuint *ids);
+
+
+extern void GLAPIENTRY
+_mesa_EnableVertexAttribArrayARB(GLuint index);
+
+
+extern void GLAPIENTRY
+_mesa_DisableVertexAttribArrayARB(GLuint index);
+
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer);
+
+
+extern GLboolean GLAPIENTRY
+_mesa_IsProgramARB(GLuint id);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
+ const GLvoid *string);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
+ GLdouble x, GLdouble y,
+ GLdouble z, GLdouble w);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
+ const GLdouble *params);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
+ const GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
+ const GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
+ GLdouble *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
+ GLdouble *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
+ GLfloat *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params);
+
+
+extern void GLAPIENTRY
+_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string);
+
+
+#endif
diff --git a/mesalib/src/mesa/shader/atifragshader.c b/mesalib/src/mesa/shader/atifragshader.c
new file mode 100644
index 000000000..ac087d415
--- /dev/null
+++ b/mesalib/src/mesa/shader/atifragshader.c
@@ -0,0 +1,759 @@
+/**
+ * \file atifragshader.c
+ * \author David Airlie
+ * Copyright (C) 2004 David Airlie 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
+ * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
+#include "atifragshader.h"
+
+#define MESA_DEBUG_ATI_FS 0
+
+static struct ati_fragment_shader DummyShader;
+
+
+/**
+ * Allocate and initialize a new ATI fragment shader object.
+ */
+struct ati_fragment_shader *
+_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id)
+{
+ struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
+ (void) ctx;
+ if (s) {
+ s->Id = id;
+ s->RefCount = 1;
+ }
+ return s;
+}
+
+
+/**
+ * Delete the given ati fragment shader
+ */
+void
+_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s)
+{
+ GLuint i;
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ if (s->Instructions[i])
+ _mesa_free(s->Instructions[i]);
+ if (s->SetupInst[i])
+ _mesa_free(s->SetupInst[i]);
+ }
+ _mesa_free(s);
+}
+
+
+
+static void
+new_arith_inst(struct ati_fragment_shader *prog)
+{
+/* set "default" instruction as not all may get defined.
+ there is no specified way to express a nop with ati fragment shaders we use
+ GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
+ prog->numArithInstr[prog->cur_pass >> 1]++;
+}
+
+static void
+new_tex_inst(struct ati_fragment_shader *prog)
+{
+}
+
+static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
+{
+ if (optype == curProg->last_optype) {
+ curProg->last_optype = 1;
+ }
+}
+
+#if MESA_DEBUG_ATI_FS
+static char *
+create_dst_mod_str(GLuint mod)
+{
+ static char ret_str[1024];
+
+ _mesa_memset(ret_str, 0, 1024);
+ if (mod & GL_2X_BIT_ATI)
+ _mesa_strncat(ret_str, "|2X", 1024);
+
+ if (mod & GL_4X_BIT_ATI)
+ _mesa_strncat(ret_str, "|4X", 1024);
+
+ if (mod & GL_8X_BIT_ATI)
+ _mesa_strncat(ret_str, "|8X", 1024);
+ if (mod & GL_HALF_BIT_ATI)
+ _mesa_strncat(ret_str, "|HA", 1024);
+ if (mod & GL_QUARTER_BIT_ATI)
+ _mesa_strncat(ret_str, "|QU", 1024);
+ if (mod & GL_EIGHTH_BIT_ATI)
+ _mesa_strncat(ret_str, "|EI", 1024);
+
+ if (mod & GL_SATURATE_BIT_ATI)
+ _mesa_strncat(ret_str, "|SAT", 1024);
+
+ if (_mesa_strlen(ret_str) == 0)
+ _mesa_strncat(ret_str, "NONE", 1024);
+ return ret_str;
+}
+
+static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
+ "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
+
+static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
+ GLuint dstMask, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
+ GLuint arg3Rep, GLuint arg3Mod)
+{
+ char *op_name;
+
+ op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
+
+ fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
+ _mesa_lookup_enum_by_nr(dst));
+ if (!optype)
+ fprintf(stderr, ", %d", dstMask);
+
+ fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
+
+ fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
+ _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
+ if (arg_count>1)
+ fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
+ _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
+ if (arg_count>2)
+ fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
+ _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
+
+ fprintf(stderr,")\n");
+
+}
+#endif
+
+static int check_arith_arg(struct ati_fragment_shader *curProg,
+ GLuint optype, GLuint arg, GLuint argRep)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
+ ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
+ (arg != GL_ZERO) && (arg != GL_ONE) &&
+ (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
+ return 0;
+ }
+ if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
+ ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
+ return 0;
+ }
+ if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
+ ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
+ return 0;
+ }
+ if ((curProg->cur_pass == 1) &&
+ ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
+ curProg->interpinp1 = GL_TRUE;
+ }
+ return 1;
+}
+
+GLuint GLAPIENTRY
+_mesa_GenFragmentShadersATI(GLuint range)
+{
+ GLuint first;
+ GLuint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (range == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
+ return 0;
+ }
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
+ return 0;
+ }
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
+ for (i = 0; i < range; i++) {
+ _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
+ }
+
+ return first;
+}
+
+void GLAPIENTRY
+_mesa_BindFragmentShaderATI(GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ struct ati_fragment_shader *newProg;
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ if (curProg->Id == id) {
+ return;
+ }
+
+ /* unbind current */
+ if (curProg->Id != 0) {
+ curProg->RefCount--;
+ if (curProg->RefCount <= 0) {
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
+ }
+ }
+
+ /* find new shader */
+ if (id == 0) {
+ newProg = ctx->Shared->DefaultFragmentShader;
+ }
+ else {
+ newProg = (struct ati_fragment_shader *)
+ _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+ if (!newProg || newProg == &DummyShader) {
+ /* allocate a new program now */
+ newProg = _mesa_new_ati_fragment_shader(ctx, id);
+ if (!newProg) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
+ }
+
+ }
+
+ /* do actual bind */
+ ctx->ATIFragmentShader.Current = newProg;
+
+ ASSERT(ctx->ATIFragmentShader.Current);
+ if (newProg)
+ newProg->RefCount++;
+
+ /*if (ctx->Driver.BindProgram)
+ ctx->Driver.BindProgram(ctx, target, prog); */
+}
+
+void GLAPIENTRY
+_mesa_DeleteFragmentShaderATI(GLuint id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
+ return;
+ }
+
+ if (id != 0) {
+ struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
+ _mesa_HashLookup(ctx->Shared->ATIShaders, id);
+ if (prog == &DummyShader) {
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
+ }
+ else if (prog) {
+ if (ctx->ATIFragmentShader.Current &&
+ ctx->ATIFragmentShader.Current->Id == id) {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ _mesa_BindFragmentShaderATI(0);
+ }
+ }
+
+ /* The ID is immediately available for re-use now */
+ _mesa_HashRemove(ctx->Shared->ATIShaders, id);
+ prog->RefCount--;
+ if (prog->RefCount <= 0) {
+ _mesa_free(prog);
+ }
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_BeginFragmentShaderATI(void)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ /* if the shader was already defined free instructions and get new ones
+ (or, could use the same mem but would need to reinitialize) */
+ /* no idea if it's allowed to redefine a shader */
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ if (ctx->ATIFragmentShader.Current->Instructions[i])
+ _mesa_free(ctx->ATIFragmentShader.Current->Instructions[i]);
+ if (ctx->ATIFragmentShader.Current->SetupInst[i])
+ _mesa_free(ctx->ATIFragmentShader.Current->SetupInst[i]);
+ }
+
+ /* malloc the instructions here - not sure if the best place but its
+ a start */
+ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
+ ctx->ATIFragmentShader.Current->Instructions[i] =
+ (struct atifs_instruction *)
+ _mesa_calloc(sizeof(struct atifs_instruction) *
+ (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
+ ctx->ATIFragmentShader.Current->SetupInst[i] =
+ (struct atifs_setupinst *)
+ _mesa_calloc(sizeof(struct atifs_setupinst) *
+ (MAX_NUM_FRAGMENT_REGISTERS_ATI));
+ }
+
+/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
+ ctx->ATIFragmentShader.Current->LocalConstDef = 0;
+ ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
+ ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
+ ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
+ ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
+ ctx->ATIFragmentShader.Current->NumPasses = 0;
+ ctx->ATIFragmentShader.Current->cur_pass = 0;
+ ctx->ATIFragmentShader.Current->last_optype = 0;
+ ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
+ ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
+ ctx->ATIFragmentShader.Current->swizzlerq = 0;
+ ctx->ATIFragmentShader.Compiling = 1;
+}
+
+void GLAPIENTRY
+_mesa_EndFragmentShaderATI(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+#if MESA_DEBUG_ATI_FS
+ GLint i, j;
+#endif
+
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
+ return;
+ }
+ if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
+ /* according to spec, DON'T return here */
+ }
+
+ match_pair_inst(curProg, 0);
+ ctx->ATIFragmentShader.Compiling = 0;
+ ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
+ if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
+ (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
+ }
+ if (ctx->ATIFragmentShader.Current->cur_pass > 1)
+ ctx->ATIFragmentShader.Current->NumPasses = 2;
+ else ctx->ATIFragmentShader.Current->NumPasses = 1;
+ ctx->ATIFragmentShader.Current->cur_pass=0;
+#if MESA_DEBUG_ATI_FS
+ for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
+ for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
+ GLuint op = curProg->SetupInst[j][i].Opcode;
+ const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
+ GLuint src = curProg->SetupInst[j][i].src;
+ GLuint swizzle = curProg->SetupInst[j][i].swizzle;
+ fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
+ swizzle);
+ }
+ for (i = 0; i < curProg->numArithInstr[j]; i++) {
+ GLuint op0 = curProg->Instructions[j][i].Opcode[0];
+ GLuint op1 = curProg->Instructions[j][i].Opcode[1];
+ const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
+ const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
+ GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
+ GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
+ fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
+ op1, op1_enum, count1);
+ }
+ }
+#endif
+ if (ctx->Driver.ProgramStringNotify)
+ ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL );
+}
+
+void GLAPIENTRY
+_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ struct atifs_setupinst *curI;
+
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
+ return;
+ }
+
+ if (curProg->cur_pass == 1) {
+ match_pair_inst(curProg, 0);
+ curProg->cur_pass = 2;
+ }
+ if ((curProg->cur_pass > 2) ||
+ ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
+ return;
+ }
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+ ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
+ return;
+ }
+ if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
+ ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
+ ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
+ return;
+ }
+ if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
+ return;
+ }
+ if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
+ return;
+ }
+ if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
+ return;
+ }
+ if (coord <= GL_TEXTURE7_ARB) {
+ GLuint tmp = coord - GL_TEXTURE0_ARB;
+ if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+ (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
+ return;
+ } else {
+ curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
+ }
+ }
+
+ curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
+ new_tex_inst(curProg);
+
+ /* add the instructions */
+ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
+
+ curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
+ curI->src = coord;
+ curI->swizzle = swizzle;
+
+#if MESA_DEBUG_ATI_FS
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
+ _mesa_lookup_enum_by_nr(swizzle));
+#endif
+}
+
+void GLAPIENTRY
+_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ struct atifs_setupinst *curI;
+
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
+ return;
+ }
+
+ if (curProg->cur_pass == 1) {
+ match_pair_inst(curProg, 0);
+ curProg->cur_pass = 2;
+ }
+ if ((curProg->cur_pass > 2) ||
+ ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
+ return;
+ }
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
+ ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
+ return;
+ }
+ if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
+ ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
+ ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
+ /* is this texture5 or texture7? spec is a bit unclear there */
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
+ return;
+ }
+ if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
+ return;
+ }
+ if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
+ return;
+ }
+ if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
+ return;
+ }
+ if (interp <= GL_TEXTURE7_ARB) {
+ GLuint tmp = interp - GL_TEXTURE0_ARB;
+ if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
+ (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
+ return;
+ } else {
+ curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
+ }
+ }
+
+ curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
+ new_tex_inst(curProg);
+
+ /* add the instructions */
+ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
+
+ curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
+ curI->src = interp;
+ curI->swizzle = swizzle;
+
+#if MESA_DEBUG_ATI_FS
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
+ _mesa_lookup_enum_by_nr(swizzle));
+#endif
+}
+
+static void
+_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
+ GLuint dstMask, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
+ GLuint arg3Rep, GLuint arg3Mod)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ GLint ci;
+ struct atifs_instruction *curI;
+ GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
+
+ if (!ctx->ATIFragmentShader.Compiling) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
+ return;
+ }
+
+ if (curProg->cur_pass==0)
+ curProg->cur_pass=1;
+
+ else if (curProg->cur_pass==2)
+ curProg->cur_pass=3;
+
+ /* decide whether this is a new instruction or not ... all color instructions are new,
+ and alpha instructions might also be new if there was no preceding color inst */
+ if ((optype == 0) || (curProg->last_optype == optype)) {
+ if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
+ return;
+ }
+ /* easier to do that here slight side effect invalid instr will still be inserted as nops */
+ match_pair_inst(curProg, optype);
+ new_arith_inst(curProg);
+ }
+ curProg->last_optype = optype;
+ ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
+
+ /* add the instructions */
+ curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
+
+ /* error checking */
+ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
+ return;
+ }
+ if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
+ (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
+ (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
+ (modtemp != GL_EIGHTH_BIT_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
+ return;
+ }
+ /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
+ if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
+ return;
+ }
+ if (optype == 1) {
+ if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
+ ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
+ ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
+ ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
+ return;
+ }
+ }
+ if ((op == GL_DOT4_ATI) &&
+ (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
+ (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
+ }
+
+ if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
+ return;
+ }
+ if (arg2) {
+ if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
+ return;
+ }
+ }
+ if (arg3) {
+ if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
+ return;
+ }
+ if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
+ (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
+ (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
+ (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
+ return;
+ }
+ }
+
+ /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
+
+ curI->Opcode[optype] = op;
+ curI->SrcReg[optype][0].Index = arg1;
+ curI->SrcReg[optype][0].argRep = arg1Rep;
+ curI->SrcReg[optype][0].argMod = arg1Mod;
+ curI->ArgCount[optype] = arg_count;
+
+ if (arg2) {
+ curI->SrcReg[optype][1].Index = arg2;
+ curI->SrcReg[optype][1].argRep = arg2Rep;
+ curI->SrcReg[optype][1].argMod = arg2Mod;
+ }
+
+ if (arg3) {
+ curI->SrcReg[optype][2].Index = arg3;
+ curI->SrcReg[optype][2].argRep = arg3Rep;
+ curI->SrcReg[optype][2].argMod = arg3Mod;
+ }
+
+ curI->DstReg[optype].Index = dst;
+ curI->DstReg[optype].dstMod = dstMod;
+ curI->DstReg[optype].dstMask = dstMask;
+
+#if MESA_DEBUG_ATI_FS
+ debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
+#endif
+
+}
+
+void GLAPIENTRY
+_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
+ dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
+}
+
+void GLAPIENTRY
+_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
+ GLuint arg2Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
+ dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
+ arg2Mod, 0, 0, 0);
+}
+
+void GLAPIENTRY
+_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
+ GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
+ GLuint arg3Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
+ dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
+ arg2Mod, arg3, arg3Rep, arg3Mod);
+}
+
+void GLAPIENTRY
+_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
+ arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
+}
+
+void GLAPIENTRY
+_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
+ arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
+ 0);
+}
+
+void GLAPIENTRY
+_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
+ GLuint arg3Rep, GLuint arg3Mod)
+{
+ _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
+ arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
+ arg3Rep, arg3Mod);
+}
+
+void GLAPIENTRY
+_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
+{
+ GLuint dstindex;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
+ /* spec says nothing about what should happen here but we can't just segfault...*/
+ _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
+ return;
+ }
+
+ dstindex = dst - GL_CON_0_ATI;
+ if (ctx->ATIFragmentShader.Compiling) {
+ struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
+ COPY_4V(curProg->Constants[dstindex], value);
+ curProg->LocalConstDef |= 1 << dstindex;
+ }
+ else {
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
+ }
+}
diff --git a/mesalib/src/mesa/shader/atifragshader.h b/mesalib/src/mesa/shader/atifragshader.h
new file mode 100644
index 000000000..e1dc20e60
--- /dev/null
+++ b/mesalib/src/mesa/shader/atifragshader.h
@@ -0,0 +1,123 @@
+/*
+ * Mesa 3-D graphics library ATI Fragment Shader
+ *
+ * Copyright (C) 2004 David Airlie All Rights Reserved.
+ *
+ */
+
+#ifndef ATIFRAGSHADER_H
+#define ATIFRAGSHADER_H
+
+#include "main/mtypes.h"
+
+#define MAX_NUM_INSTRUCTIONS_PER_PASS_ATI 8
+#define MAX_NUM_PASSES_ATI 2
+#define MAX_NUM_FRAGMENT_REGISTERS_ATI 6
+
+struct ati_fs_opcode_st
+{
+ GLenum opcode;
+ GLint num_src_args;
+};
+
+extern struct ati_fs_opcode_st ati_fs_opcodes[];
+
+struct atifragshader_src_register
+{
+ GLuint Index;
+ GLuint argRep;
+ GLuint argMod;
+};
+
+struct atifragshader_dst_register
+{
+ GLuint Index;
+ GLuint dstMod;
+ GLuint dstMask;
+};
+
+#define ATI_FRAGMENT_SHADER_COLOR_OP 0
+#define ATI_FRAGMENT_SHADER_ALPHA_OP 1
+#define ATI_FRAGMENT_SHADER_PASS_OP 2
+#define ATI_FRAGMENT_SHADER_SAMPLE_OP 3
+
+/* two opcodes - one for color/one for alpha */
+/* up to three source registers for most ops */
+struct atifs_instruction
+{
+ GLenum Opcode[2];
+ GLuint ArgCount[2];
+ struct atifragshader_src_register SrcReg[2][3];
+ struct atifragshader_dst_register DstReg[2];
+};
+
+/* different from arithmetic shader instruction */
+struct atifs_setupinst
+{
+ GLenum Opcode;
+ GLuint src;
+ GLenum swizzle;
+};
+
+
+extern struct ati_fragment_shader *
+_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id);
+
+extern void
+_mesa_delete_ati_fragment_shader(GLcontext *ctx,
+ struct ati_fragment_shader *s);
+
+
+extern GLuint GLAPIENTRY _mesa_GenFragmentShadersATI(GLuint range);
+
+extern void GLAPIENTRY _mesa_BindFragmentShaderATI(GLuint id);
+
+extern void GLAPIENTRY _mesa_DeleteFragmentShaderATI(GLuint id);
+
+extern void GLAPIENTRY _mesa_BeginFragmentShaderATI(void);
+
+extern void GLAPIENTRY _mesa_EndFragmentShaderATI(void);
+
+extern void GLAPIENTRY
+_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle);
+
+extern void GLAPIENTRY
+_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle);
+
+extern void GLAPIENTRY
+_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod);
+
+extern void GLAPIENTRY
+_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
+ GLuint arg2Mod);
+
+extern void GLAPIENTRY
+_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
+ GLuint dstMod, GLuint arg1, GLuint arg1Rep,
+ GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
+ GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
+ GLuint arg3Mod);
+
+extern void GLAPIENTRY
+_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod);
+
+extern void GLAPIENTRY
+_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod);
+
+extern void GLAPIENTRY
+_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
+ GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
+ GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
+ GLuint arg3Rep, GLuint arg3Mod);
+
+extern void GLAPIENTRY
+_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value);
+
+#endif
diff --git a/mesalib/src/mesa/shader/descrip.mms b/mesalib/src/mesa/shader/descrip.mms
new file mode 100644
index 000000000..19bafd483
--- /dev/null
+++ b/mesalib/src/mesa/shader/descrip.mms
@@ -0,0 +1,95 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 29 September 2008
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define swrast [-.swrast]
+ define array_cache [-.array_cache]
+ define glapi [-.glapi]
+ define main [-.main]
+ define shader [-.shader]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[.grammar],[-.main],[-.glapi],[.slang]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1,"__extension__=")/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = \
+ atifragshader.c \
+ arbprogparse.c \
+ arbprogram.c \
+ nvfragparse.c \
+ nvprogram.c \
+ nvvertparse.c \
+ program.c \
+ programopt.c \
+ prog_debug.c \
+ prog_execute.c \
+ prog_instruction.c \
+ prog_parameter.c \
+ prog_print.c \
+ prog_cache.c \
+ prog_statevars.c \
+ shader_api.c prog_uniform.c
+
+OBJECTS = \
+ atifragshader.obj,\
+ arbprogparse.obj,\
+ arbprogram.obj,\
+ nvfragparse.obj,\
+ nvprogram.obj,\
+ nvvertparse.obj,\
+ program.obj,\
+ programopt.obj,\
+ prog_debug.obj,\
+ prog_execute.obj,\
+ prog_instruction.obj,\
+ prog_parameter.obj,\
+ prog_print.obj,\
+ prog_statevars.obj,\
+ shader_api.obj,prog_uniform.obj,prog_cache.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+all :
+ $(MMS)$(MMSQUALIFIERS) $(LIBDIR)$(GL_LIB)
+ set def [.slang]
+ $(MMS)$(MMSQUALIFIERS)
+ set def [-.grammar]
+ $(MMS)$(MMSQUALIFIERS)
+ set def [-]
+
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+atifragshader.obj : atifragshader.c
+arbprogparse.obj : arbprogparse.c
+arbprogram.obj : arbprogram.c
+nvfragparse.obj : nvfragparse.c
+nvprogram.obj : nvprogram.c
+nvvertparse.obj : nvvertparse.c
+program.obj : program.c
+programopt. obj : programopt.c
+prog_debug.obj : prog_debug.c
+prog_execute.obj : prog_execute.c
+prog_instruction.obj : prog_instruction.c
+prog_parameter.obj : prog_parameter.c
+prog_print.obj : prog_print.c
+prog_statevars.obj : prog_statevars.c
+shader_api.obj : shader_api.c
+prog_uniform.obj : prog_uniform.c
+prog_cache.obj : prog_cache.c
diff --git a/mesalib/src/mesa/shader/grammar/grammar.c b/mesalib/src/mesa/shader/grammar/grammar.c
new file mode 100644
index 000000000..a9775961d
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar.c
@@ -0,0 +1,3178 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file grammar.c
+ * syntax parsing engine
+ * \author Michal Krol
+ */
+
+#ifndef GRAMMAR_PORT_BUILD
+#error Do not build this file directly, build your grammar_XXX.c instead, which includes this file
+#endif
+
+/*
+*/
+
+/*
+ INTRODUCTION
+ ------------
+
+ The task is to check the syntax of an input string. Input string is a stream of ASCII
+ characters terminated with a null-character ('\0'). Checking it using C language is
+ difficult and hard to implement without bugs. It is hard to maintain and make changes when
+ the syntax changes.
+
+ This is because of a high redundancy of the C code. Large blocks of code are duplicated with
+ only small changes. Even use of macros does not solve the problem because macros cannot
+ erase the complexity of the problem.
+
+ The resolution is to create a new language that will be highly oriented to our task. Once
+ we describe a particular syntax, we are done. We can then focus on the code that implements
+ the language. The size and complexity of it is relatively small than the code that directly
+ checks the syntax.
+
+ First, we must implement our new language. Here, the language is implemented in C, but it
+ could also be implemented in any other language. The code is listed below. We must take
+ a good care that it is bug free. This is simple because the code is simple and clean.
+
+ Next, we must describe the syntax of our new language in itself. Once created and checked
+ manually that it is correct, we can use it to check another scripts.
+
+ Note that our new language loading code does not have to check the syntax. It is because we
+ assume that the script describing itself is correct, and other scripts can be syntactically
+ checked by the former script. The loading code must only do semantic checking which leads us to
+ simple resolving references.
+
+ THE LANGUAGE
+ ------------
+
+ Here I will describe the syntax of the new language (further called "Synek"). It is mainly a
+ sequence of declarations terminated by a semicolon. The declaration consists of a symbol,
+ which is an identifier, and its definition. A definition is in turn a sequence of specifiers
+ connected with ".and" or ".or" operator. These operators cannot be mixed together in a one
+ definition. Specifier can be a symbol, string, character, character range or a special
+ keyword ".true" or ".false".
+
+ On the very beginning of the script there is a declaration of a root symbol and is in the form:
+ .syntax <root_symbol>;
+ The <root_symbol> must be on of the symbols in declaration sequence. The syntax is correct if
+ the root symbol evaluates to true. A symbol evaluates to true if the definition associated with
+ the symbol evaluates to true. Definition evaluation depends on the operator used to connect
+ specifiers in the definition. If ".and" operator is used, definition evaluates to true if and
+ only if all the specifiers evaluate to true. If ".or" operator is used, definition evalutes to
+ true if any of the specifiers evaluates to true. If definition contains only one specifier,
+ it is evaluated as if it was connected with ".true" keyword by ".and" operator.
+
+ If specifier is a ".true" keyword, it always evaluates to true.
+
+ If specifier is a ".false" keyword, it always evaluates to false. Specifier evaluates to false
+ when it does not evaluate to true.
+
+ Character range specifier is in the form:
+ '<first_character>' - '<second_character>'
+ If specifier is a character range, it evaluates to true if character in the stream is greater
+ or equal to <first_character> and less or equal to <second_character>. In that situation
+ the stream pointer is advanced to point to next character in the stream. All C-style escape
+ sequences are supported although trigraph sequences are not. The comparisions are performed
+ on 8-bit unsigned integers.
+
+ Character specifier is in the form:
+ '<single_character>'
+ It evaluates to true if the following character range specifier evaluates to true:
+ '<single_character>' - '<single_character>'
+
+ String specifier is in the form:
+ "<string>"
+ Let N be the number of characters in <string>. Let <string>[i] designate i-th character in
+ <string>. Then the string specifier evaluates to true if and only if for i in the range [0, N)
+ the following character specifier evaluates to true:
+ '<string>[i]'
+ If <string>[i] is a quotation mark, '<string>[i]' is replaced with '\<string>[i]'.
+
+ Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
+ .loop <symbol> (1)
+ where <symbol> is defined as follows:
+ <symbol> <definition>; (2)
+ Construction (1) is replaced by the following code:
+ <symbol$1>
+ and declaration (2) is replaced by the following:
+ <symbol$1> <symbol$2> .or .true;
+ <symbol$2> <symbol> .and <symbol$1>;
+ <symbol> <definition>;
+
+ Synek supports also a register mechanizm. User can, in its SYN file, declare a number of
+ registers that can be accessed in the syn body. Each reg has its name and a default value.
+ The register is one byte wide. The C code can change the default value by calling
+ grammar_set_reg8() with grammar id, register name and a new value. As we know, each rule is
+ a sequence of specifiers joined with .and or .or operator. And now each specifier can be
+ prefixed with a condition expression in a form ".if (<reg_name> <operator> <hex_literal>)"
+ where <operator> can be == or !=. If the condition evaluates to false, the specifier
+ evaluates to .false. Otherwise it evalutes to the specifier.
+
+ ESCAPE SEQUENCES
+ ----------------
+
+ Synek supports all escape sequences in character specifiers. The mapping table is listed below.
+ All occurences of the characters in the first column are replaced with the corresponding
+ character in the second column.
+
+ Escape sequence Represents
+ ------------------------------------------------------------------------------------------------
+ \a Bell (alert)
+ \b Backspace
+ \f Formfeed
+ \n New line
+ \r Carriage return
+ \t Horizontal tab
+ \v Vertical tab
+ \' Single quotation mark
+ \" Double quotation mark
+ \\ Backslash
+ \? Literal question mark
+ \ooo ASCII character in octal notation
+ \xhhh ASCII character in hexadecimal notation
+ ------------------------------------------------------------------------------------------------
+
+ RAISING ERRORS
+ --------------
+
+ Any specifier can be followed by a special construction that is executed when the specifier
+ evaluates to false. The construction is in the form:
+ .error <ERROR_TEXT>
+ <ERROR_TEXT> is an identifier declared earlier by error text declaration. The declaration is
+ in the form:
+ .errtext <ERROR_TEXT> "<error_desc>"
+ When specifier evaluates to false and this construction is present, parsing is stopped
+ immediately and <error_desc> is returned as a result of parsing. The error position is also
+ returned and it is meant as an offset from the beggining of the stream to the character that
+ was valid so far. Example:
+
+ (**** syntax script ****)
+
+ .syntax program;
+ .errtext MISSING_SEMICOLON "missing ';'"
+ program declaration .and .loop space .and ';' .error MISSING_SEMICOLON .and
+ .loop space .and '\0';
+ declaration "declare" .and .loop space .and identifier;
+ space ' ';
+
+ (**** sample code ****)
+
+ declare foo ,
+
+ In the example above checking the sample code will result in error message "missing ';'" and
+ error position 12. The sample code is not correct. Note the presence of '\0' specifier to
+ assure that there is no code after semicolon - only spaces.
+ <error_desc> can optionally contain identifier surrounded by dollar signs $. In such a case,
+ the identifier and dollar signs are replaced by a string retrieved by invoking symbol with
+ the identifier name. The starting position is the error position. The lenght of the resulting
+ string is the position after invoking the symbol.
+
+ PRODUCTION
+ ----------
+
+ Synek not only checks the syntax but it can also produce (emit) bytes associated with specifiers
+ that evaluate to true. That is, every specifier and optional error construction can be followed
+ by a number of emit constructions that are in the form:
+ .emit <parameter>
+ <paramater> can be a HEX number, identifier, a star * or a dollar $. HEX number is preceded by
+ 0x or 0X. If <parameter> is an identifier, it must be earlier declared by emit code declaration
+ in the form:
+ .emtcode <identifier> <hex_number>
+
+ When given specifier evaluates to true, all emits associated with the specifier are output
+ in order they were declared. A star means that last-read character should be output instead
+ of constant value. Example:
+
+ (**** syntax script ****)
+
+ .syntax foobar;
+ .emtcode WORD_FOO 0x01
+ .emtcode WORD_BAR 0x02
+ foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
+ FOO "foo" .and SPACE;
+ BAR "bar" .and SPACE;
+ SPACE ' ' .or '\0';
+
+ (**** sample text 1 ****)
+
+ foo
+
+ (**** sample text 2 ****)
+
+ foobar
+
+ For both samples the result will be one-element array. For first sample text it will be
+ value 1, for second - 0. Note that every text will be accepted because of presence of
+ .true as an alternative.
+
+ Another example:
+
+ (**** syntax script ****)
+
+ .syntax declaration;
+ .emtcode VARIABLE 0x01
+ declaration "declare" .and .loop space .and
+ identifier .emit VARIABLE .and (1)
+ .true .emit 0x00 .and (2)
+ .loop space .and ';';
+ space ' ' .or '\t';
+ identifier .loop id_char .emit *; (3)
+ id_char 'a'-'z' .or 'A'-'Z' .or '_';
+
+ (**** sample code ****)
+
+ declare fubar;
+
+ In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If it evaluates to
+ true, VARIABLE constant and then production of the symbol is output. Specifier (2) is used
+ to terminate the string with null to signal when the string ends. Specifier (3) outputs
+ all characters that make declared identifier. The result of sample code will be the
+ following array:
+ { 1, 'f', 'u', 'b', 'a', 'r', 0 }
+
+ If .emit is followed by dollar $, it means that current position should be output. Current
+ position is a 32-bit unsigned integer distance from the very beginning of the parsed string to
+ first character consumed by the specifier associated with the .emit instruction. Current
+ position is stored in the output buffer in Little-Endian convention (the lowest byte comes
+ first).
+*/
+
+#include <stdio.h>
+
+static void mem_free (void **);
+
+/*
+ internal error messages
+*/
+static const byte *OUT_OF_MEMORY = (byte *) "internal error 1001: out of physical memory";
+static const byte *UNRESOLVED_REFERENCE = (byte *) "internal error 1002: unresolved reference '$'";
+static const byte *INVALID_GRAMMAR_ID = (byte *) "internal error 1003: invalid grammar object";
+static const byte *INVALID_REGISTER_NAME = (byte *) "internal error 1004: invalid register name: '$'";
+/*static const byte *DUPLICATE_IDENTIFIER = (byte *) "internal error 1005: identifier '$' already defined";*/
+static const byte *UNREFERENCED_IDENTIFIER =(byte *) "internal error 1006: unreferenced identifier '$'";
+
+static const byte *error_message = NULL; /* points to one of the error messages above */
+static byte *error_param = NULL; /* this is inserted into error_message in place of $ */
+static int error_position = -1;
+
+static byte *unknown = (byte *) "???";
+
+static void clear_last_error (void)
+{
+ /* reset error message */
+ error_message = NULL;
+
+ /* free error parameter - if error_param is a "???" don't free it - it's static */
+ if (error_param != unknown)
+ mem_free ((void **) (void *) &error_param);
+ else
+ error_param = NULL;
+
+ /* reset error position */
+ error_position = -1;
+}
+
+static void set_last_error (const byte *msg, byte *param, int pos)
+{
+ /* error message can be set only once */
+ if (error_message != NULL)
+ {
+ mem_free ((void **) (void *) &param);
+ return;
+ }
+
+ error_message = msg;
+
+ /* if param is NULL, set error_param to unknown ("???") */
+ /* note: do not try to strdup the "???" - it may be that we are here because of */
+ /* out of memory error so strdup can fail */
+ if (param != NULL)
+ error_param = param;
+ else
+ error_param = unknown;
+
+ error_position = pos;
+}
+
+/*
+ memory management routines
+*/
+static void *mem_alloc (size_t size)
+{
+ void *ptr = grammar_alloc_malloc (size);
+ if (ptr == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return ptr;
+}
+
+static void *mem_copy (void *dst, const void *src, size_t size)
+{
+ return grammar_memory_copy (dst, src, size);
+}
+
+static void mem_free (void **ptr)
+{
+ grammar_alloc_free (*ptr);
+ *ptr = NULL;
+}
+
+static void *mem_realloc (void *ptr, size_t old_size, size_t new_size)
+{
+ void *ptr2 = grammar_alloc_realloc (ptr, old_size, new_size);
+ if (ptr2 == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return ptr2;
+}
+
+static byte *str_copy_n (byte *dst, const byte *src, size_t max_len)
+{
+ return grammar_string_copy_n (dst, src, max_len);
+}
+
+static byte *str_duplicate (const byte *str)
+{
+ byte *new_str = grammar_string_duplicate (str);
+ if (new_str == NULL)
+ set_last_error (OUT_OF_MEMORY, NULL, -1);
+ return new_str;
+}
+
+static int str_equal (const byte *str1, const byte *str2)
+{
+ return grammar_string_compare (str1, str2) == 0;
+}
+
+static int str_equal_n (const byte *str1, const byte *str2, unsigned int n)
+{
+ return grammar_string_compare_n (str1, str2, n) == 0;
+}
+
+static int
+str_length (const byte *str)
+{
+ return (int) (grammar_string_length (str));
+}
+
+/*
+ useful macros
+*/
+#define GRAMMAR_IMPLEMENT_LIST_APPEND(_Ty)\
+ static void _Ty##_append (_Ty **x, _Ty *nx) {\
+ while (*x) x = &(**x).next;\
+ *x = nx;\
+ }
+
+/*
+ string to byte map typedef
+*/
+typedef struct map_byte_
+{
+ byte *key;
+ byte data;
+ struct map_byte_ *next;
+} map_byte;
+
+static void map_byte_create (map_byte **ma)
+{
+ *ma = (map_byte *) mem_alloc (sizeof (map_byte));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = '\0';
+ (**ma).next = NULL;
+ }
+}
+
+static void map_byte_destroy (map_byte **ma)
+{
+ if (*ma)
+ {
+ map_byte_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) ma);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(map_byte)
+
+/*
+ searches the map for the specified key,
+ returns pointer to the element with the specified key if it exists
+ returns NULL otherwise
+*/
+static map_byte *map_byte_locate (map_byte **ma, const byte *key)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ return *ma;
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return NULL;
+}
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the key is matched,
+ returns 1 otherwise
+*/
+static int map_byte_find (map_byte **ma, const byte *key, byte *data)
+{
+ map_byte *found = map_byte_locate (ma, key);
+ if (found != NULL)
+ {
+ *data = found->data;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ regbyte context typedef
+
+ Each regbyte consists of its name and a default value. These are static and created at
+ grammar script compile-time, for example the following line:
+ .regbyte vertex_blend 0x00
+ adds a new regbyte named "vertex_blend" to the static list and initializes it to 0.
+ When the script is executed, this regbyte can be accessed by name for read and write. When a
+ particular regbyte is written, a new regbyte_ctx entry is added to the top of the regbyte_ctx
+ stack. The new entry contains information abot which regbyte it references and its new value.
+ When a given regbyte is accessed for read, the stack is searched top-down to find an
+ entry that references the regbyte. The first matching entry is used to return the current
+ value it holds. If no entry is found, the default value is returned.
+*/
+typedef struct regbyte_ctx_
+{
+ map_byte *m_regbyte;
+ byte m_current_value;
+ struct regbyte_ctx_ *m_prev;
+} regbyte_ctx;
+
+static void regbyte_ctx_create (regbyte_ctx **re)
+{
+ *re = (regbyte_ctx *) mem_alloc (sizeof (regbyte_ctx));
+ if (*re)
+ {
+ (**re).m_regbyte = NULL;
+ (**re).m_prev = NULL;
+ }
+}
+
+static void regbyte_ctx_destroy (regbyte_ctx **re)
+{
+ if (*re)
+ {
+ mem_free ((void **) re);
+ }
+}
+
+static byte regbyte_ctx_extract (regbyte_ctx **re, map_byte *reg)
+{
+ /* first lookup in the register stack */
+ while (*re != NULL)
+ {
+ if ((**re).m_regbyte == reg)
+ return (**re).m_current_value;
+
+ re = &(**re).m_prev;
+ }
+
+ /* if not found - return the default value */
+ return reg->data;
+}
+
+/*
+ emit type typedef
+*/
+typedef enum emit_type_
+{
+ et_byte, /* explicit number */
+ et_stream, /* eaten character */
+ et_position /* current position */
+} emit_type;
+
+/*
+ emit destination typedef
+*/
+typedef enum emit_dest_
+{
+ ed_output, /* write to the output buffer */
+ ed_regbyte /* write a particular regbyte */
+} emit_dest;
+
+/*
+ emit typedef
+*/
+typedef struct emit_
+{
+ emit_dest m_emit_dest;
+ emit_type m_emit_type; /* ed_output */
+ byte m_byte; /* et_byte */
+ map_byte *m_regbyte; /* ed_regbyte */
+ byte *m_regname; /* ed_regbyte - temporary */
+ struct emit_ *m_next;
+} emit;
+
+static void emit_create (emit **em)
+{
+ *em = (emit *) mem_alloc (sizeof (emit));
+ if (*em)
+ {
+ (**em).m_emit_dest = ed_output;
+ (**em).m_emit_type = et_byte;
+ (**em).m_byte = '\0';
+ (**em).m_regbyte = NULL;
+ (**em).m_regname = NULL;
+ (**em).m_next = NULL;
+ }
+}
+
+static void emit_destroy (emit **em)
+{
+ if (*em)
+ {
+ emit_destroy (&(**em).m_next);
+ mem_free ((void **) &(**em).m_regname);
+ mem_free ((void **) em);
+ }
+}
+
+static unsigned int emit_size (emit *_E)
+{
+ unsigned int n = 0;
+
+ while (_E != NULL)
+ {
+ if (_E->m_emit_dest == ed_output)
+ {
+ if (_E->m_emit_type == et_position)
+ n += 4; /* position is a 32-bit unsigned integer */
+ else
+ n++;
+ }
+ _E = _E->m_next;
+ }
+
+ return n;
+}
+
+static int emit_push (emit *_E, byte *_P, byte c, unsigned int _Pos, regbyte_ctx **_Ctx)
+{
+ while (_E != NULL)
+ {
+ if (_E->m_emit_dest == ed_output)
+ {
+ if (_E->m_emit_type == et_byte)
+ *_P++ = _E->m_byte;
+ else if (_E->m_emit_type == et_stream)
+ *_P++ = c;
+ else /* _Em->type == et_position */
+ {
+ *_P++ = (byte) (_Pos);
+ *_P++ = (byte) (_Pos >> 8);
+ *_P++ = (byte) (_Pos >> 16);
+ *_P++ = (byte) (_Pos >> 24);
+ }
+ }
+ else
+ {
+ regbyte_ctx *new_rbc;
+ regbyte_ctx_create (&new_rbc);
+ if (new_rbc == NULL)
+ return 1;
+
+ new_rbc->m_prev = *_Ctx;
+ new_rbc->m_regbyte = _E->m_regbyte;
+ *_Ctx = new_rbc;
+
+ if (_E->m_emit_type == et_byte)
+ new_rbc->m_current_value = _E->m_byte;
+ else if (_E->m_emit_type == et_stream)
+ new_rbc->m_current_value = c;
+ }
+
+ _E = _E->m_next;
+ }
+
+ return 0;
+}
+
+/*
+ error typedef
+*/
+typedef struct error_
+{
+ byte *m_text;
+ byte *m_token_name;
+ struct rule_ *m_token;
+} error;
+
+static void error_create (error **er)
+{
+ *er = (error *) mem_alloc (sizeof (error));
+ if (*er)
+ {
+ (**er).m_text = NULL;
+ (**er).m_token_name = NULL;
+ (**er).m_token = NULL;
+ }
+}
+
+static void error_destroy (error **er)
+{
+ if (*er)
+ {
+ mem_free ((void **) &(**er).m_text);
+ mem_free ((void **) &(**er).m_token_name);
+ mem_free ((void **) er);
+ }
+}
+
+struct dict_;
+
+static byte *
+error_get_token (error *, struct dict_ *, const byte *, int);
+
+/*
+ condition operand type typedef
+*/
+typedef enum cond_oper_type_
+{
+ cot_byte, /* constant 8-bit unsigned integer */
+ cot_regbyte /* pointer to byte register containing the current value */
+} cond_oper_type;
+
+/*
+ condition operand typedef
+*/
+typedef struct cond_oper_
+{
+ cond_oper_type m_type;
+ byte m_byte; /* cot_byte */
+ map_byte *m_regbyte; /* cot_regbyte */
+ byte *m_regname; /* cot_regbyte - temporary */
+} cond_oper;
+
+/*
+ condition type typedef
+*/
+typedef enum cond_type_
+{
+ ct_equal,
+ ct_not_equal
+} cond_type;
+
+/*
+ condition typedef
+*/
+typedef struct cond_
+{
+ cond_type m_type;
+ cond_oper m_operands[2];
+} cond;
+
+static void cond_create (cond **co)
+{
+ *co = (cond *) mem_alloc (sizeof (cond));
+ if (*co)
+ {
+ (**co).m_operands[0].m_regname = NULL;
+ (**co).m_operands[1].m_regname = NULL;
+ }
+}
+
+static void cond_destroy (cond **co)
+{
+ if (*co)
+ {
+ mem_free ((void **) &(**co).m_operands[0].m_regname);
+ mem_free ((void **) &(**co).m_operands[1].m_regname);
+ mem_free ((void **) co);
+ }
+}
+
+/*
+ specifier type typedef
+*/
+typedef enum spec_type_
+{
+ st_false,
+ st_true,
+ st_byte,
+ st_byte_range,
+ st_string,
+ st_identifier,
+ st_identifier_loop,
+ st_debug
+} spec_type;
+
+/*
+ specifier typedef
+*/
+typedef struct spec_
+{
+ spec_type m_spec_type;
+ byte m_byte[2]; /* st_byte, st_byte_range */
+ byte *m_string; /* st_string */
+ struct rule_ *m_rule; /* st_identifier, st_identifier_loop */
+ emit *m_emits;
+ error *m_errtext;
+ cond *m_cond;
+ struct spec_ *next;
+} spec;
+
+static void spec_create (spec **sp)
+{
+ *sp = (spec *) mem_alloc (sizeof (spec));
+ if (*sp)
+ {
+ (**sp).m_spec_type = st_false;
+ (**sp).m_byte[0] = '\0';
+ (**sp).m_byte[1] = '\0';
+ (**sp).m_string = NULL;
+ (**sp).m_rule = NULL;
+ (**sp).m_emits = NULL;
+ (**sp).m_errtext = NULL;
+ (**sp).m_cond = NULL;
+ (**sp).next = NULL;
+ }
+}
+
+static void spec_destroy (spec **sp)
+{
+ if (*sp)
+ {
+ spec_destroy (&(**sp).next);
+ emit_destroy (&(**sp).m_emits);
+ error_destroy (&(**sp).m_errtext);
+ mem_free ((void **) &(**sp).m_string);
+ cond_destroy (&(**sp).m_cond);
+ mem_free ((void **) sp);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(spec)
+
+/*
+ operator typedef
+*/
+typedef enum oper_
+{
+ op_none,
+ op_and,
+ op_or
+} oper;
+
+/*
+ rule typedef
+*/
+typedef struct rule_
+{
+ oper m_oper;
+ spec *m_specs;
+ struct rule_ *next;
+ int m_referenced;
+} rule;
+
+static void rule_create (rule **ru)
+{
+ *ru = (rule *) mem_alloc (sizeof (rule));
+ if (*ru)
+ {
+ (**ru).m_oper = op_none;
+ (**ru).m_specs = NULL;
+ (**ru).next = NULL;
+ (**ru).m_referenced = 0;
+ }
+}
+
+static void rule_destroy (rule **ru)
+{
+ if (*ru)
+ {
+ rule_destroy (&(**ru).next);
+ spec_destroy (&(**ru).m_specs);
+ mem_free ((void **) ru);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(rule)
+
+/*
+ returns unique grammar id
+*/
+static grammar next_valid_grammar_id (void)
+{
+ static grammar id = 0;
+
+ return ++id;
+}
+
+/*
+ dictionary typedef
+*/
+typedef struct dict_
+{
+ rule *m_rulez;
+ rule *m_syntax;
+ rule *m_string;
+ map_byte *m_regbytes;
+ grammar m_id;
+ struct dict_ *next;
+} dict;
+
+static void dict_create (dict **di)
+{
+ *di = (dict *) mem_alloc (sizeof (dict));
+ if (*di)
+ {
+ (**di).m_rulez = NULL;
+ (**di).m_syntax = NULL;
+ (**di).m_string = NULL;
+ (**di).m_regbytes = NULL;
+ (**di).m_id = next_valid_grammar_id ();
+ (**di).next = NULL;
+ }
+}
+
+static void dict_destroy (dict **di)
+{
+ if (*di)
+ {
+ rule_destroy (&(**di).m_rulez);
+ map_byte_destroy (&(**di).m_regbytes);
+ mem_free ((void **) di);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(dict)
+
+static void dict_find (dict **di, grammar key, dict **data)
+{
+ while (*di)
+ {
+ if ((**di).m_id == key)
+ {
+ *data = *di;
+ return;
+ }
+
+ di = &(**di).next;
+ }
+
+ *data = NULL;
+}
+
+static dict *g_dicts = NULL;
+
+/*
+ byte array typedef
+*/
+typedef struct barray_
+{
+ byte *data;
+ unsigned int len;
+} barray;
+
+static void barray_create (barray **ba)
+{
+ *ba = (barray *) mem_alloc (sizeof (barray));
+ if (*ba)
+ {
+ (**ba).data = NULL;
+ (**ba).len = 0;
+ }
+}
+
+static void barray_destroy (barray **ba)
+{
+ if (*ba)
+ {
+ mem_free ((void **) &(**ba).data);
+ mem_free ((void **) ba);
+ }
+}
+
+/*
+ reallocates byte array to requested size,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_resize (barray **ba, unsigned int nlen)
+{
+ byte *new_pointer;
+
+ if (nlen == 0)
+ {
+ mem_free ((void **) &(**ba).data);
+ (**ba).data = NULL;
+ (**ba).len = 0;
+
+ return 0;
+ }
+ else
+ {
+ new_pointer = (byte *) mem_realloc ((**ba).data, (**ba).len * sizeof (byte),
+ nlen * sizeof (byte));
+ if (new_pointer)
+ {
+ (**ba).data = new_pointer;
+ (**ba).len = nlen;
+
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ adds byte array pointed by *nb to the end of array pointed by *ba,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_append (barray **ba, barray **nb)
+{
+ const unsigned int len = (**ba).len;
+
+ if (barray_resize (ba, (**ba).len + (**nb).len))
+ return 1;
+
+ mem_copy ((**ba).data + len, (**nb).data, (**nb).len);
+
+ return 0;
+}
+
+/*
+ adds emit chain pointed by em to the end of array pointed by *ba,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int barray_push (barray **ba, emit *em, byte c, unsigned int pos, regbyte_ctx **rbc)
+{
+ unsigned int count = emit_size (em);
+
+ if (barray_resize (ba, (**ba).len + count))
+ return 1;
+
+ return emit_push (em, (**ba).data + ((**ba).len - count), c, pos, rbc);
+}
+
+/*
+ byte pool typedef
+*/
+typedef struct bytepool_
+{
+ byte *_F;
+ unsigned int _Siz;
+} bytepool;
+
+static void bytepool_destroy (bytepool **by)
+{
+ if (*by != NULL)
+ {
+ mem_free ((void **) &(**by)._F);
+ mem_free ((void **) by);
+ }
+}
+
+static void bytepool_create (bytepool **by, int len)
+{
+ *by = (bytepool *) (mem_alloc (sizeof (bytepool)));
+ if (*by != NULL)
+ {
+ (**by)._F = (byte *) (mem_alloc (sizeof (byte) * len));
+ (**by)._Siz = len;
+
+ if ((**by)._F == NULL)
+ bytepool_destroy (by);
+ }
+}
+
+static int bytepool_reserve (bytepool *by, unsigned int n)
+{
+ byte *_P;
+
+ if (n <= by->_Siz)
+ return 0;
+
+ /* byte pool can only grow and at least by doubling its size */
+ n = n >= by->_Siz * 2 ? n : by->_Siz * 2;
+
+ /* reallocate the memory and adjust pointers to the new memory location */
+ _P = (byte *) (mem_realloc (by->_F, sizeof (byte) * by->_Siz, sizeof (byte) * n));
+ if (_P != NULL)
+ {
+ by->_F = _P;
+ by->_Siz = n;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ string to string map typedef
+*/
+typedef struct map_str_
+{
+ byte *key;
+ byte *data;
+ struct map_str_ *next;
+} map_str;
+
+static void map_str_create (map_str **ma)
+{
+ *ma = (map_str *) mem_alloc (sizeof (map_str));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = NULL;
+ (**ma).next = NULL;
+ }
+}
+
+static void map_str_destroy (map_str **ma)
+{
+ if (*ma)
+ {
+ map_str_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) &(**ma).data);
+ mem_free ((void **) ma);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(map_str)
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the key is matched,
+ returns 1 otherwise
+*/
+static int map_str_find (map_str **ma, const byte *key, byte **data)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ {
+ *data = str_duplicate ((**ma).data);
+ if (*data == NULL)
+ return 1;
+
+ return 0;
+ }
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return 1;
+}
+
+/*
+ string to rule map typedef
+*/
+typedef struct map_rule_
+{
+ byte *key;
+ rule *data;
+ struct map_rule_ *next;
+} map_rule;
+
+static void map_rule_create (map_rule **ma)
+{
+ *ma = (map_rule *) mem_alloc (sizeof (map_rule));
+ if (*ma)
+ {
+ (**ma).key = NULL;
+ (**ma).data = NULL;
+ (**ma).next = NULL;
+ }
+}
+
+static void map_rule_destroy (map_rule **ma)
+{
+ if (*ma)
+ {
+ map_rule_destroy (&(**ma).next);
+ mem_free ((void **) &(**ma).key);
+ mem_free ((void **) ma);
+ }
+}
+
+GRAMMAR_IMPLEMENT_LIST_APPEND(map_rule)
+
+/*
+ searches the map for specified key,
+ if the key is matched, *data is filled with data associated with the key,
+ returns 0 if the is matched,
+ returns 1 otherwise
+*/
+static int map_rule_find (map_rule **ma, const byte *key, rule **data)
+{
+ while (*ma)
+ {
+ if (str_equal ((**ma).key, key))
+ {
+ *data = (**ma).data;
+
+ return 0;
+ }
+
+ ma = &(**ma).next;
+ }
+
+ set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
+ return 1;
+}
+
+/*
+ returns 1 if given character is a white space,
+ returns 0 otherwise
+*/
+static int is_space (byte c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+}
+
+/*
+ advances text pointer by 1 if character pointed by *text is a space,
+ returns 1 if a space has been eaten,
+ returns 0 otherwise
+*/
+static int eat_space (const byte **text)
+{
+ if (is_space (**text))
+ {
+ (*text)++;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ returns 1 if text points to C-style comment start string,
+ returns 0 otherwise
+*/
+static int is_comment_start (const byte *text)
+{
+ return text[0] == '/' && text[1] == '*';
+}
+
+/*
+ advances text pointer to first character after C-style comment block - if any,
+ returns 1 if C-style comment block has been encountered and eaten,
+ returns 0 otherwise
+*/
+static int eat_comment (const byte **text)
+{
+ if (is_comment_start (*text))
+ {
+ /* *text points to comment block - skip two characters to enter comment body */
+ *text += 2;
+ /* skip any character except consecutive '*' and '/' */
+ while (!((*text)[0] == '*' && (*text)[1] == '/'))
+ (*text)++;
+ /* skip those two terminating characters */
+ *text += 2;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ advances text pointer to first character that is neither space nor C-style comment block
+*/
+static void eat_spaces (const byte **text)
+{
+ while (eat_space (text) || eat_comment (text))
+ ;
+}
+
+/*
+ resizes string pointed by *ptr to successfully add character c to the end of the string,
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int string_grow (byte **ptr, unsigned int *len, byte c)
+{
+ /* reallocate the string in 16-byte increments */
+ if ((*len & 0x0F) == 0x0F || *ptr == NULL)
+ {
+ byte *tmp = (byte *) mem_realloc (*ptr, ((*len + 1) & ~0x0F) * sizeof (byte),
+ ((*len + 1 + 0x10) & ~0x0F) * sizeof (byte));
+ if (tmp == NULL)
+ return 1;
+
+ *ptr = tmp;
+ }
+
+ if (c)
+ {
+ /* append given character */
+ (*ptr)[*len] = c;
+ (*len)++;
+ }
+ (*ptr)[*len] = '\0';
+
+ return 0;
+}
+
+/*
+ returns 1 if given character is a valid identifier character a-z, A-Z, 0-9 or _
+ returns 0 otherwise
+*/
+static int is_identifier (byte c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
+}
+
+/*
+ copies characters from *text to *id until non-identifier character is encountered,
+ assumes that *id points to NULL object - caller is responsible for later freeing the string,
+ text pointer is advanced to point past the copied identifier,
+ returns 0 if identifier was successfully copied,
+ returns 1 otherwise
+*/
+static int get_identifier (const byte **text, byte **id)
+{
+ const byte *t = *text;
+ byte *p = NULL;
+ unsigned int len = 0;
+
+ if (string_grow (&p, &len, '\0'))
+ return 1;
+
+ /* loop while next character in buffer is valid for identifiers */
+ while (is_identifier (*t))
+ {
+ if (string_grow (&p, &len, *t++))
+ {
+ mem_free ((void **) (void *) &p);
+ return 1;
+ }
+ }
+
+ *text = t;
+ *id = p;
+
+ return 0;
+}
+
+/*
+ converts sequence of DEC digits pointed by *text until non-DEC digit is encountered,
+ advances text pointer past the converted sequence,
+ returns the converted value
+*/
+static unsigned int dec_convert (const byte **text)
+{
+ unsigned int value = 0;
+
+ while (**text >= '0' && **text <= '9')
+ {
+ value = value * 10 + **text - '0';
+ (*text)++;
+ }
+
+ return value;
+}
+
+/*
+ returns 1 if given character is HEX digit 0-9, A-F or a-f,
+ returns 0 otherwise
+*/
+static int is_hex (byte c)
+{
+ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+}
+
+/*
+ returns value of passed character as if it was HEX digit
+*/
+static unsigned int hex2dec (byte c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return c - 'a' + 10;
+}
+
+/*
+ converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
+ advances text pointer past the converted sequence,
+ returns the converted value
+*/
+static unsigned int hex_convert (const byte **text)
+{
+ unsigned int value = 0;
+
+ while (is_hex (**text))
+ {
+ value = value * 0x10 + hex2dec (**text);
+ (*text)++;
+ }
+
+ return value;
+}
+
+/*
+ returns 1 if given character is OCT digit 0-7,
+ returns 0 otherwise
+*/
+static int is_oct (byte c)
+{
+ return c >= '0' && c <= '7';
+}
+
+/*
+ returns value of passed character as if it was OCT digit
+*/
+static int oct2dec (byte c)
+{
+ return c - '0';
+}
+
+static byte get_escape_sequence (const byte **text)
+{
+ int value = 0;
+
+ /* skip '\' character */
+ (*text)++;
+
+ switch (*(*text)++)
+ {
+ case '\'':
+ return '\'';
+ case '"':
+ return '\"';
+ case '?':
+ return '\?';
+ case '\\':
+ return '\\';
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case 'x':
+ return (byte) hex_convert (text);
+ }
+
+ (*text)--;
+ if (is_oct (**text))
+ {
+ value = oct2dec (*(*text)++);
+ if (is_oct (**text))
+ {
+ value = value * 010 + oct2dec (*(*text)++);
+ if (is_oct (**text))
+ value = value * 010 + oct2dec (*(*text)++);
+ }
+ }
+
+ return (byte) value;
+}
+
+/*
+ copies characters from *text to *str until " or ' character is encountered,
+ assumes that *str points to NULL object - caller is responsible for later freeing the string,
+ assumes that *text points to " or ' character that starts the string,
+ text pointer is advanced to point past the " or ' character,
+ returns 0 if string was successfully copied,
+ returns 1 otherwise
+*/
+static int get_string (const byte **text, byte **str)
+{
+ const byte *t = *text;
+ byte *p = NULL;
+ unsigned int len = 0;
+ byte term_char;
+
+ if (string_grow (&p, &len, '\0'))
+ return 1;
+
+ /* read " or ' character that starts the string */
+ term_char = *t++;
+ /* while next character is not the terminating character */
+ while (*t && *t != term_char)
+ {
+ byte c;
+
+ if (*t == '\\')
+ c = get_escape_sequence (&t);
+ else
+ c = *t++;
+
+ if (string_grow (&p, &len, c))
+ {
+ mem_free ((void **) (void *) &p);
+ return 1;
+ }
+ }
+ /* skip " or ' character that ends the string */
+ t++;
+
+ *text = t;
+ *str = p;
+ return 0;
+}
+
+/*
+ gets emit code, the syntax is:
+ ".emtcode" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character>
+ assumes that *text already points to <symbol>,
+ returns 0 if emit code is successfully read,
+ returns 1 otherwise
+*/
+static int get_emtcode (const byte **text, map_byte **ma)
+{
+ const byte *t = *text;
+ map_byte *m = NULL;
+
+ map_byte_create (&m);
+ if (m == NULL)
+ return 1;
+
+ if (get_identifier (&t, &m->key))
+ {
+ map_byte_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (*t == '\'')
+ {
+ byte *c;
+
+ if (get_string (&t, &c))
+ {
+ map_byte_destroy (&m);
+ return 1;
+ }
+
+ m->data = (byte) c[0];
+ mem_free ((void **) (void *) &c);
+ }
+ else if (t[0] == '0' && (t[1] == 'x' || t[1] == 'X'))
+ {
+ /* skip HEX "0x" or "0X" prefix */
+ t += 2;
+ m->data = (byte) hex_convert (&t);
+ }
+ else
+ {
+ m->data = (byte) dec_convert (&t);
+ }
+
+ eat_spaces (&t);
+
+ *text = t;
+ *ma = m;
+ return 0;
+}
+
+/*
+ gets regbyte declaration, the syntax is:
+ ".regbyte" " " <symbol> " " (("0x" | "0X") <hex_value>) | <dec_value> | <character>
+ assumes that *text already points to <symbol>,
+ returns 0 if regbyte is successfully read,
+ returns 1 otherwise
+*/
+static int get_regbyte (const byte **text, map_byte **ma)
+{
+ /* pass it to the emtcode parser as it has the same syntax starting at <symbol> */
+ return get_emtcode (text, ma);
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise
+*/
+static int get_errtext (const byte **text, map_str **ma)
+{
+ const byte *t = *text;
+ map_str *m = NULL;
+
+ map_str_create (&m);
+ if (m == NULL)
+ return 1;
+
+ if (get_identifier (&t, &m->key))
+ {
+ map_str_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (get_string (&t, &m->data))
+ {
+ map_str_destroy (&m);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ *text = t;
+ *ma = m;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_error (const byte **text, error **er, map_str *maps)
+{
+ const byte *t = *text;
+ byte *temp = NULL;
+
+ if (*t != '.')
+ return 0;
+
+ t++;
+ if (get_identifier (&t, &temp))
+ return 1;
+ eat_spaces (&t);
+
+ if (!str_equal ((byte *) "error", temp))
+ {
+ mem_free ((void **) (void *) &temp);
+ return 0;
+ }
+
+ mem_free ((void **) (void *) &temp);
+
+ error_create (er);
+ if (*er == NULL)
+ return 1;
+
+ if (*t == '\"')
+ {
+ if (get_string (&t, &(**er).m_text))
+ {
+ error_destroy (er);
+ return 1;
+ }
+ eat_spaces (&t);
+ }
+ else
+ {
+ if (get_identifier (&t, &temp))
+ {
+ error_destroy (er);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (map_str_find (&maps, temp, &(**er).m_text))
+ {
+ mem_free ((void **) (void *) &temp);
+ error_destroy (er);
+ return 1;
+ }
+
+ mem_free ((void **) (void *) &temp);
+ }
+
+ /* try to extract "token" from "...$token$..." */
+ {
+ byte *processed = NULL;
+ unsigned int len = 0;
+ int i = 0;
+
+ if (string_grow (&processed, &len, '\0'))
+ {
+ error_destroy (er);
+ return 1;
+ }
+
+ while (i < str_length ((**er).m_text))
+ {
+ /* check if the dollar sign is repeated - if so skip it */
+ if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$')
+ {
+ if (string_grow (&processed, &len, '$'))
+ {
+ mem_free ((void **) (void *) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i += 2;
+ }
+ else if ((**er).m_text[i] != '$')
+ {
+ if (string_grow (&processed, &len, (**er).m_text[i]))
+ {
+ mem_free ((void **) (void *) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i++;
+ }
+ else
+ {
+ if (string_grow (&processed, &len, '$'))
+ {
+ mem_free ((void **) (void *) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ {
+ /* length of token being extracted */
+ unsigned int tlen = 0;
+
+ if (string_grow (&(**er).m_token_name, &tlen, '\0'))
+ {
+ mem_free ((void **) (void *) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ /* skip the dollar sign */
+ i++;
+
+ while ((**er).m_text[i] != '$')
+ {
+ if (string_grow (&(**er).m_token_name, &tlen, (**er).m_text[i]))
+ {
+ mem_free ((void **) (void *) &processed);
+ error_destroy (er);
+ return 1;
+ }
+
+ i++;
+ }
+
+ /* skip the dollar sign */
+ i++;
+ }
+ }
+ }
+
+ mem_free ((void **) &(**er).m_text);
+ (**er).m_text = processed;
+ }
+
+ *text = t;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_emits (const byte **text, emit **em, map_byte *mapb)
+{
+ const byte *t = *text;
+ byte *temp = NULL;
+ emit *e = NULL;
+ emit_dest dest;
+
+ if (*t != '.')
+ return 0;
+
+ t++;
+ if (get_identifier (&t, &temp))
+ return 1;
+ eat_spaces (&t);
+
+ /* .emit */
+ if (str_equal ((byte *) "emit", temp))
+ dest = ed_output;
+ /* .load */
+ else if (str_equal ((byte *) "load", temp))
+ dest = ed_regbyte;
+ else
+ {
+ mem_free ((void **) (void *) &temp);
+ return 0;
+ }
+
+ mem_free ((void **) (void *) &temp);
+
+ emit_create (&e);
+ if (e == NULL)
+ return 1;
+
+ e->m_emit_dest = dest;
+
+ if (dest == ed_regbyte)
+ {
+ if (get_identifier (&t, &e->m_regname))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+ eat_spaces (&t);
+ }
+
+ /* 0xNN */
+ if (*t == '0' && (t[1] == 'x' || t[1] == 'X'))
+ {
+ t += 2;
+ e->m_byte = (byte) hex_convert (&t);
+
+ e->m_emit_type = et_byte;
+ }
+ /* NNN */
+ else if (*t >= '0' && *t <= '9')
+ {
+ e->m_byte = (byte) dec_convert (&t);
+
+ e->m_emit_type = et_byte;
+ }
+ /* * */
+ else if (*t == '*')
+ {
+ t++;
+
+ e->m_emit_type = et_stream;
+ }
+ /* $ */
+ else if (*t == '$')
+ {
+ t++;
+
+ e->m_emit_type = et_position;
+ }
+ /* 'c' */
+ else if (*t == '\'')
+ {
+ if (get_string (&t, &temp))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+ e->m_byte = (byte) temp[0];
+
+ mem_free ((void **) (void *) &temp);
+
+ e->m_emit_type = et_byte;
+ }
+ else
+ {
+ if (get_identifier (&t, &temp))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+
+ if (map_byte_find (&mapb, temp, &e->m_byte))
+ {
+ mem_free ((void **) (void *) &temp);
+ emit_destroy (&e);
+ return 1;
+ }
+
+ mem_free ((void **) (void *) &temp);
+
+ e->m_emit_type = et_byte;
+ }
+
+ eat_spaces (&t);
+
+ if (get_emits (&t, &e->m_next, mapb))
+ {
+ emit_destroy (&e);
+ return 1;
+ }
+
+ *text = t;
+ *em = e;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_spec (const byte **text, spec **sp, map_str *maps, map_byte *mapb)
+{
+ const byte *t = *text;
+ spec *s = NULL;
+
+ spec_create (&s);
+ if (s == NULL)
+ return 1;
+
+ /* first - read optional .if statement */
+ if (*t == '.')
+ {
+ const byte *u = t;
+ byte *keyword = NULL;
+
+ /* skip the dot */
+ u++;
+
+ if (get_identifier (&u, &keyword))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ /* .if */
+ if (str_equal ((byte *) "if", keyword))
+ {
+ cond_create (&s->m_cond);
+ if (s->m_cond == NULL)
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ /* skip the left paren */
+ eat_spaces (&u);
+ u++;
+
+ /* get the left operand */
+ eat_spaces (&u);
+ if (get_identifier (&u, &s->m_cond->m_operands[0].m_regname))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ s->m_cond->m_operands[0].m_type = cot_regbyte;
+
+ /* get the operator (!= or ==) */
+ eat_spaces (&u);
+ if (*u == '!')
+ s->m_cond->m_type = ct_not_equal;
+ else
+ s->m_cond->m_type = ct_equal;
+ u += 2;
+ eat_spaces (&u);
+
+ if (u[0] == '0' && (u[1] == 'x' || u[1] == 'X'))
+ {
+ /* skip the 0x prefix */
+ u += 2;
+
+ /* get the right operand */
+ s->m_cond->m_operands[1].m_byte = hex_convert (&u);
+ s->m_cond->m_operands[1].m_type = cot_byte;
+ }
+ else /*if (*u >= '0' && *u <= '9')*/
+ {
+ /* get the right operand */
+ s->m_cond->m_operands[1].m_byte = dec_convert (&u);
+ s->m_cond->m_operands[1].m_type = cot_byte;
+ }
+
+ /* skip the right paren */
+ eat_spaces (&u);
+ u++;
+
+ eat_spaces (&u);
+
+ t = u;
+ }
+
+ mem_free ((void **) (void *) &keyword);
+ }
+
+ if (*t == '\'')
+ {
+ byte *temp = NULL;
+
+ if (get_string (&t, &temp))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (*t == '-')
+ {
+ byte *temp2 = NULL;
+
+ /* skip the '-' character */
+ t++;
+ eat_spaces (&t);
+
+ if (get_string (&t, &temp2))
+ {
+ mem_free ((void **) (void *) &temp);
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_byte_range;
+ s->m_byte[0] = *temp;
+ s->m_byte[1] = *temp2;
+
+ mem_free ((void **) (void *) &temp2);
+ }
+ else
+ {
+ s->m_spec_type = st_byte;
+ *s->m_byte = *temp;
+ }
+
+ mem_free ((void **) (void *) &temp);
+ }
+ else if (*t == '"')
+ {
+ if (get_string (&t, &s->m_string))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_string;
+ }
+ else if (*t == '.')
+ {
+ byte *keyword = NULL;
+
+ /* skip the dot */
+ t++;
+
+ if (get_identifier (&t, &keyword))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ /* .true */
+ if (str_equal ((byte *) "true", keyword))
+ {
+ s->m_spec_type = st_true;
+ }
+ /* .false */
+ else if (str_equal ((byte *) "false", keyword))
+ {
+ s->m_spec_type = st_false;
+ }
+ /* .debug */
+ else if (str_equal ((byte *) "debug", keyword))
+ {
+ s->m_spec_type = st_debug;
+ }
+ /* .loop */
+ else if (str_equal ((byte *) "loop", keyword))
+ {
+ if (get_identifier (&t, &s->m_string))
+ {
+ mem_free ((void **) (void *) &keyword);
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_identifier_loop;
+ }
+ mem_free ((void **) (void *) &keyword);
+ }
+ else
+ {
+ if (get_identifier (&t, &s->m_string))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ s->m_spec_type = st_identifier;
+ }
+
+ if (get_error (&t, &s->m_errtext, maps))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ if (get_emits (&t, &s->m_emits, mapb))
+ {
+ spec_destroy (&s);
+ return 1;
+ }
+
+ *text = t;
+ *sp = s;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int get_rule (const byte **text, rule **ru, map_str *maps, map_byte *mapb)
+{
+ const byte *t = *text;
+ rule *r = NULL;
+
+ rule_create (&r);
+ if (r == NULL)
+ return 1;
+
+ if (get_spec (&t, &r->m_specs, maps, mapb))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+
+ while (*t != ';')
+ {
+ byte *op = NULL;
+ spec *sp = NULL;
+
+ /* skip the dot that precedes "and" or "or" */
+ t++;
+
+ /* read "and" or "or" keyword */
+ if (get_identifier (&t, &op))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+ eat_spaces (&t);
+
+ if (r->m_oper == op_none)
+ {
+ /* .and */
+ if (str_equal ((byte *) "and", op))
+ r->m_oper = op_and;
+ /* .or */
+ else
+ r->m_oper = op_or;
+ }
+
+ mem_free ((void **) (void *) &op);
+
+ if (get_spec (&t, &sp, maps, mapb))
+ {
+ rule_destroy (&r);
+ return 1;
+ }
+
+ spec_append (&r->m_specs, sp);
+ }
+
+ /* skip the semicolon */
+ t++;
+ eat_spaces (&t);
+
+ *text = t;
+ *ru = r;
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int update_dependency (map_rule *mapr, byte *symbol, rule **ru)
+{
+ if (map_rule_find (&mapr, symbol, ru))
+ return 1;
+
+ (**ru).m_referenced = 1;
+
+ return 0;
+}
+
+/*
+ returns 0 on success,
+ returns 1 otherwise,
+*/
+static int update_dependencies (dict *di, map_rule *mapr, byte **syntax_symbol,
+ byte **string_symbol, map_byte *regbytes)
+{
+ rule *rulez = di->m_rulez;
+
+ /* update dependecies for the root and lexer symbols */
+ if (update_dependency (mapr, *syntax_symbol, &di->m_syntax) ||
+ (*string_symbol != NULL && update_dependency (mapr, *string_symbol, &di->m_string)))
+ return 1;
+
+ mem_free ((void **) syntax_symbol);
+ mem_free ((void **) string_symbol);
+
+ /* update dependecies for the rest of the rules */
+ while (rulez)
+ {
+ spec *sp = rulez->m_specs;
+
+ /* iterate through all the specifiers */
+ while (sp)
+ {
+ /* update dependency for identifier */
+ if (sp->m_spec_type == st_identifier || sp->m_spec_type == st_identifier_loop)
+ {
+ if (update_dependency (mapr, sp->m_string, &sp->m_rule))
+ return 1;
+
+ mem_free ((void **) &sp->m_string);
+ }
+
+ /* some errtexts reference to a rule */
+ if (sp->m_errtext && sp->m_errtext->m_token_name)
+ {
+ if (update_dependency (mapr, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
+ return 1;
+
+ mem_free ((void **) &sp->m_errtext->m_token_name);
+ }
+
+ /* update dependency for condition */
+ if (sp->m_cond)
+ {
+ int i;
+ for (i = 0; i < 2; i++)
+ if (sp->m_cond->m_operands[i].m_type == cot_regbyte)
+ {
+ sp->m_cond->m_operands[i].m_regbyte = map_byte_locate (&regbytes,
+ sp->m_cond->m_operands[i].m_regname);
+
+ if (sp->m_cond->m_operands[i].m_regbyte == NULL)
+ return 1;
+
+ mem_free ((void **) &sp->m_cond->m_operands[i].m_regname);
+ }
+ }
+
+ /* update dependency for all .load instructions */
+ if (sp->m_emits)
+ {
+ emit *em = sp->m_emits;
+ while (em != NULL)
+ {
+ if (em->m_emit_dest == ed_regbyte)
+ {
+ em->m_regbyte = map_byte_locate (&regbytes, em->m_regname);
+
+ if (em->m_regbyte == NULL)
+ return 1;
+
+ mem_free ((void **) &em->m_regname);
+ }
+
+ em = em->m_next;
+ }
+ }
+
+ sp = sp->next;
+ }
+
+ rulez = rulez->next;
+ }
+
+ /* check for unreferenced symbols */
+ rulez = di->m_rulez;
+ while (rulez != NULL)
+ {
+ if (!rulez->m_referenced)
+ {
+ map_rule *ma = mapr;
+ while (ma)
+ {
+ if (ma->data == rulez)
+ {
+ set_last_error (UNREFERENCED_IDENTIFIER, str_duplicate (ma->key), -1);
+ return 1;
+ }
+ ma = ma->next;
+ }
+ }
+ rulez = rulez->next;
+ }
+
+ return 0;
+}
+
+static int satisfies_condition (cond *co, regbyte_ctx *ctx)
+{
+ byte values[2];
+ int i;
+
+ if (co == NULL)
+ return 1;
+
+ for (i = 0; i < 2; i++)
+ switch (co->m_operands[i].m_type)
+ {
+ case cot_byte:
+ values[i] = co->m_operands[i].m_byte;
+ break;
+ case cot_regbyte:
+ values[i] = regbyte_ctx_extract (&ctx, co->m_operands[i].m_regbyte);
+ break;
+ }
+
+ switch (co->m_type)
+ {
+ case ct_equal:
+ return values[0] == values[1];
+ case ct_not_equal:
+ return values[0] != values[1];
+ }
+
+ return 0;
+}
+
+static void free_regbyte_ctx_stack (regbyte_ctx *top, regbyte_ctx *limit)
+{
+ while (top != limit)
+ {
+ regbyte_ctx *rbc = top->m_prev;
+ regbyte_ctx_destroy (&top);
+ top = rbc;
+ }
+}
+
+typedef enum match_result_
+{
+ mr_not_matched, /* the examined string does not match */
+ mr_matched, /* the examined string matches */
+ mr_error_raised, /* mr_not_matched + error has been raised */
+ mr_dont_emit, /* used by identifier loops only */
+ mr_internal_error /* an internal error has occured such as out of memory */
+} match_result;
+
+/*
+ * This function does the main job. It parses the text and generates output data.
+ */
+static match_result
+match (dict *di, const byte *text, int *index, rule *ru, barray **ba, int filtering_string,
+ regbyte_ctx **rbc)
+{
+ int ind = *index;
+ match_result status = mr_not_matched;
+ spec *sp = ru->m_specs;
+ regbyte_ctx *ctx = *rbc;
+
+ /* for every specifier in the rule */
+ while (sp)
+ {
+ int i, len, save_ind = ind;
+ barray *array = NULL;
+
+ if (satisfies_condition (sp->m_cond, ctx))
+ {
+ switch (sp->m_spec_type)
+ {
+ case st_identifier:
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ status = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+
+ if (status == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ break;
+ case st_string:
+ len = str_length (sp->m_string);
+
+ /* prefilter the stream */
+ if (!filtering_string && di->m_string)
+ {
+ barray *ba;
+ int filter_index = 0;
+ match_result result;
+ regbyte_ctx *null_ctx = NULL;
+
+ barray_create (&ba);
+ if (ba == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ result = match (di, text + ind, &filter_index, di->m_string, &ba, 1, &null_ctx);
+
+ if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&ba);
+ return mr_internal_error;
+ }
+
+ if (result != mr_matched)
+ {
+ barray_destroy (&ba);
+ status = mr_not_matched;
+ break;
+ }
+
+ barray_destroy (&ba);
+
+ if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
+ {
+ status = mr_not_matched;
+ break;
+ }
+
+ status = mr_matched;
+ ind += len;
+ }
+ else
+ {
+ status = mr_matched;
+ for (i = 0; status == mr_matched && i < len; i++)
+ if (text[ind + i] != sp->m_string[i])
+ status = mr_not_matched;
+
+ if (status == mr_matched)
+ ind += len;
+ }
+ break;
+ case st_byte:
+ status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_byte_range:
+ status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
+ mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_true:
+ status = mr_matched;
+ break;
+ case st_false:
+ status = mr_not_matched;
+ break;
+ case st_debug:
+ status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
+ break;
+ case st_identifier_loop:
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ status = mr_dont_emit;
+ for (;;)
+ {
+ match_result result;
+
+ save_ind = ind;
+ result = match (di, text, &ind, sp->m_rule, &array, filtering_string, &ctx);
+
+ if (result == mr_error_raised)
+ {
+ status = result;
+ break;
+ }
+ else if (result == mr_matched)
+ {
+ if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx) ||
+ barray_append (ba, &array))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ barray_destroy (&array);
+ barray_create (&array);
+ if (array == NULL)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ }
+ else if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ else
+ break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ status = mr_not_matched;
+ }
+
+ if (status == mr_error_raised)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+
+ return mr_error_raised;
+ }
+
+ if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+
+ if (sp->m_errtext)
+ {
+ set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,
+ ind), ind);
+
+ return mr_error_raised;
+ }
+
+ return mr_not_matched;
+ }
+
+ if (status == mr_matched)
+ {
+ if (sp->m_emits)
+ if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind, &ctx))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+
+ if (array)
+ if (barray_append (ba, &array))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ barray_destroy (&array);
+ return mr_internal_error;
+ }
+ }
+
+ barray_destroy (&array);
+
+ /* if the rule operator is a logical or, we pick up the first matching specifier */
+ if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ return mr_matched;
+ }
+
+ sp = sp->next;
+ }
+
+ /* everything went fine - all specifiers match up */
+ if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ return mr_matched;
+ }
+
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_not_matched;
+}
+
+static match_result
+fast_match (dict *di, const byte *text, int *index, rule *ru, int *_PP, bytepool *_BP,
+ int filtering_string, regbyte_ctx **rbc)
+{
+ int ind = *index;
+ int _P = filtering_string ? 0 : *_PP;
+ int _P2;
+ match_result status = mr_not_matched;
+ spec *sp = ru->m_specs;
+ regbyte_ctx *ctx = *rbc;
+
+ /* for every specifier in the rule */
+ while (sp)
+ {
+ int i, len, save_ind = ind;
+
+ _P2 = _P + (sp->m_emits ? emit_size (sp->m_emits) : 0);
+ if (bytepool_reserve (_BP, _P2))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ if (satisfies_condition (sp->m_cond, ctx))
+ {
+ switch (sp->m_spec_type)
+ {
+ case st_identifier:
+ status = fast_match (di, text, &ind, sp->m_rule, &_P2, _BP, filtering_string, &ctx);
+
+ if (status == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ break;
+ case st_string:
+ len = str_length (sp->m_string);
+
+ /* prefilter the stream */
+ if (!filtering_string && di->m_string)
+ {
+ int filter_index = 0;
+ match_result result;
+ regbyte_ctx *null_ctx = NULL;
+
+ result = fast_match (di, text + ind, &filter_index, di->m_string, NULL, _BP, 1, &null_ctx);
+
+ if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ if (result != mr_matched)
+ {
+ status = mr_not_matched;
+ break;
+ }
+
+ if (filter_index != len || !str_equal_n (sp->m_string, text + ind, len))
+ {
+ status = mr_not_matched;
+ break;
+ }
+
+ status = mr_matched;
+ ind += len;
+ }
+ else
+ {
+ status = mr_matched;
+ for (i = 0; status == mr_matched && i < len; i++)
+ if (text[ind + i] != sp->m_string[i])
+ status = mr_not_matched;
+
+ if (status == mr_matched)
+ ind += len;
+ }
+ break;
+ case st_byte:
+ status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_byte_range:
+ status = (text[ind] >= sp->m_byte[0] && text[ind] <= sp->m_byte[1]) ?
+ mr_matched : mr_not_matched;
+ if (status == mr_matched)
+ ind++;
+ break;
+ case st_true:
+ status = mr_matched;
+ break;
+ case st_false:
+ status = mr_not_matched;
+ break;
+ case st_debug:
+ status = ru->m_oper == op_and ? mr_matched : mr_not_matched;
+ break;
+ case st_identifier_loop:
+ status = mr_dont_emit;
+ for (;;)
+ {
+ match_result result;
+
+ save_ind = ind;
+ result = fast_match (di, text, &ind, sp->m_rule, &_P2, _BP, filtering_string, &ctx);
+
+ if (result == mr_error_raised)
+ {
+ status = result;
+ break;
+ }
+ else if (result == mr_matched)
+ {
+ if (!filtering_string)
+ {
+ if (sp->m_emits != NULL)
+ {
+ if (emit_push (sp->m_emits, _BP->_F + _P, text[ind - 1], save_ind, &ctx))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ }
+
+ _P = _P2;
+ _P2 += sp->m_emits ? emit_size (sp->m_emits) : 0;
+ if (bytepool_reserve (_BP, _P2))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ }
+ }
+ else if (result == mr_internal_error)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+ else
+ break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ status = mr_not_matched;
+ }
+
+ if (status == mr_error_raised)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+
+ return mr_error_raised;
+ }
+
+ if (ru->m_oper == op_and && status != mr_matched && status != mr_dont_emit)
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+
+ if (sp->m_errtext)
+ {
+ set_last_error (sp->m_errtext->m_text, error_get_token (sp->m_errtext, di, text,
+ ind), ind);
+
+ return mr_error_raised;
+ }
+
+ return mr_not_matched;
+ }
+
+ if (status == mr_matched)
+ {
+ if (sp->m_emits != NULL) {
+ const byte ch = (ind <= 0) ? 0 : text[ind - 1];
+ if (emit_push (sp->m_emits, _BP->_F + _P, ch, save_ind, &ctx))
+ {
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_internal_error;
+ }
+
+ }
+ _P = _P2;
+ }
+
+ /* if the rule operator is a logical or, we pick up the first matching specifier */
+ if (ru->m_oper == op_or && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ if (!filtering_string)
+ *_PP = _P;
+ return mr_matched;
+ }
+
+ sp = sp->next;
+ }
+
+ /* everything went fine - all specifiers match up */
+ if (ru->m_oper == op_and && (status == mr_matched || status == mr_dont_emit))
+ {
+ *index = ind;
+ *rbc = ctx;
+ if (!filtering_string)
+ *_PP = _P;
+ return mr_matched;
+ }
+
+ free_regbyte_ctx_stack (ctx, *rbc);
+ return mr_not_matched;
+}
+
+static byte *
+error_get_token (error *er, dict *di, const byte *text, int ind)
+{
+ byte *str = NULL;
+
+ if (er->m_token)
+ {
+ barray *ba;
+ int filter_index = 0;
+ regbyte_ctx *ctx = NULL;
+
+ barray_create (&ba);
+ if (ba != NULL)
+ {
+ if (match (di, text + ind, &filter_index, er->m_token, &ba, 0, &ctx) == mr_matched &&
+ filter_index)
+ {
+ str = (byte *) mem_alloc (filter_index + 1);
+ if (str != NULL)
+ {
+ str_copy_n (str, text + ind, filter_index);
+ str[filter_index] = '\0';
+ }
+ }
+ barray_destroy (&ba);
+ }
+ }
+
+ return str;
+}
+
+typedef struct grammar_load_state_
+{
+ dict *di;
+ byte *syntax_symbol;
+ byte *string_symbol;
+ map_str *maps;
+ map_byte *mapb;
+ map_rule *mapr;
+} grammar_load_state;
+
+static void grammar_load_state_create (grammar_load_state **gr)
+{
+ *gr = (grammar_load_state *) mem_alloc (sizeof (grammar_load_state));
+ if (*gr)
+ {
+ (**gr).di = NULL;
+ (**gr).syntax_symbol = NULL;
+ (**gr).string_symbol = NULL;
+ (**gr).maps = NULL;
+ (**gr).mapb = NULL;
+ (**gr).mapr = NULL;
+ }
+}
+
+static void grammar_load_state_destroy (grammar_load_state **gr)
+{
+ if (*gr)
+ {
+ dict_destroy (&(**gr).di);
+ mem_free ((void **) &(**gr).syntax_symbol);
+ mem_free ((void **) &(**gr).string_symbol);
+ map_str_destroy (&(**gr).maps);
+ map_byte_destroy (&(**gr).mapb);
+ map_rule_destroy (&(**gr).mapr);
+ mem_free ((void **) gr);
+ }
+}
+
+
+static void error_msg(int line, const char *msg)
+{
+ fprintf(stderr, "Error in grammar_load_from_text() at line %d: %s\n", line, msg);
+}
+
+
+/*
+ the API
+*/
+grammar grammar_load_from_text (const byte *text)
+{
+ grammar_load_state *g = NULL;
+ grammar id = 0;
+
+ clear_last_error ();
+
+ grammar_load_state_create (&g);
+ if (g == NULL) {
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ dict_create (&g->di);
+ if (g->di == NULL)
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ eat_spaces (&text);
+
+ /* skip ".syntax" keyword */
+ text += 7;
+ eat_spaces (&text);
+
+ /* retrieve root symbol */
+ if (get_identifier (&text, &g->syntax_symbol))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+ eat_spaces (&text);
+
+ /* skip semicolon */
+ text++;
+ eat_spaces (&text);
+
+ while (*text)
+ {
+ byte *symbol = NULL;
+ int is_dot = *text == '.';
+
+ if (is_dot)
+ text++;
+
+ if (get_identifier (&text, &symbol))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+ eat_spaces (&text);
+
+ /* .emtcode */
+ if (is_dot && str_equal (symbol, (byte *) "emtcode"))
+ {
+ map_byte *ma = NULL;
+
+ mem_free ((void **) (void *) &symbol);
+
+ if (get_emtcode (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ map_byte_append (&g->mapb, ma);
+ }
+ /* .regbyte */
+ else if (is_dot && str_equal (symbol, (byte *) "regbyte"))
+ {
+ map_byte *ma = NULL;
+
+ mem_free ((void **) (void *) &symbol);
+
+ if (get_regbyte (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ map_byte_append (&g->di->m_regbytes, ma);
+ }
+ /* .errtext */
+ else if (is_dot && str_equal (symbol, (byte *) "errtext"))
+ {
+ map_str *ma = NULL;
+
+ mem_free ((void **) (void *) &symbol);
+
+ if (get_errtext (&text, &ma))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ map_str_append (&g->maps, ma);
+ }
+ /* .string */
+ else if (is_dot && str_equal (symbol, (byte *) "string"))
+ {
+ mem_free ((void **) (void *) &symbol);
+
+ if (g->di->m_string != NULL)
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ if (get_identifier (&text, &g->string_symbol))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ /* skip semicolon */
+ eat_spaces (&text);
+ text++;
+ eat_spaces (&text);
+ }
+ else
+ {
+ rule *ru = NULL;
+ map_rule *ma = NULL;
+
+ if (get_rule (&text, &ru, g->maps, g->mapb))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ rule_append (&g->di->m_rulez, ru);
+
+ /* if a rule consist of only one specifier, give it an ".and" operator */
+ if (ru->m_oper == op_none)
+ ru->m_oper = op_and;
+
+ map_rule_create (&ma);
+ if (ma == NULL)
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "");
+ return 0;
+ }
+
+ ma->key = symbol;
+ ma->data = ru;
+ map_rule_append (&g->mapr, ma);
+ }
+ }
+
+ if (update_dependencies (g->di, g->mapr, &g->syntax_symbol, &g->string_symbol,
+ g->di->m_regbytes))
+ {
+ grammar_load_state_destroy (&g);
+ error_msg(__LINE__, "update_dependencies() failed");
+ return 0;
+ }
+
+ dict_append (&g_dicts, g->di);
+ id = g->di->m_id;
+ g->di = NULL;
+
+ grammar_load_state_destroy (&g);
+
+ return id;
+}
+
+int grammar_set_reg8 (grammar id, const byte *name, byte value)
+{
+ dict *di = NULL;
+ map_byte *reg = NULL;
+
+ clear_last_error ();
+
+ dict_find (&g_dicts, id, &di);
+ if (di == NULL)
+ {
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+ }
+
+ reg = map_byte_locate (&di->m_regbytes, name);
+ if (reg == NULL)
+ {
+ set_last_error (INVALID_REGISTER_NAME, str_duplicate (name), -1);
+ return 0;
+ }
+
+ reg->data = value;
+ return 1;
+}
+
+/*
+ internal checking function used by both grammar_check and grammar_fast_check functions
+*/
+static int _grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size,
+ unsigned int estimate_prod_size, int use_fast_path)
+{
+ dict *di = NULL;
+ int index = 0;
+
+ clear_last_error ();
+
+ dict_find (&g_dicts, id, &di);
+ if (di == NULL)
+ {
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+ }
+
+ *prod = NULL;
+ *size = 0;
+
+ if (use_fast_path)
+ {
+ regbyte_ctx *rbc = NULL;
+ bytepool *bp = NULL;
+ int _P = 0;
+
+ bytepool_create (&bp, estimate_prod_size);
+ if (bp == NULL)
+ return 0;
+
+ if (fast_match (di, text, &index, di->m_syntax, &_P, bp, 0, &rbc) != mr_matched)
+ {
+ bytepool_destroy (&bp);
+ free_regbyte_ctx_stack (rbc, NULL);
+ return 0;
+ }
+
+ free_regbyte_ctx_stack (rbc, NULL);
+
+ *prod = bp->_F;
+ *size = _P;
+ bp->_F = NULL;
+ bytepool_destroy (&bp);
+ }
+ else
+ {
+ regbyte_ctx *rbc = NULL;
+ barray *ba = NULL;
+
+ barray_create (&ba);
+ if (ba == NULL)
+ return 0;
+
+ if (match (di, text, &index, di->m_syntax, &ba, 0, &rbc) != mr_matched)
+ {
+ barray_destroy (&ba);
+ free_regbyte_ctx_stack (rbc, NULL);
+ return 0;
+ }
+
+ free_regbyte_ctx_stack (rbc, NULL);
+
+ *prod = (byte *) mem_alloc (ba->len * sizeof (byte));
+ if (*prod == NULL)
+ {
+ barray_destroy (&ba);
+ return 0;
+ }
+
+ mem_copy (*prod, ba->data, ba->len * sizeof (byte));
+ *size = ba->len;
+ barray_destroy (&ba);
+ }
+
+ return 1;
+}
+
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size)
+{
+ return _grammar_check (id, text, prod, size, 0, 0);
+}
+
+int grammar_fast_check (grammar id, const byte *text, byte **prod, unsigned int *size,
+ unsigned int estimate_prod_size)
+{
+ return _grammar_check (id, text, prod, size, estimate_prod_size, 1);
+}
+
+int grammar_destroy (grammar id)
+{
+ dict **di = &g_dicts;
+
+ clear_last_error ();
+
+ while (*di != NULL)
+ {
+ if ((**di).m_id == id)
+ {
+ dict *tmp = *di;
+ *di = (**di).next;
+ dict_destroy (&tmp);
+ return 1;
+ }
+
+ di = &(**di).next;
+ }
+
+ set_last_error (INVALID_GRAMMAR_ID, NULL, -1);
+ return 0;
+}
+
+static void append_character (const char x, byte *text, int *dots_made, int *len, int size)
+{
+ if (*dots_made == 0)
+ {
+ if (*len < size - 1)
+ {
+ text[(*len)++] = x;
+ text[*len] = '\0';
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < 3; i++)
+ if (--(*len) >= 0)
+ text[*len] = '.';
+ *dots_made = 1;
+ }
+ }
+}
+
+void grammar_get_last_error (byte *text, unsigned int size, int *pos)
+{
+ int len = 0, dots_made = 0;
+ const byte *p = error_message;
+
+ *text = '\0';
+
+ if (p)
+ {
+ while (*p)
+ {
+ if (*p == '$')
+ {
+ const byte *r = error_param;
+
+ while (*r)
+ {
+ append_character (*r++, text, &dots_made, &len, (int) size);
+ }
+
+ p++;
+ }
+ else
+ {
+ append_character (*p++, text, &dots_made, &len, size);
+ }
+ }
+ }
+
+ *pos = error_position;
+}
diff --git a/mesalib/src/mesa/shader/grammar/grammar.h b/mesalib/src/mesa/shader/grammar/grammar.h
new file mode 100644
index 000000000..591e38aef
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar.h
@@ -0,0 +1,103 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2
+ *
+ * Copyright (C) 1999-2004 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 GRAMMAR_H
+#define GRAMMAR_H
+
+
+#ifndef GRAMMAR_PORT_INCLUDE
+#error Do not include this file directly, include your grammar_XXX.h instead
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void grammar_alloc_free (void *);
+void *grammar_alloc_malloc (size_t);
+void *grammar_alloc_realloc (void *, size_t, size_t);
+void *grammar_memory_copy (void *, const void *, size_t);
+int grammar_string_compare (const byte *, const byte *);
+int grammar_string_compare_n (const byte *, const byte *, size_t);
+byte *grammar_string_copy (byte *, const byte *);
+byte *grammar_string_copy_n (byte *, const byte *, size_t);
+byte *grammar_string_duplicate (const byte *);
+unsigned int grammar_string_length (const byte *);
+
+/*
+ loads grammar script from null-terminated ASCII <text>
+ returns unique grammar id to grammar object
+ returns 0 if an error occurs (call grammar_get_last_error to retrieve the error text)
+*/
+grammar grammar_load_from_text (const byte *text);
+
+/*
+ sets a new <value> to a register <name> for grammar <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success
+*/
+int grammar_set_reg8 (grammar id, const byte *name, byte value);
+
+/*
+ this function is obsolete, use only for debugging purposes
+
+ checks if a null-terminated <text> matches given grammar <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success, the <prod> points to newly allocated buffer with production and <size>
+ is filled with the production size
+ call grammar_alloc_free to free the memory block pointed by <prod>
+*/
+int grammar_check (grammar id, const byte *text, byte **prod, unsigned int *size);
+
+/*
+ does the same what grammar_check does but much more (approx. 4 times) faster
+ use this function instead of grammar_check
+ <estimate_prod_size> is a hint - the initial production buffer size will be of this size,
+ but if more room is needed it will be safely resized; set it to 0x1000 or so
+*/
+int grammar_fast_check (grammar id, const byte *text, byte **prod, unsigned int *size,
+ unsigned int estimate_prod_size);
+
+/*
+ destroys grammar object identified by <id>
+ returns 0 on error (call grammar_get_last_error to retrieve the error text)
+ returns 1 on success
+*/
+int grammar_destroy (grammar id);
+
+/*
+ retrieves last grammar error reported either by grammar_load_from_text, grammar_check
+ or grammar_destroy
+ the user allocated <text> buffer receives error description, <pos> points to error position,
+ <size> is the size of the text buffer to fill in - it must be at least 4 bytes long,
+*/
+void grammar_get_last_error (byte *text, unsigned int size, int *pos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/grammar/grammar_crt.c b/mesalib/src/mesa/shader/grammar/grammar_crt.c
new file mode 100644
index 000000000..d2c95d1c8
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar_crt.c
@@ -0,0 +1,64 @@
+#include "grammar_crt.h"
+
+#define GRAMMAR_PORT_BUILD 1
+#include "grammar.c"
+#undef GRAMMAR_PORT_BUILD
+
+
+void grammar_alloc_free (void *ptr)
+{
+ free (ptr);
+}
+
+void *grammar_alloc_malloc (size_t size)
+{
+ return malloc (size);
+}
+
+void *grammar_alloc_realloc (void *ptr, size_t old_size, size_t size)
+{
+ return realloc (ptr, size);
+}
+
+void *grammar_memory_copy (void *dst, const void * src, size_t size)
+{
+ return memcpy (dst, src, size);
+}
+
+int grammar_string_compare (const byte *str1, const byte *str2)
+{
+ return strcmp ((const char *) str1, (const char *) str2);
+}
+
+int grammar_string_compare_n (const byte *str1, const byte *str2, size_t n)
+{
+ return strncmp ((const char *) str1, (const char *) str2, n);
+}
+
+byte *grammar_string_copy (byte *dst, const byte *src)
+{
+ return (byte *) strcpy ((char *) dst, (const char *) src);
+}
+
+byte *grammar_string_copy_n (byte *dst, const byte *src, size_t n)
+{
+ return (byte *) strncpy ((char *) dst, (const char *) src, n);
+}
+
+unsigned int grammar_string_length (const byte *str)
+{
+ return strlen ((const char *) str);
+}
+
+byte *grammar_string_duplicate (const byte *src)
+{
+ const unsigned int size = grammar_string_length (src);
+ byte *str = grammar_alloc_malloc (size + 1);
+ if (str != NULL)
+ {
+ grammar_memory_copy (str, src, size);
+ str[size] = '\0';
+ }
+ return str;
+}
+
diff --git a/mesalib/src/mesa/shader/grammar/grammar_crt.h b/mesalib/src/mesa/shader/grammar/grammar_crt.h
new file mode 100644
index 000000000..492711e96
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar_crt.h
@@ -0,0 +1,20 @@
+#ifndef GRAMMAR_CRT_H
+#define GRAMMAR_CRT_H
+
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+typedef unsigned long grammar;
+typedef unsigned char byte;
+
+
+#define GRAMMAR_PORT_INCLUDE 1
+#include "grammar.h"
+#undef GRAMMAR_PORT_INCLUDE
+
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/grammar/grammar_mesa.c b/mesalib/src/mesa/shader/grammar/grammar_mesa.c
new file mode 100644
index 000000000..eb962505b
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar_mesa.c
@@ -0,0 +1,87 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/**
+ * \file grammar_mesa.c
+ * mesa3d port to syntax parsing engine
+ * \author Michal Krol
+ */
+
+#include "grammar_mesa.h"
+
+#define GRAMMAR_PORT_BUILD 1
+#include "grammar.c"
+#undef GRAMMAR_PORT_BUILD
+
+
+void grammar_alloc_free (void *ptr)
+{
+ _mesa_free (ptr);
+}
+
+void *grammar_alloc_malloc (size_t size)
+{
+ return _mesa_malloc (size);
+}
+
+void *grammar_alloc_realloc (void *ptr, size_t old_size, size_t size)
+{
+ return _mesa_realloc (ptr, old_size, size);
+}
+
+void *grammar_memory_copy (void *dst, const void * src, size_t size)
+{
+ return _mesa_memcpy (dst, src, size);
+}
+
+int grammar_string_compare (const byte *str1, const byte *str2)
+{
+ return _mesa_strcmp ((const char *) str1, (const char *) str2);
+}
+
+int grammar_string_compare_n (const byte *str1, const byte *str2, size_t n)
+{
+ return _mesa_strncmp ((const char *) str1, (const char *) str2, n);
+}
+
+byte *grammar_string_copy (byte *dst, const byte *src)
+{
+ return (byte *) _mesa_strcpy ((char *) dst, (const char *) src);
+}
+
+byte *grammar_string_copy_n (byte *dst, const byte *src, size_t n)
+{
+ return (byte *) _mesa_strncpy ((char *) dst, (const char *) src, n);
+}
+
+byte *grammar_string_duplicate (const byte *src)
+{
+ return (byte *) _mesa_strdup ((const char *) src);
+}
+
+unsigned int grammar_string_length (const byte *str)
+{
+ return (unsigned int)_mesa_strlen ((const char *) str);
+}
+
diff --git a/mesalib/src/mesa/shader/grammar/grammar_mesa.h b/mesalib/src/mesa/shader/grammar/grammar_mesa.h
new file mode 100644
index 000000000..6c92c5812
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar_mesa.h
@@ -0,0 +1,43 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 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 GRAMMAR_MESA_H
+#define GRAMMAR_MESA_H
+
+
+#include "main/imports.h"
+/* NOTE: include Mesa 3-D specific headers here */
+
+
+typedef GLuint grammar;
+typedef GLubyte byte;
+
+
+#define GRAMMAR_PORT_INCLUDE 1
+#include "grammar.h"
+#undef GRAMMAR_PORT_INCLUDE
+
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/grammar/grammar_syn.h b/mesalib/src/mesa/shader/grammar/grammar_syn.h
new file mode 100644
index 000000000..840a1ab62
--- /dev/null
+++ b/mesalib/src/mesa/shader/grammar/grammar_syn.h
@@ -0,0 +1,202 @@
+".syntax grammar;\n"
+".emtcode DECLARATION_END 0\n"
+".emtcode DECLARATION_EMITCODE 1\n"
+".emtcode DECLARATION_ERRORTEXT 2\n"
+".emtcode DECLARATION_REGBYTE 3\n"
+".emtcode DECLARATION_LEXER 4\n"
+".emtcode DECLARATION_RULE 5\n"
+".emtcode SPECIFIER_END 0\n"
+".emtcode SPECIFIER_AND_TAG 1\n"
+".emtcode SPECIFIER_OR_TAG 2\n"
+".emtcode SPECIFIER_CHARACTER_RANGE 3\n"
+".emtcode SPECIFIER_CHARACTER 4\n"
+".emtcode SPECIFIER_STRING 5\n"
+".emtcode SPECIFIER_IDENTIFIER 6\n"
+".emtcode SPECIFIER_TRUE 7\n"
+".emtcode SPECIFIER_FALSE 8\n"
+".emtcode SPECIFIER_DEBUG 9\n"
+".emtcode IDENTIFIER_SIMPLE 0\n"
+".emtcode IDENTIFIER_LOOP 1\n"
+".emtcode ERROR_NOT_PRESENT 0\n"
+".emtcode ERROR_PRESENT 1\n"
+".emtcode EMIT_NULL 0\n"
+".emtcode EMIT_INTEGER 1\n"
+".emtcode EMIT_IDENTIFIER 2\n"
+".emtcode EMIT_CHARACTER 3\n"
+".emtcode EMIT_LAST_CHARACTER 4\n"
+".emtcode EMIT_CURRENT_POSITION 5\n"
+".errtext INVALID_GRAMMAR \"internal error 2001: invalid grammar script\"\n"
+".errtext SYNTAX_EXPECTED \"internal error 2002: '.syntax' keyword expected\"\n"
+".errtext IDENTIFIER_EXPECTED \"internal error 2003: identifier expected\"\n"
+".errtext MISSING_SEMICOLON \"internal error 2004: missing ';'\"\n"
+".errtext INTEGER_EXPECTED \"internal error 2005: integer value expected\"\n"
+".errtext STRING_EXPECTED \"internal error 2006: string expected\"\n"
+"grammar\n"
+" grammar_1 .error INVALID_GRAMMAR;\n"
+"grammar_1\n"
+" optional_space .and \".syntax\" .error SYNTAX_EXPECTED .and space .and identifier .and\n"
+" semicolon .and declaration_list .and optional_space .and '\\0' .emit DECLARATION_END;\n"
+"optional_space\n"
+" space .or .true;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or '\\n' .or '\\r';\n"
+"comment_block\n"
+" '/' .and '*' .and comment_rest;\n"
+"comment_rest\n"
+" .loop comment_char_no_star .and comment_rest_1;\n"
+"comment_rest_1\n"
+" comment_end .or comment_rest_2;\n"
+"comment_rest_2\n"
+" '*' .and comment_rest;\n"
+"comment_char_no_star\n"
+" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"comment_end\n"
+" '*' .and '/';\n"
+"identifier\n"
+" identifier_ne .error IDENTIFIER_EXPECTED;\n"
+"identifier_ne\n"
+" first_idchar .emit * .and .loop follow_idchar .emit * .and .true .emit '\\0';\n"
+"first_idchar\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"follow_idchar\n"
+" first_idchar .or digit_dec;\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"semicolon\n"
+" optional_space .and ';' .error MISSING_SEMICOLON .and optional_space;\n"
+"declaration_list\n"
+" declaration .and .loop declaration;\n"
+"declaration\n"
+" emitcode_definition .emit DECLARATION_EMITCODE .or\n"
+" errortext_definition .emit DECLARATION_ERRORTEXT .or\n"
+" regbyte_definition .emit DECLARATION_REGBYTE .or\n"
+" lexer_definition .emit DECLARATION_LEXER .or\n"
+" rule_definition .emit DECLARATION_RULE;\n"
+"emitcode_definition\n"
+" \".emtcode\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"integer\n"
+" integer_ne .error INTEGER_EXPECTED;\n"
+"integer_ne\n"
+" hex_integer .emit 0x10 .or dec_integer .emit 10;\n"
+"hex_integer\n"
+" hex_prefix .and digit_hex .emit * .and .loop digit_hex .emit * .and .true .emit '\\0';\n"
+"hex_prefix\n"
+" '0' .and hex_prefix_1;\n"
+"hex_prefix_1\n"
+" 'x' .or 'X';\n"
+"digit_hex\n"
+" '0'-'9' .or 'a'-'f' .or 'A'-'F';\n"
+"dec_integer\n"
+" digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n"
+"space_or_null\n"
+" space .or '\\0';\n"
+"errortext_definition\n"
+" \".errtext\" .and space .and identifier .and space .and string .and space_or_null;\n"
+"string\n"
+" string_ne .error STRING_EXPECTED;\n"
+"string_ne\n"
+" '\"' .and .loop string_char_double_quotes .and '\"' .emit '\\0';\n"
+"string_char_double_quotes\n"
+" escape_sequence .or string_char .emit * .or '\\'' .emit *;\n"
+"string_char\n"
+" '\\x5D'-'\\xFF' .or '\\x28'-'\\x5B' .or '\\x23'-'\\x26' .or '\\x0E'-'\\x21' .or '\\x0B'-'\\x0C' .or\n"
+" '\\x01'-'\\x09';\n"
+"escape_sequence\n"
+" '\\\\' .emit * .and escape_code;\n"
+"escape_code\n"
+" simple_escape_code .emit * .or hex_escape_code .or oct_escape_code;\n"
+"simple_escape_code\n"
+" '\\'' .or '\"' .or '?' .or '\\\\' .or 'a' .or 'b' .or 'f' .or 'n' .or 'r' .or 't' .or 'v';\n"
+"hex_escape_code\n"
+" 'x' .emit * .and digit_hex .emit * .and .loop digit_hex .emit *;\n"
+"oct_escape_code\n"
+" digit_oct .emit * .and optional_digit_oct .and optional_digit_oct;\n"
+"digit_oct\n"
+" '0'-'7';\n"
+"optional_digit_oct\n"
+" digit_oct .emit * .or .true;\n"
+"regbyte_definition\n"
+" \".regbyte\" .and space .and identifier .and space .and integer .and space_or_null;\n"
+"lexer_definition\n"
+" \".string\" .and space .and identifier .and semicolon;\n"
+"rule_definition\n"
+" identifier_ne .and space .and definition;\n"
+"definition\n"
+" specifier .and optional_specifiers_and_or .and semicolon .emit SPECIFIER_END;\n"
+"optional_specifiers_and_or\n"
+" and_specifiers .emit SPECIFIER_AND_TAG .or or_specifiers .emit SPECIFIER_OR_TAG .or .true;\n"
+"specifier\n"
+" specifier_condition .and optional_space .and specifier_rule;\n"
+"specifier_condition\n"
+" specifier_condition_1 .or .true;\n"
+"specifier_condition_1\n"
+" \".if\" .and optional_space .and '(' .and optional_space .and left_operand .and operator .and\n"
+" right_operand .and optional_space .and ')';\n"
+"left_operand\n"
+" identifier;\n"
+"operator\n"
+" operator_1 .or operator_2;\n"
+"operator_1\n"
+" optional_space .and '!' .and '=' .and optional_space;\n"
+"operator_2\n"
+" optional_space .and '=' .and '=' .and optional_space;\n"
+"right_operand\n"
+" integer;\n"
+"specifier_rule\n"
+" specifier_rule_1 .and optional_error .and .loop emit .and .true .emit EMIT_NULL;\n"
+"specifier_rule_1\n"
+" character_range .emit SPECIFIER_CHARACTER_RANGE .or\n"
+" character .emit SPECIFIER_CHARACTER .or\n"
+" string_ne .emit SPECIFIER_STRING .or\n"
+" \".true\" .emit SPECIFIER_TRUE .or\n"
+" \".false\" .emit SPECIFIER_FALSE .or\n"
+" \".debug\" .emit SPECIFIER_DEBUG .or\n"
+" advanced_identifier .emit SPECIFIER_IDENTIFIER;\n"
+"character\n"
+" '\\'' .and string_char_single_quotes .and '\\'' .emit '\\0';\n"
+"string_char_single_quotes\n"
+" escape_sequence .or string_char .emit * .or '\"' .emit *;\n"
+"character_range\n"
+" character .and optional_space .and '-' .and optional_space .and character;\n"
+"advanced_identifier\n"
+" optional_loop .and identifier;\n"
+"optional_loop\n"
+" optional_loop_1 .emit IDENTIFIER_LOOP .or .true .emit IDENTIFIER_SIMPLE;\n"
+"optional_loop_1\n"
+" \".loop\" .and space;\n"
+"optional_error\n"
+" error .emit ERROR_PRESENT .or .true .emit ERROR_NOT_PRESENT;\n"
+"error\n"
+" space .and \".error\" .and space .and identifier;\n"
+"emit\n"
+" emit_output .or emit_regbyte;\n"
+"emit_output\n"
+" space .and \".emit\" .and space .and emit_param;\n"
+"emit_param\n"
+" integer_ne .emit EMIT_INTEGER .or\n"
+" identifier_ne .emit EMIT_IDENTIFIER .or\n"
+" character .emit EMIT_CHARACTER .or\n"
+" '*' .emit EMIT_LAST_CHARACTER .or\n"
+" '$' .emit EMIT_CURRENT_POSITION;\n"
+"emit_regbyte\n"
+" space .and \".load\" .and space .and identifier .and space .and emit_param;\n"
+"and_specifiers\n"
+" and_specifier .and .loop and_specifier;\n"
+"or_specifiers\n"
+" or_specifier .and .loop or_specifier;\n"
+"and_specifier\n"
+" space .and \".and\" .and space .and specifier;\n"
+"or_specifier\n"
+" space .and \".or\" .and space .and specifier;\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" __first_identifier_char .and .loop __next_identifier_char;\n"
+"__first_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '.';\n"
+"__next_identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
+""
diff --git a/mesalib/src/mesa/shader/hash_table.c b/mesalib/src/mesa/shader/hash_table.c
new file mode 100644
index 000000000..881179f9d
--- /dev/null
+++ b/mesalib/src/mesa/shader/hash_table.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file hash_table.c
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "hash_table.h"
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+struct hash_table {
+ hash_func_t hash;
+ hash_compare_func_t compare;
+
+ unsigned num_buckets;
+ struct node buckets[1];
+};
+
+
+struct hash_node {
+ struct node link;
+ const void *key;
+ void *data;
+};
+
+
+struct hash_table *
+hash_table_ctor(unsigned num_buckets, hash_func_t hash,
+ hash_compare_func_t compare)
+{
+ struct hash_table *ht;
+ unsigned i;
+
+
+ if (num_buckets < 16) {
+ num_buckets = 16;
+ }
+
+ ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)
+ * sizeof(ht->buckets[0])));
+ if (ht != NULL) {
+ ht->hash = hash;
+ ht->compare = compare;
+ ht->num_buckets = num_buckets;
+
+ for (i = 0; i < num_buckets; i++) {
+ make_empty_list(& ht->buckets[i]);
+ }
+ }
+
+ return ht;
+}
+
+
+void
+hash_table_dtor(struct hash_table *ht)
+{
+ hash_table_clear(ht);
+ _mesa_free(ht);
+}
+
+
+void
+hash_table_clear(struct hash_table *ht)
+{
+ struct node *node;
+ struct node *temp;
+ unsigned i;
+
+
+ for (i = 0; i < ht->num_buckets; i++) {
+ foreach_s(node, temp, & ht->buckets[i]) {
+ remove_from_list(node);
+ _mesa_free(node);
+ }
+
+ assert(is_empty_list(& ht->buckets[i]));
+ }
+}
+
+
+void *
+hash_table_find(struct hash_table *ht, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct node *node;
+
+ foreach(node, & ht->buckets[bucket]) {
+ struct hash_node *hn = (struct hash_node *) node;
+
+ if ((*ht->compare)(hn->key, key) == 0) {
+ return hn->data;
+ }
+ }
+
+ return NULL;
+}
+
+
+void
+hash_table_insert(struct hash_table *ht, void *data, const void *key)
+{
+ const unsigned hash_value = (*ht->hash)(key);
+ const unsigned bucket = hash_value % ht->num_buckets;
+ struct hash_node *node;
+
+ node = _mesa_calloc(sizeof(*node));
+
+ node->data = data;
+ node->key = key;
+
+ insert_at_head(& ht->buckets[bucket], & node->link);
+}
+
+
+unsigned
+hash_table_string_hash(const void *key)
+{
+ const char *str = (const char *) key;
+ unsigned hash = 5381;
+
+
+ while (*str != '\0') {
+ hash = (hash * 33) + *str;
+ str++;
+ }
+
+ return hash;
+}
diff --git a/mesalib/src/mesa/shader/hash_table.h b/mesalib/src/mesa/shader/hash_table.h
new file mode 100644
index 000000000..7b302f5db
--- /dev/null
+++ b/mesalib/src/mesa/shader/hash_table.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file hash_table.h
+ * \brief Implementation of a generic, opaque hash table data type.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#ifndef HASH_TABLE_H
+#define HASH_TABLE_H
+
+#include <string.h>
+
+struct hash_table;
+
+typedef unsigned (*hash_func_t)(const void *key);
+typedef int (*hash_compare_func_t)(const void *key1, const void *key2);
+
+/**
+ * Hash table constructor
+ *
+ * Creates a hash table with the specified number of buckets. The supplied
+ * \c hash and \c compare routines are used when adding elements to the table
+ * and when searching for elements in the table.
+ *
+ * \param num_buckets Number of buckets (bins) in the hash table.
+ * \param hash Function used to compute hash value of input keys.
+ * \param compare Function used to compare keys.
+ */
+extern struct hash_table *hash_table_ctor(unsigned num_buckets,
+ hash_func_t hash, hash_compare_func_t compare);
+
+
+/**
+ * Release all memory associated with a hash table
+ *
+ * \warning
+ * This function cannot release memory occupied either by keys or data.
+ */
+extern void hash_table_dtor(struct hash_table *ht);
+
+
+/**
+ * Flush all entries from a hash table
+ *
+ * \param ht Table to be cleared of its entries.
+ */
+extern void hash_table_clear(struct hash_table *ht);
+
+
+/**
+ * Search a hash table for a specific element
+ *
+ * \param ht Table to be searched
+ * \param key Key of the desired element
+ *
+ * \return
+ * The \c data value supplied to \c hash_table_insert when the element with
+ * the matching key was added. If no matching key exists in the table,
+ * \c NULL is returned.
+ */
+extern void *hash_table_find(struct hash_table *ht, const void *key);
+
+
+/**
+ * Add an element to a hash table
+ */
+extern void hash_table_insert(struct hash_table *ht, void *data,
+ const void *key);
+
+
+/**
+ * Compute hash value of a string
+ *
+ * Computes the hash value of a string using the DJB2 algorithm developed by
+ * Professor Daniel J. Bernstein. It was published on comp.lang.c once upon
+ * a time. I was unable to find the original posting in the archives.
+ *
+ * \param key Pointer to a NUL terminated string to be hashed.
+ *
+ * \sa hash_table_string_compare
+ */
+extern unsigned hash_table_string_hash(const void *key);
+
+
+/**
+ * Compare two strings used as keys
+ *
+ * This is just a macro wrapper around \c strcmp.
+ *
+ * \sa hash_table_string_hash
+ */
+#define hash_table_string_compare ((hash_compare_func_t) strcmp)
+
+#endif /* HASH_TABLE_H */
diff --git a/mesalib/src/mesa/shader/lex.yy.c b/mesalib/src/mesa/shader/lex.yy.c
new file mode 100644
index 000000000..709426f3a
--- /dev/null
+++ b/mesalib/src/mesa/shader/lex.yy.c
@@ -0,0 +1,3574 @@
+
+#line 3 "lex.yy.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 183
+#define YY_END_OF_BUFFER 184
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[675] =
+ { 0,
+ 0, 0, 184, 182, 180, 179, 182, 182, 152, 178,
+ 154, 154, 154, 154, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 180, 0, 0, 181, 152, 0,
+ 153, 155, 175, 175, 0, 0, 0, 0, 175, 0,
+ 0, 0, 0, 0, 0, 0, 132, 176, 133, 134,
+ 166, 166, 166, 166, 0, 154, 0, 140, 141, 142,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 174, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 173, 173, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 172, 172, 172, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 163, 163, 163, 164, 164, 165, 156,
+ 155, 156, 0, 157, 11, 13, 152, 15, 152, 152,
+ 16, 18, 152, 20, 22, 24, 26, 6, 28, 30,
+ 31, 33, 35, 38, 36, 40, 41, 43, 45, 47,
+
+ 49, 51, 152, 152, 152, 53, 55, 152, 57, 59,
+ 61, 152, 63, 65, 67, 69, 152, 71, 73, 75,
+ 77, 152, 152, 152, 152, 152, 152, 0, 0, 0,
+ 0, 155, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 93, 94, 96, 0, 171, 0, 0, 0,
+ 0, 0, 0, 110, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 170, 169, 169, 122, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 160, 160,
+ 161, 162, 0, 158, 152, 152, 152, 152, 152, 152,
+ 152, 152, 143, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 144, 152, 152, 152, 152, 152, 152,
+ 152, 152, 10, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 0, 177, 0, 0, 0, 86, 87,
+ 0, 0, 0, 0, 0, 0, 0, 98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 168, 0, 0, 0,
+ 126, 0, 128, 0, 0, 0, 0, 0, 0, 167,
+ 159, 152, 152, 152, 4, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 9, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 82, 152, 152, 0, 0, 0,
+ 0, 0, 88, 89, 0, 0, 0, 0, 97, 0,
+ 0, 101, 104, 0, 0, 0, 0, 0, 0, 0,
+ 115, 116, 0, 0, 0, 0, 121, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 152, 152, 152,
+ 152, 152, 152, 5, 152, 152, 152, 152, 152, 152,
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 152,
+ 152, 7, 8, 152, 152, 152, 152, 152, 152, 152,
+
+ 152, 152, 152, 152, 152, 152, 152, 152, 152, 83,
+ 152, 79, 0, 0, 0, 0, 137, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 107, 0, 111, 112,
+ 0, 114, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 130, 131, 0, 0, 138, 12, 3, 14,
+ 148, 149, 152, 17, 19, 21, 23, 25, 27, 29,
+ 32, 34, 39, 37, 42, 44, 46, 48, 50, 52,
+ 54, 56, 58, 60, 62, 152, 152, 152, 64, 66,
+ 68, 70, 72, 74, 76, 78, 152, 81, 139, 0,
+ 0, 84, 0, 90, 0, 0, 0, 99, 0, 0,
+
+ 0, 0, 0, 0, 113, 0, 0, 119, 106, 0,
+ 0, 0, 0, 0, 0, 135, 0, 152, 145, 146,
+ 152, 80, 0, 0, 0, 0, 92, 95, 100, 0,
+ 0, 105, 0, 0, 0, 118, 0, 0, 0, 0,
+ 127, 129, 0, 152, 152, 2, 1, 0, 91, 0,
+ 103, 0, 109, 117, 0, 0, 124, 125, 136, 152,
+ 147, 0, 102, 0, 120, 123, 152, 85, 108, 152,
+ 152, 150, 151, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 5, 1, 6, 7, 1, 1, 1, 1,
+ 1, 1, 8, 1, 8, 9, 1, 10, 11, 12,
+ 13, 14, 15, 15, 15, 15, 15, 1, 1, 1,
+ 1, 1, 1, 1, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 7, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 1, 1, 1, 1, 41, 1, 42, 43, 44, 45,
+
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 66, 67, 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, 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, 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
+ } ;
+
+static yyconst flex_int32_t yy_meta[68] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 2, 1, 3, 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,
+ 2, 2, 2, 2, 2, 2, 2
+ } ;
+
+static yyconst flex_int16_t yy_base[678] =
+ { 0,
+ 0, 0, 954, 955, 66, 955, 948, 949, 0, 69,
+ 85, 128, 140, 152, 151, 58, 39, 48, 75, 927,
+ 158, 160, 73, 59, 71, 170, 54, 920, 890, 889,
+ 901, 885, 899, 898, 142, 927, 939, 955, 0, 206,
+ 955, 189, 168, 171, 53, 27, 66, 119, 175, 899,
+ 885, 123, 170, 883, 895, 183, 955, 198, 225, 99,
+ 212, 219, 223, 227, 285, 297, 308, 955, 955, 955,
+ 904, 917, 911, 165, 900, 903, 899, 914, 224, 896,
+ 910, 194, 896, 909, 900, 913, 890, 901, 892, 294,
+ 893, 884, 893, 884, 883, 884, 878, 884, 895, 881,
+
+ 878, 890, 893, 880, 873, 889, 865, 193, 139, 885,
+ 861, 846, 841, 858, 834, 839, 865, 167, 854, 259,
+ 849, 325, 282, 851, 832, 302, 842, 838, 833, 43,
+ 839, 825, 841, 838, 829, 305, 309, 831, 820, 834,
+ 837, 819, 834, 821, 818, 825, 275, 833, 254, 299,
+ 317, 327, 331, 810, 827, 828, 821, 803, 310, 804,
+ 826, 817, 316, 327, 331, 335, 339, 343, 347, 955,
+ 405, 416, 422, 428, 825, 240, 849, 0, 848, 831,
+ 821, 820, 840, 818, 817, 816, 815, 0, 814, 0,
+ 813, 812, 0, 811, 810, 0, 809, 808, 807, 806,
+
+ 805, 804, 820, 813, 826, 800, 799, 805, 797, 796,
+ 795, 816, 793, 792, 791, 790, 800, 788, 787, 786,
+ 785, 777, 776, 761, 761, 760, 759, 802, 774, 762,
+ 434, 442, 416, 766, 186, 763, 757, 757, 751, 764,
+ 764, 749, 955, 955, 764, 752, 418, 759, 281, 756,
+ 762, 308, 757, 955, 748, 755, 754, 757, 743, 742,
+ 746, 741, 278, 746, 420, 428, 430, 955, 738, 736,
+ 736, 744, 745, 727, 421, 732, 738, 419, 426, 430,
+ 434, 438, 496, 502, 752, 764, 750, 749, 742, 756,
+ 746, 745, 0, 744, 743, 742, 741, 740, 739, 738,
+
+ 737, 736, 735, 734, 733, 732, 731, 730, 733, 726,
+ 733, 726, 725, 0, 724, 723, 722, 725, 720, 719,
+ 718, 717, 0, 716, 715, 714, 713, 691, 685, 690,
+ 696, 679, 694, 315, 955, 693, 683, 687, 955, 955,
+ 677, 686, 672, 689, 672, 675, 669, 955, 670, 669,
+ 666, 673, 666, 674, 670, 680, 677, 659, 665, 672,
+ 656, 655, 673, 655, 667, 666, 955, 665, 655, 659,
+ 955, 646, 955, 651, 651, 659, 642, 643, 653, 955,
+ 955, 685, 667, 683, 0, 507, 681, 681, 680, 679,
+ 678, 677, 676, 675, 674, 673, 672, 671, 670, 669,
+
+ 668, 667, 666, 665, 652, 645, 0, 662, 661, 660,
+ 659, 658, 636, 656, 655, 654, 653, 652, 651, 650,
+ 649, 618, 621, 601, 0, 602, 595, 602, 601, 602,
+ 594, 612, 955, 955, 594, 592, 602, 595, 955, 590,
+ 607, 330, 955, 598, 582, 583, 592, 583, 582, 582,
+ 955, 581, 590, 580, 596, 593, 955, 592, 590, 579,
+ 580, 576, 568, 575, 570, 571, 566, 592, 592, 590,
+ 604, 603, 598, 0, 586, 585, 584, 583, 582, 581,
+ 580, 579, 578, 577, 576, 575, 574, 573, 572, 571,
+ 570, 0, 0, 569, 568, 567, 566, 565, 509, 564,
+
+ 563, 562, 561, 560, 559, 558, 557, 535, 535, 0,
+ 542, 0, 576, 575, 524, 542, 955, 537, 532, 525,
+ 521, 533, 523, 521, 517, 533, 524, 523, 955, 955,
+ 526, 955, 521, 514, 503, 514, 506, 510, 523, 518,
+ 521, 503, 955, 955, 515, 504, 955, 0, 0, 0,
+ 0, 0, 543, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 539, 538, 536, 0, 0,
+ 0, 0, 0, 0, 0, 0, 494, 0, 0, 545,
+ 544, 955, 491, 955, 495, 495, 504, 955, 488, 502,
+
+ 483, 485, 482, 490, 955, 468, 479, 955, 955, 483,
+ 479, 472, 470, 470, 483, 955, 467, 507, 0, 0,
+ 507, 0, 514, 513, 472, 433, 955, 955, 955, 435,
+ 435, 955, 429, 386, 377, 955, 366, 365, 323, 328,
+ 955, 955, 339, 348, 337, 955, 955, 307, 955, 305,
+ 955, 257, 955, 955, 247, 221, 955, 955, 955, 236,
+ 0, 213, 955, 150, 955, 955, 232, 955, 955, 162,
+ 138, 0, 0, 955, 541, 108, 544
+ } ;
+
+static yyconst flex_int16_t yy_def[678] =
+ { 0,
+ 674, 1, 674, 674, 674, 674, 674, 675, 676, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 674, 674, 675, 674, 676, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 677, 674, 674, 674, 674, 674,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 676, 676, 676, 676, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 676, 676, 676,
+ 676, 676, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 676, 676, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 676,
+ 676, 674, 674, 674, 674, 674, 676, 674, 674, 676,
+ 676, 676, 676, 0, 674, 674, 674
+ } ;
+
+static yyconst flex_int16_t yy_nxt[1023] =
+ { 0,
+ 4, 5, 6, 5, 7, 8, 9, 4, 10, 11,
+ 12, 13, 14, 11, 11, 15, 9, 16, 17, 18,
+ 19, 9, 9, 9, 20, 21, 22, 9, 23, 24,
+ 9, 25, 26, 27, 9, 9, 9, 28, 9, 9,
+ 9, 9, 9, 9, 9, 9, 29, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 30, 9, 31, 32,
+ 33, 9, 34, 9, 9, 9, 9, 35, 79, 35,
+ 40, 80, 129, 108, 96, 81, 130, 41, 42, 42,
+ 42, 42, 42, 42, 76, 82, 77, 97, 98, 240,
+ 99, 109, 78, 65, 66, 66, 66, 66, 66, 66,
+
+ 83, 241, 94, 100, 67, 127, 84, 95, 128, 39,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 131,
+ 132, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 67, 133, 61, 62, 63, 64, 65, 66, 66, 66,
+ 66, 66, 66, 35, 160, 35, 68, 67, 65, 66,
+ 66, 66, 66, 66, 66, 219, 673, 161, 69, 67,
+ 65, 66, 66, 66, 66, 66, 66, 71, 220, 72,
+ 70, 67, 140, 67, 134, 90, 73, 135, 141, 86,
+ 672, 87, 74, 91, 75, 67, 88, 101, 92, 89,
+ 178, 102, 103, 104, 93, 105, 179, 67, 42, 42,
+
+ 42, 42, 42, 42, 106, 189, 107, 40, 122, 123,
+ 123, 142, 126, 123, 669, 123, 136, 137, 123, 217,
+ 124, 124, 123, 190, 147, 143, 123, 125, 125, 123,
+ 218, 337, 144, 123, 122, 148, 184, 185, 149, 151,
+ 152, 150, 670, 671, 338, 153, 186, 118, 119, 45,
+ 46, 47, 48, 154, 50, 51, 123, 162, 52, 53,
+ 54, 55, 56, 57, 120, 59, 60, 668, 155, 121,
+ 156, 286, 667, 157, 158, 163, 163, 163, 163, 666,
+ 287, 159, 164, 163, 165, 166, 167, 163, 163, 168,
+ 169, 163, 163, 163, 171, 171, 171, 171, 171, 171,
+
+ 230, 665, 664, 260, 172, 65, 66, 66, 66, 66,
+ 66, 66, 198, 261, 154, 173, 67, 174, 174, 174,
+ 174, 174, 174, 233, 233, 364, 349, 257, 365, 233,
+ 172, 199, 231, 258, 232, 232, 232, 232, 232, 232,
+ 233, 350, 67, 233, 233, 236, 233, 233, 262, 233,
+ 247, 233, 233, 353, 263, 273, 233, 663, 233, 233,
+ 233, 428, 662, 233, 233, 274, 354, 233, 265, 233,
+ 661, 264, 266, 267, 233, 233, 660, 429, 233, 278,
+ 278, 278, 278, 524, 659, 233, 525, 658, 657, 233,
+ 278, 278, 278, 278, 279, 278, 278, 280, 281, 278,
+
+ 278, 278, 278, 278, 278, 278, 282, 278, 278, 278,
+ 278, 278, 278, 278, 42, 42, 42, 42, 42, 42,
+ 656, 655, 654, 283, 122, 284, 284, 284, 284, 284,
+ 284, 174, 174, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 232, 232, 232, 232, 232, 232, 653,
+ 122, 232, 232, 232, 232, 232, 232, 335, 335, 335,
+ 335, 335, 335, 335, 374, 335, 375, 335, 376, 335,
+ 335, 367, 335, 652, 335, 335, 335, 335, 335, 651,
+ 650, 377, 380, 380, 380, 380, 335, 649, 335, 380,
+ 380, 380, 380, 381, 380, 380, 380, 380, 380, 380,
+
+ 380, 380, 380, 380, 380, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 471, 472, 576,
+ 577, 648, 647, 646, 645, 644, 643, 642, 641, 640,
+ 639, 638, 637, 636, 635, 634, 633, 632, 631, 473,
+ 578, 37, 37, 37, 170, 170, 630, 629, 628, 627,
+ 626, 625, 624, 623, 622, 621, 620, 619, 618, 617,
+ 616, 615, 614, 613, 612, 611, 610, 609, 608, 607,
+ 606, 605, 604, 603, 602, 601, 600, 599, 598, 597,
+ 596, 595, 594, 593, 592, 591, 590, 589, 588, 587,
+ 586, 585, 584, 583, 582, 581, 580, 579, 575, 574,
+
+ 573, 572, 571, 570, 569, 568, 567, 566, 565, 564,
+ 563, 562, 561, 560, 559, 558, 557, 556, 555, 554,
+ 553, 552, 551, 550, 549, 548, 547, 546, 545, 544,
+ 543, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 532, 531, 530, 529, 528, 527, 526, 523, 522,
+ 521, 520, 519, 518, 517, 516, 515, 514, 513, 512,
+ 511, 510, 509, 508, 507, 506, 505, 504, 503, 502,
+ 501, 500, 499, 498, 497, 496, 495, 494, 493, 492,
+ 491, 490, 489, 488, 487, 486, 485, 484, 483, 482,
+ 481, 480, 479, 478, 477, 476, 475, 474, 470, 469,
+
+ 468, 467, 466, 465, 464, 463, 462, 461, 460, 459,
+ 458, 457, 456, 455, 454, 453, 452, 451, 450, 449,
+ 448, 447, 446, 445, 444, 443, 442, 441, 440, 439,
+ 438, 437, 436, 435, 434, 433, 432, 431, 430, 427,
+ 426, 425, 424, 423, 422, 421, 420, 419, 418, 417,
+ 416, 415, 414, 413, 412, 411, 410, 409, 408, 407,
+ 406, 405, 404, 403, 402, 401, 400, 399, 398, 397,
+ 396, 395, 394, 393, 392, 391, 390, 389, 388, 387,
+ 386, 385, 384, 383, 382, 379, 378, 373, 372, 371,
+ 370, 369, 368, 366, 363, 362, 361, 360, 359, 358,
+
+ 357, 356, 355, 352, 351, 348, 347, 346, 345, 344,
+ 343, 342, 341, 340, 339, 336, 264, 236, 334, 333,
+ 332, 331, 330, 329, 328, 327, 326, 325, 324, 323,
+ 322, 321, 320, 319, 318, 317, 316, 315, 314, 313,
+ 312, 311, 310, 309, 308, 307, 306, 305, 304, 303,
+ 302, 301, 300, 299, 298, 297, 296, 295, 294, 293,
+ 292, 291, 290, 289, 288, 285, 277, 276, 275, 272,
+ 271, 270, 269, 268, 259, 256, 255, 254, 253, 252,
+ 251, 250, 249, 248, 246, 245, 244, 243, 242, 239,
+ 238, 237, 235, 234, 162, 229, 228, 227, 226, 225,
+
+ 224, 223, 222, 221, 216, 215, 214, 213, 212, 211,
+ 210, 209, 208, 207, 206, 205, 204, 203, 202, 201,
+ 200, 197, 196, 195, 194, 193, 192, 191, 188, 187,
+ 183, 182, 181, 180, 177, 176, 175, 146, 145, 139,
+ 138, 38, 117, 116, 115, 114, 113, 112, 111, 110,
+ 85, 38, 36, 674, 3, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674
+ } ;
+
+static yyconst flex_int16_t yy_chk[1023] =
+ { 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, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 5, 17, 5,
+ 10, 17, 46, 27, 24, 18, 46, 10, 10, 10,
+ 10, 10, 10, 10, 16, 18, 16, 24, 25, 130,
+ 25, 27, 16, 11, 11, 11, 11, 11, 11, 11,
+
+ 19, 130, 23, 25, 11, 45, 19, 23, 45, 676,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 47,
+ 47, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 47, 10, 10, 10, 10, 12, 12, 12, 12,
+ 12, 12, 12, 35, 60, 35, 12, 12, 13, 13,
+ 13, 13, 13, 13, 13, 109, 671, 60, 13, 13,
+ 14, 14, 14, 14, 14, 14, 14, 15, 109, 15,
+ 14, 14, 52, 12, 48, 22, 15, 48, 52, 21,
+ 670, 21, 15, 22, 15, 13, 21, 26, 22, 21,
+ 74, 26, 26, 26, 22, 26, 74, 14, 42, 42,
+
+ 42, 42, 42, 42, 26, 82, 26, 40, 42, 43,
+ 43, 53, 44, 44, 664, 43, 49, 49, 44, 108,
+ 118, 43, 49, 82, 56, 53, 43, 118, 43, 44,
+ 108, 235, 53, 49, 42, 56, 79, 79, 56, 58,
+ 58, 56, 667, 667, 235, 58, 79, 40, 40, 40,
+ 40, 40, 40, 58, 40, 40, 58, 61, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 662, 59, 40,
+ 59, 176, 660, 59, 59, 61, 61, 61, 61, 656,
+ 176, 59, 62, 62, 62, 62, 63, 63, 63, 63,
+ 64, 64, 64, 64, 65, 65, 65, 65, 65, 65,
+
+ 120, 655, 652, 149, 65, 66, 66, 66, 66, 66,
+ 66, 66, 90, 149, 120, 67, 66, 67, 67, 67,
+ 67, 67, 67, 123, 123, 263, 249, 147, 263, 123,
+ 65, 90, 122, 147, 122, 122, 122, 122, 122, 122,
+ 123, 249, 66, 126, 126, 126, 136, 136, 150, 126,
+ 137, 137, 136, 252, 150, 159, 137, 650, 151, 151,
+ 126, 334, 648, 136, 151, 159, 252, 137, 152, 152,
+ 645, 151, 153, 153, 152, 151, 644, 334, 153, 163,
+ 163, 163, 163, 442, 643, 152, 442, 640, 639, 153,
+ 164, 164, 164, 164, 165, 165, 165, 165, 166, 166,
+
+ 166, 166, 167, 167, 167, 167, 168, 168, 168, 168,
+ 169, 169, 169, 169, 171, 171, 171, 171, 171, 171,
+ 638, 637, 635, 172, 171, 172, 172, 172, 172, 172,
+ 172, 173, 173, 173, 173, 173, 173, 174, 174, 174,
+ 174, 174, 174, 231, 231, 231, 231, 231, 231, 634,
+ 171, 232, 232, 232, 232, 232, 232, 233, 233, 247,
+ 247, 265, 265, 233, 275, 247, 275, 265, 275, 266,
+ 266, 267, 267, 633, 233, 266, 247, 267, 265, 631,
+ 630, 275, 278, 278, 278, 278, 266, 626, 267, 279,
+ 279, 279, 279, 280, 280, 280, 280, 281, 281, 281,
+
+ 281, 282, 282, 282, 282, 283, 283, 283, 283, 283,
+ 283, 284, 284, 284, 284, 284, 284, 386, 386, 499,
+ 499, 625, 624, 623, 621, 618, 617, 615, 614, 613,
+ 612, 611, 610, 607, 606, 604, 603, 602, 601, 386,
+ 499, 675, 675, 675, 677, 677, 600, 599, 597, 596,
+ 595, 593, 591, 590, 587, 578, 577, 576, 553, 546,
+ 545, 542, 541, 540, 539, 538, 537, 536, 535, 534,
+ 533, 531, 528, 527, 526, 525, 524, 523, 522, 521,
+ 520, 519, 518, 516, 515, 514, 513, 511, 509, 508,
+ 507, 506, 505, 504, 503, 502, 501, 500, 498, 497,
+
+ 496, 495, 494, 491, 490, 489, 488, 487, 486, 485,
+ 484, 483, 482, 481, 480, 479, 478, 477, 476, 475,
+ 473, 472, 471, 470, 469, 468, 467, 466, 465, 464,
+ 463, 462, 461, 460, 459, 458, 456, 455, 454, 453,
+ 452, 450, 449, 448, 447, 446, 445, 444, 441, 440,
+ 438, 437, 436, 435, 432, 431, 430, 429, 428, 427,
+ 426, 424, 423, 422, 421, 420, 419, 418, 417, 416,
+ 415, 414, 413, 412, 411, 410, 409, 408, 406, 405,
+ 404, 403, 402, 401, 400, 399, 398, 397, 396, 395,
+ 394, 393, 392, 391, 390, 389, 388, 387, 384, 383,
+
+ 382, 379, 378, 377, 376, 375, 374, 372, 370, 369,
+ 368, 366, 365, 364, 363, 362, 361, 360, 359, 358,
+ 357, 356, 355, 354, 353, 352, 351, 350, 349, 347,
+ 346, 345, 344, 343, 342, 341, 338, 337, 336, 333,
+ 332, 331, 330, 329, 328, 327, 326, 325, 324, 322,
+ 321, 320, 319, 318, 317, 316, 315, 313, 312, 311,
+ 310, 309, 308, 307, 306, 305, 304, 303, 302, 301,
+ 300, 299, 298, 297, 296, 295, 294, 292, 291, 290,
+ 289, 288, 287, 286, 285, 277, 276, 274, 273, 272,
+ 271, 270, 269, 264, 262, 261, 260, 259, 258, 257,
+
+ 256, 255, 253, 251, 250, 248, 246, 245, 242, 241,
+ 240, 239, 238, 237, 236, 234, 230, 229, 228, 227,
+ 226, 225, 224, 223, 222, 221, 220, 219, 218, 217,
+ 216, 215, 214, 213, 212, 211, 210, 209, 208, 207,
+ 206, 205, 204, 203, 202, 201, 200, 199, 198, 197,
+ 195, 194, 192, 191, 189, 187, 186, 185, 184, 183,
+ 182, 181, 180, 179, 177, 175, 162, 161, 160, 158,
+ 157, 156, 155, 154, 148, 146, 145, 144, 143, 142,
+ 141, 140, 139, 138, 135, 134, 133, 132, 131, 129,
+ 128, 127, 125, 124, 121, 119, 117, 116, 115, 114,
+
+ 113, 112, 111, 110, 107, 106, 105, 104, 103, 102,
+ 101, 100, 99, 98, 97, 96, 95, 94, 93, 92,
+ 91, 89, 88, 87, 86, 85, 84, 83, 81, 80,
+ 78, 77, 76, 75, 73, 72, 71, 55, 54, 51,
+ 50, 37, 36, 34, 33, 32, 31, 30, 29, 28,
+ 20, 8, 7, 3, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 674, 674
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "program_lexer.l"
+#line 2 "program_lexer.l"
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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 "main/glheader.h"
+#include "prog_instruction.h"
+#include "prog_statevars.h"
+
+#include "program_parser.h"
+#include "program_parse.tab.h"
+
+#define require_ARB_vp (yyextra->mode == ARB_vertex)
+#define require_ARB_fp (yyextra->mode == ARB_fragment)
+#define require_shadow (yyextra->option.Shadow)
+#define require_rect (yyextra->option.TexRect)
+#define require_texarray (yyextra->option.TexArray)
+
+#define return_token_or_IDENTIFIER(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define return_token_or_DOT(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yyless(1); \
+ return DOT; \
+ } \
+ } while (0)
+
+
+#define return_opcode(condition, token, opcode, sat) \
+ do { \
+ if (condition) { \
+ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
+ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
+ SWIZZLE_NIL, SWIZZLE_NIL)
+
+static unsigned
+mask_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return WRITEMASK_X;
+ case 'y':
+ case 'g':
+ return WRITEMASK_Y;
+ case 'z':
+ case 'b':
+ return WRITEMASK_Z;
+ case 'w':
+ case 'a':
+ return WRITEMASK_W;
+ }
+
+ return 0;
+}
+
+static unsigned
+swiz_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return SWIZZLE_X;
+ case 'y':
+ case 'g':
+ return SWIZZLE_Y;
+ case 'z':
+ case 'b':
+ return SWIZZLE_Z;
+ case 'w':
+ case 'a':
+ return SWIZZLE_W;
+ }
+
+ return 0;
+}
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yylloc->last_column; \
+ yylloc->last_column += yyleng; \
+ if ((yylloc->first_line == 1) \
+ && (yylloc->first_column == 1)) { \
+ yylloc->position = 1; \
+ } else { \
+ yylloc->position += yylloc->last_column - yylloc->first_column; \
+ } \
+ } while(0);
+
+#define YY_EXTRA_TYPE struct asm_parser_state *
+#line 1007 "lex.yy.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+
+ void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ unsigned n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 136 "program_lexer.l"
+
+
+#line 1251 "lex.yy.c"
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 955 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 138 "program_lexer.l"
+{ return ARBvp_10; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 139 "program_lexer.l"
+{ return ARBfp_10; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 140 "program_lexer.l"
+{
+ yylval->integer = at_address;
+ return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 144 "program_lexer.l"
+{ return ALIAS; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 145 "program_lexer.l"
+{ return ATTRIB; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 146 "program_lexer.l"
+{ return END; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 147 "program_lexer.l"
+{ return OPTION; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 148 "program_lexer.l"
+{ return OUTPUT; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 149 "program_lexer.l"
+{ return PARAM; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 150 "program_lexer.l"
+{ yylval->integer = at_temp; return TEMP; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 152 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, ABS, OFF); }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 153 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 154 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, ADD, OFF); }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 155 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 156 "program_lexer.l"
+{ return_opcode(require_ARB_vp, ARL, ARL, OFF); }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 158 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 159 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 160 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 161 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 163 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DP3, OFF); }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 164 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 165 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DP4, OFF); }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 166 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 167 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DPH, OFF); }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 168 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 169 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, DST, OFF); }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 170 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 172 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, EX2, OFF); }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 173 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 174 "program_lexer.l"
+{ return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 176 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, FLR, OFF); }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 177 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 178 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, FRC, OFF); }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 179 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 181 "program_lexer.l"
+{ return_opcode(require_ARB_fp, KIL, KIL, OFF); }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 183 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, LIT, OFF); }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 184 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 185 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, LG2, OFF); }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 186 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 187 "program_lexer.l"
+{ return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 188 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 189 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 191 "program_lexer.l"
+{ return_opcode( 1, TRI_OP, MAD, OFF); }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 192 "program_lexer.l"
+{ return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 193 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MAX, OFF); }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 194 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 195 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MIN, OFF); }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 196 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 197 "program_lexer.l"
+{ return_opcode( 1, VECTOR_OP, MOV, OFF); }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 198 "program_lexer.l"
+{ return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 199 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, MUL, OFF); }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 200 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 202 "program_lexer.l"
+{ return_opcode( 1, BINSC_OP, POW, OFF); }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 203 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 205 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, RCP, OFF); }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 206 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 207 "program_lexer.l"
+{ return_opcode( 1, SCALAR_OP, RSQ, OFF); }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 208 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 210 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 211 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 212 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SGE, OFF); }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 213 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 214 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 215 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 216 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SLT, OFF); }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 217 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 218 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, SUB, OFF); }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 219 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 220 "program_lexer.l"
+{ return_opcode( 1, SWZ, SWZ, OFF); }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 221 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 223 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 224 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 225 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); }
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 226 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 227 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); }
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 228 "program_lexer.l"
+{ return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 230 "program_lexer.l"
+{ return_opcode( 1, BIN_OP, XPD, OFF); }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 231 "program_lexer.l"
+{ return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 233 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 234 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 235 "program_lexer.l"
+{ return PROGRAM; }
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 236 "program_lexer.l"
+{ return STATE; }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 237 "program_lexer.l"
+{ return RESULT; }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 239 "program_lexer.l"
+{ return AMBIENT; }
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 240 "program_lexer.l"
+{ return ATTENUATION; }
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 241 "program_lexer.l"
+{ return BACK; }
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 242 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, CLIP); }
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 243 "program_lexer.l"
+{ return COLOR; }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 244 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, DEPTH); }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 245 "program_lexer.l"
+{ return DIFFUSE; }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 246 "program_lexer.l"
+{ return DIRECTION; }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 247 "program_lexer.l"
+{ return EMISSION; }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 248 "program_lexer.l"
+{ return ENV; }
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 249 "program_lexer.l"
+{ return EYE; }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 250 "program_lexer.l"
+{ return FOGCOORD; }
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 251 "program_lexer.l"
+{ return FOG; }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 252 "program_lexer.l"
+{ return FRONT; }
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 253 "program_lexer.l"
+{ return HALF; }
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 254 "program_lexer.l"
+{ return INVERSE; }
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 255 "program_lexer.l"
+{ return INVTRANS; }
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 256 "program_lexer.l"
+{ return LIGHT; }
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 257 "program_lexer.l"
+{ return LIGHTMODEL; }
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 258 "program_lexer.l"
+{ return LIGHTPROD; }
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 259 "program_lexer.l"
+{ return LOCAL; }
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 260 "program_lexer.l"
+{ return MATERIAL; }
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 261 "program_lexer.l"
+{ return MAT_PROGRAM; }
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 262 "program_lexer.l"
+{ return MATRIX; }
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 263 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 264 "program_lexer.l"
+{ return MODELVIEW; }
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 265 "program_lexer.l"
+{ return MVP; }
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 266 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, NORMAL); }
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 267 "program_lexer.l"
+{ return OBJECT; }
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 268 "program_lexer.l"
+{ return PALETTE; }
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 269 "program_lexer.l"
+{ return PARAMS; }
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 270 "program_lexer.l"
+{ return PLANE; }
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 271 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, POINT_TOK); }
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 272 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, POINTSIZE); }
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 273 "program_lexer.l"
+{ return POSITION; }
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 274 "program_lexer.l"
+{ return PRIMARY; }
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 275 "program_lexer.l"
+{ return PROJECTION; }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 276 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, RANGE); }
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 277 "program_lexer.l"
+{ return ROW; }
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 278 "program_lexer.l"
+{ return SCENECOLOR; }
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 279 "program_lexer.l"
+{ return SECONDARY; }
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 280 "program_lexer.l"
+{ return SHININESS; }
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 281 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 282 "program_lexer.l"
+{ return SPECULAR; }
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 283 "program_lexer.l"
+{ return SPOT; }
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 284 "program_lexer.l"
+{ return TEXCOORD; }
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+#line 285 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_fp, TEXENV); }
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+#line 286 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN); }
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 287 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 288 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 289 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 290 "program_lexer.l"
+{ return TEXTURE; }
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+#line 291 "program_lexer.l"
+{ return TRANSPOSE; }
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+#line 292 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 293 "program_lexer.l"
+{ return_token_or_DOT(require_ARB_vp, WEIGHT); }
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 295 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 296 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 297 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+#line 298 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+#line 299 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 300 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
+ YY_BREAK
+case 145:
+YY_RULE_SETUP
+#line 301 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 302 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 303 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 304 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
+ YY_BREAK
+case 149:
+YY_RULE_SETUP
+#line 305 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
+ YY_BREAK
+case 150:
+YY_RULE_SETUP
+#line 306 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
+ YY_BREAK
+case 151:
+YY_RULE_SETUP
+#line 307 "program_lexer.l"
+{ return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 309 "program_lexer.l"
+{
+ yylval->string = strdup(yytext);
+ return IDENTIFIER;
+}
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 314 "program_lexer.l"
+{ return DOT_DOT; }
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 316 "program_lexer.l"
+{
+ yylval->integer = strtol(yytext, NULL, 10);
+ return INTEGER;
+}
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 320 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 156:
+/* rule 156 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 324 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 328 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 332 "program_lexer.l"
+{
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 337 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return MASK4;
+}
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 343 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return MASK3;
+}
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 349 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return MASK3;
+}
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 354 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return MASK3;
+}
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 360 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+ YY_BREAK
+case 164:
+YY_RULE_SETUP
+#line 366 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 372 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return MASK2;
+}
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 378 "program_lexer.l"
+{
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return MASK1;
+}
+ YY_BREAK
+case 167:
+YY_RULE_SETUP
+#line 385 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return SWIZZLE;
+}
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 394 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return_token_or_DOT(require_ARB_fp, MASK4);
+}
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 400 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 170:
+YY_RULE_SETUP
+#line 406 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 171:
+YY_RULE_SETUP
+#line 411 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 417 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 173:
+YY_RULE_SETUP
+#line 423 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 174:
+YY_RULE_SETUP
+#line 429 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+ YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 435 "program_lexer.l"
+{
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return_token_or_DOT(require_ARB_fp, MASK1);
+}
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 443 "program_lexer.l"
+{
+ if (require_ARB_vp) {
+ return TEXGEN_R;
+ } else {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
+ yylval->swiz_mask.mask = WRITEMASK_X;
+ return MASK1;
+ }
+}
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 454 "program_lexer.l"
+{
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return_token_or_DOT(require_ARB_fp, SWIZZLE);
+}
+ YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 463 "program_lexer.l"
+{ return DOT; }
+ YY_BREAK
+case 179:
+/* rule 179 can match eol */
+YY_RULE_SETUP
+#line 465 "program_lexer.l"
+{
+ yylloc->first_line++;
+ yylloc->first_column = 1;
+ yylloc->last_line++;
+ yylloc->last_column = 1;
+ yylloc->position++;
+}
+ YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 472 "program_lexer.l"
+/* eat whitespace */ ;
+ YY_BREAK
+case 181:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 473 "program_lexer.l"
+/* eat comments */ ;
+ YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 474 "program_lexer.l"
+{ return yytext[0]; }
+ YY_BREAK
+case 183:
+YY_RULE_SETUP
+#line 475 "program_lexer.l"
+ECHO;
+ YY_BREAK
+#line 2383 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 675 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 674);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yyg->yy_hold_char;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yyg->yy_n_chars + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ yyg->yytext_ptr = yy_bp;
+ yyg->yy_hold_char = *yy_cp;
+ yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *yyget_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 475 "program_lexer.l"
+
+
+
+void
+_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
+ const char *string, size_t len)
+{
+ yylex_init_extra(state,scanner);
+ yy_scan_bytes(string,len,*scanner);
+}
+
+void
+_mesa_program_lexer_dtor(void *scanner)
+{
+ yylex_destroy(scanner);
+}
+
diff --git a/mesalib/src/mesa/shader/nvfragparse.c b/mesalib/src/mesa/shader/nvfragparse.c
new file mode 100644
index 000000000..0fd55524a
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvfragparse.c
@@ -0,0 +1,1582 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+/**
+ * \file nvfragparse.c
+ * NVIDIA fragment program parser.
+ * \author Brian Paul
+ */
+
+/*
+ * Regarding GL_NV_fragment_program:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+#include "prog_instruction.h"
+#include "nvfragparse.h"
+
+
+#define INPUT_1V 1
+#define INPUT_2V 2
+#define INPUT_3V 3
+#define INPUT_1S 4
+#define INPUT_2S 5
+#define INPUT_CC 6
+#define INPUT_1V_T 7 /* one source vector, plus textureId */
+#define INPUT_3V_T 8 /* one source vector, plus textureId */
+#define INPUT_NONE 9
+#define INPUT_1V_S 10 /* a string and a vector register */
+#define OUTPUT_V 20
+#define OUTPUT_S 21
+#define OUTPUT_NONE 22
+
+/* IRIX defines some of these */
+#undef _R
+#undef _H
+#undef _X
+#undef _C
+#undef _S
+
+/* Optional suffixes */
+#define _R FLOAT32 /* float */
+#define _H FLOAT16 /* half-float */
+#define _X FIXED12 /* fixed */
+#define _C 0x08 /* set cond codes */
+#define _S 0x10 /* saturate, clamp result to [0,1] */
+
+struct instruction_pattern {
+ const char *name;
+ enum prog_opcode opcode;
+ GLuint inputs;
+ GLuint outputs;
+ GLuint suffixes;
+};
+
+static const struct instruction_pattern Instructions[] = {
+ { "ADD", OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "COS", OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "DDX", OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
+ { "DDY", OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
+ { "DP3", OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
+ { "DP4", OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
+ { "DST", OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H | _C | _S },
+ { "EX2", OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "FLR", OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "FRC", OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "KIL", OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0 },
+ { "LG2", OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "LIT", OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H | _C | _S },
+ { "LRP", OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "MAD", OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "MAX", OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "MIN", OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "MOV", OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "MUL", OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "PK2H", OPCODE_PK2H, INPUT_1V, OUTPUT_S, 0 },
+ { "PK2US", OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0 },
+ { "PK4B", OPCODE_PK4B, INPUT_1V, OUTPUT_S, 0 },
+ { "PK4UB", OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0 },
+ { "POW", OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H | _C | _S },
+ { "RCP", OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "RFL", OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H | _C | _S },
+ { "RSQ", OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "SEQ", OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SFL", OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SGE", OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SGT", OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SIN", OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H | _C | _S },
+ { "SLE", OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SLT", OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SNE", OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "STR", OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "SUB", OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
+ { "TEX", OPCODE_TEX, INPUT_1V_T, OUTPUT_V, _C | _S },
+ { "TXD", OPCODE_TXD, INPUT_3V_T, OUTPUT_V, _C | _S },
+ { "TXP", OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V, _C | _S },
+ { "UP2H", OPCODE_UP2H, INPUT_1S, OUTPUT_V, _C | _S },
+ { "UP2US", OPCODE_UP2US, INPUT_1S, OUTPUT_V, _C | _S },
+ { "UP4B", OPCODE_UP4B, INPUT_1S, OUTPUT_V, _C | _S },
+ { "UP4UB", OPCODE_UP4UB, INPUT_1S, OUTPUT_V, _C | _S },
+ { "X2D", OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H | _C | _S },
+ { "PRINT", OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0 },
+ { NULL, (enum prog_opcode) -1, 0, 0, 0 }
+};
+
+
+/*
+ * Information needed or computed during parsing.
+ * Remember, we can't modify the target program object until we've
+ * _successfully_ parsed the program text.
+ */
+struct parse_state {
+ GLcontext *ctx;
+ const GLubyte *start; /* start of program string */
+ const GLubyte *pos; /* current position */
+ const GLubyte *curLine;
+ struct gl_fragment_program *program; /* current program */
+
+ struct gl_program_parameter_list *parameters;
+
+ GLuint numInst; /* number of instructions parsed */
+ GLuint inputsRead; /* bitmask of input registers used */
+ GLuint outputsWritten; /* bitmask of 1 << FRAG_OUTPUT_* bits */
+ GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
+};
+
+
+
+/*
+ * Called whenever we find an error during parsing.
+ */
+static void
+record_error(struct parse_state *parseState, const char *msg, int lineNo)
+{
+#ifdef DEBUG
+ GLint line, column;
+ const GLubyte *lineStr;
+ lineStr = _mesa_find_line_column(parseState->start,
+ parseState->pos, &line, &column);
+ _mesa_debug(parseState->ctx,
+ "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
+ lineNo, line, column, (char *) lineStr, msg);
+ _mesa_free((void *) lineStr);
+#else
+ (void) lineNo;
+#endif
+
+ /* Check that no error was already recorded. Only record the first one. */
+ if (parseState->ctx->Program.ErrorString[0] == 0) {
+ _mesa_set_program_error(parseState->ctx,
+ parseState->pos - parseState->start,
+ msg);
+ }
+}
+
+
+#define RETURN_ERROR \
+do { \
+ record_error(parseState, "Unexpected end of input.", __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+#define RETURN_ERROR1(msg) \
+do { \
+ record_error(parseState, msg, __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+#define RETURN_ERROR2(msg1, msg2) \
+do { \
+ char err[1000]; \
+ _mesa_sprintf(err, "%s %s", msg1, msg2); \
+ record_error(parseState, err, __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+
+
+
+/*
+ * Search a list of instruction structures for a match.
+ */
+static struct instruction_pattern
+MatchInstruction(const GLubyte *token)
+{
+ const struct instruction_pattern *inst;
+ struct instruction_pattern result;
+
+ for (inst = Instructions; inst->name; inst++) {
+ if (_mesa_strncmp((const char *) token, inst->name, 3) == 0) {
+ /* matched! */
+ int i = 3;
+ result = *inst;
+ result.suffixes = 0;
+ /* look at suffix */
+ if (token[i] == 'R') {
+ result.suffixes |= _R;
+ i++;
+ }
+ else if (token[i] == 'H') {
+ result.suffixes |= _H;
+ i++;
+ }
+ else if (token[i] == 'X') {
+ result.suffixes |= _X;
+ i++;
+ }
+ if (token[i] == 'C') {
+ result.suffixes |= _C;
+ i++;
+ }
+ if (token[i] == '_' && token[i+1] == 'S' &&
+ token[i+2] == 'A' && token[i+3] == 'T') {
+ result.suffixes |= _S;
+ }
+ return result;
+ }
+ }
+ result.opcode = MAX_OPCODE; /* i.e. invalid instruction */
+ return result;
+}
+
+
+
+
+/**********************************************************************/
+
+
+static GLboolean IsLetter(GLubyte b)
+{
+ return (b >= 'a' && b <= 'z') ||
+ (b >= 'A' && b <= 'Z') ||
+ (b == '_') ||
+ (b == '$');
+}
+
+
+static GLboolean IsDigit(GLubyte b)
+{
+ return b >= '0' && b <= '9';
+}
+
+
+static GLboolean IsWhitespace(GLubyte b)
+{
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r';
+}
+
+
+/**
+ * Starting at 'str' find the next token. A token can be an integer,
+ * an identifier or punctuation symbol.
+ * \return <= 0 we found an error, else, return number of characters parsed.
+ */
+static GLint
+GetToken(struct parse_state *parseState, GLubyte *token)
+{
+ const GLubyte *str = parseState->pos;
+ GLint i = 0, j = 0;
+
+ token[0] = 0;
+
+ /* skip whitespace and comments */
+ while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
+ if (str[i] == '#') {
+ /* skip comment */
+ while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
+ i++;
+ }
+ if (str[i] == '\n' || str[i] == '\r')
+ parseState->curLine = str + i + 1;
+ }
+ else {
+ /* skip whitespace */
+ if (str[i] == '\n' || str[i] == '\r')
+ parseState->curLine = str + i + 1;
+ i++;
+ }
+ }
+
+ if (str[i] == 0)
+ return -i;
+
+ /* try matching an integer */
+ while (str[i] && IsDigit(str[i])) {
+ token[j++] = str[i++];
+ }
+ if (j > 0 || !str[i]) {
+ token[j] = 0;
+ return i;
+ }
+
+ /* try matching an identifier */
+ if (IsLetter(str[i])) {
+ while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
+ token[j++] = str[i++];
+ }
+ token[j] = 0;
+ return i;
+ }
+
+ /* punctuation character */
+ if (str[i]) {
+ token[0] = str[i++];
+ token[1] = 0;
+ return i;
+ }
+
+ /* end of input */
+ token[0] = 0;
+ return i;
+}
+
+
+/**
+ * Get next token from input stream and increment stream pointer past token.
+ */
+static GLboolean
+Parse_Token(struct parse_state *parseState, GLubyte *token)
+{
+ GLint i;
+ i = GetToken(parseState, token);
+ if (i <= 0) {
+ parseState->pos += (-i);
+ return GL_FALSE;
+ }
+ parseState->pos += i;
+ return GL_TRUE;
+}
+
+
+/**
+ * Get next token from input stream but don't increment stream pointer.
+ */
+static GLboolean
+Peek_Token(struct parse_state *parseState, GLubyte *token)
+{
+ GLint i, len;
+ i = GetToken(parseState, token);
+ if (i <= 0) {
+ parseState->pos += (-i);
+ return GL_FALSE;
+ }
+ len = (GLint)_mesa_strlen((const char *) token);
+ parseState->pos += (i - len);
+ return GL_TRUE;
+}
+
+
+/**********************************************************************/
+
+static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = {
+ "WPOS", "COL0", "COL1", "FOGC",
+ "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
+};
+
+
+
+/**********************************************************************/
+
+/**
+ * Try to match 'pattern' as the next token after any whitespace/comments.
+ */
+static GLboolean
+Parse_String(struct parse_state *parseState, const char *pattern)
+{
+ const GLubyte *m;
+ GLint i;
+
+ /* skip whitespace and comments */
+ while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
+ if (*parseState->pos == '#') {
+ while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
+ parseState->pos += 1;
+ }
+ if (*parseState->pos == '\n' || *parseState->pos == '\r')
+ parseState->curLine = parseState->pos + 1;
+ }
+ else {
+ /* skip whitespace */
+ if (*parseState->pos == '\n' || *parseState->pos == '\r')
+ parseState->curLine = parseState->pos + 1;
+ parseState->pos += 1;
+ }
+ }
+
+ /* Try to match the pattern */
+ m = parseState->pos;
+ for (i = 0; pattern[i]; i++) {
+ if (*m != (GLubyte) pattern[i])
+ return GL_FALSE;
+ m += 1;
+ }
+ parseState->pos = m;
+
+ return GL_TRUE; /* success */
+}
+
+
+static GLboolean
+Parse_Identifier(struct parse_state *parseState, GLubyte *ident)
+{
+ if (!Parse_Token(parseState, ident))
+ RETURN_ERROR;
+ if (IsLetter(ident[0]))
+ return GL_TRUE;
+ else
+ RETURN_ERROR1("Expected an identfier");
+}
+
+
+/**
+ * Parse a floating point constant, or a defined symbol name.
+ * [+/-]N[.N[eN]]
+ * Output: number[0 .. 3] will get the value.
+ */
+static GLboolean
+Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
+{
+ char *end = NULL;
+
+ *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end);
+
+ if (end && end > (char *) parseState->pos) {
+ /* got a number */
+ parseState->pos = (GLubyte *) end;
+ number[1] = *number;
+ number[2] = *number;
+ number[3] = *number;
+ return GL_TRUE;
+ }
+ else {
+ /* should be an identifier */
+ GLubyte ident[100];
+ const GLfloat *constant;
+ if (!Parse_Identifier(parseState, ident))
+ RETURN_ERROR1("Expected an identifier");
+ constant = _mesa_lookup_parameter_value(parseState->parameters,
+ -1, (const char *) ident);
+ /* XXX Check that it's a constant and not a parameter */
+ if (!constant) {
+ RETURN_ERROR1("Undefined symbol");
+ }
+ else {
+ COPY_4V(number, constant);
+ return GL_TRUE;
+ }
+ }
+}
+
+
+
+/**
+ * Parse a vector constant, one of:
+ * { float }
+ * { float, float }
+ * { float, float, float }
+ * { float, float, float, float }
+ */
+static GLboolean
+Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
+{
+ /* "{" was already consumed */
+
+ ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
+
+ if (!Parse_ScalarConstant(parseState, vec+0)) /* X */
+ return GL_FALSE;
+
+ if (Parse_String(parseState, "}")) {
+ return GL_TRUE;
+ }
+
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected comma in vector constant");
+
+ if (!Parse_ScalarConstant(parseState, vec+1)) /* Y */
+ return GL_FALSE;
+
+ if (Parse_String(parseState, "}")) {
+ return GL_TRUE;
+ }
+
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected comma in vector constant");
+
+ if (!Parse_ScalarConstant(parseState, vec+2)) /* Z */
+ return GL_FALSE;
+
+ if (Parse_String(parseState, "}")) {
+ return GL_TRUE;
+ }
+
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected comma in vector constant");
+
+ if (!Parse_ScalarConstant(parseState, vec+3)) /* W */
+ return GL_FALSE;
+
+ if (!Parse_String(parseState, "}"))
+ RETURN_ERROR1("Expected closing brace in vector constant");
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse <number>, <varname> or {a, b, c, d}.
+ * Return number of values in the vector or scalar, or zero if parse error.
+ */
+static GLuint
+Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
+{
+ if (Parse_String(parseState, "{")) {
+ return Parse_VectorConstant(parseState, vec);
+ }
+ else {
+ GLboolean b = Parse_ScalarConstant(parseState, vec);
+ if (b) {
+ vec[1] = vec[2] = vec[3] = vec[0];
+ }
+ return b;
+ }
+}
+
+
+/**
+ * Parse a texture image source:
+ * [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT]
+ */
+static GLboolean
+Parse_TextureImageId(struct parse_state *parseState,
+ GLubyte *texUnit, GLubyte *texTargetBit)
+{
+ GLubyte imageSrc[100];
+ GLint unit;
+
+ if (!Parse_Token(parseState, imageSrc))
+ RETURN_ERROR;
+
+ if (imageSrc[0] != 'T' ||
+ imageSrc[1] != 'E' ||
+ imageSrc[2] != 'X') {
+ RETURN_ERROR1("Expected TEX# source");
+ }
+ unit = _mesa_atoi((const char *) imageSrc + 3);
+ if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) ||
+ (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) {
+ RETURN_ERROR1("Invalied TEX# source index");
+ }
+ *texUnit = unit;
+
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+
+ if (Parse_String(parseState, "1D")) {
+ *texTargetBit = TEXTURE_1D_BIT;
+ }
+ else if (Parse_String(parseState, "2D")) {
+ *texTargetBit = TEXTURE_2D_BIT;
+ }
+ else if (Parse_String(parseState, "3D")) {
+ *texTargetBit = TEXTURE_3D_BIT;
+ }
+ else if (Parse_String(parseState, "CUBE")) {
+ *texTargetBit = TEXTURE_CUBE_BIT;
+ }
+ else if (Parse_String(parseState, "RECT")) {
+ *texTargetBit = TEXTURE_RECT_BIT;
+ }
+ else {
+ RETURN_ERROR1("Invalid texture target token");
+ }
+
+ /* update record of referenced texture units */
+ parseState->texturesUsed[*texUnit] |= *texTargetBit;
+ if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
+ RETURN_ERROR1("Only one texture target can be used per texture unit.");
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse a scalar suffix like .x, .y, .z or .w or parse a swizzle suffix
+ * like .wxyz, .xxyy, etc and return the swizzle indexes.
+ */
+static GLboolean
+Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4])
+{
+ if (token[1] == 0) {
+ /* single letter swizzle (scalar) */
+ if (token[0] == 'x')
+ ASSIGN_4V(swizzle, 0, 0, 0, 0);
+ else if (token[0] == 'y')
+ ASSIGN_4V(swizzle, 1, 1, 1, 1);
+ else if (token[0] == 'z')
+ ASSIGN_4V(swizzle, 2, 2, 2, 2);
+ else if (token[0] == 'w')
+ ASSIGN_4V(swizzle, 3, 3, 3, 3);
+ else
+ return GL_FALSE;
+ }
+ else {
+ /* 4-component swizzle (vector) */
+ GLint k;
+ for (k = 0; token[k] && k < 4; k++) {
+ if (token[k] == 'x')
+ swizzle[k] = 0;
+ else if (token[k] == 'y')
+ swizzle[k] = 1;
+ else if (token[k] == 'z')
+ swizzle[k] = 2;
+ else if (token[k] == 'w')
+ swizzle[k] = 3;
+ else
+ return GL_FALSE;
+ }
+ if (k != 4)
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_CondCodeMask(struct parse_state *parseState,
+ struct prog_dst_register *dstReg)
+{
+ if (Parse_String(parseState, "EQ"))
+ dstReg->CondMask = COND_EQ;
+ else if (Parse_String(parseState, "GE"))
+ dstReg->CondMask = COND_GE;
+ else if (Parse_String(parseState, "GT"))
+ dstReg->CondMask = COND_GT;
+ else if (Parse_String(parseState, "LE"))
+ dstReg->CondMask = COND_LE;
+ else if (Parse_String(parseState, "LT"))
+ dstReg->CondMask = COND_LT;
+ else if (Parse_String(parseState, "NE"))
+ dstReg->CondMask = COND_NE;
+ else if (Parse_String(parseState, "TR"))
+ dstReg->CondMask = COND_TR;
+ else if (Parse_String(parseState, "FL"))
+ dstReg->CondMask = COND_FL;
+ else
+ RETURN_ERROR1("Invalid condition code mask");
+
+ /* look for optional .xyzw swizzle */
+ if (Parse_String(parseState, ".")) {
+ GLubyte token[100];
+ GLuint swz[4];
+
+ if (!Parse_Token(parseState, token)) /* get xyzw suffix */
+ RETURN_ERROR;
+
+ if (!Parse_SwizzleSuffix(token, swz))
+ RETURN_ERROR1("Invalid swizzle suffix");
+
+ dstReg->CondSwizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse a temporary register: Rnn or Hnn
+ */
+static GLboolean
+Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
+{
+ GLubyte token[100];
+
+ /* Should be 'R##' or 'H##' */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+ if (token[0] != 'R' && token[0] != 'H')
+ RETURN_ERROR1("Expected R## or H##");
+
+ if (IsDigit(token[1])) {
+ GLint reg = _mesa_atoi((const char *) (token + 1));
+ if (token[0] == 'H')
+ reg += 32;
+ if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
+ RETURN_ERROR1("Invalid temporary register name");
+ *tempRegNum = reg;
+ }
+ else {
+ RETURN_ERROR1("Invalid temporary register name");
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse a write-only dummy register: RC or HC.
+ */
+static GLboolean
+Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
+{
+ if (Parse_String(parseState, "RC")) {
+ *regNum = 0;
+ }
+ else if (Parse_String(parseState, "HC")) {
+ *regNum = 1;
+ }
+ else {
+ RETURN_ERROR1("Invalid write-only register name");
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse a program local parameter register "p[##]"
+ */
+static GLboolean
+Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
+{
+ GLubyte token[100];
+
+ if (!Parse_String(parseState, "p["))
+ RETURN_ERROR1("Expected p[");
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (IsDigit(token[0])) {
+ /* a numbered program parameter register */
+ GLint reg = _mesa_atoi((const char *) token);
+ if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
+ RETURN_ERROR1("Invalid constant program number");
+ *regNum = reg;
+ }
+ else {
+ RETURN_ERROR;
+ }
+
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR1("Expected ]");
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse f[name] - fragment input register
+ */
+static GLboolean
+Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
+{
+ GLubyte token[100];
+ GLint j;
+
+ /* Match 'f[' */
+ if (!Parse_String(parseState, "f["))
+ RETURN_ERROR1("Expected f[");
+
+ /* get <name> and look for match */
+ if (!Parse_Token(parseState, token)) {
+ RETURN_ERROR;
+ }
+ for (j = 0; InputRegisters[j]; j++) {
+ if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
+ *tempRegNum = j;
+ parseState->inputsRead |= (1 << j);
+ break;
+ }
+ }
+ if (!InputRegisters[j]) {
+ /* unknown input register label */
+ RETURN_ERROR2("Invalid register name", token);
+ }
+
+ /* Match '[' */
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR1("Expected ]");
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
+{
+ GLubyte token[100];
+
+ /* Match "o[" */
+ if (!Parse_String(parseState, "o["))
+ RETURN_ERROR1("Expected o[");
+
+ /* Get output reg name */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ /* try to match an output register name */
+ if (_mesa_strcmp((char *) token, "COLR") == 0 ||
+ _mesa_strcmp((char *) token, "COLH") == 0) {
+ /* note that we don't distinguish between COLR and COLH */
+ *outputRegNum = FRAG_RESULT_COLOR;
+ parseState->outputsWritten |= (1 << FRAG_RESULT_COLOR);
+ }
+ else if (_mesa_strcmp((char *) token, "DEPR") == 0) {
+ *outputRegNum = FRAG_RESULT_DEPTH;
+ parseState->outputsWritten |= (1 << FRAG_RESULT_DEPTH);
+ }
+ else {
+ RETURN_ERROR1("Invalid output register name");
+ }
+
+ /* Match ']' */
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR1("Expected ]");
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_MaskedDstReg(struct parse_state *parseState,
+ struct prog_dst_register *dstReg)
+{
+ GLubyte token[100];
+ GLint idx;
+
+ /* Dst reg can be R<n>, H<n>, o[n], RC or HC */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (_mesa_strcmp((const char *) token, "RC") == 0 ||
+ _mesa_strcmp((const char *) token, "HC") == 0) {
+ /* a write-only register */
+ dstReg->File = PROGRAM_WRITE_ONLY;
+ if (!Parse_DummyReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else if (token[0] == 'R' || token[0] == 'H') {
+ /* a temporary register */
+ dstReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else if (token[0] == 'o') {
+ /* an output register */
+ dstReg->File = PROGRAM_OUTPUT;
+ if (!Parse_OutputReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR1("Invalid destination register name");
+ }
+
+ /* Parse optional write mask */
+ if (Parse_String(parseState, ".")) {
+ /* got a mask */
+ GLint k = 0;
+
+ if (!Parse_Token(parseState, token)) /* get xyzw writemask */
+ RETURN_ERROR;
+
+ dstReg->WriteMask = 0;
+
+ if (token[k] == 'x') {
+ dstReg->WriteMask |= WRITEMASK_X;
+ k++;
+ }
+ if (token[k] == 'y') {
+ dstReg->WriteMask |= WRITEMASK_Y;
+ k++;
+ }
+ if (token[k] == 'z') {
+ dstReg->WriteMask |= WRITEMASK_Z;
+ k++;
+ }
+ if (token[k] == 'w') {
+ dstReg->WriteMask |= WRITEMASK_W;
+ k++;
+ }
+ if (k == 0) {
+ RETURN_ERROR1("Invalid writemask character");
+ }
+
+ }
+ else {
+ dstReg->WriteMask = WRITEMASK_XYZW;
+ }
+
+ /* optional condition code mask */
+ if (Parse_String(parseState, "(")) {
+ /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".x|y|z|w) */
+ /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".[xyzw]) */
+ if (!Parse_CondCodeMask(parseState, dstReg))
+ RETURN_ERROR;
+
+ if (!Parse_String(parseState, ")")) /* consume ")" */
+ RETURN_ERROR1("Expected )");
+
+ return GL_TRUE;
+ }
+ else {
+ /* no cond code mask */
+ dstReg->CondMask = COND_TR;
+ dstReg->CondSwizzle = SWIZZLE_NOOP;
+ return GL_TRUE;
+ }
+}
+
+
+/**
+ * Parse a vector source (register, constant, etc):
+ * <vectorSrc> ::= <absVectorSrc>
+ * | <baseVectorSrc>
+ * <absVectorSrc> ::= <negate> "|" <baseVectorSrc> "|"
+ */
+static GLboolean
+Parse_VectorSrc(struct parse_state *parseState,
+ struct prog_src_register *srcReg)
+{
+ GLfloat sign = 1.0F;
+ GLubyte token[100];
+ GLint idx;
+ GLuint negateBase, negateAbs;
+
+ /*
+ * First, take care of +/- and absolute value stuff.
+ */
+ if (Parse_String(parseState, "-"))
+ sign = -1.0F;
+ else if (Parse_String(parseState, "+"))
+ sign = +1.0F;
+
+ if (Parse_String(parseState, "|")) {
+ srcReg->Abs = GL_TRUE;
+ negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+
+ if (Parse_String(parseState, "-"))
+ negateBase = NEGATE_XYZW;
+ else if (Parse_String(parseState, "+"))
+ negateBase = NEGATE_NONE;
+ else
+ negateBase = NEGATE_NONE;
+ }
+ else {
+ srcReg->Abs = GL_FALSE;
+ negateAbs = NEGATE_NONE;
+ negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+ }
+
+ srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
+
+ /* This should be the real src vector/register name */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ /* Src reg can be Rn, Hn, f[n], p[n], a named parameter, a scalar
+ * literal or vector literal.
+ */
+ if (token[0] == 'R' || token[0] == 'H') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'f') {
+ /* XXX this might be an identifier! */
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_FragReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'p') {
+ /* XXX this might be an identifier! */
+ srcReg->File = PROGRAM_LOCAL_PARAM;
+ if (!Parse_ProgramParamReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (IsLetter(token[0])){
+ GLubyte ident[100];
+ GLint paramIndex;
+ if (!Parse_Identifier(parseState, ident))
+ RETURN_ERROR;
+ paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
+ -1, (const char *) ident);
+ if (paramIndex < 0) {
+ RETURN_ERROR2("Undefined constant or parameter: ", ident);
+ }
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ srcReg->Index = paramIndex;
+ }
+ else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){
+ /* literal scalar constant */
+ GLfloat values[4];
+ GLuint paramIndex;
+ if (!Parse_ScalarConstant(parseState, values))
+ RETURN_ERROR;
+ paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
+ values, 4, NULL);
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ srcReg->Index = paramIndex;
+ }
+ else if (token[0] == '{'){
+ /* literal vector constant */
+ GLfloat values[4];
+ GLuint paramIndex;
+ (void) Parse_String(parseState, "{");
+ if (!Parse_VectorConstant(parseState, values))
+ RETURN_ERROR;
+ paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
+ values, 4, NULL);
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ srcReg->Index = paramIndex;
+ }
+ else {
+ RETURN_ERROR2("Invalid source register name", token);
+ }
+
+ /* init swizzle fields */
+ srcReg->Swizzle = SWIZZLE_NOOP;
+
+ /* Look for optional swizzle suffix */
+ if (Parse_String(parseState, ".")) {
+ GLuint swz[4];
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (!Parse_SwizzleSuffix(token, swz))
+ RETURN_ERROR1("Invalid swizzle suffix");
+
+ srcReg->Swizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+ }
+
+ /* Finish absolute value */
+ if (srcReg->Abs && !Parse_String(parseState, "|")) {
+ RETURN_ERROR1("Expected |");
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_ScalarSrcReg(struct parse_state *parseState,
+ struct prog_src_register *srcReg)
+{
+ GLubyte token[100];
+ GLfloat sign = 1.0F;
+ GLboolean needSuffix = GL_TRUE;
+ GLint idx;
+ GLuint negateBase, negateAbs;
+
+ /*
+ * First, take care of +/- and absolute value stuff.
+ */
+ if (Parse_String(parseState, "-"))
+ sign = -1.0F;
+ else if (Parse_String(parseState, "+"))
+ sign = +1.0F;
+
+ if (Parse_String(parseState, "|")) {
+ srcReg->Abs = GL_TRUE;
+ negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+
+ if (Parse_String(parseState, "-"))
+ negateBase = NEGATE_XYZW;
+ else if (Parse_String(parseState, "+"))
+ negateBase = NEGATE_NONE;
+ else
+ negateBase = NEGATE_NONE;
+ }
+ else {
+ srcReg->Abs = GL_FALSE;
+ negateAbs = NEGATE_NONE;
+ negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
+ }
+
+ srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
+
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ /* Src reg can be R<n>, H<n> or a named fragment attrib */
+ if (token[0] == 'R' || token[0] == 'H') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'f') {
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_FragReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == '{') {
+ /* vector literal */
+ GLfloat values[4];
+ GLuint paramIndex;
+ (void) Parse_String(parseState, "{");
+ if (!Parse_VectorConstant(parseState, values))
+ RETURN_ERROR;
+ paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
+ values, 4, NULL);
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ srcReg->Index = paramIndex;
+ }
+ else if (IsLetter(token[0])){
+ /* named param/constant */
+ GLubyte ident[100];
+ GLint paramIndex;
+ if (!Parse_Identifier(parseState, ident))
+ RETURN_ERROR;
+ paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
+ -1, (const char *) ident);
+ if (paramIndex < 0) {
+ RETURN_ERROR2("Undefined constant or parameter: ", ident);
+ }
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ srcReg->Index = paramIndex;
+ }
+ else if (IsDigit(token[0])) {
+ /* scalar literal */
+ GLfloat values[4];
+ GLuint paramIndex;
+ if (!Parse_ScalarConstant(parseState, values))
+ RETURN_ERROR;
+ paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
+ values, 4, NULL);
+ srcReg->Index = paramIndex;
+ srcReg->File = PROGRAM_NAMED_PARAM;
+ needSuffix = GL_FALSE;
+ }
+ else {
+ RETURN_ERROR2("Invalid scalar source argument", token);
+ }
+
+ srcReg->Swizzle = 0;
+ if (needSuffix) {
+ /* parse .[xyzw] suffix */
+ if (!Parse_String(parseState, "."))
+ RETURN_ERROR1("Expected .");
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[0] == 'x' && token[1] == 0) {
+ srcReg->Swizzle = 0;
+ }
+ else if (token[0] == 'y' && token[1] == 0) {
+ srcReg->Swizzle = 1;
+ }
+ else if (token[0] == 'z' && token[1] == 0) {
+ srcReg->Swizzle = 2;
+ }
+ else if (token[0] == 'w' && token[1] == 0) {
+ srcReg->Swizzle = 3;
+ }
+ else {
+ RETURN_ERROR1("Invalid scalar source suffix");
+ }
+ }
+
+ /* Finish absolute value */
+ if (srcReg->Abs && !Parse_String(parseState, "|")) {
+ RETURN_ERROR1("Expected |");
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_PrintInstruction(struct parse_state *parseState,
+ struct prog_instruction *inst)
+{
+ const GLubyte *str;
+ GLubyte *msg;
+ GLuint len;
+ GLint idx;
+
+ /* The first argument is a literal string 'just like this' */
+ if (!Parse_String(parseState, "'"))
+ RETURN_ERROR1("Expected '");
+
+ str = parseState->pos;
+ for (len = 0; str[len] != '\''; len++) /* find closing quote */
+ ;
+ parseState->pos += len + 1;
+ msg = (GLubyte*) _mesa_malloc(len + 1);
+
+ _mesa_memcpy(msg, str, len);
+ msg[len] = 0;
+ inst->Data = msg;
+
+ if (Parse_String(parseState, ",")) {
+ /* got an optional register to print */
+ GLubyte token[100];
+ GetToken(parseState, token);
+ if (token[0] == 'o') {
+ /* dst reg */
+ if (!Parse_OutputReg(parseState, &idx))
+ RETURN_ERROR;
+ inst->SrcReg[0].Index = idx;
+ inst->SrcReg[0].File = PROGRAM_OUTPUT;
+ }
+ else {
+ /* src reg */
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ }
+ }
+ else {
+ inst->SrcReg[0].File = PROGRAM_UNDEFINED;
+ }
+
+ inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
+ inst->SrcReg[0].Abs = GL_FALSE;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_InstructionSequence(struct parse_state *parseState,
+ struct prog_instruction program[])
+{
+ while (1) {
+ struct prog_instruction *inst = program + parseState->numInst;
+ struct instruction_pattern instMatch;
+ GLubyte token[100];
+
+ /* Initialize the instruction */
+ _mesa_init_instructions(inst, 1);
+
+ /* special instructions */
+ if (Parse_String(parseState, "DEFINE")) {
+ GLubyte id[100];
+ GLfloat value[7]; /* yes, 7 to be safe */
+ if (!Parse_Identifier(parseState, id))
+ RETURN_ERROR;
+ /* XXX make sure id is not a reserved identifer, like R9 */
+ if (!Parse_String(parseState, "="))
+ RETURN_ERROR1("Expected =");
+ if (!Parse_VectorOrScalarConstant(parseState, value))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR1("Expected ;");
+ if (_mesa_lookup_parameter_index(parseState->parameters,
+ -1, (const char *) id) >= 0) {
+ RETURN_ERROR2(id, "already defined");
+ }
+ _mesa_add_named_parameter(parseState->parameters,
+ (const char *) id, value);
+ }
+ else if (Parse_String(parseState, "DECLARE")) {
+ GLubyte id[100];
+ GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0}; /* yes, to be safe */
+ if (!Parse_Identifier(parseState, id))
+ RETURN_ERROR;
+ /* XXX make sure id is not a reserved identifer, like R9 */
+ if (Parse_String(parseState, "=")) {
+ if (!Parse_VectorOrScalarConstant(parseState, value))
+ RETURN_ERROR;
+ }
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR1("Expected ;");
+ if (_mesa_lookup_parameter_index(parseState->parameters,
+ -1, (const char *) id) >= 0) {
+ RETURN_ERROR2(id, "already declared");
+ }
+ _mesa_add_named_parameter(parseState->parameters,
+ (const char *) id, value);
+ }
+ else if (Parse_String(parseState, "END")) {
+ inst->Opcode = OPCODE_END;
+ parseState->numInst++;
+ if (Parse_Token(parseState, token)) {
+ RETURN_ERROR1("Code after END opcode.");
+ }
+ break;
+ }
+ else {
+ /* general/arithmetic instruction */
+
+ /* get token */
+ if (!Parse_Token(parseState, token)) {
+ RETURN_ERROR1("Missing END instruction.");
+ }
+
+ /* try to find matching instuction */
+ instMatch = MatchInstruction(token);
+ if (instMatch.opcode >= MAX_OPCODE) {
+ /* bad instruction name */
+ RETURN_ERROR2("Unexpected token: ", token);
+ }
+
+ inst->Opcode = instMatch.opcode;
+ inst->Precision = instMatch.suffixes & (_R | _H | _X);
+ inst->SaturateMode = (instMatch.suffixes & (_S))
+ ? SATURATE_ZERO_ONE : SATURATE_OFF;
+ inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
+
+ /*
+ * parse the input and output operands
+ */
+ if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
+ if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ }
+ else if (instMatch.outputs == OUTPUT_NONE) {
+ if (instMatch.opcode == OPCODE_KIL_NV) {
+ /* This is a little weird, the cond code info is in
+ * the dest register.
+ */
+ if (!Parse_CondCodeMask(parseState, &inst->DstReg))
+ RETURN_ERROR;
+ }
+ else {
+ ASSERT(instMatch.opcode == OPCODE_PRINT);
+ }
+ }
+
+ if (instMatch.inputs == INPUT_1V) {
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ }
+ else if (instMatch.inputs == INPUT_2V) {
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+ }
+ else if (instMatch.inputs == INPUT_3V) {
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
+ RETURN_ERROR;
+ }
+ else if (instMatch.inputs == INPUT_1S) {
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ }
+ else if (instMatch.inputs == INPUT_2S) {
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+ }
+ else if (instMatch.inputs == INPUT_CC) {
+ /* XXX to-do */
+ }
+ else if (instMatch.inputs == INPUT_1V_T) {
+ GLubyte unit, idx;
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_TextureImageId(parseState, &unit, &idx))
+ RETURN_ERROR;
+ inst->TexSrcUnit = unit;
+ inst->TexSrcTarget = idx;
+ }
+ else if (instMatch.inputs == INPUT_3V_T) {
+ GLubyte unit, idx;
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
+ RETURN_ERROR;
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR1("Expected ,");
+ if (!Parse_TextureImageId(parseState, &unit, &idx))
+ RETURN_ERROR;
+ inst->TexSrcUnit = unit;
+ inst->TexSrcTarget = idx;
+ }
+ else if (instMatch.inputs == INPUT_1V_S) {
+ if (!Parse_PrintInstruction(parseState, inst))
+ RETURN_ERROR;
+ }
+
+ /* end of statement semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR1("Expected ;");
+
+ parseState->numInst++;
+
+ if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
+ RETURN_ERROR1("Program too long");
+ }
+ }
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Parse/compile the 'str' returning the compiled 'program'.
+ * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos
+ * indicates the position of the error in 'str'.
+ */
+void
+_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
+ const GLubyte *str, GLsizei len,
+ struct gl_fragment_program *program)
+{
+ struct parse_state parseState;
+ struct prog_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS];
+ struct prog_instruction *newInst;
+ GLenum target;
+ GLubyte *programString;
+
+ /* Make a null-terminated copy of the program string */
+ programString = (GLubyte *) MALLOC(len + 1);
+ if (!programString) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ MEMCPY(programString, str, len);
+ programString[len] = 0;
+
+ /* Get ready to parse */
+ _mesa_bzero(&parseState, sizeof(struct parse_state));
+ parseState.ctx = ctx;
+ parseState.start = programString;
+ parseState.program = program;
+ parseState.numInst = 0;
+ parseState.curLine = programString;
+ parseState.parameters = _mesa_new_parameter_list();
+
+ /* Reset error state */
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ /* check the program header */
+ if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
+ target = GL_FRAGMENT_PROGRAM_NV;
+ parseState.pos = programString + 7;
+ }
+ else if (_mesa_strncmp((const char *) programString, "!!FCP1.0", 8) == 0) {
+ /* fragment / register combiner program - not supported */
+ _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
+ return;
+ }
+ else {
+ /* invalid header */
+ _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
+ return;
+ }
+
+ /* make sure target and header match */
+ if (target != dstTarget) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glLoadProgramNV(target mismatch 0x%x != 0x%x)",
+ target, dstTarget);
+ return;
+ }
+
+ if (Parse_InstructionSequence(&parseState, instBuffer)) {
+ GLuint u;
+ /* successful parse! */
+
+ if (parseState.outputsWritten == 0) {
+ /* must write at least one output! */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "Invalid fragment program - no outputs written.");
+ return;
+ }
+
+ /* copy the compiled instructions */
+ assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS);
+ newInst = _mesa_alloc_instructions(parseState.numInst);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return; /* out of memory */
+ }
+ _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
+
+ /* install the program */
+ program->Base.Target = target;
+ if (program->Base.String) {
+ FREE(program->Base.String);
+ }
+ program->Base.String = programString;
+ program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
+ if (program->Base.Instructions) {
+ _mesa_free(program->Base.Instructions);
+ }
+ program->Base.Instructions = newInst;
+ program->Base.NumInstructions = parseState.numInst;
+ program->Base.InputsRead = parseState.inputsRead;
+ program->Base.OutputsWritten = parseState.outputsWritten;
+ for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
+ program->Base.TexturesUsed[u] = parseState.texturesUsed[u];
+
+ /* save program parameters */
+ program->Base.Parameters = parseState.parameters;
+
+ /* allocate registers for declared program parameters */
+#if 00
+ _mesa_assign_program_registers(&(program->SymbolTable));
+#endif
+
+#ifdef DEBUG_foo
+ _mesa_printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
+ _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
+ _mesa_printf("----------------------------------\n");
+#endif
+ }
+ else {
+ /* Error! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
+ /* NOTE: _mesa_set_program_error would have been called already */
+ }
+}
+
+
+const char *
+_mesa_nv_fragment_input_register_name(GLuint i)
+{
+ ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
+ return InputRegisters[i];
+}
+
diff --git a/mesalib/src/mesa/shader/nvfragparse.h b/mesalib/src/mesa/shader/nvfragparse.h
new file mode 100644
index 000000000..544ab80c5
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvfragparse.h
@@ -0,0 +1,43 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#ifndef NVFRAGPARSE_H
+#define NVFRAGPARSE_H
+
+
+extern void
+_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target,
+ const GLubyte *str, GLsizei len,
+ struct gl_fragment_program *program);
+
+
+extern const char *
+_mesa_nv_fragment_input_register_name(GLuint i);
+
+#endif
diff --git a/mesalib/src/mesa/shader/nvprogram.c b/mesalib/src/mesa/shader/nvprogram.c
new file mode 100644
index 000000000..471a7358a
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvprogram.c
@@ -0,0 +1,890 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file nvprogram.c
+ * NVIDIA vertex/fragment program state management functions.
+ * \author Brian Paul
+ */
+
+/*
+ * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_instruction.h"
+#include "nvfragparse.h"
+#include "nvvertparse.h"
+#include "nvprogram.h"
+
+
+
+/**
+ * Execute a vertex state program.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
+{
+ struct gl_vertex_program *vprog;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target != GL_VERTEX_STATE_PROGRAM_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id);
+
+ if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
+ return;
+ }
+
+ _mesa_problem(ctx, "glExecuteProgramNV() not supported");
+}
+
+
+/**
+ * Determine if a set of programs is resident in hardware.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+GLboolean GLAPIENTRY
+_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
+ GLboolean *residences)
+{
+ GLint i, j;
+ GLboolean allResident = GL_TRUE;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
+ return GL_FALSE;
+ }
+
+ for (i = 0; i < n; i++) {
+ const struct gl_program *prog;
+ if (ids[i] == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
+ return GL_FALSE;
+ }
+ prog = _mesa_lookup_program(ctx, ids[i]);
+ if (!prog) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
+ return GL_FALSE;
+ }
+ if (prog->Resident) {
+ if (!allResident)
+ residences[i] = GL_TRUE;
+ }
+ else {
+ if (allResident) {
+ allResident = GL_FALSE;
+ for (j = 0; j < i; j++)
+ residences[j] = GL_TRUE;
+ }
+ residences[i] = GL_FALSE;
+ }
+ }
+
+ return allResident;
+}
+
+
+/**
+ * Request that a set of programs be resident in hardware.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
+{
+ GLint i;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
+ return;
+ }
+
+ /* just error checking for now */
+ for (i = 0; i < n; i++) {
+ struct gl_program *prog;
+
+ if (ids[i] == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
+ return;
+ }
+
+ prog = _mesa_lookup_program(ctx, ids[i]);
+ if (!prog) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
+ return;
+ }
+
+ /* XXX this is really a hardware thing we should hook out */
+ prog->Resident = GL_TRUE;
+ }
+}
+
+
+/**
+ * Get a program parameter register.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
+ GLenum pname, GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (pname == GL_PROGRAM_PARAMETER_NV) {
+ if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
+ COPY_4V(params, ctx->VertexProgram.Parameters[index]);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramParameterfvNV(index)");
+ return;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
+ return;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
+ return;
+ }
+}
+
+
+/**
+ * Get a program parameter register.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
+ GLenum pname, GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_NV) {
+ if (pname == GL_PROGRAM_PARAMETER_NV) {
+ if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
+ COPY_4V(params, ctx->VertexProgram.Parameters[index]);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramParameterdvNV(index)");
+ return;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
+ return;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
+ return;
+ }
+}
+
+
+/**
+ * Get a program attribute.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
+{
+ struct gl_program *prog;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ prog = _mesa_lookup_program(ctx, id);
+ if (!prog) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
+ return;
+ }
+
+ switch (pname) {
+ case GL_PROGRAM_TARGET_NV:
+ *params = prog->Target;
+ return;
+ case GL_PROGRAM_LENGTH_NV:
+ *params = prog->String ?(GLint)_mesa_strlen((char *) prog->String) : 0;
+ return;
+ case GL_PROGRAM_RESIDENT_NV:
+ *params = prog->Resident;
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
+ return;
+ }
+}
+
+
+/**
+ * Get the program source code.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
+{
+ struct gl_program *prog;
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (pname != GL_PROGRAM_STRING_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
+ return;
+ }
+
+ prog = _mesa_lookup_program(ctx, id);
+ if (!prog) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
+ return;
+ }
+
+ if (prog->String) {
+ MEMCPY(program, prog->String, _mesa_strlen((char *) prog->String));
+ }
+ else {
+ program[0] = 0;
+ }
+}
+
+
+/**
+ * Get matrix tracking information.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_NV
+ && ctx->Extensions.NV_vertex_program) {
+ GLuint i;
+
+ if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
+ return;
+ }
+
+ i = address / 4;
+
+ switch (pname) {
+ case GL_TRACK_MATRIX_NV:
+ params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
+ return;
+ case GL_TRACK_MATRIX_TRANSFORM_NV:
+ params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
+ return;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
+ return;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
+ return;
+ }
+}
+
+
+/**
+ * Get a vertex (or vertex array) attribute.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
+{
+ const struct gl_client_array *array;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
+ return;
+ }
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
+ switch (pname) {
+ case GL_ATTRIB_ARRAY_SIZE_NV:
+ params[0] = array->Size;
+ break;
+ case GL_ATTRIB_ARRAY_STRIDE_NV:
+ params[0] = array->Stride;
+ break;
+ case GL_ATTRIB_ARRAY_TYPE_NV:
+ params[0] = array->Type;
+ break;
+ case GL_CURRENT_ATTRIB_NV:
+ if (index == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexAttribdvNV(index == 0)");
+ return;
+ }
+ FLUSH_CURRENT(ctx, 0);
+ COPY_4V(params, ctx->Current.Attrib[index]);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
+ return;
+ }
+}
+
+/**
+ * Get a vertex (or vertex array) attribute.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
+{
+ const struct gl_client_array *array;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
+ return;
+ }
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
+ switch (pname) {
+ case GL_ATTRIB_ARRAY_SIZE_NV:
+ params[0] = (GLfloat) array->Size;
+ break;
+ case GL_ATTRIB_ARRAY_STRIDE_NV:
+ params[0] = (GLfloat) array->Stride;
+ break;
+ case GL_ATTRIB_ARRAY_TYPE_NV:
+ params[0] = (GLfloat) array->Type;
+ break;
+ case GL_CURRENT_ATTRIB_NV:
+ if (index == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexAttribfvNV(index == 0)");
+ return;
+ }
+ FLUSH_CURRENT(ctx, 0);
+ COPY_4V(params, ctx->Current.Attrib[index]);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
+ return;
+ }
+}
+
+/**
+ * Get a vertex (or vertex array) attribute.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
+{
+ const struct gl_client_array *array;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
+ return;
+ }
+
+ array = &ctx->Array.ArrayObj->VertexAttrib[index];
+
+ switch (pname) {
+ case GL_ATTRIB_ARRAY_SIZE_NV:
+ params[0] = array->Size;
+ break;
+ case GL_ATTRIB_ARRAY_STRIDE_NV:
+ params[0] = array->Stride;
+ break;
+ case GL_ATTRIB_ARRAY_TYPE_NV:
+ params[0] = array->Type;
+ break;
+ case GL_CURRENT_ATTRIB_NV:
+ if (index == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetVertexAttribivNV(index == 0)");
+ return;
+ }
+ FLUSH_CURRENT(ctx, 0);
+ params[0] = (GLint) ctx->Current.Attrib[index][0];
+ params[1] = (GLint) ctx->Current.Attrib[index][1];
+ params[2] = (GLint) ctx->Current.Attrib[index][2];
+ params[3] = (GLint) ctx->Current.Attrib[index][3];
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
+ params[0] = array->BufferObj->Name;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
+ return;
+ }
+}
+
+
+/**
+ * Get a vertex array attribute pointer.
+ * \note Not compiled into display lists.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
+ return;
+ }
+
+ if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
+ return;
+ }
+
+ *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
+}
+
+void
+_mesa_emit_nv_temp_initialization(GLcontext *ctx,
+ struct gl_program *program)
+{
+ struct prog_instruction *inst;
+ int i;
+
+ if (!ctx->Shader.EmitNVTempInitialization)
+ return;
+
+ /* We'll swizzle up a zero temporary so we can use it for the
+ * ARL.
+ */
+ if (program->NumTemporaries == 0)
+ program->NumTemporaries = 1;
+
+ _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);
+
+ for (i = 0; i < program->NumTemporaries; i++) {
+ struct prog_instruction *inst = &program->Instructions[i];
+
+ inst->Opcode = OPCODE_SWZ;
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = i;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = 0;
+ inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO,
+ SWIZZLE_ZERO);
+ }
+
+ inst = &program->Instructions[i];
+ inst->Opcode = OPCODE_ARL;
+ inst->DstReg.File = PROGRAM_ADDRESS;
+ inst->DstReg.Index = 0;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = 0;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
+
+ if (program->NumAddressRegs == 0)
+ program->NumAddressRegs = 1;
+}
+
+void
+_mesa_setup_nv_temporary_count(GLcontext *ctx, struct gl_program *program)
+{
+ int i;
+
+ program->NumTemporaries = 0;
+ for (i = 0; i < program->NumInstructions; i++) {
+ struct prog_instruction *inst = &program->Instructions[i];
+
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ program->NumTemporaries = MAX2(program->NumTemporaries,
+ inst->DstReg.Index + 1);
+ }
+ if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) {
+ program->NumTemporaries = MAX2(program->NumTemporaries,
+ inst->SrcReg[0].Index + 1);
+ }
+ if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) {
+ program->NumTemporaries = MAX2(program->NumTemporaries,
+ inst->SrcReg[1].Index + 1);
+ }
+ if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) {
+ program->NumTemporaries = MAX2(program->NumTemporaries,
+ inst->SrcReg[2].Index + 1);
+ }
+ }
+}
+
+/**
+ * Load/parse/compile a program.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
+ const GLubyte *program)
+{
+ struct gl_program *prog;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (id == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
+ return;
+ }
+
+ if (len < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ prog = _mesa_lookup_program(ctx, id);
+
+ if (prog && prog->Target != 0 && prog->Target != target) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
+ return;
+ }
+
+ if ((target == GL_VERTEX_PROGRAM_NV ||
+ target == GL_VERTEX_STATE_PROGRAM_NV)
+ && ctx->Extensions.NV_vertex_program) {
+ struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
+ if (!vprog || prog == &_mesa_DummyProgram) {
+ vprog = (struct gl_vertex_program *)
+ ctx->Driver.NewProgram(ctx, target, id);
+ if (!vprog) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
+ }
+ _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
+ }
+ else if (target == GL_FRAGMENT_PROGRAM_NV
+ && ctx->Extensions.NV_fragment_program) {
+ struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
+ if (!fprog || prog == &_mesa_DummyProgram) {
+ fprog = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, target, id);
+ if (!fprog) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
+ }
+ _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
+ }
+}
+
+
+
+/**
+ * Set a sequence of program parameter registers.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
+ GLuint num, const GLdouble *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
+ GLuint i;
+ if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
+ return;
+ }
+ for (i = 0; i < num; i++) {
+ ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
+ ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
+ ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
+ ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
+ params += 4;
+ };
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
+ return;
+ }
+}
+
+
+/**
+ * Set a sequence of program parameter registers.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
+ GLuint num, const GLfloat *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
+ GLuint i;
+ if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
+ return;
+ }
+ for (i = 0; i < num; i++) {
+ COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
+ params += 4;
+ }
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
+ return;
+ }
+}
+
+
+
+/**
+ * Setup tracking of matrices into program parameter registers.
+ * \note Called from the GL API dispatcher.
+ */
+void GLAPIENTRY
+_mesa_TrackMatrixNV(GLenum target, GLuint address,
+ GLenum matrix, GLenum transform)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
+ if (address & 0x3) {
+ /* addr must be multiple of four */
+ _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
+ return;
+ }
+
+ switch (matrix) {
+ case GL_NONE:
+ case GL_MODELVIEW:
+ case GL_PROJECTION:
+ case GL_TEXTURE:
+ case GL_COLOR:
+ case GL_MODELVIEW_PROJECTION_NV:
+ case GL_MATRIX0_NV:
+ case GL_MATRIX1_NV:
+ case GL_MATRIX2_NV:
+ case GL_MATRIX3_NV:
+ case GL_MATRIX4_NV:
+ case GL_MATRIX5_NV:
+ case GL_MATRIX6_NV:
+ case GL_MATRIX7_NV:
+ /* OK, fallthrough */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
+ return;
+ }
+
+ switch (transform) {
+ case GL_IDENTITY_NV:
+ case GL_INVERSE_NV:
+ case GL_TRANSPOSE_NV:
+ case GL_INVERSE_TRANSPOSE_NV:
+ /* OK, fallthrough */
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
+ return;
+ }
+
+ ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
+ ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
+ }
+ else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ struct gl_program *prog;
+ struct gl_fragment_program *fragProg;
+ GLfloat *v;
+
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ prog = _mesa_lookup_program(ctx, id);
+ if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
+ return;
+ }
+
+ if (len <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
+ return;
+ }
+
+ fragProg = (struct gl_fragment_program *) prog;
+ v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
+ (char *) name);
+ if (v) {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ v[3] = w;
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
+ const float v[])
+{
+ _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
+ (GLfloat)z, (GLfloat)w);
+}
+
+
+void GLAPIENTRY
+_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
+ const double v[])
+{
+ _mesa_ProgramNamedParameter4fNV(id, len, name,
+ (GLfloat)v[0], (GLfloat)v[1],
+ (GLfloat)v[2], (GLfloat)v[3]);
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLfloat *params)
+{
+ struct gl_program *prog;
+ struct gl_fragment_program *fragProg;
+ const GLfloat *v;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ prog = _mesa_lookup_program(ctx, id);
+ if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
+ return;
+ }
+
+ if (len <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
+ return;
+ }
+
+ fragProg = (struct gl_fragment_program *) prog;
+ v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
+ len, (char *) name);
+ if (v) {
+ params[0] = v[0];
+ params[1] = v[1];
+ params[2] = v[2];
+ params[3] = v[3];
+ return;
+ }
+
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
+}
+
+
+void GLAPIENTRY
+_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLdouble *params)
+{
+ GLfloat floatParams[4];
+ _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
+ COPY_4V(params, floatParams);
+}
diff --git a/mesalib/src/mesa/shader/nvprogram.h b/mesalib/src/mesa/shader/nvprogram.h
new file mode 100644
index 000000000..8ee59661b
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvprogram.h
@@ -0,0 +1,113 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#ifndef NVPROGRAM_H
+#define NVPROGRAM_H
+
+
+extern void GLAPIENTRY
+_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params);
+
+extern GLboolean GLAPIENTRY
+_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, GLboolean *residences);
+
+extern void GLAPIENTRY
+_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids);
+
+extern void GLAPIENTRY
+_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, GLenum pname, GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, GLenum pname, GLdouble *params);
+
+extern void GLAPIENTRY
+_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program);
+
+extern void GLAPIENTRY
+_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params);
+
+extern void GLAPIENTRY
+_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer);
+
+extern void GLAPIENTRY
+_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+
+extern void GLAPIENTRY
+_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, GLuint num, const GLdouble *params);
+
+extern void GLAPIENTRY
+_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, GLuint num, const GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_TrackMatrixNV(GLenum target, GLuint address, GLenum matrix, GLenum transform);
+
+
+extern void GLAPIENTRY
+_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+extern void GLAPIENTRY
+_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
+ const float v[]);
+
+extern void GLAPIENTRY
+_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+
+extern void GLAPIENTRY
+_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
+ const double v[]);
+
+extern void GLAPIENTRY
+_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLfloat *params);
+
+extern void GLAPIENTRY
+_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
+ GLdouble *params);
+
+extern void
+_mesa_setup_nv_temporary_count(GLcontext *ctx, struct gl_program *program);
+
+extern void
+_mesa_emit_nv_temp_initialization(GLcontext *ctx,
+ struct gl_program *program);
+
+#endif
diff --git a/mesalib/src/mesa/shader/nvvertparse.c b/mesalib/src/mesa/shader/nvvertparse.c
new file mode 100644
index 000000000..857401605
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvvertparse.c
@@ -0,0 +1,1455 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file nvvertparse.c
+ * NVIDIA vertex program parser.
+ * \author Brian Paul
+ */
+
+/*
+ * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "nvprogram.h"
+#include "nvvertparse.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+#include "program.h"
+
+
+/**
+ * Current parsing state. This structure is passed among the parsing
+ * functions and keeps track of the current parser position and various
+ * program attributes.
+ */
+struct parse_state {
+ GLcontext *ctx;
+ const GLubyte *start;
+ const GLubyte *pos;
+ const GLubyte *curLine;
+ GLboolean isStateProgram;
+ GLboolean isPositionInvariant;
+ GLboolean isVersion1_1;
+ GLbitfield inputsRead;
+ GLbitfield outputsWritten;
+ GLboolean anyProgRegsWritten;
+ GLuint numInst; /* number of instructions parsed */
+};
+
+
+/*
+ * Called whenever we find an error during parsing.
+ */
+static void
+record_error(struct parse_state *parseState, const char *msg, int lineNo)
+{
+#ifdef DEBUG
+ GLint line, column;
+ const GLubyte *lineStr;
+ lineStr = _mesa_find_line_column(parseState->start,
+ parseState->pos, &line, &column);
+ _mesa_debug(parseState->ctx,
+ "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
+ lineNo, line, column, (char *) lineStr, msg);
+ _mesa_free((void *) lineStr);
+#else
+ (void) lineNo;
+#endif
+
+ /* Check that no error was already recorded. Only record the first one. */
+ if (parseState->ctx->Program.ErrorString[0] == 0) {
+ _mesa_set_program_error(parseState->ctx,
+ parseState->pos - parseState->start,
+ msg);
+ }
+}
+
+
+#define RETURN_ERROR \
+do { \
+ record_error(parseState, "Unexpected end of input.", __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+#define RETURN_ERROR1(msg) \
+do { \
+ record_error(parseState, msg, __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+#define RETURN_ERROR2(msg1, msg2) \
+do { \
+ char err[1000]; \
+ _mesa_sprintf(err, "%s %s", msg1, msg2); \
+ record_error(parseState, err, __LINE__); \
+ return GL_FALSE; \
+} while(0)
+
+
+
+
+
+static GLboolean IsLetter(GLubyte b)
+{
+ return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
+}
+
+
+static GLboolean IsDigit(GLubyte b)
+{
+ return b >= '0' && b <= '9';
+}
+
+
+static GLboolean IsWhitespace(GLubyte b)
+{
+ return b == ' ' || b == '\t' || b == '\n' || b == '\r';
+}
+
+
+/**
+ * Starting at 'str' find the next token. A token can be an integer,
+ * an identifier or punctuation symbol.
+ * \return <= 0 we found an error, else, return number of characters parsed.
+ */
+static GLint
+GetToken(struct parse_state *parseState, GLubyte *token)
+{
+ const GLubyte *str = parseState->pos;
+ GLint i = 0, j = 0;
+
+ token[0] = 0;
+
+ /* skip whitespace and comments */
+ while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
+ if (str[i] == '#') {
+ /* skip comment */
+ while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
+ i++;
+ }
+ if (str[i] == '\n' || str[i] == '\r')
+ parseState->curLine = str + i + 1;
+ }
+ else {
+ /* skip whitespace */
+ if (str[i] == '\n' || str[i] == '\r')
+ parseState->curLine = str + i + 1;
+ i++;
+ }
+ }
+
+ if (str[i] == 0)
+ return -i;
+
+ /* try matching an integer */
+ while (str[i] && IsDigit(str[i])) {
+ token[j++] = str[i++];
+ }
+ if (j > 0 || !str[i]) {
+ token[j] = 0;
+ return i;
+ }
+
+ /* try matching an identifier */
+ if (IsLetter(str[i])) {
+ while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
+ token[j++] = str[i++];
+ }
+ token[j] = 0;
+ return i;
+ }
+
+ /* punctuation character */
+ if (str[i]) {
+ token[0] = str[i++];
+ token[1] = 0;
+ return i;
+ }
+
+ /* end of input */
+ token[0] = 0;
+ return i;
+}
+
+
+/**
+ * Get next token from input stream and increment stream pointer past token.
+ */
+static GLboolean
+Parse_Token(struct parse_state *parseState, GLubyte *token)
+{
+ GLint i;
+ i = GetToken(parseState, token);
+ if (i <= 0) {
+ parseState->pos += (-i);
+ return GL_FALSE;
+ }
+ parseState->pos += i;
+ return GL_TRUE;
+}
+
+
+/**
+ * Get next token from input stream but don't increment stream pointer.
+ */
+static GLboolean
+Peek_Token(struct parse_state *parseState, GLubyte *token)
+{
+ GLint i, len;
+ i = GetToken(parseState, token);
+ if (i <= 0) {
+ parseState->pos += (-i);
+ return GL_FALSE;
+ }
+ len = (GLint)_mesa_strlen((const char *) token);
+ parseState->pos += (i - len);
+ return GL_TRUE;
+}
+
+
+/**
+ * Try to match 'pattern' as the next token after any whitespace/comments.
+ * Advance the current parsing position only if we match the pattern.
+ * \return GL_TRUE if pattern is matched, GL_FALSE otherwise.
+ */
+static GLboolean
+Parse_String(struct parse_state *parseState, const char *pattern)
+{
+ const GLubyte *m;
+ GLint i;
+
+ /* skip whitespace and comments */
+ while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
+ if (*parseState->pos == '#') {
+ while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
+ parseState->pos += 1;
+ }
+ if (*parseState->pos == '\n' || *parseState->pos == '\r')
+ parseState->curLine = parseState->pos + 1;
+ }
+ else {
+ /* skip whitespace */
+ if (*parseState->pos == '\n' || *parseState->pos == '\r')
+ parseState->curLine = parseState->pos + 1;
+ parseState->pos += 1;
+ }
+ }
+
+ /* Try to match the pattern */
+ m = parseState->pos;
+ for (i = 0; pattern[i]; i++) {
+ if (*m != (GLubyte) pattern[i])
+ return GL_FALSE;
+ m += 1;
+ }
+ parseState->pos = m;
+
+ return GL_TRUE; /* success */
+}
+
+
+/**********************************************************************/
+
+static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
+ "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
+ "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
+};
+
+static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
+ "HPOS", "COL0", "COL1", "FOGC",
+ "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7",
+ "PSIZ", "BFC0", "BFC1", NULL
+};
+
+
+
+/**
+ * Parse a temporary register: Rnn
+ */
+static GLboolean
+Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
+{
+ GLubyte token[100];
+
+ /* Should be 'R##' */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+ if (token[0] != 'R')
+ RETURN_ERROR1("Expected R##");
+
+ if (IsDigit(token[1])) {
+ GLint reg = _mesa_atoi((char *) (token + 1));
+ if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS)
+ RETURN_ERROR1("Bad temporary register name");
+ *tempRegNum = reg;
+ }
+ else {
+ RETURN_ERROR1("Bad temporary register name");
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse address register "A0.x"
+ */
+static GLboolean
+Parse_AddrReg(struct parse_state *parseState)
+{
+ /* match 'A0' */
+ if (!Parse_String(parseState, "A0"))
+ RETURN_ERROR;
+
+ /* match '.' */
+ if (!Parse_String(parseState, "."))
+ RETURN_ERROR;
+
+ /* match 'x' */
+ if (!Parse_String(parseState, "x"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse absolute program parameter register "c[##]"
+ */
+static GLboolean
+Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
+{
+ GLubyte token[100];
+
+ if (!Parse_String(parseState, "c"))
+ RETURN_ERROR;
+
+ if (!Parse_String(parseState, "["))
+ RETURN_ERROR;
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (IsDigit(token[0])) {
+ /* a numbered program parameter register */
+ GLint reg = _mesa_atoi((char *) token);
+ if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
+ RETURN_ERROR1("Bad program parameter number");
+ *regNum = reg;
+ }
+ else {
+ RETURN_ERROR;
+ }
+
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg)
+{
+ GLubyte token[100];
+
+ if (!Parse_String(parseState, "c"))
+ RETURN_ERROR;
+
+ if (!Parse_String(parseState, "["))
+ RETURN_ERROR;
+
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (IsDigit(token[0])) {
+ /* a numbered program parameter register */
+ GLint reg;
+ (void) Parse_Token(parseState, token);
+ reg = _mesa_atoi((char *) token);
+ if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
+ RETURN_ERROR1("Bad program parameter number");
+ srcReg->File = PROGRAM_ENV_PARAM;
+ srcReg->Index = reg;
+ }
+ else if (_mesa_strcmp((const char *) token, "A0") == 0) {
+ /* address register "A0.x" */
+ if (!Parse_AddrReg(parseState))
+ RETURN_ERROR;
+
+ srcReg->RelAddr = GL_TRUE;
+ srcReg->File = PROGRAM_ENV_PARAM;
+ /* Look for +/-N offset */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[0] == '-' || token[0] == '+') {
+ const GLubyte sign = token[0];
+ (void) Parse_Token(parseState, token); /* consume +/- */
+
+ /* an integer should be next */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (IsDigit(token[0])) {
+ const GLint k = _mesa_atoi((char *) token);
+ if (sign == '-') {
+ if (k > 64)
+ RETURN_ERROR1("Bad address offset");
+ srcReg->Index = -k;
+ }
+ else {
+ if (k > 63)
+ RETURN_ERROR1("Bad address offset");
+ srcReg->Index = k;
+ }
+ }
+ else {
+ RETURN_ERROR;
+ }
+ }
+ else {
+ /* probably got a ']', catch it below */
+ }
+ }
+ else {
+ RETURN_ERROR;
+ }
+
+ /* Match closing ']' */
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Parse v[#] or v[<name>]
+ */
+static GLboolean
+Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum)
+{
+ GLubyte token[100];
+ GLint j;
+
+ /* Match 'v' */
+ if (!Parse_String(parseState, "v"))
+ RETURN_ERROR;
+
+ /* Match '[' */
+ if (!Parse_String(parseState, "["))
+ RETURN_ERROR;
+
+ /* match number or named register */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (parseState->isStateProgram && token[0] != '0')
+ RETURN_ERROR1("Only v[0] accessible in vertex state programs");
+
+ if (IsDigit(token[0])) {
+ GLint reg = _mesa_atoi((char *) token);
+ if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS)
+ RETURN_ERROR1("Bad vertex attribute register name");
+ *tempRegNum = reg;
+ }
+ else {
+ for (j = 0; InputRegisters[j]; j++) {
+ if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
+ *tempRegNum = j;
+ break;
+ }
+ }
+ if (!InputRegisters[j]) {
+ /* unknown input register label */
+ RETURN_ERROR2("Bad register name", token);
+ }
+ }
+
+ /* Match '[' */
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
+{
+ GLubyte token[100];
+ GLint start, j;
+
+ /* Match 'o' */
+ if (!Parse_String(parseState, "o"))
+ RETURN_ERROR;
+
+ /* Match '[' */
+ if (!Parse_String(parseState, "["))
+ RETURN_ERROR;
+
+ /* Get output reg name */
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (parseState->isPositionInvariant)
+ start = 1; /* skip HPOS register name */
+ else
+ start = 0;
+
+ /* try to match an output register name */
+ for (j = start; OutputRegisters[j]; j++) {
+ if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
+ *outputRegNum = j;
+ break;
+ }
+ }
+ if (!OutputRegisters[j])
+ RETURN_ERROR1("Unrecognized output register name");
+
+ /* Match ']' */
+ if (!Parse_String(parseState, "]"))
+ RETURN_ERROR1("Expected ]");
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg)
+{
+ GLubyte token[100];
+ GLint idx;
+
+ /* Dst reg can be R<n> or o[n] */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[0] == 'R') {
+ /* a temporary register */
+ dstReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else if (!parseState->isStateProgram && token[0] == 'o') {
+ /* an output register */
+ dstReg->File = PROGRAM_OUTPUT;
+ if (!Parse_OutputReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else if (parseState->isStateProgram && token[0] == 'c' &&
+ parseState->isStateProgram) {
+ /* absolute program parameter register */
+ /* Only valid for vertex state programs */
+ dstReg->File = PROGRAM_ENV_PARAM;
+ if (!Parse_AbsParamReg(parseState, &idx))
+ RETURN_ERROR;
+ dstReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR1("Bad destination register name");
+ }
+
+ /* Parse optional write mask */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[0] == '.') {
+ /* got a mask */
+ GLint k = 0;
+
+ if (!Parse_String(parseState, "."))
+ RETURN_ERROR;
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ dstReg->WriteMask = 0;
+
+ if (token[k] == 'x') {
+ dstReg->WriteMask |= WRITEMASK_X;
+ k++;
+ }
+ if (token[k] == 'y') {
+ dstReg->WriteMask |= WRITEMASK_Y;
+ k++;
+ }
+ if (token[k] == 'z') {
+ dstReg->WriteMask |= WRITEMASK_Z;
+ k++;
+ }
+ if (token[k] == 'w') {
+ dstReg->WriteMask |= WRITEMASK_W;
+ k++;
+ }
+ if (k == 0) {
+ RETURN_ERROR1("Bad writemask character");
+ }
+ return GL_TRUE;
+ }
+ else {
+ dstReg->WriteMask = WRITEMASK_XYZW;
+ return GL_TRUE;
+ }
+}
+
+
+static GLboolean
+Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
+{
+ GLubyte token[100];
+ GLint idx;
+
+ srcReg->RelAddr = GL_FALSE;
+
+ /* check for '-' */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+ if (token[0] == '-') {
+ (void) Parse_String(parseState, "-");
+ srcReg->Negate = NEGATE_XYZW;
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+ }
+ else {
+ srcReg->Negate = NEGATE_NONE;
+ }
+
+ /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
+ if (token[0] == 'R') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'c') {
+ if (!Parse_ParamReg(parseState, srcReg))
+ RETURN_ERROR;
+ }
+ else if (token[0] == 'v') {
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_AttribReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR2("Bad source register name", token);
+ }
+
+ /* init swizzle fields */
+ srcReg->Swizzle = SWIZZLE_NOOP;
+
+ /* Look for optional swizzle suffix */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+ if (token[0] == '.') {
+ (void) Parse_String(parseState, "."); /* consume . */
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[1] == 0) {
+ /* single letter swizzle */
+ if (token[0] == 'x')
+ srcReg->Swizzle = SWIZZLE_XXXX;
+ else if (token[0] == 'y')
+ srcReg->Swizzle = SWIZZLE_YYYY;
+ else if (token[0] == 'z')
+ srcReg->Swizzle = SWIZZLE_ZZZZ;
+ else if (token[0] == 'w')
+ srcReg->Swizzle = SWIZZLE_WWWW;
+ else
+ RETURN_ERROR1("Expected x, y, z, or w");
+ }
+ else {
+ /* 2, 3 or 4-component swizzle */
+ GLint k;
+
+ srcReg->Swizzle = 0;
+
+ for (k = 0; token[k] && k < 5; k++) {
+ if (token[k] == 'x')
+ srcReg->Swizzle |= 0 << (k*3);
+ else if (token[k] == 'y')
+ srcReg->Swizzle |= 1 << (k*3);
+ else if (token[k] == 'z')
+ srcReg->Swizzle |= 2 << (k*3);
+ else if (token[k] == 'w')
+ srcReg->Swizzle |= 3 << (k*3);
+ else
+ RETURN_ERROR;
+ }
+ if (k >= 5)
+ RETURN_ERROR;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
+{
+ GLubyte token[100];
+ GLint idx;
+
+ srcReg->RelAddr = GL_FALSE;
+
+ /* check for '-' */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+ if (token[0] == '-') {
+ srcReg->Negate = NEGATE_XYZW;
+ (void) Parse_String(parseState, "-"); /* consume '-' */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+ }
+ else {
+ srcReg->Negate = NEGATE_NONE;
+ }
+
+ /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
+ if (token[0] == 'R') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'c') {
+ if (!Parse_ParamReg(parseState, srcReg))
+ RETURN_ERROR;
+ }
+ else if (token[0] == 'v') {
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_AttribReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR2("Bad source register name", token);
+ }
+
+ /* Look for .[xyzw] suffix */
+ if (!Parse_String(parseState, "."))
+ RETURN_ERROR;
+
+ if (!Parse_Token(parseState, token))
+ RETURN_ERROR;
+
+ if (token[0] == 'x' && token[1] == 0) {
+ srcReg->Swizzle = 0;
+ }
+ else if (token[0] == 'y' && token[1] == 0) {
+ srcReg->Swizzle = 1;
+ }
+ else if (token[0] == 'z' && token[1] == 0) {
+ srcReg->Swizzle = 2;
+ }
+ else if (token[0] == 'w' && token[1] == 0) {
+ srcReg->Swizzle = 3;
+ }
+ else {
+ RETURN_ERROR1("Bad scalar source suffix");
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLint
+Parse_UnaryOpInstruction(struct parse_state *parseState,
+ struct prog_instruction *inst,
+ enum prog_opcode opcode)
+{
+ if (opcode == OPCODE_ABS && !parseState->isVersion1_1)
+ RETURN_ERROR1("ABS illegal for vertex program 1.0");
+
+ inst->Opcode = opcode;
+
+ /* dest reg */
+ if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_BiOpInstruction(struct parse_state *parseState,
+ struct prog_instruction *inst,
+ enum prog_opcode opcode)
+{
+ if (opcode == OPCODE_DPH && !parseState->isVersion1_1)
+ RETURN_ERROR1("DPH illegal for vertex program 1.0");
+ if (opcode == OPCODE_SUB && !parseState->isVersion1_1)
+ RETURN_ERROR1("SUB illegal for vertex program 1.0");
+
+ inst->Opcode = opcode;
+
+ /* dest reg */
+ if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* first src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* second src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ /* make sure we don't reference more than one program parameter register */
+ if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[0].Index != inst->SrcReg[1].Index)
+ RETURN_ERROR1("Can't reference two program parameter registers");
+
+ /* make sure we don't reference more than one vertex attribute register */
+ if (inst->SrcReg[0].File == PROGRAM_INPUT &&
+ inst->SrcReg[1].File == PROGRAM_INPUT &&
+ inst->SrcReg[0].Index != inst->SrcReg[1].Index)
+ RETURN_ERROR1("Can't reference two vertex attribute registers");
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_TriOpInstruction(struct parse_state *parseState,
+ struct prog_instruction *inst,
+ enum prog_opcode opcode)
+{
+ inst->Opcode = opcode;
+
+ /* dest reg */
+ if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* first src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* second src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* third src arg */
+ if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2]))
+ RETURN_ERROR;
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ /* make sure we don't reference more than one program parameter register */
+ if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
+ (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
+ (inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
+ inst->SrcReg[1].Index != inst->SrcReg[2].Index))
+ RETURN_ERROR1("Can only reference one program register");
+
+ /* make sure we don't reference more than one vertex attribute register */
+ if ((inst->SrcReg[0].File == PROGRAM_INPUT &&
+ inst->SrcReg[1].File == PROGRAM_INPUT &&
+ inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
+ (inst->SrcReg[0].File == PROGRAM_INPUT &&
+ inst->SrcReg[2].File == PROGRAM_INPUT &&
+ inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
+ (inst->SrcReg[1].File == PROGRAM_INPUT &&
+ inst->SrcReg[2].File == PROGRAM_INPUT &&
+ inst->SrcReg[1].Index != inst->SrcReg[2].Index))
+ RETURN_ERROR1("Can only reference one input register");
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_ScalarInstruction(struct parse_state *parseState,
+ struct prog_instruction *inst,
+ enum prog_opcode opcode)
+{
+ if (opcode == OPCODE_RCC && !parseState->isVersion1_1)
+ RETURN_ERROR1("RCC illegal for vertex program 1.0");
+
+ inst->Opcode = opcode;
+
+ /* dest reg */
+ if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* first src arg */
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst)
+{
+ inst->Opcode = OPCODE_ARL;
+
+ /* Make ARB_vp backends happy */
+ inst->DstReg.File = PROGRAM_ADDRESS;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ inst->DstReg.Index = 0;
+
+ /* dest A0 reg */
+ if (!Parse_AddrReg(parseState))
+ RETURN_ERROR;
+
+ /* comma */
+ if (!Parse_String(parseState, ","))
+ RETURN_ERROR;
+
+ /* parse src reg */
+ if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
+ RETURN_ERROR;
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst)
+{
+ GLubyte token[100];
+
+ inst->Opcode = OPCODE_END;
+
+ /* this should fail! */
+ if (Parse_Token(parseState, token))
+ RETURN_ERROR2("Unexpected token after END:", token);
+ else
+ return GL_TRUE;
+}
+
+
+/**
+ * The PRINT instruction is Mesa-specific and is meant as a debugging aid for
+ * the vertex program developer.
+ * The NV_vertex_program extension grammar is modified as follows:
+ *
+ * <instruction> ::= <ARL-instruction>
+ * | ...
+ * | <PRINT-instruction>
+ *
+ * <PRINT-instruction> ::= "PRINT" <string literal>
+ * | "PRINT" <string literal> "," <srcReg>
+ * | "PRINT" <string literal> "," <dstReg>
+ */
+static GLboolean
+Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst)
+{
+ const GLubyte *str;
+ GLubyte *msg;
+ GLuint len;
+ GLubyte token[100];
+ struct prog_src_register *srcReg = &inst->SrcReg[0];
+ GLint idx;
+
+ inst->Opcode = OPCODE_PRINT;
+
+ /* The first argument is a literal string 'just like this' */
+ if (!Parse_String(parseState, "'"))
+ RETURN_ERROR;
+
+ str = parseState->pos;
+ for (len = 0; str[len] != '\''; len++) /* find closing quote */
+ ;
+ parseState->pos += len + 1;
+ msg = (GLubyte*) _mesa_malloc(len + 1);
+
+ _mesa_memcpy(msg, str, len);
+ msg[len] = 0;
+ inst->Data = msg;
+
+ /* comma */
+ if (Parse_String(parseState, ",")) {
+
+ /* The second argument is a register name */
+ if (!Peek_Token(parseState, token))
+ RETURN_ERROR;
+
+ srcReg->RelAddr = GL_FALSE;
+ srcReg->Negate = NEGATE_NONE;
+ srcReg->Swizzle = SWIZZLE_NOOP;
+
+ /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
+ * or an o[n] output register.
+ */
+ if (token[0] == 'R') {
+ srcReg->File = PROGRAM_TEMPORARY;
+ if (!Parse_TempReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'c') {
+ srcReg->File = PROGRAM_ENV_PARAM;
+ if (!Parse_ParamReg(parseState, srcReg))
+ RETURN_ERROR;
+ }
+ else if (token[0] == 'v') {
+ srcReg->File = PROGRAM_INPUT;
+ if (!Parse_AttribReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else if (token[0] == 'o') {
+ srcReg->File = PROGRAM_OUTPUT;
+ if (!Parse_OutputReg(parseState, &idx))
+ RETURN_ERROR;
+ srcReg->Index = idx;
+ }
+ else {
+ RETURN_ERROR2("Bad source register name", token);
+ }
+ }
+ else {
+ srcReg->File = 0;
+ }
+
+ /* semicolon */
+ if (!Parse_String(parseState, ";"))
+ RETURN_ERROR;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+Parse_OptionSequence(struct parse_state *parseState,
+ struct prog_instruction program[])
+{
+ (void) program;
+ while (1) {
+ if (!Parse_String(parseState, "OPTION"))
+ return GL_TRUE; /* ok, not an OPTION statement */
+ if (Parse_String(parseState, "NV_position_invariant")) {
+ parseState->isPositionInvariant = GL_TRUE;
+ }
+ else {
+ RETURN_ERROR1("unexpected OPTION statement");
+ }
+ if (!Parse_String(parseState, ";"))
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean
+Parse_InstructionSequence(struct parse_state *parseState,
+ struct prog_instruction program[])
+{
+ while (1) {
+ struct prog_instruction *inst = program + parseState->numInst;
+
+ /* Initialize the instruction */
+ _mesa_init_instructions(inst, 1);
+
+ if (Parse_String(parseState, "MOV")) {
+ if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "LIT")) {
+ if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "ABS")) {
+ if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "MUL")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "ADD")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "DP3")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "DP4")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "DST")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "MIN")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "MAX")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "SLT")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "SGE")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "DPH")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "SUB")) {
+ if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "MAD")) {
+ if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "RCP")) {
+ if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "RSQ")) {
+ if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "EXP")) {
+ if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "LOG")) {
+ if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "RCC")) {
+ if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "ARL")) {
+ if (!Parse_AddressInstruction(parseState, inst))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "PRINT")) {
+ if (!Parse_PrintInstruction(parseState, inst))
+ RETURN_ERROR;
+ }
+ else if (Parse_String(parseState, "END")) {
+ if (!Parse_EndInstruction(parseState, inst))
+ RETURN_ERROR;
+ else {
+ parseState->numInst++;
+ return GL_TRUE; /* all done */
+ }
+ }
+ else {
+ /* bad instruction name */
+ RETURN_ERROR1("Unexpected token");
+ }
+
+ /* examine input/output registers */
+ if (inst->DstReg.File == PROGRAM_OUTPUT)
+ parseState->outputsWritten |= (1 << inst->DstReg.Index);
+ else if (inst->DstReg.File == PROGRAM_ENV_PARAM)
+ parseState->anyProgRegsWritten = GL_TRUE;
+
+ if (inst->SrcReg[0].File == PROGRAM_INPUT)
+ parseState->inputsRead |= (1 << inst->SrcReg[0].Index);
+ if (inst->SrcReg[1].File == PROGRAM_INPUT)
+ parseState->inputsRead |= (1 << inst->SrcReg[1].Index);
+ if (inst->SrcReg[2].File == PROGRAM_INPUT)
+ parseState->inputsRead |= (1 << inst->SrcReg[2].Index);
+
+ parseState->numInst++;
+
+ if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
+ RETURN_ERROR1("Program too long");
+ }
+
+ RETURN_ERROR;
+}
+
+
+static GLboolean
+Parse_Program(struct parse_state *parseState,
+ struct prog_instruction instBuffer[])
+{
+ if (parseState->isVersion1_1) {
+ if (!Parse_OptionSequence(parseState, instBuffer)) {
+ return GL_FALSE;
+ }
+ }
+ return Parse_InstructionSequence(parseState, instBuffer);
+}
+
+
+/**
+ * Parse/compile the 'str' returning the compiled 'program'.
+ * ctx->Program.ErrorPos will be -1 if successful. Otherwise, ErrorPos
+ * indicates the position of the error in 'str'.
+ */
+void
+_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
+ const GLubyte *str, GLsizei len,
+ struct gl_vertex_program *program)
+{
+ struct parse_state parseState;
+ struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
+ struct prog_instruction *newInst;
+ GLenum target;
+ GLubyte *programString;
+
+ /* Make a null-terminated copy of the program string */
+ programString = (GLubyte *) MALLOC(len + 1);
+ if (!programString) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ return;
+ }
+ MEMCPY(programString, str, len);
+ programString[len] = 0;
+
+ /* Get ready to parse */
+ parseState.ctx = ctx;
+ parseState.start = programString;
+ parseState.isPositionInvariant = GL_FALSE;
+ parseState.isVersion1_1 = GL_FALSE;
+ parseState.numInst = 0;
+ parseState.inputsRead = 0;
+ parseState.outputsWritten = 0;
+ parseState.anyProgRegsWritten = GL_FALSE;
+
+ /* Reset error state */
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ /* check the program header */
+ if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
+ target = GL_VERTEX_PROGRAM_NV;
+ parseState.pos = programString + 7;
+ parseState.isStateProgram = GL_FALSE;
+ }
+ else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
+ target = GL_VERTEX_PROGRAM_NV;
+ parseState.pos = programString + 7;
+ parseState.isStateProgram = GL_FALSE;
+ parseState.isVersion1_1 = GL_TRUE;
+ }
+ else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
+ target = GL_VERTEX_STATE_PROGRAM_NV;
+ parseState.pos = programString + 8;
+ parseState.isStateProgram = GL_TRUE;
+ }
+ else {
+ /* invalid header */
+ ctx->Program.ErrorPos = 0;
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
+ return;
+ }
+
+ /* make sure target and header match */
+ if (target != dstTarget) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glLoadProgramNV(target mismatch)");
+ return;
+ }
+
+
+ if (Parse_Program(&parseState, instBuffer)) {
+ gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
+ int i;
+
+ /* successful parse! */
+
+ if (parseState.isStateProgram) {
+ if (!parseState.anyProgRegsWritten) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glLoadProgramNV(c[#] not written)");
+ return;
+ }
+ }
+ else {
+ if (!parseState.isPositionInvariant &&
+ !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) {
+ /* bit 1 = HPOS register */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glLoadProgramNV(HPOS not written)");
+ return;
+ }
+ }
+
+ /* copy the compiled instructions */
+ assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
+ newInst = _mesa_alloc_instructions(parseState.numInst);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
+ _mesa_free(programString);
+ return; /* out of memory */
+ }
+ _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
+
+ /* install the program */
+ program->Base.Target = target;
+ if (program->Base.String) {
+ _mesa_free(program->Base.String);
+ }
+ program->Base.String = programString;
+ program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
+ if (program->Base.Instructions) {
+ _mesa_free(program->Base.Instructions);
+ }
+ program->Base.Instructions = newInst;
+ program->Base.InputsRead = parseState.inputsRead;
+ if (parseState.isPositionInvariant)
+ program->Base.InputsRead |= VERT_BIT_POS;
+ program->Base.NumInstructions = parseState.numInst;
+ program->Base.OutputsWritten = parseState.outputsWritten;
+ program->IsPositionInvariant = parseState.isPositionInvariant;
+ program->IsNVProgram = GL_TRUE;
+
+#ifdef DEBUG_foo
+ _mesa_printf("--- glLoadProgramNV result ---\n");
+ _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
+ _mesa_printf("------------------------------\n");
+#endif
+
+ if (program->Base.Parameters)
+ _mesa_free_parameter_list(program->Base.Parameters);
+
+ program->Base.Parameters = _mesa_new_parameter_list ();
+ program->Base.NumParameters = 0;
+
+ state_tokens[0] = STATE_VERTEX_PROGRAM;
+ state_tokens[1] = STATE_ENV;
+ /* Add refs to all of the potential params, in order. If we want to not
+ * upload everything, _mesa_layout_parameters is the answer.
+ */
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) {
+ GLint index;
+ state_tokens[2] = i;
+ index = _mesa_add_state_reference(program->Base.Parameters,
+ state_tokens);
+ assert(index == i);
+ }
+ program->Base.NumParameters = program->Base.Parameters->NumParameters;
+
+ _mesa_setup_nv_temporary_count(ctx, &program->Base);
+ _mesa_emit_nv_temp_initialization(ctx, &program->Base);
+ }
+ else {
+ /* Error! */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
+ /* NOTE: _mesa_set_program_error would have been called already */
+ /* GL_NV_vertex_program isn't supposed to set the error string
+ * so we reset it here.
+ */
+ _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
+ }
+}
+
+
+const char *
+_mesa_nv_vertex_input_register_name(GLuint i)
+{
+ ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
+ return InputRegisters[i];
+}
+
+
+const char *
+_mesa_nv_vertex_output_register_name(GLuint i)
+{
+ ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
+ return OutputRegisters[i];
+}
+
diff --git a/mesalib/src/mesa/shader/nvvertparse.h b/mesalib/src/mesa/shader/nvvertparse.h
new file mode 100644
index 000000000..9919e2238
--- /dev/null
+++ b/mesalib/src/mesa/shader/nvvertparse.h
@@ -0,0 +1,45 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+
+#ifndef NVVERTPARSE_H
+#define NVVERTPARSE_H
+
+
+extern void
+_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target,
+ const GLubyte *str, GLsizei len,
+ struct gl_vertex_program *program);
+
+
+extern const char *
+_mesa_nv_vertex_input_register_name(GLuint i);
+
+extern const char *
+_mesa_nv_vertex_output_register_name(GLuint i);
+
+#endif
diff --git a/mesalib/src/mesa/shader/prog_cache.c b/mesalib/src/mesa/shader/prog_cache.c
new file mode 100644
index 000000000..9437e5961
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_cache.c
@@ -0,0 +1,206 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "shader/prog_cache.h"
+#include "shader/program.h"
+
+
+struct cache_item
+{
+ GLuint hash;
+ void *key;
+ struct gl_program *program;
+ struct cache_item *next;
+};
+
+struct gl_program_cache
+{
+ struct cache_item **items;
+ struct cache_item *last;
+ GLuint size, n_items;
+};
+
+
+
+/**
+ * Compute hash index from state key.
+ */
+static GLuint
+hash_key(const void *key, GLuint key_size)
+{
+ const GLuint *ikey = (const GLuint *) key;
+ GLuint hash = 0, i;
+
+ assert(key_size >= 4);
+
+ /* Make a slightly better attempt at a hash function:
+ */
+ for (i = 0; i < key_size / sizeof(*ikey); i++)
+ {
+ hash += ikey[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+
+ return hash;
+}
+
+
+/**
+ * Rebuild/expand the hash table to accomodate more entries
+ */
+static void
+rehash(struct gl_program_cache *cache)
+{
+ struct cache_item **items;
+ struct cache_item *c, *next;
+ GLuint size, i;
+
+ cache->last = NULL;
+
+ size = cache->size * 3;
+ items = (struct cache_item**) _mesa_malloc(size * sizeof(*items));
+ _mesa_memset(items, 0, size * sizeof(*items));
+
+ for (i = 0; i < cache->size; i++)
+ for (c = cache->items[i]; c; c = next) {
+ next = c->next;
+ c->next = items[c->hash % size];
+ items[c->hash % size] = c;
+ }
+
+ _mesa_free(cache->items);
+ cache->items = items;
+ cache->size = size;
+}
+
+
+static void
+clear_cache(GLcontext *ctx, struct gl_program_cache *cache)
+{
+ struct cache_item *c, *next;
+ GLuint i;
+
+ cache->last = NULL;
+
+ for (i = 0; i < cache->size; i++) {
+ for (c = cache->items[i]; c; c = next) {
+ next = c->next;
+ _mesa_free(c->key);
+ _mesa_reference_program(ctx, &c->program, NULL);
+ _mesa_free(c);
+ }
+ cache->items[i] = NULL;
+ }
+
+
+ cache->n_items = 0;
+}
+
+
+
+struct gl_program_cache *
+_mesa_new_program_cache(void)
+{
+ struct gl_program_cache *cache = CALLOC_STRUCT(gl_program_cache);
+ if (cache) {
+ cache->size = 17;
+ cache->items = (struct cache_item **)
+ _mesa_calloc(cache->size * sizeof(struct cache_item));
+ if (!cache->items) {
+ _mesa_free(cache);
+ return NULL;
+ }
+ }
+ return cache;
+}
+
+
+void
+_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache)
+{
+ clear_cache(ctx, cache);
+ _mesa_free(cache->items);
+ _mesa_free(cache);
+}
+
+
+struct gl_program *
+_mesa_search_program_cache(struct gl_program_cache *cache,
+ const void *key, GLuint keysize)
+{
+ if (cache->last &&
+ memcmp(cache->last->key, key, keysize) == 0) {
+ return cache->last->program;
+ }
+ else {
+ const GLuint hash = hash_key(key, keysize);
+ struct cache_item *c;
+
+ for (c = cache->items[hash % cache->size]; c; c = c->next) {
+ if (c->hash == hash && memcmp(c->key, key, keysize) == 0) {
+ cache->last = c;
+ return c->program;
+ }
+ }
+
+ return NULL;
+ }
+}
+
+
+void
+_mesa_program_cache_insert(GLcontext *ctx,
+ struct gl_program_cache *cache,
+ const void *key, GLuint keysize,
+ struct gl_program *program)
+{
+ const GLuint hash = hash_key(key, keysize);
+ struct cache_item *c = CALLOC_STRUCT(cache_item);
+
+ c->hash = hash;
+
+ c->key = _mesa_malloc(keysize);
+ memcpy(c->key, key, keysize);
+
+ c->program = program; /* no refcount change */
+
+ if (cache->n_items > cache->size * 1.5) {
+ if (cache->size < 1000)
+ rehash(cache);
+ else
+ clear_cache(ctx, cache);
+ }
+
+ cache->n_items++;
+ c->next = cache->items[hash % cache->size];
+ cache->items[hash % cache->size] = c;
+}
diff --git a/mesalib/src/mesa/shader/prog_cache.h b/mesalib/src/mesa/shader/prog_cache.h
new file mode 100644
index 000000000..4e1ccac03
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_cache.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef PROG_CACHE_H
+#define PROG_CACHE_H
+
+
+/** Opaque type */
+struct gl_program_cache;
+
+
+extern struct gl_program_cache *
+_mesa_new_program_cache(void);
+
+extern void
+_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc);
+
+
+extern struct gl_program *
+_mesa_search_program_cache(struct gl_program_cache *cache,
+ const void *key, GLuint keysize);
+
+extern void
+_mesa_program_cache_insert(GLcontext *ctx,
+ struct gl_program_cache *cache,
+ const void *key, GLuint keysize,
+ struct gl_program *program);
+
+
+#endif /* PROG_CACHE_H */
diff --git a/mesalib/src/mesa/shader/prog_execute.c b/mesalib/src/mesa/shader/prog_execute.c
new file mode 100644
index 000000000..69b81e724
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_execute.c
@@ -0,0 +1,1757 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file prog_execute.c
+ * Software interpreter for vertex/fragment programs.
+ * \author Brian Paul
+ */
+
+/*
+ * NOTE: we do everything in single-precision floating point; we don't
+ * currently observe the single/half/fixed-precision qualifiers.
+ *
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "program.h"
+#include "prog_execute.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+#include "prog_noise.h"
+
+
+/* debug predicate */
+#define DEBUG_PROG 0
+
+
+/**
+ * Set x to positive or negative infinity.
+ */
+#if defined(USE_IEEE) || defined(_WIN32)
+#define SET_POS_INFINITY(x) ( *((GLuint *) (void *)&x) = 0x7F800000 )
+#define SET_NEG_INFINITY(x) ( *((GLuint *) (void *)&x) = 0xFF800000 )
+#elif defined(VMS)
+#define SET_POS_INFINITY(x) x = __MAXFLOAT
+#define SET_NEG_INFINITY(x) x = -__MAXFLOAT
+#else
+#define SET_POS_INFINITY(x) x = (GLfloat) HUGE_VAL
+#define SET_NEG_INFINITY(x) x = (GLfloat) -HUGE_VAL
+#endif
+
+#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits
+
+
+static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
+
+
+
+/**
+ * Return a pointer to the 4-element float vector specified by the given
+ * source register.
+ */
+static INLINE const GLfloat *
+get_src_register_pointer(const struct prog_src_register *source,
+ const struct gl_program_machine *machine)
+{
+ const struct gl_program *prog = machine->CurProgram;
+ GLint reg = source->Index;
+
+ if (source->RelAddr) {
+ /* add address register value to src index/offset */
+ reg += machine->AddressReg[0][0];
+ if (reg < 0) {
+ return ZeroVec;
+ }
+ }
+
+ switch (source->File) {
+ case PROGRAM_TEMPORARY:
+ if (reg >= MAX_PROGRAM_TEMPS)
+ return ZeroVec;
+ return machine->Temporaries[reg];
+
+ case PROGRAM_INPUT:
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ if (reg >= VERT_ATTRIB_MAX)
+ return ZeroVec;
+ return machine->VertAttribs[reg];
+ }
+ else {
+ if (reg >= FRAG_ATTRIB_MAX)
+ return ZeroVec;
+ return machine->Attribs[reg][machine->CurElement];
+ }
+
+ case PROGRAM_OUTPUT:
+ if (reg >= MAX_PROGRAM_OUTPUTS)
+ return ZeroVec;
+ return machine->Outputs[reg];
+
+ case PROGRAM_LOCAL_PARAM:
+ if (reg >= MAX_PROGRAM_LOCAL_PARAMS)
+ return ZeroVec;
+ return machine->CurProgram->LocalParams[reg];
+
+ case PROGRAM_ENV_PARAM:
+ if (reg >= MAX_PROGRAM_ENV_PARAMS)
+ return ZeroVec;
+ return machine->EnvParams[reg];
+
+ case PROGRAM_STATE_VAR:
+ /* Fallthrough */
+ case PROGRAM_CONSTANT:
+ /* Fallthrough */
+ case PROGRAM_UNIFORM:
+ /* Fallthrough */
+ case PROGRAM_NAMED_PARAM:
+ if (reg >= (GLint) prog->Parameters->NumParameters)
+ return ZeroVec;
+ return prog->Parameters->ParameterValues[reg];
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid src register file %d in get_src_register_pointer()",
+ source->File);
+ return NULL;
+ }
+}
+
+
+/**
+ * Return a pointer to the 4-element float vector specified by the given
+ * destination register.
+ */
+static INLINE GLfloat *
+get_dst_register_pointer(const struct prog_dst_register *dest,
+ struct gl_program_machine *machine)
+{
+ static GLfloat dummyReg[4];
+ GLint reg = dest->Index;
+
+ if (dest->RelAddr) {
+ /* add address register value to src index/offset */
+ reg += machine->AddressReg[0][0];
+ if (reg < 0) {
+ return dummyReg;
+ }
+ }
+
+ switch (dest->File) {
+ case PROGRAM_TEMPORARY:
+ if (reg >= MAX_PROGRAM_TEMPS)
+ return dummyReg;
+ return machine->Temporaries[reg];
+
+ case PROGRAM_OUTPUT:
+ if (reg >= MAX_PROGRAM_OUTPUTS)
+ return dummyReg;
+ return machine->Outputs[reg];
+
+ case PROGRAM_WRITE_ONLY:
+ return dummyReg;
+
+ default:
+ _mesa_problem(NULL,
+ "Invalid dest register file %d in get_dst_register_pointer()",
+ dest->File);
+ return NULL;
+ }
+}
+
+
+
+/**
+ * Fetch a 4-element float vector from the given source register.
+ * Apply swizzling and negating as needed.
+ */
+static void
+fetch_vector4(const struct prog_src_register *source,
+ const struct gl_program_machine *machine, GLfloat result[4])
+{
+ const GLfloat *src = get_src_register_pointer(source, machine);
+ ASSERT(src);
+
+ if (source->Swizzle == SWIZZLE_NOOP) {
+ /* no swizzling */
+ COPY_4V(result, src);
+ }
+ else {
+ ASSERT(GET_SWZ(source->Swizzle, 0) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 1) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 2) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 3) <= 3);
+ result[0] = src[GET_SWZ(source->Swizzle, 0)];
+ result[1] = src[GET_SWZ(source->Swizzle, 1)];
+ result[2] = src[GET_SWZ(source->Swizzle, 2)];
+ result[3] = src[GET_SWZ(source->Swizzle, 3)];
+ }
+
+ if (source->Abs) {
+ result[0] = FABSF(result[0]);
+ result[1] = FABSF(result[1]);
+ result[2] = FABSF(result[2]);
+ result[3] = FABSF(result[3]);
+ }
+ if (source->Negate) {
+ ASSERT(source->Negate == NEGATE_XYZW);
+ result[0] = -result[0];
+ result[1] = -result[1];
+ result[2] = -result[2];
+ result[3] = -result[3];
+ }
+
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+ assert(!IS_INF_OR_NAN(result[0]));
+#endif
+}
+
+
+/**
+ * Fetch a 4-element uint vector from the given source register.
+ * Apply swizzling but not negation/abs.
+ */
+static void
+fetch_vector4ui(const struct prog_src_register *source,
+ const struct gl_program_machine *machine, GLuint result[4])
+{
+ const GLuint *src = (GLuint *) get_src_register_pointer(source, machine);
+ ASSERT(src);
+
+ if (source->Swizzle == SWIZZLE_NOOP) {
+ /* no swizzling */
+ COPY_4V(result, src);
+ }
+ else {
+ ASSERT(GET_SWZ(source->Swizzle, 0) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 1) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 2) <= 3);
+ ASSERT(GET_SWZ(source->Swizzle, 3) <= 3);
+ result[0] = src[GET_SWZ(source->Swizzle, 0)];
+ result[1] = src[GET_SWZ(source->Swizzle, 1)];
+ result[2] = src[GET_SWZ(source->Swizzle, 2)];
+ result[3] = src[GET_SWZ(source->Swizzle, 3)];
+ }
+
+ /* Note: no Negate or Abs here */
+}
+
+
+
+/**
+ * Fetch the derivative with respect to X or Y for the given register.
+ * XXX this currently only works for fragment program input attribs.
+ */
+static void
+fetch_vector4_deriv(GLcontext * ctx,
+ const struct prog_src_register *source,
+ const struct gl_program_machine *machine,
+ char xOrY, GLfloat result[4])
+{
+ if (source->File == PROGRAM_INPUT &&
+ source->Index < (GLint) machine->NumDeriv) {
+ const GLint col = machine->CurElement;
+ const GLfloat w = machine->Attribs[FRAG_ATTRIB_WPOS][col][3];
+ const GLfloat invQ = 1.0f / w;
+ GLfloat deriv[4];
+
+ if (xOrY == 'X') {
+ deriv[0] = machine->DerivX[source->Index][0] * invQ;
+ deriv[1] = machine->DerivX[source->Index][1] * invQ;
+ deriv[2] = machine->DerivX[source->Index][2] * invQ;
+ deriv[3] = machine->DerivX[source->Index][3] * invQ;
+ }
+ else {
+ deriv[0] = machine->DerivY[source->Index][0] * invQ;
+ deriv[1] = machine->DerivY[source->Index][1] * invQ;
+ deriv[2] = machine->DerivY[source->Index][2] * invQ;
+ deriv[3] = machine->DerivY[source->Index][3] * invQ;
+ }
+
+ result[0] = deriv[GET_SWZ(source->Swizzle, 0)];
+ result[1] = deriv[GET_SWZ(source->Swizzle, 1)];
+ result[2] = deriv[GET_SWZ(source->Swizzle, 2)];
+ result[3] = deriv[GET_SWZ(source->Swizzle, 3)];
+
+ if (source->Abs) {
+ result[0] = FABSF(result[0]);
+ result[1] = FABSF(result[1]);
+ result[2] = FABSF(result[2]);
+ result[3] = FABSF(result[3]);
+ }
+ if (source->Negate) {
+ ASSERT(source->Negate == NEGATE_XYZW);
+ result[0] = -result[0];
+ result[1] = -result[1];
+ result[2] = -result[2];
+ result[3] = -result[3];
+ }
+ }
+ else {
+ ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0);
+ }
+}
+
+
+/**
+ * As above, but only return result[0] element.
+ */
+static void
+fetch_vector1(const struct prog_src_register *source,
+ const struct gl_program_machine *machine, GLfloat result[4])
+{
+ const GLfloat *src = get_src_register_pointer(source, machine);
+ ASSERT(src);
+
+ result[0] = src[GET_SWZ(source->Swizzle, 0)];
+
+ if (source->Abs) {
+ result[0] = FABSF(result[0]);
+ }
+ if (source->Negate) {
+ result[0] = -result[0];
+ }
+}
+
+
+/**
+ * Fetch texel from texture. Use partial derivatives when possible.
+ */
+static INLINE void
+fetch_texel(GLcontext *ctx,
+ const struct gl_program_machine *machine,
+ const struct prog_instruction *inst,
+ const GLfloat texcoord[4], GLfloat lodBias,
+ GLfloat color[4])
+{
+ const GLuint unit = machine->Samplers[inst->TexSrcUnit];
+
+ /* Note: we only have the right derivatives for fragment input attribs.
+ */
+ if (machine->NumDeriv > 0 &&
+ inst->SrcReg[0].File == PROGRAM_INPUT &&
+ inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) {
+ /* simple texture fetch for which we should have derivatives */
+ GLuint attr = inst->SrcReg[0].Index;
+ machine->FetchTexelDeriv(ctx, texcoord,
+ machine->DerivX[attr],
+ machine->DerivY[attr],
+ lodBias, unit, color);
+ }
+ else {
+ machine->FetchTexelLod(ctx, texcoord, lodBias, unit, color);
+ }
+}
+
+
+/**
+ * Test value against zero and return GT, LT, EQ or UN if NaN.
+ */
+static INLINE GLuint
+generate_cc(float value)
+{
+ if (value != value)
+ return COND_UN; /* NaN */
+ if (value > 0.0F)
+ return COND_GT;
+ if (value < 0.0F)
+ return COND_LT;
+ return COND_EQ;
+}
+
+
+/**
+ * Test if the ccMaskRule is satisfied by the given condition code.
+ * Used to mask destination writes according to the current condition code.
+ */
+static INLINE GLboolean
+test_cc(GLuint condCode, GLuint ccMaskRule)
+{
+ switch (ccMaskRule) {
+ case COND_EQ: return (condCode == COND_EQ);
+ case COND_NE: return (condCode != COND_EQ);
+ case COND_LT: return (condCode == COND_LT);
+ case COND_GE: return (condCode == COND_GT || condCode == COND_EQ);
+ case COND_LE: return (condCode == COND_LT || condCode == COND_EQ);
+ case COND_GT: return (condCode == COND_GT);
+ case COND_TR: return GL_TRUE;
+ case COND_FL: return GL_FALSE;
+ default: return GL_TRUE;
+ }
+}
+
+
+/**
+ * Evaluate the 4 condition codes against a predicate and return GL_TRUE
+ * or GL_FALSE to indicate result.
+ */
+static INLINE GLboolean
+eval_condition(const struct gl_program_machine *machine,
+ const struct prog_instruction *inst)
+{
+ const GLuint swizzle = inst->DstReg.CondSwizzle;
+ const GLuint condMask = inst->DstReg.CondMask;
+ if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
+ test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/**
+ * Store 4 floats into a register. Observe the instructions saturate and
+ * set-condition-code flags.
+ */
+static void
+store_vector4(const struct prog_instruction *inst,
+ struct gl_program_machine *machine, const GLfloat value[4])
+{
+ const struct prog_dst_register *dstReg = &(inst->DstReg);
+ const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE;
+ GLuint writeMask = dstReg->WriteMask;
+ GLfloat clampedValue[4];
+ GLfloat *dst = get_dst_register_pointer(dstReg, machine);
+
+#if 0
+ if (value[0] > 1.0e10 ||
+ IS_INF_OR_NAN(value[0]) ||
+ IS_INF_OR_NAN(value[1]) ||
+ IS_INF_OR_NAN(value[2]) || IS_INF_OR_NAN(value[3]))
+ printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]);
+#endif
+
+ if (clamp) {
+ clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F);
+ clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F);
+ clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F);
+ clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F);
+ value = clampedValue;
+ }
+
+ if (dstReg->CondMask != COND_TR) {
+ /* condition codes may turn off some writes */
+ if (writeMask & WRITEMASK_X) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_X;
+ }
+ if (writeMask & WRITEMASK_Y) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_Y;
+ }
+ if (writeMask & WRITEMASK_Z) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_Z;
+ }
+ if (writeMask & WRITEMASK_W) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_W;
+ }
+ }
+
+#ifdef NAN_CHECK
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+ assert(!IS_INF_OR_NAN(value[0]));
+#endif
+
+ if (writeMask & WRITEMASK_X)
+ dst[0] = value[0];
+ if (writeMask & WRITEMASK_Y)
+ dst[1] = value[1];
+ if (writeMask & WRITEMASK_Z)
+ dst[2] = value[2];
+ if (writeMask & WRITEMASK_W)
+ dst[3] = value[3];
+
+ if (inst->CondUpdate) {
+ if (writeMask & WRITEMASK_X)
+ machine->CondCodes[0] = generate_cc(value[0]);
+ if (writeMask & WRITEMASK_Y)
+ machine->CondCodes[1] = generate_cc(value[1]);
+ if (writeMask & WRITEMASK_Z)
+ machine->CondCodes[2] = generate_cc(value[2]);
+ if (writeMask & WRITEMASK_W)
+ machine->CondCodes[3] = generate_cc(value[3]);
+#if DEBUG_PROG
+ printf("CondCodes=(%s,%s,%s,%s) for:\n",
+ _mesa_condcode_string(machine->CondCodes[0]),
+ _mesa_condcode_string(machine->CondCodes[1]),
+ _mesa_condcode_string(machine->CondCodes[2]),
+ _mesa_condcode_string(machine->CondCodes[3]));
+#endif
+ }
+}
+
+
+/**
+ * Store 4 uints into a register. Observe the set-condition-code flags.
+ */
+static void
+store_vector4ui(const struct prog_instruction *inst,
+ struct gl_program_machine *machine, const GLuint value[4])
+{
+ const struct prog_dst_register *dstReg = &(inst->DstReg);
+ GLuint writeMask = dstReg->WriteMask;
+ GLuint *dst = (GLuint *) get_dst_register_pointer(dstReg, machine);
+
+ if (dstReg->CondMask != COND_TR) {
+ /* condition codes may turn off some writes */
+ if (writeMask & WRITEMASK_X) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 0)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_X;
+ }
+ if (writeMask & WRITEMASK_Y) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 1)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_Y;
+ }
+ if (writeMask & WRITEMASK_Z) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 2)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_Z;
+ }
+ if (writeMask & WRITEMASK_W) {
+ if (!test_cc(machine->CondCodes[GET_SWZ(dstReg->CondSwizzle, 3)],
+ dstReg->CondMask))
+ writeMask &= ~WRITEMASK_W;
+ }
+ }
+
+ if (writeMask & WRITEMASK_X)
+ dst[0] = value[0];
+ if (writeMask & WRITEMASK_Y)
+ dst[1] = value[1];
+ if (writeMask & WRITEMASK_Z)
+ dst[2] = value[2];
+ if (writeMask & WRITEMASK_W)
+ dst[3] = value[3];
+
+ if (inst->CondUpdate) {
+ if (writeMask & WRITEMASK_X)
+ machine->CondCodes[0] = generate_cc(value[0]);
+ if (writeMask & WRITEMASK_Y)
+ machine->CondCodes[1] = generate_cc(value[1]);
+ if (writeMask & WRITEMASK_Z)
+ machine->CondCodes[2] = generate_cc(value[2]);
+ if (writeMask & WRITEMASK_W)
+ machine->CondCodes[3] = generate_cc(value[3]);
+#if DEBUG_PROG
+ printf("CondCodes=(%s,%s,%s,%s) for:\n",
+ _mesa_condcode_string(machine->CondCodes[0]),
+ _mesa_condcode_string(machine->CondCodes[1]),
+ _mesa_condcode_string(machine->CondCodes[2]),
+ _mesa_condcode_string(machine->CondCodes[3]));
+#endif
+ }
+}
+
+
+
+/**
+ * Execute the given vertex/fragment program.
+ *
+ * \param ctx rendering context
+ * \param program the program to execute
+ * \param machine machine state (must be initialized)
+ * \return GL_TRUE if program completed or GL_FALSE if program executed KIL.
+ */
+GLboolean
+_mesa_execute_program(GLcontext * ctx,
+ const struct gl_program *program,
+ struct gl_program_machine *machine)
+{
+ const GLuint numInst = program->NumInstructions;
+ const GLuint maxExec = 10000;
+ GLuint pc, numExec = 0;
+
+ machine->CurProgram = program;
+
+ if (DEBUG_PROG) {
+ printf("execute program %u --------------------\n", program->Id);
+ }
+
+ if (program->Target == GL_VERTEX_PROGRAM_ARB) {
+ machine->EnvParams = ctx->VertexProgram.Parameters;
+ }
+ else {
+ machine->EnvParams = ctx->FragmentProgram.Parameters;
+ }
+
+ for (pc = 0; pc < numInst; pc++) {
+ const struct prog_instruction *inst = program->Instructions + pc;
+
+ if (DEBUG_PROG) {
+ _mesa_print_instruction(inst);
+ }
+
+ switch (inst->Opcode) {
+ case OPCODE_ABS:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] = FABSF(a[0]);
+ result[1] = FABSF(a[1]);
+ result[2] = FABSF(a[2]);
+ result[3] = FABSF(a[3]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_ADD:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] + b[0];
+ result[1] = a[1] + b[1];
+ result[2] = a[2] + b[2];
+ result[3] = a[3] + b[3];
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_AND: /* bitwise AND */
+ {
+ GLuint a[4], b[4], result[4];
+ fetch_vector4ui(&inst->SrcReg[0], machine, a);
+ fetch_vector4ui(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] & b[0];
+ result[1] = a[1] & b[1];
+ result[2] = a[2] & b[2];
+ result[3] = a[3] & b[3];
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_ARL:
+ {
+ GLfloat t[4];
+ fetch_vector4(&inst->SrcReg[0], machine, t);
+ machine->AddressReg[0][0] = IFLOOR(t[0]);
+ }
+ break;
+ case OPCODE_BGNLOOP:
+ /* no-op */
+ break;
+ case OPCODE_ENDLOOP:
+ /* subtract 1 here since pc is incremented by for(pc) loop */
+ pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
+ break;
+ case OPCODE_BGNSUB: /* begin subroutine */
+ break;
+ case OPCODE_ENDSUB: /* end subroutine */
+ break;
+ case OPCODE_BRA: /* branch (conditional) */
+ /* fall-through */
+ case OPCODE_BRK: /* break out of loop (conditional) */
+ /* fall-through */
+ case OPCODE_CONT: /* continue loop (conditional) */
+ if (eval_condition(machine, inst)) {
+ /* take branch */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ break;
+ case OPCODE_CAL: /* Call subroutine (conditional) */
+ if (eval_condition(machine, inst)) {
+ /* call the subroutine */
+ if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
+ return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
+ }
+ machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ break;
+ case OPCODE_CMP:
+ {
+ GLfloat a[4], b[4], c[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ fetch_vector4(&inst->SrcReg[2], machine, c);
+ result[0] = a[0] < 0.0F ? b[0] : c[0];
+ result[1] = a[1] < 0.0F ? b[1] : c[1];
+ result[2] = a[2] < 0.0F ? b[2] : c[2];
+ result[3] = a[3] < 0.0F ? b[3] : c[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_COS:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] = result[1] = result[2] = result[3]
+ = (GLfloat) _mesa_cos(a[0]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_DDX: /* Partial derivative with respect to X */
+ {
+ GLfloat result[4];
+ fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
+ 'X', result);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_DDY: /* Partial derivative with respect to Y */
+ {
+ GLfloat result[4];
+ fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine,
+ 'Y', result);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_DP2:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = result[1] = result[2] = result[3] = DOT2(a, b);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("DP2 %g = (%g %g) . (%g %g)\n",
+ result[0], a[0], a[1], b[0], b[1]);
+ }
+ }
+ break;
+ case OPCODE_DP2A:
+ {
+ GLfloat a[4], b[4], c, result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ fetch_vector1(&inst->SrcReg[1], machine, &c);
+ result[0] = result[1] = result[2] = result[3] = DOT2(a, b) + c;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("DP2A %g = (%g %g) . (%g %g) + %g\n",
+ result[0], a[0], a[1], b[0], b[1], c);
+ }
+ }
+ break;
+ case OPCODE_DP3:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = result[1] = result[2] = result[3] = DOT3(a, b);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
+ result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ }
+ break;
+ case OPCODE_DP4:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = result[1] = result[2] = result[3] = DOT4(a, b);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
+ result[0], a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_DPH:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = result[1] = result[2] = result[3] = DOT3(a, b) + b[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_DST: /* Distance vector */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = 1.0F;
+ result[1] = a[1] * b[1];
+ result[2] = a[2];
+ result[3] = b[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_EXP:
+ {
+ GLfloat t[4], q[4], floor_t0;
+ fetch_vector1(&inst->SrcReg[0], machine, t);
+ floor_t0 = FLOORF(t[0]);
+ if (floor_t0 > FLT_MAX_EXP) {
+ SET_POS_INFINITY(q[0]);
+ SET_POS_INFINITY(q[2]);
+ }
+ else if (floor_t0 < FLT_MIN_EXP) {
+ q[0] = 0.0F;
+ q[2] = 0.0F;
+ }
+ else {
+ q[0] = LDEXPF(1.0, (int) floor_t0);
+ /* Note: GL_NV_vertex_program expects
+ * result.z = result.x * APPX(result.y)
+ * We do what the ARB extension says.
+ */
+ q[2] = (GLfloat) _mesa_pow(2.0, t[0]);
+ }
+ q[1] = t[0] - floor_t0;
+ q[3] = 1.0F;
+ store_vector4( inst, machine, q );
+ }
+ break;
+ case OPCODE_EX2: /* Exponential base 2 */
+ {
+ GLfloat a[4], result[4], val;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ val = (GLfloat) _mesa_pow(2.0, a[0]);
+ /*
+ if (IS_INF_OR_NAN(val))
+ val = 1.0e10;
+ */
+ result[0] = result[1] = result[2] = result[3] = val;
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_FLR:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] = FLOORF(a[0]);
+ result[1] = FLOORF(a[1]);
+ result[2] = FLOORF(a[2]);
+ result[3] = FLOORF(a[3]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_FRC:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] = a[0] - FLOORF(a[0]);
+ result[1] = a[1] - FLOORF(a[1]);
+ result[2] = a[2] - FLOORF(a[2]);
+ result[3] = a[3] - FLOORF(a[3]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_IF:
+ {
+ GLboolean cond;
+ /* eval condition */
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ cond = (a[0] != 0.0);
+ }
+ else {
+ cond = eval_condition(machine, inst);
+ }
+ if (DEBUG_PROG) {
+ printf("IF: %d\n", cond);
+ }
+ /* do if/else */
+ if (cond) {
+ /* do if-clause (just continue execution) */
+ }
+ else {
+ /* go to the instruction after ELSE or ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
+ }
+ }
+ break;
+ case OPCODE_ELSE:
+ /* goto ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
+ break;
+ case OPCODE_ENDIF:
+ /* nothing */
+ break;
+ case OPCODE_KIL_NV: /* NV_f_p only (conditional) */
+ if (eval_condition(machine, inst)) {
+ return GL_FALSE;
+ }
+ break;
+ case OPCODE_KIL: /* ARB_f_p only */
+ {
+ GLfloat a[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ if (DEBUG_PROG) {
+ printf("KIL if (%g %g %g %g) <= 0.0\n",
+ a[0], a[1], a[2], a[3]);
+ }
+
+ if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) {
+ return GL_FALSE;
+ }
+ }
+ break;
+ case OPCODE_LG2: /* log base 2 */
+ {
+ GLfloat a[4], result[4], val;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ /* The fast LOG2 macro doesn't meet the precision requirements.
+ */
+ if (a[0] == 0.0F) {
+ val = 0.0F;
+ }
+ else {
+ val = log(a[0]) * 1.442695F;
+ }
+ result[0] = result[1] = result[2] = result[3] = val;
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_LIT:
+ {
+ const GLfloat epsilon = 1.0F / 256.0F; /* from NV VP spec */
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ a[0] = MAX2(a[0], 0.0F);
+ a[1] = MAX2(a[1], 0.0F);
+ /* XXX ARB version clamps a[3], NV version doesn't */
+ a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon));
+ result[0] = 1.0F;
+ result[1] = a[0];
+ /* XXX we could probably just use pow() here */
+ if (a[0] > 0.0F) {
+ if (a[1] == 0.0 && a[3] == 0.0)
+ result[2] = 1.0;
+ else
+ result[2] = (GLfloat) _mesa_pow(a[1], a[3]);
+ }
+ else {
+ result[2] = 0.0;
+ }
+ result[3] = 1.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("LIT (%g %g %g %g) : (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3]);
+ }
+ }
+ break;
+ case OPCODE_LOG:
+ {
+ GLfloat t[4], q[4], abs_t0;
+ fetch_vector1(&inst->SrcReg[0], machine, t);
+ abs_t0 = FABSF(t[0]);
+ if (abs_t0 != 0.0F) {
+ /* Since we really can't handle infinite values on VMS
+ * like other OSes we'll use __MAXFLOAT to represent
+ * infinity. This may need some tweaking.
+ */
+#ifdef VMS
+ if (abs_t0 == __MAXFLOAT)
+#else
+ if (IS_INF_OR_NAN(abs_t0))
+#endif
+ {
+ SET_POS_INFINITY(q[0]);
+ q[1] = 1.0F;
+ SET_POS_INFINITY(q[2]);
+ }
+ else {
+ int exponent;
+ GLfloat mantissa = FREXPF(t[0], &exponent);
+ q[0] = (GLfloat) (exponent - 1);
+ q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */
+
+ /* The fast LOG2 macro doesn't meet the precision
+ * requirements.
+ */
+ q[2] = (log(t[0]) * 1.442695F);
+ }
+ }
+ else {
+ SET_NEG_INFINITY(q[0]);
+ q[1] = 1.0F;
+ SET_NEG_INFINITY(q[2]);
+ }
+ q[3] = 1.0;
+ store_vector4(inst, machine, q);
+ }
+ break;
+ case OPCODE_LRP:
+ {
+ GLfloat a[4], b[4], c[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ fetch_vector4(&inst->SrcReg[2], machine, c);
+ result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0];
+ result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1];
+ result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2];
+ result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3];
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("LRP (%g %g %g %g) = (%g %g %g %g), "
+ "(%g %g %g %g), (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
+ }
+ }
+ break;
+ case OPCODE_MAD:
+ {
+ GLfloat a[4], b[4], c[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ fetch_vector4(&inst->SrcReg[2], machine, c);
+ result[0] = a[0] * b[0] + c[0];
+ result[1] = a[1] * b[1] + c[1];
+ result[2] = a[2] * b[2] + c[2];
+ result[3] = a[3] * b[3] + c[3];
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("MAD (%g %g %g %g) = (%g %g %g %g) * "
+ "(%g %g %g %g) + (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]);
+ }
+ }
+ break;
+ case OPCODE_MAX:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = MAX2(a[0], b[0]);
+ result[1] = MAX2(a[1], b[1]);
+ result[2] = MAX2(a[2], b[2]);
+ result[3] = MAX2(a[3], b[3]);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_MIN:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = MIN2(a[0], b[0]);
+ result[1] = MIN2(a[1], b[1]);
+ result[2] = MIN2(a[2], b[2]);
+ result[3] = MIN2(a[3], b[3]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_MOV:
+ {
+ GLfloat result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, result);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("MOV (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3]);
+ }
+ }
+ break;
+ case OPCODE_MUL:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] * b[0];
+ result[1] = a[1] * b[1];
+ result[2] = a[2] * b[2];
+ result[3] = a[3] * b[3];
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_NOISE1:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = _mesa_noise1(a[0]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_NOISE2:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] =
+ result[1] =
+ result[2] = result[3] = _mesa_noise2(a[0], a[1]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_NOISE3:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = _mesa_noise3(a[0], a[1], a[2]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_NOISE4:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = _mesa_noise4(a[0], a[1], a[2], a[3]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_NOP:
+ break;
+ case OPCODE_NOT: /* bitwise NOT */
+ {
+ GLuint a[4], result[4];
+ fetch_vector4ui(&inst->SrcReg[0], machine, a);
+ result[0] = ~a[0];
+ result[1] = ~a[1];
+ result[2] = ~a[2];
+ result[3] = ~a[3];
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_NRM3: /* 3-component normalization */
+ {
+ GLfloat a[4], result[4];
+ GLfloat tmp;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
+ if (tmp != 0.0F)
+ tmp = INV_SQRTF(tmp);
+ result[0] = tmp * a[0];
+ result[1] = tmp * a[1];
+ result[2] = tmp * a[2];
+ result[3] = 0.0; /* undefined, but prevent valgrind warnings */
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_NRM4: /* 4-component normalization */
+ {
+ GLfloat a[4], result[4];
+ GLfloat tmp;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ tmp = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3];
+ if (tmp != 0.0F)
+ tmp = INV_SQRTF(tmp);
+ result[0] = tmp * a[0];
+ result[1] = tmp * a[1];
+ result[2] = tmp * a[2];
+ result[3] = tmp * a[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_OR: /* bitwise OR */
+ {
+ GLuint a[4], b[4], result[4];
+ fetch_vector4ui(&inst->SrcReg[0], machine, a);
+ fetch_vector4ui(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] | b[0];
+ result[1] = a[1] | b[1];
+ result[2] = a[2] | b[2];
+ result[3] = a[3] | b[3];
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */
+ {
+ GLfloat a[4];
+ GLuint result[4];
+ GLhalfNV hx, hy;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ hx = _mesa_float_to_half(a[0]);
+ hy = _mesa_float_to_half(a[1]);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = hx | (hy << 16);
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_PK2US: /* pack two GLushorts into one 32-bit float */
+ {
+ GLfloat a[4];
+ GLuint result[4], usx, usy;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ a[0] = CLAMP(a[0], 0.0F, 1.0F);
+ a[1] = CLAMP(a[1], 0.0F, 1.0F);
+ usx = IROUND(a[0] * 65535.0F);
+ usy = IROUND(a[1] * 65535.0F);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = usx | (usy << 16);
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_PK4B: /* pack four GLbytes into one 32-bit float */
+ {
+ GLfloat a[4];
+ GLuint result[4], ubx, uby, ubz, ubw;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ a[0] = CLAMP(a[0], -128.0F / 127.0F, 1.0F);
+ a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F);
+ a[2] = CLAMP(a[2], -128.0F / 127.0F, 1.0F);
+ a[3] = CLAMP(a[3], -128.0F / 127.0F, 1.0F);
+ ubx = IROUND(127.0F * a[0] + 128.0F);
+ uby = IROUND(127.0F * a[1] + 128.0F);
+ ubz = IROUND(127.0F * a[2] + 128.0F);
+ ubw = IROUND(127.0F * a[3] + 128.0F);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_PK4UB: /* pack four GLubytes into one 32-bit float */
+ {
+ GLfloat a[4];
+ GLuint result[4], ubx, uby, ubz, ubw;
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ a[0] = CLAMP(a[0], 0.0F, 1.0F);
+ a[1] = CLAMP(a[1], 0.0F, 1.0F);
+ a[2] = CLAMP(a[2], 0.0F, 1.0F);
+ a[3] = CLAMP(a[3], 0.0F, 1.0F);
+ ubx = IROUND(255.0F * a[0]);
+ uby = IROUND(255.0F * a[1]);
+ ubz = IROUND(255.0F * a[2]);
+ ubw = IROUND(255.0F * a[3]);
+ result[0] =
+ result[1] =
+ result[2] =
+ result[3] = ubx | (uby << 8) | (ubz << 16) | (ubw << 24);
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_POW:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ fetch_vector1(&inst->SrcReg[1], machine, b);
+ result[0] = result[1] = result[2] = result[3]
+ = (GLfloat) _mesa_pow(a[0], b[0]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_RCP:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ if (DEBUG_PROG) {
+ if (a[0] == 0)
+ printf("RCP(0)\n");
+ else if (IS_INF_OR_NAN(a[0]))
+ printf("RCP(inf)\n");
+ }
+ result[0] = result[1] = result[2] = result[3] = 1.0F / a[0];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_RET: /* return from subroutine (conditional) */
+ if (eval_condition(machine, inst)) {
+ if (machine->StackDepth == 0) {
+ return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
+ }
+ /* subtract one because of pc++ in the for loop */
+ pc = machine->CallStack[--machine->StackDepth] - 1;
+ }
+ break;
+ case OPCODE_RFL: /* reflection vector */
+ {
+ GLfloat axis[4], dir[4], result[4], tmpX, tmpW;
+ fetch_vector4(&inst->SrcReg[0], machine, axis);
+ fetch_vector4(&inst->SrcReg[1], machine, dir);
+ tmpW = DOT3(axis, axis);
+ tmpX = (2.0F * DOT3(axis, dir)) / tmpW;
+ result[0] = tmpX * axis[0] - dir[0];
+ result[1] = tmpX * axis[1] - dir[1];
+ result[2] = tmpX * axis[2] - dir[2];
+ /* result[3] is never written! XXX enforce in parser! */
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_RSQ: /* 1 / sqrt() */
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ a[0] = FABSF(a[0]);
+ result[0] = result[1] = result[2] = result[3] = INV_SQRTF(a[0]);
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
+ }
+ }
+ break;
+ case OPCODE_SCS: /* sine and cos */
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] = (GLfloat) _mesa_cos(a[0]);
+ result[1] = (GLfloat) _mesa_sin(a[0]);
+ result[2] = 0.0; /* undefined! */
+ result[3] = 0.0; /* undefined! */
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_SEQ: /* set on equal */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] == b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] == b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] == b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] == b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SEQ (%g %g %g %g) = (%g %g %g %g) == (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SFL: /* set false, operands ignored */
+ {
+ static const GLfloat result[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_SGE: /* set on greater or equal */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SGE (%g %g %g %g) = (%g %g %g %g) >= (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SGT: /* set on greater */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] > b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] > b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] > b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] > b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SGT (%g %g %g %g) = (%g %g %g %g) > (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SIN:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] = result[1] = result[2] = result[3]
+ = (GLfloat) _mesa_sin(a[0]);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_SLE: /* set on less or equal */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] <= b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] <= b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] <= b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] <= b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SLE (%g %g %g %g) = (%g %g %g %g) <= (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SLT: /* set on less */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] < b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] < b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] < b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] < b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SLT (%g %g %g %g) = (%g %g %g %g) < (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SNE: /* set on not equal */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = (a[0] != b[0]) ? 1.0F : 0.0F;
+ result[1] = (a[1] != b[1]) ? 1.0F : 0.0F;
+ result[2] = (a[2] != b[2]) ? 1.0F : 0.0F;
+ result[3] = (a[3] != b[3]) ? 1.0F : 0.0F;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SNE (%g %g %g %g) = (%g %g %g %g) != (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3],
+ b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SSG: /* set sign (-1, 0 or +1) */
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] = (GLfloat) ((a[0] > 0.0F) - (a[0] < 0.0F));
+ result[1] = (GLfloat) ((a[1] > 0.0F) - (a[1] < 0.0F));
+ result[2] = (GLfloat) ((a[2] > 0.0F) - (a[2] < 0.0F));
+ result[3] = (GLfloat) ((a[3] > 0.0F) - (a[3] < 0.0F));
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_STR: /* set true, operands ignored */
+ {
+ static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F };
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_SUB:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] - b[0];
+ result[1] = a[1] - b[1];
+ result[2] = a[2] - b[2];
+ result[3] = a[3] - b[3];
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+ }
+ }
+ break;
+ case OPCODE_SWZ: /* extended swizzle */
+ {
+ const struct prog_src_register *source = &inst->SrcReg[0];
+ const GLfloat *src = get_src_register_pointer(source, machine);
+ GLfloat result[4];
+ GLuint i;
+ for (i = 0; i < 4; i++) {
+ const GLuint swz = GET_SWZ(source->Swizzle, i);
+ if (swz == SWIZZLE_ZERO)
+ result[i] = 0.0;
+ else if (swz == SWIZZLE_ONE)
+ result[i] = 1.0;
+ else {
+ ASSERT(swz >= 0);
+ ASSERT(swz <= 3);
+ result[i] = src[swz];
+ }
+ if (source->Negate & (1 << i))
+ result[i] = -result[i];
+ }
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_TEX: /* Both ARB and NV frag prog */
+ /* Simple texel lookup */
+ {
+ GLfloat texcoord[4], color[4];
+ fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+
+ fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
+
+ if (DEBUG_PROG) {
+ printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g]\n",
+ color[0], color[1], color[2], color[3],
+ inst->TexSrcUnit,
+ texcoord[0], texcoord[1], texcoord[2], texcoord[3]);
+ }
+ store_vector4(inst, machine, color);
+ }
+ break;
+ case OPCODE_TXB: /* GL_ARB_fragment_program only */
+ /* Texel lookup with LOD bias */
+ {
+ GLfloat texcoord[4], color[4], lodBias;
+
+ fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+
+ /* texcoord[3] is the bias to add to lambda */
+ lodBias = texcoord[3];
+
+ fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
+
+ store_vector4(inst, machine, color);
+ }
+ break;
+ case OPCODE_TXD: /* GL_NV_fragment_program only */
+ /* Texture lookup w/ partial derivatives for LOD */
+ {
+ GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
+ fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+ fetch_vector4(&inst->SrcReg[1], machine, dtdx);
+ fetch_vector4(&inst->SrcReg[2], machine, dtdy);
+ machine->FetchTexelDeriv(ctx, texcoord, dtdx, dtdy,
+ 0.0, /* lodBias */
+ inst->TexSrcUnit, color);
+ store_vector4(inst, machine, color);
+ }
+ break;
+ case OPCODE_TXP: /* GL_ARB_fragment_program only */
+ /* Texture lookup w/ projective divide */
+ {
+ GLfloat texcoord[4], color[4];
+
+ fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+ /* Not so sure about this test - if texcoord[3] is
+ * zero, we'd probably be fine except for an ASSERT in
+ * IROUND_POS() which gets triggered by the inf values created.
+ */
+ if (texcoord[3] != 0.0) {
+ texcoord[0] /= texcoord[3];
+ texcoord[1] /= texcoord[3];
+ texcoord[2] /= texcoord[3];
+ }
+
+ fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
+
+ store_vector4(inst, machine, color);
+ }
+ break;
+ case OPCODE_TXP_NV: /* GL_NV_fragment_program only */
+ /* Texture lookup w/ projective divide, as above, but do not
+ * do the divide by w if sampling from a cube map.
+ */
+ {
+ GLfloat texcoord[4], color[4];
+
+ fetch_vector4(&inst->SrcReg[0], machine, texcoord);
+ if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
+ texcoord[3] != 0.0) {
+ texcoord[0] /= texcoord[3];
+ texcoord[1] /= texcoord[3];
+ texcoord[2] /= texcoord[3];
+ }
+
+ fetch_texel(ctx, machine, inst, texcoord, 0.0, color);
+
+ store_vector4(inst, machine, color);
+ }
+ break;
+ case OPCODE_TRUNC: /* truncate toward zero */
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ result[0] = (GLfloat) (GLint) a[0];
+ result[1] = (GLfloat) (GLint) a[1];
+ result[2] = (GLfloat) (GLint) a[2];
+ result[3] = (GLfloat) (GLint) a[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_UP2H: /* unpack two 16-bit floats */
+ {
+ GLfloat a[4], result[4];
+ const GLuint *rawBits = (const GLuint *) a;
+ GLhalfNV hx, hy;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ hx = rawBits[0] & 0xffff;
+ hy = rawBits[0] >> 16;
+ result[0] = result[2] = _mesa_half_to_float(hx);
+ result[1] = result[3] = _mesa_half_to_float(hy);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_UP2US: /* unpack two GLushorts */
+ {
+ GLfloat a[4], result[4];
+ const GLuint *rawBits = (const GLuint *) a;
+ GLushort usx, usy;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ usx = rawBits[0] & 0xffff;
+ usy = rawBits[0] >> 16;
+ result[0] = result[2] = usx * (1.0f / 65535.0f);
+ result[1] = result[3] = usy * (1.0f / 65535.0f);
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_UP4B: /* unpack four GLbytes */
+ {
+ GLfloat a[4], result[4];
+ const GLuint *rawBits = (const GLuint *) a;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] = (((rawBits[0] >> 0) & 0xff) - 128) / 127.0F;
+ result[1] = (((rawBits[0] >> 8) & 0xff) - 128) / 127.0F;
+ result[2] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F;
+ result[3] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F;
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_UP4UB: /* unpack four GLubytes */
+ {
+ GLfloat a[4], result[4];
+ const GLuint *rawBits = (const GLuint *) a;
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ result[0] = ((rawBits[0] >> 0) & 0xff) / 255.0F;
+ result[1] = ((rawBits[0] >> 8) & 0xff) / 255.0F;
+ result[2] = ((rawBits[0] >> 16) & 0xff) / 255.0F;
+ result[3] = ((rawBits[0] >> 24) & 0xff) / 255.0F;
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_XOR: /* bitwise XOR */
+ {
+ GLuint a[4], b[4], result[4];
+ fetch_vector4ui(&inst->SrcReg[0], machine, a);
+ fetch_vector4ui(&inst->SrcReg[1], machine, b);
+ result[0] = a[0] ^ b[0];
+ result[1] = a[1] ^ b[1];
+ result[2] = a[2] ^ b[2];
+ result[3] = a[3] ^ b[3];
+ store_vector4ui(inst, machine, result);
+ }
+ break;
+ case OPCODE_XPD: /* cross product */
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ result[0] = a[1] * b[2] - a[2] * b[1];
+ result[1] = a[2] * b[0] - a[0] * b[2];
+ result[2] = a[0] * b[1] - a[1] * b[0];
+ result[3] = 1.0;
+ store_vector4(inst, machine, result);
+ if (DEBUG_PROG) {
+ printf("XPD (%g %g %g %g) = (%g %g %g) X (%g %g %g)\n",
+ result[0], result[1], result[2], result[3],
+ a[0], a[1], a[2], b[0], b[1], b[2]);
+ }
+ }
+ break;
+ case OPCODE_X2D: /* 2-D matrix transform */
+ {
+ GLfloat a[4], b[4], c[4], result[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ fetch_vector4(&inst->SrcReg[1], machine, b);
+ fetch_vector4(&inst->SrcReg[2], machine, c);
+ result[0] = a[0] + b[0] * c[0] + b[1] * c[1];
+ result[1] = a[1] + b[0] * c[2] + b[1] * c[3];
+ result[2] = a[2] + b[0] * c[0] + b[1] * c[1];
+ result[3] = a[3] + b[0] * c[2] + b[1] * c[3];
+ store_vector4(inst, machine, result);
+ }
+ break;
+ case OPCODE_PRINT:
+ {
+ if (inst->SrcReg[0].File != -1) {
+ GLfloat a[4];
+ fetch_vector4(&inst->SrcReg[0], machine, a);
+ _mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
+ a[0], a[1], a[2], a[3]);
+ }
+ else {
+ _mesa_printf("%s\n", (const char *) inst->Data);
+ }
+ }
+ break;
+ case OPCODE_END:
+ return GL_TRUE;
+ default:
+ _mesa_problem(ctx, "Bad opcode %d in _mesa_execute_program",
+ inst->Opcode);
+ return GL_TRUE; /* return value doesn't matter */
+ }
+
+ numExec++;
+ if (numExec > maxExec) {
+ _mesa_problem(ctx, "Infinite loop detected in fragment program");
+ return GL_TRUE;
+ }
+
+ } /* for pc */
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/shader/prog_execute.h b/mesalib/src/mesa/shader/prog_execute.h
new file mode 100644
index 000000000..adefc5439
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_execute.h
@@ -0,0 +1,85 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 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 PROG_EXECUTE_H
+#define PROG_EXECUTE_H
+
+#include "main/config.h"
+
+
+typedef void (*FetchTexelLodFunc)(GLcontext *ctx, const GLfloat texcoord[4],
+ GLfloat lambda, GLuint unit, GLfloat color[4]);
+
+typedef void (*FetchTexelDerivFunc)(GLcontext *ctx, const GLfloat texcoord[4],
+ const GLfloat texdx[4],
+ const GLfloat texdy[4],
+ GLfloat lodBias,
+ GLuint unit, GLfloat color[4]);
+
+
+/**
+ * Virtual machine state used during execution of vertex/fragment programs.
+ */
+struct gl_program_machine
+{
+ const struct gl_program *CurProgram;
+
+ /** Fragment Input attributes */
+ GLfloat (*Attribs)[MAX_WIDTH][4];
+ GLfloat (*DerivX)[4];
+ GLfloat (*DerivY)[4];
+ GLuint NumDeriv; /**< Max index into DerivX/Y arrays */
+ GLuint CurElement; /**< Index into Attribs arrays */
+
+ /** Vertex Input attribs */
+ GLfloat VertAttribs[VERT_ATTRIB_MAX][4];
+
+ GLfloat Temporaries[MAX_PROGRAM_TEMPS][4];
+ GLfloat Outputs[MAX_PROGRAM_OUTPUTS][4];
+ GLfloat (*EnvParams)[4]; /**< Vertex or Fragment env parameters */
+ GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */
+ GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4];
+
+ const GLubyte *Samplers; /** Array mapping sampler var to tex unit */
+
+ GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
+ GLuint StackDepth; /**< Index/ptr to top of CallStack[] */
+
+ /** Texture fetch functions */
+ FetchTexelLodFunc FetchTexelLod;
+ FetchTexelDerivFunc FetchTexelDeriv;
+};
+
+
+extern void
+_mesa_get_program_register(GLcontext *ctx, gl_register_file file,
+ GLuint index, GLfloat val[4]);
+
+extern GLboolean
+_mesa_execute_program(GLcontext *ctx,
+ const struct gl_program *program,
+ struct gl_program_machine *machine);
+
+
+#endif /* PROG_EXECUTE_H */
diff --git a/mesalib/src/mesa/shader/prog_instruction.c b/mesalib/src/mesa/shader/prog_instruction.c
new file mode 100644
index 000000000..44c961927
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_instruction.c
@@ -0,0 +1,352 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "prog_instruction.h"
+
+
+/**
+ * Initialize program instruction fields to defaults.
+ * \param inst first instruction to initialize
+ * \param count number of instructions to initialize
+ */
+void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count)
+{
+ GLuint i;
+
+ _mesa_bzero(inst, count * sizeof(struct prog_instruction));
+
+ for (i = 0; i < count; i++) {
+ inst[i].SrcReg[0].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
+ inst[i].SrcReg[1].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ inst[i].SrcReg[2].File = PROGRAM_UNDEFINED;
+ inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+ inst[i].DstReg.File = PROGRAM_UNDEFINED;
+ inst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+ inst[i].DstReg.CondMask = COND_TR;
+ inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP;
+
+ inst[i].SaturateMode = SATURATE_OFF;
+ inst[i].Precision = FLOAT32;
+ }
+}
+
+
+/**
+ * Allocate an array of program instructions.
+ * \param numInst number of instructions
+ * \return pointer to instruction memory
+ */
+struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst)
+{
+ return (struct prog_instruction *)
+ _mesa_calloc(numInst * sizeof(struct prog_instruction));
+}
+
+
+/**
+ * Reallocate memory storing an array of program instructions.
+ * This is used when we need to append additional instructions onto an
+ * program.
+ * \param oldInst pointer to first of old/src instructions
+ * \param numOldInst number of instructions at <oldInst>
+ * \param numNewInst desired size of new instruction array.
+ * \return pointer to start of new instruction array.
+ */
+struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+ GLuint numOldInst, GLuint numNewInst)
+{
+ struct prog_instruction *newInst;
+
+ newInst = (struct prog_instruction *)
+ _mesa_realloc(oldInst,
+ numOldInst * sizeof(struct prog_instruction),
+ numNewInst * sizeof(struct prog_instruction));
+
+ return newInst;
+}
+
+
+/**
+ * Copy an array of program instructions.
+ * \param dest pointer to destination.
+ * \param src pointer to source.
+ * \param n number of instructions to copy.
+ * \return pointer to destination.
+ */
+struct prog_instruction *
+_mesa_copy_instructions(struct prog_instruction *dest,
+ const struct prog_instruction *src, GLuint n)
+{
+ GLuint i;
+ _mesa_memcpy(dest, src, n * sizeof(struct prog_instruction));
+ for (i = 0; i < n; i++) {
+ if (src[i].Comment)
+ dest[i].Comment = _mesa_strdup(src[i].Comment);
+ }
+ return dest;
+}
+
+
+/**
+ * Free an array of instructions
+ */
+void
+_mesa_free_instructions(struct prog_instruction *inst, GLuint count)
+{
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ if (inst[i].Data)
+ _mesa_free(inst[i].Data);
+ if (inst[i].Comment)
+ _mesa_free((char *) inst[i].Comment);
+ }
+ _mesa_free(inst);
+}
+
+
+/**
+ * Basic info about each instruction
+ */
+struct instruction_info
+{
+ gl_inst_opcode Opcode;
+ const char *Name;
+ GLuint NumSrcRegs;
+ GLuint NumDstRegs;
+};
+
+/**
+ * Instruction info
+ * \note Opcode should equal array index!
+ */
+static const struct instruction_info InstInfo[MAX_OPCODE] = {
+ { OPCODE_NOP, "NOP", 0, 0 },
+ { OPCODE_ABS, "ABS", 1, 1 },
+ { OPCODE_ADD, "ADD", 2, 1 },
+ { OPCODE_AND, "AND", 2, 1 },
+ { OPCODE_ARA, "ARA", 1, 1 },
+ { OPCODE_ARL, "ARL", 1, 1 },
+ { OPCODE_ARL_NV, "ARL_NV", 1, 1 },
+ { OPCODE_ARR, "ARL", 1, 1 },
+ { OPCODE_BGNLOOP,"BGNLOOP", 0, 0 },
+ { OPCODE_BGNSUB, "BGNSUB", 0, 0 },
+ { OPCODE_BRA, "BRA", 0, 0 },
+ { OPCODE_BRK, "BRK", 0, 0 },
+ { OPCODE_CAL, "CAL", 0, 0 },
+ { OPCODE_CMP, "CMP", 3, 1 },
+ { OPCODE_CONT, "CONT", 0, 0 },
+ { OPCODE_COS, "COS", 1, 1 },
+ { OPCODE_DDX, "DDX", 1, 1 },
+ { OPCODE_DDY, "DDY", 1, 1 },
+ { OPCODE_DP2, "DP2", 2, 1 },
+ { OPCODE_DP2A, "DP2A", 3, 1 },
+ { OPCODE_DP3, "DP3", 2, 1 },
+ { OPCODE_DP4, "DP4", 2, 1 },
+ { OPCODE_DPH, "DPH", 2, 1 },
+ { OPCODE_DST, "DST", 2, 1 },
+ { OPCODE_ELSE, "ELSE", 0, 0 },
+ { OPCODE_END, "END", 0, 0 },
+ { OPCODE_ENDIF, "ENDIF", 0, 0 },
+ { OPCODE_ENDLOOP,"ENDLOOP", 0, 0 },
+ { OPCODE_ENDSUB, "ENDSUB", 0, 0 },
+ { OPCODE_EX2, "EX2", 1, 1 },
+ { OPCODE_EXP, "EXP", 1, 1 },
+ { OPCODE_FLR, "FLR", 1, 1 },
+ { OPCODE_FRC, "FRC", 1, 1 },
+ { OPCODE_IF, "IF", 1, 0 },
+ { OPCODE_KIL, "KIL", 1, 0 },
+ { OPCODE_KIL_NV, "KIL_NV", 0, 0 },
+ { OPCODE_LG2, "LG2", 1, 1 },
+ { OPCODE_LIT, "LIT", 1, 1 },
+ { OPCODE_LOG, "LOG", 1, 1 },
+ { OPCODE_LRP, "LRP", 3, 1 },
+ { OPCODE_MAD, "MAD", 3, 1 },
+ { OPCODE_MAX, "MAX", 2, 1 },
+ { OPCODE_MIN, "MIN", 2, 1 },
+ { OPCODE_MOV, "MOV", 1, 1 },
+ { OPCODE_MUL, "MUL", 2, 1 },
+ { OPCODE_NOISE1, "NOISE1", 1, 1 },
+ { OPCODE_NOISE2, "NOISE2", 1, 1 },
+ { OPCODE_NOISE3, "NOISE3", 1, 1 },
+ { OPCODE_NOISE4, "NOISE4", 1, 1 },
+ { OPCODE_NOT, "NOT", 1, 1 },
+ { OPCODE_NRM3, "NRM3", 1, 1 },
+ { OPCODE_NRM4, "NRM4", 1, 1 },
+ { OPCODE_OR, "OR", 2, 1 },
+ { OPCODE_PK2H, "PK2H", 1, 1 },
+ { OPCODE_PK2US, "PK2US", 1, 1 },
+ { OPCODE_PK4B, "PK4B", 1, 1 },
+ { OPCODE_PK4UB, "PK4UB", 1, 1 },
+ { OPCODE_POW, "POW", 2, 1 },
+ { OPCODE_POPA, "POPA", 0, 0 },
+ { OPCODE_PRINT, "PRINT", 1, 0 },
+ { OPCODE_PUSHA, "PUSHA", 0, 0 },
+ { OPCODE_RCC, "RCC", 1, 1 },
+ { OPCODE_RCP, "RCP", 1, 1 },
+ { OPCODE_RET, "RET", 0, 0 },
+ { OPCODE_RFL, "RFL", 1, 1 },
+ { OPCODE_RSQ, "RSQ", 1, 1 },
+ { OPCODE_SCS, "SCS", 1, 1 },
+ { OPCODE_SEQ, "SEQ", 2, 1 },
+ { OPCODE_SFL, "SFL", 0, 1 },
+ { OPCODE_SGE, "SGE", 2, 1 },
+ { OPCODE_SGT, "SGT", 2, 1 },
+ { OPCODE_SIN, "SIN", 1, 1 },
+ { OPCODE_SLE, "SLE", 2, 1 },
+ { OPCODE_SLT, "SLT", 2, 1 },
+ { OPCODE_SNE, "SNE", 2, 1 },
+ { OPCODE_SSG, "SSG", 1, 1 },
+ { OPCODE_STR, "STR", 0, 1 },
+ { OPCODE_SUB, "SUB", 2, 1 },
+ { OPCODE_SWZ, "SWZ", 1, 1 },
+ { OPCODE_TEX, "TEX", 1, 1 },
+ { OPCODE_TXB, "TXB", 1, 1 },
+ { OPCODE_TXD, "TXD", 3, 1 },
+ { OPCODE_TXL, "TXL", 1, 1 },
+ { OPCODE_TXP, "TXP", 1, 1 },
+ { OPCODE_TXP_NV, "TXP_NV", 1, 1 },
+ { OPCODE_TRUNC, "TRUNC", 1, 1 },
+ { OPCODE_UP2H, "UP2H", 1, 1 },
+ { OPCODE_UP2US, "UP2US", 1, 1 },
+ { OPCODE_UP4B, "UP4B", 1, 1 },
+ { OPCODE_UP4UB, "UP4UB", 1, 1 },
+ { OPCODE_X2D, "X2D", 3, 1 },
+ { OPCODE_XOR, "XOR", 2, 1 },
+ { OPCODE_XPD, "XPD", 2, 1 }
+};
+
+
+/**
+ * Return the number of src registers for the given instruction/opcode.
+ */
+GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode)
+{
+ ASSERT(opcode < MAX_OPCODE);
+ ASSERT(opcode == InstInfo[opcode].Opcode);
+ ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
+ return InstInfo[opcode].NumSrcRegs;
+}
+
+
+/**
+ * Return the number of dst registers for the given instruction/opcode.
+ */
+GLuint
+_mesa_num_inst_dst_regs(gl_inst_opcode opcode)
+{
+ ASSERT(opcode < MAX_OPCODE);
+ ASSERT(opcode == InstInfo[opcode].Opcode);
+ ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode);
+ return InstInfo[opcode].NumDstRegs;
+}
+
+
+GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode)
+{
+ return (opcode == OPCODE_TEX ||
+ opcode == OPCODE_TXB ||
+ opcode == OPCODE_TXD ||
+ opcode == OPCODE_TXL ||
+ opcode == OPCODE_TXP);
+}
+
+
+/**
+ * Check if there's a potential src/dst register data dependency when
+ * using SOA execution.
+ * Example:
+ * MOV T, T.yxwz;
+ * This would expand into:
+ * MOV t0, t1;
+ * MOV t1, t0;
+ * MOV t2, t3;
+ * MOV t3, t2;
+ * The second instruction will have the wrong value for t0 if executed as-is.
+ */
+GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst)
+{
+ GLuint i, chan;
+
+ if (inst->DstReg.WriteMask == WRITEMASK_X ||
+ inst->DstReg.WriteMask == WRITEMASK_Y ||
+ inst->DstReg.WriteMask == WRITEMASK_Z ||
+ inst->DstReg.WriteMask == WRITEMASK_W ||
+ inst->DstReg.WriteMask == 0x0) {
+ /* no chance of data dependency */
+ return GL_FALSE;
+ }
+
+ /* loop over src regs */
+ for (i = 0; i < 3; i++) {
+ if (inst->SrcReg[i].File == inst->DstReg.File &&
+ inst->SrcReg[i].Index == inst->DstReg.Index) {
+ /* loop over dest channels */
+ GLuint channelsWritten = 0x0;
+ for (chan = 0; chan < 4; chan++) {
+ if (inst->DstReg.WriteMask & (1 << chan)) {
+ /* check if we're reading a channel that's been written */
+ GLuint swizzle = GET_SWZ(inst->SrcReg[i].Swizzle, chan);
+ if (swizzle <= SWIZZLE_W &&
+ (channelsWritten & (1 << swizzle))) {
+ return GL_TRUE;
+ }
+
+ channelsWritten |= (1 << chan);
+ }
+ }
+ }
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Return string name for given program opcode.
+ */
+const char *
+_mesa_opcode_string(gl_inst_opcode opcode)
+{
+ if (opcode < MAX_OPCODE)
+ return InstInfo[opcode].Name;
+ else {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "OP%u", opcode);
+ return s;
+ }
+}
+
diff --git a/mesalib/src/mesa/shader/prog_instruction.h b/mesalib/src/mesa/shader/prog_instruction.h
new file mode 100644
index 000000000..39a221eea
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_instruction.h
@@ -0,0 +1,439 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file prog_instruction.h
+ *
+ * Vertex/fragment program instruction datatypes and constants.
+ *
+ * \author Brian Paul
+ * \author Keith Whitwell
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+#ifndef PROG_INSTRUCTION_H
+#define PROG_INSTRUCTION_H
+
+
+#include "main/mfeatures.h"
+
+
+/**
+ * Swizzle indexes.
+ * Do not change!
+ */
+/*@{*/
+#define SWIZZLE_X 0
+#define SWIZZLE_Y 1
+#define SWIZZLE_Z 2
+#define SWIZZLE_W 3
+#define SWIZZLE_ZERO 4 /**< For SWZ instruction only */
+#define SWIZZLE_ONE 5 /**< For SWZ instruction only */
+#define SWIZZLE_NIL 7 /**< used during shader code gen (undefined value) */
+/*@}*/
+
+#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9))
+#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3)
+#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7)
+#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1)
+
+#define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
+#define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)
+#define SWIZZLE_YYYY MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y)
+#define SWIZZLE_ZZZZ MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z)
+#define SWIZZLE_WWWW MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+
+
+/**
+ * Writemask values, 1 bit per component.
+ */
+/*@{*/
+#define WRITEMASK_X 0x1
+#define WRITEMASK_Y 0x2
+#define WRITEMASK_XY 0x3
+#define WRITEMASK_Z 0x4
+#define WRITEMASK_XZ 0x5
+#define WRITEMASK_YZ 0x6
+#define WRITEMASK_XYZ 0x7
+#define WRITEMASK_W 0x8
+#define WRITEMASK_XW 0x9
+#define WRITEMASK_YW 0xa
+#define WRITEMASK_XYW 0xb
+#define WRITEMASK_ZW 0xc
+#define WRITEMASK_XZW 0xd
+#define WRITEMASK_YZW 0xe
+#define WRITEMASK_XYZW 0xf
+/*@}*/
+
+
+/**
+ * Condition codes
+ */
+/*@{*/
+#define COND_GT 1 /**< greater than zero */
+#define COND_EQ 2 /**< equal to zero */
+#define COND_LT 3 /**< less than zero */
+#define COND_UN 4 /**< unordered (NaN) */
+#define COND_GE 5 /**< greater then or equal to zero */
+#define COND_LE 6 /**< less then or equal to zero */
+#define COND_NE 7 /**< not equal to zero */
+#define COND_TR 8 /**< always true */
+#define COND_FL 9 /**< always false */
+/*@}*/
+
+
+/**
+ * Instruction precision for GL_NV_fragment_program
+ */
+/*@{*/
+#define FLOAT32 0x1
+#define FLOAT16 0x2
+#define FIXED12 0x4
+/*@}*/
+
+
+/**
+ * Saturation modes when storing values.
+ */
+/*@{*/
+#define SATURATE_OFF 0
+#define SATURATE_ZERO_ONE 1
+#define SATURATE_PLUS_MINUS_ONE 2
+/*@}*/
+
+
+/**
+ * Per-component negation masks
+ */
+/*@{*/
+#define NEGATE_X 0x1
+#define NEGATE_Y 0x2
+#define NEGATE_Z 0x4
+#define NEGATE_W 0x8
+#define NEGATE_XYZ 0x7
+#define NEGATE_XYZW 0xf
+#define NEGATE_NONE 0x0
+/*@}*/
+
+
+/**
+ * Program instruction opcodes, for both vertex and fragment programs.
+ * \note changes to this opcode list must be reflected in t_vb_arbprogram.c
+ */
+typedef enum prog_opcode {
+ /* ARB_vp ARB_fp NV_vp NV_fp GLSL */
+ /*------------------------------------------*/
+ OPCODE_NOP = 0, /* X */
+ OPCODE_ABS, /* X X 1.1 X */
+ OPCODE_ADD, /* X X X X X */
+ OPCODE_AND, /* */
+ OPCODE_ARA, /* 2 */
+ OPCODE_ARL, /* X X */
+ OPCODE_ARL_NV, /* 2 */
+ OPCODE_ARR, /* 2 */
+ OPCODE_BGNLOOP, /* opt */
+ OPCODE_BGNSUB, /* opt */
+ OPCODE_BRA, /* 2 X */
+ OPCODE_BRK, /* 2 opt */
+ OPCODE_CAL, /* 2 2 */
+ OPCODE_CMP, /* X */
+ OPCODE_CONT, /* opt */
+ OPCODE_COS, /* X 2 X X */
+ OPCODE_DDX, /* X X */
+ OPCODE_DDY, /* X X */
+ OPCODE_DP2, /* 2 */
+ OPCODE_DP2A, /* 2 */
+ OPCODE_DP3, /* X X X X X */
+ OPCODE_DP4, /* X X X X X */
+ OPCODE_DPH, /* X X 1.1 */
+ OPCODE_DST, /* X X X X */
+ OPCODE_ELSE, /* X */
+ OPCODE_END, /* X X X X opt */
+ OPCODE_ENDIF, /* opt */
+ OPCODE_ENDLOOP, /* opt */
+ OPCODE_ENDSUB, /* opt */
+ OPCODE_EX2, /* X X 2 X X */
+ OPCODE_EXP, /* X X X */
+ OPCODE_FLR, /* X X 2 X X */
+ OPCODE_FRC, /* X X 2 X X */
+ OPCODE_IF, /* opt */
+ OPCODE_KIL, /* X */
+ OPCODE_KIL_NV, /* X X */
+ OPCODE_LG2, /* X X 2 X X */
+ OPCODE_LIT, /* X X X X */
+ OPCODE_LOG, /* X X X */
+ OPCODE_LRP, /* X X */
+ OPCODE_MAD, /* X X X X X */
+ OPCODE_MAX, /* X X X X X */
+ OPCODE_MIN, /* X X X X X */
+ OPCODE_MOV, /* X X X X X */
+ OPCODE_MUL, /* X X X X X */
+ OPCODE_NOISE1, /* X */
+ OPCODE_NOISE2, /* X */
+ OPCODE_NOISE3, /* X */
+ OPCODE_NOISE4, /* X */
+ OPCODE_NOT, /* */
+ OPCODE_NRM3, /* */
+ OPCODE_NRM4, /* */
+ OPCODE_OR, /* */
+ OPCODE_PK2H, /* X */
+ OPCODE_PK2US, /* X */
+ OPCODE_PK4B, /* X */
+ OPCODE_PK4UB, /* X */
+ OPCODE_POW, /* X X X X */
+ OPCODE_POPA, /* 3 */
+ OPCODE_PRINT, /* X X */
+ OPCODE_PUSHA, /* 3 */
+ OPCODE_RCC, /* 1.1 */
+ OPCODE_RCP, /* X X X X X */
+ OPCODE_RET, /* 2 2 */
+ OPCODE_RFL, /* X X */
+ OPCODE_RSQ, /* X X X X X */
+ OPCODE_SCS, /* X */
+ OPCODE_SEQ, /* 2 X X */
+ OPCODE_SFL, /* 2 X */
+ OPCODE_SGE, /* X X X X X */
+ OPCODE_SGT, /* 2 X X */
+ OPCODE_SIN, /* X 2 X X */
+ OPCODE_SLE, /* 2 X X */
+ OPCODE_SLT, /* X X X X X */
+ OPCODE_SNE, /* 2 X X */
+ OPCODE_SSG, /* 2 */
+ OPCODE_STR, /* 2 X */
+ OPCODE_SUB, /* X X 1.1 X X */
+ OPCODE_SWZ, /* X X */
+ OPCODE_TEX, /* X 3 X X */
+ OPCODE_TXB, /* X 3 X */
+ OPCODE_TXD, /* X X */
+ OPCODE_TXL, /* 3 2 X */
+ OPCODE_TXP, /* X X */
+ OPCODE_TXP_NV, /* 3 X */
+ OPCODE_TRUNC, /* X */
+ OPCODE_UP2H, /* X */
+ OPCODE_UP2US, /* X */
+ OPCODE_UP4B, /* X */
+ OPCODE_UP4UB, /* X */
+ OPCODE_X2D, /* X */
+ OPCODE_XOR, /* */
+ OPCODE_XPD, /* X X X */
+ MAX_OPCODE
+} gl_inst_opcode;
+
+
+/**
+ * Number of bits for the src/dst register Index field.
+ * This limits the size of temp/uniform register files.
+ */
+#define INST_INDEX_BITS 10
+
+
+/**
+ * Instruction source register.
+ */
+struct prog_src_register
+{
+ GLuint File:4; /**< One of the PROGRAM_* register file values. */
+ GLint Index:(INST_INDEX_BITS+1); /**< Extra bit here for sign bit.
+ * May be negative for relative addressing.
+ */
+ GLuint Swizzle:12;
+ GLuint RelAddr:1;
+
+ /** Take the component-wise absolute value */
+ GLuint Abs:1;
+
+ /**
+ * Post-Abs negation.
+ * This will either be NEGATE_NONE or NEGATE_XYZW, except for the SWZ
+ * instruction which allows per-component negation.
+ */
+ GLuint Negate:4;
+};
+
+
+/**
+ * Instruction destination register.
+ */
+struct prog_dst_register
+{
+ GLuint File:4; /**< One of the PROGRAM_* register file values */
+ GLuint Index:INST_INDEX_BITS; /**< Unsigned, never negative */
+ GLuint WriteMask:4;
+ GLuint RelAddr:1;
+
+ /**
+ * \name Conditional destination update control.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ /*@{*/
+ /**
+ * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT,
+ * NE, TR, or UN). Dest reg is only written to if the matching
+ * (swizzled) condition code value passes. When a conditional update mask
+ * is not specified, this will be \c COND_TR.
+ */
+ GLuint CondMask:4;
+
+ /**
+ * Condition code swizzle value.
+ */
+ GLuint CondSwizzle:12;
+
+ /**
+ * Selects the condition code register to use for conditional destination
+ * update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only
+ * condition code register 0 is available. In NV_vertex_program3 mode,
+ * condition code registers 0 and 1 are available.
+ */
+ GLuint CondSrc:1;
+ /*@}*/
+ GLuint pad:28;
+};
+
+
+/**
+ * Vertex/fragment program instruction.
+ */
+struct prog_instruction
+{
+ gl_inst_opcode Opcode;
+ struct prog_src_register SrcReg[3];
+ struct prog_dst_register DstReg;
+
+ /**
+ * Indicates that the instruction should update the condition code
+ * register.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ GLuint CondUpdate:1;
+
+ /**
+ * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
+ * condition code register that is to be updated.
+ *
+ * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
+ * code register 0 is available. In GL_NV_vertex_program3 mode, condition
+ * code registers 0 and 1 are available.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2,
+ * NV_vertex_program2_option.
+ */
+ GLuint CondDst:1;
+
+ /**
+ * Saturate each value of the vectored result to the range [0,1] or the
+ * range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is
+ * only available in NV_fragment_program2 mode.
+ * Value is one of the SATURATE_* tokens.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3.
+ */
+ GLuint SaturateMode:2;
+
+ /**
+ * Per-instruction selectable precision: FLOAT32, FLOAT16, FIXED12.
+ *
+ * \since
+ * NV_fragment_program, NV_fragment_program_option.
+ */
+ GLuint Precision:3;
+
+ /**
+ * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions.
+ */
+ /*@{*/
+ /** Source texture unit. */
+ GLuint TexSrcUnit:5;
+
+ /** Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX */
+ GLuint TexSrcTarget:3;
+
+ /** True if tex instruction should do shadow comparison */
+ GLuint TexShadow:1;
+ /*@}*/
+
+ /**
+ * For BRA and CAL instructions, the location to jump to.
+ * For BGNLOOP, points to ENDLOOP (and vice-versa).
+ * For BRK, points to BGNLOOP (which points to ENDLOOP).
+ * For IF, points to ELSE or ENDIF.
+ * For ELSE, points to ENDIF.
+ */
+ GLint BranchTarget;
+
+ /** for debugging purposes */
+ const char *Comment;
+
+ /** Arbitrary data. Used for OPCODE_PRINT and some drivers */
+ void *Data;
+
+ /** for driver use (try to remove someday) */
+ GLint Aux;
+};
+
+
+extern void
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count);
+
+extern struct prog_instruction *
+_mesa_alloc_instructions(GLuint numInst);
+
+extern struct prog_instruction *
+_mesa_realloc_instructions(struct prog_instruction *oldInst,
+ GLuint numOldInst, GLuint numNewInst);
+
+extern struct prog_instruction *
+_mesa_copy_instructions(struct prog_instruction *dest,
+ const struct prog_instruction *src, GLuint n);
+
+extern void
+_mesa_free_instructions(struct prog_instruction *inst, GLuint count);
+
+extern GLuint
+_mesa_num_inst_src_regs(gl_inst_opcode opcode);
+
+extern GLuint
+_mesa_num_inst_dst_regs(gl_inst_opcode opcode);
+
+extern GLboolean
+_mesa_is_tex_instruction(gl_inst_opcode opcode);
+
+extern GLboolean
+_mesa_check_soa_dependencies(const struct prog_instruction *inst);
+
+extern const char *
+_mesa_opcode_string(gl_inst_opcode opcode);
+
+
+#endif /* PROG_INSTRUCTION_H */
diff --git a/mesalib/src/mesa/shader/prog_noise.c b/mesalib/src/mesa/shader/prog_noise.c
new file mode 100644
index 000000000..1713ddb5f
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_noise.c
@@ -0,0 +1,638 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+/*
+ * SimplexNoise1234
+ * Copyright (c) 2003-2005, Stefan Gustavson
+ *
+ * Contact: stegu@itn.liu.se
+ */
+
+/**
+ * \file
+ * \brief C implementation of Perlin Simplex Noise over 1, 2, 3 and 4 dims.
+ * \author Stefan Gustavson (stegu@itn.liu.se)
+ *
+ *
+ * This implementation is "Simplex Noise" as presented by
+ * Ken Perlin at a relatively obscure and not often cited course
+ * session "Real-Time Shading" at Siggraph 2001 (before real
+ * time shading actually took on), under the title "hardware noise".
+ * The 3D function is numerically equivalent to his Java reference
+ * code available in the PDF course notes, although I re-implemented
+ * it from scratch to get more readable code. The 1D, 2D and 4D cases
+ * were implemented from scratch by me from Ken Perlin's text.
+ *
+ * This file has no dependencies on any other file, not even its own
+ * header file. The header file is made for use by external code only.
+ */
+
+
+#include "main/imports.h"
+#include "prog_noise.h"
+
+#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) )
+
+/*
+ * ---------------------------------------------------------------------
+ * Static data
+ */
+
+/**
+ * Permutation table. This is just a random jumble of all numbers 0-255,
+ * repeated twice to avoid wrapping the index at 255 for each lookup.
+ * This needs to be exactly the same for all instances on all platforms,
+ * so it's easiest to just keep it as static explicit data.
+ * This also removes the need for any initialisation of this class.
+ *
+ * Note that making this an int[] instead of a char[] might make the
+ * code run faster on platforms with a high penalty for unaligned single
+ * byte addressing. Intel x86 is generally single-byte-friendly, but
+ * some other CPUs are faster with 4-aligned reads.
+ * However, a char[] is smaller, which avoids cache trashing, and that
+ * is probably the most important aspect on most architectures.
+ * This array is accessed a *lot* by the noise functions.
+ * A vector-valued noise over 3D accesses it 96 times, and a
+ * float-valued 4D noise 64 times. We want this to fit in the cache!
+ */
+unsigned char perm[512] = { 151, 160, 137, 91, 90, 15,
+ 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8,
+ 99, 37, 240, 21, 10, 23,
+ 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35,
+ 11, 32, 57, 177, 33,
+ 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71,
+ 134, 139, 48, 27, 166,
+ 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41,
+ 55, 46, 245, 40, 244,
+ 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89,
+ 18, 169, 200, 196,
+ 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217,
+ 226, 250, 124, 123,
+ 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58,
+ 17, 182, 189, 28, 42,
+ 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155,
+ 167, 43, 172, 9,
+ 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
+ 218, 246, 97, 228,
+ 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235,
+ 249, 14, 239, 107,
+ 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45,
+ 127, 4, 150, 254,
+ 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66,
+ 215, 61, 156, 180,
+ 151, 160, 137, 91, 90, 15,
+ 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8,
+ 99, 37, 240, 21, 10, 23,
+ 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35,
+ 11, 32, 57, 177, 33,
+ 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71,
+ 134, 139, 48, 27, 166,
+ 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41,
+ 55, 46, 245, 40, 244,
+ 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89,
+ 18, 169, 200, 196,
+ 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217,
+ 226, 250, 124, 123,
+ 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58,
+ 17, 182, 189, 28, 42,
+ 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155,
+ 167, 43, 172, 9,
+ 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
+ 218, 246, 97, 228,
+ 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235,
+ 249, 14, 239, 107,
+ 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45,
+ 127, 4, 150, 254,
+ 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66,
+ 215, 61, 156, 180
+};
+
+/*
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * Helper functions to compute gradients-dot-residualvectors (1D to 4D)
+ * Note that these generate gradients of more than unit length. To make
+ * a close match with the value range of classic Perlin noise, the final
+ * noise values need to be rescaled to fit nicely within [-1,1].
+ * (The simplex noise functions as such also have different scaling.)
+ * Note also that these noise functions are the most practical and useful
+ * signed version of Perlin noise. To return values according to the
+ * RenderMan specification from the SL noise() and pnoise() functions,
+ * the noise values need to be scaled and offset to [0,1], like this:
+ * float SLnoise = (SimplexNoise1234::noise(x,y,z) + 1.0) * 0.5;
+ */
+
+static float
+grad1(int hash, float x)
+{
+ int h = hash & 15;
+ float grad = 1.0f + (h & 7); /* Gradient value 1.0, 2.0, ..., 8.0 */
+ if (h & 8)
+ grad = -grad; /* Set a random sign for the gradient */
+ return (grad * x); /* Multiply the gradient with the distance */
+}
+
+static float
+grad2(int hash, float x, float y)
+{
+ int h = hash & 7; /* Convert low 3 bits of hash code */
+ float u = h < 4 ? x : y; /* into 8 simple gradient directions, */
+ float v = h < 4 ? y : x; /* and compute the dot product with (x,y). */
+ return ((h & 1) ? -u : u) + ((h & 2) ? -2.0f * v : 2.0f * v);
+}
+
+static float
+grad3(int hash, float x, float y, float z)
+{
+ int h = hash & 15; /* Convert low 4 bits of hash code into 12 simple */
+ float u = h < 8 ? x : y; /* gradient directions, and compute dot product. */
+ float v = h < 4 ? y : h == 12 || h == 14 ? x : z; /* Fix repeats at h = 12 to 15 */
+ return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
+}
+
+static float
+grad4(int hash, float x, float y, float z, float t)
+{
+ int h = hash & 31; /* Convert low 5 bits of hash code into 32 simple */
+ float u = h < 24 ? x : y; /* gradient directions, and compute dot product. */
+ float v = h < 16 ? y : z;
+ float w = h < 8 ? z : t;
+ return ((h & 1) ? -u : u) + ((h & 2) ? -v : v) + ((h & 4) ? -w : w);
+}
+
+/**
+ * A lookup table to traverse the simplex around a given point in 4D.
+ * Details can be found where this table is used, in the 4D noise method.
+ * TODO: This should not be required, backport it from Bill's GLSL code!
+ */
+static unsigned char simplex[64][4] = {
+ {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 0, 0, 0}, {0, 2, 3, 1},
+ {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 2, 3, 0},
+ {0, 2, 1, 3}, {0, 0, 0, 0}, {0, 3, 1, 2}, {0, 3, 2, 1},
+ {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 3, 2, 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, 2, 0, 3}, {0, 0, 0, 0}, {1, 3, 0, 2}, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {0, 0, 0, 0}, {2, 3, 0, 1}, {2, 3, 1, 0},
+ {1, 0, 2, 3}, {1, 0, 3, 2}, {0, 0, 0, 0}, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {2, 0, 3, 1}, {0, 0, 0, 0}, {2, 1, 3, 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},
+ {2, 0, 1, 3}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
+ {3, 0, 1, 2}, {3, 0, 2, 1}, {0, 0, 0, 0}, {3, 1, 2, 0},
+ {2, 1, 0, 3}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
+ {3, 1, 0, 2}, {0, 0, 0, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}
+};
+
+
+/** 1D simplex noise */
+GLfloat
+_mesa_noise1(GLfloat x)
+{
+ int i0 = FASTFLOOR(x);
+ int i1 = i0 + 1;
+ float x0 = x - i0;
+ float x1 = x0 - 1.0f;
+ float t1 = 1.0f - x1 * x1;
+ float n0, n1;
+
+ float t0 = 1.0f - x0 * x0;
+/* if(t0 < 0.0f) t0 = 0.0f; // this never happens for the 1D case */
+ t0 *= t0;
+ n0 = t0 * t0 * grad1(perm[i0 & 0xff], x0);
+
+/* if(t1 < 0.0f) t1 = 0.0f; // this never happens for the 1D case */
+ t1 *= t1;
+ n1 = t1 * t1 * grad1(perm[i1 & 0xff], x1);
+ /* The maximum value of this noise is 8*(3/4)^4 = 2.53125 */
+ /* A factor of 0.395 would scale to fit exactly within [-1,1], but */
+ /* we want to match PRMan's 1D noise, so we scale it down some more. */
+ return 0.25f * (n0 + n1);
+}
+
+
+/** 2D simplex noise */
+GLfloat
+_mesa_noise2(GLfloat x, GLfloat y)
+{
+#define F2 0.366025403f /* F2 = 0.5*(sqrt(3.0)-1.0) */
+#define G2 0.211324865f /* G2 = (3.0-Math.sqrt(3.0))/6.0 */
+
+ float n0, n1, n2; /* Noise contributions from the three corners */
+
+ /* Skew the input space to determine which simplex cell we're in */
+ float s = (x + y) * F2; /* Hairy factor for 2D */
+ float xs = x + s;
+ float ys = y + s;
+ int i = FASTFLOOR(xs);
+ int j = FASTFLOOR(ys);
+
+ float t = (float) (i + j) * G2;
+ float X0 = i - t; /* Unskew the cell origin back to (x,y) space */
+ float Y0 = j - t;
+ float x0 = x - X0; /* The x,y distances from the cell origin */
+ float y0 = y - Y0;
+
+ float x1, y1, x2, y2;
+ int ii, jj;
+ float t0, t1, t2;
+
+ /* For the 2D case, the simplex shape is an equilateral triangle. */
+ /* Determine which simplex we are in. */
+ int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */
+ if (x0 > y0) {
+ i1 = 1;
+ j1 = 0;
+ } /* lower triangle, XY order: (0,0)->(1,0)->(1,1) */
+ else {
+ i1 = 0;
+ j1 = 1;
+ } /* upper triangle, YX order: (0,0)->(0,1)->(1,1) */
+
+ /* A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and */
+ /* a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where */
+ /* c = (3-sqrt(3))/6 */
+
+ x1 = x0 - i1 + G2; /* Offsets for middle corner in (x,y) unskewed coords */
+ y1 = y0 - j1 + G2;
+ x2 = x0 - 1.0f + 2.0f * G2; /* Offsets for last corner in (x,y) unskewed coords */
+ y2 = y0 - 1.0f + 2.0f * G2;
+
+ /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */
+ ii = i % 256;
+ jj = j % 256;
+
+ /* Calculate the contribution from the three corners */
+ t0 = 0.5f - x0 * x0 - y0 * y0;
+ if (t0 < 0.0f)
+ n0 = 0.0f;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * grad2(perm[ii + perm[jj]], x0, y0);
+ }
+
+ t1 = 0.5f - x1 * x1 - y1 * y1;
+ if (t1 < 0.0f)
+ n1 = 0.0f;
+ else {
+ t1 *= t1;
+ n1 = t1 * t1 * grad2(perm[ii + i1 + perm[jj + j1]], x1, y1);
+ }
+
+ t2 = 0.5f - x2 * x2 - y2 * y2;
+ if (t2 < 0.0f)
+ n2 = 0.0f;
+ else {
+ t2 *= t2;
+ n2 = t2 * t2 * grad2(perm[ii + 1 + perm[jj + 1]], x2, y2);
+ }
+
+ /* Add contributions from each corner to get the final noise value. */
+ /* The result is scaled to return values in the interval [-1,1]. */
+ return 40.0f * (n0 + n1 + n2); /* TODO: The scale factor is preliminary! */
+}
+
+
+/** 3D simplex noise */
+GLfloat
+_mesa_noise3(GLfloat x, GLfloat y, GLfloat z)
+{
+/* Simple skewing factors for the 3D case */
+#define F3 0.333333333f
+#define G3 0.166666667f
+
+ float n0, n1, n2, n3; /* Noise contributions from the four corners */
+
+ /* Skew the input space to determine which simplex cell we're in */
+ float s = (x + y + z) * F3; /* Very nice and simple skew factor for 3D */
+ float xs = x + s;
+ float ys = y + s;
+ float zs = z + s;
+ int i = FASTFLOOR(xs);
+ int j = FASTFLOOR(ys);
+ int k = FASTFLOOR(zs);
+
+ float t = (float) (i + j + k) * G3;
+ float X0 = i - t; /* Unskew the cell origin back to (x,y,z) space */
+ float Y0 = j - t;
+ float Z0 = k - t;
+ float x0 = x - X0; /* The x,y,z distances from the cell origin */
+ float y0 = y - Y0;
+ float z0 = z - Z0;
+
+ float x1, y1, z1, x2, y2, z2, x3, y3, z3;
+ int ii, jj, kk;
+ float t0, t1, t2, t3;
+
+ /* For the 3D case, the simplex shape is a slightly irregular tetrahedron. */
+ /* Determine which simplex we are in. */
+ int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */
+ int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */
+
+/* This code would benefit from a backport from the GLSL version! */
+ if (x0 >= y0) {
+ if (y0 >= z0) {
+ i1 = 1;
+ j1 = 0;
+ k1 = 0;
+ i2 = 1;
+ j2 = 1;
+ k2 = 0;
+ } /* X Y Z order */
+ else if (x0 >= z0) {
+ i1 = 1;
+ j1 = 0;
+ k1 = 0;
+ i2 = 1;
+ j2 = 0;
+ k2 = 1;
+ } /* X Z Y order */
+ else {
+ i1 = 0;
+ j1 = 0;
+ k1 = 1;
+ i2 = 1;
+ j2 = 0;
+ k2 = 1;
+ } /* Z X Y order */
+ }
+ else { /* x0<y0 */
+ if (y0 < z0) {
+ i1 = 0;
+ j1 = 0;
+ k1 = 1;
+ i2 = 0;
+ j2 = 1;
+ k2 = 1;
+ } /* Z Y X order */
+ else if (x0 < z0) {
+ i1 = 0;
+ j1 = 1;
+ k1 = 0;
+ i2 = 0;
+ j2 = 1;
+ k2 = 1;
+ } /* Y Z X order */
+ else {
+ i1 = 0;
+ j1 = 1;
+ k1 = 0;
+ i2 = 1;
+ j2 = 1;
+ k2 = 0;
+ } /* Y X Z order */
+ }
+
+ /* A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in
+ * (x,y,z), a step of (0,1,0) in (i,j,k) means a step of
+ * (-c,1-c,-c) in (x,y,z), and a step of (0,0,1) in (i,j,k) means a
+ * step of (-c,-c,1-c) in (x,y,z), where c = 1/6.
+ */
+
+ x1 = x0 - i1 + G3; /* Offsets for second corner in (x,y,z) coords */
+ y1 = y0 - j1 + G3;
+ z1 = z0 - k1 + G3;
+ x2 = x0 - i2 + 2.0f * G3; /* Offsets for third corner in (x,y,z) coords */
+ y2 = y0 - j2 + 2.0f * G3;
+ z2 = z0 - k2 + 2.0f * G3;
+ x3 = x0 - 1.0f + 3.0f * G3;/* Offsets for last corner in (x,y,z) coords */
+ y3 = y0 - 1.0f + 3.0f * G3;
+ z3 = z0 - 1.0f + 3.0f * G3;
+
+ /* Wrap the integer indices at 256 to avoid indexing perm[] out of bounds */
+ ii = i % 256;
+ jj = j % 256;
+ kk = k % 256;
+
+ /* Calculate the contribution from the four corners */
+ t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0;
+ if (t0 < 0.0f)
+ n0 = 0.0f;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * grad3(perm[ii + perm[jj + perm[kk]]], x0, y0, z0);
+ }
+
+ t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1;
+ if (t1 < 0.0f)
+ n1 = 0.0f;
+ else {
+ t1 *= t1;
+ n1 =
+ t1 * t1 * grad3(perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]], x1,
+ y1, z1);
+ }
+
+ t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2;
+ if (t2 < 0.0f)
+ n2 = 0.0f;
+ else {
+ t2 *= t2;
+ n2 =
+ t2 * t2 * grad3(perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]], x2,
+ y2, z2);
+ }
+
+ t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3;
+ if (t3 < 0.0f)
+ n3 = 0.0f;
+ else {
+ t3 *= t3;
+ n3 =
+ t3 * t3 * grad3(perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]], x3, y3,
+ z3);
+ }
+
+ /* Add contributions from each corner to get the final noise value.
+ * The result is scaled to stay just inside [-1,1]
+ */
+ return 32.0f * (n0 + n1 + n2 + n3); /* TODO: The scale factor is preliminary! */
+}
+
+
+/** 4D simplex noise */
+GLfloat
+_mesa_noise4(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ /* The skewing and unskewing factors are hairy again for the 4D case */
+#define F4 0.309016994f /* F4 = (Math.sqrt(5.0)-1.0)/4.0 */
+#define G4 0.138196601f /* G4 = (5.0-Math.sqrt(5.0))/20.0 */
+
+ float n0, n1, n2, n3, n4; /* Noise contributions from the five corners */
+
+ /* Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in */
+ float s = (x + y + z + w) * F4; /* Factor for 4D skewing */
+ float xs = x + s;
+ float ys = y + s;
+ float zs = z + s;
+ float ws = w + s;
+ int i = FASTFLOOR(xs);
+ int j = FASTFLOOR(ys);
+ int k = FASTFLOOR(zs);
+ int l = FASTFLOOR(ws);
+
+ float t = (i + j + k + l) * G4; /* Factor for 4D unskewing */
+ float X0 = i - t; /* Unskew the cell origin back to (x,y,z,w) space */
+ float Y0 = j - t;
+ float Z0 = k - t;
+ float W0 = l - t;
+
+ float x0 = x - X0; /* The x,y,z,w distances from the cell origin */
+ float y0 = y - Y0;
+ float z0 = z - Z0;
+ float w0 = w - W0;
+
+ /* For the 4D case, the simplex is a 4D shape I won't even try to describe.
+ * To find out which of the 24 possible simplices we're in, we need to
+ * determine the magnitude ordering of x0, y0, z0 and w0.
+ * The method below is a good way of finding the ordering of x,y,z,w and
+ * then find the correct traversal order for the simplex we're in.
+ * First, six pair-wise comparisons are performed between each possible pair
+ * of the four coordinates, and the results are used to add up binary bits
+ * for an integer index.
+ */
+ int c1 = (x0 > y0) ? 32 : 0;
+ int c2 = (x0 > z0) ? 16 : 0;
+ int c3 = (y0 > z0) ? 8 : 0;
+ int c4 = (x0 > w0) ? 4 : 0;
+ int c5 = (y0 > w0) ? 2 : 0;
+ int c6 = (z0 > w0) ? 1 : 0;
+ int c = c1 + c2 + c3 + c4 + c5 + c6;
+
+ int i1, j1, k1, l1; /* The integer offsets for the second simplex corner */
+ int i2, j2, k2, l2; /* The integer offsets for the third simplex corner */
+ int i3, j3, k3, l3; /* The integer offsets for the fourth simplex corner */
+
+ float x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4;
+ int ii, jj, kk, ll;
+ float t0, t1, t2, t3, t4;
+
+ /*
+ * simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some
+ * order. Many values of c will never occur, since e.g. x>y>z>w
+ * makes x<z, y<w and x<w impossible. Only the 24 indices which
+ * have non-zero entries make any sense. We use a thresholding to
+ * set the coordinates in turn from the largest magnitude. The
+ * number 3 in the "simplex" array is at the position of the
+ * largest coordinate.
+ */
+ i1 = simplex[c][0] >= 3 ? 1 : 0;
+ j1 = simplex[c][1] >= 3 ? 1 : 0;
+ k1 = simplex[c][2] >= 3 ? 1 : 0;
+ l1 = simplex[c][3] >= 3 ? 1 : 0;
+ /* The number 2 in the "simplex" array is at the second largest coordinate. */
+ i2 = simplex[c][0] >= 2 ? 1 : 0;
+ j2 = simplex[c][1] >= 2 ? 1 : 0;
+ k2 = simplex[c][2] >= 2 ? 1 : 0;
+ l2 = simplex[c][3] >= 2 ? 1 : 0;
+ /* The number 1 in the "simplex" array is at the second smallest coordinate. */
+ i3 = simplex[c][0] >= 1 ? 1 : 0;
+ j3 = simplex[c][1] >= 1 ? 1 : 0;
+ k3 = simplex[c][2] >= 1 ? 1 : 0;
+ l3 = simplex[c][3] >= 1 ? 1 : 0;
+ /* The fifth corner has all coordinate offsets = 1, so no need to look that up. */
+
+ x1 = x0 - i1 + G4; /* Offsets for second corner in (x,y,z,w) coords */
+ y1 = y0 - j1 + G4;
+ z1 = z0 - k1 + G4;
+ w1 = w0 - l1 + G4;
+ x2 = x0 - i2 + 2.0f * G4; /* Offsets for third corner in (x,y,z,w) coords */
+ y2 = y0 - j2 + 2.0f * G4;
+ z2 = z0 - k2 + 2.0f * G4;
+ w2 = w0 - l2 + 2.0f * G4;
+ x3 = x0 - i3 + 3.0f * G4; /* Offsets for fourth corner in (x,y,z,w) coords */
+ y3 = y0 - j3 + 3.0f * G4;
+ z3 = z0 - k3 + 3.0f * G4;
+ w3 = w0 - l3 + 3.0f * G4;
+ x4 = x0 - 1.0f + 4.0f * G4; /* Offsets for last corner in (x,y,z,w) coords */
+ y4 = y0 - 1.0f + 4.0f * G4;
+ z4 = z0 - 1.0f + 4.0f * G4;
+ w4 = w0 - 1.0f + 4.0f * G4;
+
+ /* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */
+ ii = i % 256;
+ jj = j % 256;
+ kk = k % 256;
+ ll = l % 256;
+
+ /* Calculate the contribution from the five corners */
+ t0 = 0.6f - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
+ if (t0 < 0.0f)
+ n0 = 0.0f;
+ else {
+ t0 *= t0;
+ n0 =
+ t0 * t0 * grad4(perm[ii + perm[jj + perm[kk + perm[ll]]]], x0, y0,
+ z0, w0);
+ }
+
+ t1 = 0.6f - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
+ if (t1 < 0.0f)
+ n1 = 0.0f;
+ else {
+ t1 *= t1;
+ n1 =
+ t1 * t1 *
+ grad4(perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]],
+ x1, y1, z1, w1);
+ }
+
+ t2 = 0.6f - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
+ if (t2 < 0.0f)
+ n2 = 0.0f;
+ else {
+ t2 *= t2;
+ n2 =
+ t2 * t2 *
+ grad4(perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]],
+ x2, y2, z2, w2);
+ }
+
+ t3 = 0.6f - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
+ if (t3 < 0.0f)
+ n3 = 0.0f;
+ else {
+ t3 *= t3;
+ n3 =
+ t3 * t3 *
+ grad4(perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]],
+ x3, y3, z3, w3);
+ }
+
+ t4 = 0.6f - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
+ if (t4 < 0.0f)
+ n4 = 0.0f;
+ else {
+ t4 *= t4;
+ n4 =
+ t4 * t4 *
+ grad4(perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]], x4,
+ y4, z4, w4);
+ }
+
+ /* Sum up and scale the result to cover the range [-1,1] */
+ return 27.0f * (n0 + n1 + n2 + n3 + n4); /* TODO: The scale factor is preliminary! */
+}
diff --git a/mesalib/src/mesa/shader/prog_noise.h b/mesalib/src/mesa/shader/prog_noise.h
new file mode 100644
index 000000000..c4779479f
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_noise.h
@@ -0,0 +1,34 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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 PROG_NOISE
+#define PROG_NOISE
+
+extern GLfloat _mesa_noise1(GLfloat);
+extern GLfloat _mesa_noise2(GLfloat, GLfloat);
+extern GLfloat _mesa_noise3(GLfloat, GLfloat, GLfloat);
+extern GLfloat _mesa_noise4(GLfloat, GLfloat, GLfloat, GLfloat);
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/prog_optimize.c b/mesalib/src/mesa/shader/prog_optimize.c
new file mode 100644
index 000000000..be903106a
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_optimize.c
@@ -0,0 +1,832 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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
+ * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "program.h"
+#include "prog_instruction.h"
+#include "prog_optimize.h"
+#include "prog_print.h"
+
+
+#define MAX_LOOP_NESTING 50
+
+
+static GLboolean dbg = GL_FALSE;
+
+
+/**
+ * In 'prog' remove instruction[i] if removeFlags[i] == TRUE.
+ * \return number of instructions removed
+ */
+static GLuint
+remove_instructions(struct gl_program *prog, const GLboolean *removeFlags)
+{
+ GLint i, removeEnd = 0, removeCount = 0;
+ GLuint totalRemoved = 0;
+
+ /* go backward */
+ for (i = prog->NumInstructions - 1; i >= 0; i--) {
+ if (removeFlags[i]) {
+ totalRemoved++;
+ if (removeCount == 0) {
+ /* begin a run of instructions to remove */
+ removeEnd = i;
+ removeCount = 1;
+ }
+ else {
+ /* extend the run of instructions to remove */
+ removeCount++;
+ }
+ }
+ else {
+ /* don't remove this instruction, but check if the preceeding
+ * instructions are to be removed.
+ */
+ if (removeCount > 0) {
+ GLint removeStart = removeEnd - removeCount + 1;
+ _mesa_delete_instructions(prog, removeStart, removeCount);
+ removeStart = removeCount = 0; /* reset removal info */
+ }
+ }
+ }
+ return totalRemoved;
+}
+
+
+/**
+ * Remap register indexes according to map.
+ * \param prog the program to search/replace
+ * \param file the type of register file to search/replace
+ * \param map maps old register indexes to new indexes
+ */
+static void
+replace_regs(struct gl_program *prog, gl_register_file file, const GLint map[])
+{
+ GLuint i;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == file) {
+ GLuint index = inst->SrcReg[j].Index;
+ ASSERT(map[index] >= 0);
+ inst->SrcReg[j].Index = map[index];
+ }
+ }
+ if (inst->DstReg.File == file) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(map[index] >= 0);
+ inst->DstReg.Index = map[index];
+ }
+ }
+}
+
+
+/**
+ * Consolidate temporary registers to use low numbers. For example, if the
+ * shader only uses temps 4, 5, 8, replace them with 0, 1, 2.
+ */
+static void
+_mesa_consolidate_registers(struct gl_program *prog)
+{
+ GLboolean tempUsed[MAX_PROGRAM_TEMPS];
+ GLint tempMap[MAX_PROGRAM_TEMPS];
+ GLuint tempMax = 0, i;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin register consolidation\n");
+ }
+
+ memset(tempUsed, 0, sizeof(tempUsed));
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ tempMap[i] = -1;
+ }
+
+ /* set tempUsed[i] if temporary [i] is referenced */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ tempUsed[index] = GL_TRUE;
+ tempMax = MAX2(tempMax, index);
+ break;
+ }
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ tempUsed[index] = GL_TRUE;
+ tempMax = MAX2(tempMax, index);
+ }
+ }
+
+ /* allocate a new index for each temp that's used */
+ {
+ GLuint freeTemp = 0;
+ for (i = 0; i <= tempMax; i++) {
+ if (tempUsed[i]) {
+ tempMap[i] = freeTemp++;
+ /*_mesa_printf("replace %u with %u\n", i, tempMap[i]);*/
+ }
+ }
+ if (freeTemp == tempMax + 1) {
+ /* no consolidation possible */
+ return;
+ }
+ if (dbg) {
+ _mesa_printf("Replace regs 0..%u with 0..%u\n", tempMax, freeTemp-1);
+ }
+ }
+
+ replace_regs(prog, PROGRAM_TEMPORARY, tempMap);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End register consolidation\n");
+ }
+}
+
+
+/**
+ * Remove dead instructions from the given program.
+ * This is very primitive for now. Basically look for temp registers
+ * that are written to but never read. Remove any instructions that
+ * write to such registers. Be careful with condition code setters.
+ */
+static void
+_mesa_remove_dead_code(struct gl_program *prog)
+{
+ GLboolean tempWritten[MAX_PROGRAM_TEMPS], tempRead[MAX_PROGRAM_TEMPS];
+ GLboolean *removeInst; /* per-instruction removal flag */
+ GLuint i, rem;
+
+ memset(tempWritten, 0, sizeof(tempWritten));
+ memset(tempRead, 0, sizeof(tempRead));
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin dead code removal\n");
+ /*_mesa_print_program(prog);*/
+ }
+
+ removeInst = (GLboolean *)
+ _mesa_calloc(prog->NumInstructions * sizeof(GLboolean));
+
+ /* Determine which temps are read and written */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+
+ /* check src regs */
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+
+ if (inst->SrcReg[j].RelAddr) {
+ if (dbg)
+ _mesa_printf("abort remove dead code (indirect temp)\n");
+ return;
+ }
+
+ tempRead[index] = GL_TRUE;
+ }
+ }
+
+ /* check dst reg */
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+
+ if (inst->DstReg.RelAddr) {
+ if (dbg)
+ _mesa_printf("abort remove dead code (indirect temp)\n");
+ return;
+ }
+
+ tempWritten[index] = GL_TRUE;
+ if (inst->CondUpdate) {
+ /* If we're writing to this register and setting condition
+ * codes we cannot remove the instruction. Prevent removal
+ * by setting the 'read' flag.
+ */
+ tempRead[index] = GL_TRUE;
+ }
+ }
+ }
+
+ if (dbg) {
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (tempWritten[i] && !tempRead[i])
+ _mesa_printf("Remove writes to tmp %u\n", i);
+ }
+ }
+
+ /* find instructions that write to dead registers, flag for removal */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ GLint index = inst->DstReg.Index;
+ removeInst[i] = (tempWritten[index] && !tempRead[index]);
+ if (dbg && removeInst[i]) {
+ _mesa_printf("Remove inst %u: ", i);
+ _mesa_print_instruction(inst);
+ }
+ }
+ }
+
+ /* now remove the instructions which aren't needed */
+ rem = remove_instructions(prog, removeInst);
+
+ _mesa_free(removeInst);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End dead code removal. %u instructions removed\n", rem);
+ /*_mesa_print_program(prog);*/
+ }
+}
+
+
+enum temp_use
+{
+ READ,
+ WRITE,
+ FLOW,
+ END
+};
+
+/**
+ * Scan forward in program from 'start' for the next occurance of TEMP[index].
+ * Return READ, WRITE, FLOW or END to indicate the next usage or an indicator
+ * that we can't look further.
+ */
+static enum temp_use
+find_next_temp_use(const struct gl_program *prog, GLuint start, GLuint index)
+{
+ GLuint i;
+
+ for (i = start; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ switch (inst->Opcode) {
+ case OPCODE_BGNLOOP:
+ case OPCODE_ENDLOOP:
+ case OPCODE_BGNSUB:
+ case OPCODE_ENDSUB:
+ return FLOW;
+ default:
+ {
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY &&
+ inst->SrcReg[j].Index == index)
+ return READ;
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY &&
+ inst->DstReg.Index == index)
+ return WRITE;
+ }
+ }
+ }
+
+ return END;
+}
+
+
+/**
+ * Try to remove extraneous MOV instructions from the given program.
+ */
+static void
+_mesa_remove_extra_moves(struct gl_program *prog)
+{
+ GLboolean *removeInst; /* per-instruction removal flag */
+ GLuint i, rem, loopNesting = 0, subroutineNesting = 0;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin remove extra moves\n");
+ _mesa_print_program(prog);
+ }
+
+ removeInst = (GLboolean *)
+ _mesa_calloc(prog->NumInstructions * sizeof(GLboolean));
+
+ /*
+ * Look for sequences such as this:
+ * FOO tmpX, arg0, arg1;
+ * MOV tmpY, tmpX;
+ * and convert into:
+ * FOO tmpY, arg0, arg1;
+ */
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+
+ switch (inst->Opcode) {
+ case OPCODE_BGNLOOP:
+ loopNesting++;
+ break;
+ case OPCODE_ENDLOOP:
+ loopNesting--;
+ break;
+ case OPCODE_BGNSUB:
+ subroutineNesting++;
+ break;
+ case OPCODE_ENDSUB:
+ subroutineNesting--;
+ break;
+ case OPCODE_MOV:
+ if (i > 0 &&
+ loopNesting == 0 &&
+ subroutineNesting == 0 &&
+ inst->SrcReg[0].File == PROGRAM_TEMPORARY &&
+ inst->SrcReg[0].Swizzle == SWIZZLE_XYZW) {
+ /* see if this MOV can be removed */
+ const GLuint tempIndex = inst->SrcReg[0].Index;
+ struct prog_instruction *prevInst;
+ GLuint prevI;
+
+ /* get pointer to previous instruction */
+ prevI = i - 1;
+ while (removeInst[prevI] && prevI > 0)
+ prevI--;
+ prevInst = prog->Instructions + prevI;
+
+ if (prevInst->DstReg.File == PROGRAM_TEMPORARY &&
+ prevInst->DstReg.Index == tempIndex &&
+ prevInst->DstReg.WriteMask == WRITEMASK_XYZW) {
+
+ enum temp_use next_use =
+ find_next_temp_use(prog, i + 1, tempIndex);
+
+ if (next_use == WRITE || next_use == END) {
+ /* OK, we can safely remove this MOV instruction.
+ * Transform:
+ * prevI: FOO tempIndex, x, y;
+ * i: MOV z, tempIndex;
+ * Into:
+ * prevI: FOO z, x, y;
+ */
+
+ /* patch up prev inst */
+ prevInst->DstReg.File = inst->DstReg.File;
+ prevInst->DstReg.Index = inst->DstReg.Index;
+
+ /* flag this instruction for removal */
+ removeInst[i] = GL_TRUE;
+
+ if (dbg) {
+ _mesa_printf("Remove MOV at %u\n", i);
+ _mesa_printf("new prev inst %u: ", prevI);
+ _mesa_print_instruction(prevInst);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ ; /* nothing */
+ }
+ }
+
+ /* now remove the instructions which aren't needed */
+ rem = remove_instructions(prog, removeInst);
+
+ if (dbg) {
+ _mesa_printf("Optimize: End remove extra moves. %u instructions removed\n", rem);
+ /*_mesa_print_program(prog);*/
+ }
+}
+
+
+/** A live register interval */
+struct interval
+{
+ GLuint Reg; /** The temporary register index */
+ GLuint Start, End; /** Start/end instruction numbers */
+};
+
+
+/** A list of register intervals */
+struct interval_list
+{
+ GLuint Num;
+ struct interval Intervals[MAX_PROGRAM_TEMPS];
+};
+
+
+static void
+append_interval(struct interval_list *list, const struct interval *inv)
+{
+ list->Intervals[list->Num++] = *inv;
+}
+
+
+/** Insert interval inv into list, sorted by interval end */
+static void
+insert_interval_by_end(struct interval_list *list, const struct interval *inv)
+{
+ /* XXX we could do a binary search insertion here since list is sorted */
+ GLint i = list->Num - 1;
+ while (i >= 0 && list->Intervals[i].End > inv->End) {
+ list->Intervals[i + 1] = list->Intervals[i];
+ i--;
+ }
+ list->Intervals[i + 1] = *inv;
+ list->Num++;
+
+#ifdef DEBUG
+ {
+ GLuint i;
+ for (i = 0; i + 1 < list->Num; i++) {
+ ASSERT(list->Intervals[i].End <= list->Intervals[i + 1].End);
+ }
+ }
+#endif
+}
+
+
+/** Remove the given interval from the interval list */
+static void
+remove_interval(struct interval_list *list, const struct interval *inv)
+{
+ /* XXX we could binary search since list is sorted */
+ GLuint k;
+ for (k = 0; k < list->Num; k++) {
+ if (list->Intervals[k].Reg == inv->Reg) {
+ /* found, remove it */
+ ASSERT(list->Intervals[k].Start == inv->Start);
+ ASSERT(list->Intervals[k].End == inv->End);
+ while (k < list->Num - 1) {
+ list->Intervals[k] = list->Intervals[k + 1];
+ k++;
+ }
+ list->Num--;
+ return;
+ }
+ }
+}
+
+
+/** called by qsort() */
+static int
+compare_start(const void *a, const void *b)
+{
+ const struct interval *ia = (const struct interval *) a;
+ const struct interval *ib = (const struct interval *) b;
+ if (ia->Start < ib->Start)
+ return -1;
+ else if (ia->Start > ib->Start)
+ return +1;
+ else
+ return 0;
+}
+
+/** sort the interval list according to interval starts */
+static void
+sort_interval_list_by_start(struct interval_list *list)
+{
+ qsort(list->Intervals, list->Num, sizeof(struct interval), compare_start);
+#ifdef DEBUG
+ {
+ GLuint i;
+ for (i = 0; i + 1 < list->Num; i++) {
+ ASSERT(list->Intervals[i].Start <= list->Intervals[i + 1].Start);
+ }
+ }
+#endif
+}
+
+
+/**
+ * Update the intermediate interval info for register 'index' and
+ * instruction 'ic'.
+ */
+static void
+update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic)
+{
+ ASSERT(index < MAX_PROGRAM_TEMPS);
+ if (intBegin[index] == -1) {
+ ASSERT(intEnd[index] == -1);
+ intBegin[index] = intEnd[index] = ic;
+ }
+ else {
+ intEnd[index] = ic;
+ }
+}
+
+
+/**
+ * Find first/last instruction that references each temporary register.
+ */
+GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS])
+{
+ struct loop_info
+ {
+ GLuint Start, End; /**< Start, end instructions of loop */
+ };
+ struct loop_info loopStack[MAX_LOOP_NESTING];
+ GLuint loopStackDepth = 0;
+ GLuint i;
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ intBegin[i] = intEnd[i] = -1;
+ }
+
+ /* Scan instructions looking for temporary registers */
+ for (i = 0; i < numInstructions; i++) {
+ const struct prog_instruction *inst = instructions + i;
+ if (inst->Opcode == OPCODE_BGNLOOP) {
+ loopStack[loopStackDepth].Start = i;
+ loopStack[loopStackDepth].End = inst->BranchTarget;
+ loopStackDepth++;
+ }
+ else if (inst->Opcode == OPCODE_ENDLOOP) {
+ loopStackDepth--;
+ }
+ else if (inst->Opcode == OPCODE_CAL) {
+ return GL_FALSE;
+ }
+ else {
+ const GLuint numSrc = 3;/*_mesa_num_inst_src_regs(inst->Opcode);*/
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->SrcReg[j].Index;
+ if (inst->SrcReg[j].RelAddr)
+ return GL_FALSE;
+ update_interval(intBegin, intEnd, index, i);
+ if (loopStackDepth > 0) {
+ /* extend temp register's interval to end of loop */
+ GLuint loopEnd = loopStack[loopStackDepth - 1].End;
+ update_interval(intBegin, intEnd, index, loopEnd);
+ }
+ }
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ const GLuint index = inst->DstReg.Index;
+ if (inst->DstReg.RelAddr)
+ return GL_FALSE;
+ update_interval(intBegin, intEnd, index, i);
+ if (loopStackDepth > 0) {
+ /* extend temp register's interval to end of loop */
+ GLuint loopEnd = loopStack[loopStackDepth - 1].End;
+ update_interval(intBegin, intEnd, index, loopEnd);
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Find the live intervals for each temporary register in the program.
+ * For register R, the interval [A,B] indicates that R is referenced
+ * from instruction A through instruction B.
+ * Special consideration is needed for loops and subroutines.
+ * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason
+ */
+static GLboolean
+find_live_intervals(struct gl_program *prog,
+ struct interval_list *liveIntervals)
+{
+ GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS];
+ GLuint i;
+
+ /*
+ * Note: we'll return GL_FALSE below if we find relative indexing
+ * into the TEMP register file. We can't handle that yet.
+ * We also give up on subroutines for now.
+ */
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin find intervals\n");
+ }
+
+ /* build intermediate arrays */
+ if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions,
+ intBegin, intEnd))
+ return GL_FALSE;
+
+ /* Build live intervals list from intermediate arrays */
+ liveIntervals->Num = 0;
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (intBegin[i] >= 0) {
+ struct interval inv;
+ inv.Reg = i;
+ inv.Start = intBegin[i];
+ inv.End = intEnd[i];
+ append_interval(liveIntervals, &inv);
+ }
+ }
+
+ /* Sort the list according to interval starts */
+ sort_interval_list_by_start(liveIntervals);
+
+ if (dbg) {
+ /* print interval info */
+ for (i = 0; i < liveIntervals->Num; i++) {
+ const struct interval *inv = liveIntervals->Intervals + i;
+ _mesa_printf("Reg[%d] live [%d, %d]:",
+ inv->Reg, inv->Start, inv->End);
+ if (1) {
+ int j;
+ for (j = 0; j < inv->Start; j++)
+ _mesa_printf(" ");
+ for (j = inv->Start; j <= inv->End; j++)
+ _mesa_printf("x");
+ }
+ _mesa_printf("\n");
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/** Scan the array of used register flags to find free entry */
+static GLint
+alloc_register(GLboolean usedRegs[MAX_PROGRAM_TEMPS])
+{
+ GLuint k;
+ for (k = 0; k < MAX_PROGRAM_TEMPS; k++) {
+ if (!usedRegs[k]) {
+ usedRegs[k] = GL_TRUE;
+ return k;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * This function implements "Linear Scan Register Allocation" to reduce
+ * the number of temporary registers used by the program.
+ *
+ * We compute the "live interval" for all temporary registers then
+ * examine the overlap of the intervals to allocate new registers.
+ * Basically, if two intervals do not overlap, they can use the same register.
+ */
+static void
+_mesa_reallocate_registers(struct gl_program *prog)
+{
+ struct interval_list liveIntervals;
+ GLint registerMap[MAX_PROGRAM_TEMPS];
+ GLboolean usedRegs[MAX_PROGRAM_TEMPS];
+ GLuint i;
+ GLint maxTemp = -1;
+
+ if (dbg) {
+ _mesa_printf("Optimize: Begin live-interval register reallocation\n");
+ _mesa_print_program(prog);
+ }
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++){
+ registerMap[i] = -1;
+ usedRegs[i] = GL_FALSE;
+ }
+
+ if (!find_live_intervals(prog, &liveIntervals)) {
+ if (dbg)
+ _mesa_printf("Aborting register reallocation\n");
+ return;
+ }
+
+ {
+ struct interval_list activeIntervals;
+ activeIntervals.Num = 0;
+
+ /* loop over live intervals, allocating a new register for each */
+ for (i = 0; i < liveIntervals.Num; i++) {
+ const struct interval *live = liveIntervals.Intervals + i;
+
+ if (dbg)
+ _mesa_printf("Consider register %u\n", live->Reg);
+
+ /* Expire old intervals. Intervals which have ended with respect
+ * to the live interval can have their remapped registers freed.
+ */
+ {
+ GLint j;
+ for (j = 0; j < activeIntervals.Num; j++) {
+ const struct interval *inv = activeIntervals.Intervals + j;
+ if (inv->End >= live->Start) {
+ /* Stop now. Since the activeInterval list is sorted
+ * we know we don't have to go further.
+ */
+ break;
+ }
+ else {
+ /* Interval 'inv' has expired */
+ const GLint regNew = registerMap[inv->Reg];
+ ASSERT(regNew >= 0);
+
+ if (dbg)
+ _mesa_printf(" expire interval for reg %u\n", inv->Reg);
+
+ /* remove interval j from active list */
+ remove_interval(&activeIntervals, inv);
+ j--; /* counter-act j++ in for-loop above */
+
+ /* return register regNew to the free pool */
+ if (dbg)
+ _mesa_printf(" free reg %d\n", regNew);
+ ASSERT(usedRegs[regNew] == GL_TRUE);
+ usedRegs[regNew] = GL_FALSE;
+ }
+ }
+ }
+
+ /* find a free register for this live interval */
+ {
+ const GLint k = alloc_register(usedRegs);
+ if (k < 0) {
+ /* out of registers, give up */
+ return;
+ }
+ registerMap[live->Reg] = k;
+ maxTemp = MAX2(maxTemp, k);
+ if (dbg)
+ _mesa_printf(" remap register %u -> %d\n", live->Reg, k);
+ }
+
+ /* Insert this live interval into the active list which is sorted
+ * by increasing end points.
+ */
+ insert_interval_by_end(&activeIntervals, live);
+ }
+ }
+
+ if (maxTemp + 1 < liveIntervals.Num) {
+ /* OK, we've reduced the number of registers needed.
+ * Scan the program and replace all the old temporary register
+ * indexes with the new indexes.
+ */
+ replace_regs(prog, PROGRAM_TEMPORARY, registerMap);
+
+ prog->NumTemporaries = maxTemp + 1;
+ }
+
+ if (dbg) {
+ _mesa_printf("Optimize: End live-interval register reallocation\n");
+ _mesa_printf("Num temp regs before: %u after: %u\n",
+ liveIntervals.Num, maxTemp + 1);
+ _mesa_print_program(prog);
+ }
+}
+
+
+/**
+ * Apply optimizations to the given program to eliminate unnecessary
+ * instructions, temp regs, etc.
+ */
+void
+_mesa_optimize_program(GLcontext *ctx, struct gl_program *program)
+{
+ if (1)
+ _mesa_remove_dead_code(program);
+
+ if (0) /* not tested much yet */
+ _mesa_remove_extra_moves(program);
+
+ if (0)
+ _mesa_consolidate_registers(program);
+ else
+ _mesa_reallocate_registers(program);
+}
diff --git a/mesalib/src/mesa/shader/prog_optimize.h b/mesalib/src/mesa/shader/prog_optimize.h
new file mode 100644
index 000000000..43894a272
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_optimize.h
@@ -0,0 +1,45 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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
+ * VMWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 PROG_OPT_H
+#define PROG_OPT_H
+
+
+#include "main/config.h"
+
+
+struct gl_program;
+struct prog_instruction;
+
+
+extern GLboolean
+_mesa_find_temp_intervals(const struct prog_instruction *instructions,
+ GLuint numInstructions,
+ GLint intBegin[MAX_PROGRAM_TEMPS],
+ GLint intEnd[MAX_PROGRAM_TEMPS]);
+
+extern void
+_mesa_optimize_program(GLcontext *ctx, struct gl_program *program);
+
+#endif
diff --git a/mesalib/src/mesa/shader/prog_parameter.c b/mesalib/src/mesa/shader/prog_parameter.c
new file mode 100644
index 000000000..2f029b02e
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_parameter.c
@@ -0,0 +1,750 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file prog_parameter.c
+ * Program parameter lists and functions.
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_statevars.h"
+
+
+struct gl_program_parameter_list *
+_mesa_new_parameter_list(void)
+{
+ return CALLOC_STRUCT(gl_program_parameter_list);
+}
+
+
+struct gl_program_parameter_list *
+_mesa_new_parameter_list_sized(unsigned size)
+{
+ struct gl_program_parameter_list *p = _mesa_new_parameter_list();
+
+ if ((p != NULL) && (size != 0)) {
+ p->Size = size;
+
+ /* alloc arrays */
+ p->Parameters = (struct gl_program_parameter *)
+ _mesa_calloc(size * sizeof(struct gl_program_parameter));
+
+ p->ParameterValues = (GLfloat (*)[4])
+ _mesa_align_malloc(size * 4 *sizeof(GLfloat), 16);
+
+
+ if ((p->Parameters == NULL) || (p->ParameterValues == NULL)) {
+ _mesa_free(p->Parameters);
+ _mesa_align_free(p->ParameterValues);
+ _mesa_free(p);
+ p = NULL;
+ }
+ }
+
+ return p;
+}
+
+
+/**
+ * Free a parameter list and all its parameters
+ */
+void
+_mesa_free_parameter_list(struct gl_program_parameter_list *paramList)
+{
+ GLuint i;
+ for (i = 0; i < paramList->NumParameters; i++) {
+ if (paramList->Parameters[i].Name)
+ _mesa_free((void *) paramList->Parameters[i].Name);
+ }
+ _mesa_free(paramList->Parameters);
+ if (paramList->ParameterValues)
+ _mesa_align_free(paramList->ParameterValues);
+ _mesa_free(paramList);
+}
+
+
+/**
+ * Add a new parameter to a parameter list.
+ * Note that parameter values are usually 4-element GLfloat vectors.
+ * When size > 4 we'll allocate a sequential block of parameters to
+ * store all the values (in blocks of 4).
+ *
+ * \param paramList the list to add the parameter to
+ * \param type type of parameter, such as
+ * \param name the parameter name, will be duplicated/copied!
+ * \param size number of elements in 'values' vector (1..4, or more)
+ * \param datatype GL_FLOAT, GL_FLOAT_VECx, GL_INT, GL_INT_VECx or GL_NONE.
+ * \param values initial parameter value, up to 4 GLfloats, or NULL
+ * \param state state indexes, or NULL
+ * \return index of new parameter in the list, or -1 if error (out of mem)
+ */
+GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+ gl_register_file type, const char *name,
+ GLuint size, GLenum datatype, const GLfloat *values,
+ const gl_state_index state[STATE_LENGTH],
+ GLbitfield flags)
+{
+ const GLuint oldNum = paramList->NumParameters;
+ const GLuint sz4 = (size + 3) / 4; /* no. of new param slots needed */
+
+ assert(size > 0);
+
+ if (oldNum + sz4 > paramList->Size) {
+ /* Need to grow the parameter list array (alloc some extra) */
+ paramList->Size = paramList->Size + 4 * sz4;
+
+ /* realloc arrays */
+ paramList->Parameters = (struct gl_program_parameter *)
+ _mesa_realloc(paramList->Parameters,
+ oldNum * sizeof(struct gl_program_parameter),
+ paramList->Size * sizeof(struct gl_program_parameter));
+
+ paramList->ParameterValues = (GLfloat (*)[4])
+ _mesa_align_realloc(paramList->ParameterValues, /* old buf */
+ oldNum * 4 * sizeof(GLfloat), /* old size */
+ paramList->Size * 4 *sizeof(GLfloat), /* new sz */
+ 16);
+ }
+
+ if (!paramList->Parameters ||
+ !paramList->ParameterValues) {
+ /* out of memory */
+ paramList->NumParameters = 0;
+ paramList->Size = 0;
+ return -1;
+ }
+ else {
+ GLuint i;
+
+ paramList->NumParameters = oldNum + sz4;
+
+ _mesa_memset(&paramList->Parameters[oldNum], 0,
+ sz4 * sizeof(struct gl_program_parameter));
+
+ for (i = 0; i < sz4; i++) {
+ struct gl_program_parameter *p = paramList->Parameters + oldNum + i;
+ p->Name = name ? _mesa_strdup(name) : NULL;
+ p->Type = type;
+ p->Size = size;
+ p->DataType = datatype;
+ p->Flags = flags;
+ if (values) {
+ COPY_4V(paramList->ParameterValues[oldNum + i], values);
+ values += 4;
+ p->Initialized = GL_TRUE;
+ }
+ else {
+ /* silence valgrind */
+ ASSIGN_4V(paramList->ParameterValues[oldNum + i], 0, 0, 0, 0);
+ }
+ size -= 4;
+ }
+
+ if (state) {
+ for (i = 0; i < STATE_LENGTH; i++)
+ paramList->Parameters[oldNum].StateIndexes[i] = state[i];
+ }
+
+ return (GLint) oldNum;
+ }
+}
+
+
+/**
+ * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement)
+ * \return index of the new entry in the parameter list
+ */
+GLint
+_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4])
+{
+ return _mesa_add_parameter(paramList, PROGRAM_NAMED_PARAM, name,
+ 4, GL_NONE, values, NULL, 0x0);
+
+}
+
+
+/**
+ * Add a new named constant to the parameter list.
+ * This will be used when the program contains something like this:
+ * PARAM myVals = { 0, 1, 2, 3 };
+ *
+ * \param paramList the parameter list
+ * \param name the name for the constant
+ * \param values four float values
+ * \return index/position of the new parameter in the parameter list
+ */
+GLint
+_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4],
+ GLuint size)
+{
+ /* first check if this is a duplicate constant */
+ GLint pos;
+ for (pos = 0; pos < paramList->NumParameters; pos++) {
+ const GLfloat *pvals = paramList->ParameterValues[pos];
+ if (pvals[0] == values[0] &&
+ pvals[1] == values[1] &&
+ pvals[2] == values[2] &&
+ pvals[3] == values[3] &&
+ _mesa_strcmp(paramList->Parameters[pos].Name, name) == 0) {
+ /* Same name and value is already in the param list - reuse it */
+ return pos;
+ }
+ }
+ /* not found, add new parameter */
+ return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name,
+ size, GL_NONE, values, NULL, 0x0);
+}
+
+
+/**
+ * Add a new unnamed constant to the parameter list. This will be used
+ * when a fragment/vertex program contains something like this:
+ * MOV r, { 0, 1, 2, 3 };
+ * We'll search the parameter list for an existing instance of the
+ * constant. If swizzleOut is non-null, we'll try swizzling when
+ * looking for a match.
+ *
+ * \param paramList the parameter list
+ * \param values four float values
+ * \param swizzleOut returns swizzle mask for accessing the constant
+ * \return index/position of the new parameter in the parameter list.
+ */
+GLint
+_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+ const GLfloat values[4], GLuint size,
+ GLuint *swizzleOut)
+{
+ GLint pos;
+ ASSERT(size >= 1);
+ ASSERT(size <= 4);
+
+ if (_mesa_lookup_parameter_constant(paramList, values,
+ size, &pos, swizzleOut)) {
+ return pos;
+ }
+
+ /* Look for empty space in an already unnamed constant parameter
+ * to add this constant. This will only work for single-element
+ * constants because we rely on smearing (i.e. .yyyy or .zzzz).
+ */
+ if (size == 1 && swizzleOut) {
+ for (pos = 0; pos < (GLint) paramList->NumParameters; pos++) {
+ struct gl_program_parameter *p = paramList->Parameters + pos;
+ if (p->Type == PROGRAM_CONSTANT && p->Size + size <= 4) {
+ /* ok, found room */
+ GLfloat *pVal = paramList->ParameterValues[pos];
+ GLuint swz = p->Size; /* 1, 2 or 3 for Y, Z, W */
+ pVal[p->Size] = values[0];
+ p->Size++;
+ *swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz);
+ return pos;
+ }
+ }
+ }
+
+ /* add a new parameter to store this constant */
+ pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
+ size, GL_NONE, values, NULL, 0x0);
+ if (pos >= 0 && swizzleOut) {
+ if (size == 1)
+ *swizzleOut = SWIZZLE_XXXX;
+ else
+ *swizzleOut = SWIZZLE_NOOP;
+ }
+ return pos;
+}
+
+
+/**
+ * Add a uniform to the parameter list.
+ * Note that if the uniform is an array, size may be greater than
+ * what's implied by the datatype.
+ * \param name uniform's name
+ * \param size number of floats to allocate
+ * \param datatype GL_FLOAT_VEC3, GL_FLOAT_MAT4, etc.
+ */
+GLint
+_mesa_add_uniform(struct gl_program_parameter_list *paramList,
+ const char *name, GLuint size, GLenum datatype,
+ const GLfloat *values)
+{
+ GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+ ASSERT(datatype != GL_NONE);
+ if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) {
+ ASSERT(paramList->Parameters[i].Size == size);
+ ASSERT(paramList->Parameters[i].DataType == datatype);
+ /* already in list */
+ return i;
+ }
+ else {
+ i = _mesa_add_parameter(paramList, PROGRAM_UNIFORM, name,
+ size, datatype, values, NULL, 0x0);
+ return i;
+ }
+}
+
+
+/**
+ * Mark the named uniform as 'used'.
+ */
+void
+_mesa_use_uniform(struct gl_program_parameter_list *paramList,
+ const char *name)
+{
+ GLuint i;
+ for (i = 0; i < paramList->NumParameters; i++) {
+ struct gl_program_parameter *p = paramList->Parameters + i;
+ if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER) &&
+ _mesa_strcmp(p->Name, name) == 0) {
+ p->Used = GL_TRUE;
+ /* Note that large uniforms may occupy several slots so we're
+ * not done searching yet.
+ */
+ }
+ }
+}
+
+
+/**
+ * Add a sampler to the parameter list.
+ * \param name uniform's name
+ * \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc.
+ * \param index the sampler number (as seen in TEX instructions)
+ * \return sampler index (starting at zero) or -1 if error
+ */
+GLint
+_mesa_add_sampler(struct gl_program_parameter_list *paramList,
+ const char *name, GLenum datatype)
+{
+ GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+ if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) {
+ ASSERT(paramList->Parameters[i].Size == 1);
+ ASSERT(paramList->Parameters[i].DataType == datatype);
+ /* already in list */
+ return (GLint) paramList->ParameterValues[i][0];
+ }
+ else {
+ GLuint i;
+ const GLint size = 1; /* a sampler is basically a texture unit number */
+ GLfloat value[4];
+ GLint numSamplers = 0;
+ for (i = 0; i < paramList->NumParameters; i++) {
+ if (paramList->Parameters[i].Type == PROGRAM_SAMPLER)
+ numSamplers++;
+ }
+ value[0] = (GLfloat) numSamplers;
+ value[1] = value[2] = value[3] = 0.0F;
+ (void) _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name,
+ size, datatype, value, NULL, 0x0);
+ return numSamplers;
+ }
+}
+
+
+/**
+ * Add parameter representing a varying variable.
+ */
+GLint
+_mesa_add_varying(struct gl_program_parameter_list *paramList,
+ const char *name, GLuint size, GLbitfield flags)
+{
+ GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+ if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) {
+ /* already in list */
+ return i;
+ }
+ else {
+ /*assert(size == 4);*/
+ i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name,
+ size, GL_NONE, NULL, NULL, flags);
+ return i;
+ }
+}
+
+
+/**
+ * Add parameter representing a vertex program attribute.
+ * \param size size of attribute (in floats), may be -1 if unknown
+ * \param attrib the attribute index, or -1 if unknown
+ */
+GLint
+_mesa_add_attribute(struct gl_program_parameter_list *paramList,
+ const char *name, GLint size, GLenum datatype, GLint attrib)
+{
+ GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
+ if (i >= 0) {
+ /* replace */
+ if (attrib < 0)
+ attrib = i;
+ paramList->Parameters[i].StateIndexes[0] = attrib;
+ }
+ else {
+ /* add */
+ gl_state_index state[STATE_LENGTH];
+ state[0] = (gl_state_index) attrib;
+ if (size < 0)
+ size = 4;
+ i = _mesa_add_parameter(paramList, PROGRAM_INPUT, name,
+ size, datatype, NULL, state, 0x0);
+ }
+ return i;
+}
+
+
+
+#if 0 /* not used yet */
+/**
+ * Returns the number of 4-component registers needed to store a piece
+ * of GL state. For matrices this may be as many as 4 registers,
+ * everything else needs
+ * just 1 register.
+ */
+static GLuint
+sizeof_state_reference(const GLint *stateTokens)
+{
+ if (stateTokens[0] == STATE_MATRIX) {
+ GLuint rows = stateTokens[4] - stateTokens[3] + 1;
+ assert(rows >= 1);
+ assert(rows <= 4);
+ return rows;
+ }
+ else {
+ return 1;
+ }
+}
+#endif
+
+
+/**
+ * Add a new state reference to the parameter list.
+ * This will be used when the program contains something like this:
+ * PARAM ambient = state.material.front.ambient;
+ *
+ * \param paramList the parameter list
+ * \param stateTokens an array of 5 (STATE_LENGTH) state tokens
+ * \return index of the new parameter.
+ */
+GLint
+_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
+ const gl_state_index stateTokens[STATE_LENGTH])
+{
+ const GLuint size = 4; /* XXX fix */
+ char *name;
+ GLint index;
+
+ /* Check if the state reference is already in the list */
+ for (index = 0; index < (GLint) paramList->NumParameters; index++) {
+ GLuint i, match = 0;
+ for (i = 0; i < STATE_LENGTH; i++) {
+ if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) {
+ match++;
+ }
+ else {
+ break;
+ }
+ }
+ if (match == STATE_LENGTH) {
+ /* this state reference is already in the parameter list */
+ return index;
+ }
+ }
+
+ name = _mesa_program_state_string(stateTokens);
+ index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name,
+ size, GL_NONE,
+ NULL, (gl_state_index *) stateTokens, 0x0);
+ paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
+
+ /* free name string here since we duplicated it in add_parameter() */
+ _mesa_free(name);
+
+ return index;
+}
+
+
+/**
+ * Lookup a parameter value by name in the given parameter list.
+ * \return pointer to the float[4] values.
+ */
+GLfloat *
+_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
+ GLsizei nameLen, const char *name)
+{
+ GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name);
+ if (i < 0)
+ return NULL;
+ else
+ return paramList->ParameterValues[i];
+}
+
+
+/**
+ * Given a program parameter name, find its position in the list of parameters.
+ * \param paramList the parameter list to search
+ * \param nameLen length of name (in chars).
+ * If length is negative, assume that name is null-terminated.
+ * \param name the name to search for
+ * \return index of parameter in the list.
+ */
+GLint
+_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
+ GLsizei nameLen, const char *name)
+{
+ GLint i;
+
+ if (!paramList)
+ return -1;
+
+ if (nameLen == -1) {
+ /* name is null-terminated */
+ for (i = 0; i < (GLint) paramList->NumParameters; i++) {
+ if (paramList->Parameters[i].Name &&
+ _mesa_strcmp(paramList->Parameters[i].Name, name) == 0)
+ return i;
+ }
+ }
+ else {
+ /* name is not null-terminated, use nameLen */
+ for (i = 0; i < (GLint) paramList->NumParameters; i++) {
+ if (paramList->Parameters[i].Name &&
+ _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
+ && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Look for a float vector in the given parameter list. The float vector
+ * may be of length 1, 2, 3 or 4. If swizzleOut is non-null, we'll try
+ * swizzling to find a match.
+ * \param list the parameter list to search
+ * \param v the float vector to search for
+ * \param vSize number of element in v
+ * \param posOut returns the position of the constant, if found
+ * \param swizzleOut returns a swizzle mask describing location of the
+ * vector elements if found.
+ * \return GL_TRUE if found, GL_FALSE if not found
+ */
+GLboolean
+_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
+ const GLfloat v[], GLuint vSize,
+ GLint *posOut, GLuint *swizzleOut)
+{
+ GLuint i;
+
+ assert(vSize >= 1);
+ assert(vSize <= 4);
+
+ if (!list)
+ return -1;
+
+ for (i = 0; i < list->NumParameters; i++) {
+ if (list->Parameters[i].Type == PROGRAM_CONSTANT) {
+ if (!swizzleOut) {
+ /* swizzle not allowed */
+ GLuint j, match = 0;
+ for (j = 0; j < vSize; j++) {
+ if (v[j] == list->ParameterValues[i][j])
+ match++;
+ }
+ if (match == vSize) {
+ *posOut = i;
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* try matching w/ swizzle */
+ if (vSize == 1) {
+ /* look for v[0] anywhere within float[4] value */
+ GLuint j;
+ for (j = 0; j < 4; j++) {
+ if (list->ParameterValues[i][j] == v[0]) {
+ /* found it */
+ *posOut = i;
+ *swizzleOut = MAKE_SWIZZLE4(j, j, j, j);
+ return GL_TRUE;
+ }
+ }
+ }
+ else if (vSize <= list->Parameters[i].Size) {
+ /* see if we can match this constant (with a swizzle) */
+ GLuint swz[4];
+ GLuint match = 0, j, k;
+ for (j = 0; j < vSize; j++) {
+ if (v[j] == list->ParameterValues[i][j]) {
+ swz[j] = j;
+ match++;
+ }
+ else {
+ for (k = 0; k < list->Parameters[i].Size; k++) {
+ if (v[j] == list->ParameterValues[i][k]) {
+ swz[j] = k;
+ match++;
+ break;
+ }
+ }
+ }
+ }
+ /* smear last value to remaining positions */
+ for (; j < 4; j++)
+ swz[j] = swz[j-1];
+
+ if (match == vSize) {
+ *posOut = i;
+ *swizzleOut = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+ return GL_TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ *posOut = -1;
+ return GL_FALSE;
+}
+
+
+struct gl_program_parameter_list *
+_mesa_clone_parameter_list(const struct gl_program_parameter_list *list)
+{
+ struct gl_program_parameter_list *clone;
+ GLuint i;
+
+ clone = _mesa_new_parameter_list();
+ if (!clone)
+ return NULL;
+
+ /** Not too efficient, but correct */
+ for (i = 0; i < list->NumParameters; i++) {
+ struct gl_program_parameter *p = list->Parameters + i;
+ struct gl_program_parameter *pCopy;
+ GLuint size = MIN2(p->Size, 4);
+ GLint j = _mesa_add_parameter(clone, p->Type, p->Name, size, p->DataType,
+ list->ParameterValues[i], NULL, 0x0);
+ ASSERT(j >= 0);
+ pCopy = clone->Parameters + j;
+ pCopy->Used = p->Used;
+ pCopy->Flags = p->Flags;
+ /* copy state indexes */
+ if (p->Type == PROGRAM_STATE_VAR) {
+ GLint k;
+ for (k = 0; k < STATE_LENGTH; k++) {
+ pCopy->StateIndexes[k] = p->StateIndexes[k];
+ }
+ }
+ else {
+ clone->Parameters[j].Size = p->Size;
+ }
+
+ }
+
+ clone->StateFlags = list->StateFlags;
+
+ return clone;
+}
+
+
+/**
+ * Return a new parameter list which is listA + listB.
+ */
+struct gl_program_parameter_list *
+_mesa_combine_parameter_lists(const struct gl_program_parameter_list *listA,
+ const struct gl_program_parameter_list *listB)
+{
+ struct gl_program_parameter_list *list;
+
+ if (listA) {
+ list = _mesa_clone_parameter_list(listA);
+ if (list && listB) {
+ GLuint i;
+ for (i = 0; i < listB->NumParameters; i++) {
+ struct gl_program_parameter *param = listB->Parameters + i;
+ _mesa_add_parameter(list, param->Type, param->Name, param->Size,
+ param->DataType,
+ listB->ParameterValues[i],
+ param->StateIndexes,
+ param->Flags);
+ }
+ }
+ }
+ else if (listB) {
+ list = _mesa_clone_parameter_list(listB);
+ }
+ else {
+ list = NULL;
+ }
+ return list;
+}
+
+
+
+/**
+ * Find longest name of all uniform parameters in list.
+ */
+GLuint
+_mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
+ gl_register_file type)
+{
+ GLuint i, maxLen = 0;
+ if (!list)
+ return 0;
+ for (i = 0; i < list->NumParameters; i++) {
+ if (list->Parameters[i].Type == type) {
+ GLuint len = _mesa_strlen(list->Parameters[i].Name);
+ if (len > maxLen)
+ maxLen = len;
+ }
+ }
+ return maxLen;
+}
+
+
+/**
+ * Count the number of parameters in the last that match the given type.
+ */
+GLuint
+_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
+ gl_register_file type)
+{
+ GLuint i, count = 0;
+ if (list) {
+ for (i = 0; i < list->NumParameters; i++) {
+ if (list->Parameters[i].Type == type)
+ count++;
+ }
+ }
+ return count;
+}
diff --git a/mesalib/src/mesa/shader/prog_parameter.h b/mesalib/src/mesa/shader/prog_parameter.h
new file mode 100644
index 000000000..d1fcf47e6
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_parameter.h
@@ -0,0 +1,174 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file prog_parameter.c
+ * Program parameter lists and functions.
+ * \author Brian Paul
+ */
+
+#ifndef PROG_PARAMETER_H
+#define PROG_PARAMETER_H
+
+#include "main/mtypes.h"
+#include "prog_statevars.h"
+
+
+/**
+ * Program parameter flags
+ */
+/*@{*/
+#define PROG_PARAM_BIT_CENTROID 0x1 /**< for varying vars (GLSL 1.20) */
+#define PROG_PARAM_BIT_INVARIANT 0x2 /**< for varying vars (GLSL 1.20) */
+#define PROG_PARAM_BIT_FLAT 0x4 /**< for varying vars (GLSL 1.30) */
+#define PROG_PARAM_BIT_LINEAR 0x8 /**< for varying vars (GLSL 1.30) */
+/*@}*/
+
+
+
+/**
+ * Program parameter.
+ * Used by shaders/programs for uniforms, constants, varying vars, etc.
+ */
+struct gl_program_parameter
+{
+ const char *Name; /**< Null-terminated string */
+ gl_register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */
+ GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
+ GLuint Size; /**< Number of components (1..4) */
+ GLboolean Used; /**< Helper flag for GLSL uniform tracking */
+ GLboolean Initialized; /**< Has the ParameterValue[] been set? */
+ GLbitfield Flags; /**< Bitmask of PROG_PARAM_*_BIT */
+ /**
+ * A sequence of STATE_* tokens and integers to identify GL state.
+ */
+ gl_state_index StateIndexes[STATE_LENGTH];
+};
+
+
+/**
+ * List of gl_program_parameter instances.
+ */
+struct gl_program_parameter_list
+{
+ GLuint Size; /**< allocated size of Parameters, ParameterValues */
+ GLuint NumParameters; /**< number of parameters in arrays */
+ struct gl_program_parameter *Parameters; /**< Array [Size] */
+ GLfloat (*ParameterValues)[4]; /**< Array [Size] of GLfloat[4] */
+ GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes
+ might invalidate ParameterValues[] */
+};
+
+
+extern struct gl_program_parameter_list *
+_mesa_new_parameter_list(void);
+
+extern struct gl_program_parameter_list *
+_mesa_new_parameter_list_sized(unsigned size);
+
+extern void
+_mesa_free_parameter_list(struct gl_program_parameter_list *paramList);
+
+extern struct gl_program_parameter_list *
+_mesa_clone_parameter_list(const struct gl_program_parameter_list *list);
+
+extern struct gl_program_parameter_list *
+_mesa_combine_parameter_lists(const struct gl_program_parameter_list *a,
+ const struct gl_program_parameter_list *b);
+
+static INLINE GLuint
+_mesa_num_parameters(const struct gl_program_parameter_list *list)
+{
+ return list ? list->NumParameters : 0;
+}
+
+extern GLint
+_mesa_add_parameter(struct gl_program_parameter_list *paramList,
+ gl_register_file type, const char *name,
+ GLuint size, GLenum datatype, const GLfloat *values,
+ const gl_state_index state[STATE_LENGTH],
+ GLbitfield flags);
+
+extern GLint
+_mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4]);
+
+extern GLint
+_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
+ const char *name, const GLfloat values[4],
+ GLuint size);
+
+extern GLint
+_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
+ const GLfloat values[4], GLuint size,
+ GLuint *swizzleOut);
+
+extern GLint
+_mesa_add_uniform(struct gl_program_parameter_list *paramList,
+ const char *name, GLuint size, GLenum datatype,
+ const GLfloat *values);
+
+extern void
+_mesa_use_uniform(struct gl_program_parameter_list *paramList,
+ const char *name);
+
+extern GLint
+_mesa_add_sampler(struct gl_program_parameter_list *paramList,
+ const char *name, GLenum datatype);
+
+extern GLint
+_mesa_add_varying(struct gl_program_parameter_list *paramList,
+ const char *name, GLuint size, GLbitfield flags);
+
+extern GLint
+_mesa_add_attribute(struct gl_program_parameter_list *paramList,
+ const char *name, GLint size, GLenum datatype, GLint attrib);
+
+extern GLint
+_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
+ const gl_state_index stateTokens[STATE_LENGTH]);
+
+extern GLfloat *
+_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
+ GLsizei nameLen, const char *name);
+
+extern GLint
+_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
+ GLsizei nameLen, const char *name);
+
+extern GLboolean
+_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
+ const GLfloat v[], GLuint vSize,
+ GLint *posOut, GLuint *swizzleOut);
+
+extern GLuint
+_mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
+ gl_register_file type);
+
+extern GLuint
+_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
+ gl_register_file type);
+
+
+#endif /* PROG_PARAMETER_H */
diff --git a/mesalib/src/mesa/shader/prog_parameter_layout.c b/mesalib/src/mesa/shader/prog_parameter_layout.c
new file mode 100644
index 000000000..1c37b3a7a
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_parameter_layout.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter_layout.c
+ * \brief Helper functions to layout storage for program parameters
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#include "main/mtypes.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+unsigned
+_mesa_combine_swizzles(unsigned base, unsigned applied)
+{
+ unsigned swiz = 0;
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ const unsigned s = GET_SWZ(applied, i);
+
+ swiz |= ((s <= SWIZZLE_W) ? GET_SWZ(base, s) : s) << (i * 3);
+ }
+
+ return swiz;
+}
+
+
+/**
+ * Copy indirect access array from one parameter list to another
+ *
+ * \param src Parameter array copied from
+ * \param dst Parameter array copied to
+ * \param first Index of first element in \c src to copy
+ * \param count Number of elements to copy
+ *
+ * \return
+ * The location in \c dst of the first element copied from \c src on
+ * success. -1 on failure.
+ *
+ * \warning
+ * This function assumes that there is already enough space available in
+ * \c dst to hold all of the elements that will be copied over.
+ */
+static int
+copy_indirect_accessed_array(struct gl_program_parameter_list *src,
+ struct gl_program_parameter_list *dst,
+ unsigned first, unsigned count)
+{
+ const int base = dst->NumParameters;
+ unsigned i;
+ unsigned j;
+
+
+ for (i = first; i < (first + count); i++) {
+ struct gl_program_parameter *curr = & src->Parameters[i];
+
+
+ if (curr->Type == PROGRAM_CONSTANT) {
+ j = dst->NumParameters;
+ } else {
+ for (j = 0; j < dst->NumParameters; j++) {
+ if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes,
+ sizeof(curr->StateIndexes)) == 0) {
+ return -1;
+ }
+ }
+ }
+
+ assert(j == dst->NumParameters);
+
+ memcpy(& dst->Parameters[j], curr,
+ sizeof(dst->Parameters[j]));
+ memcpy(dst->ParameterValues[j], src->ParameterValues[i],
+ sizeof(GLfloat) * 4);
+ curr->Name = NULL;
+
+ dst->NumParameters++;
+ }
+
+ return base;
+}
+
+
+/**
+ * XXX description???
+ * \return GL_TRUE for success, GL_FALSE for failure
+ */
+GLboolean
+_mesa_layout_parameters(struct asm_parser_state *state)
+{
+ struct gl_program_parameter_list *layout;
+ struct asm_instruction *inst;
+ unsigned i;
+
+
+ layout =
+ _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters);
+
+
+ /* PASS 1: Move any parameters that are accessed indirectly from the
+ * original parameter list to the new parameter list.
+ */
+ for (inst = state->inst_head; inst != NULL; inst = inst->next) {
+ for (i = 0; i < 3; i++) {
+ if (inst->SrcReg[i].Base.RelAddr) {
+ /* Only attempt to add the to the new parameter list once.
+ */
+ if (!inst->SrcReg[i].Symbol->pass1_done) {
+ const int new_begin =
+ copy_indirect_accessed_array(state->prog->Parameters, layout,
+ inst->SrcReg[i].Symbol->param_binding_begin,
+ inst->SrcReg[i].Symbol->param_binding_length);
+
+ if (new_begin < 0) {
+ return GL_FALSE;
+ }
+
+ inst->SrcReg[i].Symbol->param_binding_begin = new_begin;
+ inst->SrcReg[i].Symbol->pass1_done = 1;
+ }
+
+ /* Previously the Index was just the offset from the parameter
+ * array. Now that the base of the parameter array is known, the
+ * index can be updated to its actual value.
+ */
+ inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
+ inst->Base.SrcReg[i].Index +=
+ inst->SrcReg[i].Symbol->param_binding_begin;
+ }
+ }
+ }
+
+
+ /* PASS 2: Move any parameters that are not accessed indirectly from the
+ * original parameter list to the new parameter list.
+ */
+ for (inst = state->inst_head; inst != NULL; inst = inst->next) {
+ for (i = 0; i < 3; i++) {
+ const struct gl_program_parameter *p;
+ const int idx = inst->SrcReg[i].Base.Index;
+ unsigned swizzle = SWIZZLE_NOOP;
+
+
+ /* All relative addressed operands were processed on the first
+ * pass. Just skip them here.
+ */
+ if (inst->SrcReg[i].Base.RelAddr) {
+ continue;
+ }
+
+
+ if ((inst->SrcReg[i].Base.File <= PROGRAM_VARYING )
+ || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) {
+ continue;
+ }
+
+ inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
+ p = & state->prog->Parameters->Parameters[idx];
+
+ switch (p->Type) {
+ case PROGRAM_CONSTANT: {
+ const float *const v =
+ state->prog->Parameters->ParameterValues[idx];
+
+ inst->Base.SrcReg[i].Index =
+ _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle);
+
+ inst->Base.SrcReg[i].Swizzle =
+ _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle);
+ break;
+ }
+
+ case PROGRAM_STATE_VAR:
+ inst->Base.SrcReg[i].Index =
+ _mesa_add_state_reference(layout, p->StateIndexes);
+ break;
+
+ default:
+ break;
+ }
+
+ inst->SrcReg[i].Base.File = p->Type;
+ inst->Base.SrcReg[i].File = p->Type;
+ }
+ }
+
+
+ _mesa_free_parameter_list(state->prog->Parameters);
+ state->prog->Parameters = layout;
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/shader/prog_parameter_layout.h b/mesalib/src/mesa/shader/prog_parameter_layout.h
new file mode 100644
index 000000000..99a7b6c72
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_parameter_layout.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file prog_parameter_layout.h
+ * \brief Helper functions to layout storage for program parameters
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+#pragma once
+
+#ifndef PROG_PARAMETER_LAYOUT_H
+#define PROG_PARAMETER_LAYOUT_H
+
+extern unsigned _mesa_combine_swizzles(unsigned base, unsigned applied);
+
+struct asm_parser_state;
+
+extern GLboolean _mesa_layout_parameters(struct asm_parser_state *state);
+
+#endif /* PROG_PARAMETER_LAYOUT_H */
diff --git a/mesalib/src/mesa/shader/prog_print.c b/mesalib/src/mesa/shader/prog_print.c
new file mode 100644
index 000000000..b71735aa8
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_print.c
@@ -0,0 +1,1019 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file prog_print.c
+ * Print vertex/fragment programs - for debugging.
+ * \author Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+#include "prog_statevars.h"
+
+
+
+/**
+ * Return string name for given program/register file.
+ */
+static const char *
+file_string(gl_register_file f, gl_prog_print_mode mode)
+{
+ switch (f) {
+ case PROGRAM_TEMPORARY:
+ return "TEMP";
+ case PROGRAM_LOCAL_PARAM:
+ return "LOCAL";
+ case PROGRAM_ENV_PARAM:
+ return "ENV";
+ case PROGRAM_STATE_VAR:
+ return "STATE";
+ case PROGRAM_INPUT:
+ return "INPUT";
+ case PROGRAM_OUTPUT:
+ return "OUTPUT";
+ case PROGRAM_NAMED_PARAM:
+ return "NAMED";
+ case PROGRAM_CONSTANT:
+ return "CONST";
+ case PROGRAM_UNIFORM:
+ return "UNIFORM";
+ case PROGRAM_VARYING:
+ return "VARYING";
+ case PROGRAM_WRITE_ONLY:
+ return "WRITE_ONLY";
+ case PROGRAM_ADDRESS:
+ return "ADDR";
+ case PROGRAM_SAMPLER:
+ return "SAMPLER";
+ case PROGRAM_UNDEFINED:
+ return "UNDEFINED";
+ default:
+ {
+ static char s[20];
+ _mesa_snprintf(s, sizeof(s), "FILE%u", f);
+ return s;
+ }
+ }
+}
+
+
+/**
+ * Return ARB_v/f_prog-style input attrib string.
+ */
+static const char *
+arb_input_attrib_string(GLint index, GLenum progType)
+{
+ /*
+ * These strings should match the VERT_ATTRIB_x and FRAG_ATTRIB_x tokens.
+ */
+ const char *vertAttribs[] = {
+ "vertex.position",
+ "vertex.weight",
+ "vertex.normal",
+ "vertex.color.primary",
+ "vertex.color.secondary",
+ "vertex.fogcoord",
+ "vertex.(six)",
+ "vertex.(seven)",
+ "vertex.texcoord[0]",
+ "vertex.texcoord[1]",
+ "vertex.texcoord[2]",
+ "vertex.texcoord[3]",
+ "vertex.texcoord[4]",
+ "vertex.texcoord[5]",
+ "vertex.texcoord[6]",
+ "vertex.texcoord[7]",
+ "vertex.attrib[0]",
+ "vertex.attrib[1]",
+ "vertex.attrib[2]",
+ "vertex.attrib[3]",
+ "vertex.attrib[4]",
+ "vertex.attrib[5]",
+ "vertex.attrib[6]",
+ "vertex.attrib[7]",
+ "vertex.attrib[8]",
+ "vertex.attrib[9]",
+ "vertex.attrib[10]",
+ "vertex.attrib[11]",
+ "vertex.attrib[12]",
+ "vertex.attrib[13]",
+ "vertex.attrib[14]",
+ "vertex.attrib[15]"
+ };
+ const char *fragAttribs[] = {
+ "fragment.position",
+ "fragment.color.primary",
+ "fragment.color.secondary",
+ "fragment.fogcoord",
+ "fragment.texcoord[0]",
+ "fragment.texcoord[1]",
+ "fragment.texcoord[2]",
+ "fragment.texcoord[3]",
+ "fragment.texcoord[4]",
+ "fragment.texcoord[5]",
+ "fragment.texcoord[6]",
+ "fragment.texcoord[7]",
+ "fragment.varying[0]",
+ "fragment.varying[1]",
+ "fragment.varying[2]",
+ "fragment.varying[3]",
+ "fragment.varying[4]",
+ "fragment.varying[5]",
+ "fragment.varying[6]",
+ "fragment.varying[7]"
+ };
+
+ if (progType == GL_VERTEX_PROGRAM_ARB) {
+ assert(index < sizeof(vertAttribs) / sizeof(vertAttribs[0]));
+ return vertAttribs[index];
+ }
+ else {
+ assert(index < sizeof(fragAttribs) / sizeof(fragAttribs[0]));
+ return fragAttribs[index];
+ }
+}
+
+
+/**
+ * Return ARB_v/f_prog-style output attrib string.
+ */
+static const char *
+arb_output_attrib_string(GLint index, GLenum progType)
+{
+ /*
+ * These strings should match the VERT_RESULT_x and FRAG_RESULT_x tokens.
+ */
+ const char *vertResults[] = {
+ "result.position",
+ "result.color.primary",
+ "result.color.secondary",
+ "result.fogcoord",
+ "result.texcoord[0]",
+ "result.texcoord[1]",
+ "result.texcoord[2]",
+ "result.texcoord[3]",
+ "result.texcoord[4]",
+ "result.texcoord[5]",
+ "result.texcoord[6]",
+ "result.texcoord[7]",
+ "result.varying[0]",
+ "result.varying[1]",
+ "result.varying[2]",
+ "result.varying[3]",
+ "result.varying[4]",
+ "result.varying[5]",
+ "result.varying[6]",
+ "result.varying[7]"
+ };
+ const char *fragResults[] = {
+ "result.color",
+ "result.color(half)",
+ "result.depth",
+ "result.color[0]",
+ "result.color[1]",
+ "result.color[2]",
+ "result.color[3]"
+ };
+
+ if (progType == GL_VERTEX_PROGRAM_ARB) {
+ assert(index < sizeof(vertResults) / sizeof(vertResults[0]));
+ return vertResults[index];
+ }
+ else {
+ assert(index < sizeof(fragResults) / sizeof(fragResults[0]));
+ return fragResults[index];
+ }
+}
+
+
+/**
+ * Return string representation of the given register.
+ * Note that some types of registers (like PROGRAM_UNIFORM) aren't defined
+ * by the ARB/NV program languages so we've taken some liberties here.
+ * \param f the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc)
+ * \param index number of the register in the register file
+ * \param mode the output format/mode/style
+ * \param prog pointer to containing program
+ */
+static const char *
+reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode,
+ GLboolean relAddr, const struct gl_program *prog)
+{
+ static char str[100];
+ const char *addr = relAddr ? "ADDR+" : "";
+
+ str[0] = 0;
+
+ switch (mode) {
+ case PROG_PRINT_DEBUG:
+ _mesa_sprintf(str, "%s[%s%d]", file_string(f, mode), addr, index);
+ break;
+
+ case PROG_PRINT_ARB:
+ switch (f) {
+ case PROGRAM_INPUT:
+ _mesa_sprintf(str, "%s", arb_input_attrib_string(index, prog->Target));
+ break;
+ case PROGRAM_OUTPUT:
+ _mesa_sprintf(str, "%s", arb_output_attrib_string(index, prog->Target));
+ break;
+ case PROGRAM_TEMPORARY:
+ _mesa_sprintf(str, "temp%d", index);
+ break;
+ case PROGRAM_ENV_PARAM:
+ _mesa_sprintf(str, "program.env[%s%d]", addr, index);
+ break;
+ case PROGRAM_LOCAL_PARAM:
+ _mesa_sprintf(str, "program.local[%s%d]", addr, index);
+ break;
+ case PROGRAM_VARYING: /* extension */
+ _mesa_sprintf(str, "varying[%s%d]", addr, index);
+ break;
+ case PROGRAM_CONSTANT: /* extension */
+ _mesa_sprintf(str, "constant[%s%d]", addr, index);
+ break;
+ case PROGRAM_UNIFORM: /* extension */
+ _mesa_sprintf(str, "uniform[%s%d]", addr, index);
+ break;
+ case PROGRAM_STATE_VAR:
+ {
+ struct gl_program_parameter *param
+ = prog->Parameters->Parameters + index;
+ char *state = _mesa_program_state_string(param->StateIndexes);
+ _mesa_sprintf(str, state);
+ _mesa_free(state);
+ }
+ break;
+ case PROGRAM_ADDRESS:
+ _mesa_sprintf(str, "A%d", index);
+ break;
+ default:
+ _mesa_problem(NULL, "bad file in reg_string()");
+ }
+ break;
+
+ case PROG_PRINT_NV:
+ switch (f) {
+ case PROGRAM_INPUT:
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+ _mesa_sprintf(str, "v[%d]", index);
+ else
+ _mesa_sprintf(str, "f[%d]", index);
+ break;
+ case PROGRAM_OUTPUT:
+ _mesa_sprintf(str, "o[%d]", index);
+ break;
+ case PROGRAM_TEMPORARY:
+ _mesa_sprintf(str, "R%d", index);
+ break;
+ case PROGRAM_ENV_PARAM:
+ _mesa_sprintf(str, "c[%d]", index);
+ break;
+ case PROGRAM_VARYING: /* extension */
+ _mesa_sprintf(str, "varying[%s%d]", addr, index);
+ break;
+ case PROGRAM_UNIFORM: /* extension */
+ _mesa_sprintf(str, "uniform[%s%d]", addr, index);
+ break;
+ case PROGRAM_CONSTANT: /* extension */
+ _mesa_sprintf(str, "constant[%s%d]", addr, index);
+ break;
+ case PROGRAM_STATE_VAR: /* extension */
+ _mesa_sprintf(str, "state[%s%d]", addr, index);
+ break;
+ default:
+ _mesa_problem(NULL, "bad file in reg_string()");
+ }
+ break;
+
+ default:
+ _mesa_problem(NULL, "bad mode in reg_string()");
+ }
+
+ return str;
+}
+
+
+/**
+ * Return a string representation of the given swizzle word.
+ * If extended is true, use extended (comma-separated) format.
+ * \param swizzle the swizzle field
+ * \param negateBase 4-bit negation vector
+ * \param extended if true, also allow 0, 1 values
+ */
+const char *
+_mesa_swizzle_string(GLuint swizzle, GLuint negateMask, GLboolean extended)
+{
+ static const char swz[] = "xyzw01!?"; /* See SWIZZLE_x definitions */
+ static char s[20];
+ GLuint i = 0;
+
+ if (!extended && swizzle == SWIZZLE_NOOP && negateMask == 0)
+ return ""; /* no swizzle/negation */
+
+ if (!extended)
+ s[i++] = '.';
+
+ if (negateMask & NEGATE_X)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 0)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_Y)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 1)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_Z)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 2)];
+
+ if (extended) {
+ s[i++] = ',';
+ }
+
+ if (negateMask & NEGATE_W)
+ s[i++] = '-';
+ s[i++] = swz[GET_SWZ(swizzle, 3)];
+
+ s[i] = 0;
+ return s;
+}
+
+
+void
+_mesa_print_swizzle(GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_XYZW) {
+ _mesa_printf(".xyzw\n");
+ }
+ else {
+ const char *s = _mesa_swizzle_string(swizzle, 0, 0);
+ _mesa_printf("%s\n", s);
+ }
+}
+
+
+const char *
+_mesa_writemask_string(GLuint writeMask)
+{
+ static char s[10];
+ GLuint i = 0;
+
+ if (writeMask == WRITEMASK_XYZW)
+ return "";
+
+ s[i++] = '.';
+ if (writeMask & WRITEMASK_X)
+ s[i++] = 'x';
+ if (writeMask & WRITEMASK_Y)
+ s[i++] = 'y';
+ if (writeMask & WRITEMASK_Z)
+ s[i++] = 'z';
+ if (writeMask & WRITEMASK_W)
+ s[i++] = 'w';
+
+ s[i] = 0;
+ return s;
+}
+
+
+const char *
+_mesa_condcode_string(GLuint condcode)
+{
+ switch (condcode) {
+ case COND_GT: return "GT";
+ case COND_EQ: return "EQ";
+ case COND_LT: return "LT";
+ case COND_UN: return "UN";
+ case COND_GE: return "GE";
+ case COND_LE: return "LE";
+ case COND_NE: return "NE";
+ case COND_TR: return "TR";
+ case COND_FL: return "FL";
+ default: return "cond???";
+ }
+}
+
+
+static void
+fprint_dst_reg(FILE * f,
+ const struct prog_dst_register *dstReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ _mesa_fprintf(f, "%s%s",
+ reg_string((gl_register_file) dstReg->File,
+ dstReg->Index, mode, dstReg->RelAddr, prog),
+ _mesa_writemask_string(dstReg->WriteMask));
+
+ if (dstReg->CondMask != COND_TR) {
+ _mesa_fprintf(f, " (%s.%s)",
+ _mesa_condcode_string(dstReg->CondMask),
+ _mesa_swizzle_string(dstReg->CondSwizzle,
+ GL_FALSE, GL_FALSE));
+ }
+
+#if 0
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) dstReg->File, mode),
+ dstReg->Index,
+ _mesa_writemask_string(dstReg->WriteMask));
+#endif
+}
+
+
+static void
+fprint_src_reg(FILE *f,
+ const struct prog_src_register *srcReg,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ const char *abs = srcReg->Abs ? "|" : "";
+
+ _mesa_fprintf(f, "%s%s%s%s",
+ abs,
+ reg_string((gl_register_file) srcReg->File,
+ srcReg->Index, mode, srcReg->RelAddr, prog),
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE),
+ abs);
+#if 0
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) srcReg->File, mode),
+ srcReg->Index,
+ _mesa_swizzle_string(srcReg->Swizzle,
+ srcReg->Negate, GL_FALSE));
+#endif
+}
+
+
+static void
+fprint_comment(FILE *f, const struct prog_instruction *inst)
+{
+ if (inst->Comment)
+ _mesa_fprintf(f, "; # %s\n", inst->Comment);
+ else
+ _mesa_fprintf(f, ";\n");
+}
+
+
+static void
+fprint_alu_instruction(FILE *f,
+ const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ GLuint j;
+
+ _mesa_fprintf(f, "%s", opcode_string);
+ if (inst->CondUpdate)
+ _mesa_fprintf(f, ".C");
+
+ /* frag prog only */
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ _mesa_fprintf(f, "_SAT");
+
+ _mesa_fprintf(f, " ");
+ if (inst->DstReg.File != PROGRAM_UNDEFINED) {
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ }
+ else {
+ _mesa_fprintf(f, " ???");
+ }
+
+ if (numRegs > 0)
+ _mesa_fprintf(f, ", ");
+
+ for (j = 0; j < numRegs; j++) {
+ fprint_src_reg(f, inst->SrcReg + j, mode, prog);
+ if (j + 1 < numRegs)
+ _mesa_fprintf(f, ", ");
+ }
+
+ fprint_comment(f, inst);
+}
+
+
+void
+_mesa_print_alu_instruction(const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs)
+{
+ fprint_alu_instruction(stderr, inst, opcode_string,
+ numRegs, PROG_PRINT_DEBUG, NULL);
+}
+
+
+/**
+ * Print a single vertex/fragment program instruction.
+ */
+GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ GLint i;
+
+ if (inst->Opcode == OPCODE_ELSE ||
+ inst->Opcode == OPCODE_ENDIF ||
+ inst->Opcode == OPCODE_ENDLOOP ||
+ inst->Opcode == OPCODE_ENDSUB) {
+ indent -= 3;
+ }
+ for (i = 0; i < indent; i++) {
+ _mesa_fprintf(f, " ");
+ }
+
+ switch (inst->Opcode) {
+ case OPCODE_PRINT:
+ _mesa_fprintf(f, "PRINT '%s'", inst->Data);
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ _mesa_fprintf(f, ", ");
+ _mesa_fprintf(f, "%s[%d]%s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
+ mode),
+ inst->SrcReg[0].Index,
+ _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
+ inst->SrcReg[0].Negate, GL_FALSE));
+ }
+ if (inst->Comment)
+ _mesa_fprintf(f, " # %s", inst->Comment);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_SWZ:
+ _mesa_fprintf(f, "SWZ");
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ _mesa_fprintf(f, "_SAT");
+ _mesa_fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", %s[%d], %s",
+ file_string((gl_register_file) inst->SrcReg[0].File,
+ mode),
+ inst->SrcReg[0].Index,
+ _mesa_swizzle_string(inst->SrcReg[0].Swizzle,
+ inst->SrcReg[0].Negate, GL_TRUE));
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_TEX:
+ case OPCODE_TXP:
+ case OPCODE_TXL:
+ case OPCODE_TXB:
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ if (inst->SaturateMode == SATURATE_ZERO_ONE)
+ _mesa_fprintf(f, "_SAT");
+ _mesa_fprintf(f, " ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ _mesa_fprintf(f, ", texture[%d], ", inst->TexSrcUnit);
+ switch (inst->TexSrcTarget) {
+ case TEXTURE_1D_INDEX: _mesa_fprintf(f, "1D"); break;
+ case TEXTURE_2D_INDEX: _mesa_fprintf(f, "2D"); break;
+ case TEXTURE_3D_INDEX: _mesa_fprintf(f, "3D"); break;
+ case TEXTURE_CUBE_INDEX: _mesa_fprintf(f, "CUBE"); break;
+ case TEXTURE_RECT_INDEX: _mesa_fprintf(f, "RECT"); break;
+ default:
+ ;
+ }
+ if (inst->TexShadow)
+ _mesa_fprintf(f, " SHADOW");
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_KIL:
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ _mesa_fprintf(f, " ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_KIL_NV:
+ _mesa_fprintf(f, "%s", _mesa_opcode_string(inst->Opcode));
+ _mesa_fprintf(f, " ");
+ _mesa_fprintf(f, "%s.%s",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ GL_FALSE, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_ARL:
+ _mesa_fprintf(f, "ARL ");
+ fprint_dst_reg(f, &inst->DstReg, mode, prog);
+ _mesa_fprintf(f, ", ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_BRA:
+ _mesa_fprintf(f, "BRA %d (%s%s)",
+ inst->BranchTarget,
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+ case OPCODE_IF:
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ /* Use ordinary register */
+ _mesa_fprintf(f, "IF ");
+ fprint_src_reg(f, &inst->SrcReg[0], mode, prog);
+ _mesa_fprintf(f, "; ");
+ }
+ else {
+ /* Use cond codes */
+ _mesa_fprintf(f, "IF (%s%s);",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ 0, GL_FALSE));
+ }
+ _mesa_fprintf(f, " # (if false, goto %d)", inst->BranchTarget);
+ fprint_comment(f, inst);
+ return indent + 3;
+ case OPCODE_ELSE:
+ _mesa_fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget);
+ return indent + 3;
+ case OPCODE_ENDIF:
+ _mesa_fprintf(f, "ENDIF;\n");
+ break;
+ case OPCODE_BGNLOOP:
+ _mesa_fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget);
+ return indent + 3;
+ case OPCODE_ENDLOOP:
+ _mesa_fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget);
+ break;
+ case OPCODE_BRK:
+ case OPCODE_CONT:
+ _mesa_fprintf(f, "%s (%s%s); # (goto %d)",
+ _mesa_opcode_string(inst->Opcode),
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
+ inst->BranchTarget);
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_BGNSUB:
+ if (mode == PROG_PRINT_NV) {
+ _mesa_fprintf(f, "%s:\n", inst->Comment); /* comment is label */
+ return indent;
+ }
+ else {
+ _mesa_fprintf(f, "BGNSUB");
+ fprint_comment(f, inst);
+ return indent + 3;
+ }
+ case OPCODE_ENDSUB:
+ if (mode == PROG_PRINT_DEBUG) {
+ _mesa_fprintf(f, "ENDSUB");
+ fprint_comment(f, inst);
+ }
+ break;
+ case OPCODE_CAL:
+ if (mode == PROG_PRINT_NV) {
+ _mesa_fprintf(f, "CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget);
+ }
+ else {
+ _mesa_fprintf(f, "CAL %u", inst->BranchTarget);
+ fprint_comment(f, inst);
+ }
+ break;
+ case OPCODE_RET:
+ _mesa_fprintf(f, "RET (%s%s)",
+ _mesa_condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ fprint_comment(f, inst);
+ break;
+
+ case OPCODE_END:
+ _mesa_fprintf(f, "END\n");
+ break;
+ case OPCODE_NOP:
+ if (mode == PROG_PRINT_DEBUG) {
+ _mesa_fprintf(f, "NOP");
+ fprint_comment(f, inst);
+ }
+ else if (inst->Comment) {
+ /* ARB/NV extensions don't have NOP instruction */
+ _mesa_fprintf(f, "# %s\n", inst->Comment);
+ }
+ break;
+ /* XXX may need other special-case instructions */
+ default:
+ if (inst->Opcode < MAX_OPCODE) {
+ /* typical alu instruction */
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ _mesa_num_inst_src_regs(inst->Opcode),
+ mode, prog);
+ }
+ else {
+ fprint_alu_instruction(f, inst,
+ _mesa_opcode_string(inst->Opcode),
+ 3/*_mesa_num_inst_src_regs(inst->Opcode)*/,
+ mode, prog);
+ }
+ break;
+ }
+ return indent;
+}
+
+
+GLint
+_mesa_print_instruction_opt(const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog)
+{
+ return _mesa_fprint_instruction_opt(stderr, inst, indent, mode, prog);
+}
+
+
+void
+_mesa_print_instruction(const struct prog_instruction *inst)
+{
+ /* note: 4th param should be ignored for PROG_PRINT_DEBUG */
+ _mesa_fprint_instruction_opt(stderr, inst, 0, PROG_PRINT_DEBUG, NULL);
+}
+
+
+
+/**
+ * Print program, with options.
+ */
+void
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog,
+ gl_prog_print_mode mode,
+ GLboolean lineNumbers)
+{
+ GLuint i, indent = 0;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ if (mode == PROG_PRINT_ARB)
+ _mesa_fprintf(f, "!!ARBvp1.0\n");
+ else if (mode == PROG_PRINT_NV)
+ _mesa_fprintf(f, "!!VP1.0\n");
+ else
+ _mesa_fprintf(f, "# Vertex Program/Shader\n");
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ case GL_FRAGMENT_PROGRAM_NV:
+ if (mode == PROG_PRINT_ARB)
+ _mesa_fprintf(f, "!!ARBfp1.0\n");
+ else if (mode == PROG_PRINT_NV)
+ _mesa_fprintf(f, "!!FP1.0\n");
+ else
+ _mesa_fprintf(f, "# Fragment Program/Shader\n");
+ break;
+ }
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ if (lineNumbers)
+ _mesa_fprintf(f, "%3d: ", i);
+ indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i,
+ indent, mode, prog);
+ }
+}
+
+
+/**
+ * Print program to stderr, default options.
+ */
+void
+_mesa_print_program(const struct gl_program *prog)
+{
+ _mesa_fprint_program_opt(stderr, prog, PROG_PRINT_DEBUG, GL_TRUE);
+}
+
+
+/**
+ * Return binary representation of value (as a string).
+ * Insert a comma to separate each group of 8 bits.
+ * XXX move to imports.[ch] if useful elsewhere.
+ */
+static const char *
+binary(GLbitfield val)
+{
+ static char buf[50];
+ GLint i, len = 0;
+ for (i = 31; i >= 0; --i) {
+ if (val & (1 << i))
+ buf[len++] = '1';
+ else if (len > 0 || i == 0)
+ buf[len++] = '0';
+ if (len > 0 && ((i-1) % 8) == 7)
+ buf[len++] = ',';
+ }
+ buf[len] = '\0';
+ return buf;
+}
+
+
+/**
+ * Print all of a program's parameters/fields to given file.
+ */
+static void
+_mesa_fprint_program_parameters(FILE *f,
+ GLcontext *ctx,
+ const struct gl_program *prog)
+{
+ GLuint i;
+
+ _mesa_fprintf(f, "InputsRead: 0x%x (0b%s)\n",
+ prog->InputsRead, binary(prog->InputsRead));
+ _mesa_fprintf(f, "OutputsWritten: 0x%x (0b%s)\n",
+ prog->OutputsWritten, binary(prog->OutputsWritten));
+ _mesa_fprintf(f, "NumInstructions=%d\n", prog->NumInstructions);
+ _mesa_fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries);
+ _mesa_fprintf(f, "NumParameters=%d\n", prog->NumParameters);
+ _mesa_fprintf(f, "NumAttributes=%d\n", prog->NumAttributes);
+ _mesa_fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs);
+ _mesa_fprintf(f, "SamplersUsed: 0x%x (0b%s)\n",
+ prog->SamplersUsed, binary(prog->SamplersUsed));
+ _mesa_fprintf(f, "Samplers=[ ");
+ for (i = 0; i < MAX_SAMPLERS; i++) {
+ _mesa_fprintf(f, "%d ", prog->SamplerUnits[i]);
+ }
+ _mesa_fprintf(f, "]\n");
+
+ _mesa_load_state_parameters(ctx, prog->Parameters);
+
+#if 0
+ _mesa_fprintf(f, "Local Params:\n");
+ for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){
+ const GLfloat *p = prog->LocalParams[i];
+ _mesa_fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]);
+ }
+#endif
+ _mesa_print_parameter_list(prog->Parameters);
+}
+
+
+/**
+ * Print all of a program's parameters/fields to stderr.
+ */
+void
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog)
+{
+ _mesa_fprint_program_parameters(stderr, ctx, prog);
+}
+
+
+/**
+ * Print a program parameter list to given file.
+ */
+static void
+_mesa_fprint_parameter_list(FILE *f,
+ const struct gl_program_parameter_list *list)
+{
+ const gl_prog_print_mode mode = PROG_PRINT_DEBUG;
+ GLuint i;
+
+ if (!list)
+ return;
+
+ _mesa_fprintf(f, "param list %p\n", (void *) list);
+ _mesa_fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags);
+ for (i = 0; i < list->NumParameters; i++){
+ struct gl_program_parameter *param = list->Parameters + i;
+ const GLfloat *v = list->ParameterValues[i];
+ _mesa_fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}",
+ i, param->Size,
+ file_string(list->Parameters[i].Type, mode),
+ param->Name, v[0], v[1], v[2], v[3]);
+ if (param->Flags & PROG_PARAM_BIT_CENTROID)
+ _mesa_fprintf(f, " Centroid");
+ if (param->Flags & PROG_PARAM_BIT_INVARIANT)
+ _mesa_fprintf(f, " Invariant");
+ if (param->Flags & PROG_PARAM_BIT_FLAT)
+ _mesa_fprintf(f, " Flat");
+ if (param->Flags & PROG_PARAM_BIT_LINEAR)
+ _mesa_fprintf(f, " Linear");
+ _mesa_fprintf(f, "\n");
+ }
+}
+
+
+/**
+ * Print a program parameter list to stderr.
+ */
+void
+_mesa_print_parameter_list(const struct gl_program_parameter_list *list)
+{
+ _mesa_fprint_parameter_list(stderr, list);
+}
+
+
+/**
+ * Write shader and associated info to a file.
+ */
+void
+_mesa_write_shader_to_file(const struct gl_shader *shader)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "w");
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for writing\n", filename);
+ return;
+ }
+
+ fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum);
+ fputs(shader->Source, f);
+ fprintf(f, "\n");
+
+ fprintf(f, "/* Compile status: %s */\n",
+ shader->CompileStatus ? "ok" : "fail");
+ if (!shader->CompileStatus) {
+ fprintf(f, "/* Log Info: */\n");
+ fputs(shader->InfoLog, f);
+ }
+ else {
+ fprintf(f, "/* GPU code */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE);
+ fprintf(f, "*/\n");
+ fprintf(f, "/* Parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, shader->Program->Parameters);
+ fprintf(f, "*/\n");
+ }
+
+ fclose(f);
+}
+
+
+/**
+ * Append the shader's uniform info/values to the shader log file.
+ * The log file will typically have been created by the
+ * _mesa_write_shader_to_file function.
+ */
+void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog)
+{
+ const char *type;
+ char filename[100];
+ FILE *f;
+
+ if (shader->Type == GL_FRAGMENT_SHADER)
+ type = "frag";
+ else
+ type = "vert";
+
+ _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type);
+ f = fopen(filename, "a"); /* append */
+ if (!f) {
+ fprintf(stderr, "Unable to open %s for appending\n", filename);
+ return;
+ }
+
+ fprintf(f, "/* First-draw parameters / constants */\n");
+ fprintf(f, "/*\n");
+ _mesa_fprint_parameter_list(f, prog->Parameters);
+ fprintf(f, "*/\n");
+
+ fclose(f);
+}
diff --git a/mesalib/src/mesa/shader/prog_print.h b/mesalib/src/mesa/shader/prog_print.h
new file mode 100644
index 000000000..fc286ded5
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_print.h
@@ -0,0 +1,94 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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 PROG_PRINT_H
+#define PROG_PRINT_H
+
+
+/**
+ * The output style to use when printing programs.
+ */
+typedef enum {
+ PROG_PRINT_ARB,
+ PROG_PRINT_NV,
+ PROG_PRINT_DEBUG
+} gl_prog_print_mode;
+
+
+extern const char *
+_mesa_condcode_string(GLuint condcode);
+
+extern const char *
+_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended);
+
+const char *
+_mesa_writemask_string(GLuint writeMask);
+
+extern void
+_mesa_print_swizzle(GLuint swizzle);
+
+extern void
+_mesa_print_alu_instruction(const struct prog_instruction *inst,
+ const char *opcode_string, GLuint numRegs);
+
+extern void
+_mesa_print_instruction(const struct prog_instruction *inst);
+
+extern GLint
+_mesa_fprint_instruction_opt(FILE *f,
+ const struct prog_instruction *inst,
+ GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern GLint
+_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
+ gl_prog_print_mode mode,
+ const struct gl_program *prog);
+
+extern void
+_mesa_print_program(const struct gl_program *prog);
+
+extern void
+_mesa_fprint_program_opt(FILE *f,
+ const struct gl_program *prog, gl_prog_print_mode mode,
+ GLboolean lineNumbers);
+
+extern void
+_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog);
+
+extern void
+_mesa_print_parameter_list(const struct gl_program_parameter_list *list);
+
+
+extern void
+_mesa_write_shader_to_file(const struct gl_shader *shader);
+
+extern void
+_mesa_append_uniforms_to_file(const struct gl_shader *shader,
+ const struct gl_program *prog);
+
+
+#endif /* PROG_PRINT_H */
diff --git a/mesalib/src/mesa/shader/prog_statevars.c b/mesalib/src/mesa/shader/prog_statevars.c
new file mode 100644
index 000000000..058d4bbaf
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_statevars.c
@@ -0,0 +1,1120 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file prog_statevars.c
+ * Program state variable management.
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "prog_statevars.h"
+#include "prog_parameter.h"
+
+
+/**
+ * Use the list of tokens in the state[] array to find global GL state
+ * and return it in <value>. Usually, four values are returned in <value>
+ * but matrix queries may return as many as 16 values.
+ * This function is used for ARB vertex/fragment programs.
+ * The program parser will produce the state[] values.
+ */
+static void
+_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
+ GLfloat *value)
+{
+ switch (state[0]) {
+ case STATE_MATERIAL:
+ {
+ /* state[1] is either 0=front or 1=back side */
+ const GLuint face = (GLuint) state[1];
+ const struct gl_material *mat = &ctx->Light.Material;
+ ASSERT(face == 0 || face == 1);
+ /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
+ ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
+ /* XXX we could get rid of this switch entirely with a little
+ * work in arbprogparse.c's parse_state_single_item().
+ */
+ /* state[2] is the material attribute */
+ switch (state[2]) {
+ case STATE_AMBIENT:
+ COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
+ return;
+ case STATE_DIFFUSE:
+ COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
+ return;
+ case STATE_SPECULAR:
+ COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
+ return;
+ case STATE_EMISSION:
+ COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
+ return;
+ case STATE_SHININESS:
+ value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
+ value[1] = 0.0F;
+ value[2] = 0.0F;
+ value[3] = 1.0F;
+ return;
+ default:
+ _mesa_problem(ctx, "Invalid material state in fetch_state");
+ return;
+ }
+ }
+ case STATE_LIGHT:
+ {
+ /* state[1] is the light number */
+ const GLuint ln = (GLuint) state[1];
+ /* state[2] is the light attribute */
+ switch (state[2]) {
+ case STATE_AMBIENT:
+ COPY_4V(value, ctx->Light.Light[ln].Ambient);
+ return;
+ case STATE_DIFFUSE:
+ COPY_4V(value, ctx->Light.Light[ln].Diffuse);
+ return;
+ case STATE_SPECULAR:
+ COPY_4V(value, ctx->Light.Light[ln].Specular);
+ return;
+ case STATE_POSITION:
+ COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+ return;
+ case STATE_ATTENUATION:
+ value[0] = ctx->Light.Light[ln].ConstantAttenuation;
+ value[1] = ctx->Light.Light[ln].LinearAttenuation;
+ value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
+ value[3] = ctx->Light.Light[ln].SpotExponent;
+ return;
+ case STATE_SPOT_DIRECTION:
+ COPY_3V(value, ctx->Light.Light[ln].SpotDirection);
+ value[3] = ctx->Light.Light[ln]._CosCutoff;
+ return;
+ case STATE_SPOT_CUTOFF:
+ value[0] = ctx->Light.Light[ln].SpotCutoff;
+ return;
+ case STATE_HALF_VECTOR:
+ {
+ static const GLfloat eye_z[] = {0, 0, 1};
+ GLfloat p[3];
+ /* Compute infinite half angle vector:
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+ * light.EyePosition.w should be 0 for infinite lights.
+ */
+ COPY_3V(p, ctx->Light.Light[ln].EyePosition);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, eye_z);
+ NORMALIZE_3FV(value);
+ value[3] = 1.0;
+ }
+ return;
+ default:
+ _mesa_problem(ctx, "Invalid light state in fetch_state");
+ return;
+ }
+ }
+ case STATE_LIGHTMODEL_AMBIENT:
+ COPY_4V(value, ctx->Light.Model.Ambient);
+ return;
+ case STATE_LIGHTMODEL_SCENECOLOR:
+ if (state[1] == 0) {
+ /* front */
+ GLint i;
+ for (i = 0; i < 3; i++) {
+ value[i] = ctx->Light.Model.Ambient[i]
+ * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
+ + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
+ }
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+ }
+ else {
+ /* back */
+ GLint i;
+ for (i = 0; i < 3; i++) {
+ value[i] = ctx->Light.Model.Ambient[i]
+ * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
+ + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
+ }
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+ }
+ return;
+ case STATE_LIGHTPROD:
+ {
+ const GLuint ln = (GLuint) state[1];
+ const GLuint face = (GLuint) state[2];
+ GLint i;
+ ASSERT(face == 0 || face == 1);
+ switch (state[3]) {
+ case STATE_AMBIENT:
+ for (i = 0; i < 3; i++) {
+ value[i] = ctx->Light.Light[ln].Ambient[i] *
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
+ }
+ /* [3] = material alpha */
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
+ return;
+ case STATE_DIFFUSE:
+ for (i = 0; i < 3; i++) {
+ value[i] = ctx->Light.Light[ln].Diffuse[i] *
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
+ }
+ /* [3] = material alpha */
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+ return;
+ case STATE_SPECULAR:
+ for (i = 0; i < 3; i++) {
+ value[i] = ctx->Light.Light[ln].Specular[i] *
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
+ }
+ /* [3] = material alpha */
+ value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
+ return;
+ default:
+ _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
+ return;
+ }
+ }
+ case STATE_TEXGEN:
+ {
+ /* state[1] is the texture unit */
+ const GLuint unit = (GLuint) state[1];
+ /* state[2] is the texgen attribute */
+ switch (state[2]) {
+ case STATE_TEXGEN_EYE_S:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane);
+ return;
+ case STATE_TEXGEN_EYE_T:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane);
+ return;
+ case STATE_TEXGEN_EYE_R:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane);
+ return;
+ case STATE_TEXGEN_EYE_Q:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane);
+ return;
+ case STATE_TEXGEN_OBJECT_S:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane);
+ return;
+ case STATE_TEXGEN_OBJECT_T:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane);
+ return;
+ case STATE_TEXGEN_OBJECT_R:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane);
+ return;
+ case STATE_TEXGEN_OBJECT_Q:
+ COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane);
+ return;
+ default:
+ _mesa_problem(ctx, "Invalid texgen state in fetch_state");
+ return;
+ }
+ }
+ case STATE_TEXENV_COLOR:
+ {
+ /* state[1] is the texture unit */
+ const GLuint unit = (GLuint) state[1];
+ COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+ }
+ return;
+ case STATE_FOG_COLOR:
+ COPY_4V(value, ctx->Fog.Color);
+ return;
+ case STATE_FOG_PARAMS:
+ value[0] = ctx->Fog.Density;
+ value[1] = ctx->Fog.Start;
+ value[2] = ctx->Fog.End;
+ value[3] = (ctx->Fog.End == ctx->Fog.Start)
+ ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start));
+ return;
+ case STATE_CLIPPLANE:
+ {
+ const GLuint plane = (GLuint) state[1];
+ COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
+ }
+ return;
+ case STATE_POINT_SIZE:
+ value[0] = ctx->Point.Size;
+ value[1] = ctx->Point.MinSize;
+ value[2] = ctx->Point.MaxSize;
+ value[3] = ctx->Point.Threshold;
+ return;
+ case STATE_POINT_ATTENUATION:
+ value[0] = ctx->Point.Params[0];
+ value[1] = ctx->Point.Params[1];
+ value[2] = ctx->Point.Params[2];
+ value[3] = 1.0F;
+ return;
+ case STATE_MODELVIEW_MATRIX:
+ case STATE_PROJECTION_MATRIX:
+ case STATE_MVP_MATRIX:
+ case STATE_TEXTURE_MATRIX:
+ case STATE_PROGRAM_MATRIX:
+ case STATE_COLOR_MATRIX:
+ {
+ /* state[0] = modelview, projection, texture, etc. */
+ /* state[1] = which texture matrix or program matrix */
+ /* state[2] = first row to fetch */
+ /* state[3] = last row to fetch */
+ /* state[4] = transpose, inverse or invtrans */
+ const GLmatrix *matrix;
+ const gl_state_index mat = state[0];
+ const GLuint index = (GLuint) state[1];
+ const GLuint firstRow = (GLuint) state[2];
+ const GLuint lastRow = (GLuint) state[3];
+ const gl_state_index modifier = state[4];
+ const GLfloat *m;
+ GLuint row, i;
+ ASSERT(firstRow >= 0);
+ ASSERT(firstRow < 4);
+ ASSERT(lastRow >= 0);
+ ASSERT(lastRow < 4);
+ if (mat == STATE_MODELVIEW_MATRIX) {
+ matrix = ctx->ModelviewMatrixStack.Top;
+ }
+ else if (mat == STATE_PROJECTION_MATRIX) {
+ matrix = ctx->ProjectionMatrixStack.Top;
+ }
+ else if (mat == STATE_MVP_MATRIX) {
+ matrix = &ctx->_ModelProjectMatrix;
+ }
+ else if (mat == STATE_TEXTURE_MATRIX) {
+ matrix = ctx->TextureMatrixStack[index].Top;
+ }
+ else if (mat == STATE_PROGRAM_MATRIX) {
+ matrix = ctx->ProgramMatrixStack[index].Top;
+ }
+ else if (mat == STATE_COLOR_MATRIX) {
+ matrix = ctx->ColorMatrixStack.Top;
+ }
+ else {
+ _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
+ return;
+ }
+ if (modifier == STATE_MATRIX_INVERSE ||
+ modifier == STATE_MATRIX_INVTRANS) {
+ /* Be sure inverse is up to date:
+ */
+ _math_matrix_alloc_inv( (GLmatrix *) matrix );
+ _math_matrix_analyse( (GLmatrix*) matrix );
+ m = matrix->inv;
+ }
+ else {
+ m = matrix->m;
+ }
+ if (modifier == STATE_MATRIX_TRANSPOSE ||
+ modifier == STATE_MATRIX_INVTRANS) {
+ for (i = 0, row = firstRow; row <= lastRow; row++) {
+ value[i++] = m[row * 4 + 0];
+ value[i++] = m[row * 4 + 1];
+ value[i++] = m[row * 4 + 2];
+ value[i++] = m[row * 4 + 3];
+ }
+ }
+ else {
+ for (i = 0, row = firstRow; row <= lastRow; row++) {
+ value[i++] = m[row + 0];
+ value[i++] = m[row + 4];
+ value[i++] = m[row + 8];
+ value[i++] = m[row + 12];
+ }
+ }
+ }
+ return;
+ case STATE_DEPTH_RANGE:
+ value[0] = ctx->Viewport.Near; /* near */
+ value[1] = ctx->Viewport.Far; /* far */
+ value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
+ value[3] = 1.0;
+ return;
+ case STATE_FRAGMENT_PROGRAM:
+ {
+ /* state[1] = {STATE_ENV, STATE_LOCAL} */
+ /* state[2] = parameter index */
+ const int idx = (int) state[2];
+ switch (state[1]) {
+ case STATE_ENV:
+ COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
+ return;
+ case STATE_LOCAL:
+ COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
+ return;
+ default:
+ _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+ return;
+ }
+ }
+ return;
+
+ case STATE_VERTEX_PROGRAM:
+ {
+ /* state[1] = {STATE_ENV, STATE_LOCAL} */
+ /* state[2] = parameter index */
+ const int idx = (int) state[2];
+ switch (state[1]) {
+ case STATE_ENV:
+ COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
+ return;
+ case STATE_LOCAL:
+ COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
+ return;
+ default:
+ _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+ return;
+ }
+ }
+ return;
+
+ case STATE_NORMAL_SCALE:
+ ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
+ return;
+
+ case STATE_INTERNAL:
+ switch (state[1]) {
+ case STATE_CURRENT_ATTRIB:
+ {
+ const GLuint idx = (GLuint) state[2];
+ COPY_4V(value, ctx->Current.Attrib[idx]);
+ }
+ return;
+
+ case STATE_NORMAL_SCALE:
+ ASSIGN_4V(value,
+ ctx->_ModelViewInvScale,
+ ctx->_ModelViewInvScale,
+ ctx->_ModelViewInvScale,
+ 1);
+ return;
+
+ case STATE_TEXRECT_SCALE:
+ /* Value = { 1/texWidth, 1/texHeight, 0, 1 }.
+ * Used to convert unnormalized texcoords to normalized texcoords.
+ */
+ {
+ const int unit = (int) state[2];
+ const struct gl_texture_object *texObj
+ = ctx->Texture.Unit[unit]._Current;
+ if (texObj) {
+ struct gl_texture_image *texImage = texObj->Image[0][0];
+ ASSIGN_4V(value,
+ (GLfloat) (1.0 / texImage->Width),
+ (GLfloat) (1.0 / texImage->Height),
+ 0.0f, 1.0f);
+ }
+ }
+ return;
+
+ case STATE_FOG_PARAMS_OPTIMIZED:
+ /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
+ * might be more expensive than EX2 on some hw, plus it needs
+ * another constant (e) anyway. Linear fog can now be done with a
+ * single MAD.
+ * linear: fogcoord * -1/(end-start) + end/(end-start)
+ * exp: 2^-(density/ln(2) * fogcoord)
+ * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2)
+ */
+ value[0] = (ctx->Fog.End == ctx->Fog.Start)
+ ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
+ value[1] = ctx->Fog.End * -value[0];
+ value[2] = (GLfloat)(ctx->Fog.Density * ONE_DIV_LN2);
+ value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
+ return;
+
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ {
+ /* here, state[2] is the light number */
+ /* pre-normalize spot dir */
+ const GLuint ln = (GLuint) state[2];
+ COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
+ value[3] = ctx->Light.Light[ln]._CosCutoff;
+ }
+ return;
+
+ case STATE_LIGHT_POSITION:
+ {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ }
+ return;
+
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV( value );
+ }
+ return;
+
+ case STATE_LIGHT_HALF_VECTOR:
+ {
+ const GLuint ln = (GLuint) state[2];
+ GLfloat p[3];
+ /* Compute infinite half angle vector:
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+ * light.EyePosition.w should be 0 for infinite lights.
+ */
+ COPY_3V(p, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, ctx->_EyeZDir);
+ NORMALIZE_3FV(value);
+ value[3] = 1.0;
+ }
+ return;
+
+ case STATE_PT_SCALE:
+ value[0] = ctx->Pixel.RedScale;
+ value[1] = ctx->Pixel.GreenScale;
+ value[2] = ctx->Pixel.BlueScale;
+ value[3] = ctx->Pixel.AlphaScale;
+ return;
+
+ case STATE_PT_BIAS:
+ value[0] = ctx->Pixel.RedBias;
+ value[1] = ctx->Pixel.GreenBias;
+ value[2] = ctx->Pixel.BlueBias;
+ value[3] = ctx->Pixel.AlphaBias;
+ return;
+
+ case STATE_PCM_SCALE:
+ COPY_4V(value, ctx->Pixel.PostColorMatrixScale);
+ return;
+
+ case STATE_PCM_BIAS:
+ COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
+ return;
+
+ case STATE_SHADOW_AMBIENT:
+ {
+ const int unit = (int) state[2];
+ const struct gl_texture_object *texObj
+ = ctx->Texture.Unit[unit]._Current;
+ if (texObj) {
+ value[0] =
+ value[1] =
+ value[2] =
+ value[3] = texObj->CompareFailValue;
+ }
+ }
+ return;
+
+ case STATE_FB_SIZE:
+ value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
+ value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ value[2] = 0.0F;
+ value[3] = 0.0F;
+ return;
+
+ case STATE_ROT_MATRIX_0:
+ {
+ const int unit = (int) state[2];
+ GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
+ value[0] = rotMat22[0];
+ value[1] = rotMat22[2];
+ value[2] = 0.0;
+ value[3] = 0.0;
+ }
+ return;
+
+ case STATE_ROT_MATRIX_1:
+ {
+ const int unit = (int) state[2];
+ GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
+ value[0] = rotMat22[1];
+ value[1] = rotMat22[3];
+ value[2] = 0.0;
+ value[3] = 0.0;
+ }
+ return;
+
+ /* XXX: make sure new tokens added here are also handled in the
+ * _mesa_program_state_flags() switch, below.
+ */
+ default:
+ /* Unknown state indexes are silently ignored here.
+ * Drivers may do something special.
+ */
+ return;
+ }
+ return;
+
+ default:
+ _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
+ return;
+ }
+}
+
+
+/**
+ * Return a bitmask of the Mesa state flags (_NEW_* values) which would
+ * indicate that the given context state may have changed.
+ * The bitmask is used during validation to determine if we need to update
+ * vertex/fragment program parameters (like "state.material.color") when
+ * some GL state has changed.
+ */
+GLbitfield
+_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
+{
+ switch (state[0]) {
+ case STATE_MATERIAL:
+ case STATE_LIGHT:
+ case STATE_LIGHTMODEL_AMBIENT:
+ case STATE_LIGHTMODEL_SCENECOLOR:
+ case STATE_LIGHTPROD:
+ return _NEW_LIGHT;
+
+ case STATE_TEXGEN:
+ case STATE_TEXENV_COLOR:
+ return _NEW_TEXTURE;
+
+ case STATE_FOG_COLOR:
+ case STATE_FOG_PARAMS:
+ return _NEW_FOG;
+
+ case STATE_CLIPPLANE:
+ return _NEW_TRANSFORM;
+
+ case STATE_POINT_SIZE:
+ case STATE_POINT_ATTENUATION:
+ return _NEW_POINT;
+
+ case STATE_MODELVIEW_MATRIX:
+ return _NEW_MODELVIEW;
+ case STATE_PROJECTION_MATRIX:
+ return _NEW_PROJECTION;
+ case STATE_MVP_MATRIX:
+ return _NEW_MODELVIEW | _NEW_PROJECTION;
+ case STATE_TEXTURE_MATRIX:
+ return _NEW_TEXTURE_MATRIX;
+ case STATE_PROGRAM_MATRIX:
+ return _NEW_TRACK_MATRIX;
+ case STATE_COLOR_MATRIX:
+ return _NEW_COLOR_MATRIX;
+
+ case STATE_DEPTH_RANGE:
+ return _NEW_VIEWPORT;
+
+ case STATE_FRAGMENT_PROGRAM:
+ case STATE_VERTEX_PROGRAM:
+ return _NEW_PROGRAM;
+
+ case STATE_NORMAL_SCALE:
+ return _NEW_MODELVIEW;
+
+ case STATE_INTERNAL:
+ switch (state[1]) {
+ case STATE_CURRENT_ATTRIB:
+ return _NEW_CURRENT_ATTRIB;
+
+ case STATE_NORMAL_SCALE:
+ return _NEW_MODELVIEW;
+
+ case STATE_TEXRECT_SCALE:
+ case STATE_SHADOW_AMBIENT:
+ case STATE_ROT_MATRIX_0:
+ case STATE_ROT_MATRIX_1:
+ return _NEW_TEXTURE;
+ case STATE_FOG_PARAMS_OPTIMIZED:
+ return _NEW_FOG;
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ case STATE_LIGHT_POSITION:
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ case STATE_LIGHT_HALF_VECTOR:
+ return _NEW_LIGHT;
+
+ case STATE_PT_SCALE:
+ case STATE_PT_BIAS:
+ case STATE_PCM_SCALE:
+ case STATE_PCM_BIAS:
+ return _NEW_PIXEL;
+
+ case STATE_FB_SIZE:
+ return _NEW_BUFFERS;
+
+ default:
+ /* unknown state indexes are silently ignored and
+ * no flag set, since it is handled by the driver.
+ */
+ return 0;
+ }
+
+ default:
+ _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
+ return 0;
+ }
+}
+
+
+static void
+append(char *dst, const char *src)
+{
+ while (*dst)
+ dst++;
+ while (*src)
+ *dst++ = *src++;
+ *dst = 0;
+}
+
+
+/**
+ * Convert token 'k' to a string, append it onto 'dst' string.
+ */
+static void
+append_token(char *dst, gl_state_index k)
+{
+ switch (k) {
+ case STATE_MATERIAL:
+ append(dst, "material");
+ break;
+ case STATE_LIGHT:
+ append(dst, "light");
+ break;
+ case STATE_LIGHTMODEL_AMBIENT:
+ append(dst, "lightmodel.ambient");
+ break;
+ case STATE_LIGHTMODEL_SCENECOLOR:
+ break;
+ case STATE_LIGHTPROD:
+ append(dst, "lightprod");
+ break;
+ case STATE_TEXGEN:
+ append(dst, "texgen");
+ break;
+ case STATE_FOG_COLOR:
+ append(dst, "fog.color");
+ break;
+ case STATE_FOG_PARAMS:
+ append(dst, "fog.params");
+ break;
+ case STATE_CLIPPLANE:
+ append(dst, "clip");
+ break;
+ case STATE_POINT_SIZE:
+ append(dst, "point.size");
+ break;
+ case STATE_POINT_ATTENUATION:
+ append(dst, "point.attenuation");
+ break;
+ case STATE_MODELVIEW_MATRIX:
+ append(dst, "matrix.modelview");
+ break;
+ case STATE_PROJECTION_MATRIX:
+ append(dst, "matrix.projection");
+ break;
+ case STATE_MVP_MATRIX:
+ append(dst, "matrix.mvp");
+ break;
+ case STATE_TEXTURE_MATRIX:
+ append(dst, "matrix.texture");
+ break;
+ case STATE_PROGRAM_MATRIX:
+ append(dst, "matrix.program");
+ break;
+ case STATE_COLOR_MATRIX:
+ append(dst, "matrix.color");
+ break;
+ case STATE_MATRIX_INVERSE:
+ append(dst, ".inverse");
+ break;
+ case STATE_MATRIX_TRANSPOSE:
+ append(dst, ".transpose");
+ break;
+ case STATE_MATRIX_INVTRANS:
+ append(dst, ".invtrans");
+ break;
+ case STATE_AMBIENT:
+ append(dst, ".ambient");
+ break;
+ case STATE_DIFFUSE:
+ append(dst, ".diffuse");
+ break;
+ case STATE_SPECULAR:
+ append(dst, ".specular");
+ break;
+ case STATE_EMISSION:
+ append(dst, ".emission");
+ break;
+ case STATE_SHININESS:
+ append(dst, "lshininess");
+ break;
+ case STATE_HALF_VECTOR:
+ append(dst, ".half");
+ break;
+ case STATE_POSITION:
+ append(dst, ".position");
+ break;
+ case STATE_ATTENUATION:
+ append(dst, ".attenuation");
+ break;
+ case STATE_SPOT_DIRECTION:
+ append(dst, ".spot.direction");
+ break;
+ case STATE_SPOT_CUTOFF:
+ append(dst, ".spot.cutoff");
+ break;
+ case STATE_TEXGEN_EYE_S:
+ append(dst, ".eye.s");
+ break;
+ case STATE_TEXGEN_EYE_T:
+ append(dst, ".eye.t");
+ break;
+ case STATE_TEXGEN_EYE_R:
+ append(dst, ".eye.r");
+ break;
+ case STATE_TEXGEN_EYE_Q:
+ append(dst, ".eye.q");
+ break;
+ case STATE_TEXGEN_OBJECT_S:
+ append(dst, ".object.s");
+ break;
+ case STATE_TEXGEN_OBJECT_T:
+ append(dst, ".object.t");
+ break;
+ case STATE_TEXGEN_OBJECT_R:
+ append(dst, ".object.r");
+ break;
+ case STATE_TEXGEN_OBJECT_Q:
+ append(dst, ".object.q");
+ break;
+ case STATE_TEXENV_COLOR:
+ append(dst, "texenv");
+ break;
+ case STATE_DEPTH_RANGE:
+ append(dst, "depth.range");
+ break;
+ case STATE_VERTEX_PROGRAM:
+ case STATE_FRAGMENT_PROGRAM:
+ break;
+ case STATE_ENV:
+ append(dst, "env");
+ break;
+ case STATE_LOCAL:
+ append(dst, "local");
+ break;
+ /* BEGIN internal state vars */
+ case STATE_INTERNAL:
+ append(dst, ".internal.");
+ break;
+ case STATE_CURRENT_ATTRIB:
+ append(dst, "current");
+ break;
+ case STATE_NORMAL_SCALE:
+ append(dst, "normalScale");
+ break;
+ case STATE_TEXRECT_SCALE:
+ append(dst, "texrectScale");
+ break;
+ case STATE_FOG_PARAMS_OPTIMIZED:
+ append(dst, "fogParamsOptimized");
+ break;
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED:
+ append(dst, "lightSpotDirNormalized");
+ break;
+ case STATE_LIGHT_POSITION:
+ append(dst, "lightPosition");
+ break;
+ case STATE_LIGHT_POSITION_NORMALIZED:
+ append(dst, "light.position.normalized");
+ break;
+ case STATE_LIGHT_HALF_VECTOR:
+ append(dst, "lightHalfVector");
+ break;
+ case STATE_PT_SCALE:
+ append(dst, "PTscale");
+ break;
+ case STATE_PT_BIAS:
+ append(dst, "PTbias");
+ break;
+ case STATE_PCM_SCALE:
+ append(dst, "PCMscale");
+ break;
+ case STATE_PCM_BIAS:
+ append(dst, "PCMbias");
+ break;
+ case STATE_SHADOW_AMBIENT:
+ append(dst, "CompareFailValue");
+ break;
+ case STATE_FB_SIZE:
+ append(dst, "FbSize");
+ break;
+ case STATE_ROT_MATRIX_0:
+ append(dst, "rotMatrixRow0");
+ break;
+ case STATE_ROT_MATRIX_1:
+ append(dst, "rotMatrixRow1");
+ break;
+ default:
+ /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
+ append(dst, "driverState");
+ }
+}
+
+static void
+append_face(char *dst, GLint face)
+{
+ if (face == 0)
+ append(dst, "front.");
+ else
+ append(dst, "back.");
+}
+
+static void
+append_index(char *dst, GLint index)
+{
+ char s[20];
+ _mesa_sprintf(s, "[%d]", index);
+ append(dst, s);
+}
+
+/**
+ * Make a string from the given state vector.
+ * For example, return "state.matrix.texture[2].inverse".
+ * Use _mesa_free() to deallocate the string.
+ */
+char *
+_mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
+{
+ char str[1000] = "";
+ char tmp[30];
+
+ append(str, "state.");
+ append_token(str, state[0]);
+
+ switch (state[0]) {
+ case STATE_MATERIAL:
+ append_face(str, state[1]);
+ append_token(str, state[2]);
+ break;
+ case STATE_LIGHT:
+ append_index(str, state[1]); /* light number [i]. */
+ append_token(str, state[2]); /* coefficients */
+ break;
+ case STATE_LIGHTMODEL_AMBIENT:
+ append(str, "lightmodel.ambient");
+ break;
+ case STATE_LIGHTMODEL_SCENECOLOR:
+ if (state[1] == 0) {
+ append(str, "lightmodel.front.scenecolor");
+ }
+ else {
+ append(str, "lightmodel.back.scenecolor");
+ }
+ break;
+ case STATE_LIGHTPROD:
+ append_index(str, state[1]); /* light number [i]. */
+ append_face(str, state[2]);
+ append_token(str, state[3]);
+ break;
+ case STATE_TEXGEN:
+ append_index(str, state[1]); /* tex unit [i] */
+ append_token(str, state[2]); /* plane coef */
+ break;
+ case STATE_TEXENV_COLOR:
+ append_index(str, state[1]); /* tex unit [i] */
+ append(str, "color");
+ break;
+ case STATE_CLIPPLANE:
+ append_index(str, state[1]); /* plane [i] */
+ append(str, ".plane");
+ break;
+ case STATE_MODELVIEW_MATRIX:
+ case STATE_PROJECTION_MATRIX:
+ case STATE_MVP_MATRIX:
+ case STATE_TEXTURE_MATRIX:
+ case STATE_PROGRAM_MATRIX:
+ case STATE_COLOR_MATRIX:
+ {
+ /* state[0] = modelview, projection, texture, etc. */
+ /* state[1] = which texture matrix or program matrix */
+ /* state[2] = first row to fetch */
+ /* state[3] = last row to fetch */
+ /* state[4] = transpose, inverse or invtrans */
+ const gl_state_index mat = state[0];
+ const GLuint index = (GLuint) state[1];
+ const GLuint firstRow = (GLuint) state[2];
+ const GLuint lastRow = (GLuint) state[3];
+ const gl_state_index modifier = state[4];
+ if (index ||
+ mat == STATE_TEXTURE_MATRIX ||
+ mat == STATE_PROGRAM_MATRIX)
+ append_index(str, index);
+ if (modifier)
+ append_token(str, modifier);
+ if (firstRow == lastRow)
+ _mesa_sprintf(tmp, ".row[%d]", firstRow);
+ else
+ _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
+ append(str, tmp);
+ }
+ break;
+ case STATE_POINT_SIZE:
+ break;
+ case STATE_POINT_ATTENUATION:
+ break;
+ case STATE_FOG_PARAMS:
+ break;
+ case STATE_FOG_COLOR:
+ break;
+ case STATE_DEPTH_RANGE:
+ break;
+ case STATE_FRAGMENT_PROGRAM:
+ case STATE_VERTEX_PROGRAM:
+ /* state[1] = {STATE_ENV, STATE_LOCAL} */
+ /* state[2] = parameter index */
+ append_token(str, state[1]);
+ append_index(str, state[2]);
+ break;
+ case STATE_INTERNAL:
+ append_token(str, state[1]);
+ if (state[1] == STATE_CURRENT_ATTRIB)
+ append_index(str, state[2]);
+ break;
+ default:
+ _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
+ break;
+ }
+
+ return _mesa_strdup(str);
+}
+
+
+/**
+ * Loop over all the parameters in a parameter list. If the parameter
+ * is a GL state reference, look up the current value of that state
+ * variable and put it into the parameter's Value[4] array.
+ * This would be called at glBegin time when using a fragment program.
+ */
+void
+_mesa_load_state_parameters(GLcontext *ctx,
+ struct gl_program_parameter_list *paramList)
+{
+ GLuint i;
+
+ if (!paramList)
+ return;
+
+ /*assert(ctx->Driver.NeedFlush == 0);*/
+
+ for (i = 0; i < paramList->NumParameters; i++) {
+ if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
+ _mesa_fetch_state(ctx,
+ (gl_state_index *) paramList->Parameters[i].StateIndexes,
+ paramList->ParameterValues[i]);
+ }
+ }
+}
+
+
+/**
+ * Copy the 16 elements of a matrix into four consecutive program
+ * registers starting at 'pos'.
+ */
+static void
+load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
+{
+ GLuint i;
+ for (i = 0; i < 4; i++) {
+ registers[pos + i][0] = mat[0 + i];
+ registers[pos + i][1] = mat[4 + i];
+ registers[pos + i][2] = mat[8 + i];
+ registers[pos + i][3] = mat[12 + i];
+ }
+}
+
+
+/**
+ * As above, but transpose the matrix.
+ */
+static void
+load_transpose_matrix(GLfloat registers[][4], GLuint pos,
+ const GLfloat mat[16])
+{
+ MEMCPY(registers[pos], mat, 16 * sizeof(GLfloat));
+}
+
+
+/**
+ * Load current vertex program's parameter registers with tracked
+ * matrices (if NV program). This only needs to be done per
+ * glBegin/glEnd, not per-vertex.
+ */
+void
+_mesa_load_tracked_matrices(GLcontext *ctx)
+{
+ GLuint i;
+
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
+ /* point 'mat' at source matrix */
+ GLmatrix *mat;
+ if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
+ mat = ctx->ModelviewMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
+ mat = ctx->ProjectionMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
+ mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) {
+ mat = ctx->ColorMatrixStack.Top;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
+ /* XXX verify the combined matrix is up to date */
+ mat = &ctx->_ModelProjectMatrix;
+ }
+ else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
+ ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
+ GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
+ ASSERT(n < MAX_PROGRAM_MATRICES);
+ mat = ctx->ProgramMatrixStack[n].Top;
+ }
+ else {
+ /* no matrix is tracked, but we leave the register values as-is */
+ assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
+ continue;
+ }
+
+ /* load the matrix values into sequential registers */
+ if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
+ load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+ }
+ else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
+ _math_matrix_analyse(mat); /* update the inverse */
+ ASSERT(!_math_matrix_is_dirty(mat));
+ load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+ }
+ else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
+ load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
+ }
+ else {
+ assert(ctx->VertexProgram.TrackMatrixTransform[i]
+ == GL_INVERSE_TRANSPOSE_NV);
+ _math_matrix_analyse(mat); /* update the inverse */
+ ASSERT(!_math_matrix_is_dirty(mat));
+ load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
+ }
+ }
+}
diff --git a/mesalib/src/mesa/shader/prog_statevars.h b/mesalib/src/mesa/shader/prog_statevars.h
new file mode 100644
index 000000000..1180d9eaa
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_statevars.h
@@ -0,0 +1,145 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 PROG_STATEVARS_H
+#define PROG_STATEVARS_H
+
+#include "main/mtypes.h"
+
+
+/**
+ * Number of STATE_* values we need to address any GL state.
+ * Used to dimension arrays.
+ */
+#define STATE_LENGTH 5
+
+
+/**
+ * Used for describing GL state referenced from inside ARB vertex and
+ * fragment programs.
+ * A string such as "state.light[0].ambient" gets translated into a
+ * sequence of tokens such as [ STATE_LIGHT, 0, STATE_AMBIENT ].
+ *
+ * For state that's an array, like STATE_CLIPPLANE, the 2nd token [1] should
+ * always be the array index.
+ */
+typedef enum gl_state_index_ {
+ STATE_MATERIAL = 100, /* start at 100 so small ints are seen as ints */
+
+ STATE_LIGHT,
+ STATE_LIGHTMODEL_AMBIENT,
+ STATE_LIGHTMODEL_SCENECOLOR,
+ STATE_LIGHTPROD,
+
+ STATE_TEXGEN,
+
+ STATE_FOG_COLOR,
+ STATE_FOG_PARAMS,
+
+ STATE_CLIPPLANE,
+
+ STATE_POINT_SIZE,
+ STATE_POINT_ATTENUATION,
+
+ STATE_MODELVIEW_MATRIX,
+ STATE_PROJECTION_MATRIX,
+ STATE_MVP_MATRIX,
+ STATE_TEXTURE_MATRIX,
+ STATE_PROGRAM_MATRIX,
+ STATE_COLOR_MATRIX,
+ STATE_MATRIX_INVERSE,
+ STATE_MATRIX_TRANSPOSE,
+ STATE_MATRIX_INVTRANS,
+
+ STATE_AMBIENT,
+ STATE_DIFFUSE,
+ STATE_SPECULAR,
+ STATE_EMISSION,
+ STATE_SHININESS,
+ STATE_HALF_VECTOR,
+
+ STATE_POSITION, /**< xyzw = position */
+ STATE_ATTENUATION, /**< xyz = attenuation, w = spot exponent */
+ STATE_SPOT_DIRECTION, /**< xyz = direction, w = cos(cutoff) */
+ STATE_SPOT_CUTOFF, /**< x = cutoff, yzw = undefined */
+
+ STATE_TEXGEN_EYE_S,
+ STATE_TEXGEN_EYE_T,
+ STATE_TEXGEN_EYE_R,
+ STATE_TEXGEN_EYE_Q,
+ STATE_TEXGEN_OBJECT_S,
+ STATE_TEXGEN_OBJECT_T,
+ STATE_TEXGEN_OBJECT_R,
+ STATE_TEXGEN_OBJECT_Q,
+
+ STATE_TEXENV_COLOR,
+
+ STATE_DEPTH_RANGE,
+
+ STATE_VERTEX_PROGRAM,
+ STATE_FRAGMENT_PROGRAM,
+
+ STATE_ENV,
+ STATE_LOCAL,
+
+ STATE_INTERNAL, /* Mesa additions */
+ STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */
+ STATE_NORMAL_SCALE,
+ STATE_TEXRECT_SCALE,
+ STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
+ STATE_LIGHT_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */
+ STATE_LIGHT_POSITION, /* object vs eye space */
+ STATE_LIGHT_POSITION_NORMALIZED, /* object vs eye space */
+ STATE_LIGHT_HALF_VECTOR, /* object vs eye space */
+ STATE_PT_SCALE, /**< Pixel transfer RGBA scale */
+ STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
+ STATE_PCM_SCALE, /**< Post color matrix RGBA scale */
+ STATE_PCM_BIAS, /**< Post color matrix RGBA bias */
+ STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
+ STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */
+ STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
+ STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
+ STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
+} gl_state_index;
+
+
+
+extern void
+_mesa_load_state_parameters(GLcontext *ctx,
+ struct gl_program_parameter_list *paramList);
+
+
+extern GLbitfield
+_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]);
+
+
+extern char *
+_mesa_program_state_string(const gl_state_index state[STATE_LENGTH]);
+
+
+extern void
+_mesa_load_tracked_matrices(GLcontext *ctx);
+
+
+#endif /* PROG_STATEVARS_H */
diff --git a/mesalib/src/mesa/shader/prog_uniform.c b/mesalib/src/mesa/shader/prog_uniform.c
new file mode 100644
index 000000000..064271314
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_uniform.c
@@ -0,0 +1,165 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file prog_uniform.c
+ * Shader uniform functions.
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "prog_uniform.h"
+
+
+struct gl_uniform_list *
+_mesa_new_uniform_list(void)
+{
+ return CALLOC_STRUCT(gl_uniform_list);
+}
+
+
+void
+_mesa_free_uniform_list(struct gl_uniform_list *list)
+{
+ GLuint i;
+ for (i = 0; i < list->NumUniforms; i++) {
+ _mesa_free((void *) list->Uniforms[i].Name);
+ }
+ _mesa_free(list->Uniforms);
+ _mesa_free(list);
+}
+
+
+struct gl_uniform *
+_mesa_append_uniform(struct gl_uniform_list *list,
+ const char *name, GLenum target, GLuint progPos)
+{
+ const GLuint oldNum = list->NumUniforms;
+ struct gl_uniform *uniform;
+ GLint index;
+
+ assert(target == GL_VERTEX_PROGRAM_ARB ||
+ target == GL_FRAGMENT_PROGRAM_ARB);
+
+ index = _mesa_lookup_uniform(list, name);
+ if (index < 0) {
+ /* not found - append to list */
+
+ if (oldNum + 1 > list->Size) {
+ /* Need to grow the list array (alloc some extra) */
+ list->Size += 4;
+
+ /* realloc arrays */
+ list->Uniforms = (struct gl_uniform *)
+ _mesa_realloc(list->Uniforms,
+ oldNum * sizeof(struct gl_uniform),
+ list->Size * sizeof(struct gl_uniform));
+ }
+
+ if (!list->Uniforms) {
+ /* out of memory */
+ list->NumUniforms = 0;
+ list->Size = 0;
+ return GL_FALSE;
+ }
+
+ uniform = list->Uniforms + oldNum;
+
+ uniform->Name = _mesa_strdup(name);
+ uniform->VertPos = -1;
+ uniform->FragPos = -1;
+ uniform->Initialized = GL_FALSE;
+
+ list->NumUniforms++;
+ }
+ else {
+ /* found */
+ uniform = list->Uniforms + index;
+ }
+
+ /* update position for the vertex or fragment program */
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ if (uniform->VertPos != -1) {
+ /* this uniform is already in the list - that shouldn't happen */
+ return GL_FALSE;
+ }
+ uniform->VertPos = progPos;
+ }
+ else {
+ if (uniform->FragPos != -1) {
+ /* this uniform is already in the list - that shouldn't happen */
+ return GL_FALSE;
+ }
+ uniform->FragPos = progPos;
+ }
+
+ return uniform;
+}
+
+
+/**
+ * Return the location/index of the named uniform in the uniform list,
+ * or -1 if not found.
+ */
+GLint
+_mesa_lookup_uniform(const struct gl_uniform_list *list, const char *name)
+{
+ GLuint i;
+ for (i = 0; list && i < list->NumUniforms; i++) {
+ if (!_mesa_strcmp(list->Uniforms[i].Name, name)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+GLint
+_mesa_longest_uniform_name(const struct gl_uniform_list *list)
+{
+ GLint max = 0;
+ GLuint i;
+ for (i = 0; list && i < list->NumUniforms; i++) {
+ GLint len = (GLint)_mesa_strlen(list->Uniforms[i].Name);
+ if (len > max)
+ max = len;
+ }
+ return max;
+}
+
+
+void
+_mesa_print_uniforms(const struct gl_uniform_list *list)
+{
+ GLuint i;
+ printf("Uniform list %p:\n", (void *) list);
+ for (i = 0; i < list->NumUniforms; i++) {
+ printf("%d: %s %d %d\n",
+ i,
+ list->Uniforms[i].Name,
+ list->Uniforms[i].VertPos,
+ list->Uniforms[i].FragPos);
+ }
+}
diff --git a/mesalib/src/mesa/shader/prog_uniform.h b/mesalib/src/mesa/shader/prog_uniform.h
new file mode 100644
index 000000000..22a2bfd97
--- /dev/null
+++ b/mesalib/src/mesa/shader/prog_uniform.h
@@ -0,0 +1,92 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file prog_uniform.c
+ * Shader uniform functions.
+ * \author Brian Paul
+ */
+
+#ifndef PROG_UNIFORM_H
+#define PROG_UNIFORM_H
+
+#include "main/mtypes.h"
+#include "prog_statevars.h"
+
+
+/**
+ * Shader program uniform variable.
+ * The glGetUniformLocation() and glUniform() commands will use this
+ * information.
+ * Note that a uniform such as "binormal" might be used in both the
+ * vertex shader and the fragment shader. When glUniform() is called to
+ * set the uniform's value, it must be updated in both the vertex and
+ * fragment shaders. The uniform may be in different locations in the
+ * two shaders so we keep track of that here.
+ */
+struct gl_uniform
+{
+ const char *Name; /**< Null-terminated string */
+ GLint VertPos;
+ GLint FragPos;
+ GLboolean Initialized; /**< For debug. Has this uniform been set? */
+#if 0
+ GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */
+ GLuint Size; /**< Number of components (1..4) */
+#endif
+};
+
+
+/**
+ * List of gl_uniforms
+ */
+struct gl_uniform_list
+{
+ GLuint Size; /**< allocated size of Uniforms array */
+ GLuint NumUniforms; /**< number of uniforms in the array */
+ struct gl_uniform *Uniforms; /**< Array [Size] */
+};
+
+
+extern struct gl_uniform_list *
+_mesa_new_uniform_list(void);
+
+extern void
+_mesa_free_uniform_list(struct gl_uniform_list *list);
+
+extern struct gl_uniform *
+_mesa_append_uniform(struct gl_uniform_list *list,
+ const char *name, GLenum target, GLuint progPos);
+
+extern GLint
+_mesa_lookup_uniform(const struct gl_uniform_list *list, const char *name);
+
+extern GLint
+_mesa_longest_uniform_name(const struct gl_uniform_list *list);
+
+extern void
+_mesa_print_uniforms(const struct gl_uniform_list *list);
+
+
+#endif /* PROG_UNIFORM_H */
diff --git a/mesalib/src/mesa/shader/program.c b/mesalib/src/mesa/shader/program.c
new file mode 100644
index 000000000..2cd6eb8a3
--- /dev/null
+++ b/mesalib/src/mesa/shader/program.c
@@ -0,0 +1,889 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file program.c
+ * Vertex and fragment program support functions.
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "program.h"
+#include "prog_cache.h"
+#include "prog_parameter.h"
+#include "prog_instruction.h"
+
+
+/**
+ * A pointer to this dummy program is put into the hash table when
+ * glGenPrograms is called.
+ */
+struct gl_program _mesa_DummyProgram;
+
+
+/**
+ * Init context's vertex/fragment program state
+ */
+void
+_mesa_init_program(GLcontext *ctx)
+{
+ GLuint i;
+
+ /*
+ * If this assertion fails, we need to increase the field
+ * size for register indexes.
+ */
+ ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
+ <= (1 << INST_INDEX_BITS));
+ ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
+ <= (1 << INST_INDEX_BITS));
+
+ /* If this fails, increase prog_instruction::TexSrcUnit size */
+ ASSERT(MAX_TEXTURE_UNITS < (1 << 5));
+
+ /* If this fails, increase prog_instruction::TexSrcTarget size */
+ ASSERT(NUM_TEXTURE_TARGETS < (1 << 3));
+
+ ctx->Program.ErrorPos = -1;
+ ctx->Program.ErrorString = _mesa_strdup("");
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ ctx->VertexProgram.Enabled = GL_FALSE;
+#if FEATURE_es2_glsl
+ ctx->VertexProgram.PointSizeEnabled = GL_TRUE;
+#else
+ ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
+#endif
+ ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ ctx->Shared->DefaultVertexProgram);
+ assert(ctx->VertexProgram.Current);
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
+ ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
+ ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
+ }
+ ctx->VertexProgram.Cache = _mesa_new_program_cache();
+#endif
+
+#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
+ ctx->FragmentProgram.Enabled = GL_FALSE;
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ ctx->Shared->DefaultFragmentProgram);
+ assert(ctx->FragmentProgram.Current);
+ ctx->FragmentProgram.Cache = _mesa_new_program_cache();
+#endif
+
+
+ /* XXX probably move this stuff */
+#if FEATURE_ATI_fragment_shader
+ ctx->ATIFragmentShader.Enabled = GL_FALSE;
+ ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
+ assert(ctx->ATIFragmentShader.Current);
+ ctx->ATIFragmentShader.Current->RefCount++;
+#endif
+}
+
+
+/**
+ * Free a context's vertex/fragment program state
+ */
+void
+_mesa_free_program_data(GLcontext *ctx)
+{
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
+ _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
+#endif
+#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
+ _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache);
+#endif
+ /* XXX probably move this stuff */
+#if FEATURE_ATI_fragment_shader
+ if (ctx->ATIFragmentShader.Current) {
+ ctx->ATIFragmentShader.Current->RefCount--;
+ if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
+ _mesa_free(ctx->ATIFragmentShader.Current);
+ }
+ }
+#endif
+ _mesa_free((void *) ctx->Program.ErrorString);
+}
+
+
+/**
+ * Update the default program objects in the given context to reference those
+ * specified in the shared state and release those referencing the old
+ * shared state.
+ */
+void
+_mesa_update_default_objects_program(GLcontext *ctx)
+{
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
+ (struct gl_vertex_program *)
+ ctx->Shared->DefaultVertexProgram);
+ assert(ctx->VertexProgram.Current);
+#endif
+
+#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
+ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
+ (struct gl_fragment_program *)
+ ctx->Shared->DefaultFragmentProgram);
+ assert(ctx->FragmentProgram.Current);
+#endif
+
+ /* XXX probably move this stuff */
+#if FEATURE_ATI_fragment_shader
+ if (ctx->ATIFragmentShader.Current) {
+ ctx->ATIFragmentShader.Current->RefCount--;
+ if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
+ _mesa_free(ctx->ATIFragmentShader.Current);
+ }
+ }
+ ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
+ assert(ctx->ATIFragmentShader.Current);
+ ctx->ATIFragmentShader.Current->RefCount++;
+#endif
+}
+
+
+/**
+ * Set the vertex/fragment program error state (position and error string).
+ * This is generally called from within the parsers.
+ */
+void
+_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
+{
+ ctx->Program.ErrorPos = pos;
+ _mesa_free((void *) ctx->Program.ErrorString);
+ if (!string)
+ string = "";
+ ctx->Program.ErrorString = _mesa_strdup(string);
+}
+
+
+/**
+ * Find the line number and column for 'pos' within 'string'.
+ * Return a copy of the line which contains 'pos'. Free the line with
+ * _mesa_free().
+ * \param string the program string
+ * \param pos the position within the string
+ * \param line returns the line number corresponding to 'pos'.
+ * \param col returns the column number corresponding to 'pos'.
+ * \return copy of the line containing 'pos'.
+ */
+const GLubyte *
+_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
+ GLint *line, GLint *col)
+{
+ const GLubyte *lineStart = string;
+ const GLubyte *p = string;
+ GLubyte *s;
+ int len;
+
+ *line = 1;
+
+ while (p != pos) {
+ if (*p == (GLubyte) '\n') {
+ (*line)++;
+ lineStart = p + 1;
+ }
+ p++;
+ }
+
+ *col = (pos - lineStart) + 1;
+
+ /* return copy of this line */
+ while (*p != 0 && *p != '\n')
+ p++;
+ len = p - lineStart;
+ s = (GLubyte *) _mesa_malloc(len + 1);
+ _mesa_memcpy(s, lineStart, len);
+ s[len] = 0;
+
+ return s;
+}
+
+
+/**
+ * Initialize a new vertex/fragment program object.
+ */
+static struct gl_program *
+_mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog,
+ GLenum target, GLuint id)
+{
+ (void) ctx;
+ if (prog) {
+ GLuint i;
+ _mesa_bzero(prog, sizeof(*prog));
+ prog->Id = id;
+ prog->Target = target;
+ prog->Resident = GL_TRUE;
+ prog->RefCount = 1;
+ prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
+
+ /* default mapping from samplers to texture units */
+ for (i = 0; i < MAX_SAMPLERS; i++)
+ prog->SamplerUnits[i] = i;
+ }
+
+ return prog;
+}
+
+
+/**
+ * Initialize a new fragment program object.
+ */
+struct gl_program *
+_mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog)
+ return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+ else
+ return NULL;
+}
+
+
+/**
+ * Initialize a new vertex program object.
+ */
+struct gl_program *
+_mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog)
+ return _mesa_init_program_struct( ctx, &prog->Base, target, id );
+ else
+ return NULL;
+}
+
+
+/**
+ * Allocate and initialize a new fragment/vertex program object but
+ * don't put it into the program hash table. Called via
+ * ctx->Driver.NewProgram. May be overridden (ie. replaced) by a
+ * device driver function to implement OO deriviation with additional
+ * types not understood by this function.
+ *
+ * \param ctx context
+ * \param id program id/number
+ * \param target program target/type
+ * \return pointer to new program object
+ */
+struct gl_program *
+_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
+{
+ struct gl_program *prog;
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
+ case GL_VERTEX_STATE_PROGRAM_NV:
+ prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
+ target, id );
+ break;
+ case GL_FRAGMENT_PROGRAM_NV:
+ case GL_FRAGMENT_PROGRAM_ARB:
+ prog =_mesa_init_fragment_program(ctx,
+ CALLOC_STRUCT(gl_fragment_program),
+ target, id );
+ break;
+ default:
+ _mesa_problem(ctx, "bad target in _mesa_new_program");
+ prog = NULL;
+ }
+ return prog;
+}
+
+
+/**
+ * Delete a program and remove it from the hash table, ignoring the
+ * reference count.
+ * Called via ctx->Driver.DeleteProgram. May be wrapped (OO deriviation)
+ * by a device driver function.
+ */
+void
+_mesa_delete_program(GLcontext *ctx, struct gl_program *prog)
+{
+ (void) ctx;
+ ASSERT(prog);
+ ASSERT(prog->RefCount==0);
+
+ if (prog == &_mesa_DummyProgram)
+ return;
+
+ if (prog->String)
+ _mesa_free(prog->String);
+
+ _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
+
+ if (prog->Parameters) {
+ _mesa_free_parameter_list(prog->Parameters);
+ }
+ if (prog->Varying) {
+ _mesa_free_parameter_list(prog->Varying);
+ }
+ if (prog->Attributes) {
+ _mesa_free_parameter_list(prog->Attributes);
+ }
+
+ /* XXX this is a little ugly */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
+ if (vprog->TnlData)
+ _mesa_free(vprog->TnlData);
+ }
+
+ _mesa_free(prog);
+}
+
+
+/**
+ * Return the gl_program object for a given ID.
+ * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
+ * casts elsewhere.
+ */
+struct gl_program *
+_mesa_lookup_program(GLcontext *ctx, GLuint id)
+{
+ if (id)
+ return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
+ else
+ return NULL;
+}
+
+
+/**
+ * Reference counting for vertex/fragment programs
+ */
+void
+_mesa_reference_program(GLcontext *ctx,
+ struct gl_program **ptr,
+ struct gl_program *prog)
+{
+ assert(ptr);
+ if (*ptr && prog) {
+ /* sanity check */
+ if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
+ ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
+ ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
+ prog->Target == GL_FRAGMENT_PROGRAM_NV);
+ }
+ if (*ptr == prog) {
+ return; /* no change */
+ }
+ if (*ptr) {
+ GLboolean deleteFlag;
+
+ /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
+#if 0
+ printf("Program %p ID=%u Target=%s Refcount-- to %d\n",
+ *ptr, (*ptr)->Id,
+ ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"),
+ (*ptr)->RefCount - 1);
+#endif
+ ASSERT((*ptr)->RefCount > 0);
+ (*ptr)->RefCount--;
+
+ deleteFlag = ((*ptr)->RefCount == 0);
+ /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
+
+ if (deleteFlag) {
+ ASSERT(ctx);
+ ctx->Driver.DeleteProgram(ctx, *ptr);
+ }
+
+ *ptr = NULL;
+ }
+
+ assert(!*ptr);
+ if (prog) {
+ /*_glthread_LOCK_MUTEX(prog->Mutex);*/
+ prog->RefCount++;
+#if 0
+ printf("Program %p ID=%u Target=%s Refcount++ to %d\n",
+ prog, prog->Id,
+ (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"),
+ prog->RefCount);
+#endif
+ /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
+ }
+
+ *ptr = prog;
+}
+
+
+/**
+ * Return a copy of a program.
+ * XXX Problem here if the program object is actually OO-derivation
+ * made by a device driver.
+ */
+struct gl_program *
+_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
+{
+ struct gl_program *clone;
+
+ clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
+ if (!clone)
+ return NULL;
+
+ assert(clone->Target == prog->Target);
+ assert(clone->RefCount == 1);
+
+ clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
+ clone->Format = prog->Format;
+ clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
+ if (!clone->Instructions) {
+ _mesa_reference_program(ctx, &clone, NULL);
+ return NULL;
+ }
+ _mesa_copy_instructions(clone->Instructions, prog->Instructions,
+ prog->NumInstructions);
+ clone->InputsRead = prog->InputsRead;
+ clone->OutputsWritten = prog->OutputsWritten;
+ clone->SamplersUsed = prog->SamplersUsed;
+ clone->ShadowSamplers = prog->ShadowSamplers;
+ memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
+
+ if (prog->Parameters)
+ clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
+ memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
+ if (prog->Varying)
+ clone->Varying = _mesa_clone_parameter_list(prog->Varying);
+ if (prog->Attributes)
+ clone->Attributes = _mesa_clone_parameter_list(prog->Attributes);
+ memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
+ clone->NumInstructions = prog->NumInstructions;
+ clone->NumTemporaries = prog->NumTemporaries;
+ clone->NumParameters = prog->NumParameters;
+ clone->NumAttributes = prog->NumAttributes;
+ clone->NumAddressRegs = prog->NumAddressRegs;
+ clone->NumNativeInstructions = prog->NumNativeInstructions;
+ clone->NumNativeTemporaries = prog->NumNativeTemporaries;
+ clone->NumNativeParameters = prog->NumNativeParameters;
+ clone->NumNativeAttributes = prog->NumNativeAttributes;
+ clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
+ clone->NumAluInstructions = prog->NumAluInstructions;
+ clone->NumTexInstructions = prog->NumTexInstructions;
+ clone->NumTexIndirections = prog->NumTexIndirections;
+ clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
+ clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
+ clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
+
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ const struct gl_vertex_program *vp
+ = (const struct gl_vertex_program *) prog;
+ struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
+ vpc->IsPositionInvariant = vp->IsPositionInvariant;
+ vpc->IsNVProgram = vp->IsNVProgram;
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ const struct gl_fragment_program *fp
+ = (const struct gl_fragment_program *) prog;
+ struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
+ fpc->FogOption = fp->FogOption;
+ fpc->UsesKill = fp->UsesKill;
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
+ }
+
+ return clone;
+}
+
+
+/**
+ * Insert 'count' NOP instructions at 'start' in the given program.
+ * Adjust branch targets accordingly.
+ */
+GLboolean
+_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
+{
+ const GLuint origLen = prog->NumInstructions;
+ const GLuint newLen = origLen + count;
+ struct prog_instruction *newInst;
+ GLuint i;
+
+ /* adjust branches */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->BranchTarget > 0) {
+ if ((GLuint)inst->BranchTarget >= start) {
+ inst->BranchTarget += count;
+ }
+ }
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ return GL_FALSE;
+ }
+
+ /* Copy 'start' instructions into new instruction buffer */
+ _mesa_copy_instructions(newInst, prog->Instructions, start);
+
+ /* init the new instructions */
+ _mesa_init_instructions(newInst + start, count);
+
+ /* Copy the remaining/tail instructions to new inst buffer */
+ _mesa_copy_instructions(newInst + start + count,
+ prog->Instructions + start,
+ origLen - start);
+
+ /* free old instructions */
+ _mesa_free_instructions(prog->Instructions, origLen);
+
+ /* install new instructions */
+ prog->Instructions = newInst;
+ prog->NumInstructions = newLen;
+
+ return GL_TRUE;
+}
+
+/**
+ * Delete 'count' instructions at 'start' in the given program.
+ * Adjust branch targets accordingly.
+ */
+GLboolean
+_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
+{
+ const GLuint origLen = prog->NumInstructions;
+ const GLuint newLen = origLen - count;
+ struct prog_instruction *newInst;
+ GLuint i;
+
+ /* adjust branches */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->BranchTarget > 0) {
+ if (inst->BranchTarget > start) {
+ inst->BranchTarget -= count;
+ }
+ }
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ return GL_FALSE;
+ }
+
+ /* Copy 'start' instructions into new instruction buffer */
+ _mesa_copy_instructions(newInst, prog->Instructions, start);
+
+ /* Copy the remaining/tail instructions to new inst buffer */
+ _mesa_copy_instructions(newInst + start,
+ prog->Instructions + start + count,
+ newLen - start);
+
+ /* free old instructions */
+ _mesa_free_instructions(prog->Instructions, origLen);
+
+ /* install new instructions */
+ prog->Instructions = newInst;
+ prog->NumInstructions = newLen;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Search instructions for registers that match (oldFile, oldIndex),
+ * replacing them with (newFile, newIndex).
+ */
+static void
+replace_registers(struct prog_instruction *inst, GLuint numInst,
+ GLuint oldFile, GLuint oldIndex,
+ GLuint newFile, GLuint newIndex)
+{
+ GLuint i, j;
+ for (i = 0; i < numInst; i++) {
+ /* src regs */
+ for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) {
+ if (inst[i].SrcReg[j].File == oldFile &&
+ inst[i].SrcReg[j].Index == oldIndex) {
+ inst[i].SrcReg[j].File = newFile;
+ inst[i].SrcReg[j].Index = newIndex;
+ }
+ }
+ /* dst reg */
+ if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
+ inst[i].DstReg.File = newFile;
+ inst[i].DstReg.Index = newIndex;
+ }
+ }
+}
+
+
+/**
+ * Search instructions for references to program parameters. When found,
+ * increment the parameter index by 'offset'.
+ * Used when combining programs.
+ */
+static void
+adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
+ GLuint offset)
+{
+ GLuint i, j;
+ for (i = 0; i < numInst; i++) {
+ for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) {
+ GLuint f = inst[i].SrcReg[j].File;
+ if (f == PROGRAM_CONSTANT ||
+ f == PROGRAM_UNIFORM ||
+ f == PROGRAM_STATE_VAR) {
+ inst[i].SrcReg[j].Index += offset;
+ }
+ }
+ }
+}
+
+
+/**
+ * Combine two programs into one. Fix instructions so the outputs of
+ * the first program go to the inputs of the second program.
+ */
+struct gl_program *
+_mesa_combine_programs(GLcontext *ctx,
+ const struct gl_program *progA,
+ const struct gl_program *progB)
+{
+ struct prog_instruction *newInst;
+ struct gl_program *newProg;
+ const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
+ const GLuint lenB = progB->NumInstructions;
+ const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
+ const GLuint newLength = lenA + lenB;
+ GLbitfield inputsB;
+ GLuint i;
+
+ ASSERT(progA->Target == progB->Target);
+
+ newInst = _mesa_alloc_instructions(newLength);
+ if (!newInst)
+ return GL_FALSE;
+
+ _mesa_copy_instructions(newInst, progA->Instructions, lenA);
+ _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
+
+ /* adjust branch / instruction addresses for B's instructions */
+ for (i = 0; i < lenB; i++) {
+ newInst[lenA + i].BranchTarget += lenA;
+ }
+
+ newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
+ newProg->Instructions = newInst;
+ newProg->NumInstructions = newLength;
+
+ if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct gl_fragment_program *fprogA, *fprogB, *newFprog;
+ GLbitfield progB_inputsRead = progB->InputsRead;
+ GLint progB_colorFile, progB_colorIndex;
+
+ fprogA = (struct gl_fragment_program *) progA;
+ fprogB = (struct gl_fragment_program *) progB;
+ newFprog = (struct gl_fragment_program *) newProg;
+
+ newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
+
+ /* We'll do a search and replace for instances
+ * of progB_colorFile/progB_colorIndex below...
+ */
+ progB_colorFile = PROGRAM_INPUT;
+ progB_colorIndex = FRAG_ATTRIB_COL0;
+
+ /*
+ * The fragment program may get color from a state var rather than
+ * a fragment input (vertex output) if it's constant.
+ * See the texenvprogram.c code.
+ * So, search the program's parameter list now to see if the program
+ * gets color from a state var instead of a conventional fragment
+ * input register.
+ */
+ for (i = 0; i < progB->Parameters->NumParameters; i++) {
+ struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
+ if (p->Type == PROGRAM_STATE_VAR &&
+ p->StateIndexes[0] == STATE_INTERNAL &&
+ p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
+ p->StateIndexes[2] == VERT_ATTRIB_COLOR0) {
+ progB_inputsRead |= FRAG_BIT_COL0;
+ progB_colorFile = PROGRAM_STATE_VAR;
+ progB_colorIndex = i;
+ break;
+ }
+ }
+
+ /* Connect color outputs of fprogA to color inputs of fprogB, via a
+ * new temporary register.
+ */
+ if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) &&
+ (progB_inputsRead & FRAG_BIT_COL0)) {
+ GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
+ if (tempReg < 0) {
+ _mesa_problem(ctx, "No free temp regs found in "
+ "_mesa_combine_programs(), using 31");
+ tempReg = 31;
+ }
+ /* replace writes to result.color[0] with tempReg */
+ replace_registers(newInst, lenA,
+ PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
+ PROGRAM_TEMPORARY, tempReg);
+ /* replace reads from the input color with tempReg */
+ replace_registers(newInst + lenA, lenB,
+ progB_colorFile, progB_colorIndex, /* search for */
+ PROGRAM_TEMPORARY, tempReg /* replace with */ );
+ }
+
+ /* compute combined program's InputsRead */
+ inputsB = progB_inputsRead;
+ if (progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
+ inputsB &= ~(1 << FRAG_ATTRIB_COL0);
+ }
+ newProg->InputsRead = progA->InputsRead | inputsB;
+ newProg->OutputsWritten = progB->OutputsWritten;
+ newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
+ }
+ else {
+ /* vertex program */
+ assert(0); /* XXX todo */
+ }
+
+ /*
+ * Merge parameters (uniforms, constants, etc)
+ */
+ newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
+ progB->Parameters);
+
+ adjust_param_indexes(newInst + lenA, lenB, numParamsA);
+
+
+ return newProg;
+}
+
+
+
+
+/**
+ * Scan the given program to find a free register of the given type.
+ * \param regFile - PROGRAM_INPUT, PROGRAM_OUTPUT or PROGRAM_TEMPORARY
+ */
+GLint
+_mesa_find_free_register(const struct gl_program *prog, GLuint regFile)
+{
+ GLboolean used[MAX_PROGRAM_TEMPS];
+ GLuint i, k;
+
+ assert(regFile == PROGRAM_INPUT ||
+ regFile == PROGRAM_OUTPUT ||
+ regFile == PROGRAM_TEMPORARY);
+
+ _mesa_memset(used, 0, sizeof(used));
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
+
+ for (k = 0; k < n; k++) {
+ if (inst->SrcReg[k].File == regFile) {
+ used[inst->SrcReg[k].Index] = GL_TRUE;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (!used[i])
+ return i;
+ }
+
+ return -1;
+}
+
+
+
+/**
+ * "Post-process" a GPU program. This is intended to be used for debugging.
+ * Example actions include no-op'ing instructions or changing instruction
+ * behaviour.
+ */
+void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog)
+{
+ static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
+ GLuint i;
+ GLuint whiteSwizzle;
+ GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
+ white, 4, &whiteSwizzle);
+
+ (void) whiteIndex;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
+
+ (void) n;
+
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+#if 0
+ /* replace TEX/TXP/TXB with MOV */
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+
+#if 0
+ /* disable shadow texture mode */
+ inst->TexShadow = 0;
+#endif
+ }
+
+ if (inst->Opcode == OPCODE_TXP) {
+#if 0
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.WriteMask = WRITEMASK_XYZW;
+ inst->SrcReg[0].File = PROGRAM_CONSTANT;
+ inst->SrcReg[0].Index = whiteIndex;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
+ inst->SrcReg[0].Negate = NEGATE_NONE;
+#endif
+#if 0
+ inst->TexShadow = 0;
+#endif
+#if 0
+ inst->Opcode = OPCODE_TEX;
+ inst->TexShadow = 0;
+#endif
+ }
+
+ }
+}
diff --git a/mesalib/src/mesa/shader/program.h b/mesalib/src/mesa/shader/program.h
new file mode 100644
index 000000000..56a4191f5
--- /dev/null
+++ b/mesalib/src/mesa/shader/program.h
@@ -0,0 +1,129 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file program.c
+ * Vertex and fragment program support functions.
+ * \author Brian Paul
+ */
+
+
+/**
+ * \mainpage Mesa vertex and fragment program module
+ *
+ * This module or directory contains most of the code for vertex and
+ * fragment programs and shaders, including state management, parsers,
+ * and (some) software routines for executing programs
+ */
+
+#ifndef PROGRAM_H
+#define PROGRAM_H
+
+#include "main/mtypes.h"
+
+
+extern struct gl_program _mesa_DummyProgram;
+
+
+extern void
+_mesa_init_program(GLcontext *ctx);
+
+extern void
+_mesa_free_program_data(GLcontext *ctx);
+
+extern void
+_mesa_update_default_objects_program(GLcontext *ctx);
+
+extern void
+_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
+
+extern const GLubyte *
+_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
+ GLint *line, GLint *col);
+
+
+extern struct gl_program *
+_mesa_init_vertex_program(GLcontext *ctx,
+ struct gl_vertex_program *prog,
+ GLenum target, GLuint id);
+
+extern struct gl_program *
+_mesa_init_fragment_program(GLcontext *ctx,
+ struct gl_fragment_program *prog,
+ GLenum target, GLuint id);
+
+extern struct gl_program *
+_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id);
+
+extern void
+_mesa_delete_program(GLcontext *ctx, struct gl_program *prog);
+
+extern struct gl_program *
+_mesa_lookup_program(GLcontext *ctx, GLuint id);
+
+extern void
+_mesa_reference_program(GLcontext *ctx,
+ struct gl_program **ptr,
+ struct gl_program *prog);
+
+static INLINE void
+_mesa_reference_vertprog(GLcontext *ctx,
+ struct gl_vertex_program **ptr,
+ struct gl_vertex_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static INLINE void
+_mesa_reference_fragprog(GLcontext *ctx,
+ struct gl_fragment_program **ptr,
+ struct gl_fragment_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+extern struct gl_program *
+_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog);
+
+extern GLboolean
+_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count);
+
+extern GLboolean
+_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count);
+
+extern struct gl_program *
+_mesa_combine_programs(GLcontext *ctx,
+ const struct gl_program *progA,
+ const struct gl_program *progB);
+
+extern GLint
+_mesa_find_free_register(const struct gl_program *prog, GLuint regFile);
+
+extern void
+_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
+
+
+#endif /* PROGRAM_H */
diff --git a/mesalib/src/mesa/shader/program_lexer.l b/mesalib/src/mesa/shader/program_lexer.l
new file mode 100644
index 000000000..d24021748
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_lexer.l
@@ -0,0 +1,489 @@
+%{
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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 "main/glheader.h"
+#include "prog_instruction.h"
+#include "prog_statevars.h"
+
+#include "program_parser.h"
+#include "program_parse.tab.h"
+
+#define require_ARB_vp (yyextra->mode == ARB_vertex)
+#define require_ARB_fp (yyextra->mode == ARB_fragment)
+#define require_shadow (yyextra->option.Shadow)
+#define require_rect (yyextra->option.TexRect)
+#define require_texarray (yyextra->option.TexArray)
+
+#define return_token_or_IDENTIFIER(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define return_token_or_DOT(condition, token) \
+ do { \
+ if (condition) { \
+ return token; \
+ } else { \
+ yyless(1); \
+ return DOT; \
+ } \
+ } while (0)
+
+
+#define return_opcode(condition, token, opcode, sat) \
+ do { \
+ if (condition) { \
+ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
+ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \
+ return token; \
+ } else { \
+ yylval->string = strdup(yytext); \
+ return IDENTIFIER; \
+ } \
+ } while (0)
+
+#define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
+ SWIZZLE_NIL, SWIZZLE_NIL)
+
+static unsigned
+mask_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return WRITEMASK_X;
+ case 'y':
+ case 'g':
+ return WRITEMASK_Y;
+ case 'z':
+ case 'b':
+ return WRITEMASK_Z;
+ case 'w':
+ case 'a':
+ return WRITEMASK_W;
+ }
+
+ return 0;
+}
+
+static unsigned
+swiz_from_char(char c)
+{
+ switch (c) {
+ case 'x':
+ case 'r':
+ return SWIZZLE_X;
+ case 'y':
+ case 'g':
+ return SWIZZLE_Y;
+ case 'z':
+ case 'b':
+ return SWIZZLE_Z;
+ case 'w':
+ case 'a':
+ return SWIZZLE_W;
+ }
+
+ return 0;
+}
+
+#define YY_USER_ACTION \
+ do { \
+ yylloc->first_column = yylloc->last_column; \
+ yylloc->last_column += yyleng; \
+ if ((yylloc->first_line == 1) \
+ && (yylloc->first_column == 1)) { \
+ yylloc->position = 1; \
+ } else { \
+ yylloc->position += yylloc->last_column - yylloc->first_column; \
+ } \
+ } while(0);
+
+#define YY_EXTRA_TYPE struct asm_parser_state *
+%}
+
+num [0-9]+
+exp [Ee][-+]?[0-9]+
+frac "."[0-9]+
+dot "."[ \t]*
+
+%option bison-bridge bison-locations reentrant noyywrap
+%%
+
+"!!ARBvp1.0" { return ARBvp_10; }
+"!!ARBfp1.0" { return ARBfp_10; }
+ADDRESS {
+ yylval->integer = at_address;
+ return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
+}
+ALIAS { return ALIAS; }
+ATTRIB { return ATTRIB; }
+END { return END; }
+OPTION { return OPTION; }
+OUTPUT { return OUTPUT; }
+PARAM { return PARAM; }
+TEMP { yylval->integer = at_temp; return TEMP; }
+
+ABS { return_opcode( 1, VECTOR_OP, ABS, OFF); }
+ABS_SAT { return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); }
+ADD { return_opcode( 1, BIN_OP, ADD, OFF); }
+ADD_SAT { return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); }
+ARL { return_opcode(require_ARB_vp, ARL, ARL, OFF); }
+
+CMP { return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); }
+CMP_SAT { return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); }
+COS { return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); }
+COS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); }
+
+DP3 { return_opcode( 1, BIN_OP, DP3, OFF); }
+DP3_SAT { return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); }
+DP4 { return_opcode( 1, BIN_OP, DP4, OFF); }
+DP4_SAT { return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); }
+DPH { return_opcode( 1, BIN_OP, DPH, OFF); }
+DPH_SAT { return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); }
+DST { return_opcode( 1, BIN_OP, DST, OFF); }
+DST_SAT { return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); }
+
+EX2 { return_opcode( 1, SCALAR_OP, EX2, OFF); }
+EX2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); }
+EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); }
+
+FLR { return_opcode( 1, VECTOR_OP, FLR, OFF); }
+FLR_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); }
+FRC { return_opcode( 1, VECTOR_OP, FRC, OFF); }
+FRC_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); }
+
+KIL { return_opcode(require_ARB_fp, KIL, KIL, OFF); }
+
+LIT { return_opcode( 1, VECTOR_OP, LIT, OFF); }
+LIT_SAT { return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); }
+LG2 { return_opcode( 1, SCALAR_OP, LG2, OFF); }
+LG2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); }
+LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); }
+LRP { return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); }
+LRP_SAT { return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); }
+
+MAD { return_opcode( 1, TRI_OP, MAD, OFF); }
+MAD_SAT { return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); }
+MAX { return_opcode( 1, BIN_OP, MAX, OFF); }
+MAX_SAT { return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); }
+MIN { return_opcode( 1, BIN_OP, MIN, OFF); }
+MIN_SAT { return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); }
+MOV { return_opcode( 1, VECTOR_OP, MOV, OFF); }
+MOV_SAT { return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); }
+MUL { return_opcode( 1, BIN_OP, MUL, OFF); }
+MUL_SAT { return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); }
+
+POW { return_opcode( 1, BINSC_OP, POW, OFF); }
+POW_SAT { return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); }
+
+RCP { return_opcode( 1, SCALAR_OP, RCP, OFF); }
+RCP_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); }
+RSQ { return_opcode( 1, SCALAR_OP, RSQ, OFF); }
+RSQ_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); }
+
+SCS { return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); }
+SCS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); }
+SGE { return_opcode( 1, BIN_OP, SGE, OFF); }
+SGE_SAT { return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); }
+SIN { return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); }
+SIN_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); }
+SLT { return_opcode( 1, BIN_OP, SLT, OFF); }
+SLT_SAT { return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); }
+SUB { return_opcode( 1, BIN_OP, SUB, OFF); }
+SUB_SAT { return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); }
+SWZ { return_opcode( 1, SWZ, SWZ, OFF); }
+SWZ_SAT { return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); }
+
+TEX { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); }
+TEX_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); }
+TXB { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); }
+TXB_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); }
+TXP { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); }
+TXP_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); }
+
+XPD { return_opcode( 1, BIN_OP, XPD, OFF); }
+XPD_SAT { return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); }
+
+vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
+fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
+program { return PROGRAM; }
+state { return STATE; }
+result { return RESULT; }
+
+{dot}ambient { return AMBIENT; }
+{dot}attenuation { return ATTENUATION; }
+{dot}back { return BACK; }
+{dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); }
+{dot}color { return COLOR; }
+{dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); }
+{dot}diffuse { return DIFFUSE; }
+{dot}direction { return DIRECTION; }
+{dot}emission { return EMISSION; }
+{dot}env { return ENV; }
+{dot}eye { return EYE; }
+{dot}fogcoord { return FOGCOORD; }
+{dot}fog { return FOG; }
+{dot}front { return FRONT; }
+{dot}half { return HALF; }
+{dot}inverse { return INVERSE; }
+{dot}invtrans { return INVTRANS; }
+{dot}light { return LIGHT; }
+{dot}lightmodel { return LIGHTMODEL; }
+{dot}lightprod { return LIGHTPROD; }
+{dot}local { return LOCAL; }
+{dot}material { return MATERIAL; }
+{dot}program { return MAT_PROGRAM; }
+{dot}matrix { return MATRIX; }
+{dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
+{dot}modelview { return MODELVIEW; }
+{dot}mvp { return MVP; }
+{dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); }
+{dot}object { return OBJECT; }
+{dot}palette { return PALETTE; }
+{dot}params { return PARAMS; }
+{dot}plane { return PLANE; }
+{dot}point { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
+{dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
+{dot}position { return POSITION; }
+{dot}primary { return PRIMARY; }
+{dot}projection { return PROJECTION; }
+{dot}range { return_token_or_DOT(require_ARB_fp, RANGE); }
+{dot}row { return ROW; }
+{dot}scenecolor { return SCENECOLOR; }
+{dot}secondary { return SECONDARY; }
+{dot}shininess { return SHININESS; }
+{dot}size { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
+{dot}specular { return SPECULAR; }
+{dot}spot { return SPOT; }
+{dot}texcoord { return TEXCOORD; }
+{dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); }
+{dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); }
+{dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
+{dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
+{dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
+{dot}texture { return TEXTURE; }
+{dot}transpose { return TRANSPOSE; }
+{dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
+{dot}weight { return_token_or_DOT(require_ARB_vp, WEIGHT); }
+
+texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
+1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
+2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
+3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
+CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
+RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
+SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
+SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
+SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
+ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
+ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
+ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
+ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
+
+[_a-zA-Z$][_a-zA-Z0-9$]* {
+ yylval->string = strdup(yytext);
+ return IDENTIFIER;
+}
+
+".." { return DOT_DOT; }
+
+{num} {
+ yylval->integer = strtol(yytext, NULL, 10);
+ return INTEGER;
+}
+{num}?{frac}{exp}? {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."/[^.] {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+{num}"."{exp} {
+ yylval->real = strtod(yytext, NULL);
+ return REAL;
+}
+
+".xyzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return MASK4;
+}
+
+".xy"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return MASK3;
+}
+".xzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return MASK3;
+}
+".yzw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return MASK3;
+}
+
+".x"[yzw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".y"[zw] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return MASK2;
+}
+".zw" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return MASK2;
+}
+
+"."[xyzw] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return MASK1;
+}
+
+"."[xyzw]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return SWIZZLE;
+}
+
+".rgba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
+ yylval->swiz_mask.mask = WRITEMASK_XYZW;
+ return_token_or_DOT(require_ARB_fp, MASK4);
+}
+
+".rg"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XY
+ | mask_from_char(yytext[3]);
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".rba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_XZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+".gba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_YZW;
+ return_token_or_DOT(require_ARB_fp, MASK3);
+}
+
+".r"[gba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_X
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".g"[ba] {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_Y
+ | mask_from_char(yytext[2]);
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+".ba" {
+ yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
+ yylval->swiz_mask.mask = WRITEMASK_ZW;
+ return_token_or_DOT(require_ARB_fp, MASK2);
+}
+
+"."[gba] {
+ const unsigned s = swiz_from_char(yytext[1]);
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
+ yylval->swiz_mask.mask = mask_from_char(yytext[1]);
+ return_token_or_DOT(require_ARB_fp, MASK1);
+}
+
+
+".r" {
+ if (require_ARB_vp) {
+ return TEXGEN_R;
+ } else {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
+ SWIZZLE_X, SWIZZLE_X);
+ yylval->swiz_mask.mask = WRITEMASK_X;
+ return MASK1;
+ }
+}
+
+"."[rgba]{4} {
+ yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
+ swiz_from_char(yytext[2]),
+ swiz_from_char(yytext[3]),
+ swiz_from_char(yytext[4]));
+ yylval->swiz_mask.mask = 0;
+ return_token_or_DOT(require_ARB_fp, SWIZZLE);
+}
+
+"." { return DOT; }
+
+\n {
+ yylloc->first_line++;
+ yylloc->first_column = 1;
+ yylloc->last_line++;
+ yylloc->last_column = 1;
+ yylloc->position++;
+}
+[ \t\r]+ /* eat whitespace */ ;
+#.*$ /* eat comments */ ;
+. { return yytext[0]; }
+%%
+
+void
+_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
+ const char *string, size_t len)
+{
+ yylex_init_extra(state, scanner);
+ yy_scan_bytes(string, len, *scanner);
+}
+
+void
+_mesa_program_lexer_dtor(void *scanner)
+{
+ yylex_destroy(scanner);
+}
diff --git a/mesalib/src/mesa/shader/program_parse.tab.c b/mesalib/src/mesa/shader/program_parse.tab.c
new file mode 100644
index 000000000..9f2d4de90
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_parse.tab.c
@@ -0,0 +1,5249 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "program_parse.y"
+
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_statevars.h"
+#include "prog_instruction.h"
+
+#include "symbol_table.h"
+#include "program_parser.h"
+
+extern void *yy_scan_string(char *);
+extern void yy_delete_buffer(void *);
+
+static struct asm_symbol *declare_variable(struct asm_parser_state *state,
+ char *name, enum asm_type t, struct YYLTYPE *locp);
+
+static int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var, const struct asm_vector *vec);
+
+static int yyparse(struct asm_parser_state *state);
+
+static char *make_error_string(const char *fmt, ...);
+
+static void yyerror(struct YYLTYPE *locp, struct asm_parser_state *state,
+ const char *s);
+
+static int validate_inputs(struct YYLTYPE *locp,
+ struct asm_parser_state *state);
+
+static void init_dst_reg(struct prog_dst_register *r);
+
+static void init_src_reg(struct asm_src_register *r);
+
+static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst, const struct asm_src_register *src0,
+ const struct asm_src_register *src1, const struct asm_src_register *src2);
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 1).position; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } else { \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_line = (Current).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
+ (Current).last_column = (Current).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 0).position \
+ + (Current).first_column; \
+ } \
+ } while(YYID(0))
+
+#define YYLEX_PARAM state->scanner
+
+
+/* Line 189 of yacc.c */
+#line 174 "program_parse.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ARBvp_10 = 258,
+ ARBfp_10 = 259,
+ ADDRESS = 260,
+ ALIAS = 261,
+ ATTRIB = 262,
+ OPTION = 263,
+ OUTPUT = 264,
+ PARAM = 265,
+ TEMP = 266,
+ END = 267,
+ BIN_OP = 268,
+ BINSC_OP = 269,
+ SAMPLE_OP = 270,
+ SCALAR_OP = 271,
+ TRI_OP = 272,
+ VECTOR_OP = 273,
+ ARL = 274,
+ KIL = 275,
+ SWZ = 276,
+ INTEGER = 277,
+ REAL = 278,
+ AMBIENT = 279,
+ ATTENUATION = 280,
+ BACK = 281,
+ CLIP = 282,
+ COLOR = 283,
+ DEPTH = 284,
+ DIFFUSE = 285,
+ DIRECTION = 286,
+ EMISSION = 287,
+ ENV = 288,
+ EYE = 289,
+ FOG = 290,
+ FOGCOORD = 291,
+ FRAGMENT = 292,
+ FRONT = 293,
+ HALF = 294,
+ INVERSE = 295,
+ INVTRANS = 296,
+ LIGHT = 297,
+ LIGHTMODEL = 298,
+ LIGHTPROD = 299,
+ LOCAL = 300,
+ MATERIAL = 301,
+ MAT_PROGRAM = 302,
+ MATRIX = 303,
+ MATRIXINDEX = 304,
+ MODELVIEW = 305,
+ MVP = 306,
+ NORMAL = 307,
+ OBJECT = 308,
+ PALETTE = 309,
+ PARAMS = 310,
+ PLANE = 311,
+ POINT_TOK = 312,
+ POINTSIZE = 313,
+ POSITION = 314,
+ PRIMARY = 315,
+ PROGRAM = 316,
+ PROJECTION = 317,
+ RANGE = 318,
+ RESULT = 319,
+ ROW = 320,
+ SCENECOLOR = 321,
+ SECONDARY = 322,
+ SHININESS = 323,
+ SIZE_TOK = 324,
+ SPECULAR = 325,
+ SPOT = 326,
+ STATE = 327,
+ TEXCOORD = 328,
+ TEXENV = 329,
+ TEXGEN = 330,
+ TEXGEN_Q = 331,
+ TEXGEN_R = 332,
+ TEXGEN_S = 333,
+ TEXGEN_T = 334,
+ TEXTURE = 335,
+ TRANSPOSE = 336,
+ TEXTURE_UNIT = 337,
+ TEX_1D = 338,
+ TEX_2D = 339,
+ TEX_3D = 340,
+ TEX_CUBE = 341,
+ TEX_RECT = 342,
+ TEX_SHADOW1D = 343,
+ TEX_SHADOW2D = 344,
+ TEX_SHADOWRECT = 345,
+ TEX_ARRAY1D = 346,
+ TEX_ARRAY2D = 347,
+ TEX_ARRAYSHADOW1D = 348,
+ TEX_ARRAYSHADOW2D = 349,
+ VERTEX = 350,
+ VTXATTRIB = 351,
+ WEIGHT = 352,
+ IDENTIFIER = 353,
+ MASK4 = 354,
+ MASK3 = 355,
+ MASK2 = 356,
+ MASK1 = 357,
+ SWIZZLE = 358,
+ DOT_DOT = 359,
+ DOT = 360
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 107 "program_parse.y"
+
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+
+
+
+/* Line 214 of yacc.c */
+#line 343 "program_parse.tab.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+/* Line 264 of yacc.c */
+#line 249 "program_parse.y"
+
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+ void *yyscanner);
+
+
+/* Line 264 of yacc.c */
+#line 374 "program_parse.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 5
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 342
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 115
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 134
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 264
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 436
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 360
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 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, 110, 107, 111, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 106,
+ 2, 112, 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, 108, 2, 109, 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, 113, 2, 114, 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, 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, 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, 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, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 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, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 8, 10, 12, 15, 16, 20, 23,
+ 24, 27, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 52, 57, 62, 67, 74, 81, 90,
+ 99, 102, 105, 107, 109, 111, 113, 115, 117, 119,
+ 121, 123, 125, 127, 129, 136, 140, 144, 147, 150,
+ 158, 161, 163, 165, 167, 169, 174, 176, 178, 180,
+ 182, 184, 186, 188, 192, 193, 196, 199, 201, 203,
+ 205, 207, 209, 211, 213, 215, 217, 218, 220, 222,
+ 224, 226, 227, 229, 231, 233, 235, 237, 239, 244,
+ 247, 250, 252, 255, 257, 260, 262, 265, 270, 275,
+ 277, 278, 282, 284, 286, 289, 291, 294, 296, 298,
+ 302, 309, 310, 312, 315, 320, 322, 326, 328, 330,
+ 332, 334, 336, 338, 340, 342, 344, 346, 349, 352,
+ 355, 358, 361, 364, 367, 370, 373, 376, 379, 382,
+ 386, 388, 390, 392, 398, 400, 402, 404, 407, 409,
+ 411, 414, 416, 419, 426, 428, 432, 434, 436, 438,
+ 440, 442, 447, 449, 451, 453, 455, 457, 459, 462,
+ 464, 466, 472, 474, 477, 479, 481, 487, 490, 491,
+ 498, 502, 503, 505, 507, 509, 511, 513, 516, 518,
+ 520, 523, 528, 533, 534, 538, 540, 542, 544, 547,
+ 549, 551, 553, 555, 561, 563, 567, 573, 579, 581,
+ 585, 591, 593, 595, 597, 599, 601, 603, 605, 607,
+ 609, 613, 619, 627, 637, 640, 643, 645, 647, 648,
+ 649, 653, 654, 658, 662, 664, 669, 672, 675, 678,
+ 681, 685, 688, 692, 693, 695, 697, 698, 700, 702,
+ 703, 705, 707, 708, 710, 712, 713, 717, 718, 722,
+ 723, 727, 729, 731, 733
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 116, 0, -1, 117, 118, 120, 12, -1, 3, -1,
+ 4, -1, 118, 119, -1, -1, 8, 98, 106, -1,
+ 120, 121, -1, -1, 122, 106, -1, 158, 106, -1,
+ 123, -1, 124, -1, 125, -1, 126, -1, 127, -1,
+ 128, -1, 129, -1, 130, -1, 135, -1, 131, -1,
+ 132, -1, 19, 139, 107, 136, -1, 18, 138, 107,
+ 137, -1, 16, 138, 107, 136, -1, 14, 138, 107,
+ 136, 107, 136, -1, 13, 138, 107, 137, 107, 137,
+ -1, 17, 138, 107, 137, 107, 137, 107, 137, -1,
+ 15, 138, 107, 137, 107, 133, 107, 134, -1, 20,
+ 137, -1, 82, 243, -1, 83, -1, 84, -1, 85,
+ -1, 86, -1, 87, -1, 88, -1, 89, -1, 90,
+ -1, 91, -1, 92, -1, 93, -1, 94, -1, 21,
+ 138, 107, 143, 107, 140, -1, 229, 143, 155, -1,
+ 229, 143, 156, -1, 144, 157, -1, 152, 154, -1,
+ 141, 107, 141, 107, 141, 107, 141, -1, 229, 142,
+ -1, 22, -1, 98, -1, 98, -1, 160, -1, 145,
+ 108, 146, 109, -1, 174, -1, 236, -1, 98, -1,
+ 98, -1, 147, -1, 148, -1, 22, -1, 152, 153,
+ 149, -1, -1, 110, 150, -1, 111, 151, -1, 22,
+ -1, 22, -1, 98, -1, 102, -1, 102, -1, 102,
+ -1, 102, -1, 99, -1, 103, -1, -1, 99, -1,
+ 100, -1, 101, -1, 102, -1, -1, 159, -1, 166,
+ -1, 230, -1, 232, -1, 235, -1, 248, -1, 7,
+ 98, 112, 160, -1, 95, 161, -1, 37, 165, -1,
+ 59, -1, 97, 163, -1, 52, -1, 28, 241, -1,
+ 36, -1, 73, 242, -1, 49, 108, 164, 109, -1,
+ 96, 108, 162, 109, -1, 22, -1, -1, 108, 164,
+ 109, -1, 22, -1, 59, -1, 28, 241, -1, 36,
+ -1, 73, 242, -1, 167, -1, 168, -1, 10, 98,
+ 170, -1, 10, 98, 108, 169, 109, 171, -1, -1,
+ 22, -1, 112, 173, -1, 112, 113, 172, 114, -1,
+ 175, -1, 172, 107, 175, -1, 177, -1, 213, -1,
+ 223, -1, 177, -1, 213, -1, 224, -1, 176, -1,
+ 214, -1, 223, -1, 177, -1, 72, 201, -1, 72,
+ 178, -1, 72, 180, -1, 72, 183, -1, 72, 185,
+ -1, 72, 191, -1, 72, 187, -1, 72, 194, -1,
+ 72, 196, -1, 72, 198, -1, 72, 200, -1, 72,
+ 212, -1, 46, 240, 179, -1, 189, -1, 32, -1,
+ 68, -1, 42, 108, 190, 109, 181, -1, 189, -1,
+ 59, -1, 25, -1, 71, 182, -1, 39, -1, 31,
+ -1, 43, 184, -1, 24, -1, 240, 66, -1, 44,
+ 108, 190, 109, 240, 186, -1, 189, -1, 74, 244,
+ 188, -1, 28, -1, 24, -1, 30, -1, 70, -1,
+ 22, -1, 75, 242, 192, 193, -1, 34, -1, 53,
+ -1, 78, -1, 79, -1, 77, -1, 76, -1, 35,
+ 195, -1, 28, -1, 55, -1, 27, 108, 197, 109,
+ 56, -1, 22, -1, 57, 199, -1, 69, -1, 25,
+ -1, 203, 65, 108, 206, 109, -1, 203, 202, -1,
+ -1, 65, 108, 206, 104, 206, 109, -1, 48, 207,
+ 204, -1, -1, 205, -1, 40, -1, 81, -1, 41,
+ -1, 22, -1, 50, 208, -1, 62, -1, 51, -1,
+ 80, 242, -1, 54, 108, 210, 109, -1, 47, 108,
+ 211, 109, -1, -1, 108, 209, 109, -1, 22, -1,
+ 22, -1, 22, -1, 29, 63, -1, 217, -1, 220,
+ -1, 215, -1, 218, -1, 61, 33, 108, 216, 109,
+ -1, 221, -1, 221, 104, 221, -1, 61, 33, 108,
+ 221, 109, -1, 61, 45, 108, 219, 109, -1, 222,
+ -1, 222, 104, 222, -1, 61, 45, 108, 222, 109,
+ -1, 22, -1, 22, -1, 225, -1, 227, -1, 226,
+ -1, 227, -1, 228, -1, 23, -1, 22, -1, 113,
+ 228, 114, -1, 113, 228, 107, 228, 114, -1, 113,
+ 228, 107, 228, 107, 228, 114, -1, 113, 228, 107,
+ 228, 107, 228, 107, 228, 114, -1, 229, 23, -1,
+ 229, 22, -1, 110, -1, 111, -1, -1, -1, 11,
+ 231, 234, -1, -1, 5, 233, 234, -1, 234, 107,
+ 98, -1, 98, -1, 9, 98, 112, 236, -1, 64,
+ 59, -1, 64, 36, -1, 64, 237, -1, 64, 58,
+ -1, 64, 73, 242, -1, 64, 29, -1, 28, 238,
+ 239, -1, -1, 38, -1, 26, -1, -1, 60, -1,
+ 67, -1, -1, 38, -1, 26, -1, -1, 60, -1,
+ 67, -1, -1, 108, 245, 109, -1, -1, 108, 246,
+ 109, -1, -1, 108, 247, 109, -1, 22, -1, 22,
+ -1, 22, -1, 6, 98, 112, 98, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 256, 256, 259, 267, 279, 280, 283, 305, 306,
+ 309, 324, 327, 332, 339, 340, 341, 342, 343, 344,
+ 345, 348, 349, 352, 358, 365, 372, 380, 387, 395,
+ 440, 447, 453, 454, 455, 456, 457, 458, 459, 460,
+ 461, 462, 463, 464, 467, 480, 493, 506, 528, 537,
+ 570, 577, 592, 642, 684, 695, 716, 726, 732, 763,
+ 780, 780, 782, 789, 801, 802, 803, 806, 818, 830,
+ 848, 859, 871, 873, 874, 875, 876, 879, 879, 879,
+ 879, 880, 883, 884, 885, 886, 887, 888, 891, 909,
+ 913, 919, 923, 927, 931, 940, 949, 953, 958, 964,
+ 975, 975, 976, 978, 982, 986, 990, 996, 996, 998,
+ 1014, 1037, 1040, 1051, 1057, 1063, 1064, 1071, 1077, 1083,
+ 1091, 1097, 1103, 1111, 1117, 1123, 1131, 1132, 1135, 1136,
+ 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1148,
+ 1157, 1161, 1165, 1171, 1180, 1184, 1188, 1197, 1201, 1207,
+ 1213, 1220, 1225, 1233, 1243, 1245, 1253, 1259, 1263, 1267,
+ 1273, 1284, 1293, 1297, 1302, 1306, 1310, 1314, 1320, 1327,
+ 1331, 1337, 1345, 1356, 1363, 1367, 1373, 1383, 1394, 1398,
+ 1416, 1425, 1428, 1434, 1438, 1442, 1448, 1459, 1464, 1469,
+ 1474, 1479, 1484, 1492, 1495, 1500, 1513, 1521, 1532, 1540,
+ 1540, 1542, 1542, 1544, 1554, 1559, 1566, 1576, 1585, 1590,
+ 1597, 1607, 1617, 1629, 1629, 1630, 1630, 1632, 1642, 1650,
+ 1660, 1668, 1676, 1685, 1696, 1700, 1706, 1707, 1708, 1711,
+ 1711, 1714, 1714, 1717, 1723, 1731, 1744, 1753, 1762, 1766,
+ 1775, 1784, 1795, 1802, 1807, 1816, 1828, 1831, 1840, 1851,
+ 1852, 1853, 1856, 1857, 1858, 1861, 1862, 1865, 1866, 1869,
+ 1870, 1873, 1884, 1895, 1906
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ARBvp_10", "ARBfp_10", "ADDRESS",
+ "ALIAS", "ATTRIB", "OPTION", "OUTPUT", "PARAM", "TEMP", "END", "BIN_OP",
+ "BINSC_OP", "SAMPLE_OP", "SCALAR_OP", "TRI_OP", "VECTOR_OP", "ARL",
+ "KIL", "SWZ", "INTEGER", "REAL", "AMBIENT", "ATTENUATION", "BACK",
+ "CLIP", "COLOR", "DEPTH", "DIFFUSE", "DIRECTION", "EMISSION", "ENV",
+ "EYE", "FOG", "FOGCOORD", "FRAGMENT", "FRONT", "HALF", "INVERSE",
+ "INVTRANS", "LIGHT", "LIGHTMODEL", "LIGHTPROD", "LOCAL", "MATERIAL",
+ "MAT_PROGRAM", "MATRIX", "MATRIXINDEX", "MODELVIEW", "MVP", "NORMAL",
+ "OBJECT", "PALETTE", "PARAMS", "PLANE", "POINT_TOK", "POINTSIZE",
+ "POSITION", "PRIMARY", "PROGRAM", "PROJECTION", "RANGE", "RESULT", "ROW",
+ "SCENECOLOR", "SECONDARY", "SHININESS", "SIZE_TOK", "SPECULAR", "SPOT",
+ "STATE", "TEXCOORD", "TEXENV", "TEXGEN", "TEXGEN_Q", "TEXGEN_R",
+ "TEXGEN_S", "TEXGEN_T", "TEXTURE", "TRANSPOSE", "TEXTURE_UNIT", "TEX_1D",
+ "TEX_2D", "TEX_3D", "TEX_CUBE", "TEX_RECT", "TEX_SHADOW1D",
+ "TEX_SHADOW2D", "TEX_SHADOWRECT", "TEX_ARRAY1D", "TEX_ARRAY2D",
+ "TEX_ARRAYSHADOW1D", "TEX_ARRAYSHADOW2D", "VERTEX", "VTXATTRIB",
+ "WEIGHT", "IDENTIFIER", "MASK4", "MASK3", "MASK2", "MASK1", "SWIZZLE",
+ "DOT_DOT", "DOT", "';'", "','", "'['", "']'", "'+'", "'-'", "'='", "'{'",
+ "'}'", "$accept", "program", "language", "optionSequence", "option",
+ "statementSequence", "statement", "instruction", "ALU_instruction",
+ "TexInstruction", "ARL_instruction", "VECTORop_instruction",
+ "SCALARop_instruction", "BINSCop_instruction", "BINop_instruction",
+ "TRIop_instruction", "SAMPLE_instruction", "KIL_instruction",
+ "texImageUnit", "texTarget", "SWZ_instruction", "scalarSrcReg",
+ "swizzleSrcReg", "maskedDstReg", "maskedAddrReg", "extendedSwizzle",
+ "extSwizComp", "extSwizSel", "srcReg", "dstReg", "progParamArray",
+ "progParamArrayMem", "progParamArrayAbs", "progParamArrayRel",
+ "addrRegRelOffset", "addrRegPosOffset", "addrRegNegOffset", "addrReg",
+ "addrComponent", "addrWriteMask", "scalarSuffix", "swizzleSuffix",
+ "optionalMask", "namingStatement", "ATTRIB_statement", "attribBinding",
+ "vtxAttribItem", "vtxAttribNum", "vtxOptWeightNum", "vtxWeightNum",
+ "fragAttribItem", "PARAM_statement", "PARAM_singleStmt",
+ "PARAM_multipleStmt", "optArraySize", "paramSingleInit",
+ "paramMultipleInit", "paramMultInitList", "paramSingleItemDecl",
+ "paramSingleItemUse", "paramMultipleItem", "stateMultipleItem",
+ "stateSingleItem", "stateMaterialItem", "stateMatProperty",
+ "stateLightItem", "stateLightProperty", "stateSpotProperty",
+ "stateLightModelItem", "stateLModProperty", "stateLightProdItem",
+ "stateLProdProperty", "stateTexEnvItem", "stateTexEnvProperty",
+ "ambDiffSpecProperty", "stateLightNumber", "stateTexGenItem",
+ "stateTexGenType", "stateTexGenCoord", "stateFogItem",
+ "stateFogProperty", "stateClipPlaneItem", "stateClipPlaneNum",
+ "statePointItem", "statePointProperty", "stateMatrixRow",
+ "stateMatrixRows", "optMatrixRows", "stateMatrixItem",
+ "stateOptMatModifier", "stateMatModifier", "stateMatrixRowNum",
+ "stateMatrixName", "stateOptModMatNum", "stateModMatNum",
+ "statePaletteMatNum", "stateProgramMatNum", "stateDepthItem",
+ "programSingleItem", "programMultipleItem", "progEnvParams",
+ "progEnvParamNums", "progEnvParam", "progLocalParams",
+ "progLocalParamNums", "progLocalParam", "progEnvParamNum",
+ "progLocalParamNum", "paramConstDecl", "paramConstUse",
+ "paramConstScalarDecl", "paramConstScalarUse", "paramConstVector",
+ "signedFloatConstant", "optionalSign", "TEMP_statement", "@1",
+ "ADDRESS_statement", "@2", "varNameList", "OUTPUT_statement",
+ "resultBinding", "resultColBinding", "optResultFaceType",
+ "optResultColorType", "optFaceType", "optColorType",
+ "optTexCoordUnitNum", "optTexImageUnitNum", "optLegacyTexUnitNum",
+ "texCoordUnitNum", "texImageUnitNum", "legacyTexUnitNum",
+ "ALIAS_statement", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 359, 360, 59, 44, 91, 93,
+ 43, 45, 61, 123, 125
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 115, 116, 117, 117, 118, 118, 119, 120, 120,
+ 121, 121, 122, 122, 123, 123, 123, 123, 123, 123,
+ 123, 124, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 134, 134, 134, 134, 134, 134, 134,
+ 134, 134, 134, 134, 135, 136, 137, 138, 139, 140,
+ 141, 142, 142, 143, 143, 143, 143, 144, 144, 145,
+ 146, 146, 147, 148, 149, 149, 149, 150, 151, 152,
+ 153, 154, 155, 156, 156, 156, 156, 157, 157, 157,
+ 157, 157, 158, 158, 158, 158, 158, 158, 159, 160,
+ 160, 161, 161, 161, 161, 161, 161, 161, 161, 162,
+ 163, 163, 164, 165, 165, 165, 165, 166, 166, 167,
+ 168, 169, 169, 170, 171, 172, 172, 173, 173, 173,
+ 174, 174, 174, 175, 175, 175, 176, 176, 177, 177,
+ 177, 177, 177, 177, 177, 177, 177, 177, 177, 178,
+ 179, 179, 179, 180, 181, 181, 181, 181, 181, 182,
+ 183, 184, 184, 185, 186, 187, 188, 189, 189, 189,
+ 190, 191, 192, 192, 193, 193, 193, 193, 194, 195,
+ 195, 196, 197, 198, 199, 199, 200, 201, 202, 202,
+ 203, 204, 204, 205, 205, 205, 206, 207, 207, 207,
+ 207, 207, 207, 208, 208, 209, 210, 211, 212, 213,
+ 213, 214, 214, 215, 216, 216, 217, 218, 219, 219,
+ 220, 221, 222, 223, 223, 224, 224, 225, 226, 226,
+ 227, 227, 227, 227, 228, 228, 229, 229, 229, 231,
+ 230, 233, 232, 234, 234, 235, 236, 236, 236, 236,
+ 236, 236, 237, 238, 238, 238, 239, 239, 239, 240,
+ 240, 240, 241, 241, 241, 242, 242, 243, 243, 244,
+ 244, 245, 246, 247, 248
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 4, 1, 1, 2, 0, 3, 2, 0,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 4, 4, 4, 6, 6, 8, 8,
+ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 6, 3, 3, 2, 2, 7,
+ 2, 1, 1, 1, 1, 4, 1, 1, 1, 1,
+ 1, 1, 1, 3, 0, 2, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 4, 2,
+ 2, 1, 2, 1, 2, 1, 2, 4, 4, 1,
+ 0, 3, 1, 1, 2, 1, 2, 1, 1, 3,
+ 6, 0, 1, 2, 4, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+ 1, 1, 1, 5, 1, 1, 1, 2, 1, 1,
+ 2, 1, 2, 6, 1, 3, 1, 1, 1, 1,
+ 1, 4, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 5, 1, 2, 1, 1, 5, 2, 0, 6,
+ 3, 0, 1, 1, 1, 1, 1, 2, 1, 1,
+ 2, 4, 4, 0, 3, 1, 1, 1, 2, 1,
+ 1, 1, 1, 5, 1, 3, 5, 5, 1, 3,
+ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 5, 7, 9, 2, 2, 1, 1, 0, 0,
+ 3, 0, 3, 3, 1, 4, 2, 2, 2, 2,
+ 3, 2, 3, 0, 1, 1, 0, 1, 1, 0,
+ 1, 1, 0, 1, 1, 0, 3, 0, 3, 0,
+ 3, 1, 1, 1, 4
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint16 yydefact[] =
+{
+ 0, 3, 4, 0, 6, 1, 9, 0, 5, 0,
+ 0, 231, 0, 0, 0, 0, 229, 2, 0, 0,
+ 0, 0, 0, 0, 0, 228, 0, 8, 0, 12,
+ 13, 14, 15, 16, 17, 18, 19, 21, 22, 20,
+ 0, 82, 83, 107, 108, 84, 85, 86, 87, 7,
+ 0, 0, 0, 0, 0, 0, 0, 58, 0, 81,
+ 57, 0, 0, 0, 0, 0, 69, 0, 0, 226,
+ 227, 30, 0, 0, 10, 11, 234, 232, 0, 0,
+ 0, 111, 228, 109, 230, 243, 241, 237, 239, 236,
+ 255, 238, 228, 77, 78, 79, 80, 47, 228, 228,
+ 228, 228, 228, 228, 71, 48, 219, 218, 0, 0,
+ 0, 0, 53, 228, 76, 0, 54, 56, 120, 121,
+ 199, 200, 122, 215, 216, 0, 0, 264, 88, 235,
+ 112, 0, 113, 117, 118, 119, 213, 214, 217, 0,
+ 245, 244, 246, 0, 240, 0, 0, 0, 0, 25,
+ 0, 24, 23, 252, 105, 103, 255, 90, 0, 0,
+ 0, 0, 0, 0, 249, 0, 249, 0, 0, 259,
+ 255, 128, 129, 130, 131, 133, 132, 134, 135, 136,
+ 137, 0, 138, 252, 95, 0, 93, 91, 255, 0,
+ 100, 89, 0, 74, 73, 75, 46, 0, 0, 233,
+ 0, 225, 224, 247, 248, 242, 261, 0, 228, 228,
+ 0, 0, 228, 253, 254, 104, 106, 0, 0, 0,
+ 198, 169, 170, 168, 0, 151, 251, 250, 150, 0,
+ 0, 0, 0, 193, 189, 0, 188, 255, 181, 175,
+ 174, 173, 0, 0, 0, 0, 94, 0, 96, 0,
+ 0, 92, 228, 220, 62, 0, 60, 61, 0, 228,
+ 0, 110, 256, 27, 26, 72, 45, 257, 0, 0,
+ 211, 0, 212, 0, 172, 0, 160, 0, 152, 0,
+ 157, 158, 141, 142, 159, 139, 140, 0, 0, 187,
+ 0, 190, 183, 185, 184, 180, 182, 263, 0, 156,
+ 155, 162, 163, 0, 0, 102, 0, 99, 0, 0,
+ 0, 55, 70, 64, 44, 0, 0, 228, 0, 31,
+ 0, 228, 206, 210, 0, 0, 249, 197, 0, 195,
+ 0, 196, 0, 260, 167, 166, 164, 165, 161, 186,
+ 0, 97, 98, 101, 228, 221, 0, 0, 63, 228,
+ 51, 52, 50, 0, 0, 0, 115, 123, 126, 124,
+ 201, 202, 125, 262, 0, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 29, 28, 171,
+ 146, 148, 145, 0, 143, 144, 0, 192, 194, 191,
+ 176, 0, 67, 65, 68, 66, 0, 0, 0, 127,
+ 178, 228, 114, 258, 149, 147, 153, 154, 228, 222,
+ 228, 0, 0, 0, 177, 116, 0, 0, 0, 204,
+ 0, 208, 0, 223, 228, 203, 0, 207, 0, 0,
+ 49, 205, 209, 0, 0, 179
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 3, 4, 6, 8, 9, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 268, 377,
+ 39, 146, 71, 58, 67, 314, 315, 352, 114, 59,
+ 115, 255, 256, 257, 348, 393, 395, 68, 313, 105,
+ 266, 196, 97, 40, 41, 116, 191, 308, 251, 306,
+ 157, 42, 43, 44, 131, 83, 261, 355, 132, 117,
+ 356, 357, 118, 171, 285, 172, 384, 405, 173, 228,
+ 174, 406, 175, 300, 286, 277, 176, 303, 338, 177,
+ 223, 178, 275, 179, 241, 180, 399, 414, 181, 295,
+ 296, 340, 238, 289, 330, 332, 328, 182, 119, 359,
+ 360, 418, 120, 361, 420, 121, 271, 273, 362, 122,
+ 136, 123, 124, 138, 72, 45, 55, 46, 50, 77,
+ 47, 60, 91, 142, 205, 229, 215, 144, 319, 243,
+ 207, 364, 298, 48
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -369
+static const yytype_int16 yypact[] =
+{
+ 143, -369, -369, 36, -369, -369, 45, -39, -369, 169,
+ -33, -369, -19, -6, -4, 12, -369, -369, -34, -34,
+ -34, -34, -34, -34, 15, 62, -34, -369, 26, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ 60, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ 20, 56, 107, 110, 37, 20, -3, -369, 111, 109,
+ -369, 113, 114, 116, 117, 118, -369, 119, 125, -369,
+ -369, -369, -15, 121, -369, -369, -369, 122, 132, -18,
+ 167, 210, -11, -369, 122, 63, -369, -369, -369, -369,
+ 130, -369, 62, -369, -369, -369, -369, -369, 62, 62,
+ 62, 62, 62, 62, -369, -369, -369, -369, 9, 72,
+ 87, -1, 131, 62, 104, 134, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -15, 142, -369, -369, -369,
+ -369, 135, -369, -369, -369, -369, -369, -369, -369, 182,
+ -369, -369, 52, 219, -369, 138, 139, -15, 140, -369,
+ 141, -369, -369, 61, -369, -369, 130, -369, 144, 145,
+ 146, 180, 11, 147, 85, 148, 99, 89, -2, 149,
+ 130, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, 184, -369, 61, -369, 150, -369, -369, 130, 151,
+ 152, -369, 27, -369, -369, -369, -369, -10, 154, -369,
+ 153, -369, -369, -369, -369, -369, -369, 155, 62, 62,
+ 161, 168, 62, -369, -369, -369, -369, 229, 244, 246,
+ -369, -369, -369, -369, 247, -369, -369, -369, -369, 204,
+ 247, 17, 163, 164, -369, 165, -369, 130, 67, -369,
+ -369, -369, 252, 248, 18, 170, -369, 253, -369, 255,
+ 253, -369, 62, -369, -369, 171, -369, -369, 177, 62,
+ 172, -369, -369, -369, -369, -369, -369, 173, 175, 176,
+ -369, 178, -369, 179, -369, 181, -369, 183, -369, 185,
+ -369, -369, -369, -369, -369, -369, -369, 262, 264, -369,
+ 267, -369, -369, -369, -369, -369, -369, -369, 186, -369,
+ -369, -369, -369, 136, 269, -369, 187, -369, 188, 190,
+ 43, -369, -369, 106, -369, 193, -5, -7, 271, -369,
+ 108, 62, -369, -369, 245, 4, 99, -369, 194, -369,
+ 195, -369, 196, -369, -369, -369, -369, -369, -369, -369,
+ 197, -369, -369, -369, 62, -369, 280, 285, -369, 62,
+ -369, -369, -369, 93, 87, 53, -369, -369, -369, -369,
+ -369, -369, -369, -369, 199, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, 278, -369, -369, 8, -369, -369, -369,
+ -369, 57, -369, -369, -369, -369, 203, 205, 206, -369,
+ 250, -7, -369, -369, -369, -369, -369, -369, 62, -369,
+ 62, 229, 244, 208, -369, -369, 198, 211, 202, 213,
+ 214, 218, 269, -369, 62, -369, 229, -369, 244, 54,
+ -369, -369, -369, 269, 215, -369
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -369, -94, -88, 133, -369, -369, -334, -369, -85, -369,
+ -369, -369, -369, -369, -369, -369, -369, 128, -369, -369,
+ -369, -369, -369, -369, -369, 251, -369, -369, -369, 77,
+ -369, -369, -369, -369, -369, -369, -369, -369, -369, -369,
+ -72, -369, -81, -369, -369, -369, -369, -369, -369, -369,
+ -369, -369, -369, -369, -305, 101, -369, -369, -369, -369,
+ -369, -369, -369, -369, -369, -369, -369, -369, -22, -369,
+ -369, -336, -369, -369, -369, -369, -369, -369, 254, -369,
+ -369, -369, -369, -369, -369, -369, -342, -368, 256, -369,
+ -369, -369, -80, -110, -82, -369, -369, -369, -369, 279,
+ -369, 257, -369, -369, -369, -161, 156, -146, -369, -369,
+ -369, -369, -369, -369
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -60
+static const yytype_int16 yytable[] =
+{
+ 139, 133, 137, 192, 145, 231, 149, 106, 107, 152,
+ 216, 148, 254, 150, 151, 396, 147, 350, 147, 108,
+ 385, 147, 108, 239, 244, 85, 86, 183, 280, 380,
+ 56, 139, 280, 87, 281, 184, 5, 153, 281, 221,
+ 198, 280, 248, 381, 421, 154, 109, 281, 185, 282,
+ 109, 186, 301, 7, 353, 88, 89, 110, 187, 10,
+ 432, 110, 210, 382, 57, 354, 222, 240, 155, 419,
+ 90, 302, 188, 49, 284, 383, 417, 111, 284, 51,
+ 111, 407, 156, 112, 431, 283, 429, 284, 66, 140,
+ 430, 291, 52, 351, 53, 189, 190, 434, 113, 69,
+ 70, 141, 113, 69, 70, 158, 113, 292, 293, 225,
+ 54, 226, 203, 66, 160, 264, 161, 159, 76, 204,
+ 263, 213, 162, 227, 269, 226, 397, 147, 214, 163,
+ 164, 165, 74, 166, 252, 167, 232, 227, 398, 233,
+ 234, 253, 310, 235, 168, 81, 1, 2, 294, 82,
+ 344, 236, 61, 62, 63, 64, 65, 345, 433, 73,
+ 401, 169, 170, 390, 408, 386, 75, 402, 78, 237,
+ 139, 409, 69, 70, 11, 12, 13, 316, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 365, 366, 367, 368, 369, 370, 371, 372, 373,
+ 374, 375, 376, 193, 201, 202, 194, 195, 93, 94,
+ 95, 96, 334, 335, 336, 337, 346, 347, 92, 79,
+ 98, 99, 80, 100, 101, 102, 103, 104, 125, 126,
+ 127, 56, 130, 378, 391, 139, 358, 137, 143, -59,
+ 199, 206, 197, 220, 200, 208, 209, 211, 212, 245,
+ 267, 270, 217, 218, 219, 224, 230, 242, 247, 249,
+ 250, 259, 139, 265, 262, 260, 272, 316, 274, 276,
+ 278, 287, 288, 290, 297, 305, 299, 307, 304, 312,
+ 311, 318, 320, 321, 327, 317, 329, 322, 323, 331,
+ 324, 339, 325, 363, 326, 333, 341, 342, 416, 343,
+ 349, 379, 392, 387, 388, 389, 390, 394, 403, 404,
+ 410, 425, 423, 411, 412, 413, 422, 426, 424, 139,
+ 358, 137, 428, 427, 435, 258, 139, 309, 316, 415,
+ 128, 279, 400, 0, 84, 0, 134, 129, 135, 246,
+ 0, 0, 316
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 82, 82, 82, 113, 92, 166, 100, 22, 23, 103,
+ 156, 99, 22, 101, 102, 349, 98, 22, 100, 37,
+ 325, 103, 37, 25, 170, 28, 29, 28, 24, 25,
+ 64, 113, 24, 36, 30, 36, 0, 28, 30, 28,
+ 125, 24, 188, 39, 412, 36, 61, 30, 49, 32,
+ 61, 52, 34, 8, 61, 58, 59, 72, 59, 98,
+ 428, 72, 147, 59, 98, 72, 55, 69, 59, 411,
+ 73, 53, 73, 106, 70, 71, 410, 95, 70, 98,
+ 95, 386, 73, 98, 426, 68, 422, 70, 98, 26,
+ 424, 237, 98, 98, 98, 96, 97, 433, 113, 110,
+ 111, 38, 113, 110, 111, 33, 113, 40, 41, 24,
+ 98, 26, 60, 98, 27, 209, 29, 45, 98, 67,
+ 208, 60, 35, 38, 212, 26, 33, 209, 67, 42,
+ 43, 44, 106, 46, 107, 48, 47, 38, 45, 50,
+ 51, 114, 252, 54, 57, 108, 3, 4, 81, 112,
+ 107, 62, 19, 20, 21, 22, 23, 114, 104, 26,
+ 107, 74, 75, 109, 107, 326, 106, 114, 112, 80,
+ 252, 114, 110, 111, 5, 6, 7, 259, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 99, 22, 23, 102, 103, 99, 100,
+ 101, 102, 76, 77, 78, 79, 110, 111, 107, 112,
+ 107, 107, 112, 107, 107, 107, 107, 102, 107, 107,
+ 98, 64, 22, 321, 344, 317, 317, 317, 108, 108,
+ 98, 22, 108, 63, 109, 107, 107, 107, 107, 65,
+ 82, 22, 108, 108, 108, 108, 108, 108, 108, 108,
+ 108, 107, 344, 102, 109, 112, 22, 349, 22, 22,
+ 66, 108, 108, 108, 22, 22, 28, 22, 108, 102,
+ 109, 108, 107, 107, 22, 113, 22, 109, 109, 22,
+ 109, 22, 109, 22, 109, 109, 109, 109, 408, 109,
+ 107, 56, 22, 109, 109, 109, 109, 22, 109, 31,
+ 107, 109, 114, 108, 108, 65, 108, 104, 107, 401,
+ 401, 401, 104, 109, 109, 197, 408, 250, 410, 401,
+ 79, 230, 354, -1, 55, -1, 82, 80, 82, 183,
+ -1, -1, 424
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 4, 116, 117, 0, 118, 8, 119, 120,
+ 98, 5, 6, 7, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 135,
+ 158, 159, 166, 167, 168, 230, 232, 235, 248, 106,
+ 233, 98, 98, 98, 98, 231, 64, 98, 138, 144,
+ 236, 138, 138, 138, 138, 138, 98, 139, 152, 110,
+ 111, 137, 229, 138, 106, 106, 98, 234, 112, 112,
+ 112, 108, 112, 170, 234, 28, 29, 36, 58, 59,
+ 73, 237, 107, 99, 100, 101, 102, 157, 107, 107,
+ 107, 107, 107, 107, 102, 154, 22, 23, 37, 61,
+ 72, 95, 98, 113, 143, 145, 160, 174, 177, 213,
+ 217, 220, 224, 226, 227, 107, 107, 98, 160, 236,
+ 22, 169, 173, 177, 213, 223, 225, 227, 228, 229,
+ 26, 38, 238, 108, 242, 137, 136, 229, 137, 136,
+ 137, 137, 136, 28, 36, 59, 73, 165, 33, 45,
+ 27, 29, 35, 42, 43, 44, 46, 48, 57, 74,
+ 75, 178, 180, 183, 185, 187, 191, 194, 196, 198,
+ 200, 203, 212, 28, 36, 49, 52, 59, 73, 96,
+ 97, 161, 228, 99, 102, 103, 156, 108, 143, 98,
+ 109, 22, 23, 60, 67, 239, 22, 245, 107, 107,
+ 143, 107, 107, 60, 67, 241, 242, 108, 108, 108,
+ 63, 28, 55, 195, 108, 24, 26, 38, 184, 240,
+ 108, 240, 47, 50, 51, 54, 62, 80, 207, 25,
+ 69, 199, 108, 244, 242, 65, 241, 108, 242, 108,
+ 108, 163, 107, 114, 22, 146, 147, 148, 152, 107,
+ 112, 171, 109, 137, 136, 102, 155, 82, 133, 137,
+ 22, 221, 22, 222, 22, 197, 22, 190, 66, 190,
+ 24, 30, 32, 68, 70, 179, 189, 108, 108, 208,
+ 108, 242, 40, 41, 81, 204, 205, 22, 247, 28,
+ 188, 34, 53, 192, 108, 22, 164, 22, 162, 164,
+ 228, 109, 102, 153, 140, 141, 229, 113, 108, 243,
+ 107, 107, 109, 109, 109, 109, 109, 22, 211, 22,
+ 209, 22, 210, 109, 76, 77, 78, 79, 193, 22,
+ 206, 109, 109, 109, 107, 114, 110, 111, 149, 107,
+ 22, 98, 142, 61, 72, 172, 175, 176, 177, 214,
+ 215, 218, 223, 22, 246, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 134, 137, 56,
+ 25, 39, 59, 71, 181, 189, 240, 109, 109, 109,
+ 109, 228, 22, 150, 22, 151, 141, 33, 45, 201,
+ 203, 107, 114, 109, 31, 182, 186, 189, 107, 114,
+ 107, 108, 108, 65, 202, 175, 228, 141, 216, 221,
+ 219, 222, 108, 114, 107, 109, 104, 109, 104, 206,
+ 141, 221, 222, 104, 206, 109
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, state, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc, scanner)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, state); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct asm_parser_state *state)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (state);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct asm_parser_state *state)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, state)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, state);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct asm_parser_state *state)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, state)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ struct asm_parser_state *state;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , state);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, state); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct asm_parser_state *state)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, state)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ struct asm_parser_state *state;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (state);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (struct asm_parser_state *state);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct asm_parser_state *state)
+#else
+int
+yyparse (state)
+ struct asm_parser_state *state;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+#if YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 1;
+#endif
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 3:
+
+/* Line 1455 of yacc.c */
+#line 260 "program_parse.y"
+ {
+ if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid fragment program header");
+
+ }
+ state->mode = ARB_vertex;
+ ;}
+ break;
+
+ case 4:
+
+/* Line 1455 of yacc.c */
+#line 268 "program_parse.y"
+ {
+ if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid vertex program header");
+ }
+ state->mode = ARB_fragment;
+
+ state->option.TexRect =
+ (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
+ ;}
+ break;
+
+ case 7:
+
+/* Line 1455 of yacc.c */
+#line 284 "program_parse.y"
+ {
+ int valid = 0;
+
+ if (state->mode == ARB_vertex) {
+ valid = _mesa_ARBvp_parse_option(state, (yyvsp[(2) - (3)].string));
+ } else if (state->mode == ARB_fragment) {
+ valid = _mesa_ARBfp_parse_option(state, (yyvsp[(2) - (3)].string));
+ }
+
+
+ if (!valid) {
+ const char *const err_str = (state->mode == ARB_vertex)
+ ? "invalid ARB vertex program option"
+ : "invalid ARB fragment program option";
+
+ yyerror(& (yylsp[(2) - (3)]), state, err_str);
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 10:
+
+/* Line 1455 of yacc.c */
+#line 310 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (2)].inst) != NULL) {
+ if (state->inst_tail == NULL) {
+ state->inst_head = (yyvsp[(1) - (2)].inst);
+ } else {
+ state->inst_tail->next = (yyvsp[(1) - (2)].inst);
+ }
+
+ state->inst_tail = (yyvsp[(1) - (2)].inst);
+ (yyvsp[(1) - (2)].inst)->next = NULL;
+
+ state->prog->NumInstructions++;
+ }
+ ;}
+ break;
+
+ case 12:
+
+/* Line 1455 of yacc.c */
+#line 328 "program_parse.y"
+ {
+ (yyval.inst) = (yyvsp[(1) - (1)].inst);
+ state->prog->NumAluInstructions++;
+ ;}
+ break;
+
+ case 13:
+
+/* Line 1455 of yacc.c */
+#line 333 "program_parse.y"
+ {
+ (yyval.inst) = (yyvsp[(1) - (1)].inst);
+ state->prog->NumTexInstructions++;
+ ;}
+ break;
+
+ case 23:
+
+/* Line 1455 of yacc.c */
+#line 353 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor(OPCODE_ARL, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ ;}
+ break;
+
+ case 24:
+
+/* Line 1455 of yacc.c */
+#line 359 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (4)].temp_inst).Opcode, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (4)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 25:
+
+/* Line 1455 of yacc.c */
+#line 366 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (4)].temp_inst).Opcode, & (yyvsp[(2) - (4)].dst_reg), & (yyvsp[(4) - (4)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (4)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 26:
+
+/* Line 1455 of yacc.c */
+#line 373 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (6)].temp_inst).Opcode, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), & (yyvsp[(6) - (6)].src_reg), NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 27:
+
+/* Line 1455 of yacc.c */
+#line 381 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (6)].temp_inst).Opcode, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), & (yyvsp[(6) - (6)].src_reg), NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 28:
+
+/* Line 1455 of yacc.c */
+#line 389 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (8)].temp_inst).Opcode, & (yyvsp[(2) - (8)].dst_reg), & (yyvsp[(4) - (8)].src_reg), & (yyvsp[(6) - (8)].src_reg), & (yyvsp[(8) - (8)].src_reg));
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (8)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 29:
+
+/* Line 1455 of yacc.c */
+#line 396 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor((yyvsp[(1) - (8)].temp_inst).Opcode, & (yyvsp[(2) - (8)].dst_reg), & (yyvsp[(4) - (8)].src_reg), NULL, NULL);
+ if ((yyval.inst) != NULL) {
+ const GLbitfield tex_mask = (1U << (yyvsp[(6) - (8)].integer));
+ GLbitfield shadow_tex = 0;
+ GLbitfield target_mask = 0;
+
+
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (8)].temp_inst).SaturateMode;
+ (yyval.inst)->Base.TexSrcUnit = (yyvsp[(6) - (8)].integer);
+
+ if ((yyvsp[(8) - (8)].integer) < 0) {
+ shadow_tex = tex_mask;
+
+ (yyval.inst)->Base.TexSrcTarget = -(yyvsp[(8) - (8)].integer);
+ (yyval.inst)->Base.TexShadow = 1;
+ } else {
+ (yyval.inst)->Base.TexSrcTarget = (yyvsp[(8) - (8)].integer);
+ }
+
+ target_mask = (1U << (yyval.inst)->Base.TexSrcTarget);
+
+ /* If this texture unit was previously accessed and that access
+ * had a different texture target, generate an error.
+ *
+ * If this texture unit was previously accessed and that access
+ * had a different shadow mode, generate an error.
+ */
+ if ((state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] != 0)
+ && ((state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] != target_mask)
+ || ((state->prog->ShadowSamplers & tex_mask)
+ != shadow_tex))) {
+ yyerror(& (yylsp[(8) - (8)]), state,
+ "multiple targets used on one texture image unit");
+ YYERROR;
+ }
+
+
+ state->prog->TexturesUsed[(yyvsp[(6) - (8)].integer)] |= target_mask;
+ state->prog->ShadowSamplers |= shadow_tex;
+ }
+ ;}
+ break;
+
+ case 30:
+
+/* Line 1455 of yacc.c */
+#line 441 "program_parse.y"
+ {
+ (yyval.inst) = asm_instruction_ctor(OPCODE_KIL, NULL, & (yyvsp[(2) - (2)].src_reg), NULL, NULL);
+ state->fragment.UsesKill = 1;
+ ;}
+ break;
+
+ case 31:
+
+/* Line 1455 of yacc.c */
+#line 448 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 32:
+
+/* Line 1455 of yacc.c */
+#line 453 "program_parse.y"
+ { (yyval.integer) = TEXTURE_1D_INDEX; ;}
+ break;
+
+ case 33:
+
+/* Line 1455 of yacc.c */
+#line 454 "program_parse.y"
+ { (yyval.integer) = TEXTURE_2D_INDEX; ;}
+ break;
+
+ case 34:
+
+/* Line 1455 of yacc.c */
+#line 455 "program_parse.y"
+ { (yyval.integer) = TEXTURE_3D_INDEX; ;}
+ break;
+
+ case 35:
+
+/* Line 1455 of yacc.c */
+#line 456 "program_parse.y"
+ { (yyval.integer) = TEXTURE_CUBE_INDEX; ;}
+ break;
+
+ case 36:
+
+/* Line 1455 of yacc.c */
+#line 457 "program_parse.y"
+ { (yyval.integer) = TEXTURE_RECT_INDEX; ;}
+ break;
+
+ case 37:
+
+/* Line 1455 of yacc.c */
+#line 458 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_1D_INDEX; ;}
+ break;
+
+ case 38:
+
+/* Line 1455 of yacc.c */
+#line 459 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_2D_INDEX; ;}
+ break;
+
+ case 39:
+
+/* Line 1455 of yacc.c */
+#line 460 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_RECT_INDEX; ;}
+ break;
+
+ case 40:
+
+/* Line 1455 of yacc.c */
+#line 461 "program_parse.y"
+ { (yyval.integer) = TEXTURE_1D_ARRAY_INDEX; ;}
+ break;
+
+ case 41:
+
+/* Line 1455 of yacc.c */
+#line 462 "program_parse.y"
+ { (yyval.integer) = TEXTURE_2D_ARRAY_INDEX; ;}
+ break;
+
+ case 42:
+
+/* Line 1455 of yacc.c */
+#line 463 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_1D_ARRAY_INDEX; ;}
+ break;
+
+ case 43:
+
+/* Line 1455 of yacc.c */
+#line 464 "program_parse.y"
+ { (yyval.integer) = -TEXTURE_2D_ARRAY_INDEX; ;}
+ break;
+
+ case 44:
+
+/* Line 1455 of yacc.c */
+#line 468 "program_parse.y"
+ {
+ /* FIXME: Is this correct? Should the extenedSwizzle be applied
+ * FIXME: to the existing swizzle?
+ */
+ (yyvsp[(4) - (6)].src_reg).Base.Swizzle = (yyvsp[(6) - (6)].swiz_mask).swizzle;
+ (yyvsp[(4) - (6)].src_reg).Base.Negate = (yyvsp[(6) - (6)].swiz_mask).mask;
+
+ (yyval.inst) = asm_instruction_ctor(OPCODE_SWZ, & (yyvsp[(2) - (6)].dst_reg), & (yyvsp[(4) - (6)].src_reg), NULL, NULL);
+ (yyval.inst)->Base.SaturateMode = (yyvsp[(1) - (6)].temp_inst).SaturateMode;
+ ;}
+ break;
+
+ case 45:
+
+/* Line 1455 of yacc.c */
+#line 481 "program_parse.y"
+ {
+ (yyval.src_reg) = (yyvsp[(2) - (3)].src_reg);
+
+ if ((yyvsp[(1) - (3)].negate)) {
+ (yyval.src_reg).Base.Negate = ~(yyval.src_reg).Base.Negate;
+ }
+
+ (yyval.src_reg).Base.Swizzle = _mesa_combine_swizzles((yyval.src_reg).Base.Swizzle,
+ (yyvsp[(3) - (3)].swiz_mask).swizzle);
+ ;}
+ break;
+
+ case 46:
+
+/* Line 1455 of yacc.c */
+#line 494 "program_parse.y"
+ {
+ (yyval.src_reg) = (yyvsp[(2) - (3)].src_reg);
+
+ if ((yyvsp[(1) - (3)].negate)) {
+ (yyval.src_reg).Base.Negate = ~(yyval.src_reg).Base.Negate;
+ }
+
+ (yyval.src_reg).Base.Swizzle = _mesa_combine_swizzles((yyval.src_reg).Base.Swizzle,
+ (yyvsp[(3) - (3)].swiz_mask).swizzle);
+ ;}
+ break;
+
+ case 47:
+
+/* Line 1455 of yacc.c */
+#line 507 "program_parse.y"
+ {
+ (yyval.dst_reg) = (yyvsp[(1) - (2)].dst_reg);
+ (yyval.dst_reg).WriteMask = (yyvsp[(2) - (2)].swiz_mask).mask;
+
+ if ((yyval.dst_reg).File == PROGRAM_OUTPUT) {
+ /* Technically speaking, this should check that it is in
+ * vertex program mode. However, PositionInvariant can never be
+ * set in fragment program mode, so it is somewhat irrelevant.
+ */
+ if (state->option.PositionInvariant
+ && ((yyval.dst_reg).Index == VERT_RESULT_HPOS)) {
+ yyerror(& (yylsp[(1) - (2)]), state, "position-invariant programs cannot "
+ "write position");
+ YYERROR;
+ }
+
+ state->prog->OutputsWritten |= (1U << (yyval.dst_reg).Index);
+ }
+ ;}
+ break;
+
+ case 48:
+
+/* Line 1455 of yacc.c */
+#line 529 "program_parse.y"
+ {
+ init_dst_reg(& (yyval.dst_reg));
+ (yyval.dst_reg).File = PROGRAM_ADDRESS;
+ (yyval.dst_reg).Index = 0;
+ (yyval.dst_reg).WriteMask = (yyvsp[(2) - (2)].swiz_mask).mask;
+ ;}
+ break;
+
+ case 49:
+
+/* Line 1455 of yacc.c */
+#line 538 "program_parse.y"
+ {
+ const unsigned xyzw_valid =
+ ((yyvsp[(1) - (7)].ext_swizzle).xyzw_valid << 0)
+ | ((yyvsp[(3) - (7)].ext_swizzle).xyzw_valid << 1)
+ | ((yyvsp[(5) - (7)].ext_swizzle).xyzw_valid << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).xyzw_valid << 3);
+ const unsigned rgba_valid =
+ ((yyvsp[(1) - (7)].ext_swizzle).rgba_valid << 0)
+ | ((yyvsp[(3) - (7)].ext_swizzle).rgba_valid << 1)
+ | ((yyvsp[(5) - (7)].ext_swizzle).rgba_valid << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).rgba_valid << 3);
+
+ /* All of the swizzle components have to be valid in either RGBA
+ * or XYZW. Note that 0 and 1 are valid in both, so both masks
+ * can have some bits set.
+ *
+ * We somewhat deviate from the spec here. It would be really hard
+ * to figure out which component is the error, and there probably
+ * isn't a lot of benefit.
+ */
+ if ((rgba_valid != 0x0f) && (xyzw_valid != 0x0f)) {
+ yyerror(& (yylsp[(1) - (7)]), state, "cannot combine RGBA and XYZW swizzle "
+ "components");
+ YYERROR;
+ }
+
+ (yyval.swiz_mask).swizzle = MAKE_SWIZZLE4((yyvsp[(1) - (7)].ext_swizzle).swz, (yyvsp[(3) - (7)].ext_swizzle).swz, (yyvsp[(5) - (7)].ext_swizzle).swz, (yyvsp[(7) - (7)].ext_swizzle).swz);
+ (yyval.swiz_mask).mask = ((yyvsp[(1) - (7)].ext_swizzle).negate) | ((yyvsp[(3) - (7)].ext_swizzle).negate << 1) | ((yyvsp[(5) - (7)].ext_swizzle).negate << 2)
+ | ((yyvsp[(7) - (7)].ext_swizzle).negate << 3);
+ ;}
+ break;
+
+ case 50:
+
+/* Line 1455 of yacc.c */
+#line 571 "program_parse.y"
+ {
+ (yyval.ext_swizzle) = (yyvsp[(2) - (2)].ext_swizzle);
+ (yyval.ext_swizzle).negate = ((yyvsp[(1) - (2)].negate)) ? 1 : 0;
+ ;}
+ break;
+
+ case 51:
+
+/* Line 1455 of yacc.c */
+#line 578 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) != 0) && ((yyvsp[(1) - (1)].integer) != 1)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ (yyval.ext_swizzle).swz = ((yyvsp[(1) - (1)].integer) == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
+
+ /* 0 and 1 are valid for both RGBA swizzle names and XYZW
+ * swizzle names.
+ */
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ ;}
+ break;
+
+ case 52:
+
+/* Line 1455 of yacc.c */
+#line 593 "program_parse.y"
+ {
+ if (strlen((yyvsp[(1) - (1)].string)) > 1) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ switch ((yyvsp[(1) - (1)].string)[0]) {
+ case 'x':
+ (yyval.ext_swizzle).swz = SWIZZLE_X;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'y':
+ (yyval.ext_swizzle).swz = SWIZZLE_Y;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'z':
+ (yyval.ext_swizzle).swz = SWIZZLE_Z;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+ case 'w':
+ (yyval.ext_swizzle).swz = SWIZZLE_W;
+ (yyval.ext_swizzle).xyzw_valid = 1;
+ break;
+
+ case 'r':
+ (yyval.ext_swizzle).swz = SWIZZLE_X;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'g':
+ (yyval.ext_swizzle).swz = SWIZZLE_Y;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'b':
+ (yyval.ext_swizzle).swz = SWIZZLE_Z;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+ case 'a':
+ (yyval.ext_swizzle).swz = SWIZZLE_W;
+ (yyval.ext_swizzle).rgba_valid = 1;
+ break;
+
+ default:
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid extended swizzle selector");
+ YYERROR;
+ break;
+ }
+ ;}
+ break;
+
+ case 53:
+
+/* Line 1455 of yacc.c */
+#line 643 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) && (s->type != at_temp)
+ && (s->type != at_attrib)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type == at_param) && s->param_is_array) {
+ yyerror(& (yylsp[(1) - (1)]), state, "non-array access to array PARAM");
+ YYERROR;
+ }
+
+ init_src_reg(& (yyval.src_reg));
+ switch (s->type) {
+ case at_temp:
+ (yyval.src_reg).Base.File = PROGRAM_TEMPORARY;
+ (yyval.src_reg).Base.Index = s->temp_binding;
+ break;
+ case at_param:
+ (yyval.src_reg).Base.File = s->param_binding_type;
+ (yyval.src_reg).Base.Index = s->param_binding_begin;
+ break;
+ case at_attrib:
+ (yyval.src_reg).Base.File = PROGRAM_INPUT;
+ (yyval.src_reg).Base.Index = s->attrib_binding;
+ state->prog->InputsRead |= (1U << (yyval.src_reg).Base.Index);
+
+ if (!validate_inputs(& (yylsp[(1) - (1)]), state)) {
+ YYERROR;
+ }
+ break;
+
+ default:
+ YYERROR;
+ break;
+ }
+ ;}
+ break;
+
+ case 54:
+
+/* Line 1455 of yacc.c */
+#line 685 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = PROGRAM_INPUT;
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].attrib);
+ state->prog->InputsRead |= (1U << (yyval.src_reg).Base.Index);
+
+ if (!validate_inputs(& (yylsp[(1) - (1)]), state)) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 55:
+
+/* Line 1455 of yacc.c */
+#line 696 "program_parse.y"
+ {
+ if (! (yyvsp[(3) - (4)].src_reg).Base.RelAddr
+ && ((unsigned) (yyvsp[(3) - (4)].src_reg).Base.Index >= (yyvsp[(1) - (4)].sym)->param_binding_length)) {
+ yyerror(& (yylsp[(3) - (4)]), state, "out of bounds array access");
+ YYERROR;
+ }
+
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = (yyvsp[(1) - (4)].sym)->param_binding_type;
+
+ if ((yyvsp[(3) - (4)].src_reg).Base.RelAddr) {
+ (yyvsp[(1) - (4)].sym)->param_accessed_indirectly = 1;
+
+ (yyval.src_reg).Base.RelAddr = 1;
+ (yyval.src_reg).Base.Index = (yyvsp[(3) - (4)].src_reg).Base.Index;
+ (yyval.src_reg).Symbol = (yyvsp[(1) - (4)].sym);
+ } else {
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (4)].sym)->param_binding_begin + (yyvsp[(3) - (4)].src_reg).Base.Index;
+ }
+ ;}
+ break;
+
+ case 56:
+
+/* Line 1455 of yacc.c */
+#line 717 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.File = ((yyvsp[(1) - (1)].temp_sym).name != NULL)
+ ? (yyvsp[(1) - (1)].temp_sym).param_binding_type
+ : PROGRAM_CONSTANT;
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].temp_sym).param_binding_begin;
+ ;}
+ break;
+
+ case 57:
+
+/* Line 1455 of yacc.c */
+#line 727 "program_parse.y"
+ {
+ init_dst_reg(& (yyval.dst_reg));
+ (yyval.dst_reg).File = PROGRAM_OUTPUT;
+ (yyval.dst_reg).Index = (yyvsp[(1) - (1)].result);
+ ;}
+ break;
+
+ case 58:
+
+/* Line 1455 of yacc.c */
+#line 733 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_output) && (s->type != at_temp)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ }
+
+ init_dst_reg(& (yyval.dst_reg));
+ switch (s->type) {
+ case at_temp:
+ (yyval.dst_reg).File = PROGRAM_TEMPORARY;
+ (yyval.dst_reg).Index = s->temp_binding;
+ break;
+ case at_output:
+ (yyval.dst_reg).File = PROGRAM_OUTPUT;
+ (yyval.dst_reg).Index = s->output_binding;
+ break;
+ default:
+ (yyval.dst_reg).File = s->param_binding_type;
+ (yyval.dst_reg).Index = s->param_binding_begin;
+ break;
+ }
+ ;}
+ break;
+
+ case 59:
+
+/* Line 1455 of yacc.c */
+#line 764 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) || !s->param_is_array) {
+ yyerror(& (yylsp[(1) - (1)]), state, "array access to non-PARAM variable");
+ YYERROR;
+ } else {
+ (yyval.sym) = s;
+ }
+ ;}
+ break;
+
+ case 62:
+
+/* Line 1455 of yacc.c */
+#line 783 "program_parse.y"
+ {
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.Index = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 63:
+
+/* Line 1455 of yacc.c */
+#line 790 "program_parse.y"
+ {
+ /* FINISHME: Add support for multiple address registers.
+ */
+ /* FINISHME: Add support for 4-component address registers.
+ */
+ init_src_reg(& (yyval.src_reg));
+ (yyval.src_reg).Base.RelAddr = 1;
+ (yyval.src_reg).Base.Index = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 64:
+
+/* Line 1455 of yacc.c */
+#line 801 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 65:
+
+/* Line 1455 of yacc.c */
+#line 802 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 66:
+
+/* Line 1455 of yacc.c */
+#line 803 "program_parse.y"
+ { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 67:
+
+/* Line 1455 of yacc.c */
+#line 807 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 0) || ((yyvsp[(1) - (1)].integer) > 63)) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "relative address offset too large (positive)");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 68:
+
+/* Line 1455 of yacc.c */
+#line 819 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 0) || ((yyvsp[(1) - (1)].integer) > 64)) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "relative address offset too large (negative)");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 69:
+
+/* Line 1455 of yacc.c */
+#line 831 "program_parse.y"
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(1) - (1)].string));
+
+ if (s == NULL) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid array member");
+ YYERROR;
+ } else if (s->type != at_address) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "invalid variable for indexed array access");
+ YYERROR;
+ } else {
+ (yyval.sym) = s;
+ }
+ ;}
+ break;
+
+ case 70:
+
+/* Line 1455 of yacc.c */
+#line 849 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].swiz_mask).mask != WRITEMASK_X) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid address component selector");
+ YYERROR;
+ } else {
+ (yyval.swiz_mask) = (yyvsp[(1) - (1)].swiz_mask);
+ }
+ ;}
+ break;
+
+ case 71:
+
+/* Line 1455 of yacc.c */
+#line 860 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].swiz_mask).mask != WRITEMASK_X) {
+ yyerror(& (yylsp[(1) - (1)]), state,
+ "address register write mask must be \".x\"");
+ YYERROR;
+ } else {
+ (yyval.swiz_mask) = (yyvsp[(1) - (1)].swiz_mask);
+ }
+ ;}
+ break;
+
+ case 76:
+
+/* Line 1455 of yacc.c */
+#line 876 "program_parse.y"
+ { (yyval.swiz_mask).swizzle = SWIZZLE_NOOP; (yyval.swiz_mask).mask = WRITEMASK_XYZW; ;}
+ break;
+
+ case 81:
+
+/* Line 1455 of yacc.c */
+#line 880 "program_parse.y"
+ { (yyval.swiz_mask).swizzle = SWIZZLE_NOOP; (yyval.swiz_mask).mask = WRITEMASK_XYZW; ;}
+ break;
+
+ case 88:
+
+/* Line 1455 of yacc.c */
+#line 892 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (4)].string), at_attrib, & (yylsp[(2) - (4)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->attrib_binding = (yyvsp[(4) - (4)].attrib);
+ state->InputsBound |= (1U << s->attrib_binding);
+
+ if (!validate_inputs(& (yylsp[(4) - (4)]), state)) {
+ YYERROR;
+ }
+ }
+ ;}
+ break;
+
+ case 89:
+
+/* Line 1455 of yacc.c */
+#line 910 "program_parse.y"
+ {
+ (yyval.attrib) = (yyvsp[(2) - (2)].attrib);
+ ;}
+ break;
+
+ case 90:
+
+/* Line 1455 of yacc.c */
+#line 914 "program_parse.y"
+ {
+ (yyval.attrib) = (yyvsp[(2) - (2)].attrib);
+ ;}
+ break;
+
+ case 91:
+
+/* Line 1455 of yacc.c */
+#line 920 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_POS;
+ ;}
+ break;
+
+ case 92:
+
+/* Line 1455 of yacc.c */
+#line 924 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_WEIGHT;
+ ;}
+ break;
+
+ case 93:
+
+/* Line 1455 of yacc.c */
+#line 928 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_NORMAL;
+ ;}
+ break;
+
+ case 94:
+
+/* Line 1455 of yacc.c */
+#line 932 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_secondary_color) {
+ yyerror(& (yylsp[(2) - (2)]), state, "GL_EXT_secondary_color not supported");
+ YYERROR;
+ }
+
+ (yyval.attrib) = VERT_ATTRIB_COLOR0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 95:
+
+/* Line 1455 of yacc.c */
+#line 941 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_fog_coord) {
+ yyerror(& (yylsp[(1) - (1)]), state, "GL_EXT_fog_coord not supported");
+ YYERROR;
+ }
+
+ (yyval.attrib) = VERT_ATTRIB_FOG;
+ ;}
+ break;
+
+ case 96:
+
+/* Line 1455 of yacc.c */
+#line 950 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_TEX0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 97:
+
+/* Line 1455 of yacc.c */
+#line 954 "program_parse.y"
+ {
+ yyerror(& (yylsp[(1) - (4)]), state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ ;}
+ break;
+
+ case 98:
+
+/* Line 1455 of yacc.c */
+#line 959 "program_parse.y"
+ {
+ (yyval.attrib) = VERT_ATTRIB_GENERIC0 + (yyvsp[(3) - (4)].integer);
+ ;}
+ break;
+
+ case 99:
+
+/* Line 1455 of yacc.c */
+#line 965 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxAttribs) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid vertex attribute reference");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 103:
+
+/* Line 1455 of yacc.c */
+#line 979 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_WPOS;
+ ;}
+ break;
+
+ case 104:
+
+/* Line 1455 of yacc.c */
+#line 983 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_COL0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 105:
+
+/* Line 1455 of yacc.c */
+#line 987 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_FOGC;
+ ;}
+ break;
+
+ case 106:
+
+/* Line 1455 of yacc.c */
+#line 991 "program_parse.y"
+ {
+ (yyval.attrib) = FRAG_ATTRIB_TEX0 + (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 109:
+
+/* Line 1455 of yacc.c */
+#line 999 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (3)].string), at_param, & (yylsp[(2) - (3)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = (yyvsp[(3) - (3)].temp_sym).param_binding_type;
+ s->param_binding_begin = (yyvsp[(3) - (3)].temp_sym).param_binding_begin;
+ s->param_binding_length = (yyvsp[(3) - (3)].temp_sym).param_binding_length;
+ s->param_is_array = 0;
+ }
+ ;}
+ break;
+
+ case 110:
+
+/* Line 1455 of yacc.c */
+#line 1015 "program_parse.y"
+ {
+ if (((yyvsp[(4) - (6)].integer) != 0) && ((unsigned) (yyvsp[(4) - (6)].integer) != (yyvsp[(6) - (6)].temp_sym).param_binding_length)) {
+ yyerror(& (yylsp[(4) - (6)]), state,
+ "parameter array size and number of bindings must match");
+ YYERROR;
+ } else {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (6)].string), (yyvsp[(6) - (6)].temp_sym).type, & (yylsp[(2) - (6)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = (yyvsp[(6) - (6)].temp_sym).param_binding_type;
+ s->param_binding_begin = (yyvsp[(6) - (6)].temp_sym).param_binding_begin;
+ s->param_binding_length = (yyvsp[(6) - (6)].temp_sym).param_binding_length;
+ s->param_is_array = 1;
+ }
+ }
+ ;}
+ break;
+
+ case 111:
+
+/* Line 1455 of yacc.c */
+#line 1037 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 112:
+
+/* Line 1455 of yacc.c */
+#line 1041 "program_parse.y"
+ {
+ if (((yyvsp[(1) - (1)].integer) < 1) || ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxParameters)) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid parameter array size");
+ YYERROR;
+ } else {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ }
+ ;}
+ break;
+
+ case 113:
+
+/* Line 1455 of yacc.c */
+#line 1052 "program_parse.y"
+ {
+ (yyval.temp_sym) = (yyvsp[(2) - (2)].temp_sym);
+ ;}
+ break;
+
+ case 114:
+
+/* Line 1455 of yacc.c */
+#line 1058 "program_parse.y"
+ {
+ (yyval.temp_sym) = (yyvsp[(3) - (4)].temp_sym);
+ ;}
+ break;
+
+ case 116:
+
+/* Line 1455 of yacc.c */
+#line 1065 "program_parse.y"
+ {
+ (yyvsp[(1) - (3)].temp_sym).param_binding_length += (yyvsp[(3) - (3)].temp_sym).param_binding_length;
+ (yyval.temp_sym) = (yyvsp[(1) - (3)].temp_sym);
+ ;}
+ break;
+
+ case 117:
+
+/* Line 1455 of yacc.c */
+#line 1072 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 118:
+
+/* Line 1455 of yacc.c */
+#line 1078 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 119:
+
+/* Line 1455 of yacc.c */
+#line 1084 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 120:
+
+/* Line 1455 of yacc.c */
+#line 1092 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 121:
+
+/* Line 1455 of yacc.c */
+#line 1098 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 122:
+
+/* Line 1455 of yacc.c */
+#line 1104 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 123:
+
+/* Line 1455 of yacc.c */
+#line 1112 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 124:
+
+/* Line 1455 of yacc.c */
+#line 1118 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & (yyval.temp_sym), (yyvsp[(1) - (1)].state));
+ ;}
+ break;
+
+ case 125:
+
+/* Line 1455 of yacc.c */
+#line 1124 "program_parse.y"
+ {
+ memset(& (yyval.temp_sym), 0, sizeof((yyval.temp_sym)));
+ (yyval.temp_sym).param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & (yyval.temp_sym), & (yyvsp[(1) - (1)].vector));
+ ;}
+ break;
+
+ case 126:
+
+/* Line 1455 of yacc.c */
+#line 1131 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(1) - (1)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 127:
+
+/* Line 1455 of yacc.c */
+#line 1132 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 128:
+
+/* Line 1455 of yacc.c */
+#line 1135 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 129:
+
+/* Line 1455 of yacc.c */
+#line 1136 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 130:
+
+/* Line 1455 of yacc.c */
+#line 1137 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 131:
+
+/* Line 1455 of yacc.c */
+#line 1138 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 132:
+
+/* Line 1455 of yacc.c */
+#line 1139 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 133:
+
+/* Line 1455 of yacc.c */
+#line 1140 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 134:
+
+/* Line 1455 of yacc.c */
+#line 1141 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 135:
+
+/* Line 1455 of yacc.c */
+#line 1142 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 136:
+
+/* Line 1455 of yacc.c */
+#line 1143 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 137:
+
+/* Line 1455 of yacc.c */
+#line 1144 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 138:
+
+/* Line 1455 of yacc.c */
+#line 1145 "program_parse.y"
+ { memcpy((yyval.state), (yyvsp[(2) - (2)].state), sizeof((yyval.state))); ;}
+ break;
+
+ case 139:
+
+/* Line 1455 of yacc.c */
+#line 1149 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_MATERIAL;
+ (yyval.state)[1] = (yyvsp[(2) - (3)].integer);
+ (yyval.state)[2] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 140:
+
+/* Line 1455 of yacc.c */
+#line 1158 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 141:
+
+/* Line 1455 of yacc.c */
+#line 1162 "program_parse.y"
+ {
+ (yyval.integer) = STATE_EMISSION;
+ ;}
+ break;
+
+ case 142:
+
+/* Line 1455 of yacc.c */
+#line 1166 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SHININESS;
+ ;}
+ break;
+
+ case 143:
+
+/* Line 1455 of yacc.c */
+#line 1172 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHT;
+ (yyval.state)[1] = (yyvsp[(3) - (5)].integer);
+ (yyval.state)[2] = (yyvsp[(5) - (5)].integer);
+ ;}
+ break;
+
+ case 144:
+
+/* Line 1455 of yacc.c */
+#line 1181 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 145:
+
+/* Line 1455 of yacc.c */
+#line 1185 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POSITION;
+ ;}
+ break;
+
+ case 146:
+
+/* Line 1455 of yacc.c */
+#line 1189 "program_parse.y"
+ {
+ if (!state->ctx->Extensions.EXT_point_parameters) {
+ yyerror(& (yylsp[(1) - (1)]), state, "GL_ARB_point_parameters not supported");
+ YYERROR;
+ }
+
+ (yyval.integer) = STATE_ATTENUATION;
+ ;}
+ break;
+
+ case 147:
+
+/* Line 1455 of yacc.c */
+#line 1198 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 148:
+
+/* Line 1455 of yacc.c */
+#line 1202 "program_parse.y"
+ {
+ (yyval.integer) = STATE_HALF_VECTOR;
+ ;}
+ break;
+
+ case 149:
+
+/* Line 1455 of yacc.c */
+#line 1208 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SPOT_DIRECTION;
+ ;}
+ break;
+
+ case 150:
+
+/* Line 1455 of yacc.c */
+#line 1214 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(2) - (2)].state)[0];
+ (yyval.state)[1] = (yyvsp[(2) - (2)].state)[1];
+ ;}
+ break;
+
+ case 151:
+
+/* Line 1455 of yacc.c */
+#line 1221 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTMODEL_AMBIENT;
+ ;}
+ break;
+
+ case 152:
+
+/* Line 1455 of yacc.c */
+#line 1226 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ (yyval.state)[1] = (yyvsp[(1) - (2)].integer);
+ ;}
+ break;
+
+ case 153:
+
+/* Line 1455 of yacc.c */
+#line 1234 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_LIGHTPROD;
+ (yyval.state)[1] = (yyvsp[(3) - (6)].integer);
+ (yyval.state)[2] = (yyvsp[(5) - (6)].integer);
+ (yyval.state)[3] = (yyvsp[(6) - (6)].integer);
+ ;}
+ break;
+
+ case 155:
+
+/* Line 1455 of yacc.c */
+#line 1246 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(3) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 156:
+
+/* Line 1455 of yacc.c */
+#line 1254 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXENV_COLOR;
+ ;}
+ break;
+
+ case 157:
+
+/* Line 1455 of yacc.c */
+#line 1260 "program_parse.y"
+ {
+ (yyval.integer) = STATE_AMBIENT;
+ ;}
+ break;
+
+ case 158:
+
+/* Line 1455 of yacc.c */
+#line 1264 "program_parse.y"
+ {
+ (yyval.integer) = STATE_DIFFUSE;
+ ;}
+ break;
+
+ case 159:
+
+/* Line 1455 of yacc.c */
+#line 1268 "program_parse.y"
+ {
+ (yyval.integer) = STATE_SPECULAR;
+ ;}
+ break;
+
+ case 160:
+
+/* Line 1455 of yacc.c */
+#line 1274 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxLights) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid light selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 161:
+
+/* Line 1455 of yacc.c */
+#line 1285 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_TEXGEN;
+ (yyval.state)[1] = (yyvsp[(2) - (4)].integer);
+ (yyval.state)[2] = (yyvsp[(3) - (4)].integer) + (yyvsp[(4) - (4)].integer);
+ ;}
+ break;
+
+ case 162:
+
+/* Line 1455 of yacc.c */
+#line 1294 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 163:
+
+/* Line 1455 of yacc.c */
+#line 1298 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_OBJECT_S;
+ ;}
+ break;
+
+ case 164:
+
+/* Line 1455 of yacc.c */
+#line 1303 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 165:
+
+/* Line 1455 of yacc.c */
+#line 1307 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 166:
+
+/* Line 1455 of yacc.c */
+#line 1311 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 167:
+
+/* Line 1455 of yacc.c */
+#line 1315 "program_parse.y"
+ {
+ (yyval.integer) = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
+ ;}
+ break;
+
+ case 168:
+
+/* Line 1455 of yacc.c */
+#line 1321 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 169:
+
+/* Line 1455 of yacc.c */
+#line 1328 "program_parse.y"
+ {
+ (yyval.integer) = STATE_FOG_COLOR;
+ ;}
+ break;
+
+ case 170:
+
+/* Line 1455 of yacc.c */
+#line 1332 "program_parse.y"
+ {
+ (yyval.integer) = STATE_FOG_PARAMS;
+ ;}
+ break;
+
+ case 171:
+
+/* Line 1455 of yacc.c */
+#line 1338 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_CLIPPLANE;
+ (yyval.state)[1] = (yyvsp[(3) - (5)].integer);
+ ;}
+ break;
+
+ case 172:
+
+/* Line 1455 of yacc.c */
+#line 1346 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxClipPlanes) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid clip plane selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 173:
+
+/* Line 1455 of yacc.c */
+#line 1357 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 174:
+
+/* Line 1455 of yacc.c */
+#line 1364 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POINT_SIZE;
+ ;}
+ break;
+
+ case 175:
+
+/* Line 1455 of yacc.c */
+#line 1368 "program_parse.y"
+ {
+ (yyval.integer) = STATE_POINT_ATTENUATION;
+ ;}
+ break;
+
+ case 176:
+
+/* Line 1455 of yacc.c */
+#line 1374 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (5)].state)[0];
+ (yyval.state)[1] = (yyvsp[(1) - (5)].state)[1];
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[4] = (yyvsp[(1) - (5)].state)[2];
+ ;}
+ break;
+
+ case 177:
+
+/* Line 1455 of yacc.c */
+#line 1384 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (2)].state)[0];
+ (yyval.state)[1] = (yyvsp[(1) - (2)].state)[1];
+ (yyval.state)[2] = (yyvsp[(2) - (2)].state)[2];
+ (yyval.state)[3] = (yyvsp[(2) - (2)].state)[3];
+ (yyval.state)[4] = (yyvsp[(1) - (2)].state)[2];
+ ;}
+ break;
+
+ case 178:
+
+/* Line 1455 of yacc.c */
+#line 1394 "program_parse.y"
+ {
+ (yyval.state)[2] = 0;
+ (yyval.state)[3] = 3;
+ ;}
+ break;
+
+ case 179:
+
+/* Line 1455 of yacc.c */
+#line 1399 "program_parse.y"
+ {
+ /* It seems logical that the matrix row range specifier would have
+ * to specify a range or more than one row (i.e., $5 > $3).
+ * However, the ARB_vertex_program spec says "a program will fail
+ * to load if <a> is greater than <b>." This means that $3 == $5
+ * is valid.
+ */
+ if ((yyvsp[(3) - (6)].integer) > (yyvsp[(5) - (6)].integer)) {
+ yyerror(& (yylsp[(3) - (6)]), state, "invalid matrix row range");
+ YYERROR;
+ }
+
+ (yyval.state)[2] = (yyvsp[(3) - (6)].integer);
+ (yyval.state)[3] = (yyvsp[(5) - (6)].integer);
+ ;}
+ break;
+
+ case 180:
+
+/* Line 1455 of yacc.c */
+#line 1417 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(2) - (3)].state)[0];
+ (yyval.state)[1] = (yyvsp[(2) - (3)].state)[1];
+ (yyval.state)[2] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 181:
+
+/* Line 1455 of yacc.c */
+#line 1425 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 182:
+
+/* Line 1455 of yacc.c */
+#line 1429 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 183:
+
+/* Line 1455 of yacc.c */
+#line 1435 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_INVERSE;
+ ;}
+ break;
+
+ case 184:
+
+/* Line 1455 of yacc.c */
+#line 1439 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_TRANSPOSE;
+ ;}
+ break;
+
+ case 185:
+
+/* Line 1455 of yacc.c */
+#line 1443 "program_parse.y"
+ {
+ (yyval.integer) = STATE_MATRIX_INVTRANS;
+ ;}
+ break;
+
+ case 186:
+
+/* Line 1455 of yacc.c */
+#line 1449 "program_parse.y"
+ {
+ if ((yyvsp[(1) - (1)].integer) > 3) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid matrix row reference");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 187:
+
+/* Line 1455 of yacc.c */
+#line 1460 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_MODELVIEW_MATRIX;
+ (yyval.state)[1] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 188:
+
+/* Line 1455 of yacc.c */
+#line 1465 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_PROJECTION_MATRIX;
+ (yyval.state)[1] = 0;
+ ;}
+ break;
+
+ case 189:
+
+/* Line 1455 of yacc.c */
+#line 1470 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_MVP_MATRIX;
+ (yyval.state)[1] = 0;
+ ;}
+ break;
+
+ case 190:
+
+/* Line 1455 of yacc.c */
+#line 1475 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_TEXTURE_MATRIX;
+ (yyval.state)[1] = (yyvsp[(2) - (2)].integer);
+ ;}
+ break;
+
+ case 191:
+
+/* Line 1455 of yacc.c */
+#line 1480 "program_parse.y"
+ {
+ yyerror(& (yylsp[(1) - (4)]), state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ ;}
+ break;
+
+ case 192:
+
+/* Line 1455 of yacc.c */
+#line 1485 "program_parse.y"
+ {
+ (yyval.state)[0] = STATE_PROGRAM_MATRIX;
+ (yyval.state)[1] = (yyvsp[(3) - (4)].integer);
+ ;}
+ break;
+
+ case 193:
+
+/* Line 1455 of yacc.c */
+#line 1492 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 194:
+
+/* Line 1455 of yacc.c */
+#line 1496 "program_parse.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 195:
+
+/* Line 1455 of yacc.c */
+#line 1501 "program_parse.y"
+ {
+ /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
+ * zero is valid.
+ */
+ if ((yyvsp[(1) - (1)].integer) != 0) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid modelview matrix index");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 196:
+
+/* Line 1455 of yacc.c */
+#line 1514 "program_parse.y"
+ {
+ /* Since GL_ARB_matrix_palette isn't supported, just let any value
+ * through here. The error will be generated later.
+ */
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 197:
+
+/* Line 1455 of yacc.c */
+#line 1522 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxProgramMatrices) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program matrix selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 198:
+
+/* Line 1455 of yacc.c */
+#line 1533 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = STATE_DEPTH_RANGE;
+ ;}
+ break;
+
+ case 203:
+
+/* Line 1455 of yacc.c */
+#line 1545 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_ENV;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].state)[0];
+ (yyval.state)[3] = (yyvsp[(4) - (5)].state)[1];
+ ;}
+ break;
+
+ case 204:
+
+/* Line 1455 of yacc.c */
+#line 1555 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (1)].integer);
+ (yyval.state)[1] = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 205:
+
+/* Line 1455 of yacc.c */
+#line 1560 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 206:
+
+/* Line 1455 of yacc.c */
+#line 1567 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_ENV;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ ;}
+ break;
+
+ case 207:
+
+/* Line 1455 of yacc.c */
+#line 1577 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_LOCAL;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].state)[0];
+ (yyval.state)[3] = (yyvsp[(4) - (5)].state)[1];
+ ;}
+ break;
+
+ case 208:
+
+/* Line 1455 of yacc.c */
+#line 1586 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (1)].integer);
+ (yyval.state)[1] = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 209:
+
+/* Line 1455 of yacc.c */
+#line 1591 "program_parse.y"
+ {
+ (yyval.state)[0] = (yyvsp[(1) - (3)].integer);
+ (yyval.state)[1] = (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 210:
+
+/* Line 1455 of yacc.c */
+#line 1598 "program_parse.y"
+ {
+ memset((yyval.state), 0, sizeof((yyval.state)));
+ (yyval.state)[0] = state->state_param_enum;
+ (yyval.state)[1] = STATE_LOCAL;
+ (yyval.state)[2] = (yyvsp[(4) - (5)].integer);
+ (yyval.state)[3] = (yyvsp[(4) - (5)].integer);
+ ;}
+ break;
+
+ case 211:
+
+/* Line 1455 of yacc.c */
+#line 1608 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxEnvParams) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid environment parameter reference");
+ YYERROR;
+ }
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 212:
+
+/* Line 1455 of yacc.c */
+#line 1618 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->limits->MaxLocalParams) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid local parameter reference");
+ YYERROR;
+ }
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 217:
+
+/* Line 1455 of yacc.c */
+#line 1633 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[1] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[2] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[3] = (yyvsp[(1) - (1)].real);
+ ;}
+ break;
+
+ case 218:
+
+/* Line 1455 of yacc.c */
+#line 1643 "program_parse.y"
+ {
+ (yyval.vector).count = 1;
+ (yyval.vector).data[0] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[1] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[2] = (yyvsp[(1) - (1)].real);
+ (yyval.vector).data[3] = (yyvsp[(1) - (1)].real);
+ ;}
+ break;
+
+ case 219:
+
+/* Line 1455 of yacc.c */
+#line 1651 "program_parse.y"
+ {
+ (yyval.vector).count = 1;
+ (yyval.vector).data[0] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[1] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[2] = (float) (yyvsp[(1) - (1)].integer);
+ (yyval.vector).data[3] = (float) (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 220:
+
+/* Line 1455 of yacc.c */
+#line 1661 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (3)].real);
+ (yyval.vector).data[1] = 0.0f;
+ (yyval.vector).data[2] = 0.0f;
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 221:
+
+/* Line 1455 of yacc.c */
+#line 1669 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (5)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (5)].real);
+ (yyval.vector).data[2] = 0.0f;
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 222:
+
+/* Line 1455 of yacc.c */
+#line 1678 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (7)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (7)].real);
+ (yyval.vector).data[2] = (yyvsp[(6) - (7)].real);
+ (yyval.vector).data[3] = 1.0f;
+ ;}
+ break;
+
+ case 223:
+
+/* Line 1455 of yacc.c */
+#line 1687 "program_parse.y"
+ {
+ (yyval.vector).count = 4;
+ (yyval.vector).data[0] = (yyvsp[(2) - (9)].real);
+ (yyval.vector).data[1] = (yyvsp[(4) - (9)].real);
+ (yyval.vector).data[2] = (yyvsp[(6) - (9)].real);
+ (yyval.vector).data[3] = (yyvsp[(8) - (9)].real);
+ ;}
+ break;
+
+ case 224:
+
+/* Line 1455 of yacc.c */
+#line 1697 "program_parse.y"
+ {
+ (yyval.real) = ((yyvsp[(1) - (2)].negate)) ? -(yyvsp[(2) - (2)].real) : (yyvsp[(2) - (2)].real);
+ ;}
+ break;
+
+ case 225:
+
+/* Line 1455 of yacc.c */
+#line 1701 "program_parse.y"
+ {
+ (yyval.real) = (float)(((yyvsp[(1) - (2)].negate)) ? -(yyvsp[(2) - (2)].integer) : (yyvsp[(2) - (2)].integer));
+ ;}
+ break;
+
+ case 226:
+
+/* Line 1455 of yacc.c */
+#line 1706 "program_parse.y"
+ { (yyval.negate) = FALSE; ;}
+ break;
+
+ case 227:
+
+/* Line 1455 of yacc.c */
+#line 1707 "program_parse.y"
+ { (yyval.negate) = TRUE; ;}
+ break;
+
+ case 228:
+
+/* Line 1455 of yacc.c */
+#line 1708 "program_parse.y"
+ { (yyval.negate) = FALSE; ;}
+ break;
+
+ case 229:
+
+/* Line 1455 of yacc.c */
+#line 1711 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(1) - (1)].integer); ;}
+ break;
+
+ case 231:
+
+/* Line 1455 of yacc.c */
+#line 1714 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(1) - (1)].integer); ;}
+ break;
+
+ case 233:
+
+/* Line 1455 of yacc.c */
+#line 1718 "program_parse.y"
+ {
+ if (!declare_variable(state, (yyvsp[(3) - (3)].string), (yyvsp[(0) - (3)].integer), & (yylsp[(3) - (3)]))) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 234:
+
+/* Line 1455 of yacc.c */
+#line 1724 "program_parse.y"
+ {
+ if (!declare_variable(state, (yyvsp[(1) - (1)].string), (yyvsp[(0) - (1)].integer), & (yylsp[(1) - (1)]))) {
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 235:
+
+/* Line 1455 of yacc.c */
+#line 1732 "program_parse.y"
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, (yyvsp[(2) - (4)].string), at_output, & (yylsp[(2) - (4)]));
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->output_binding = (yyvsp[(4) - (4)].result);
+ }
+ ;}
+ break;
+
+ case 236:
+
+/* Line 1455 of yacc.c */
+#line 1745 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_HPOS;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 237:
+
+/* Line 1455 of yacc.c */
+#line 1754 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_FOGC;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 238:
+
+/* Line 1455 of yacc.c */
+#line 1763 "program_parse.y"
+ {
+ (yyval.result) = (yyvsp[(2) - (2)].result);
+ ;}
+ break;
+
+ case 239:
+
+/* Line 1455 of yacc.c */
+#line 1767 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_PSIZ;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 240:
+
+/* Line 1455 of yacc.c */
+#line 1776 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.result) = VERT_RESULT_TEX0 + (yyvsp[(3) - (3)].integer);
+ } else {
+ yyerror(& (yylsp[(2) - (3)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 241:
+
+/* Line 1455 of yacc.c */
+#line 1785 "program_parse.y"
+ {
+ if (state->mode == ARB_fragment) {
+ (yyval.result) = FRAG_RESULT_DEPTH;
+ } else {
+ yyerror(& (yylsp[(2) - (2)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 242:
+
+/* Line 1455 of yacc.c */
+#line 1796 "program_parse.y"
+ {
+ (yyval.result) = (yyvsp[(2) - (3)].integer) + (yyvsp[(3) - (3)].integer);
+ ;}
+ break;
+
+ case 243:
+
+/* Line 1455 of yacc.c */
+#line 1802 "program_parse.y"
+ {
+ (yyval.integer) = (state->mode == ARB_vertex)
+ ? VERT_RESULT_COL0
+ : FRAG_RESULT_COLOR;
+ ;}
+ break;
+
+ case 244:
+
+/* Line 1455 of yacc.c */
+#line 1808 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = VERT_RESULT_COL0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 245:
+
+/* Line 1455 of yacc.c */
+#line 1817 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = VERT_RESULT_BFC0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 246:
+
+/* Line 1455 of yacc.c */
+#line 1828 "program_parse.y"
+ {
+ (yyval.integer) = 0;
+ ;}
+ break;
+
+ case 247:
+
+/* Line 1455 of yacc.c */
+#line 1832 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = 0;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 248:
+
+/* Line 1455 of yacc.c */
+#line 1841 "program_parse.y"
+ {
+ if (state->mode == ARB_vertex) {
+ (yyval.integer) = 1;
+ } else {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid program result name");
+ YYERROR;
+ }
+ ;}
+ break;
+
+ case 249:
+
+/* Line 1455 of yacc.c */
+#line 1851 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 250:
+
+/* Line 1455 of yacc.c */
+#line 1852 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 251:
+
+/* Line 1455 of yacc.c */
+#line 1853 "program_parse.y"
+ { (yyval.integer) = 1; ;}
+ break;
+
+ case 252:
+
+/* Line 1455 of yacc.c */
+#line 1856 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 253:
+
+/* Line 1455 of yacc.c */
+#line 1857 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 254:
+
+/* Line 1455 of yacc.c */
+#line 1858 "program_parse.y"
+ { (yyval.integer) = 1; ;}
+ break;
+
+ case 255:
+
+/* Line 1455 of yacc.c */
+#line 1861 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 256:
+
+/* Line 1455 of yacc.c */
+#line 1862 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 257:
+
+/* Line 1455 of yacc.c */
+#line 1865 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 258:
+
+/* Line 1455 of yacc.c */
+#line 1866 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 259:
+
+/* Line 1455 of yacc.c */
+#line 1869 "program_parse.y"
+ { (yyval.integer) = 0; ;}
+ break;
+
+ case 260:
+
+/* Line 1455 of yacc.c */
+#line 1870 "program_parse.y"
+ { (yyval.integer) = (yyvsp[(2) - (3)].integer); ;}
+ break;
+
+ case 261:
+
+/* Line 1455 of yacc.c */
+#line 1874 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureCoordUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture coordinate unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 262:
+
+/* Line 1455 of yacc.c */
+#line 1885 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureImageUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture image unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 263:
+
+/* Line 1455 of yacc.c */
+#line 1896 "program_parse.y"
+ {
+ if ((unsigned) (yyvsp[(1) - (1)].integer) >= state->MaxTextureUnits) {
+ yyerror(& (yylsp[(1) - (1)]), state, "invalid texture unit selector");
+ YYERROR;
+ }
+
+ (yyval.integer) = (yyvsp[(1) - (1)].integer);
+ ;}
+ break;
+
+ case 264:
+
+/* Line 1455 of yacc.c */
+#line 1907 "program_parse.y"
+ {
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(2) - (4)].string));
+ struct asm_symbol *target = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, (yyvsp[(4) - (4)].string));
+
+
+ if (exist != NULL) {
+ yyerror(& (yylsp[(2) - (4)]), state, "redeclared identifier");
+ YYERROR;
+ } else if (target == NULL) {
+ yyerror(& (yylsp[(4) - (4)]), state,
+ "undefined variable binding in ALIAS statement");
+ YYERROR;
+ } else {
+ _mesa_symbol_table_add_symbol(state->st, 0, (yyvsp[(2) - (4)].string), target);
+ }
+ ;}
+ break;
+
+
+
+/* Line 1455 of yacc.c */
+#line 4577 "program_parse.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, state, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (&yylloc, state, yymsg);
+ }
+ else
+ {
+ yyerror (&yylloc, state, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[0] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, state);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[0] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+ yyerror_range[1] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, state, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, state);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, state);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c */
+#line 1927 "program_parse.y"
+
+
+struct asm_instruction *
+asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst,
+ const struct asm_src_register *src0,
+ const struct asm_src_register *src1,
+ const struct asm_src_register *src2)
+{
+ struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
+
+ if (inst) {
+ _mesa_init_instructions(& inst->Base, 1);
+ inst->Base.Opcode = op;
+
+ /* In the core ARB extensions only the KIL instruction doesn't have a
+ * destination register.
+ */
+ if (dst == NULL) {
+ init_dst_reg(& inst->Base.DstReg);
+ } else {
+ inst->Base.DstReg = *dst;
+ }
+
+ inst->Base.SrcReg[0] = src0->Base;
+ inst->SrcReg[0] = *src0;
+
+ if (src1 != NULL) {
+ inst->Base.SrcReg[1] = src1->Base;
+ inst->SrcReg[1] = *src1;
+ } else {
+ init_src_reg(& inst->SrcReg[1]);
+ }
+
+ if (src2 != NULL) {
+ inst->Base.SrcReg[2] = src2->Base;
+ inst->SrcReg[2] = *src2;
+ } else {
+ init_src_reg(& inst->SrcReg[2]);
+ }
+ }
+
+ return inst;
+}
+
+
+void
+init_dst_reg(struct prog_dst_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->File = PROGRAM_UNDEFINED;
+ r->WriteMask = WRITEMASK_XYZW;
+ r->CondMask = COND_TR;
+ r->CondSwizzle = SWIZZLE_NOOP;
+}
+
+
+void
+init_src_reg(struct asm_src_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->Base.File = PROGRAM_UNDEFINED;
+ r->Base.Swizzle = SWIZZLE_NOOP;
+ r->Symbol = NULL;
+}
+
+
+/**
+ * Validate the set of inputs used by a program
+ *
+ * Validates that legal sets of inputs are used by the program. In this case
+ * "used" included both reading the input or binding the input to a name using
+ * the \c ATTRIB command.
+ *
+ * \return
+ * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
+ */
+int
+validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
+{
+ const int inputs = state->prog->InputsRead | state->InputsBound;
+
+ if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
+ yyerror(locp, state, "illegal use of generic attribute and name attribute");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+struct asm_symbol *
+declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
+ struct YYLTYPE *locp)
+{
+ struct asm_symbol *s = NULL;
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, name);
+
+
+ if (exist != NULL) {
+ yyerror(locp, state, "redeclared identifier");
+ } else {
+ s = calloc(1, sizeof(struct asm_symbol));
+ s->name = name;
+ s->type = t;
+
+ switch (t) {
+ case at_temp:
+ if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
+ yyerror(locp, state, "too many temporaries declared");
+ free(s);
+ return NULL;
+ }
+
+ s->temp_binding = state->prog->NumTemporaries;
+ state->prog->NumTemporaries++;
+ break;
+
+ case at_address:
+ if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
+ yyerror(locp, state, "too many address registers declared");
+ free(s);
+ return NULL;
+ }
+
+ /* FINISHME: Add support for multiple address registers.
+ */
+ state->prog->NumAddressRegs++;
+ break;
+
+ default:
+ break;
+ }
+
+ _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
+ s->next = state->sym;
+ state->sym = s;
+ }
+
+ return s;
+}
+
+
+int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ const GLuint size = 4; /* XXX fix */
+ char *name;
+ GLint index;
+
+ name = _mesa_program_state_string(tokens);
+ index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
+ size, GL_NONE, NULL, tokens, 0x0);
+ param_list->StateFlags |= _mesa_program_state_flags(tokens);
+
+ /* free name string here since we duplicated it in add_parameter() */
+ _mesa_free(name);
+
+ return index;
+}
+
+
+int
+initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+
+ /* If we are adding a STATE_MATRIX that has multiple rows, we need to
+ * unroll it and call add_state_reference() for each row
+ */
+ if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
+ state_tokens[0] == STATE_PROJECTION_MATRIX ||
+ state_tokens[0] == STATE_MVP_MATRIX ||
+ state_tokens[0] == STATE_TEXTURE_MATRIX ||
+ state_tokens[0] == STATE_PROGRAM_MATRIX)
+ && (state_tokens[2] != state_tokens[3])) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
+ || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
+ assert((state_tokens[1] == STATE_ENV)
+ || (state_tokens[1] == STATE_LOCAL));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
+ ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
+
+ /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
+ * we need to unroll it and call add_state_reference() for each row
+ */
+ if (state_tokens[2] != state_tokens[3]) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const struct asm_vector *vec)
+{
+ const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
+ NULL, vec->count, GL_NONE, vec->data,
+ NULL, 0x0);
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_CONSTANT;
+
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+
+ return idx;
+}
+
+
+char *
+make_error_string(const char *fmt, ...)
+{
+ int length;
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+
+ /* Call vsnprintf once to determine how large the final string is. Call it
+ * again to do the actual formatting. from the vsnprintf manual page:
+ *
+ * Upon successful return, these functions return the number of
+ * characters printed (not including the trailing '\0' used to end
+ * output to strings).
+ */
+ length = 1 + vsnprintf(NULL, 0, fmt, args);
+
+ str = _mesa_malloc(length);
+ if (str) {
+ vsnprintf(str, length, fmt, args);
+ }
+
+ va_end(args);
+
+ return str;
+}
+
+
+void
+yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
+{
+ char *err_str;
+
+
+ err_str = make_error_string("glProgramStringARB(%s)\n", s);
+ if (err_str) {
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_free(err_str);
+ }
+
+ err_str = make_error_string("line %u, char %u: error: %s\n",
+ locp->first_line, locp->first_column, s);
+ _mesa_set_program_error(state->ctx, locp->position, err_str);
+
+ if (err_str) {
+ _mesa_free(err_str);
+ }
+}
+
+
+GLboolean
+_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+ GLsizei len, struct asm_parser_state *state)
+{
+ struct asm_instruction *inst;
+ unsigned i;
+ GLubyte *strz;
+ GLboolean result = GL_FALSE;
+ void *temp;
+ struct asm_symbol *sym;
+
+ state->ctx = ctx;
+ state->prog->Target = target;
+ state->prog->Parameters = _mesa_new_parameter_list();
+
+ /* Make a copy of the program string and force it to be NUL-terminated.
+ */
+ strz = (GLubyte *) _mesa_malloc(len + 1);
+ if (strz == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return GL_FALSE;
+ }
+ _mesa_memcpy (strz, str, len);
+ strz[len] = '\0';
+
+ state->prog->String = strz;
+
+ state->st = _mesa_symbol_table_ctor();
+
+ state->limits = (target == GL_VERTEX_PROGRAM_ARB)
+ ? & ctx->Const.VertexProgram
+ : & ctx->Const.FragmentProgram;
+
+ state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+ state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
+ state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
+ state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
+ state->MaxLights = ctx->Const.MaxLights;
+ state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+
+ state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
+ ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
+
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
+ yyparse(state);
+ _mesa_program_lexer_dtor(state->scanner);
+
+
+ if (ctx->Program.ErrorPos != -1) {
+ goto error;
+ }
+
+ if (! _mesa_layout_parameters(state)) {
+ struct YYLTYPE loc;
+
+ loc.first_line = 0;
+ loc.first_column = 0;
+ loc.position = len;
+
+ yyerror(& loc, state, "invalid PARAM usage");
+ goto error;
+ }
+
+
+
+ /* Add one instruction to store the "END" instruction.
+ */
+ state->prog->Instructions =
+ _mesa_alloc_instructions(state->prog->NumInstructions + 1);
+ inst = state->inst_head;
+ for (i = 0; i < state->prog->NumInstructions; i++) {
+ struct asm_instruction *const temp = inst->next;
+
+ state->prog->Instructions[i] = inst->Base;
+ inst = temp;
+ }
+
+ /* Finally, tag on an OPCODE_END instruction */
+ {
+ const GLuint numInst = state->prog->NumInstructions;
+ _mesa_init_instructions(state->prog->Instructions + numInst, 1);
+ state->prog->Instructions[numInst].Opcode = OPCODE_END;
+ }
+ state->prog->NumInstructions++;
+
+ state->prog->NumParameters = state->prog->Parameters->NumParameters;
+ state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
+
+ /*
+ * Initialize native counts to logical counts. The device driver may
+ * change them if program is translated into a hardware program.
+ */
+ state->prog->NumNativeInstructions = state->prog->NumInstructions;
+ state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
+ state->prog->NumNativeParameters = state->prog->NumParameters;
+ state->prog->NumNativeAttributes = state->prog->NumAttributes;
+ state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
+
+ result = GL_TRUE;
+
+error:
+ for (inst = state->inst_head; inst != NULL; inst = temp) {
+ temp = inst->next;
+ _mesa_free(inst);
+ }
+
+ state->inst_head = NULL;
+ state->inst_tail = NULL;
+
+ for (sym = state->sym; sym != NULL; sym = temp) {
+ temp = sym->next;
+
+ _mesa_free((void *) sym->name);
+ _mesa_free(sym);
+ }
+ state->sym = NULL;
+
+ _mesa_symbol_table_dtor(state->st);
+ state->st = NULL;
+
+ return result;
+}
+
diff --git a/mesalib/src/mesa/shader/program_parse.tab.h b/mesalib/src/mesa/shader/program_parse.tab.h
new file mode 100644
index 000000000..dabb3bf1a
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_parse.tab.h
@@ -0,0 +1,207 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ARBvp_10 = 258,
+ ARBfp_10 = 259,
+ ADDRESS = 260,
+ ALIAS = 261,
+ ATTRIB = 262,
+ OPTION = 263,
+ OUTPUT = 264,
+ PARAM = 265,
+ TEMP = 266,
+ END = 267,
+ BIN_OP = 268,
+ BINSC_OP = 269,
+ SAMPLE_OP = 270,
+ SCALAR_OP = 271,
+ TRI_OP = 272,
+ VECTOR_OP = 273,
+ ARL = 274,
+ KIL = 275,
+ SWZ = 276,
+ INTEGER = 277,
+ REAL = 278,
+ AMBIENT = 279,
+ ATTENUATION = 280,
+ BACK = 281,
+ CLIP = 282,
+ COLOR = 283,
+ DEPTH = 284,
+ DIFFUSE = 285,
+ DIRECTION = 286,
+ EMISSION = 287,
+ ENV = 288,
+ EYE = 289,
+ FOG = 290,
+ FOGCOORD = 291,
+ FRAGMENT = 292,
+ FRONT = 293,
+ HALF = 294,
+ INVERSE = 295,
+ INVTRANS = 296,
+ LIGHT = 297,
+ LIGHTMODEL = 298,
+ LIGHTPROD = 299,
+ LOCAL = 300,
+ MATERIAL = 301,
+ MAT_PROGRAM = 302,
+ MATRIX = 303,
+ MATRIXINDEX = 304,
+ MODELVIEW = 305,
+ MVP = 306,
+ NORMAL = 307,
+ OBJECT = 308,
+ PALETTE = 309,
+ PARAMS = 310,
+ PLANE = 311,
+ POINT_TOK = 312,
+ POINTSIZE = 313,
+ POSITION = 314,
+ PRIMARY = 315,
+ PROGRAM = 316,
+ PROJECTION = 317,
+ RANGE = 318,
+ RESULT = 319,
+ ROW = 320,
+ SCENECOLOR = 321,
+ SECONDARY = 322,
+ SHININESS = 323,
+ SIZE_TOK = 324,
+ SPECULAR = 325,
+ SPOT = 326,
+ STATE = 327,
+ TEXCOORD = 328,
+ TEXENV = 329,
+ TEXGEN = 330,
+ TEXGEN_Q = 331,
+ TEXGEN_R = 332,
+ TEXGEN_S = 333,
+ TEXGEN_T = 334,
+ TEXTURE = 335,
+ TRANSPOSE = 336,
+ TEXTURE_UNIT = 337,
+ TEX_1D = 338,
+ TEX_2D = 339,
+ TEX_3D = 340,
+ TEX_CUBE = 341,
+ TEX_RECT = 342,
+ TEX_SHADOW1D = 343,
+ TEX_SHADOW2D = 344,
+ TEX_SHADOWRECT = 345,
+ TEX_ARRAY1D = 346,
+ TEX_ARRAY2D = 347,
+ TEX_ARRAYSHADOW1D = 348,
+ TEX_ARRAYSHADOW2D = 349,
+ VERTEX = 350,
+ VTXATTRIB = 351,
+ WEIGHT = 352,
+ IDENTIFIER = 353,
+ MASK4 = 354,
+ MASK3 = 355,
+ MASK2 = 356,
+ MASK1 = 357,
+ SWIZZLE = 358,
+ DOT_DOT = 359,
+ DOT = 360
+ };
+#endif
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 107 "program_parse.y"
+
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+
+
+
+/* Line 1676 of yacc.c */
+#line 185 "program_parse.tab.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/mesalib/src/mesa/shader/program_parse.y b/mesalib/src/mesa/shader/program_parse.y
new file mode 100644
index 000000000..06c1915fb
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_parse.y
@@ -0,0 +1,2379 @@
+%{
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "main/mtypes.h"
+#include "main/imports.h"
+#include "program.h"
+#include "prog_parameter.h"
+#include "prog_parameter_layout.h"
+#include "prog_statevars.h"
+#include "prog_instruction.h"
+
+#include "symbol_table.h"
+#include "program_parser.h"
+
+extern void *yy_scan_string(char *);
+extern void yy_delete_buffer(void *);
+
+static struct asm_symbol *declare_variable(struct asm_parser_state *state,
+ char *name, enum asm_type t, struct YYLTYPE *locp);
+
+static int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var, const gl_state_index tokens[STATE_LENGTH]);
+
+static int initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var, const struct asm_vector *vec);
+
+static int yyparse(struct asm_parser_state *state);
+
+static char *make_error_string(const char *fmt, ...);
+
+static void yyerror(struct YYLTYPE *locp, struct asm_parser_state *state,
+ const char *s);
+
+static int validate_inputs(struct YYLTYPE *locp,
+ struct asm_parser_state *state);
+
+static void init_dst_reg(struct prog_dst_register *r);
+
+static void init_src_reg(struct asm_src_register *r);
+
+static struct asm_instruction *asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst, const struct asm_src_register *src0,
+ const struct asm_src_register *src1, const struct asm_src_register *src2);
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 1).position; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC(Rhs, N).last_column; \
+ } else { \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_line = (Current).first_line; \
+ (Current).first_column = YYRHSLOC(Rhs, 0).last_column; \
+ (Current).last_column = (Current).first_column; \
+ (Current).position = YYRHSLOC(Rhs, 0).position \
+ + (Current).first_column; \
+ } \
+ } while(YYID(0))
+
+#define YYLEX_PARAM state->scanner
+%}
+
+%pure-parser
+%locations
+%parse-param { struct asm_parser_state *state }
+%error-verbose
+%lex-param { void *scanner }
+
+%union {
+ struct asm_instruction *inst;
+ struct asm_symbol *sym;
+ struct asm_symbol temp_sym;
+ struct asm_swizzle_mask swiz_mask;
+ struct asm_src_register src_reg;
+ struct prog_dst_register dst_reg;
+ struct prog_instruction temp_inst;
+ char *string;
+ unsigned result;
+ unsigned attrib;
+ int integer;
+ float real;
+ gl_state_index state[STATE_LENGTH];
+ int negate;
+ struct asm_vector vector;
+ gl_inst_opcode opcode;
+
+ struct {
+ unsigned swz;
+ unsigned rgba_valid:1;
+ unsigned xyzw_valid:1;
+ unsigned negate:1;
+ } ext_swizzle;
+}
+
+%token ARBvp_10 ARBfp_10
+
+/* Tokens for assembler pseudo-ops */
+%token <integer> ADDRESS
+%token ALIAS ATTRIB
+%token OPTION OUTPUT
+%token PARAM
+%token <integer> TEMP
+%token END
+
+ /* Tokens for instructions */
+%token <temp_inst> BIN_OP BINSC_OP SAMPLE_OP SCALAR_OP TRI_OP VECTOR_OP
+%token <temp_inst> ARL KIL SWZ
+
+%token <integer> INTEGER
+%token <real> REAL
+
+%token AMBIENT ATTENUATION
+%token BACK
+%token CLIP COLOR
+%token DEPTH DIFFUSE DIRECTION
+%token EMISSION ENV EYE
+%token FOG FOGCOORD FRAGMENT FRONT
+%token HALF
+%token INVERSE INVTRANS
+%token LIGHT LIGHTMODEL LIGHTPROD LOCAL
+%token MATERIAL MAT_PROGRAM MATRIX MATRIXINDEX MODELVIEW MVP
+%token NORMAL
+%token OBJECT
+%token PALETTE PARAMS PLANE POINT_TOK POINTSIZE POSITION PRIMARY PROGRAM PROJECTION
+%token RANGE RESULT ROW
+%token SCENECOLOR SECONDARY SHININESS SIZE_TOK SPECULAR SPOT STATE
+%token TEXCOORD TEXENV TEXGEN TEXGEN_Q TEXGEN_R TEXGEN_S TEXGEN_T TEXTURE TRANSPOSE
+%token TEXTURE_UNIT TEX_1D TEX_2D TEX_3D TEX_CUBE TEX_RECT
+%token TEX_SHADOW1D TEX_SHADOW2D TEX_SHADOWRECT
+%token TEX_ARRAY1D TEX_ARRAY2D TEX_ARRAYSHADOW1D TEX_ARRAYSHADOW2D
+%token VERTEX VTXATTRIB
+%token WEIGHT
+
+%token <string> IDENTIFIER
+%token <swiz_mask> MASK4 MASK3 MASK2 MASK1 SWIZZLE
+%token DOT_DOT
+%token DOT
+
+%type <inst> instruction ALU_instruction TexInstruction
+%type <inst> ARL_instruction VECTORop_instruction
+%type <inst> SCALARop_instruction BINSCop_instruction BINop_instruction
+%type <inst> TRIop_instruction SWZ_instruction SAMPLE_instruction
+%type <inst> KIL_instruction
+
+%type <dst_reg> dstReg maskedDstReg maskedAddrReg
+%type <src_reg> srcReg scalarSrcReg swizzleSrcReg
+%type <swiz_mask> scalarSuffix swizzleSuffix extendedSwizzle
+%type <ext_swizzle> extSwizComp extSwizSel
+%type <swiz_mask> optionalMask
+
+%type <sym> progParamArray
+%type <integer> addrRegRelOffset addrRegPosOffset addrRegNegOffset
+%type <src_reg> progParamArrayMem progParamArrayAbs progParamArrayRel
+%type <sym> addrReg
+%type <swiz_mask> addrComponent addrWriteMask
+
+%type <result> resultBinding resultColBinding
+%type <integer> optFaceType optColorType
+%type <integer> optResultFaceType optResultColorType
+
+%type <integer> optTexImageUnitNum texImageUnitNum
+%type <integer> optTexCoordUnitNum texCoordUnitNum
+%type <integer> optLegacyTexUnitNum legacyTexUnitNum
+%type <integer> texImageUnit texTarget
+%type <integer> vtxAttribNum
+
+%type <attrib> attribBinding vtxAttribItem fragAttribItem
+
+%type <temp_sym> paramSingleInit paramSingleItemDecl
+%type <integer> optArraySize
+
+%type <state> stateSingleItem stateMultipleItem
+%type <state> stateMaterialItem
+%type <state> stateLightItem stateLightModelItem stateLightProdItem
+%type <state> stateTexGenItem stateFogItem stateClipPlaneItem statePointItem
+%type <state> stateMatrixItem stateMatrixRow stateMatrixRows
+%type <state> stateTexEnvItem stateDepthItem
+
+%type <state> stateLModProperty
+%type <state> stateMatrixName optMatrixRows
+
+%type <integer> stateMatProperty
+%type <integer> stateLightProperty stateSpotProperty
+%type <integer> stateLightNumber stateLProdProperty
+%type <integer> stateTexGenType stateTexGenCoord
+%type <integer> stateTexEnvProperty
+%type <integer> stateFogProperty
+%type <integer> stateClipPlaneNum
+%type <integer> statePointProperty
+
+%type <integer> stateOptMatModifier stateMatModifier stateMatrixRowNum
+%type <integer> stateOptModMatNum stateModMatNum statePaletteMatNum
+%type <integer> stateProgramMatNum
+
+%type <integer> ambDiffSpecProperty
+
+%type <state> programSingleItem progEnvParam progLocalParam
+%type <state> programMultipleItem progEnvParams progLocalParams
+
+%type <temp_sym> paramMultipleInit paramMultInitList paramMultipleItem
+%type <temp_sym> paramSingleItemUse
+
+%type <integer> progEnvParamNum progLocalParamNum
+%type <state> progEnvParamNums progLocalParamNums
+
+%type <vector> paramConstDecl paramConstUse
+%type <vector> paramConstScalarDecl paramConstScalarUse paramConstVector
+%type <real> signedFloatConstant
+%type <negate> optionalSign
+
+%{
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param,
+ void *yyscanner);
+%}
+
+%%
+
+program: language optionSequence statementSequence END
+ ;
+
+language: ARBvp_10
+ {
+ if (state->prog->Target != GL_VERTEX_PROGRAM_ARB) {
+ yyerror(& @1, state, "invalid fragment program header");
+
+ }
+ state->mode = ARB_vertex;
+ }
+ | ARBfp_10
+ {
+ if (state->prog->Target != GL_FRAGMENT_PROGRAM_ARB) {
+ yyerror(& @1, state, "invalid vertex program header");
+ }
+ state->mode = ARB_fragment;
+
+ state->option.TexRect =
+ (state->ctx->Extensions.NV_texture_rectangle != GL_FALSE);
+ }
+ ;
+
+optionSequence: optionSequence option
+ |
+ ;
+
+option: OPTION IDENTIFIER ';'
+ {
+ int valid = 0;
+
+ if (state->mode == ARB_vertex) {
+ valid = _mesa_ARBvp_parse_option(state, $2);
+ } else if (state->mode == ARB_fragment) {
+ valid = _mesa_ARBfp_parse_option(state, $2);
+ }
+
+
+ if (!valid) {
+ const char *const err_str = (state->mode == ARB_vertex)
+ ? "invalid ARB vertex program option"
+ : "invalid ARB fragment program option";
+
+ yyerror(& @2, state, err_str);
+ YYERROR;
+ }
+ }
+ ;
+
+statementSequence: statementSequence statement
+ |
+ ;
+
+statement: instruction ';'
+ {
+ if ($1 != NULL) {
+ if (state->inst_tail == NULL) {
+ state->inst_head = $1;
+ } else {
+ state->inst_tail->next = $1;
+ }
+
+ state->inst_tail = $1;
+ $1->next = NULL;
+
+ state->prog->NumInstructions++;
+ }
+ }
+ | namingStatement ';'
+ ;
+
+instruction: ALU_instruction
+ {
+ $$ = $1;
+ state->prog->NumAluInstructions++;
+ }
+ | TexInstruction
+ {
+ $$ = $1;
+ state->prog->NumTexInstructions++;
+ }
+ ;
+
+ALU_instruction: ARL_instruction
+ | VECTORop_instruction
+ | SCALARop_instruction
+ | BINSCop_instruction
+ | BINop_instruction
+ | TRIop_instruction
+ | SWZ_instruction
+ ;
+
+TexInstruction: SAMPLE_instruction
+ | KIL_instruction
+ ;
+
+ARL_instruction: ARL maskedAddrReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor(OPCODE_ARL, & $2, & $4, NULL, NULL);
+ }
+ ;
+
+VECTORop_instruction: VECTOR_OP maskedDstReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+SCALARop_instruction: SCALAR_OP maskedDstReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+BINSCop_instruction: BINSC_OP maskedDstReg ',' scalarSrcReg ',' scalarSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+
+BINop_instruction: BIN_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+TRIop_instruction: TRI_OP maskedDstReg ','
+ swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, & $6, & $8);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+SAMPLE_instruction: SAMPLE_OP maskedDstReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
+ {
+ $$ = asm_instruction_ctor($1.Opcode, & $2, & $4, NULL, NULL);
+ if ($$ != NULL) {
+ const GLbitfield tex_mask = (1U << $6);
+ GLbitfield shadow_tex = 0;
+ GLbitfield target_mask = 0;
+
+
+ $$->Base.SaturateMode = $1.SaturateMode;
+ $$->Base.TexSrcUnit = $6;
+
+ if ($8 < 0) {
+ shadow_tex = tex_mask;
+
+ $$->Base.TexSrcTarget = -$8;
+ $$->Base.TexShadow = 1;
+ } else {
+ $$->Base.TexSrcTarget = $8;
+ }
+
+ target_mask = (1U << $$->Base.TexSrcTarget);
+
+ /* If this texture unit was previously accessed and that access
+ * had a different texture target, generate an error.
+ *
+ * If this texture unit was previously accessed and that access
+ * had a different shadow mode, generate an error.
+ */
+ if ((state->prog->TexturesUsed[$6] != 0)
+ && ((state->prog->TexturesUsed[$6] != target_mask)
+ || ((state->prog->ShadowSamplers & tex_mask)
+ != shadow_tex))) {
+ yyerror(& @8, state,
+ "multiple targets used on one texture image unit");
+ YYERROR;
+ }
+
+
+ state->prog->TexturesUsed[$6] |= target_mask;
+ state->prog->ShadowSamplers |= shadow_tex;
+ }
+ }
+ ;
+
+KIL_instruction: KIL swizzleSrcReg
+ {
+ $$ = asm_instruction_ctor(OPCODE_KIL, NULL, & $2, NULL, NULL);
+ state->fragment.UsesKill = 1;
+ }
+ ;
+
+texImageUnit: TEXTURE_UNIT optTexImageUnitNum
+ {
+ $$ = $2;
+ }
+ ;
+
+texTarget: TEX_1D { $$ = TEXTURE_1D_INDEX; }
+ | TEX_2D { $$ = TEXTURE_2D_INDEX; }
+ | TEX_3D { $$ = TEXTURE_3D_INDEX; }
+ | TEX_CUBE { $$ = TEXTURE_CUBE_INDEX; }
+ | TEX_RECT { $$ = TEXTURE_RECT_INDEX; }
+ | TEX_SHADOW1D { $$ = -TEXTURE_1D_INDEX; }
+ | TEX_SHADOW2D { $$ = -TEXTURE_2D_INDEX; }
+ | TEX_SHADOWRECT { $$ = -TEXTURE_RECT_INDEX; }
+ | TEX_ARRAY1D { $$ = TEXTURE_1D_ARRAY_INDEX; }
+ | TEX_ARRAY2D { $$ = TEXTURE_2D_ARRAY_INDEX; }
+ | TEX_ARRAYSHADOW1D { $$ = -TEXTURE_1D_ARRAY_INDEX; }
+ | TEX_ARRAYSHADOW2D { $$ = -TEXTURE_2D_ARRAY_INDEX; }
+ ;
+
+SWZ_instruction: SWZ maskedDstReg ',' srcReg ',' extendedSwizzle
+ {
+ /* FIXME: Is this correct? Should the extenedSwizzle be applied
+ * FIXME: to the existing swizzle?
+ */
+ $4.Base.Swizzle = $6.swizzle;
+ $4.Base.Negate = $6.mask;
+
+ $$ = asm_instruction_ctor(OPCODE_SWZ, & $2, & $4, NULL, NULL);
+ $$->Base.SaturateMode = $1.SaturateMode;
+ }
+ ;
+
+scalarSrcReg: optionalSign srcReg scalarSuffix
+ {
+ $$ = $2;
+
+ if ($1) {
+ $$.Base.Negate = ~$$.Base.Negate;
+ }
+
+ $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
+ $3.swizzle);
+ }
+ ;
+
+swizzleSrcReg: optionalSign srcReg swizzleSuffix
+ {
+ $$ = $2;
+
+ if ($1) {
+ $$.Base.Negate = ~$$.Base.Negate;
+ }
+
+ $$.Base.Swizzle = _mesa_combine_swizzles($$.Base.Swizzle,
+ $3.swizzle);
+ }
+ ;
+
+maskedDstReg: dstReg optionalMask
+ {
+ $$ = $1;
+ $$.WriteMask = $2.mask;
+
+ if ($$.File == PROGRAM_OUTPUT) {
+ /* Technically speaking, this should check that it is in
+ * vertex program mode. However, PositionInvariant can never be
+ * set in fragment program mode, so it is somewhat irrelevant.
+ */
+ if (state->option.PositionInvariant
+ && ($$.Index == VERT_RESULT_HPOS)) {
+ yyerror(& @1, state, "position-invariant programs cannot "
+ "write position");
+ YYERROR;
+ }
+
+ state->prog->OutputsWritten |= (1U << $$.Index);
+ }
+ }
+ ;
+
+maskedAddrReg: addrReg addrWriteMask
+ {
+ init_dst_reg(& $$);
+ $$.File = PROGRAM_ADDRESS;
+ $$.Index = 0;
+ $$.WriteMask = $2.mask;
+ }
+ ;
+
+extendedSwizzle: extSwizComp ',' extSwizComp ',' extSwizComp ',' extSwizComp
+ {
+ const unsigned xyzw_valid =
+ ($1.xyzw_valid << 0)
+ | ($3.xyzw_valid << 1)
+ | ($5.xyzw_valid << 2)
+ | ($7.xyzw_valid << 3);
+ const unsigned rgba_valid =
+ ($1.rgba_valid << 0)
+ | ($3.rgba_valid << 1)
+ | ($5.rgba_valid << 2)
+ | ($7.rgba_valid << 3);
+
+ /* All of the swizzle components have to be valid in either RGBA
+ * or XYZW. Note that 0 and 1 are valid in both, so both masks
+ * can have some bits set.
+ *
+ * We somewhat deviate from the spec here. It would be really hard
+ * to figure out which component is the error, and there probably
+ * isn't a lot of benefit.
+ */
+ if ((rgba_valid != 0x0f) && (xyzw_valid != 0x0f)) {
+ yyerror(& @1, state, "cannot combine RGBA and XYZW swizzle "
+ "components");
+ YYERROR;
+ }
+
+ $$.swizzle = MAKE_SWIZZLE4($1.swz, $3.swz, $5.swz, $7.swz);
+ $$.mask = ($1.negate) | ($3.negate << 1) | ($5.negate << 2)
+ | ($7.negate << 3);
+ }
+ ;
+
+extSwizComp: optionalSign extSwizSel
+ {
+ $$ = $2;
+ $$.negate = ($1) ? 1 : 0;
+ }
+ ;
+
+extSwizSel: INTEGER
+ {
+ if (($1 != 0) && ($1 != 1)) {
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ $$.swz = ($1 == 0) ? SWIZZLE_ZERO : SWIZZLE_ONE;
+
+ /* 0 and 1 are valid for both RGBA swizzle names and XYZW
+ * swizzle names.
+ */
+ $$.xyzw_valid = 1;
+ $$.rgba_valid = 1;
+ }
+ | IDENTIFIER
+ {
+ if (strlen($1) > 1) {
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ }
+
+ switch ($1[0]) {
+ case 'x':
+ $$.swz = SWIZZLE_X;
+ $$.xyzw_valid = 1;
+ break;
+ case 'y':
+ $$.swz = SWIZZLE_Y;
+ $$.xyzw_valid = 1;
+ break;
+ case 'z':
+ $$.swz = SWIZZLE_Z;
+ $$.xyzw_valid = 1;
+ break;
+ case 'w':
+ $$.swz = SWIZZLE_W;
+ $$.xyzw_valid = 1;
+ break;
+
+ case 'r':
+ $$.swz = SWIZZLE_X;
+ $$.rgba_valid = 1;
+ break;
+ case 'g':
+ $$.swz = SWIZZLE_Y;
+ $$.rgba_valid = 1;
+ break;
+ case 'b':
+ $$.swz = SWIZZLE_Z;
+ $$.rgba_valid = 1;
+ break;
+ case 'a':
+ $$.swz = SWIZZLE_W;
+ $$.rgba_valid = 1;
+ break;
+
+ default:
+ yyerror(& @1, state, "invalid extended swizzle selector");
+ YYERROR;
+ break;
+ }
+ }
+ ;
+
+srcReg: IDENTIFIER /* temporaryReg | progParamSingle */
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) && (s->type != at_temp)
+ && (s->type != at_attrib)) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type == at_param) && s->param_is_array) {
+ yyerror(& @1, state, "non-array access to array PARAM");
+ YYERROR;
+ }
+
+ init_src_reg(& $$);
+ switch (s->type) {
+ case at_temp:
+ $$.Base.File = PROGRAM_TEMPORARY;
+ $$.Base.Index = s->temp_binding;
+ break;
+ case at_param:
+ $$.Base.File = s->param_binding_type;
+ $$.Base.Index = s->param_binding_begin;
+ break;
+ case at_attrib:
+ $$.Base.File = PROGRAM_INPUT;
+ $$.Base.Index = s->attrib_binding;
+ state->prog->InputsRead |= (1U << $$.Base.Index);
+
+ if (!validate_inputs(& @1, state)) {
+ YYERROR;
+ }
+ break;
+
+ default:
+ YYERROR;
+ break;
+ }
+ }
+ | attribBinding
+ {
+ init_src_reg(& $$);
+ $$.Base.File = PROGRAM_INPUT;
+ $$.Base.Index = $1;
+ state->prog->InputsRead |= (1U << $$.Base.Index);
+
+ if (!validate_inputs(& @1, state)) {
+ YYERROR;
+ }
+ }
+ | progParamArray '[' progParamArrayMem ']'
+ {
+ if (! $3.Base.RelAddr
+ && ((unsigned) $3.Base.Index >= $1->param_binding_length)) {
+ yyerror(& @3, state, "out of bounds array access");
+ YYERROR;
+ }
+
+ init_src_reg(& $$);
+ $$.Base.File = $1->param_binding_type;
+
+ if ($3.Base.RelAddr) {
+ $1->param_accessed_indirectly = 1;
+
+ $$.Base.RelAddr = 1;
+ $$.Base.Index = $3.Base.Index;
+ $$.Symbol = $1;
+ } else {
+ $$.Base.Index = $1->param_binding_begin + $3.Base.Index;
+ }
+ }
+ | paramSingleItemUse
+ {
+ init_src_reg(& $$);
+ $$.Base.File = ($1.name != NULL)
+ ? $1.param_binding_type
+ : PROGRAM_CONSTANT;
+ $$.Base.Index = $1.param_binding_begin;
+ }
+ ;
+
+dstReg: resultBinding
+ {
+ init_dst_reg(& $$);
+ $$.File = PROGRAM_OUTPUT;
+ $$.Index = $1;
+ }
+ | IDENTIFIER /* temporaryReg | vertexResultReg */
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_output) && (s->type != at_temp)) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ }
+
+ init_dst_reg(& $$);
+ switch (s->type) {
+ case at_temp:
+ $$.File = PROGRAM_TEMPORARY;
+ $$.Index = s->temp_binding;
+ break;
+ case at_output:
+ $$.File = PROGRAM_OUTPUT;
+ $$.Index = s->output_binding;
+ break;
+ default:
+ $$.File = s->param_binding_type;
+ $$.Index = s->param_binding_begin;
+ break;
+ }
+ }
+ ;
+
+progParamArray: IDENTIFIER
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid operand variable");
+ YYERROR;
+ } else if ((s->type != at_param) || !s->param_is_array) {
+ yyerror(& @1, state, "array access to non-PARAM variable");
+ YYERROR;
+ } else {
+ $$ = s;
+ }
+ }
+ ;
+
+progParamArrayMem: progParamArrayAbs | progParamArrayRel;
+
+progParamArrayAbs: INTEGER
+ {
+ init_src_reg(& $$);
+ $$.Base.Index = $1;
+ }
+ ;
+
+progParamArrayRel: addrReg addrComponent addrRegRelOffset
+ {
+ /* FINISHME: Add support for multiple address registers.
+ */
+ /* FINISHME: Add support for 4-component address registers.
+ */
+ init_src_reg(& $$);
+ $$.Base.RelAddr = 1;
+ $$.Base.Index = $3;
+ }
+ ;
+
+addrRegRelOffset: { $$ = 0; }
+ | '+' addrRegPosOffset { $$ = $2; }
+ | '-' addrRegNegOffset { $$ = -$2; }
+ ;
+
+addrRegPosOffset: INTEGER
+ {
+ if (($1 < 0) || ($1 > 63)) {
+ yyerror(& @1, state,
+ "relative address offset too large (positive)");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrRegNegOffset: INTEGER
+ {
+ if (($1 < 0) || ($1 > 64)) {
+ yyerror(& @1, state,
+ "relative address offset too large (negative)");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrReg: IDENTIFIER
+ {
+ struct asm_symbol *const s = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $1);
+
+ if (s == NULL) {
+ yyerror(& @1, state, "invalid array member");
+ YYERROR;
+ } else if (s->type != at_address) {
+ yyerror(& @1, state,
+ "invalid variable for indexed array access");
+ YYERROR;
+ } else {
+ $$ = s;
+ }
+ }
+ ;
+
+addrComponent: MASK1
+ {
+ if ($1.mask != WRITEMASK_X) {
+ yyerror(& @1, state, "invalid address component selector");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+addrWriteMask: MASK1
+ {
+ if ($1.mask != WRITEMASK_X) {
+ yyerror(& @1, state,
+ "address register write mask must be \".x\"");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+scalarSuffix: MASK1;
+
+swizzleSuffix: MASK1
+ | MASK4
+ | SWIZZLE
+ | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
+ ;
+
+optionalMask: MASK4 | MASK3 | MASK2 | MASK1
+ | { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
+ ;
+
+namingStatement: ATTRIB_statement
+ | PARAM_statement
+ | TEMP_statement
+ | ADDRESS_statement
+ | OUTPUT_statement
+ | ALIAS_statement
+ ;
+
+ATTRIB_statement: ATTRIB IDENTIFIER '=' attribBinding
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_attrib, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->attrib_binding = $4;
+ state->InputsBound |= (1U << s->attrib_binding);
+
+ if (!validate_inputs(& @4, state)) {
+ YYERROR;
+ }
+ }
+ }
+ ;
+
+attribBinding: VERTEX vtxAttribItem
+ {
+ $$ = $2;
+ }
+ | FRAGMENT fragAttribItem
+ {
+ $$ = $2;
+ }
+ ;
+
+vtxAttribItem: POSITION
+ {
+ $$ = VERT_ATTRIB_POS;
+ }
+ | WEIGHT vtxOptWeightNum
+ {
+ $$ = VERT_ATTRIB_WEIGHT;
+ }
+ | NORMAL
+ {
+ $$ = VERT_ATTRIB_NORMAL;
+ }
+ | COLOR optColorType
+ {
+ if (!state->ctx->Extensions.EXT_secondary_color) {
+ yyerror(& @2, state, "GL_EXT_secondary_color not supported");
+ YYERROR;
+ }
+
+ $$ = VERT_ATTRIB_COLOR0 + $2;
+ }
+ | FOGCOORD
+ {
+ if (!state->ctx->Extensions.EXT_fog_coord) {
+ yyerror(& @1, state, "GL_EXT_fog_coord not supported");
+ YYERROR;
+ }
+
+ $$ = VERT_ATTRIB_FOG;
+ }
+ | TEXCOORD optTexCoordUnitNum
+ {
+ $$ = VERT_ATTRIB_TEX0 + $2;
+ }
+ | MATRIXINDEX '[' vtxWeightNum ']'
+ {
+ yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ }
+ | VTXATTRIB '[' vtxAttribNum ']'
+ {
+ $$ = VERT_ATTRIB_GENERIC0 + $3;
+ }
+ ;
+
+vtxAttribNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxAttribs) {
+ yyerror(& @1, state, "invalid vertex attribute reference");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+vtxOptWeightNum: | '[' vtxWeightNum ']';
+vtxWeightNum: INTEGER;
+
+fragAttribItem: POSITION
+ {
+ $$ = FRAG_ATTRIB_WPOS;
+ }
+ | COLOR optColorType
+ {
+ $$ = FRAG_ATTRIB_COL0 + $2;
+ }
+ | FOGCOORD
+ {
+ $$ = FRAG_ATTRIB_FOGC;
+ }
+ | TEXCOORD optTexCoordUnitNum
+ {
+ $$ = FRAG_ATTRIB_TEX0 + $2;
+ }
+ ;
+
+PARAM_statement: PARAM_singleStmt | PARAM_multipleStmt;
+
+PARAM_singleStmt: PARAM IDENTIFIER paramSingleInit
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_param, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = $3.param_binding_type;
+ s->param_binding_begin = $3.param_binding_begin;
+ s->param_binding_length = $3.param_binding_length;
+ s->param_is_array = 0;
+ }
+ }
+ ;
+
+PARAM_multipleStmt: PARAM IDENTIFIER '[' optArraySize ']' paramMultipleInit
+ {
+ if (($4 != 0) && ((unsigned) $4 != $6.param_binding_length)) {
+ yyerror(& @4, state,
+ "parameter array size and number of bindings must match");
+ YYERROR;
+ } else {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, $6.type, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->param_binding_type = $6.param_binding_type;
+ s->param_binding_begin = $6.param_binding_begin;
+ s->param_binding_length = $6.param_binding_length;
+ s->param_is_array = 1;
+ }
+ }
+ }
+ ;
+
+optArraySize:
+ {
+ $$ = 0;
+ }
+ | INTEGER
+ {
+ if (($1 < 1) || ((unsigned) $1 >= state->limits->MaxParameters)) {
+ yyerror(& @1, state, "invalid parameter array size");
+ YYERROR;
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+paramSingleInit: '=' paramSingleItemDecl
+ {
+ $$ = $2;
+ }
+ ;
+
+paramMultipleInit: '=' '{' paramMultInitList '}'
+ {
+ $$ = $3;
+ }
+ ;
+
+paramMultInitList: paramMultipleItem
+ | paramMultInitList ',' paramMultipleItem
+ {
+ $1.param_binding_length += $3.param_binding_length;
+ $$ = $1;
+ }
+ ;
+
+paramSingleItemDecl: stateSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstDecl
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+paramSingleItemUse: stateSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programSingleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstUse
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+paramMultipleItem: stateMultipleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_state(state->prog, & $$, $1);
+ }
+ | programMultipleItem
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_param(state->prog, & $$, $1);
+ }
+ | paramConstDecl
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.param_binding_begin = ~0;
+ initialize_symbol_from_const(state->prog, & $$, & $1);
+ }
+ ;
+
+stateMultipleItem: stateSingleItem { memcpy($$, $1, sizeof($$)); }
+ | STATE stateMatrixRows { memcpy($$, $2, sizeof($$)); }
+ ;
+
+stateSingleItem: STATE stateMaterialItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightModelItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateLightProdItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateTexGenItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateTexEnvItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateFogItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateClipPlaneItem { memcpy($$, $2, sizeof($$)); }
+ | STATE statePointItem { memcpy($$, $2, sizeof($$)); }
+ | STATE stateMatrixRow { memcpy($$, $2, sizeof($$)); }
+ | STATE stateDepthItem { memcpy($$, $2, sizeof($$)); }
+ ;
+
+stateMaterialItem: MATERIAL optFaceType stateMatProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_MATERIAL;
+ $$[1] = $2;
+ $$[2] = $3;
+ }
+ ;
+
+stateMatProperty: ambDiffSpecProperty
+ {
+ $$ = $1;
+ }
+ | EMISSION
+ {
+ $$ = STATE_EMISSION;
+ }
+ | SHININESS
+ {
+ $$ = STATE_SHININESS;
+ }
+ ;
+
+stateLightItem: LIGHT '[' stateLightNumber ']' stateLightProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHT;
+ $$[1] = $3;
+ $$[2] = $5;
+ }
+ ;
+
+stateLightProperty: ambDiffSpecProperty
+ {
+ $$ = $1;
+ }
+ | POSITION
+ {
+ $$ = STATE_POSITION;
+ }
+ | ATTENUATION
+ {
+ if (!state->ctx->Extensions.EXT_point_parameters) {
+ yyerror(& @1, state, "GL_ARB_point_parameters not supported");
+ YYERROR;
+ }
+
+ $$ = STATE_ATTENUATION;
+ }
+ | SPOT stateSpotProperty
+ {
+ $$ = $2;
+ }
+ | HALF
+ {
+ $$ = STATE_HALF_VECTOR;
+ }
+ ;
+
+stateSpotProperty: DIRECTION
+ {
+ $$ = STATE_SPOT_DIRECTION;
+ }
+ ;
+
+stateLightModelItem: LIGHTMODEL stateLModProperty
+ {
+ $$[0] = $2[0];
+ $$[1] = $2[1];
+ }
+ ;
+
+stateLModProperty: AMBIENT
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTMODEL_AMBIENT;
+ }
+ | optFaceType SCENECOLOR
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ $$[1] = $1;
+ }
+ ;
+
+stateLightProdItem: LIGHTPROD '[' stateLightNumber ']' optFaceType stateLProdProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_LIGHTPROD;
+ $$[1] = $3;
+ $$[2] = $5;
+ $$[3] = $6;
+ }
+ ;
+
+stateLProdProperty: ambDiffSpecProperty;
+
+stateTexEnvItem: TEXENV optLegacyTexUnitNum stateTexEnvProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $3;
+ $$[1] = $2;
+ }
+ ;
+
+stateTexEnvProperty: COLOR
+ {
+ $$ = STATE_TEXENV_COLOR;
+ }
+ ;
+
+ambDiffSpecProperty: AMBIENT
+ {
+ $$ = STATE_AMBIENT;
+ }
+ | DIFFUSE
+ {
+ $$ = STATE_DIFFUSE;
+ }
+ | SPECULAR
+ {
+ $$ = STATE_SPECULAR;
+ }
+ ;
+
+stateLightNumber: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxLights) {
+ yyerror(& @1, state, "invalid light selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateTexGenItem: TEXGEN optTexCoordUnitNum stateTexGenType stateTexGenCoord
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_TEXGEN;
+ $$[1] = $2;
+ $$[2] = $3 + $4;
+ }
+ ;
+
+stateTexGenType: EYE
+ {
+ $$ = STATE_TEXGEN_EYE_S;
+ }
+ | OBJECT
+ {
+ $$ = STATE_TEXGEN_OBJECT_S;
+ }
+ ;
+stateTexGenCoord: TEXGEN_S
+ {
+ $$ = STATE_TEXGEN_EYE_S - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_T
+ {
+ $$ = STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_R
+ {
+ $$ = STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S;
+ }
+ | TEXGEN_Q
+ {
+ $$ = STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S;
+ }
+ ;
+
+stateFogItem: FOG stateFogProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $2;
+ }
+ ;
+
+stateFogProperty: COLOR
+ {
+ $$ = STATE_FOG_COLOR;
+ }
+ | PARAMS
+ {
+ $$ = STATE_FOG_PARAMS;
+ }
+ ;
+
+stateClipPlaneItem: CLIP '[' stateClipPlaneNum ']' PLANE
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_CLIPPLANE;
+ $$[1] = $3;
+ }
+ ;
+
+stateClipPlaneNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxClipPlanes) {
+ yyerror(& @1, state, "invalid clip plane selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+statePointItem: POINT_TOK statePointProperty
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = $2;
+ }
+ ;
+
+statePointProperty: SIZE_TOK
+ {
+ $$ = STATE_POINT_SIZE;
+ }
+ | ATTENUATION
+ {
+ $$ = STATE_POINT_ATTENUATION;
+ }
+ ;
+
+stateMatrixRow: stateMatrixItem ROW '[' stateMatrixRowNum ']'
+ {
+ $$[0] = $1[0];
+ $$[1] = $1[1];
+ $$[2] = $4;
+ $$[3] = $4;
+ $$[4] = $1[2];
+ }
+ ;
+
+stateMatrixRows: stateMatrixItem optMatrixRows
+ {
+ $$[0] = $1[0];
+ $$[1] = $1[1];
+ $$[2] = $2[2];
+ $$[3] = $2[3];
+ $$[4] = $1[2];
+ }
+ ;
+
+optMatrixRows:
+ {
+ $$[2] = 0;
+ $$[3] = 3;
+ }
+ | ROW '[' stateMatrixRowNum DOT_DOT stateMatrixRowNum ']'
+ {
+ /* It seems logical that the matrix row range specifier would have
+ * to specify a range or more than one row (i.e., $5 > $3).
+ * However, the ARB_vertex_program spec says "a program will fail
+ * to load if <a> is greater than <b>." This means that $3 == $5
+ * is valid.
+ */
+ if ($3 > $5) {
+ yyerror(& @3, state, "invalid matrix row range");
+ YYERROR;
+ }
+
+ $$[2] = $3;
+ $$[3] = $5;
+ }
+ ;
+
+stateMatrixItem: MATRIX stateMatrixName stateOptMatModifier
+ {
+ $$[0] = $2[0];
+ $$[1] = $2[1];
+ $$[2] = $3;
+ }
+ ;
+
+stateOptMatModifier:
+ {
+ $$ = 0;
+ }
+ | stateMatModifier
+ {
+ $$ = $1;
+ }
+ ;
+
+stateMatModifier: INVERSE
+ {
+ $$ = STATE_MATRIX_INVERSE;
+ }
+ | TRANSPOSE
+ {
+ $$ = STATE_MATRIX_TRANSPOSE;
+ }
+ | INVTRANS
+ {
+ $$ = STATE_MATRIX_INVTRANS;
+ }
+ ;
+
+stateMatrixRowNum: INTEGER
+ {
+ if ($1 > 3) {
+ yyerror(& @1, state, "invalid matrix row reference");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateMatrixName: MODELVIEW stateOptModMatNum
+ {
+ $$[0] = STATE_MODELVIEW_MATRIX;
+ $$[1] = $2;
+ }
+ | PROJECTION
+ {
+ $$[0] = STATE_PROJECTION_MATRIX;
+ $$[1] = 0;
+ }
+ | MVP
+ {
+ $$[0] = STATE_MVP_MATRIX;
+ $$[1] = 0;
+ }
+ | TEXTURE optTexCoordUnitNum
+ {
+ $$[0] = STATE_TEXTURE_MATRIX;
+ $$[1] = $2;
+ }
+ | PALETTE '[' statePaletteMatNum ']'
+ {
+ yyerror(& @1, state, "GL_ARB_matrix_palette not supported");
+ YYERROR;
+ }
+ | MAT_PROGRAM '[' stateProgramMatNum ']'
+ {
+ $$[0] = STATE_PROGRAM_MATRIX;
+ $$[1] = $3;
+ }
+ ;
+
+stateOptModMatNum:
+ {
+ $$ = 0;
+ }
+ | '[' stateModMatNum ']'
+ {
+ $$ = $2;
+ }
+ ;
+stateModMatNum: INTEGER
+ {
+ /* Since GL_ARB_vertex_blend isn't supported, only modelview matrix
+ * zero is valid.
+ */
+ if ($1 != 0) {
+ yyerror(& @1, state, "invalid modelview matrix index");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+statePaletteMatNum: INTEGER
+ {
+ /* Since GL_ARB_matrix_palette isn't supported, just let any value
+ * through here. The error will be generated later.
+ */
+ $$ = $1;
+ }
+ ;
+stateProgramMatNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxProgramMatrices) {
+ yyerror(& @1, state, "invalid program matrix selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+stateDepthItem: DEPTH RANGE
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = STATE_DEPTH_RANGE;
+ }
+ ;
+
+
+programSingleItem: progEnvParam | progLocalParam;
+
+programMultipleItem: progEnvParams | progLocalParams;
+
+progEnvParams: PROGRAM ENV '[' progEnvParamNums ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_ENV;
+ $$[2] = $4[0];
+ $$[3] = $4[1];
+ }
+ ;
+
+progEnvParamNums: progEnvParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $1;
+ }
+ | progEnvParamNum DOT_DOT progEnvParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $3;
+ }
+ ;
+
+progEnvParam: PROGRAM ENV '[' progEnvParamNum ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_ENV;
+ $$[2] = $4;
+ $$[3] = $4;
+ }
+ ;
+
+progLocalParams: PROGRAM LOCAL '[' progLocalParamNums ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_LOCAL;
+ $$[2] = $4[0];
+ $$[3] = $4[1];
+ }
+
+progLocalParamNums: progLocalParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $1;
+ }
+ | progLocalParamNum DOT_DOT progLocalParamNum
+ {
+ $$[0] = $1;
+ $$[1] = $3;
+ }
+ ;
+
+progLocalParam: PROGRAM LOCAL '[' progLocalParamNum ']'
+ {
+ memset($$, 0, sizeof($$));
+ $$[0] = state->state_param_enum;
+ $$[1] = STATE_LOCAL;
+ $$[2] = $4;
+ $$[3] = $4;
+ }
+ ;
+
+progEnvParamNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxEnvParams) {
+ yyerror(& @1, state, "invalid environment parameter reference");
+ YYERROR;
+ }
+ $$ = $1;
+ }
+ ;
+
+progLocalParamNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->limits->MaxLocalParams) {
+ yyerror(& @1, state, "invalid local parameter reference");
+ YYERROR;
+ }
+ $$ = $1;
+ }
+ ;
+
+
+
+paramConstDecl: paramConstScalarDecl | paramConstVector;
+paramConstUse: paramConstScalarUse | paramConstVector;
+
+paramConstScalarDecl: signedFloatConstant
+ {
+ $$.count = 4;
+ $$.data[0] = $1;
+ $$.data[1] = $1;
+ $$.data[2] = $1;
+ $$.data[3] = $1;
+ }
+ ;
+
+paramConstScalarUse: REAL
+ {
+ $$.count = 1;
+ $$.data[0] = $1;
+ $$.data[1] = $1;
+ $$.data[2] = $1;
+ $$.data[3] = $1;
+ }
+ | INTEGER
+ {
+ $$.count = 1;
+ $$.data[0] = (float) $1;
+ $$.data[1] = (float) $1;
+ $$.data[2] = (float) $1;
+ $$.data[3] = (float) $1;
+ }
+ ;
+
+paramConstVector: '{' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = 0.0f;
+ $$.data[2] = 0.0f;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = 0.0f;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant ','
+ signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = $6;
+ $$.data[3] = 1.0f;
+ }
+ | '{' signedFloatConstant ',' signedFloatConstant ','
+ signedFloatConstant ',' signedFloatConstant '}'
+ {
+ $$.count = 4;
+ $$.data[0] = $2;
+ $$.data[1] = $4;
+ $$.data[2] = $6;
+ $$.data[3] = $8;
+ }
+ ;
+
+signedFloatConstant: optionalSign REAL
+ {
+ $$ = ($1) ? -$2 : $2;
+ }
+ | optionalSign INTEGER
+ {
+ $$ = (float)(($1) ? -$2 : $2);
+ }
+ ;
+
+optionalSign: '+' { $$ = FALSE; }
+ | '-' { $$ = TRUE; }
+ | { $$ = FALSE; }
+ ;
+
+TEMP_statement: TEMP { $<integer>$ = $1; } varNameList
+ ;
+
+ADDRESS_statement: ADDRESS { $<integer>$ = $1; } varNameList
+ ;
+
+varNameList: varNameList ',' IDENTIFIER
+ {
+ if (!declare_variable(state, $3, $<integer>0, & @3)) {
+ YYERROR;
+ }
+ }
+ | IDENTIFIER
+ {
+ if (!declare_variable(state, $1, $<integer>0, & @1)) {
+ YYERROR;
+ }
+ }
+ ;
+
+OUTPUT_statement: OUTPUT IDENTIFIER '=' resultBinding
+ {
+ struct asm_symbol *const s =
+ declare_variable(state, $2, at_output, & @2);
+
+ if (s == NULL) {
+ YYERROR;
+ } else {
+ s->output_binding = $4;
+ }
+ }
+ ;
+
+resultBinding: RESULT POSITION
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_HPOS;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT FOGCOORD
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_FOGC;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT resultColBinding
+ {
+ $$ = $2;
+ }
+ | RESULT POINTSIZE
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_PSIZ;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT TEXCOORD optTexCoordUnitNum
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_TEX0 + $3;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | RESULT DEPTH
+ {
+ if (state->mode == ARB_fragment) {
+ $$ = FRAG_RESULT_DEPTH;
+ } else {
+ yyerror(& @2, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+resultColBinding: COLOR optResultFaceType optResultColorType
+ {
+ $$ = $2 + $3;
+ }
+ ;
+
+optResultFaceType:
+ {
+ $$ = (state->mode == ARB_vertex)
+ ? VERT_RESULT_COL0
+ : FRAG_RESULT_COLOR;
+ }
+ | FRONT
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_COL0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | BACK
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = VERT_RESULT_BFC0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+optResultColorType:
+ {
+ $$ = 0;
+ }
+ | PRIMARY
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = 0;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ | SECONDARY
+ {
+ if (state->mode == ARB_vertex) {
+ $$ = 1;
+ } else {
+ yyerror(& @1, state, "invalid program result name");
+ YYERROR;
+ }
+ }
+ ;
+
+optFaceType: { $$ = 0; }
+ | FRONT { $$ = 0; }
+ | BACK { $$ = 1; }
+ ;
+
+optColorType: { $$ = 0; }
+ | PRIMARY { $$ = 0; }
+ | SECONDARY { $$ = 1; }
+ ;
+
+optTexCoordUnitNum: { $$ = 0; }
+ | '[' texCoordUnitNum ']' { $$ = $2; }
+ ;
+
+optTexImageUnitNum: { $$ = 0; }
+ | '[' texImageUnitNum ']' { $$ = $2; }
+ ;
+
+optLegacyTexUnitNum: { $$ = 0; }
+ | '[' legacyTexUnitNum ']' { $$ = $2; }
+ ;
+
+texCoordUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureCoordUnits) {
+ yyerror(& @1, state, "invalid texture coordinate unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+texImageUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureImageUnits) {
+ yyerror(& @1, state, "invalid texture image unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+legacyTexUnitNum: INTEGER
+ {
+ if ((unsigned) $1 >= state->MaxTextureUnits) {
+ yyerror(& @1, state, "invalid texture unit selector");
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+ALIAS_statement: ALIAS IDENTIFIER '=' IDENTIFIER
+ {
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $2);
+ struct asm_symbol *target = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, $4);
+
+
+ if (exist != NULL) {
+ yyerror(& @2, state, "redeclared identifier");
+ YYERROR;
+ } else if (target == NULL) {
+ yyerror(& @4, state,
+ "undefined variable binding in ALIAS statement");
+ YYERROR;
+ } else {
+ _mesa_symbol_table_add_symbol(state->st, 0, $2, target);
+ }
+ }
+ ;
+
+%%
+
+struct asm_instruction *
+asm_instruction_ctor(gl_inst_opcode op,
+ const struct prog_dst_register *dst,
+ const struct asm_src_register *src0,
+ const struct asm_src_register *src1,
+ const struct asm_src_register *src2)
+{
+ struct asm_instruction *inst = calloc(1, sizeof(struct asm_instruction));
+
+ if (inst) {
+ _mesa_init_instructions(& inst->Base, 1);
+ inst->Base.Opcode = op;
+
+ /* In the core ARB extensions only the KIL instruction doesn't have a
+ * destination register.
+ */
+ if (dst == NULL) {
+ init_dst_reg(& inst->Base.DstReg);
+ } else {
+ inst->Base.DstReg = *dst;
+ }
+
+ inst->Base.SrcReg[0] = src0->Base;
+ inst->SrcReg[0] = *src0;
+
+ if (src1 != NULL) {
+ inst->Base.SrcReg[1] = src1->Base;
+ inst->SrcReg[1] = *src1;
+ } else {
+ init_src_reg(& inst->SrcReg[1]);
+ }
+
+ if (src2 != NULL) {
+ inst->Base.SrcReg[2] = src2->Base;
+ inst->SrcReg[2] = *src2;
+ } else {
+ init_src_reg(& inst->SrcReg[2]);
+ }
+ }
+
+ return inst;
+}
+
+
+void
+init_dst_reg(struct prog_dst_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->File = PROGRAM_UNDEFINED;
+ r->WriteMask = WRITEMASK_XYZW;
+ r->CondMask = COND_TR;
+ r->CondSwizzle = SWIZZLE_NOOP;
+}
+
+
+void
+init_src_reg(struct asm_src_register *r)
+{
+ memset(r, 0, sizeof(*r));
+ r->Base.File = PROGRAM_UNDEFINED;
+ r->Base.Swizzle = SWIZZLE_NOOP;
+ r->Symbol = NULL;
+}
+
+
+/**
+ * Validate the set of inputs used by a program
+ *
+ * Validates that legal sets of inputs are used by the program. In this case
+ * "used" included both reading the input or binding the input to a name using
+ * the \c ATTRIB command.
+ *
+ * \return
+ * \c TRUE if the combination of inputs used is valid, \c FALSE otherwise.
+ */
+int
+validate_inputs(struct YYLTYPE *locp, struct asm_parser_state *state)
+{
+ const int inputs = state->prog->InputsRead | state->InputsBound;
+
+ if (((inputs & 0x0ffff) & (inputs >> 16)) != 0) {
+ yyerror(locp, state, "illegal use of generic attribute and name attribute");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+struct asm_symbol *
+declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
+ struct YYLTYPE *locp)
+{
+ struct asm_symbol *s = NULL;
+ struct asm_symbol *exist = (struct asm_symbol *)
+ _mesa_symbol_table_find_symbol(state->st, 0, name);
+
+
+ if (exist != NULL) {
+ yyerror(locp, state, "redeclared identifier");
+ } else {
+ s = calloc(1, sizeof(struct asm_symbol));
+ s->name = name;
+ s->type = t;
+
+ switch (t) {
+ case at_temp:
+ if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
+ yyerror(locp, state, "too many temporaries declared");
+ free(s);
+ return NULL;
+ }
+
+ s->temp_binding = state->prog->NumTemporaries;
+ state->prog->NumTemporaries++;
+ break;
+
+ case at_address:
+ if (state->prog->NumAddressRegs >= state->limits->MaxAddressRegs) {
+ yyerror(locp, state, "too many address registers declared");
+ free(s);
+ return NULL;
+ }
+
+ /* FINISHME: Add support for multiple address registers.
+ */
+ state->prog->NumAddressRegs++;
+ break;
+
+ default:
+ break;
+ }
+
+ _mesa_symbol_table_add_symbol(state->st, 0, s->name, s);
+ s->next = state->sym;
+ state->sym = s;
+ }
+
+ return s;
+}
+
+
+int add_state_reference(struct gl_program_parameter_list *param_list,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ const GLuint size = 4; /* XXX fix */
+ char *name;
+ GLint index;
+
+ name = _mesa_program_state_string(tokens);
+ index = _mesa_add_parameter(param_list, PROGRAM_STATE_VAR, name,
+ size, GL_NONE, NULL, tokens, 0x0);
+ param_list->StateFlags |= _mesa_program_state_flags(tokens);
+
+ /* free name string here since we duplicated it in add_parameter() */
+ _mesa_free(name);
+
+ return index;
+}
+
+
+int
+initialize_symbol_from_state(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_STATE_VAR;
+
+ /* If we are adding a STATE_MATRIX that has multiple rows, we need to
+ * unroll it and call add_state_reference() for each row
+ */
+ if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
+ state_tokens[0] == STATE_PROJECTION_MATRIX ||
+ state_tokens[0] == STATE_MVP_MATRIX ||
+ state_tokens[0] == STATE_TEXTURE_MATRIX ||
+ state_tokens[0] == STATE_PROGRAM_MATRIX)
+ && (state_tokens[2] != state_tokens[3])) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_param(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const gl_state_index tokens[STATE_LENGTH])
+{
+ int idx = -1;
+ gl_state_index state_tokens[STATE_LENGTH];
+
+
+ memcpy(state_tokens, tokens, sizeof(state_tokens));
+
+ assert((state_tokens[0] == STATE_VERTEX_PROGRAM)
+ || (state_tokens[0] == STATE_FRAGMENT_PROGRAM));
+ assert((state_tokens[1] == STATE_ENV)
+ || (state_tokens[1] == STATE_LOCAL));
+
+ param_var->type = at_param;
+ param_var->param_binding_type = (state_tokens[1] == STATE_ENV)
+ ? PROGRAM_ENV_PARAM : PROGRAM_LOCAL_PARAM;
+
+ /* If we are adding a STATE_ENV or STATE_LOCAL that has multiple elements,
+ * we need to unroll it and call add_state_reference() for each row
+ */
+ if (state_tokens[2] != state_tokens[3]) {
+ int row;
+ const int first_row = state_tokens[2];
+ const int last_row = state_tokens[3];
+
+ for (row = first_row; row <= last_row; row++) {
+ state_tokens[2] = state_tokens[3] = row;
+
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+ }
+ else {
+ idx = add_state_reference(prog->Parameters, state_tokens);
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+ }
+
+ return idx;
+}
+
+
+int
+initialize_symbol_from_const(struct gl_program *prog,
+ struct asm_symbol *param_var,
+ const struct asm_vector *vec)
+{
+ const int idx = _mesa_add_parameter(prog->Parameters, PROGRAM_CONSTANT,
+ NULL, vec->count, GL_NONE, vec->data,
+ NULL, 0x0);
+
+ param_var->type = at_param;
+ param_var->param_binding_type = PROGRAM_CONSTANT;
+
+ if (param_var->param_binding_begin == ~0U)
+ param_var->param_binding_begin = idx;
+ param_var->param_binding_length++;
+
+ return idx;
+}
+
+
+char *
+make_error_string(const char *fmt, ...)
+{
+ int length;
+ char *str;
+ va_list args;
+
+ va_start(args, fmt);
+
+ /* Call vsnprintf once to determine how large the final string is. Call it
+ * again to do the actual formatting. from the vsnprintf manual page:
+ *
+ * Upon successful return, these functions return the number of
+ * characters printed (not including the trailing '\0' used to end
+ * output to strings).
+ */
+ length = 1 + vsnprintf(NULL, 0, fmt, args);
+
+ str = _mesa_malloc(length);
+ if (str) {
+ vsnprintf(str, length, fmt, args);
+ }
+
+ va_end(args);
+
+ return str;
+}
+
+
+void
+yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
+{
+ char *err_str;
+
+
+ err_str = make_error_string("glProgramStringARB(%s)\n", s);
+ if (err_str) {
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_free(err_str);
+ }
+
+ err_str = make_error_string("line %u, char %u: error: %s\n",
+ locp->first_line, locp->first_column, s);
+ _mesa_set_program_error(state->ctx, locp->position, err_str);
+
+ if (err_str) {
+ _mesa_free(err_str);
+ }
+}
+
+
+GLboolean
+_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
+ GLsizei len, struct asm_parser_state *state)
+{
+ struct asm_instruction *inst;
+ unsigned i;
+ GLubyte *strz;
+ GLboolean result = GL_FALSE;
+ void *temp;
+ struct asm_symbol *sym;
+
+ state->ctx = ctx;
+ state->prog->Target = target;
+ state->prog->Parameters = _mesa_new_parameter_list();
+
+ /* Make a copy of the program string and force it to be NUL-terminated.
+ */
+ strz = (GLubyte *) _mesa_malloc(len + 1);
+ if (strz == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ return GL_FALSE;
+ }
+ _mesa_memcpy (strz, str, len);
+ strz[len] = '\0';
+
+ state->prog->String = strz;
+
+ state->st = _mesa_symbol_table_ctor();
+
+ state->limits = (target == GL_VERTEX_PROGRAM_ARB)
+ ? & ctx->Const.VertexProgram
+ : & ctx->Const.FragmentProgram;
+
+ state->MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits;
+ state->MaxTextureCoordUnits = ctx->Const.MaxTextureCoordUnits;
+ state->MaxTextureUnits = ctx->Const.MaxTextureUnits;
+ state->MaxClipPlanes = ctx->Const.MaxClipPlanes;
+ state->MaxLights = ctx->Const.MaxLights;
+ state->MaxProgramMatrices = ctx->Const.MaxProgramMatrices;
+
+ state->state_param_enum = (target == GL_VERTEX_PROGRAM_ARB)
+ ? STATE_VERTEX_PROGRAM : STATE_FRAGMENT_PROGRAM;
+
+ _mesa_set_program_error(ctx, -1, NULL);
+
+ _mesa_program_lexer_ctor(& state->scanner, state, (const char *) str, len);
+ yyparse(state);
+ _mesa_program_lexer_dtor(state->scanner);
+
+
+ if (ctx->Program.ErrorPos != -1) {
+ goto error;
+ }
+
+ if (! _mesa_layout_parameters(state)) {
+ struct YYLTYPE loc;
+
+ loc.first_line = 0;
+ loc.first_column = 0;
+ loc.position = len;
+
+ yyerror(& loc, state, "invalid PARAM usage");
+ goto error;
+ }
+
+
+
+ /* Add one instruction to store the "END" instruction.
+ */
+ state->prog->Instructions =
+ _mesa_alloc_instructions(state->prog->NumInstructions + 1);
+ inst = state->inst_head;
+ for (i = 0; i < state->prog->NumInstructions; i++) {
+ struct asm_instruction *const temp = inst->next;
+
+ state->prog->Instructions[i] = inst->Base;
+ inst = temp;
+ }
+
+ /* Finally, tag on an OPCODE_END instruction */
+ {
+ const GLuint numInst = state->prog->NumInstructions;
+ _mesa_init_instructions(state->prog->Instructions + numInst, 1);
+ state->prog->Instructions[numInst].Opcode = OPCODE_END;
+ }
+ state->prog->NumInstructions++;
+
+ state->prog->NumParameters = state->prog->Parameters->NumParameters;
+ state->prog->NumAttributes = _mesa_bitcount(state->prog->InputsRead);
+
+ /*
+ * Initialize native counts to logical counts. The device driver may
+ * change them if program is translated into a hardware program.
+ */
+ state->prog->NumNativeInstructions = state->prog->NumInstructions;
+ state->prog->NumNativeTemporaries = state->prog->NumTemporaries;
+ state->prog->NumNativeParameters = state->prog->NumParameters;
+ state->prog->NumNativeAttributes = state->prog->NumAttributes;
+ state->prog->NumNativeAddressRegs = state->prog->NumAddressRegs;
+
+ result = GL_TRUE;
+
+error:
+ for (inst = state->inst_head; inst != NULL; inst = temp) {
+ temp = inst->next;
+ _mesa_free(inst);
+ }
+
+ state->inst_head = NULL;
+ state->inst_tail = NULL;
+
+ for (sym = state->sym; sym != NULL; sym = temp) {
+ temp = sym->next;
+
+ _mesa_free((void *) sym->name);
+ _mesa_free(sym);
+ }
+ state->sym = NULL;
+
+ _mesa_symbol_table_dtor(state->st);
+ state->st = NULL;
+
+ return result;
+}
diff --git a/mesalib/src/mesa/shader/program_parse_extra.c b/mesalib/src/mesa/shader/program_parse_extra.c
new file mode 100644
index 000000000..8e4be606f
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_parse_extra.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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 <string.h>
+#include "main/mtypes.h"
+#include "prog_instruction.h"
+#include "program_parser.h"
+
+
+/**
+ * Extra assembly-level parser routines
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+
+int
+_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ if (strcmp(option, "ARB_position_invariant") == 0) {
+ state->option.PositionInvariant = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
+{
+ /* All of the options currently supported start with "ARB_". The code is
+ * currently structured with nested if-statements because eventually options
+ * that start with "NV_" will be supported. This structure will result in
+ * less churn when those options are added.
+ */
+ if (strncmp(option, "ARB_", 4) == 0) {
+ /* Advance the pointer past the "ARB_" prefix.
+ */
+ option += 4;
+
+
+ if (strncmp(option, "fog_", 4) == 0) {
+ option += 4;
+
+ if (state->option.Fog == OPTION_NONE) {
+ if (strcmp(option, "exp") == 0) {
+ state->option.Fog = OPTION_FOG_EXP;
+ return 1;
+ } else if (strcmp(option, "exp2") == 0) {
+ state->option.Fog = OPTION_FOG_EXP2;
+ return 1;
+ } else if (strcmp(option, "linear") == 0) {
+ state->option.Fog = OPTION_FOG_LINEAR;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strncmp(option, "precision_hint_", 15) == 0) {
+ option += 15;
+
+ if (state->option.PrecisionHint == OPTION_NONE) {
+ if (strcmp(option, "nicest") == 0) {
+ state->option.PrecisionHint = OPTION_NICEST;
+ return 1;
+ } else if (strcmp(option, "fastest") == 0) {
+ state->option.PrecisionHint = OPTION_FASTEST;
+ return 1;
+ }
+ }
+
+ return 0;
+ } else if (strcmp(option, "draw_buffers") == 0) {
+ /* Don't need to check extension availability because all Mesa-based
+ * drivers support GL_ARB_draw_buffers.
+ */
+ state->option.DrawBuffers = 1;
+ return 1;
+ } else if (strcmp(option, "fragment_program_shadow") == 0) {
+ if (state->ctx->Extensions.ARB_fragment_program_shadow) {
+ state->option.Shadow = 1;
+ return 1;
+ }
+ }
+ } else if (strncmp(option, "MESA_", 5) == 0) {
+ option += 5;
+
+ if (strcmp(option, "texture_array") == 0) {
+ if (state->ctx->Extensions.MESA_texture_array) {
+ state->option.TexArray = 1;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/mesalib/src/mesa/shader/program_parser.h b/mesalib/src/mesa/shader/program_parser.h
new file mode 100644
index 000000000..fa47d8456
--- /dev/null
+++ b/mesalib/src/mesa/shader/program_parser.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include "main/config.h"
+
+#ifndef MTYPES_H
+struct __GLcontextRec;
+typedef struct __GLcontextRec GLcontext;
+#endif
+
+enum asm_type {
+ at_none,
+ at_address,
+ at_attrib,
+ at_param,
+ at_temp,
+ at_output,
+};
+
+struct asm_symbol {
+ struct asm_symbol *next; /**< List linkage for freeing. */
+ const char *name;
+ enum asm_type type;
+ unsigned attrib_binding;
+ unsigned output_binding; /**< Output / result register number. */
+
+ /**
+ * One of PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM, or PROGRAM_ENV_PARAM.
+ */
+ unsigned param_binding_type;
+
+ /**
+ * Offset into the program_parameter_list where the tokens representing our
+ * bound state (or constants) start.
+ */
+ unsigned param_binding_begin;
+
+ /* This is how many entries in the the program_parameter_list we take up
+ * with our state tokens or constants. Note that this is _not_ the same as
+ * the number of param registers we eventually use.
+ */
+ unsigned param_binding_length;
+
+ /**
+ * Index of the temp register assigned to this variable.
+ */
+ unsigned temp_binding;
+
+ /**
+ * Flag whether or not a PARAM is an array
+ */
+ unsigned param_is_array:1;
+
+
+ /**
+ * Flag whether or not a PARAM array is accessed indirectly
+ */
+ unsigned param_accessed_indirectly:1;
+
+
+ /**
+ * \brief Is first pass of parameter layout done with this variable?
+ *
+ * The parameter layout routine operates in two passes. This flag tracks
+ * whether or not the first pass has handled this variable.
+ *
+ * \sa _mesa_layout_parameters
+ */
+ unsigned pass1_done:1;
+};
+
+
+struct asm_vector {
+ unsigned count;
+ float data[4];
+};
+
+
+struct asm_swizzle_mask {
+ unsigned swizzle:12;
+ unsigned mask:4;
+};
+
+
+struct asm_src_register {
+ struct prog_src_register Base;
+
+ /**
+ * Symbol associated with indirect access to parameter arrays.
+ *
+ * If \c Base::RelAddr is 1, this will point to the symbol for the parameter
+ * that is being dereferenced. Further, \c Base::Index will be the offset
+ * from the address register being used.
+ */
+ struct asm_symbol *Symbol;
+};
+
+
+struct asm_instruction {
+ struct prog_instruction Base;
+ struct asm_instruction *next;
+ struct asm_src_register SrcReg[3];
+};
+
+
+struct asm_parser_state {
+ GLcontext *ctx;
+ struct gl_program *prog;
+
+ /**
+ * Per-program target limits
+ */
+ struct gl_program_constants *limits;
+
+ struct _mesa_symbol_table *st;
+
+ /**
+ * Linked list of symbols
+ *
+ * This list is \b only used when cleaning up compiler state and freeing
+ * memory.
+ */
+ struct asm_symbol *sym;
+
+ /**
+ * State for the lexer.
+ */
+ void *scanner;
+
+ /**
+ * Linked list of instructions generated during parsing.
+ */
+ /*@{*/
+ struct asm_instruction *inst_head;
+ struct asm_instruction *inst_tail;
+ /*@}*/
+
+
+ /**
+ * Selected limits copied from gl_constants
+ *
+ * These are limits from the GL context, but various bits in the program
+ * must be validated against these values.
+ */
+ /*@{*/
+ unsigned MaxTextureCoordUnits;
+ unsigned MaxTextureImageUnits;
+ unsigned MaxTextureUnits;
+ unsigned MaxClipPlanes;
+ unsigned MaxLights;
+ unsigned MaxProgramMatrices;
+ /*@}*/
+
+ /**
+ * Value to use in state vector accessors for environment and local
+ * parameters
+ */
+ unsigned state_param_enum;
+
+
+ /**
+ * Input attributes bound to specific names
+ *
+ * This is only needed so that errors can be properly produced when
+ * multiple ATTRIB statements bind illegal combinations of vertex
+ * attributes.
+ */
+ unsigned InputsBound;
+
+ enum {
+ invalid_mode = 0,
+ ARB_vertex,
+ ARB_fragment
+ } mode;
+
+ struct {
+ unsigned PositionInvariant:1;
+ unsigned Fog:2;
+ unsigned PrecisionHint:2;
+ unsigned DrawBuffers:1;
+ unsigned Shadow:1;
+ unsigned TexRect:1;
+ unsigned TexArray:1;
+ } option;
+
+ struct {
+ unsigned UsesKill:1;
+ } fragment;
+};
+
+#define OPTION_NONE 0
+#define OPTION_FOG_EXP 1
+#define OPTION_FOG_EXP2 2
+#define OPTION_FOG_LINEAR 3
+#define OPTION_NICEST 1
+#define OPTION_FASTEST 2
+
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ int position;
+} YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED 1
+#define YYLTYPE_IS_TRIVIAL 1
+
+
+extern GLboolean _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
+ const GLubyte *str, GLsizei len, struct asm_parser_state *state);
+
+
+
+/* From program_lexer.l. */
+extern void _mesa_program_lexer_dtor(void *scanner);
+
+extern void _mesa_program_lexer_ctor(void **scanner,
+ struct asm_parser_state *state, const char *string, size_t len);
+
+
+/**
+ *\name From program_parse_extra.c
+ */
+/*@{*/
+
+/**
+ * Parses and processes an option string to an ARB vertex program
+ *
+ * \return
+ * Non-zero on success, zero on failure.
+ */
+extern int _mesa_ARBvp_parse_option(struct asm_parser_state *state,
+ const char *option);
+
+/**
+ * Parses and processes an option string to an ARB fragment program
+ *
+ * \return
+ * Non-zero on success, zero on failure.
+ */
+extern int _mesa_ARBfp_parse_option(struct asm_parser_state *state,
+ const char *option);
+
+/*@}*/
diff --git a/mesalib/src/mesa/shader/programopt.c b/mesalib/src/mesa/shader/programopt.c
new file mode 100644
index 000000000..f70c75cec
--- /dev/null
+++ b/mesalib/src/mesa/shader/programopt.c
@@ -0,0 +1,575 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/**
+ * \file programopt.c
+ * Vertex/Fragment program optimizations and transformations for program
+ * options, etc.
+ *
+ * \author Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "prog_parameter.h"
+#include "prog_statevars.h"
+#include "program.h"
+#include "programopt.h"
+#include "prog_instruction.h"
+
+
+/**
+ * This function inserts instructions for coordinate modelview * projection
+ * into a vertex program.
+ * May be used to implement the position_invariant option.
+ */
+static void
+_mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+{
+ struct prog_instruction *newInst;
+ const GLuint origLen = vprog->Base.NumInstructions;
+ const GLuint newLen = origLen + 4;
+ GLuint i;
+
+ /*
+ * Setup state references for the modelview/projection matrix.
+ * XXX we should check if these state vars are already declared.
+ */
+ static const gl_state_index mvpState[4][STATE_LENGTH] = {
+ { STATE_MVP_MATRIX, 0, 0, 0, 0 }, /* state.matrix.mvp.row[0] */
+ { STATE_MVP_MATRIX, 0, 1, 1, 0 }, /* state.matrix.mvp.row[1] */
+ { STATE_MVP_MATRIX, 0, 2, 2, 0 }, /* state.matrix.mvp.row[2] */
+ { STATE_MVP_MATRIX, 0, 3, 3, 0 }, /* state.matrix.mvp.row[3] */
+ };
+ GLint mvpRef[4];
+
+ for (i = 0; i < 4; i++) {
+ mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters,
+ mvpState[i]);
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glProgramString(inserting position_invariant code)");
+ return;
+ }
+
+ /*
+ * Generated instructions:
+ * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position;
+ * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position;
+ * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position;
+ * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position;
+ */
+ _mesa_init_instructions(newInst, 4);
+ for (i = 0; i < 4; i++) {
+ newInst[i].Opcode = OPCODE_DP4;
+ newInst[i].DstReg.File = PROGRAM_OUTPUT;
+ newInst[i].DstReg.Index = VERT_RESULT_HPOS;
+ newInst[i].DstReg.WriteMask = (WRITEMASK_X << i);
+ newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR;
+ newInst[i].SrcReg[0].Index = mvpRef[i];
+ newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
+ newInst[i].SrcReg[1].File = PROGRAM_INPUT;
+ newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS;
+ newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ }
+
+ /* Append original instructions after new instructions */
+ _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);
+
+ /* free old instructions */
+ _mesa_free_instructions(vprog->Base.Instructions, origLen);
+
+ /* install new instructions */
+ vprog->Base.Instructions = newInst;
+ vprog->Base.NumInstructions = newLen;
+ vprog->Base.InputsRead |= VERT_BIT_POS;
+ vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS);
+}
+
+
+static void
+_mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+{
+ struct prog_instruction *newInst;
+ const GLuint origLen = vprog->Base.NumInstructions;
+ const GLuint newLen = origLen + 4;
+ GLuint hposTemp;
+ GLuint i;
+
+ /*
+ * Setup state references for the modelview/projection matrix.
+ * XXX we should check if these state vars are already declared.
+ */
+ static const gl_state_index mvpState[4][STATE_LENGTH] = {
+ { STATE_MVP_MATRIX, 0, 0, 0, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 1, 1, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 2, 2, STATE_MATRIX_TRANSPOSE },
+ { STATE_MVP_MATRIX, 0, 3, 3, STATE_MATRIX_TRANSPOSE },
+ };
+ GLint mvpRef[4];
+
+ for (i = 0; i < 4; i++) {
+ mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters,
+ mvpState[i]);
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glProgramString(inserting position_invariant code)");
+ return;
+ }
+
+ /* TEMP hposTemp; */
+ hposTemp = vprog->Base.NumTemporaries++;
+
+ /*
+ * Generated instructions:
+ * emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]);
+ * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp);
+ * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp);
+ * emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp);
+ */
+ _mesa_init_instructions(newInst, 4);
+
+ newInst[0].Opcode = OPCODE_MUL;
+ newInst[0].DstReg.File = PROGRAM_TEMPORARY;
+ newInst[0].DstReg.Index = hposTemp;
+ newInst[0].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[0].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[0].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[0].SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[0].SrcReg[1].Index = mvpRef[0];
+ newInst[0].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+
+ for (i = 1; i <= 2; i++) {
+ newInst[i].Opcode = OPCODE_MAD;
+ newInst[i].DstReg.File = PROGRAM_TEMPORARY;
+ newInst[i].DstReg.Index = hposTemp;
+ newInst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[i].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[i].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(i,i,i,i);
+ newInst[i].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[i].SrcReg[1].Index = mvpRef[i];
+ newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ newInst[i].SrcReg[2].File = PROGRAM_TEMPORARY;
+ newInst[i].SrcReg[2].Index = hposTemp;
+ newInst[1].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+ }
+
+ newInst[3].Opcode = OPCODE_MAD;
+ newInst[3].DstReg.File = PROGRAM_OUTPUT;
+ newInst[3].DstReg.Index = VERT_RESULT_HPOS;
+ newInst[3].DstReg.WriteMask = WRITEMASK_XYZW;
+ newInst[3].SrcReg[0].File = PROGRAM_INPUT;
+ newInst[3].SrcReg[0].Index = VERT_ATTRIB_POS;
+ newInst[3].SrcReg[0].Swizzle = SWIZZLE_WWWW;
+ newInst[3].SrcReg[1].File = PROGRAM_STATE_VAR;
+ newInst[3].SrcReg[1].Index = mvpRef[3];
+ newInst[3].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ newInst[3].SrcReg[2].File = PROGRAM_TEMPORARY;
+ newInst[3].SrcReg[2].Index = hposTemp;
+ newInst[3].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+
+ /* Append original instructions after new instructions */
+ _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen);
+
+ /* free old instructions */
+ _mesa_free_instructions(vprog->Base.Instructions, origLen);
+
+ /* install new instructions */
+ vprog->Base.Instructions = newInst;
+ vprog->Base.NumInstructions = newLen;
+ vprog->Base.InputsRead |= VERT_BIT_POS;
+ vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS);
+}
+
+
+void
+_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
+{
+ if (ctx->mvp_with_dp4)
+ _mesa_insert_mvp_dp4_code( ctx, vprog );
+ else
+ _mesa_insert_mvp_mad_code( ctx, vprog );
+}
+
+
+
+
+
+
+/**
+ * Append extra instructions onto the given fragment program to implement
+ * the fog mode specified by fprog->FogOption.
+ * The fragment.fogcoord input is used to compute the fog blend factor.
+ *
+ * XXX with a little work, this function could be adapted to add fog code
+ * to vertex programs too.
+ */
+void
+_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
+{
+ static const gl_state_index fogPStateOpt[STATE_LENGTH]
+ = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
+ static const gl_state_index fogColorState[STATE_LENGTH]
+ = { STATE_FOG_COLOR, 0, 0, 0, 0};
+ struct prog_instruction *newInst, *inst;
+ const GLuint origLen = fprog->Base.NumInstructions;
+ const GLuint newLen = origLen + 5;
+ GLuint i;
+ GLint fogPRefOpt, fogColorRef; /* state references */
+ GLuint colorTemp, fogFactorTemp; /* temporary registerss */
+
+ if (fprog->FogOption == GL_NONE) {
+ _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program"
+ " with FogOption == GL_NONE");
+ return;
+ }
+
+ /* Alloc storage for new instructions */
+ newInst = _mesa_alloc_instructions(newLen);
+ if (!newInst) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY,
+ "glProgramString(inserting fog_option code)");
+ return;
+ }
+
+ /* Copy orig instructions into new instruction buffer */
+ _mesa_copy_instructions(newInst, fprog->Base.Instructions, origLen);
+
+ /* PARAM fogParamsRefOpt = internal optimized fog params; */
+ fogPRefOpt
+ = _mesa_add_state_reference(fprog->Base.Parameters, fogPStateOpt);
+ /* PARAM fogColorRef = state.fog.color; */
+ fogColorRef
+ = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState);
+
+ /* TEMP colorTemp; */
+ colorTemp = fprog->Base.NumTemporaries++;
+ /* TEMP fogFactorTemp; */
+ fogFactorTemp = fprog->Base.NumTemporaries++;
+
+ /* Scan program to find where result.color is written */
+ inst = newInst;
+ for (i = 0; i < fprog->Base.NumInstructions; i++) {
+ if (inst->Opcode == OPCODE_END)
+ break;
+ if (inst->DstReg.File == PROGRAM_OUTPUT &&
+ inst->DstReg.Index == FRAG_RESULT_COLOR) {
+ /* change the instruction to write to colorTemp w/ clamping */
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = colorTemp;
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ /* don't break (may be several writes to result.color) */
+ }
+ inst++;
+ }
+ assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */
+
+ _mesa_init_instructions(inst, 5);
+
+ /* emit instructions to compute fog blending factor */
+ if (fprog->FogOption == GL_LINEAR) {
+ /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */
+ inst->Opcode = OPCODE_MAD;
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = fogFactorTemp;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ inst->SrcReg[0].File = PROGRAM_INPUT;
+ inst->SrcReg[0].Index = FRAG_ATTRIB_FOGC;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ inst->SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst->SrcReg[1].Index = fogPRefOpt;
+ inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
+ inst->SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst->SrcReg[2].Index = fogPRefOpt;
+ inst->SrcReg[2].Swizzle = SWIZZLE_YYYY;
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ inst++;
+ }
+ else {
+ ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2);
+ /* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */
+ /* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */
+ /* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */
+ inst->Opcode = OPCODE_MUL;
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = fogFactorTemp;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ inst->SrcReg[0].File = PROGRAM_STATE_VAR;
+ inst->SrcReg[0].Index = fogPRefOpt;
+ inst->SrcReg[0].Swizzle
+ = (fprog->FogOption == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW;
+ inst->SrcReg[1].File = PROGRAM_INPUT;
+ inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC;
+ inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
+ inst++;
+ if (fprog->FogOption == GL_EXP2) {
+ /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */
+ inst->Opcode = OPCODE_MUL;
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = fogFactorTemp;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = fogFactorTemp;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ inst->SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[1].Index = fogFactorTemp;
+ inst->SrcReg[1].Swizzle = SWIZZLE_XXXX;
+ inst++;
+ }
+ /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */
+ inst->Opcode = OPCODE_EX2;
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = fogFactorTemp;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = fogFactorTemp;
+ inst->SrcReg[0].Negate = NEGATE_XYZW;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ inst++;
+ }
+ /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */
+ inst->Opcode = OPCODE_LRP;
+ inst->DstReg.File = PROGRAM_OUTPUT;
+ inst->DstReg.Index = FRAG_RESULT_COLOR;
+ inst->DstReg.WriteMask = WRITEMASK_XYZ;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = fogFactorTemp;
+ inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
+ inst->SrcReg[1].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[1].Index = colorTemp;
+ inst->SrcReg[1].Swizzle = SWIZZLE_NOOP;
+ inst->SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst->SrcReg[2].Index = fogColorRef;
+ inst->SrcReg[2].Swizzle = SWIZZLE_NOOP;
+ inst++;
+ /* MOV result.color.w, colorTemp.x; # copy alpha */
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.File = PROGRAM_OUTPUT;
+ inst->DstReg.Index = FRAG_RESULT_COLOR;
+ inst->DstReg.WriteMask = WRITEMASK_W;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = colorTemp;
+ inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
+ inst++;
+ /* END; */
+ inst->Opcode = OPCODE_END;
+ inst++;
+
+ /* free old instructions */
+ _mesa_free_instructions(fprog->Base.Instructions, origLen);
+
+ /* install new instructions */
+ fprog->Base.Instructions = newInst;
+ fprog->Base.NumInstructions = inst - newInst;
+ fprog->Base.InputsRead |= FRAG_BIT_FOGC;
+ /* XXX do this? fprog->FogOption = GL_NONE; */
+}
+
+
+
+static GLboolean
+is_texture_instruction(const struct prog_instruction *inst)
+{
+ switch (inst->Opcode) {
+ case OPCODE_TEX:
+ case OPCODE_TXB:
+ case OPCODE_TXD:
+ case OPCODE_TXL:
+ case OPCODE_TXP:
+ case OPCODE_TXP_NV:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Count the number of texure indirections in the given program.
+ * The program's NumTexIndirections field will be updated.
+ * See the GL_ARB_fragment_program spec (issue 24) for details.
+ * XXX we count texture indirections in texenvprogram.c (maybe use this code
+ * instead and elsewhere).
+ */
+void
+_mesa_count_texture_indirections(struct gl_program *prog)
+{
+ GLuint indirections = 1;
+ GLbitfield tempsOutput = 0x0;
+ GLbitfield aluTemps = 0x0;
+ GLuint i;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+
+ if (is_texture_instruction(inst)) {
+ if (((inst->SrcReg[0].File == PROGRAM_TEMPORARY) &&
+ (tempsOutput & (1 << inst->SrcReg[0].Index))) ||
+ ((inst->Opcode != OPCODE_KIL) &&
+ (inst->DstReg.File == PROGRAM_TEMPORARY) &&
+ (aluTemps & (1 << inst->DstReg.Index))))
+ {
+ indirections++;
+ tempsOutput = 0x0;
+ aluTemps = 0x0;
+ }
+ }
+ else {
+ GLuint j;
+ for (j = 0; j < 3; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
+ aluTemps |= (1 << inst->SrcReg[j].Index);
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY)
+ aluTemps |= (1 << inst->DstReg.Index);
+ }
+
+ if ((inst->Opcode != OPCODE_KIL) && (inst->DstReg.File == PROGRAM_TEMPORARY))
+ tempsOutput |= (1 << inst->DstReg.Index);
+ }
+
+ prog->NumTexIndirections = indirections;
+}
+
+
+/**
+ * Count number of texture instructions in given program and update the
+ * program's NumTexInstructions field.
+ */
+void
+_mesa_count_texture_instructions(struct gl_program *prog)
+{
+ GLuint i;
+ prog->NumTexInstructions = 0;
+ for (i = 0; i < prog->NumInstructions; i++) {
+ prog->NumTexInstructions += is_texture_instruction(prog->Instructions + i);
+ }
+}
+
+
+/**
+ * Scan/rewrite program to remove reads of custom (output) registers.
+ * The passed type has to be either PROGRAM_OUTPUT or PROGRAM_VARYING
+ * (for vertex shaders).
+ * In GLSL shaders, varying vars can be read and written.
+ * On some hardware, trying to read an output register causes trouble.
+ * So, rewrite the program to use a temporary register in this case.
+ */
+void
+_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
+{
+ GLuint i;
+ GLint outputMap[VERT_RESULT_MAX];
+ GLuint numVaryingReads = 0;
+
+ assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT);
+ assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING);
+
+ for (i = 0; i < VERT_RESULT_MAX; i++)
+ outputMap[i] = -1;
+
+ /* look for instructions which read from varying vars */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == type) {
+ /* replace the read with a temp reg */
+ const GLuint var = inst->SrcReg[j].Index;
+ if (outputMap[var] == -1) {
+ numVaryingReads++;
+ outputMap[var] = _mesa_find_free_register(prog,
+ PROGRAM_TEMPORARY);
+ }
+ inst->SrcReg[j].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[j].Index = outputMap[var];
+ }
+ }
+ }
+
+ if (numVaryingReads == 0)
+ return; /* nothing to be done */
+
+ /* look for instructions which write to the varying vars identified above */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ GLuint j;
+ for (j = 0; j < numSrc; j++) {
+ if (inst->DstReg.File == type &&
+ outputMap[inst->DstReg.Index] >= 0) {
+ /* change inst to write to the temp reg, instead of the varying */
+ inst->DstReg.File = PROGRAM_TEMPORARY;
+ inst->DstReg.Index = outputMap[inst->DstReg.Index];
+ }
+ }
+ }
+
+ /* insert new instructions to copy the temp vars to the varying vars */
+ {
+ struct prog_instruction *inst;
+ GLint endPos, var;
+
+ /* Look for END instruction and insert the new varying writes */
+ endPos = -1;
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (inst->Opcode == OPCODE_END) {
+ endPos = i;
+ _mesa_insert_instructions(prog, i, numVaryingReads);
+ break;
+ }
+ }
+
+ assert(endPos >= 0);
+
+ /* insert new MOV instructions here */
+ inst = prog->Instructions + endPos;
+ for (var = 0; var < VERT_RESULT_MAX; var++) {
+ if (outputMap[var] >= 0) {
+ /* MOV VAR[var], TEMP[tmp]; */
+ inst->Opcode = OPCODE_MOV;
+ inst->DstReg.File = type;
+ inst->DstReg.Index = var;
+ inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst->SrcReg[0].Index = outputMap[var];
+ inst++;
+ }
+ }
+ }
+}
diff --git a/mesalib/src/mesa/shader/programopt.h b/mesalib/src/mesa/shader/programopt.h
new file mode 100644
index 000000000..96acaf956
--- /dev/null
+++ b/mesalib/src/mesa/shader/programopt.h
@@ -0,0 +1,45 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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 PROGRAMOPT_H
+#define PROGRAMOPT_H 1
+
+
+extern void
+_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog);
+
+extern void
+_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog);
+
+extern void
+_mesa_count_texture_indirections(struct gl_program *prog);
+
+extern void
+_mesa_count_texture_instructions(struct gl_program *prog);
+
+extern void
+_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type);
+
+#endif /* PROGRAMOPT_H */
diff --git a/mesalib/src/mesa/shader/shader_api.c b/mesalib/src/mesa/shader/shader_api.c
new file mode 100644
index 000000000..178b7d0db
--- /dev/null
+++ b/mesalib/src/mesa/shader/shader_api.c
@@ -0,0 +1,2154 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file shader_api.c
+ * Implementation of GLSL-related API functions
+ * \author Brian Paul
+ */
+
+/**
+ * XXX things to do:
+ * 1. Check that the right error code is generated for all _mesa_error() calls.
+ * 2. Insert FLUSH_VERTICES calls in various places
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "shader/prog_uniform.h"
+#include "shader/shader_api.h"
+#include "shader/slang/slang_compile.h"
+#include "shader/slang/slang_link.h"
+#include "glapi/dispatch.h"
+
+
+/**
+ * Allocate a new gl_shader_program object, initialize it.
+ */
+static struct gl_shader_program *
+_mesa_new_shader_program(GLcontext *ctx, GLuint name)
+{
+ struct gl_shader_program *shProg;
+ shProg = CALLOC_STRUCT(gl_shader_program);
+ if (shProg) {
+ shProg->Type = GL_SHADER_PROGRAM_MESA;
+ shProg->Name = name;
+ shProg->RefCount = 1;
+ shProg->Attributes = _mesa_new_parameter_list();
+ }
+ return shProg;
+}
+
+
+/**
+ * Clear (free) the shader program state that gets produced by linking.
+ */
+void
+_mesa_clear_shader_program_data(GLcontext *ctx,
+ struct gl_shader_program *shProg)
+{
+ _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
+ _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
+
+ if (shProg->Uniforms) {
+ _mesa_free_uniform_list(shProg->Uniforms);
+ shProg->Uniforms = NULL;
+ }
+
+ if (shProg->Varying) {
+ _mesa_free_parameter_list(shProg->Varying);
+ shProg->Varying = NULL;
+ }
+}
+
+
+/**
+ * Free all the data that hangs off a shader program object, but not the
+ * object itself.
+ */
+void
+_mesa_free_shader_program_data(GLcontext *ctx,
+ struct gl_shader_program *shProg)
+{
+ GLuint i;
+
+ assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
+
+ _mesa_clear_shader_program_data(ctx, shProg);
+
+ if (shProg->Attributes) {
+ _mesa_free_parameter_list(shProg->Attributes);
+ shProg->Attributes = NULL;
+ }
+
+ /* detach shaders */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
+ }
+ shProg->NumShaders = 0;
+
+ if (shProg->Shaders) {
+ _mesa_free(shProg->Shaders);
+ shProg->Shaders = NULL;
+ }
+
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ shProg->InfoLog = NULL;
+ }
+}
+
+
+/**
+ * Free/delete a shader program object.
+ */
+void
+_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
+{
+ _mesa_free_shader_program_data(ctx, shProg);
+
+ _mesa_free(shProg);
+}
+
+
+/**
+ * Set ptr to point to shProg.
+ * If ptr is pointing to another object, decrement its refcount (and delete
+ * if refcount hits zero).
+ * Then set ptr to point to shProg, incrementing its refcount.
+ */
+/* XXX this could be static */
+void
+_mesa_reference_shader_program(GLcontext *ctx,
+ struct gl_shader_program **ptr,
+ struct gl_shader_program *shProg)
+{
+ assert(ptr);
+ if (*ptr == shProg) {
+ /* no-op */
+ return;
+ }
+ if (*ptr) {
+ /* Unreference the old shader program */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_shader_program *old = *ptr;
+
+ ASSERT(old->RefCount > 0);
+ old->RefCount--;
+#if 0
+ printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
+ (void *) old, old->Name, old->RefCount);
+#endif
+ deleteFlag = (old->RefCount == 0);
+
+ if (deleteFlag) {
+ _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
+ _mesa_free_shader_program(ctx, old);
+ }
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (shProg) {
+ shProg->RefCount++;
+#if 0
+ printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
+ (void *) shProg, shProg->Name, shProg->RefCount);
+#endif
+ *ptr = shProg;
+ }
+}
+
+
+/**
+ * Lookup a GLSL program object.
+ */
+struct gl_shader_program *
+_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
+{
+ struct gl_shader_program *shProg;
+ if (name) {
+ shProg = (struct gl_shader_program *)
+ _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
+ /* Note that both gl_shader and gl_shader_program objects are kept
+ * in the same hash table. Check the object's type to be sure it's
+ * what we're expecting.
+ */
+ if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
+ return NULL;
+ }
+ return shProg;
+ }
+ return NULL;
+}
+
+
+/**
+ * As above, but record an error if program is not found.
+ */
+static struct gl_shader_program *
+_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
+ const char *caller)
+{
+ if (!name) {
+ _mesa_error(ctx, GL_INVALID_VALUE, caller);
+ return NULL;
+ }
+ else {
+ struct gl_shader_program *shProg = (struct gl_shader_program *)
+ _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
+ if (!shProg) {
+ _mesa_error(ctx, GL_INVALID_VALUE, caller);
+ return NULL;
+ }
+ if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, caller);
+ return NULL;
+ }
+ return shProg;
+ }
+}
+
+
+
+
+/**
+ * Allocate a new gl_shader object, initialize it.
+ */
+struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
+{
+ struct gl_shader *shader;
+ assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
+ shader = CALLOC_STRUCT(gl_shader);
+ if (shader) {
+ shader->Type = type;
+ shader->Name = name;
+ shader->RefCount = 1;
+ }
+ return shader;
+}
+
+
+void
+_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
+{
+ if (sh->Source)
+ _mesa_free((void *) sh->Source);
+ if (sh->InfoLog)
+ _mesa_free(sh->InfoLog);
+ _mesa_reference_program(ctx, &sh->Program, NULL);
+ _mesa_free(sh);
+}
+
+
+/**
+ * Set ptr to point to sh.
+ * If ptr is pointing to another shader, decrement its refcount (and delete
+ * if refcount hits zero).
+ * Then set ptr to point to sh, incrementing its refcount.
+ */
+/* XXX this could be static */
+void
+_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh)
+{
+ assert(ptr);
+ if (*ptr == sh) {
+ /* no-op */
+ return;
+ }
+ if (*ptr) {
+ /* Unreference the old shader */
+ GLboolean deleteFlag = GL_FALSE;
+ struct gl_shader *old = *ptr;
+
+ ASSERT(old->RefCount > 0);
+ old->RefCount--;
+ /*printf("SHADER DECR %p (%d) to %d\n",
+ (void*) old, old->Name, old->RefCount);*/
+ deleteFlag = (old->RefCount == 0);
+
+ if (deleteFlag) {
+ _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
+ _mesa_free_shader(ctx, old);
+ }
+
+ *ptr = NULL;
+ }
+ assert(!*ptr);
+
+ if (sh) {
+ /* reference new */
+ sh->RefCount++;
+ /*printf("SHADER INCR %p (%d) to %d\n",
+ (void*) sh, sh->Name, sh->RefCount);*/
+ *ptr = sh;
+ }
+}
+
+
+/**
+ * Lookup a GLSL shader object.
+ */
+struct gl_shader *
+_mesa_lookup_shader(GLcontext *ctx, GLuint name)
+{
+ if (name) {
+ struct gl_shader *sh = (struct gl_shader *)
+ _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
+ /* Note that both gl_shader and gl_shader_program objects are kept
+ * in the same hash table. Check the object's type to be sure it's
+ * what we're expecting.
+ */
+ if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
+ return NULL;
+ }
+ return sh;
+ }
+ return NULL;
+}
+
+
+/**
+ * As above, but record an error if shader is not found.
+ */
+static struct gl_shader *
+_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
+{
+ if (!name) {
+ _mesa_error(ctx, GL_INVALID_VALUE, caller);
+ return NULL;
+ }
+ else {
+ struct gl_shader *sh = (struct gl_shader *)
+ _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
+ if (!sh) {
+ _mesa_error(ctx, GL_INVALID_VALUE, caller);
+ return NULL;
+ }
+ if (sh->Type == GL_SHADER_PROGRAM_MESA) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, caller);
+ return NULL;
+ }
+ return sh;
+ }
+}
+
+
+/**
+ * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
+ */
+static GLbitfield
+get_shader_flags(void)
+{
+ GLbitfield flags = 0x0;
+ const char *env = _mesa_getenv("MESA_GLSL");
+
+ if (env) {
+ if (_mesa_strstr(env, "dump"))
+ flags |= GLSL_DUMP;
+ if (_mesa_strstr(env, "log"))
+ flags |= GLSL_LOG;
+ if (_mesa_strstr(env, "nopt"))
+ flags |= GLSL_NO_OPT;
+ else if (_mesa_strstr(env, "opt"))
+ flags |= GLSL_OPT;
+ if (_mesa_strstr(env, "uniform"))
+ flags |= GLSL_UNIFORMS;
+ }
+
+ return flags;
+}
+
+
+/**
+ * Initialize context's shader state.
+ */
+void
+_mesa_init_shader_state(GLcontext * ctx)
+{
+ /* Device drivers may override these to control what kind of instructions
+ * are generated by the GLSL compiler.
+ */
+ ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
+ ctx->Shader.EmitContReturn = GL_TRUE;
+ ctx->Shader.EmitCondCodes = GL_FALSE;
+ ctx->Shader.EmitComments = GL_FALSE;
+ ctx->Shader.Flags = get_shader_flags();
+
+ /* Default pragma settings */
+ ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
+ ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
+ ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
+ ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
+}
+
+
+/**
+ * Free the per-context shader-related state.
+ */
+void
+_mesa_free_shader_state(GLcontext *ctx)
+{
+ _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
+}
+
+
+/**
+ * Copy string from <src> to <dst>, up to maxLength characters, returning
+ * length of <dst> in <length>.
+ * \param src the strings source
+ * \param maxLength max chars to copy
+ * \param length returns number of chars copied
+ * \param dst the string destination
+ */
+static void
+copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
+{
+ GLsizei len;
+ for (len = 0; len < maxLength - 1 && src && src[len]; len++)
+ dst[len] = src[len];
+ if (maxLength > 0)
+ dst[len] = 0;
+ if (length)
+ *length = len;
+}
+
+
+static GLboolean
+_mesa_is_program(GLcontext *ctx, GLuint name)
+{
+ struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
+ return shProg ? GL_TRUE : GL_FALSE;
+}
+
+
+static GLboolean
+_mesa_is_shader(GLcontext *ctx, GLuint name)
+{
+ struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
+ return shader ? GL_TRUE : GL_FALSE;
+}
+
+
+/**
+ * Called via ctx->Driver.AttachShader()
+ */
+static void
+_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
+{
+ struct gl_shader_program *shProg;
+ struct gl_shader *sh;
+ GLuint i, n;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
+ if (!shProg)
+ return;
+
+ sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
+ if (!sh) {
+ return;
+ }
+
+ n = shProg->NumShaders;
+ for (i = 0; i < n; i++) {
+ if (shProg->Shaders[i] == sh) {
+ /* The shader is already attched to this program. The
+ * GL_ARB_shader_objects spec says:
+ *
+ * "The error INVALID_OPERATION is generated by AttachObjectARB
+ * if <obj> is already attached to <containerObj>."
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
+ return;
+ }
+ }
+
+ /* grow list */
+ shProg->Shaders = (struct gl_shader **)
+ _mesa_realloc(shProg->Shaders,
+ n * sizeof(struct gl_shader *),
+ (n + 1) * sizeof(struct gl_shader *));
+ if (!shProg->Shaders) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
+ return;
+ }
+
+ /* append */
+ shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
+ _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
+ shProg->NumShaders++;
+}
+
+
+static GLint
+_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
+ const GLchar *name)
+{
+ struct gl_shader_program *shProg
+ = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
+
+ if (!shProg) {
+ return -1;
+ }
+
+ if (!shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetAttribLocation(program not linked)");
+ return -1;
+ }
+
+ if (!name)
+ return -1;
+
+ if (shProg->VertexProgram) {
+ const struct gl_program_parameter_list *attribs =
+ shProg->VertexProgram->Base.Attributes;
+ if (attribs) {
+ GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
+ if (i >= 0) {
+ return attribs->Parameters[i].StateIndexes[0];
+ }
+ }
+ }
+ return -1;
+}
+
+
+static void
+_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
+ const GLchar *name)
+{
+ struct gl_shader_program *shProg;
+ const GLint size = -1; /* unknown size */
+ GLint i, oldIndex;
+ GLenum datatype = GL_FLOAT_VEC4;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glBindAttribLocation");
+ if (!shProg) {
+ return;
+ }
+
+ if (!name)
+ return;
+
+ if (strncmp(name, "gl_", 3) == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBindAttribLocation(illegal name)");
+ return;
+ }
+
+ if (index >= ctx->Const.VertexProgram.MaxAttribs) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
+ return;
+ }
+
+ if (shProg->LinkStatus) {
+ /* get current index/location for the attribute */
+ oldIndex = _mesa_get_attrib_location(ctx, program, name);
+ }
+ else {
+ oldIndex = -1;
+ }
+
+ /* this will replace the current value if it's already in the list */
+ i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
+ if (i < 0) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
+ return;
+ }
+
+ /*
+ * Note that this attribute binding won't go into effect until
+ * glLinkProgram is called again.
+ */
+}
+
+
+static GLuint
+_mesa_create_shader(GLcontext *ctx, GLenum type)
+{
+ struct gl_shader *sh;
+ GLuint name;
+
+ name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
+
+ switch (type) {
+ case GL_FRAGMENT_SHADER:
+ case GL_VERTEX_SHADER:
+ sh = _mesa_new_shader(ctx, name, type);
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
+ return 0;
+ }
+
+ _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
+
+ return name;
+}
+
+
+static GLuint
+_mesa_create_program(GLcontext *ctx)
+{
+ GLuint name;
+ struct gl_shader_program *shProg;
+
+ name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
+ shProg = _mesa_new_shader_program(ctx, name);
+
+ _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
+
+ assert(shProg->RefCount == 1);
+
+ return name;
+}
+
+
+/**
+ * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
+ * DeleteProgramARB.
+ */
+static void
+_mesa_delete_program2(GLcontext *ctx, GLuint name)
+{
+ /*
+ * NOTE: deleting shaders/programs works a bit differently than
+ * texture objects (and buffer objects, etc). Shader/program
+ * handles/IDs exist in the hash table until the object is really
+ * deleted (refcount==0). With texture objects, the handle/ID is
+ * removed from the hash table in glDeleteTextures() while the tex
+ * object itself might linger until its refcount goes to zero.
+ */
+ struct gl_shader_program *shProg;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
+ if (!shProg)
+ return;
+
+ shProg->DeletePending = GL_TRUE;
+
+ /* effectively, decr shProg's refcount */
+ _mesa_reference_shader_program(ctx, &shProg, NULL);
+}
+
+
+static void
+_mesa_delete_shader(GLcontext *ctx, GLuint shader)
+{
+ struct gl_shader *sh;
+
+ sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
+ if (!sh)
+ return;
+
+ sh->DeletePending = GL_TRUE;
+
+ /* effectively, decr sh's refcount */
+ _mesa_reference_shader(ctx, &sh, NULL);
+}
+
+
+static void
+_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
+{
+ struct gl_shader_program *shProg;
+ GLuint n;
+ GLuint i, j;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
+ if (!shProg)
+ return;
+
+ n = shProg->NumShaders;
+
+ for (i = 0; i < n; i++) {
+ if (shProg->Shaders[i]->Name == shader) {
+ /* found it */
+ struct gl_shader **newList;
+
+ /* release */
+ _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
+
+ /* alloc new, smaller array */
+ newList = (struct gl_shader **)
+ _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
+ if (!newList) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
+ return;
+ }
+ for (j = 0; j < i; j++) {
+ newList[j] = shProg->Shaders[j];
+ }
+ while (++i < n)
+ newList[j++] = shProg->Shaders[i];
+ _mesa_free(shProg->Shaders);
+
+ shProg->Shaders = newList;
+ shProg->NumShaders = n - 1;
+
+#ifdef DEBUG
+ /* sanity check */
+ {
+ for (j = 0; j < shProg->NumShaders; j++) {
+ assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
+ shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
+ assert(shProg->Shaders[j]->RefCount > 0);
+ }
+ }
+#endif
+
+ return;
+ }
+ }
+
+ /* not found */
+ {
+ GLenum err;
+ if (_mesa_is_shader(ctx, shader))
+ err = GL_INVALID_OPERATION;
+ else if (_mesa_is_program(ctx, shader))
+ err = GL_INVALID_OPERATION;
+ else
+ err = GL_INVALID_VALUE;
+ _mesa_error(ctx, err, "glDetachProgram(shader)");
+ return;
+ }
+}
+
+
+static GLint
+sizeof_glsl_type(GLenum type)
+{
+ switch (type) {
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_BOOL:
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_SHADOW_ARB:
+ case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
+ case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
+ case GL_SAMPLER_CUBE_SHADOW_EXT:
+ return 1;
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ return 2;
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ return 4;
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT2x4:
+ return 8; /* two float[4] vectors */
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT3x2:
+ case GL_FLOAT_MAT3x4:
+ return 12; /* three float[4] vectors */
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT4x2:
+ case GL_FLOAT_MAT4x3:
+ return 16; /* four float[4] vectors */
+ default:
+ _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
+ return 1;
+ }
+}
+
+
+static GLboolean
+is_boolean_type(GLenum type)
+{
+ switch (type) {
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean
+is_integer_type(GLenum type)
+{
+ switch (type) {
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean
+is_sampler_type(GLenum type)
+{
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_SHADOW_ARB:
+ case GL_SAMPLER_1D_ARRAY_EXT:
+ case GL_SAMPLER_2D_ARRAY_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static void
+_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei *length, GLint *size,
+ GLenum *type, GLchar *nameOut)
+{
+ const struct gl_program_parameter_list *attribs = NULL;
+ struct gl_shader_program *shProg;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
+ if (!shProg)
+ return;
+
+ if (shProg->VertexProgram)
+ attribs = shProg->VertexProgram->Base.Attributes;
+
+ if (!attribs || index >= attribs->NumParameters) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
+ return;
+ }
+
+ copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
+
+ if (size)
+ *size = attribs->Parameters[index].Size
+ / sizeof_glsl_type(attribs->Parameters[index].DataType);
+
+ if (type)
+ *type = attribs->Parameters[index].DataType;
+}
+
+
+static struct gl_program_parameter *
+get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
+{
+ const struct gl_program *prog = NULL;
+ GLint progPos;
+
+ progPos = shProg->Uniforms->Uniforms[index].VertPos;
+ if (progPos >= 0) {
+ prog = &shProg->VertexProgram->Base;
+ }
+ else {
+ progPos = shProg->Uniforms->Uniforms[index].FragPos;
+ if (progPos >= 0) {
+ prog = &shProg->FragmentProgram->Base;
+ }
+ }
+
+ if (!prog || progPos < 0)
+ return NULL; /* should never happen */
+
+ return &prog->Parameters->Parameters[progPos];
+}
+
+
+/**
+ * Called via ctx->Driver.GetActiveUniform().
+ */
+static void
+_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei *length, GLint *size,
+ GLenum *type, GLchar *nameOut)
+{
+ const struct gl_shader_program *shProg;
+ const struct gl_program *prog = NULL;
+ const struct gl_program_parameter *param;
+ GLint progPos;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
+ if (!shProg)
+ return;
+
+ if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
+ return;
+ }
+
+ progPos = shProg->Uniforms->Uniforms[index].VertPos;
+ if (progPos >= 0) {
+ prog = &shProg->VertexProgram->Base;
+ }
+ else {
+ progPos = shProg->Uniforms->Uniforms[index].FragPos;
+ if (progPos >= 0) {
+ prog = &shProg->FragmentProgram->Base;
+ }
+ }
+
+ if (!prog || progPos < 0)
+ return; /* should never happen */
+
+ ASSERT(progPos < prog->Parameters->NumParameters);
+ param = &prog->Parameters->Parameters[progPos];
+
+ if (nameOut) {
+ copy_string(nameOut, maxLength, length, param->Name);
+ }
+
+ if (size) {
+ GLint typeSize = sizeof_glsl_type(param->DataType);
+ if (param->Size > typeSize) {
+ /* This is an array.
+ * Array elements are placed on vector[4] boundaries so they're
+ * a multiple of four floats. We round typeSize up to next multiple
+ * of four to get the right size below.
+ */
+ typeSize = (typeSize + 3) & ~3;
+ }
+ /* Note that the returned size is in units of the <type>, not bytes */
+ *size = param->Size / typeSize;
+ }
+
+ if (type) {
+ *type = param->DataType;
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.GetAttachedShaders().
+ */
+static void
+_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
+ GLsizei *count, GLuint *obj)
+{
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
+ if (shProg) {
+ GLuint i;
+ for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
+ obj[i] = shProg->Shaders[i]->Name;
+ }
+ if (count)
+ *count = i;
+ }
+}
+
+
+static GLuint
+_mesa_get_handle(GLcontext *ctx, GLenum pname)
+{
+ GLint handle = 0;
+
+ if (pname == GL_PROGRAM_OBJECT_ARB) {
+ CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
+ } else {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
+ }
+
+ return handle;
+}
+
+
+static void
+_mesa_get_programiv(GLcontext *ctx, GLuint program,
+ GLenum pname, GLint *params)
+{
+ const struct gl_program_parameter_list *attribs;
+ struct gl_shader_program *shProg
+ = _mesa_lookup_shader_program(ctx, program);
+
+ if (!shProg) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
+ return;
+ }
+
+ if (shProg->VertexProgram)
+ attribs = shProg->VertexProgram->Base.Attributes;
+ else
+ attribs = NULL;
+
+ switch (pname) {
+ case GL_DELETE_STATUS:
+ *params = shProg->DeletePending;
+ break;
+ case GL_LINK_STATUS:
+ *params = shProg->LinkStatus;
+ break;
+ case GL_VALIDATE_STATUS:
+ *params = shProg->Validated;
+ break;
+ case GL_INFO_LOG_LENGTH:
+ *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
+ break;
+ case GL_ATTACHED_SHADERS:
+ *params = shProg->NumShaders;
+ break;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = attribs ? attribs->NumParameters : 0;
+ break;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
+ break;
+ case GL_ACTIVE_UNIFORMS:
+ *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
+ break;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = _mesa_longest_uniform_name(shProg->Uniforms);
+ if (*params > 0)
+ (*params)++; /* add one for terminating zero */
+ break;
+ case GL_PROGRAM_BINARY_LENGTH_OES:
+ *params = 0;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
+ return;
+ }
+}
+
+
+static void
+_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
+{
+ struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
+
+ if (!shader) {
+ return;
+ }
+
+ switch (pname) {
+ case GL_SHADER_TYPE:
+ *params = shader->Type;
+ break;
+ case GL_DELETE_STATUS:
+ *params = shader->DeletePending;
+ break;
+ case GL_COMPILE_STATUS:
+ *params = shader->CompileStatus;
+ break;
+ case GL_INFO_LOG_LENGTH:
+ *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
+ break;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
+ return;
+ }
+}
+
+
+static void
+_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog)
+{
+ struct gl_shader_program *shProg
+ = _mesa_lookup_shader_program(ctx, program);
+ if (!shProg) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
+ return;
+ }
+ copy_string(infoLog, bufSize, length, shProg->InfoLog);
+}
+
+
+static void
+_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
+ GLsizei *length, GLchar *infoLog)
+{
+ struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
+ if (!sh) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
+ return;
+ }
+ copy_string(infoLog, bufSize, length, sh->InfoLog);
+}
+
+
+/**
+ * Called via ctx->Driver.GetShaderSource().
+ */
+static void
+_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
+ GLsizei *length, GLchar *sourceOut)
+{
+ struct gl_shader *sh;
+ sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
+ if (!sh) {
+ return;
+ }
+ copy_string(sourceOut, maxLength, length, sh->Source);
+}
+
+
+static void
+get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
+{
+ switch (type) {
+ case GL_FLOAT_MAT2:
+ *rows = *cols = 2;
+ break;
+ case GL_FLOAT_MAT2x3:
+ *rows = 3;
+ *cols = 2;
+ break;
+ case GL_FLOAT_MAT2x4:
+ *rows = 4;
+ *cols = 2;
+ break;
+ case GL_FLOAT_MAT3:
+ *rows = 3;
+ *cols = 3;
+ break;
+ case GL_FLOAT_MAT3x2:
+ *rows = 2;
+ *cols = 3;
+ break;
+ case GL_FLOAT_MAT3x4:
+ *rows = 4;
+ *cols = 3;
+ break;
+ case GL_FLOAT_MAT4:
+ *rows = 4;
+ *cols = 4;
+ break;
+ case GL_FLOAT_MAT4x2:
+ *rows = 2;
+ *cols = 4;
+ break;
+ case GL_FLOAT_MAT4x3:
+ *rows = 3;
+ *cols = 4;
+ break;
+ default:
+ *rows = *cols = 0;
+ }
+}
+
+
+/**
+ * Determine the number of rows and columns occupied by a uniform
+ * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
+ * the number of rows = 1 and cols = number of elements in the vector.
+ */
+static void
+get_uniform_rows_cols(const struct gl_program_parameter *p,
+ GLint *rows, GLint *cols)
+{
+ get_matrix_dims(p->DataType, rows, cols);
+ if (*rows == 0 && *cols == 0) {
+ /* not a matrix type, probably a float or vector */
+ if (p->Size <= 4) {
+ *rows = 1;
+ *cols = p->Size;
+ }
+ else {
+ *rows = p->Size / 4 + 1;
+ if (p->Size % 4 == 0)
+ *cols = 4;
+ else
+ *cols = p->Size % 4;
+ }
+ }
+}
+
+
+/**
+ * Helper for get_uniform[fi]v() functions.
+ * Given a shader program name and uniform location, return a pointer
+ * to the shader program and return the program parameter position.
+ */
+static void
+lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
+ struct gl_program **progOut, GLint *paramPosOut)
+{
+ struct gl_shader_program *shProg
+ = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
+ struct gl_program *prog = NULL;
+ GLint progPos = -1;
+
+ /* if shProg is NULL, we'll have already recorded an error */
+
+ if (shProg) {
+ if (!shProg->Uniforms ||
+ location < 0 ||
+ location >= (GLint) shProg->Uniforms->NumUniforms) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
+ }
+ else {
+ /* OK, find the gl_program and program parameter location */
+ progPos = shProg->Uniforms->Uniforms[location].VertPos;
+ if (progPos >= 0) {
+ prog = &shProg->VertexProgram->Base;
+ }
+ else {
+ progPos = shProg->Uniforms->Uniforms[location].FragPos;
+ if (progPos >= 0) {
+ prog = &shProg->FragmentProgram->Base;
+ }
+ }
+ }
+ }
+
+ *progOut = prog;
+ *paramPosOut = progPos;
+}
+
+
+/**
+ * Called via ctx->Driver.GetUniformfv().
+ */
+static void
+_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
+ GLfloat *params)
+{
+ struct gl_program *prog;
+ GLint paramPos;
+
+ lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
+
+ if (prog) {
+ const struct gl_program_parameter *p =
+ &prog->Parameters->Parameters[paramPos];
+ GLint rows, cols, i, j, k;
+
+ get_uniform_rows_cols(p, &rows, &cols);
+
+ k = 0;
+ for (i = 0; i < rows; i++) {
+ for (j = 0; j < cols; j++ ) {
+ params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
+ }
+ }
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.GetUniformiv().
+ * \sa _mesa_get_uniformfv, only difference is a cast.
+ */
+static void
+_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
+ GLint *params)
+{
+ struct gl_program *prog;
+ GLint paramPos;
+
+ lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
+
+ if (prog) {
+ const struct gl_program_parameter *p =
+ &prog->Parameters->Parameters[paramPos];
+ GLint rows, cols, i, j, k;
+
+ get_uniform_rows_cols(p, &rows, &cols);
+
+ k = 0;
+ for (i = 0; i < rows; i++) {
+ for (j = 0; j < cols; j++ ) {
+ params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
+ }
+ }
+ }
+}
+
+
+/**
+ * The value returned by GetUniformLocation actually encodes two things:
+ * 1. the index into the prog->Uniforms[] array for the uniform
+ * 2. an offset in the prog->ParameterValues[] array for specifying array
+ * elements or structure fields.
+ * This function merges those two values.
+ */
+static void
+merge_location_offset(GLint *location, GLint offset)
+{
+ *location = *location | (offset << 16);
+}
+
+
+/**
+ * Seperate the uniform location and parameter offset. See above.
+ */
+static void
+split_location_offset(GLint *location, GLint *offset)
+{
+ *offset = (*location >> 16);
+ *location = *location & 0xffff;
+}
+
+
+/**
+ * Called via ctx->Driver.GetUniformLocation().
+ *
+ * The return value will encode two values, the uniform location and an
+ * offset (used for arrays, structs).
+ */
+static GLint
+_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
+{
+ GLint offset = 0, location = -1;
+
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
+
+ if (!shProg)
+ return -1;
+
+ if (shProg->LinkStatus == GL_FALSE) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
+ return -1;
+ }
+
+ /* XXX we should return -1 if the uniform was declared, but not
+ * actually used.
+ */
+
+ /* XXX we need to be able to parse uniform names for structs and arrays
+ * such as:
+ * mymatrix[1]
+ * mystruct.field1
+ */
+
+ {
+ /* handle 1-dimension arrays here... */
+ char *c = strchr(name, '[');
+ if (c) {
+ /* truncate name at [ */
+ const GLint len = c - name;
+ GLchar *newName = _mesa_malloc(len + 1);
+ if (!newName)
+ return -1; /* out of mem */
+ _mesa_memcpy(newName, name, len);
+ newName[len] = 0;
+
+ location = _mesa_lookup_uniform(shProg->Uniforms, newName);
+ if (location >= 0) {
+ const GLint element = _mesa_atoi(c + 1);
+ if (element > 0) {
+ /* get type of the uniform array element */
+ struct gl_program_parameter *p;
+ p = get_uniform_parameter(shProg, location);
+ if (p) {
+ GLint rows, cols;
+ get_matrix_dims(p->DataType, &rows, &cols);
+ if (rows < 1)
+ rows = 1;
+ offset = element * rows;
+ }
+ }
+ }
+
+ _mesa_free(newName);
+ }
+ }
+
+ if (location < 0) {
+ location = _mesa_lookup_uniform(shProg->Uniforms, name);
+ }
+
+ if (location >= 0) {
+ merge_location_offset(&location, offset);
+ }
+
+ return location;
+}
+
+
+
+/**
+ * Called via ctx->Driver.ShaderSource()
+ */
+static void
+_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
+{
+ struct gl_shader *sh;
+
+ sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
+ if (!sh)
+ return;
+
+ /* free old shader source string and install new one */
+ if (sh->Source) {
+ _mesa_free((void *) sh->Source);
+ }
+ sh->Source = source;
+ sh->CompileStatus = GL_FALSE;
+#ifdef DEBUG
+ sh->SourceChecksum = _mesa_str_checksum(sh->Source);
+#endif
+}
+
+
+/**
+ * Called via ctx->Driver.CompileShader()
+ */
+static void
+_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
+{
+ struct gl_shader *sh;
+
+ sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
+ if (!sh)
+ return;
+
+ /* set default pragma state for shader */
+ sh->Pragmas = ctx->Shader.DefaultPragmas;
+
+ /* this call will set the sh->CompileStatus field to indicate if
+ * compilation was successful.
+ */
+ (void) _slang_compile(ctx, sh);
+}
+
+
+/**
+ * Called via ctx->Driver.LinkProgram()
+ */
+static void
+_mesa_link_program(GLcontext *ctx, GLuint program)
+{
+ struct gl_shader_program *shProg;
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
+ if (!shProg)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+
+ _slang_link(ctx, program, shProg);
+
+ /* debug code */
+ if (0) {
+ GLuint i;
+
+ _mesa_printf("Link %u shaders in program %u: %s\n",
+ shProg->NumShaders, shProg->Name,
+ shProg->LinkStatus ? "Success" : "Failed");
+
+ for (i = 0; i < shProg->NumShaders; i++) {
+ _mesa_printf(" shader %u, type 0x%x\n",
+ shProg->Shaders[i]->Name,
+ shProg->Shaders[i]->Type);
+ }
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.UseProgram()
+ */
+void
+_mesa_use_program(GLcontext *ctx, GLuint program)
+{
+ struct gl_shader_program *shProg;
+
+ if (ctx->Shader.CurrentProgram &&
+ ctx->Shader.CurrentProgram->Name == program) {
+ /* no-op */
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
+ if (program) {
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
+ if (!shProg) {
+ return;
+ }
+ if (!shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUseProgram(program %u not linked)", program);
+ return;
+ }
+
+ /* debug code */
+ if (0) {
+ GLuint i;
+ _mesa_printf("Use Shader %u\n", shProg->Name);
+ for (i = 0; i < shProg->NumShaders; i++) {
+ _mesa_printf(" shader %u, type 0x%x, checksum %u\n",
+ shProg->Shaders[i]->Name,
+ shProg->Shaders[i]->Type,
+ shProg->Shaders[i]->SourceChecksum);
+ }
+ if (shProg->VertexProgram)
+ printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
+ if (shProg->FragmentProgram)
+ printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
+ }
+ }
+ else {
+ shProg = NULL;
+ }
+
+ _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
+}
+
+
+
+/**
+ * Update the vertex/fragment program's TexturesUsed array.
+ *
+ * This needs to be called after glUniform(set sampler var) is called.
+ * A call to glUniform(samplerVar, value) causes a sampler to point to a
+ * particular texture unit. We know the sampler's texture target
+ * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
+ * set by glUniform() calls.
+ *
+ * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
+ * information to update the prog->TexturesUsed[] values.
+ * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
+ * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
+ * We'll use that info for state validation before rendering.
+ */
+void
+_mesa_update_shader_textures_used(struct gl_program *prog)
+{
+ GLuint s;
+
+ memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
+
+ for (s = 0; s < MAX_SAMPLERS; s++) {
+ if (prog->SamplersUsed & (1 << s)) {
+ GLuint unit = prog->SamplerUnits[s];
+ GLuint tgt = prog->SamplerTargets[s];
+ assert(unit < MAX_TEXTURE_IMAGE_UNITS);
+ assert(tgt < NUM_TEXTURE_TARGETS);
+ prog->TexturesUsed[unit] |= (1 << tgt);
+ }
+ }
+}
+
+
+/**
+ * Check if the type given by userType is allowed to set a uniform of the
+ * target type. Generally, equivalence is required, but setting Boolean
+ * uniforms can be done with glUniformiv or glUniformfv.
+ */
+static GLboolean
+compatible_types(GLenum userType, GLenum targetType)
+{
+ if (userType == targetType)
+ return GL_TRUE;
+
+ if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
+ return GL_TRUE;
+
+ if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
+ userType == GL_INT_VEC2))
+ return GL_TRUE;
+
+ if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
+ userType == GL_INT_VEC3))
+ return GL_TRUE;
+
+ if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
+ userType == GL_INT_VEC4))
+ return GL_TRUE;
+
+ if (is_sampler_type(targetType) && userType == GL_INT)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Set the value of a program's uniform variable.
+ * \param program the program whose uniform to update
+ * \param index the index of the program parameter for the uniform
+ * \param offset additional parameter slot offset (for arrays)
+ * \param type the incoming datatype of 'values'
+ * \param count the number of uniforms to set
+ * \param elems number of elements per uniform (1, 2, 3 or 4)
+ * \param values the new values, of datatype 'type'
+ */
+static void
+set_program_uniform(GLcontext *ctx, struct gl_program *program,
+ GLint index, GLint offset,
+ GLenum type, GLsizei count, GLint elems,
+ const void *values)
+{
+ const struct gl_program_parameter *param =
+ &program->Parameters->Parameters[index];
+
+ assert(offset >= 0);
+ assert(elems >= 1);
+ assert(elems <= 4);
+
+ if (!compatible_types(type, param->DataType)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
+ return;
+ }
+
+ if (index + offset > (GLint) program->Parameters->Size) {
+ /* out of bounds! */
+ return;
+ }
+
+ if (param->Type == PROGRAM_SAMPLER) {
+ /* This controls which texture unit which is used by a sampler */
+ GLboolean changed = GL_FALSE;
+ GLint i;
+
+ /* this should have been caught by the compatible_types() check */
+ ASSERT(type == GL_INT);
+
+ /* loop over number of samplers to change */
+ for (i = 0; i < count; i++) {
+ GLuint sampler =
+ (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
+ GLuint texUnit = ((GLuint *) values)[i];
+
+ /* check that the sampler (tex unit index) is legal */
+ if (texUnit >= ctx->Const.MaxTextureImageUnits) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glUniform1(invalid sampler/tex unit index)");
+ return;
+ }
+
+ /* This maps a sampler to a texture unit: */
+ if (sampler < MAX_SAMPLERS) {
+#if 0
+ _mesa_printf("Set program %p sampler %d '%s' to unit %u\n",
+ program, sampler, param->Name, texUnit);
+#endif
+ if (program->SamplerUnits[sampler] != texUnit) {
+ program->SamplerUnits[sampler] = texUnit;
+ changed = GL_TRUE;
+ }
+ }
+ }
+
+ if (changed) {
+ /* When a sampler's value changes it usually requires rewriting
+ * a GPU program's TEX instructions since there may not be a
+ * sampler->texture lookup table. We signal this with the
+ * ProgramStringNotify() callback.
+ */
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
+ _mesa_update_shader_textures_used(program);
+ ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
+ }
+ }
+ else {
+ /* ordinary uniform variable */
+ const GLboolean isUniformBool = is_boolean_type(param->DataType);
+ const GLboolean areIntValues = is_integer_type(type);
+ const GLint slots = (param->Size + 3) / 4;
+ const GLint typeSize = sizeof_glsl_type(param->DataType);
+ GLsizei k, i;
+
+ if (param->Size > typeSize) {
+ /* an array */
+ /* we'll ignore extra data below */
+ }
+ else {
+ /* non-array: count must be one */
+ if (count != 1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniform(uniform is not an array)");
+ return;
+ }
+ }
+
+ /* loop over number of array elements */
+ for (k = 0; k < count; k++) {
+ GLfloat *uniformVal;
+
+ if (offset + k >= slots) {
+ /* Extra array data is ignored */
+ break;
+ }
+
+ /* uniformVal (the destination) is always float[4] */
+ uniformVal = program->Parameters->ParameterValues[index + offset + k];
+
+ if (areIntValues) {
+ /* convert user's ints to floats */
+ const GLint *iValues = ((const GLint *) values) + k * elems;
+ for (i = 0; i < elems; i++) {
+ uniformVal[i] = (GLfloat) iValues[i];
+ }
+ }
+ else {
+ const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
+ for (i = 0; i < elems; i++) {
+ uniformVal[i] = fValues[i];
+ }
+ }
+
+ /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
+ if (isUniformBool) {
+ for (i = 0; i < elems; i++) {
+ uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Called via ctx->Driver.Uniform().
+ */
+static void
+_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
+ const GLvoid *values, GLenum type)
+{
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ struct gl_uniform *uniform;
+ GLint elems, offset;
+ GLenum basicType;
+
+ if (!shProg || !shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
+ return;
+ }
+
+ if (location == -1)
+ return; /* The standard specifies this as a no-op */
+
+ if (location < -1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
+ return;
+ }
+
+ split_location_offset(&location, &offset);
+
+ if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
+ return;
+ }
+
+ if (count < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
+ return;
+ }
+
+ switch (type) {
+ case GL_FLOAT:
+ basicType = GL_FLOAT;
+ elems = 1;
+ break;
+ case GL_INT:
+ basicType = GL_INT;
+ elems = 1;
+ break;
+ case GL_FLOAT_VEC2:
+ basicType = GL_FLOAT;
+ elems = 2;
+ break;
+ case GL_INT_VEC2:
+ basicType = GL_INT;
+ elems = 2;
+ break;
+ case GL_FLOAT_VEC3:
+ basicType = GL_FLOAT;
+ elems = 3;
+ break;
+ case GL_INT_VEC3:
+ basicType = GL_INT;
+ elems = 3;
+ break;
+ case GL_FLOAT_VEC4:
+ basicType = GL_FLOAT;
+ elems = 4;
+ break;
+ case GL_INT_VEC4:
+ basicType = GL_INT;
+ elems = 4;
+ break;
+ default:
+ _mesa_problem(ctx, "Invalid type in _mesa_uniform");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ uniform = &shProg->Uniforms->Uniforms[location];
+
+ if (ctx->Shader.Flags & GLSL_UNIFORMS) {
+ GLint i;
+ _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
+ shProg->Name, uniform->Name, location);
+ if (basicType == GL_INT) {
+ const GLint *v = (const GLint *) values;
+ for (i = 0; i < count * elems; i++) {
+ _mesa_printf("%d ", v[i]);
+ }
+ }
+ else {
+ const GLfloat *v = (const GLfloat *) values;
+ for (i = 0; i < count * elems; i++) {
+ _mesa_printf("%g ", v[i]);
+ }
+ }
+ _mesa_printf("\n");
+ }
+
+ /* A uniform var may be used by both a vertex shader and a fragment
+ * shader. We may need to update one or both shader's uniform here:
+ */
+ if (shProg->VertexProgram) {
+ /* convert uniform location to program parameter index */
+ GLint index = uniform->VertPos;
+ if (index >= 0) {
+ set_program_uniform(ctx, &shProg->VertexProgram->Base,
+ index, offset, type, count, elems, values);
+ }
+ }
+
+ if (shProg->FragmentProgram) {
+ /* convert uniform location to program parameter index */
+ GLint index = uniform->FragPos;
+ if (index >= 0) {
+ set_program_uniform(ctx, &shProg->FragmentProgram->Base,
+ index, offset, type, count, elems, values);
+ }
+ }
+
+ uniform->Initialized = GL_TRUE;
+}
+
+
+/**
+ * Set a matrix-valued program parameter.
+ */
+static void
+set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
+ GLuint index, GLuint offset,
+ GLuint count, GLuint rows, GLuint cols,
+ GLboolean transpose, const GLfloat *values)
+{
+ GLuint mat, row, col;
+ GLuint dst = index + offset, src = 0;
+ GLint nr, nc;
+
+ /* check that the number of rows, columns is correct */
+ get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
+ if (rows != nr || cols != nc) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniformMatrix(matrix size mismatch)");
+ return;
+ }
+
+ if (index + offset > program->Parameters->Size) {
+ /* out of bounds! */
+ return;
+ }
+
+ /*
+ * Note: the _columns_ of a matrix are stored in program registers, not
+ * the rows. So, the loops below look a little funny.
+ * XXX could optimize this a bit...
+ */
+
+ /* loop over matrices */
+ for (mat = 0; mat < count; mat++) {
+
+ /* each matrix: */
+ for (col = 0; col < cols; col++) {
+ GLfloat *v = program->Parameters->ParameterValues[dst];
+ for (row = 0; row < rows; row++) {
+ if (transpose) {
+ v[row] = values[src + row * cols + col];
+ }
+ else {
+ v[row] = values[src + col * rows + row];
+ }
+ }
+ dst++;
+ }
+
+ src += rows * cols; /* next matrix */
+ }
+}
+
+
+/**
+ * Called by ctx->Driver.UniformMatrix().
+ * Note: cols=2, rows=4 ==> array[2] of vec4
+ */
+static void
+_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
+ GLint location, GLsizei count,
+ GLboolean transpose, const GLfloat *values)
+{
+ struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+ struct gl_uniform *uniform;
+ GLint offset;
+
+ if (!shProg || !shProg->LinkStatus) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glUniformMatrix(program not linked)");
+ return;
+ }
+
+ if (location == -1)
+ return; /* The standard specifies this as a no-op */
+
+ if (location < -1) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
+ return;
+ }
+
+ split_location_offset(&location, &offset);
+
+ if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
+ return;
+ }
+ if (values == NULL) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
+
+ uniform = &shProg->Uniforms->Uniforms[location];
+
+ if (shProg->VertexProgram) {
+ /* convert uniform location to program parameter index */
+ GLint index = uniform->VertPos;
+ if (index >= 0) {
+ set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
+ index, offset,
+ count, rows, cols, transpose, values);
+ }
+ }
+
+ if (shProg->FragmentProgram) {
+ /* convert uniform location to program parameter index */
+ GLint index = uniform->FragPos;
+ if (index >= 0) {
+ set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
+ index, offset,
+ count, rows, cols, transpose, values);
+ }
+ }
+
+ uniform->Initialized = GL_TRUE;
+}
+
+
+/**
+ * Validate a program's samplers.
+ * Specifically, check that there aren't two samplers of different types
+ * pointing to the same texture unit.
+ * \return GL_TRUE if valid, GL_FALSE if invalid
+ */
+static GLboolean
+validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
+{
+ static const char *targetName[] = {
+ "TEXTURE_2D_ARRAY",
+ "TEXTURE_1D_ARRAY",
+ "TEXTURE_CUBE",
+ "TEXTURE_3D",
+ "TEXTURE_RECT",
+ "TEXTURE_2D",
+ "TEXTURE_1D",
+ };
+ GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
+ GLbitfield samplersUsed = prog->SamplersUsed;
+ GLuint i;
+
+ assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
+
+ if (samplersUsed == 0x0)
+ return GL_TRUE;
+
+ for (i = 0; i < Elements(targetUsed); i++)
+ targetUsed[i] = -1;
+
+ /* walk over bits which are set in 'samplers' */
+ while (samplersUsed) {
+ GLuint unit;
+ gl_texture_index target;
+ GLint sampler = _mesa_ffs(samplersUsed) - 1;
+ assert(sampler >= 0);
+ assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
+ unit = prog->SamplerUnits[sampler];
+ target = prog->SamplerTargets[sampler];
+ if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
+ _mesa_snprintf(errMsg, 100,
+ "Texture unit %d is accessed both as %s and %s",
+ unit, targetName[targetUsed[unit]], targetName[target]);
+ return GL_FALSE;
+ }
+ targetUsed[unit] = target;
+ samplersUsed ^= (1 << sampler);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do validation of the given shader program.
+ * \param errMsg returns error message if validation fails.
+ * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
+ */
+GLboolean
+_mesa_validate_shader_program(GLcontext *ctx,
+ const struct gl_shader_program *shProg,
+ char *errMsg)
+{
+ const struct gl_vertex_program *vp = shProg->VertexProgram;
+ const struct gl_fragment_program *fp = shProg->FragmentProgram;
+
+ if (!shProg->LinkStatus) {
+ return GL_FALSE;
+ }
+
+ /* From the GL spec, a program is invalid if any of these are true:
+
+ any two active samplers in the current program object are of
+ different types, but refer to the same texture image unit,
+
+ any active sampler in the current program object refers to a texture
+ image unit where fixed-function fragment processing accesses a
+ texture target that does not match the sampler type, or
+
+ the sum of the number of active samplers in the program and the
+ number of texture image units enabled for fixed-function fragment
+ processing exceeds the combined limit on the total number of texture
+ image units allowed.
+ */
+
+
+ /*
+ * Check: any two active samplers in the current program object are of
+ * different types, but refer to the same texture image unit,
+ */
+ if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+ if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Called via glValidateProgram()
+ */
+static void
+_mesa_validate_program(GLcontext *ctx, GLuint program)
+{
+ struct gl_shader_program *shProg;
+ char errMsg[100];
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
+ if (!shProg) {
+ return;
+ }
+
+ shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
+ if (!shProg->Validated) {
+ /* update info log */
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ }
+ shProg->InfoLog = _mesa_strdup(errMsg);
+ }
+}
+
+
+/**
+ * Plug in Mesa's GLSL functions into the device driver function table.
+ */
+void
+_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
+{
+ driver->AttachShader = _mesa_attach_shader;
+ driver->BindAttribLocation = _mesa_bind_attrib_location;
+ driver->CompileShader = _mesa_compile_shader;
+ driver->CreateProgram = _mesa_create_program;
+ driver->CreateShader = _mesa_create_shader;
+ driver->DeleteProgram2 = _mesa_delete_program2;
+ driver->DeleteShader = _mesa_delete_shader;
+ driver->DetachShader = _mesa_detach_shader;
+ driver->GetActiveAttrib = _mesa_get_active_attrib;
+ driver->GetActiveUniform = _mesa_get_active_uniform;
+ driver->GetAttachedShaders = _mesa_get_attached_shaders;
+ driver->GetAttribLocation = _mesa_get_attrib_location;
+ driver->GetHandle = _mesa_get_handle;
+ driver->GetProgramiv = _mesa_get_programiv;
+ driver->GetProgramInfoLog = _mesa_get_program_info_log;
+ driver->GetShaderiv = _mesa_get_shaderiv;
+ driver->GetShaderInfoLog = _mesa_get_shader_info_log;
+ driver->GetShaderSource = _mesa_get_shader_source;
+ driver->GetUniformfv = _mesa_get_uniformfv;
+ driver->GetUniformiv = _mesa_get_uniformiv;
+ driver->GetUniformLocation = _mesa_get_uniform_location;
+ driver->IsProgram = _mesa_is_program;
+ driver->IsShader = _mesa_is_shader;
+ driver->LinkProgram = _mesa_link_program;
+ driver->ShaderSource = _mesa_shader_source;
+ driver->Uniform = _mesa_uniform;
+ driver->UniformMatrix = _mesa_uniform_matrix;
+ driver->UseProgram = _mesa_use_program;
+ driver->ValidateProgram = _mesa_validate_program;
+}
diff --git a/mesalib/src/mesa/shader/shader_api.h b/mesalib/src/mesa/shader/shader_api.h
new file mode 100644
index 000000000..d08d47373
--- /dev/null
+++ b/mesalib/src/mesa/shader/shader_api.h
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 SHADER_API_H
+#define SHADER_API_H
+
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+
+
+/**
+ * Internal functions
+ */
+
+extern void
+_mesa_init_shader_state(GLcontext * ctx);
+
+extern void
+_mesa_free_shader_state(GLcontext *ctx);
+
+/*
+extern struct gl_shader_program *
+_mesa_new_shader_program(GLcontext *ctx, GLuint name);
+*/
+extern void
+_mesa_clear_shader_program_data(GLcontext *ctx,
+ struct gl_shader_program *shProg);
+
+extern void
+_mesa_free_shader_program_data(GLcontext *ctx,
+ struct gl_shader_program *shProg);
+
+extern void
+_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg);
+
+extern void
+_mesa_reference_shader_program(GLcontext *ctx,
+ struct gl_shader_program **ptr,
+ struct gl_shader_program *shProg);
+
+extern struct gl_shader_program *
+_mesa_lookup_shader_program(GLcontext *ctx, GLuint name);
+
+
+extern struct gl_shader *
+_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
+
+extern void
+_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh);
+
+extern void
+_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh);
+
+extern struct gl_shader *
+_mesa_lookup_shader(GLcontext *ctx, GLuint name);
+
+
+extern void
+_mesa_update_shader_textures_used(struct gl_program *prog);
+
+
+extern void
+_mesa_use_program(GLcontext *ctx, GLuint program);
+
+
+extern GLboolean
+_mesa_validate_shader_program(GLcontext *ctx,
+ const struct gl_shader_program *shProg,
+ char *errMsg);
+
+extern void
+_mesa_init_glsl_driver_functions(struct dd_function_table *driver);
+
+
+#endif /* SHADER_API_H */
diff --git a/mesalib/src/mesa/shader/slang/descrip.mms b/mesalib/src/mesa/shader/slang/descrip.mms
new file mode 100644
index 000000000..6eefbcf5b
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/descrip.mms
@@ -0,0 +1,68 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+ define gl [----.include.gl]
+ define math [--.math]
+ define swrast [--.swrast]
+ define array_cache [--.array_cache]
+ define main [--.main]
+ define glapi [--.glapi]
+ define shader [--.shader]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi],[-.slang],[-.grammar],[-]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = \
+ slang_compile.c,slang_preprocess.c
+
+OBJECTS = slang_builtin.obj,slang_codegen.obj,slang_compile.obj,\
+ slang_compile_function.obj,slang_compile_operation.obj,\
+ slang_compile_struct.obj,slang_compile_variable.obj,slang_emit.obj,\
+ slang_ir.obj,slang_label.obj,slang_library_noise.obj,slang_link.obj,\
+ slang_log.obj,slang_mem.obj,slang_preprocess.obj,slang_print.obj,\
+ slang_simplify.obj,slang_storage.obj,slang_typeinfo.obj,\
+ slang_utility.obj,slang_vartable.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+slang_builtin.obj : slang_builtin.c
+slang_codegen.obj : slang_codegen.c
+slang_compile.obj : slang_compile.c
+slang_compile_function.obj : slang_compile_function.c
+slang_compile_operation.obj : slang_compile_operation.c
+slang_compile_struct.obj : slang_compile_struct.c
+slang_compile_variable.obj : slang_compile_variable.c
+slang_emit.obj : slang_emit.c
+slang_ir.obj : slang_ir.c
+slang_label.obj : slang_label.c
+slang_library_noise.obj : slang_library_noise.c
+slang_link.obj : slang_link.c
+slang_log.obj : slang_log.c
+slang_mem.obj : slang_mem.c
+slang_preprocess.obj : slang_preprocess.c
+slang_print.obj : slang_print.c
+slang_simplify.obj : slang_simplify.c
+slang_storage.obj : slang_storage.c
+slang_typeinfo.obj : slang_typeinfo.c
+slang_utility.obj : slang_utility.c
+slang_vartable.obj : slang_vartable.c
diff --git a/mesalib/src/mesa/shader/slang/library/Makefile b/mesalib/src/mesa/shader/slang/library/Makefile
new file mode 100644
index 000000000..0e03fac2e
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/Makefile
@@ -0,0 +1,81 @@
+# src/mesa/shader/slang/library/Makefile
+
+TOP = ../../../../..
+
+include $(TOP)/configs/current
+
+INCDIR = $(TOP)/include
+
+LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
+
+#
+# targets
+#
+
+.PHONY: default clean
+
+default: syntax builtin
+
+clean:
+ -rm -f syn_to_c gc_to_bin *_syn.h *_gc.h
+
+syntax: slang_pp_directives_syn.h slang_pp_expression_syn.h slang_shader_syn.h slang_pp_version_syn.h
+
+builtin: builtin_110 builtin_120
+
+#
+# executables
+#
+
+syn_to_c: syn_to_c.c
+ $(CC) syn_to_c.c -o syn_to_c
+
+gc_to_bin: gc_to_bin.c slang_shader_syn.h
+ $(CC) gc_to_bin.c -o gc_to_bin
+
+#
+# syntax scripts
+#
+
+slang_pp_directives_syn.h: syn_to_c slang_pp_directives.syn
+ ./syn_to_c slang_pp_directives.syn > slang_pp_directives_syn.h
+
+slang_pp_expression_syn.h: syn_to_c slang_pp_expression.syn
+ ./syn_to_c slang_pp_expression.syn > slang_pp_expression_syn.h
+
+slang_shader_syn.h: syn_to_c slang_shader.syn
+ ./syn_to_c slang_shader.syn > slang_shader_syn.h
+
+slang_pp_version_syn.h: syn_to_c slang_pp_version.syn
+ ./syn_to_c slang_pp_version.syn > slang_pp_version_syn.h
+
+#
+# builtin library sources
+#
+
+builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h
+
+builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h
+
+
+slang_120_core_gc.h: gc_to_bin slang_120_core.gc
+ ./gc_to_bin 1 slang_120_core.gc slang_120_core_gc.h
+
+slang_builtin_120_common_gc.h: gc_to_bin slang_builtin_120_common.gc
+ ./gc_to_bin 1 slang_builtin_120_common.gc slang_builtin_120_common_gc.h
+
+slang_builtin_120_fragment_gc.h: gc_to_bin slang_builtin_120_fragment.gc
+ ./gc_to_bin 1 slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h
+
+slang_common_builtin_gc.h: gc_to_bin slang_common_builtin.gc
+ ./gc_to_bin 1 slang_common_builtin.gc slang_common_builtin_gc.h
+
+slang_core_gc.h: gc_to_bin slang_core.gc
+ ./gc_to_bin 1 slang_core.gc slang_core_gc.h
+
+slang_fragment_builtin_gc.h: gc_to_bin slang_fragment_builtin.gc
+ ./gc_to_bin 1 slang_fragment_builtin.gc slang_fragment_builtin_gc.h
+
+slang_vertex_builtin_gc.h: gc_to_bin slang_vertex_builtin.gc
+ ./gc_to_bin 2 slang_vertex_builtin.gc slang_vertex_builtin_gc.h
+
diff --git a/mesalib/src/mesa/shader/slang/library/gc_to_bin.c b/mesalib/src/mesa/shader/slang/library/gc_to_bin.c
new file mode 100644
index 000000000..8aef7b541
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/gc_to_bin.c
@@ -0,0 +1,85 @@
+#include "../../grammar/grammar_crt.h"
+#include "../../grammar/grammar_crt.c"
+#include <stdlib.h>
+#include <stdio.h>
+
+static const char *slang_shader_syn =
+#include "slang_shader_syn.h"
+;
+
+static int gc_to_bin (grammar id, const char *in, const char *out)
+{
+ FILE *f;
+ byte *source, *prod;
+ unsigned int size, i, line = 0;
+
+ printf ("Precompiling %s\n", in);
+
+ f = fopen (in, "r");
+ if (f == NULL)
+ return 1;
+ fseek (f, 0, SEEK_END);
+ size = ftell (f);
+ fseek (f, 0, SEEK_SET);
+ source = (byte *) grammar_alloc_malloc (size + 1);
+ source[fread (source, 1, size, f)] = '\0';
+ fclose (f);
+
+ if (!grammar_fast_check (id, source, &prod, &size, 65536))
+ {
+ grammar_alloc_free (source);
+ return 1;
+ }
+
+ f = fopen (out, "w");
+ fprintf (f, "\n");
+ fprintf (f, "/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */\n");
+ fprintf (f, "/* %s */\n", in);
+ fprintf (f, "\n");
+ for (i = 0; i < size; i++)
+ {
+ unsigned int a;
+ if (prod[i] < 10)
+ a = 1;
+ else if (prod[i] < 100)
+ a = 2;
+ else
+ a = 3;
+ if (i < size - 1)
+ a++;
+ if (line + a >= 100)
+ {
+ fprintf (f, "\n");
+ line = 0;
+ }
+ line += a;
+ fprintf (f, "%d", prod[i]);
+ if (i < size - 1)
+ fprintf (f, ",");
+ }
+ fprintf (f, "\n");
+ fclose (f);
+ grammar_alloc_free (prod);
+ return 0;
+}
+
+int main (int argc, char *argv[])
+{
+ grammar id;
+
+ id = grammar_load_from_text ((const byte *) slang_shader_syn);
+ if (id == 0) {
+ fprintf(stderr, "Error loading grammar from text\n");
+ return 1;
+ }
+ grammar_set_reg8 (id, (const byte *) "parsing_builtin", 1);
+ grammar_set_reg8 (id, (const byte *) "shader_type", atoi (argv[1]));
+ if (gc_to_bin (id, argv[2], argv[3])) {
+ fprintf(stderr, "Error in gc_to_bin %s %s\n", argv[2], argv[3]);
+ grammar_destroy (id);
+ return 1;
+ }
+ grammar_destroy (id);
+ return 0;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_120_core.gc b/mesalib/src/mesa/shader/slang/library/slang_120_core.gc
new file mode 100644
index 000000000..04c5ec2ec
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_120_core.gc
@@ -0,0 +1,1978 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// Constructors and operators introduced in GLSL 1.20 - mostly on new
+// (non-square) types of matrices.
+//
+// One important change in the language is that when a matrix is used
+// as an argument to a matrix constructor, it must be the only argument
+// for the constructor. The compiler takes care of it by itself and
+// here we only care to re-introduce constructors for old (square)
+// types of matrices.
+//
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+//// mat2x3: 2 columns of vec3
+
+mat2x3 __constructor(const float f00, const float f10, const float f20,
+ const float f01, const float f11, const float f21)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[0].z = f20;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[1].z = f21;
+}
+
+mat2x3 __constructor(const float f)
+{
+ __retVal = mat2x3( f, 0.0, 0.0,
+ 0.0, f, 0.0);
+}
+
+mat2x3 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat2x3(f);
+}
+
+mat2x3 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat2x3(f);
+}
+
+mat2x3 __constructor(const vec3 c0, const vec3 c1)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+}
+
+
+
+//// mat2x4: 2 columns of vec4
+
+mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30,
+ const float f01, const float f11, const float f21, const float f31)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[0].z = f20;
+ __retVal[0].w = f30;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[1].z = f21;
+ __retVal[1].w = f31;
+}
+
+mat2x4 __constructor(const float f)
+{
+ __retVal = mat2x4( f, 0.0, 0.0, 0.0,
+ 0.0, f, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat2x4(f);
+}
+
+mat2x4 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat2x4(f);
+}
+
+mat2x4 __constructor(const vec4 c0, const vec4 c1)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+}
+
+
+
+//// mat3x2: 3 columns of vec2
+
+mat3x2 __constructor(const float f00, const float f10,
+ const float f01, const float f11,
+ const float f02, const float f12)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[2].x = f02;
+ __retVal[2].y = f12;
+}
+
+mat3x2 __constructor(const float f)
+{
+ __retVal = mat3x2( f, 0.0,
+ 0.0, f,
+ 0.0, 0.0);
+}
+
+mat3x2 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat3x2(f);
+}
+
+mat3x2 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat3x2(f);
+}
+
+mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+}
+
+
+
+//// mat3x4: 3 columns of vec4
+
+mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30,
+ const float f01, const float f11, const float f21, const float f31,
+ const float f02, const float f12, const float f22, const float f32)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[0].z = f20;
+ __retVal[0].w = f30;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[1].z = f21;
+ __retVal[1].w = f31;
+ __retVal[2].x = f02;
+ __retVal[2].y = f12;
+ __retVal[2].z = f22;
+ __retVal[2].w = f32;
+}
+
+mat3x4 __constructor(const float f)
+{
+ __retVal = mat3x4( f, 0.0, 0.0, 0.0,
+ 0.0, f, 0.0, 0.0,
+ 0.0, 0.0, f, 0.0);
+}
+
+mat3x4 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat3x4(f);
+}
+
+mat3x4 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat3x4(f);
+}
+
+mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+}
+
+
+
+//// mat4x2: 4 columns of vec2
+
+mat4x2 __constructor(const float f00, const float f10,
+ const float f01, const float f11,
+ const float f02, const float f12,
+ const float f03, const float f13)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[2].x = f02;
+ __retVal[2].y = f12;
+ __retVal[3].x = f03;
+ __retVal[3].y = f13;
+}
+
+mat4x2 __constructor(const float f)
+{
+ __retVal = mat4x2( f, 0.0,
+ 0.0, 4,
+ 0.0, 0.0,
+ 0.0, 0.0);
+}
+
+mat4x2 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat4x2(f);
+}
+
+mat4x2 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat4x2(f);
+}
+
+mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+ __retVal[3] = c3;
+}
+
+
+
+//// mat4x3: 4 columns of vec3
+
+mat4x3 __constructor(const float f00, const float f10, const float f20,
+ const float f01, const float f11, const float f21,
+ const float f02, const float f12, const float f22,
+ const float f03, const float f13, const float f23)
+{
+ __retVal[0].x = f00;
+ __retVal[0].y = f10;
+ __retVal[0].z = f20;
+ __retVal[1].x = f01;
+ __retVal[1].y = f11;
+ __retVal[1].z = f21;
+ __retVal[2].x = f02;
+ __retVal[2].y = f12;
+ __retVal[2].z = f22;
+ __retVal[3].x = f03;
+ __retVal[3].y = f13;
+ __retVal[3].z = f23;
+}
+
+mat4x3 __constructor(const float f)
+{
+ __retVal = mat4x3( f, 0.0, 0.0,
+ 0.0, f, 0.0,
+ 0.0, 0.0, f,
+ 0.0, 0.0, 0.0);
+}
+
+mat4x3 __constructor(const int i)
+{
+ const float f = float(i);
+ __retVal = mat4x3(f);
+}
+
+mat4x3 __constructor(const bool b)
+{
+ const float f = float(b);
+ __retVal = mat4x3(f);
+}
+
+mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+ __retVal[3] = c3;
+}
+
+
+
+//// misc assorted matrix constructors
+
+mat2 __constructor(const mat2 m)
+{
+ __retVal = m;
+}
+
+mat2 __constructor(const mat3x2 m)
+{
+ __retVal = mat2(m[0], m[1]);
+}
+
+mat2 __constructor(const mat4x2 m)
+{
+ __retVal = mat2(m[0], m[1]);
+}
+
+mat2 __constructor(const mat2x3 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat2x4 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat3 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat3x4 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat4x3 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+mat2 __constructor(const mat4 m)
+{
+ __retVal = mat2(m[0].xy, m[1].xy);
+}
+
+
+
+mat2x3 __constructor(const mat2x3 m)
+{
+ __retVal = m;
+}
+
+mat2x3 __constructor(const mat3 m)
+{
+ __retVal = mat2x3(m[0], m[1]);
+}
+
+mat2x3 __constructor(const mat4x3 m)
+{
+ __retVal = mat2x3(m[0], m[1]);
+}
+
+mat2x3 __constructor(const mat2x4 m)
+{
+ __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat3x4 m)
+{
+ __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat4 m)
+{
+ __retVal = mat2x3(m[0].xyz, m[1].xyz);
+}
+
+mat2x3 __constructor(const mat2 m)
+{
+ __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+ m[1].x, m[1].y, 0.0);
+}
+
+mat2x3 __constructor(const mat3x2 m)
+{
+ __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+ m[1].x, m[1].y, 0.0);
+}
+
+mat2x3 __constructor(const mat4x2 m)
+{
+ __retVal = mat2x3(m[0].x, m[0].y, 0.0,
+ m[1].x, m[1].y, 0.0);
+}
+
+
+
+mat2x4 __constructor(const mat2x4 m)
+{
+ __retVal = m;
+}
+
+mat2x4 __constructor(const mat3x4 m)
+{
+ __retVal = mat2x4(m[0], m[1]);
+}
+
+mat2x4 __constructor(const mat4 m)
+{
+ __retVal = mat2x4(m[0], m[1]);
+}
+
+mat2x4 __constructor(const mat2x3 m)
+{
+ __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+ m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat3 m)
+{
+ __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+ m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat4x3 m)
+{
+ __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0,
+ m[1].x, m[1].y, m[1].z, 0.0);
+}
+
+mat2x4 __constructor(const mat2 m)
+{
+ __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0,
+ m[1].x, m[1].y, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const mat3x2 m)
+{
+ __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
+ m[1].x, m[1].y, 0.0, 0.0);
+}
+
+mat2x4 __constructor(const mat4x2 m)
+{
+ __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0,
+ m[1].x, m[1].y, 0.0, 0.0);
+}
+
+
+
+mat3x2 __constructor(const mat3x2 m)
+{
+ __retVal = m;
+}
+
+mat3x2 __constructor(const mat4x2 m)
+{
+ __retVal = mat3x2(m[0], m[1], m[2]);
+}
+
+mat3x2 __constructor(const mat3 m)
+{
+ __retVal = mat3x2(m[0], m[1], m[2]);
+}
+
+mat3x2 __constructor(const mat3x4 m)
+{
+ __retVal = mat3x2(m[0].x, m[0].y,
+ m[1].x, m[1].y,
+ m[2].x, m[2].y);
+}
+
+mat3x2 __constructor(const mat4x3 m)
+{
+ __retVal = mat3x2(m[0].x, m[0].y,
+ m[1].x, m[1].y,
+ m[2].x, m[2].y);
+}
+
+mat3x2 __constructor(const mat4 m)
+{
+ __retVal = mat3x2(m[0].x, m[0].y,
+ m[1].x, m[1].y,
+ 0.0, 0.0);
+}
+
+mat3x2 __constructor(const mat2 m)
+{
+ __retVal = mat3x2(m[0], m[1], vec2(0.0));
+}
+
+mat3x2 __constructor(const mat2x3 m)
+{
+ __retVal = mat3x2(m[0].x, m[0].y,
+ m[1].x, m[1].y,
+ 0.0, 0.0);
+}
+
+mat3x2 __constructor(const mat2x4 m)
+{
+ __retVal = mat3x2(m[0].x, m[0].y,
+ m[1].x, m[1].y,
+ 0.0, 0.0);
+}
+
+
+
+
+mat3 __constructor(const mat3 m)
+{
+ __retVal = m;
+}
+
+mat3 __constructor(const mat4x3 m)
+{
+ __retVal = mat3 (
+ m[0],
+ m[1],
+ m[2]
+ );
+}
+
+mat3 __constructor(const mat3x4 m)
+{
+ __retVal = mat3 (
+ m[0].xyz,
+ m[1].xyz,
+ m[2].xyz
+ );
+}
+
+mat3 __constructor(const mat4 m)
+{
+ __retVal = mat3 (
+ m[0].xyz,
+ m[1].xyz,
+ m[2].xyz
+ );
+}
+
+mat3 __constructor(const mat2x3 m)
+{
+ __retVal = mat3 (
+ m[0],
+ m[1],
+ 0., 0., 1.
+ );
+}
+
+mat3 __constructor(const mat2x4 m)
+{
+ __retVal = mat3 (
+ m[0].xyz,
+ m[1].xyz,
+ 0., 0., 1.
+ );
+}
+
+mat3 __constructor(const mat3x2 m)
+{
+ __retVal = mat3 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 1.
+ );
+}
+
+mat3 __constructor(const mat4x2 m)
+{
+ __retVal = mat3 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 1.
+ );
+}
+
+mat3 __constructor(const mat2 m)
+{
+ __retVal = mat3 (
+ m[0], 0.,
+ m[1], 0.,
+ 0., 0., 1.
+ );
+}
+
+
+mat3x4 __constructor(const mat3x4 m)
+{
+ __retVal = m;
+}
+
+mat3x4 __constructor(const mat4 m)
+{
+ __retVal = mat3x4 (
+ m[0],
+ m[1],
+ m[2]
+ );
+}
+
+mat3x4 __constructor(const mat3 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 0.
+ );
+}
+
+mat3x4 __constructor(const mat4x3 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 0.
+ );
+}
+
+mat3x4 __constructor(const mat2x4 m)
+{
+ __retVal = mat3x4 (
+ m[0],
+ m[1],
+ 0., 0., 1., 0.
+ );
+}
+
+mat3x4 __constructor(const mat2x3 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0.,
+ m[1], 0.,
+ 0., 0., 1., 0.
+ );
+}
+
+mat3x4 __constructor(const mat3x2 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ m[2], 1., 0.
+ );
+}
+
+mat3x4 __constructor(const mat4x2 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ m[2], 1., 0.
+ );
+}
+
+mat3x4 __constructor(const mat2 m)
+{
+ __retVal = mat3x4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ 0., 0., 1., 0.
+ );
+}
+
+
+mat4x2 __constructor(const mat4x2 m)
+{
+ __retVal = m;
+}
+
+mat4x2 __constructor(const mat4x3 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ m[2].xy,
+ m[3].xy
+ );
+}
+
+mat4x2 __constructor(const mat4 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ m[2].xy,
+ m[3].xy
+ );
+}
+
+mat4x2 __constructor(const mat3x2 m)
+{
+ __retVal = mat4x2 (
+ m[0],
+ m[1],
+ 0., 0.
+ );
+}
+
+mat4x2 __constructor(const mat3 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ m[2].xy,
+ 0., 0.
+ );
+}
+
+mat4x2 __constructor(const mat3x4 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ m[2].xy,
+ 0., 0.
+ );
+}
+
+mat4x2 __constructor(const mat2 m)
+{
+ __retVal = mat4x2 (
+ m[0],
+ m[1],
+ 0., 0.,
+ 0., 0.
+ );
+}
+
+mat4x2 __constructor(const mat2x3 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ 0., 0.,
+ 0., 0.
+ );
+}
+
+mat4x2 __constructor(const mat2x4 m)
+{
+ __retVal = mat4x2 (
+ m[0].xy,
+ m[1].xy,
+ 0., 0.,
+ 0., 0.
+ );
+}
+
+
+mat4x3 __constructor(const mat4x3 m)
+{
+ __retVal = m;
+}
+
+mat4x3 __constructor(const mat4 m)
+{
+ __retVal = mat4x3 (
+ m[0].xyz,
+ m[1].xyz,
+ m[2].xyz,
+ m[3].xyz
+ );
+}
+
+mat4x3 __constructor(const mat3 m)
+{
+ __retVal = mat4x3 (
+ m[0],
+ m[1],
+ m[2],
+ 0., 0., 0.
+ );
+}
+
+mat4x3 __constructor(const mat3x4 m)
+{
+ __retVal = mat4x3 (
+ m[0].xyz,
+ m[1].xyz,
+ m[2].xyz,
+ 0., 0., 0.
+ );
+}
+
+mat4x3 __constructor(const mat4x2 m)
+{
+ __retVal = mat4x3 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 1.,
+ m[3], 0.
+ );
+}
+
+mat4x3 __constructor(const mat2x3 m)
+{
+ __retVal = mat4x3 (
+ m[0],
+ m[1],
+ 0., 0., 1.,
+ 0., 0., 0.
+ );
+}
+
+mat4x3 __constructor(const mat3x2 m)
+{
+ __retVal = mat4x3 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 1.,
+ 0., 0., 0.
+ );
+}
+
+mat4x3 __constructor(const mat2x4 m)
+{
+ __retVal = mat4x3 (
+ m[0].xyz,
+ m[1].xyz,
+ 0., 0., 1.,
+ 0., 0., 0.
+ );
+}
+
+mat4x3 __constructor(const mat2 m)
+{
+ __retVal = mat4x3 (
+ m[0], 0.,
+ m[1], 0.,
+ 0., 0., 1.,
+ 0., 0., 0.
+ );
+}
+
+
+mat4 __constructor(const mat4 m)
+{
+ __retVal = m;
+}
+
+mat4 __constructor(const mat3x4 m)
+{
+ __retVal = mat4 (
+ m[0],
+ m[1],
+ m[2],
+ 0., 0., 0., 1.
+ );
+}
+
+mat4 __constructor(const mat4x3 m)
+{
+ __retVal = mat4 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 0.,
+ m[3], 1.
+ );
+}
+
+mat4 __constructor(const mat2x4 m)
+{
+ __retVal = mat4 (
+ m[0],
+ m[1],
+ 0., 0., 1., 0.,
+ 0., 0., 0., 1.
+ );
+}
+
+mat4 __constructor(const mat4x2 m)
+{
+ __retVal = mat4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ m[2], 1., 0.,
+ m[3], 0., 1.
+ );
+}
+
+mat4 __constructor(const mat3 m)
+{
+ __retVal = mat4 (
+ m[0], 0.,
+ m[1], 0.,
+ m[2], 0.,
+ 0., 0., 0., 1.
+ );
+}
+
+mat4 __constructor(const mat2x3 m)
+{
+ __retVal = mat4 (
+ m[0], 0.,
+ m[1], 0.,
+ 0., 0., 1., 0.,
+ 0., 0., 0., 1.
+ );
+}
+
+mat4 __constructor(const mat3x2 m)
+{
+ __retVal = mat4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ m[2], 1., 0.,
+ 0., 0., 0., 1.
+ );
+}
+
+mat4 __constructor(const mat2 m)
+{
+ __retVal = mat4 (
+ m[0], 0., 0.,
+ m[1], 0., 0.,
+ 0., 0., 1., 0.,
+ 0., 0., 0., 1.
+ );
+}
+
+
+void __operator += (inout mat2x3 m, const mat2x3 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+}
+
+void __operator += (inout mat2x4 m, const mat2x4 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+}
+
+void __operator += (inout mat3x2 m, const mat3x2 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+ m[2] += n[2];
+}
+
+void __operator += (inout mat3x4 m, const mat3x4 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+ m[2] += n[2];
+}
+
+void __operator += (inout mat4x2 m, const mat4x2 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+ m[2] += n[2];
+ m[3] += n[3];
+}
+
+void __operator += (inout mat4x3 m, const mat4x3 n) {
+ m[0] += n[0];
+ m[1] += n[1];
+ m[2] += n[2];
+ m[3] += n[3];
+}
+
+
+void __operator -= (inout mat2x3 m, const mat2x3 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+}
+
+void __operator -= (inout mat2x4 m, const mat2x4 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+}
+
+void __operator -= (inout mat3x2 m, const mat3x2 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+ m[2] -= n[2];
+}
+
+void __operator -= (inout mat3x4 m, const mat3x4 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+ m[2] -= n[2];
+}
+
+void __operator -= (inout mat4x2 m, const mat4x2 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+ m[2] -= n[2];
+ m[3] -= n[3];
+}
+
+void __operator -= (inout mat4x3 m, const mat4x3 n) {
+ m[0] -= n[0];
+ m[1] -= n[1];
+ m[2] -= n[2];
+ m[3] -= n[3];
+}
+
+
+void __operator /= (inout mat2x3 m, const mat2x3 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+}
+
+void __operator /= (inout mat2x4 m, const mat2x4 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+}
+
+void __operator /= (inout mat3x2 m, const mat3x2 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+ m[2] /= n[2];
+}
+
+void __operator /= (inout mat3x4 m, const mat3x4 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+ m[2] /= n[2];
+}
+
+void __operator /= (inout mat4x2 m, const mat4x2 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+ m[2] /= n[2];
+ m[3] /= n[3];
+}
+
+void __operator /= (inout mat4x3 m, const mat4x3 n) {
+ m[0] /= n[0];
+ m[1] /= n[1];
+ m[2] /= n[2];
+ m[3] /= n[3];
+}
+
+
+vec3 __operator * (const mat2x3 m, const vec2 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y;
+ __retVal.z = v.x * m[0].z + v.y * m[1].z;
+}
+
+vec4 __operator * (const mat2x4 m, const vec2 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y;
+ __retVal.z = v.x * m[0].z + v.y * m[1].z;
+ __retVal.w = v.x * m[0].w + v.y * m[1].w;
+}
+
+vec2 __operator * (const mat3x2 m, const vec3 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
+}
+
+vec4 __operator * (const mat3x4 m, const vec3 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y;
+ __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z;
+ __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w;
+}
+
+vec2 __operator * (const mat4x2 m, const vec4 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
+}
+
+vec3 __operator * (const mat4x3 m, const vec4 v)
+{
+ __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x;
+ __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y;
+ __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z;
+}
+
+
+mat3x2 __operator * (const mat2 m, const mat3x2 n)
+{
+ //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat2 m, const mat4x2 n)
+{
+ //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat2x3 m, const mat2 n)
+{
+ //return mat2x3 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3 __operator * (const mat2x3 m, const mat3x2 n)
+{
+ //return mat3 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4x3 __operator * (const mat2x3 m, const mat4x2 n)
+{
+ //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat2x4 m, const mat2 n)
+{
+ //return mat2x4 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat2x4 m, const mat3x2 n)
+{
+ //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4 __operator * (const mat2x4 m, const mat4x2 n)
+{
+ //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2 __operator * (const mat3x2 m, const mat2x3 n)
+{
+ //return mat2 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3x2 __operator * (const mat3x2 m, const mat3 n)
+{
+ //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat3x2 m, const mat4x3 n)
+{
+ //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat3 m, const mat2x3 n)
+{
+ //return mat2x3 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat4x3 __operator * (const mat3 m, const mat4x3 n)
+{
+ //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat3x4 m, const mat2x3 n)
+{
+ //return mat2x4 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat3x4 m, const mat3 n)
+{
+ //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4 __operator * (const mat3x4 m, const mat4x3 n)
+{
+ //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2 __operator * (const mat4x2 m, const mat2x4 n)
+{
+ //return = mat2 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3x2 __operator * (const mat4x2 m, const mat3x4 n)
+{
+ //return mat3x2 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4x2 __operator * (const mat4x2 m, const mat4 n)
+{
+ //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x3 __operator * (const mat4x3 m, const mat2x4 n)
+{
+ //return mat2x3 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3 __operator * (const mat4x3 m, const mat3x4 n)
+{
+ //return mat3 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+mat4x3 __operator * (const mat4x3 m, const mat4 n)
+{
+ //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+ __retVal[3] = m * n[3];
+}
+
+
+mat2x4 __operator * (const mat4 m, const mat2x4 n)
+{
+ //return mat2x4 (m * n[0], m * n[1]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+}
+
+mat3x4 __operator * (const mat4 m, const mat3x4 n)
+{
+ //return mat3x4 (m * n[0], m * n[1], m * n[2]);
+ __retVal[0] = m * n[0];
+ __retVal[1] = m * n[1];
+ __retVal[2] = m * n[2];
+}
+
+
+void __operator *= (inout mat2x3 m, const mat2 n) {
+ m = m * n;
+}
+
+void __operator *= (inout mat2x4 m, const mat2 n) {
+ m = m * n;
+}
+
+void __operator *= (inout mat3x2 m, const mat3 n) {
+ m = m * n;
+}
+
+void __operator *= (inout mat3x4 m, const mat3 n) {
+ m = m * n;
+}
+
+void __operator *= (inout mat4x2 m, const mat4 n) {
+ m = m * n;
+}
+
+void __operator *= (inout mat4x3 m, const mat4 n) {
+ m = m * n;
+}
+
+
+vec3 __operator * (const vec2 v, const mat3x2 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+}
+
+vec4 __operator * (const vec2 v, const mat4x2 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+ __retVal.w = dot(v, m[3]);
+}
+
+vec2 __operator * (const vec3 v, const mat2x3 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+}
+
+vec4 __operator * (const vec3 v, const mat4x3 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+ __retVal.w = dot(v, m[3]);
+}
+
+vec2 __operator * (const vec4 v, const mat2x4 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+}
+
+vec3 __operator * (const vec4 v, const mat3x4 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+}
+
+
+void __operator += (inout mat2x3 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+}
+
+void __operator += (inout mat2x4 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+}
+
+void __operator += (inout mat3x2 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+ m[2] += a;
+}
+
+void __operator += (inout mat3x4 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+ m[2] += a;
+}
+
+void __operator += (inout mat4x2 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+ m[2] += a;
+ m[3] += a;
+}
+
+void __operator += (inout mat4x3 m, const float a) {
+ m[0] += a;
+ m[1] += a;
+ m[2] += a;
+ m[3] += a;
+}
+
+
+void __operator -= (inout mat2x3 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+}
+
+void __operator -= (inout mat2x4 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+}
+
+void __operator -= (inout mat3x2 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+ m[2] -= a;
+}
+
+void __operator -= (inout mat3x4 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+ m[2] -= a;
+}
+
+void __operator -= (inout mat4x2 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+ m[2] -= a;
+ m[3] -= a;
+}
+
+void __operator -= (inout mat4x3 m, const float a) {
+ m[0] -= a;
+ m[1] -= a;
+ m[2] -= a;
+ m[3] -= a;
+}
+
+
+void __operator *= (inout mat2x3 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+}
+
+void __operator *= (inout mat2x4 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+}
+
+void __operator *= (inout mat3x2 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+ m[2] *= a;
+}
+
+void __operator *= (inout mat3x4 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+ m[2] *= a;
+}
+
+void __operator *= (inout mat4x2 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+ m[2] *= a;
+ m[3] *= a;
+}
+
+void __operator *= (inout mat4x3 m, const float a) {
+ m[0] *= a;
+ m[1] *= a;
+ m[2] *= a;
+ m[3] *= a;
+}
+
+
+void __operator /= (inout mat2x3 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+}
+
+void __operator /= (inout mat2x4 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+}
+
+void __operator /= (inout mat3x2 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+ m[2] /= a;
+}
+
+void __operator /= (inout mat3x4 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+ m[2] /= a;
+}
+
+void __operator /= (inout mat4x2 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+ m[2] /= a;
+ m[3] /= a;
+}
+
+void __operator /= (inout mat4x3 m, const float a) {
+ m[0] /= a;
+ m[1] /= a;
+ m[2] /= a;
+ m[3] /= a;
+}
+
+
+mat2x3 __operator + (const mat2x3 m, const mat2x3 n) {
+ return mat2x3 (m[0] + n[0], m[1] + n[1]);
+}
+
+mat2x4 __operator + (const mat2x4 m, const mat2x4 n) {
+ return mat2x4 (m[0] + n[0], m[1] + n[1]);
+}
+
+mat3x2 __operator + (const mat3x2 m, const mat3x2 n) {
+ return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
+}
+
+mat3x4 __operator + (const mat3x4 m, const mat3x4 n) {
+ return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]);
+}
+
+mat4x2 __operator + (const mat4x2 m, const mat4x2 n) {
+ return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
+}
+
+mat4x3 __operator + (const mat4x3 m, const mat4x3 n) {
+ return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]);
+}
+
+
+mat2x3 __operator - (const mat2x3 m, const mat2x3 n) {
+ return mat2x3 (m[0] - n[0], m[1] - n[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m, const mat2x4 n) {
+ return mat2x4 (m[0] - n[0], m[1] - n[1]);
+}
+
+mat3x2 __operator - (const mat3x2 m, const mat3x2 n) {
+ return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m, const mat3x4 n) {
+ return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]);
+}
+
+mat4x2 __operator - (const mat4x2 m, const mat4x2 n) {
+ return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m, const mat4x3 n) {
+ return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]);
+}
+
+
+mat2x3 __operator / (const mat2x3 m, const mat2x3 n) {
+ return mat2x3 (m[0] / n[0], m[1] / n[1]);
+}
+
+mat2x4 __operator / (const mat2x4 m, const mat2x4 n) {
+ return mat2x4 (m[0] / n[0], m[1] / n[1]);
+}
+
+mat3x2 __operator / (const mat3x2 m, const mat3x2 n) {
+ return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
+}
+
+mat3x4 __operator / (const mat3x4 m, const mat3x4 n) {
+ return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]);
+}
+
+mat4x2 __operator / (const mat4x2 m, const mat4x2 n) {
+ return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
+}
+
+mat4x3 __operator / (const mat4x3 m, const mat4x3 n) {
+ return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]);
+}
+
+
+mat2x3 __operator + (const float a, const mat2x3 n) {
+ return mat2x3 (a + n[0], a + n[1]);
+}
+
+mat2x3 __operator + (const mat2x3 m, const float b) {
+ return mat2x3 (m[0] + b, m[1] + b);
+}
+
+mat2x4 __operator + (const float a, const mat2x4 n) {
+ return mat2x4 (a + n[0], a + n[1]);
+}
+
+mat2x4 __operator + (const mat2x4 m, const float b) {
+ return mat2x4 (m[0] + b, m[1] + b);
+}
+
+mat3x2 __operator + (const float a, const mat3x2 n) {
+ return mat3x2 (a + n[0], a + n[1], a + n[2]);
+}
+
+mat3x2 __operator + (const mat3x2 m, const float b) {
+ return mat3x2 (m[0] + b, m[1] + b, m[2] + b);
+}
+
+mat3x4 __operator + (const float a, const mat3x4 n) {
+ return mat3x4 (a + n[0], a + n[1], a + n[2]);
+}
+
+mat3x4 __operator + (const mat3x4 m, const float b) {
+ return mat3x4 (m[0] + b, m[1] + b, m[2] + b);
+}
+
+mat4x2 __operator + (const mat4x2 m, const float b) {
+ return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
+}
+
+mat4x2 __operator + (const float a, const mat4x2 n) {
+ return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]);
+}
+
+mat4x3 __operator + (const mat4x3 m, const float b) {
+ return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b);
+}
+
+mat4x3 __operator + (const float a, const mat4x3 n) {
+ return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]);
+}
+
+
+mat2x3 __operator - (const float a, const mat2x3 n) {
+ return mat2x3 (a - n[0], a - n[1]);
+}
+
+mat2x3 __operator - (const mat2x3 m, const float b) {
+ return mat2x3 (m[0] - b, m[1] - b);
+}
+
+mat2x4 __operator - (const float a, const mat2x4 n) {
+ return mat2x4 (a - n[0], a - n[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m, const float b) {
+ return mat2x4 (m[0] - b, m[1] - b);
+}
+
+mat3x2 __operator - (const float a, const mat3x2 n) {
+ return mat3x2 (a - n[0], a - n[1], a - n[2]);
+}
+
+mat3x2 __operator - (const mat3x2 m, const float b) {
+ return mat3x2 (m[0] - b, m[1] - b, m[2] - b);
+}
+
+mat3x4 __operator - (const float a, const mat3x4 n) {
+ return mat3x4 (a - n[0], a - n[1], a - n[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m, const float b) {
+ return mat3x4 (m[0] - b, m[1] - b, m[2] - b);
+}
+
+mat4x2 __operator - (const mat4x2 m, const float b) {
+ return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
+}
+
+mat4x2 __operator - (const float a, const mat4x2 n) {
+ return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m, const float b) {
+ return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b);
+}
+
+mat4x3 __operator - (const float a, const mat4x3 n) {
+ return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]);
+}
+
+
+mat2x3 __operator * (const float a, const mat2x3 n)
+{
+ //return mat2x3 (a * n[0], a * n[1]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+}
+
+mat2x3 __operator * (const mat2x3 m, const float b)
+{
+ //return mat2x3 (m[0] * b, m[1] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+}
+
+mat2x4 __operator * (const float a, const mat2x4 n)
+{
+ //return mat2x4 (a * n[0], a * n[1]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+}
+
+mat2x4 __operator * (const mat2x4 m, const float b)
+{
+ //return mat2x4 (m[0] * b, m[1] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+}
+
+mat3x2 __operator * (const float a, const mat3x2 n)
+{
+ //return mat3x2 (a * n[0], a * n[1], a * n[2]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+}
+
+mat3x2 __operator * (const mat3x2 m, const float b)
+{
+ //return mat3x2 (m[0] * b, m[1] * b, m[2] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+}
+
+mat3x4 __operator * (const float a, const mat3x4 n)
+{
+ //return mat3x4 (a * n[0], a * n[1], a * n[2]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+}
+
+mat3x4 __operator * (const mat3x4 m, const float b)
+{
+ //return mat3x4 (m[0] * b, m[1] * b, m[2] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+}
+
+mat4x2 __operator * (const mat4x2 m, const float b)
+{
+ //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+ __retVal[3] = m[3] * b;
+}
+
+mat4x2 __operator * (const float a, const mat4x2 n)
+{
+ //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+ __retVal[3] = a * n[3];
+}
+
+mat4x3 __operator * (const mat4x3 m, const float b)
+{
+ //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b);
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+ __retVal[3] = m[3] * b;
+}
+
+mat4x3 __operator * (const float a, const mat4x3 n)
+{
+ //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]);
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+ __retVal[3] = a * n[3];
+}
+
+
+mat2x3 __operator / (const float a, const mat2x3 n)
+{
+ //return mat2x3 (a / n[0], a / n[1]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+}
+
+mat2x3 __operator / (const mat2x3 m, const float b)
+{
+ //return mat2x3 (m[0] / b, m[1] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+}
+
+mat2x4 __operator / (const float a, const mat2x4 n)
+{
+ //return mat2x4 (a / n[0], a / n[1]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+}
+
+mat2x4 __operator / (const mat2x4 m, const float b)
+{
+ //return mat2x4 (m[0] / b, m[1] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+}
+
+mat3x2 __operator / (const float a, const mat3x2 n)
+{
+ //return mat3x2 (a / n[0], a / n[1], a / n[2]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+ __retVal[2] = inv * n[2];
+}
+
+mat3x2 __operator / (const mat3x2 m, const float b)
+{
+ //return mat3x2 (m[0] / b, m[1] / b, m[2] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+ __retVal[2] = m[2] * inv;
+}
+
+mat3x4 __operator / (const float a, const mat3x4 n)
+{
+ //return mat3x4 (a / n[0], a / n[1], a / n[2]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+ __retVal[2] = inv * n[2];
+}
+
+mat3x4 __operator / (const mat3x4 m, const float b)
+{
+ //return mat3x4 (m[0] / b, m[1] / b, m[2] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+ __retVal[2] = m[2] * inv;
+}
+
+mat4x2 __operator / (const mat4x2 m, const float b)
+{
+ //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+ __retVal[2] = m[2] * inv;
+ __retVal[3] = m[3] * inv;
+}
+
+mat4x2 __operator / (const float a, const mat4x2 n)
+{
+ //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+ __retVal[2] = inv * n[2];
+ __retVal[3] = inv * n[3];
+}
+
+mat4x3 __operator / (const mat4x3 m, const float b)
+{
+ //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b);
+ const float inv = 1.0 / b;
+ __retVal[0] = m[0] * inv;
+ __retVal[1] = m[1] * inv;
+ __retVal[2] = m[2] * inv;
+ __retVal[3] = m[3] * inv;
+}
+
+mat4x3 __operator / (const float a, const mat4x3 n)
+{
+ //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]);
+ const float inv = 1.0 / a;
+ __retVal[0] = inv * n[0];
+ __retVal[1] = inv * n[1];
+ __retVal[2] = inv * n[2];
+ __retVal[3] = inv * n[3];
+}
+
+
+mat2x3 __operator - (const mat2x3 m) {
+ return mat2x3 (-m[0], -m[1]);
+}
+
+mat2x4 __operator - (const mat2x4 m) {
+ return mat2x4 (-m[0], -m[1]);
+}
+
+mat3x2 __operator - (const mat3x2 m) {
+ return mat3x2 (-m[0], -m[1], -m[2]);
+}
+
+mat3x4 __operator - (const mat3x4 m) {
+ return mat3x4 (-m[0], -m[1], -m[2]);
+}
+
+mat4x2 __operator - (const mat4x2 m) {
+ return mat4x2 (-m[0], -m[1], -m[2], -m[3]);
+}
+
+mat4x3 __operator - (const mat4x3 m) {
+ return mat4x3 (-m[0], -m[1], -m[2], -m[3]);
+}
+
+
+void __operator -- (inout mat2x3 m) {
+ --m[0];
+ --m[1];
+}
+
+void __operator -- (inout mat2x4 m) {
+ --m[0];
+ --m[1];
+}
+
+void __operator -- (inout mat3x2 m) {
+ --m[0];
+ --m[1];
+ --m[2];
+}
+
+void __operator -- (inout mat3x4 m) {
+ --m[0];
+ --m[1];
+ --m[2];
+}
+
+void __operator -- (inout mat4x2 m) {
+ --m[0];
+ --m[1];
+ --m[2];
+ --m[3];
+}
+
+void __operator -- (inout mat4x3 m) {
+ --m[0];
+ --m[1];
+ --m[2];
+ --m[3];
+}
+
+
+void __operator ++ (inout mat2x3 m) {
+ ++m[0];
+ ++m[1];
+}
+
+void __operator ++ (inout mat2x4 m) {
+ ++m[0];
+ ++m[1];
+}
+
+void __operator ++ (inout mat3x2 m) {
+ ++m[0];
+ ++m[1];
+ ++m[2];
+}
+
+void __operator ++ (inout mat3x4 m) {
+ ++m[0];
+ ++m[1];
+ ++m[2];
+}
+
+void __operator ++ (inout mat4x2 m) {
+ ++m[0];
+ ++m[1];
+ ++m[2];
+ ++m[3];
+}
+
+void __operator ++ (inout mat4x3 m) {
+ ++m[0];
+ ++m[1];
+ ++m[2];
+ ++m[3];
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_120_core_gc.h b/mesalib/src/mesa/shader/slang/library/slang_120_core_gc.h
new file mode 100644
index 000000000..1fdbddf7c
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_120_core_gc.h
@@ -0,0 +1,764 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_120_core.gc */
+
+5,1,90,95,0,0,26,0,1,1,1,0,0,9,0,102,48,48,0,0,1,1,0,0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,50,48,0,0,
+1,1,0,0,9,0,102,48,49,0,0,1,1,0,0,9,0,102,49,49,0,0,1,1,0,0,9,0,102,50,49,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,
+18,102,50,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,49,0,20,0,
+9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,59,122,0,18,102,50,49,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,9,0,102,0,
+0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,0,18,102,0,0,17,48,0,48,0,0,0,
+17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,
+5,0,105,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,9,18,95,95,
+114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,
+1,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,9,18,95,95,
+114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,
+11,0,99,48,0,0,1,1,0,0,11,0,99,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,
+0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,
+0,9,0,102,48,48,0,0,1,1,0,0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,50,48,0,0,1,1,0,0,9,0,102,51,48,0,0,
+1,1,0,0,9,0,102,48,49,0,0,1,1,0,0,9,0,102,49,49,0,0,1,1,0,0,9,0,102,50,49,0,0,1,1,0,0,9,0,102,51,
+49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,
+0,16,8,48,0,57,59,122,0,18,102,50,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,119,
+0,18,102,51,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,49,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,59,122,0,18,102,50,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,49,0,57,59,119,0,18,102,51,49,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,
+17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,
+0,28,0,1,1,1,0,0,5,0,105,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,
+0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,102,0,0,0,20,0,0,1,90,95,0,
+0,28,0,1,1,1,0,0,1,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,
+0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,
+28,0,1,1,1,0,0,12,0,99,48,0,0,1,1,0,0,12,0,99,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,
+48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,0,1,90,95,
+0,0,27,0,1,1,1,0,0,9,0,102,48,48,0,0,1,1,0,0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,48,49,0,0,1,1,0,0,9,
+0,102,49,49,0,0,1,1,0,0,9,0,102,48,50,0,0,1,1,0,0,9,0,102,49,50,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,
+59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,
+49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,
+0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,5,0,105,0,0,0,
+1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,9,18,95,95,114,101,116,86,
+97,108,0,58,109,97,116,51,120,50,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,1,0,98,0,0,0,1,
+3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,51,120,50,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,10,0,99,48,0,0,1,
+1,0,0,10,0,99,49,0,0,1,1,0,0,10,0,99,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,9,0,102,48,48,0,0,1,1,0,
+0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,50,48,0,0,1,1,0,0,9,0,102,51,48,0,0,1,1,0,0,9,0,102,48,49,0,0,
+1,1,0,0,9,0,102,49,49,0,0,1,1,0,0,9,0,102,50,49,0,0,1,1,0,0,9,0,102,51,49,0,0,1,1,0,0,9,0,102,48,
+50,0,0,1,1,0,0,9,0,102,49,50,0,0,1,1,0,0,9,0,102,50,50,0,0,1,1,0,0,9,0,102,51,50,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,
+122,0,18,102,50,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,119,0,18,102,51,48,0,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,49,0,57,59,122,0,18,102,50,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,119,
+0,18,102,51,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,59,122,0,18,102,50,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,50,0,57,59,119,0,18,102,51,50,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,
+17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,
+48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,5,0,105,0,0,0,1,3,2,
+90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,51,120,52,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,1,0,98,0,0,0,1,3,
+2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,51,120,52,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,12,0,99,48,0,0,1,
+1,0,0,12,0,99,49,0,0,1,1,0,0,12,0,99,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,9,0,102,48,48,0,0,1,1,0,
+0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,48,49,0,0,1,1,0,0,9,0,102,49,49,0,0,1,1,0,0,9,0,102,48,50,0,0,
+1,1,0,0,9,0,102,49,50,0,0,1,1,0,0,9,0,102,48,51,0,0,1,1,0,0,9,0,102,49,51,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,
+0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,51,0,57,59,120,0,18,102,48,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,121,0,
+18,102,49,51,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,58,109,97,116,52,120,50,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,16,10,52,0,0,17,48,0,48,
+0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,5,0,
+105,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,9,18,95,95,114,
+101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,1,0,
+98,0,0,0,1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,9,18,95,95,114,
+101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,10,
+0,99,48,0,0,1,1,0,0,10,0,99,49,0,0,1,1,0,0,10,0,99,50,0,0,1,1,0,0,10,0,99,51,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,99,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,51,0,57,18,99,51,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,9,0,102,48,48,0,0,1,
+1,0,0,9,0,102,49,48,0,0,1,1,0,0,9,0,102,50,48,0,0,1,1,0,0,9,0,102,48,49,0,0,1,1,0,0,9,0,102,49,49,
+0,0,1,1,0,0,9,0,102,50,49,0,0,1,1,0,0,9,0,102,48,50,0,0,1,1,0,0,9,0,102,49,50,0,0,1,1,0,0,9,0,102,
+50,50,0,0,1,1,0,0,9,0,102,48,51,0,0,1,1,0,0,9,0,102,49,51,0,0,1,1,0,0,9,0,102,50,51,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,
+59,122,0,18,102,50,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,
+49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,59,122,0,18,102,50,49,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,
+59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,122,0,18,102,50,
+50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,120,0,18,102,48,51,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,51,0,57,59,121,0,18,102,49,51,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,51,0,57,59,122,0,18,102,50,51,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,
+0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,
+48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,5,0,105,0,0,0,
+1,3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,9,18,95,95,114,101,116,86,
+97,108,0,58,109,97,116,52,120,51,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,1,0,98,0,0,0,1,
+3,2,90,95,1,0,9,0,1,102,0,2,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,52,120,51,0,0,18,102,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,11,0,99,48,0,0,1,
+1,0,0,11,0,99,49,0,0,1,1,0,0,11,0,99,50,0,0,1,1,0,0,11,0,99,51,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,51,0,57,18,99,51,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,
+90,95,0,0,13,0,1,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,0,
+18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,26,0,109,0,0,
+0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,
+18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,
+10,49,0,57,59,120,121,0,0,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,
+59,120,121,0,0,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,
+0,0,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,
+1,90,95,0,0,13,0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,
+0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,1,90,95,0,0,
+26,0,1,1,1,0,0,26,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,26,
+0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,0,18,109,
+0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,31,0,109,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,
+10,49,0,57,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,
+120,121,122,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,
+59,120,121,122,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,
+57,59,120,121,122,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,
+121,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,
+0,48,0,0,0,0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,
+48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,
+0,20,0,0,1,90,95,0,0,26,0,1,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,
+116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,
+0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,0,20,0,0,1,
+90,95,0,0,28,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,
+95,0,0,28,0,1,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,
+0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,15,0,109,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,0,18,
+109,0,16,10,49,0,57,0,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,26,0,109,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,
+121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,
+0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,122,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,
+28,0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,
+109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,17,
+48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,
+49,0,57,59,122,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,
+16,8,48,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,
+59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,122,0,0,17,48,0,48,0,0,0,0,
+20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,
+116,50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,
+0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,
+48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,
+59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,
+57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,28,0,1,1,1,0,0,29,0,109,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,
+18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,
+0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,0,0,27,0,1,
+1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,27,0,1,1,1,
+0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,0,18,109,0,16,8,
+48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,14,
+0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,
+0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,30,0,109,0,
+0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,59,120,
+0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,
+121,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,121,0,0,0,20,0,0,1,90,95,0,0,
+27,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,0,18,
+109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,120,0,0,
+18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,121,
+0,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,
+10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,
+1,90,95,0,0,27,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,
+120,50,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,58,118,101,99,50,0,0,17,48,0,48,0,0,0,
+0,0,0,20,0,0,1,90,95,0,0,27,0,1,1,1,0,0,26,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,
+10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,
+1,90,95,0,0,27,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,
+120,50,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,
+57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,90,95,
+0,0,14,0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,
+14,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,109,0,
+16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,
+0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,
+59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10,50,0,57,59,120,121,122,
+0,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,51,0,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,
+18,109,0,16,10,50,0,57,59,120,121,122,0,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,26,0,109,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,
+57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,28,0,109,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,
+18,109,0,16,10,49,0,57,59,120,121,122,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,
+95,0,0,14,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,
+109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,
+17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,
+0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,13,0,109,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,
+109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,
+30,0,1,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,30,
+0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,109,
+0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,
+0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,109,0,16,8,
+48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,
+0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,
+18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,
+49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,
+0,0,26,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,109,0,16,8,
+48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,
+0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,58,109,97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,
+16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,0,
+20,0,0,1,90,95,0,0,30,0,1,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,
+116,51,120,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,
+48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,
+30,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,0,18,
+109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,
+0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,29,
+0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,31,0,
+109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,
+59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18,109,0,16,10,50,0,57,59,120,121,0,0,18,109,
+0,16,10,51,0,57,59,120,121,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,
+10,49,0,57,59,120,121,0,0,18,109,0,16,10,50,0,57,59,120,121,0,0,18,109,0,16,10,51,0,57,59,120,121,
+0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,
+0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,
+116,52,120,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18,
+109,0,16,10,50,0,57,59,120,121,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,
+30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,
+57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18,109,0,16,10,50,0,57,59,120,121,0,0,17,
+48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,
+0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,26,0,109,0,0,
+0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,59,120,
+121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,
+0,0,0,20,0,0,1,90,95,0,0,29,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,
+97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,17,
+48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,31,0,109,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,15,0,109,0,0,
+0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,59,120,
+121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10,50,0,57,59,120,121,122,0,0,18,
+109,0,16,10,51,0,57,59,120,121,122,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,14,0,109,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,
+49,0,57,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,
+31,0,1,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,
+109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10,50,
+0,57,59,120,121,122,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,
+0,0,29,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,109,0,16,8,
+48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,
+0,0,18,109,0,16,10,51,0,57,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,26,0,109,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,
+10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,
+20,0,0,1,90,95,0,0,31,0,1,1,1,0,0,27,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,
+116,52,120,51,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,
+109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,
+31,0,1,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,
+109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,17,48,0,0,0,0,17,
+48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,31,0,1,1,1,
+0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,0,18,109,0,16,8,
+48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,
+0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,15,0,109,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,30,0,109,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,
+57,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,
+90,95,0,0,15,0,1,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,
+18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,
+57,0,17,48,0,0,0,0,18,109,0,16,10,51,0,57,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,28,0,
+109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,18,109,
+0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,
+0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,
+18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,
+0,0,0,0,18,109,0,16,10,51,0,57,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,
+14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,
+17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,17,48,
+0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,26,0,109,0,0,
+0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,
+18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,
+48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,27,0,109,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,0,17,48,0,0,
+0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,
+49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,90,95,
+0,0,15,0,1,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,0,18,109,
+0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,
+17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,
+17,49,0,0,0,0,0,20,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,109,
+0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,0,1,
+90,95,0,0,0,0,2,1,1,0,2,0,28,0,109,0,0,1,1,0,0,28,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,
+16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,
+0,27,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,
+109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,
+0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,30,0,109,0,0,1,1,0,0,30,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,
+110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,
+57,18,110,0,16,10,50,0,57,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,29,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,
+9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,
+51,0,57,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,31,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,109,0,16,8,
+48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,
+16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,21,0,0,1,
+90,95,0,0,0,0,2,2,1,0,2,0,26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,
+16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,
+0,28,0,109,0,0,1,1,0,0,28,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,
+109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,27,0,109,0,0,1,1,0,0,
+27,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,
+110,0,16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,0,1,90,95,0,0,0,0,2,
+2,1,0,2,0,30,0,109,0,0,1,1,0,0,30,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,
+9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,
+57,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,29,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,9,18,109,0,16,8,48,0,
+57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,9,18,109,0,16,
+10,50,0,57,18,110,0,16,10,50,0,57,22,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,22,0,0,1,90,
+95,0,0,0,0,2,2,1,0,2,0,31,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,
+48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,
+0,16,10,50,0,57,22,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,22,0,0,1,90,95,0,0,0,0,2,4,1,
+0,2,0,26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,
+18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,28,0,109,0,0,1,1,
+0,0,28,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,
+18,110,0,16,10,49,0,57,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,27,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,9,
+18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+24,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,30,0,109,0,
+0,1,1,0,0,30,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,
+0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,0,1,90,95,0,
+0,0,0,2,4,1,0,2,0,29,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,
+57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0,57,18,110,0,16,
+10,50,0,57,24,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,
+31,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,
+0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,9,
+18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,24,0,0,1,90,95,0,0,11,0,2,21,1,1,0,0,26,0,109,0,0,1,
+1,0,0,10,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18,109,0,16,8,
+48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,
+18,109,0,16,10,49,0,57,59,121,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59,
+120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,20,
+0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,28,0,109,0,0,1,1,0,0,10,0,118,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,59,120,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,
+16,10,49,0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,
+109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,
+0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,
+18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,119,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,
+119,0,48,46,20,0,0,1,90,95,0,0,10,0,2,21,1,1,0,0,27,0,109,0,0,1,1,0,0,11,0,118,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,
+121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,48,
+46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,
+0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,
+57,59,121,0,48,46,20,0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,30,0,109,0,0,1,1,0,0,11,0,118,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,
+0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,
+48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,
+121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,
+50,0,57,59,121,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59,120,0,18,109,0,
+16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,18,118,0,59,122,0,
+18,109,0,16,10,50,0,57,59,122,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,18,118,0,59,
+120,0,18,109,0,16,8,48,0,57,59,119,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,119,0,48,46,18,
+118,0,59,122,0,18,109,0,16,10,50,0,57,59,119,0,48,46,20,0,0,1,90,95,0,0,10,0,2,21,1,1,0,0,29,0,109,
+0,0,1,1,0,0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18,109,
+0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59,122,
+0,18,109,0,16,10,50,0,57,59,120,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,120,0,48,46,20,
+0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,
+18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,
+59,121,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,121,0,48,46,20,0,0,1,90,95,0,0,11,0,2,
+21,1,1,0,0,31,0,109,0,0,1,1,0,0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,
+118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,
+48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,
+0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,
+8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59,122,0,18,
+109,0,16,10,50,0,57,59,121,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,121,0,48,46,20,0,9,
+18,95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,
+118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,
+122,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,122,0,48,46,20,0,0,1,90,95,0,0,27,0,2,21,1,
+1,0,0,13,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,
+0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,
+16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,
+0,57,48,20,0,0,1,90,95,0,0,29,0,2,21,1,1,0,0,13,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,
+0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,26,0,2,21,1,1,0,0,26,0,109,0,0,1,1,0,0,
+13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,
+90,95,0,0,14,0,2,21,1,1,0,0,26,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,
+0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,31,0,2,21,1,1,0,0,26,0,109,0,0,1,1,0,0,29,0,110,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,28,0,2,21,1,1,
+0,0,28,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,
+18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,
+16,10,49,0,57,48,20,0,0,1,90,95,0,0,30,0,2,21,1,1,0,0,28,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,15,0,2,21,1,1,0,0,
+28,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,
+110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,
+10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,
+0,0,1,90,95,0,0,13,0,2,21,1,1,0,0,27,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,27,0,2,21,1,1,0,0,27,0,109,0,0,1,
+1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,
+95,0,0,29,0,2,21,1,1,0,0,27,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,
+0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,
+0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,26,0,2,21,1,1,0,0,14,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,31,0,2,21,
+1,1,0,0,14,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,
+110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,
+10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,
+57,48,20,0,0,1,90,95,0,0,28,0,2,21,1,1,0,0,30,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,30,0,2,21,1,1,0,0,30,
+0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,
+0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,
+0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,
+20,0,0,1,90,95,0,0,15,0,2,21,1,1,0,0,30,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,
+0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,
+109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,13,0,2,21,1,1,0,0,29,0,109,0,0,1,1,0,0,28,0,110,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,
+0,27,0,2,21,1,1,0,0,29,0,109,0,0,1,1,0,0,30,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,
+48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,
+110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,29,0,2,21,1,1,0,0,29,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,26,0,2,21,1,1,0,0,31,0,
+109,0,0,1,1,0,0,28,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,
+16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,
+57,48,20,0,0,1,90,95,0,0,14,0,2,21,1,1,0,0,31,0,109,0,0,1,1,0,0,30,0,110,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,31,0,2,21,1,1,0,0,31,0,109,0,0,
+1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,
+0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,
+95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,
+28,0,2,21,1,1,0,0,15,0,109,0,0,1,1,0,0,28,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,
+0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,30,0,2,21,1,1,0,0,15,0,109,0,0,1,1,0,0,30,0,110,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,0,0,2,
+3,1,0,2,0,26,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,90,95,0,0,
+0,0,2,3,1,0,2,0,28,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,90,
+95,0,0,0,0,2,3,1,0,2,0,27,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,
+0,1,90,95,0,0,0,0,2,3,1,0,2,0,30,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,
+48,20,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,29,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,109,0,18,109,0,18,
+110,0,48,20,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,31,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,109,0,18,
+109,0,18,110,0,48,20,0,0,1,90,95,0,0,11,0,2,21,1,1,0,0,10,0,118,0,0,1,1,0,0,27,0,109,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,
+0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,
+50,0,57,0,0,20,0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,10,0,118,0,0,1,1,0,0,29,0,109,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,50,0,57,
+0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,
+51,0,57,0,0,20,0,0,1,90,95,0,0,10,0,2,21,1,1,0,0,11,0,118,0,0,1,1,0,0,26,0,109,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,
+0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,11,0,118,0,0,1,1,0,0,31,0,109,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,59,122,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,9,
+18,95,95,114,101,116,86,97,108,0,59,119,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,51,0,57,0,0,
+20,0,0,1,90,95,0,0,10,0,2,21,1,1,0,0,12,0,118,0,0,1,1,0,0,28,0,109,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,90,
+95,0,0,11,0,2,21,1,1,0,0,12,0,118,0,0,1,1,0,0,30,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,122,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,
+0,0,0,2,1,1,0,2,0,26,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,
+109,0,16,10,49,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,28,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,
+9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,2,1,1,
+0,2,0,27,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,
+0,57,18,97,0,21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,30,0,109,0,0,
+1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,
+9,18,109,0,16,10,50,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,29,0,109,0,0,1,1,0,0,9,0,97,0,
+0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,9,18,109,0,16,10,
+50,0,57,18,97,0,21,0,9,18,109,0,16,10,51,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,2,1,1,0,2,0,31,0,109,
+0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,
+21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,9,18,109,0,16,10,51,0,57,18,97,0,21,0,0,1,90,95,0,0,0,0,
+2,2,1,0,2,0,26,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,
+10,49,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,28,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,
+0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,27,
+0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,
+97,0,22,0,9,18,109,0,16,10,50,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,30,0,109,0,0,1,1,0,0,
+9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9,18,109,
+0,16,10,50,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,29,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,
+18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9,18,109,0,16,10,50,0,57,
+18,97,0,22,0,9,18,109,0,16,10,51,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,2,1,0,2,0,31,0,109,0,0,1,1,
+0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9,18,
+109,0,16,10,50,0,57,18,97,0,22,0,9,18,109,0,16,10,51,0,57,18,97,0,22,0,0,1,90,95,0,0,0,0,2,3,1,0,2,
+0,26,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,
+57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,28,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,
+48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,27,0,109,
+0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,
+23,0,9,18,109,0,16,10,50,0,57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,30,0,109,0,0,1,1,0,0,9,0,
+97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,
+16,10,50,0,57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,29,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,
+109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,16,10,50,0,57,18,
+97,0,23,0,9,18,109,0,16,10,51,0,57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,3,1,0,2,0,31,0,109,0,0,1,1,0,0,
+9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,
+0,16,10,50,0,57,18,97,0,23,0,9,18,109,0,16,10,51,0,57,18,97,0,23,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,
+26,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,
+18,97,0,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,28,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,
+0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,27,0,109,0,0,
+1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,
+9,18,109,0,16,10,50,0,57,18,97,0,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,30,0,109,0,0,1,1,0,0,9,0,97,0,
+0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,
+50,0,57,18,97,0,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,29,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,109,0,
+16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0,
+24,0,9,18,109,0,16,10,51,0,57,18,97,0,24,0,0,1,90,95,0,0,0,0,2,4,1,0,2,0,31,0,109,0,0,1,1,0,0,9,0,
+97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,
+16,10,50,0,57,18,97,0,24,0,9,18,109,0,16,10,51,0,57,18,97,0,24,0,0,1,90,95,0,0,26,0,2,26,1,1,0,0,
+26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,
+16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,0,0,0,1,90,95,0,0,28,0,2,26,1,
+1,0,0,28,0,109,0,0,1,1,0,0,28,0,110,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,18,
+110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,0,0,0,1,90,95,0,0,27,0,
+2,26,1,1,0,0,27,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,
+0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,
+50,0,57,18,110,0,16,10,50,0,57,46,0,0,0,0,1,90,95,0,0,30,0,2,26,1,1,0,0,30,0,109,0,0,1,1,0,0,30,0,
+110,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,
+0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,0,0,
+0,1,90,95,0,0,29,0,2,26,1,1,0,0,29,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,8,58,109,97,116,52,120,50,0,
+0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,
+57,46,0,0,0,0,1,90,95,0,0,31,0,2,26,1,1,0,0,31,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,8,58,109,97,116,
+52,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,
+10,49,0,57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,18,109,0,16,10,51,0,57,18,110,0,
+16,10,51,0,57,46,0,0,0,0,1,90,95,0,0,26,0,2,27,1,1,0,0,26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,8,58,
+109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,
+18,110,0,16,10,49,0,57,47,0,0,0,0,1,90,95,0,0,28,0,2,27,1,1,0,0,28,0,109,0,0,1,1,0,0,28,0,110,0,0,
+0,1,8,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,
+49,0,57,18,110,0,16,10,49,0,57,47,0,0,0,0,1,90,95,0,0,27,0,2,27,1,1,0,0,27,0,109,0,0,1,1,0,0,27,0,
+110,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,
+0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0,0,0,
+0,1,90,95,0,0,30,0,2,27,1,1,0,0,30,0,109,0,0,1,1,0,0,30,0,110,0,0,0,1,8,58,109,97,116,51,120,52,0,
+0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0,0,0,0,1,90,95,0,0,29,0,2,27,1,1,0,0,29,0,
+109,0,0,1,1,0,0,29,0,110,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,
+48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,
+10,50,0,57,47,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,47,0,0,0,0,1,90,95,0,0,31,0,2,27,1,1,
+0,0,31,0,109,0,0,1,1,0,0,31,0,110,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,18,
+110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,
+18,110,0,16,10,50,0,57,47,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,47,0,0,0,0,1,90,95,0,0,
+26,0,2,22,1,1,0,0,26,0,109,0,0,1,1,0,0,26,0,110,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,
+8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,0,0,0,1,90,
+95,0,0,28,0,2,22,1,1,0,0,28,0,109,0,0,1,1,0,0,28,0,110,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,
+109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,0,
+0,0,1,90,95,0,0,27,0,2,22,1,1,0,0,27,0,109,0,0,1,1,0,0,27,0,110,0,0,0,1,8,58,109,97,116,51,120,50,
+0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,0,0,0,1,90,95,0,0,30,0,2,22,1,1,0,0,30,0,
+109,0,0,1,1,0,0,30,0,110,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,
+48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,
+10,50,0,57,49,0,0,0,0,1,90,95,0,0,29,0,2,22,1,1,0,0,29,0,109,0,0,1,1,0,0,29,0,110,0,0,0,1,8,58,109,
+97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,
+110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,18,109,0,16,10,51,0,57,
+18,110,0,16,10,51,0,57,49,0,0,0,0,1,90,95,0,0,31,0,2,22,1,1,0,0,31,0,109,0,0,1,1,0,0,31,0,110,0,0,
+0,1,8,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,
+49,0,57,18,110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,18,109,0,16,
+10,51,0,57,18,110,0,16,10,51,0,57,49,0,0,0,0,1,90,95,0,0,26,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,26,0,
+110,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,
+10,49,0,57,46,0,0,0,0,1,90,95,0,0,26,0,2,26,1,1,0,0,26,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,
+97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,0,0,0,
+1,90,95,0,0,28,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,28,0,110,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,
+97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,0,0,0,1,90,95,0,0,28,0,2,26,1,
+1,0,0,28,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,18,
+98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,0,0,0,1,90,95,0,0,27,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,
+0,27,0,110,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,
+0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,0,0,0,1,90,95,0,0,27,0,2,26,1,1,0,0,27,0,
+109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,
+109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0,0,0,0,1,90,95,0,0,30,0,2,26,1,
+1,0,0,9,0,97,0,0,1,1,0,0,30,0,110,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,97,0,18,110,0,16,8,48,0,
+57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,0,0,0,1,90,95,0,0,
+30,0,2,26,1,1,0,0,30,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,109,0,16,8,
+48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0,0,0,0,
+1,90,95,0,0,29,0,2,26,1,1,0,0,29,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,
+109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,
+46,0,18,109,0,16,10,51,0,57,18,98,0,46,0,0,0,0,1,90,95,0,0,29,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,29,
+0,110,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,
+10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,18,97,0,18,110,0,16,10,51,0,57,46,0,0,0,0,1,90,
+95,0,0,31,0,2,26,1,1,0,0,31,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,109,
+0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,
+0,18,109,0,16,10,51,0,57,18,98,0,46,0,0,0,0,1,90,95,0,0,31,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,31,0,
+110,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,
+10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,18,97,0,18,110,0,16,10,51,0,57,46,0,0,0,0,1,90,
+95,0,0,26,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,26,0,110,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,97,0,
+18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,0,0,0,1,90,95,0,0,26,0,2,27,1,1,0,0,
+26,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,18,98,0,47,
+0,18,109,0,16,10,49,0,57,18,98,0,47,0,0,0,0,1,90,95,0,0,28,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,28,0,
+110,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,
+10,49,0,57,47,0,0,0,0,1,90,95,0,0,28,0,2,27,1,1,0,0,28,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,
+97,116,50,120,52,0,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,0,0,0,
+1,90,95,0,0,27,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,27,0,110,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,
+97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,
+47,0,0,0,0,1,90,95,0,0,27,0,2,27,1,1,0,0,27,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,8,58,109,97,116,51,
+120,50,0,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,
+50,0,57,18,98,0,47,0,0,0,0,1,90,95,0,0,30,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,30,0,110,0,0,0,1,8,58,
+109,97,116,51,120,52,0,0,18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,
+97,0,18,110,0,16,10,50,0,57,47,0,0,0,0,1,90,95,0,0,30,0,2,27,1,1,0,0,30,0,109,0,0,1,1,0,0,9,0,98,0,
+0,0,1,8,58,109,97,116,51,120,52,0,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,
+98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,0,0,0,1,90,95,0,0,29,0,2,27,1,1,0,0,29,0,109,0,0,1,1,
+0,0,9,0,98,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,
+49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,18,109,0,16,10,51,0,57,18,98,0,47,0,0,0,0,
+1,90,95,0,0,29,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,29,0,110,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,
+97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,
+47,0,18,97,0,18,110,0,16,10,51,0,57,47,0,0,0,0,1,90,95,0,0,31,0,2,27,1,1,0,0,31,0,109,0,0,1,1,0,0,
+9,0,98,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,
+0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,18,109,0,16,10,51,0,57,18,98,0,47,0,0,0,0,1,
+90,95,0,0,31,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,31,0,110,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,
+97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,
+47,0,18,97,0,18,110,0,16,10,51,0,57,47,0,0,0,0,1,90,95,0,0,26,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,26,
+0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,
+95,0,0,26,0,2,21,1,1,0,0,26,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,
+8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,
+18,109,0,16,10,49,0,57,18,98,0,48,20,0,0,1,90,95,0,0,28,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,28,0,110,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,
+95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,
+28,0,2,21,1,1,0,0,28,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,
+57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,
+16,10,49,0,57,18,98,0,48,20,0,0,1,90,95,0,0,27,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,27,0,110,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,27,0,2,21,1,1,0,
+0,27,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,
+8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,
+18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,
+20,0,0,1,90,95,0,0,30,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,30,0,110,0,0,0,1,9,18,95,95,114,101,116,86,
+97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,
+18,97,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,30,0,2,21,1,1,0,0,30,0,109,0,0,1,1,0,0,9,0,98,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,
+95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,20,0,0,1,90,95,0,0,29,0,2,21,1,
+1,0,0,29,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,
+16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,
+57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,
+48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,98,0,48,20,0,0,
+1,90,95,0,0,29,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,29,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,
+18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0,
+16,10,51,0,57,48,20,0,0,1,90,95,0,0,31,0,2,21,1,1,0,0,31,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,51,0,57,18,109,0,16,10,51,0,57,18,98,0,48,20,0,0,1,90,95,0,0,31,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,
+0,31,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,
+48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,26,0,2,
+22,1,1,0,0,9,0,97,0,0,1,1,0,0,26,0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,
+18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,105,110,118,0,18,110,0,16,10,49,0,
+57,48,20,0,0,1,90,95,0,0,26,0,2,22,1,1,0,0,26,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,
+105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,0,1,90,95,0,0,28,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,28,
+0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,
+116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,49,0,57,18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,28,0,2,22,
+1,1,0,0,28,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,18,
+98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,
+48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,
+48,20,0,0,1,90,95,0,0,27,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,27,0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,
+105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,27,0,2,22,1,1,0,0,27,0,109,0,0,1,1,0,0,
+9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,0,1,90,95,0,0,30,0,2,
+22,1,1,0,0,9,0,97,0,0,1,1,0,0,30,0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,
+18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,105,110,118,0,18,110,0,16,10,49,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,105,110,118,0,18,110,0,16,10,50,0,
+57,48,20,0,0,1,90,95,0,0,30,0,2,22,1,1,0,0,30,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,
+105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,0,1,90,95,0,0,29,0,2,22,1,1,0,0,29,0,109,0,0,1,1,0,0,
+9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,105,110,118,0,48,20,0,0,1,90,95,0,0,29,0,2,
+22,1,1,0,0,9,0,97,0,0,1,1,0,0,29,0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,
+18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,105,110,118,0,18,110,0,16,10,49,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,105,110,118,0,18,110,0,16,10,50,0,
+57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,105,110,118,0,18,110,0,16,10,51,0,
+57,48,20,0,0,1,90,95,0,0,31,0,2,22,1,1,0,0,31,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,1,0,9,0,1,
+105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,
+109,0,16,10,51,0,57,18,105,110,118,0,48,20,0,0,1,90,95,0,0,31,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,31,
+0,110,0,0,0,1,3,2,90,95,1,0,9,0,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,
+116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,49,0,57,18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,50,0,57,18,105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,51,0,57,18,105,110,118,0,18,110,0,16,10,51,0,57,48,20,0,0,1,90,95,0,0,26,0,2,27,
+1,1,0,0,26,0,109,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,
+49,0,57,54,0,0,0,0,1,90,95,0,0,28,0,2,27,1,1,0,0,28,0,109,0,0,0,1,8,58,109,97,116,50,120,52,0,0,18,
+109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,0,0,0,1,90,95,0,0,27,0,2,27,1,1,0,0,27,0,109,0,
+0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,18,109,
+0,16,10,50,0,57,54,0,0,0,0,1,90,95,0,0,30,0,2,27,1,1,0,0,30,0,109,0,0,0,1,8,58,109,97,116,51,120,
+52,0,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,0,0,0,1,
+90,95,0,0,29,0,2,27,1,1,0,0,29,0,109,0,0,0,1,8,58,109,97,116,52,120,50,0,0,18,109,0,16,8,48,0,57,
+54,0,18,109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,18,109,0,16,10,51,0,57,54,0,0,0,0,1,
+90,95,0,0,31,0,2,27,1,1,0,0,31,0,109,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,
+54,0,18,109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,18,109,0,16,10,51,0,57,54,0,0,0,0,1,
+90,95,0,0,0,0,2,25,1,0,2,0,26,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,
+52,0,0,1,90,95,0,0,0,0,2,25,1,0,2,0,28,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,
+49,0,57,52,0,0,1,90,95,0,0,0,0,2,25,1,0,2,0,27,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,
+0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,0,1,90,95,0,0,0,0,2,25,1,0,2,0,30,0,109,0,0,0,1,
+9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,0,1,90,95,
+0,0,0,0,2,25,1,0,2,0,29,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,
+18,109,0,16,10,50,0,57,52,0,9,18,109,0,16,10,51,0,57,52,0,0,1,90,95,0,0,0,0,2,25,1,0,2,0,31,0,109,
+0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,9,
+18,109,0,16,10,51,0,57,52,0,0,1,90,95,0,0,0,0,2,24,1,0,2,0,26,0,109,0,0,0,1,9,18,109,0,16,8,48,0,
+57,51,0,9,18,109,0,16,10,49,0,57,51,0,0,1,90,95,0,0,0,0,2,24,1,0,2,0,28,0,109,0,0,0,1,9,18,109,0,
+16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,0,1,90,95,0,0,0,0,2,24,1,0,2,0,27,0,109,0,0,0,1,9,
+18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,18,109,0,16,10,50,0,57,51,0,0,1,90,95,0,
+0,0,0,2,24,1,0,2,0,30,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,
+18,109,0,16,10,50,0,57,51,0,0,1,90,95,0,0,0,0,2,24,1,0,2,0,29,0,109,0,0,0,1,9,18,109,0,16,8,48,0,
+57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,18,109,0,16,10,50,0,57,51,0,9,18,109,0,16,10,51,0,57,51,0,
+0,1,90,95,0,0,0,0,2,24,1,0,2,0,31,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,
+57,51,0,9,18,109,0,16,10,50,0,57,51,0,9,18,109,0,16,10,51,0,57,51,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common.gc b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common.gc
new file mode 100644
index 000000000..c6264c3b4
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common.gc
@@ -0,0 +1,200 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+//
+// 8.5 Matrix Functions
+//
+
+mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) {
+ return mat2x3 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) {
+ return mat2x4 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) {
+ return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) {
+ return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) {
+ return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) {
+ return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+mat2 outerProduct (vec2 c, vec2 r) {
+ return mat2 (
+ c.x * r.x, c.y * r.x,
+ c.x * r.y, c.y * r.y
+ );
+}
+
+mat3 outerProduct (vec3 c, vec3 r) {
+ return mat3 (
+ c.x * r.x, c.y * r.x, c.z * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y,
+ c.x * r.z, c.y * r.z, c.z * r.z
+ );
+}
+
+mat4 outerProduct (vec4 c, vec4 r) {
+ return mat4 (
+ c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
+ c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z,
+ c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w
+ );
+}
+
+mat2x3 outerProduct (vec3 c, vec2 r) {
+ return mat2x3 (
+ c.x * r.x, c.y * r.x, c.z * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y
+ );
+}
+
+mat3x2 outerProduct (vec2 c, vec3 r) {
+ return mat3x2 (
+ c.x * r.x, c.y * r.x,
+ c.x * r.y, c.y * r.y,
+ c.x * r.z, c.y * r.z
+ );
+}
+
+mat2x4 outerProduct (vec4 c, vec2 r) {
+ return mat2x4 (
+ c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y
+ );
+}
+
+mat4x2 outerProduct (vec2 c, vec4 r) {
+ return mat4x2 (
+ c.x * r.x, c.y * r.x,
+ c.x * r.y, c.y * r.y,
+ c.x * r.z, c.y * r.z,
+ c.x * r.w, c.y * r.w
+ );
+}
+
+mat3x4 outerProduct (vec4 c, vec3 r) {
+ return mat3x4 (
+ c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y,
+ c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z
+ );
+}
+
+mat4x3 outerProduct (vec3 c, vec4 r) {
+ return mat4x3 (
+ c.x * r.x, c.y * r.x, c.z * r.x,
+ c.x * r.y, c.y * r.y, c.z * r.y,
+ c.x * r.z, c.y * r.z, c.z * r.z,
+ c.x * r.w, c.y * r.w, c.z * r.w
+ );
+}
+
+mat2 transpose (mat2 m) {
+ return mat2 (
+ m[0].x, m[1].x,
+ m[0].y, m[1].y
+ );
+}
+
+mat3 transpose (mat3 m) {
+ return mat3 (
+ m[0].x, m[1].x, m[2].x,
+ m[0].y, m[1].y, m[2].y,
+ m[0].z, m[1].z, m[2].z
+ );
+}
+
+mat4 transpose (mat4 m) {
+ return mat4 (
+ m[0].x, m[1].x, m[2].x, m[3].x,
+ m[0].y, m[1].y, m[2].y, m[3].y,
+ m[0].z, m[1].z, m[2].z, m[3].z,
+ m[0].w, m[1].w, m[2].w, m[3].w
+ );
+}
+
+mat2x3 transpose (mat3x2 m) {
+ return mat2x3 (
+ m[0].x, m[1].x, m[2].x,
+ m[0].y, m[1].y, m[2].y
+ );
+}
+
+mat3x2 transpose (mat2x3 m) {
+ return mat3x2 (
+ m[0].x, m[1].x,
+ m[0].y, m[1].y,
+ m[0].z, m[1].z
+ );
+}
+
+mat2x4 transpose (mat4x2 m) {
+ return mat2x4 (
+ m[0].x, m[1].x, m[2].x, m[3].x,
+ m[0].y, m[1].y, m[2].y, m[3].y
+ );
+}
+
+mat4x2 transpose (mat2x4 m) {
+ return mat4x2 (
+ m[0].x, m[1].x,
+ m[0].y, m[1].y,
+ m[0].z, m[1].z,
+ m[0].w, m[1].w
+ );
+}
+
+mat3x4 transpose (mat4x3 m) {
+ return mat3x4 (
+ m[0].x, m[1].x, m[2].x, m[3].x,
+ m[0].y, m[1].y, m[2].y, m[3].y,
+ m[0].z, m[1].z, m[2].z, m[3].z
+ );
+}
+
+mat4x3 transpose (mat3x4 m) {
+ return mat4x3 (
+ m[0].x, m[1].x, m[2].x,
+ m[0].y, m[1].y, m[2].y,
+ m[0].z, m[1].z, m[2].z,
+ m[0].w, m[1].w, m[2].w
+ );
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h
new file mode 100644
index 000000000..c397b9f0f
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h
@@ -0,0 +1,108 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_builtin_120_common.gc */
+
+5,1,90,95,0,0,26,0,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,0,26,0,109,0,0,1,
+0,0,0,26,0,110,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,
+48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,0,0,0,1,90,95,0,0,28,0,0,109,97,116,114,
+105,120,67,111,109,112,77,117,108,116,0,1,0,0,0,28,0,109,0,0,1,0,0,0,28,0,110,0,0,0,1,8,58,109,97,
+116,50,120,52,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,
+16,10,49,0,57,48,0,0,0,0,1,90,95,0,0,27,0,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,
+1,0,0,0,27,0,109,0,0,1,0,0,0,27,0,110,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,16,8,48,0,57,
+18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,
+57,18,110,0,16,10,50,0,57,48,0,0,0,0,1,90,95,0,0,30,0,0,109,97,116,114,105,120,67,111,109,112,77,
+117,108,116,0,1,0,0,0,30,0,109,0,0,1,0,0,0,30,0,110,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,109,0,
+16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,
+0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,0,0,0,1,90,95,0,0,29,0,0,109,97,116,114,105,120,67,111,
+109,112,77,117,108,116,0,1,0,0,0,29,0,109,0,0,1,0,0,0,29,0,110,0,0,0,1,8,58,109,97,116,52,120,50,0,
+0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,
+48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,
+57,48,0,0,0,0,1,90,95,0,0,31,0,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,0,31,
+0,109,0,0,1,0,0,0,31,0,110,0,0,0,1,8,58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,18,110,0,16,
+8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,
+16,10,50,0,57,48,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,48,0,0,0,0,1,90,95,0,0,13,0,0,111,
+117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,10,0,99,0,0,1,0,0,0,10,0,114,0,0,0,1,8,58,109,
+97,116,50,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,
+99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,0,0,0,1,90,95,0,0,14,
+0,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,11,0,99,0,0,1,0,0,0,11,0,114,0,0,0,1,8,
+58,109,97,116,51,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,
+0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,
+18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,
+48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0,48,0,0,0,0,1,90,95,
+0,0,15,0,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,12,0,99,0,0,1,0,0,0,12,0,114,0,
+0,0,1,8,58,109,97,116,52,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,
+120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,119,0,18,114,0,59,120,0,48,0,18,99,0,
+59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,
+59,121,0,48,0,18,99,0,59,119,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,48,0,18,
+99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0,48,0,18,99,0,59,119,0,18,
+114,0,59,122,0,48,0,18,99,0,59,120,0,18,114,0,59,119,0,48,0,18,99,0,59,121,0,18,114,0,59,119,0,48,
+0,18,99,0,59,122,0,18,114,0,59,119,0,48,0,18,99,0,59,119,0,18,114,0,59,119,0,48,0,0,0,0,1,90,95,0,
+0,26,0,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,11,0,99,0,0,1,0,0,0,10,0,114,0,0,
+0,1,8,58,109,97,116,50,120,51,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,
+0,59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,
+99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,0,0,0,1,90,95,0,0,27,
+0,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,10,0,99,0,0,1,0,0,0,11,0,114,0,0,0,1,8,
+58,109,97,116,51,120,50,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,
+120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,
+59,120,0,18,114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,0,0,0,1,90,95,0,0,28,0,0,
+111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,12,0,99,0,0,1,0,0,0,10,0,114,0,0,0,1,8,58,
+109,97,116,50,120,52,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,
+0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,119,0,18,114,0,59,120,0,48,0,18,99,0,59,
+120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,
+121,0,48,0,18,99,0,59,119,0,18,114,0,59,121,0,48,0,0,0,0,1,90,95,0,0,29,0,0,111,117,116,101,114,80,
+114,111,100,117,99,116,0,1,0,0,0,10,0,99,0,0,1,0,0,0,12,0,114,0,0,0,1,8,58,109,97,116,52,120,50,0,
+0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,
+18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,
+48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,120,0,18,114,0,59,119,0,48,0,18,99,0,59,
+121,0,18,114,0,59,119,0,48,0,0,0,0,1,90,95,0,0,30,0,0,111,117,116,101,114,80,114,111,100,117,99,
+116,0,1,0,0,0,12,0,99,0,0,1,0,0,0,11,0,114,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,99,0,59,120,0,
+18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,
+48,0,18,99,0,59,119,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,
+121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,119,0,18,114,0,59,
+121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,
+59,122,0,18,114,0,59,122,0,48,0,18,99,0,59,119,0,18,114,0,59,122,0,48,0,0,0,0,1,90,95,0,0,31,0,0,
+111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,0,11,0,99,0,0,1,0,0,0,12,0,114,0,0,0,1,8,58,
+109,97,116,52,120,51,0,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,
+0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,
+121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,
+122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0,48,0,18,99,0,
+59,120,0,18,114,0,59,119,0,48,0,18,99,0,59,121,0,18,114,0,59,119,0,48,0,18,99,0,59,122,0,18,114,0,
+59,119,0,48,0,0,0,0,1,90,95,0,0,13,0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,13,0,109,0,0,0,
+1,8,58,109,97,116,50,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,
+0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,0,0,0,1,90,95,0,0,14,0,0,116,114,97,
+110,115,112,111,115,101,0,1,0,0,0,14,0,109,0,0,0,1,8,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,59,
+120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,8,48,0,57,
+59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,8,48,0,
+57,59,122,0,0,18,109,0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57,59,122,0,0,0,0,0,1,90,95,0,
+0,15,0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,15,0,109,0,0,0,1,8,58,109,97,116,52,0,0,18,
+109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,
+18,109,0,16,10,51,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,
+0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,10,51,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,
+0,0,18,109,0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57,59,122,0,0,18,109,0,16,10,51,0,57,59,
+122,0,0,18,109,0,16,8,48,0,57,59,119,0,0,18,109,0,16,10,49,0,57,59,119,0,0,18,109,0,16,10,50,0,57,
+59,119,0,0,18,109,0,16,10,51,0,57,59,119,0,0,0,0,0,1,90,95,0,0,26,0,0,116,114,97,110,115,112,111,
+115,101,0,1,0,0,0,27,0,109,0,0,0,1,8,58,109,97,116,50,120,51,0,0,18,109,0,16,8,48,0,57,59,120,0,0,
+18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,
+0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0,0,0,0,1,90,95,0,0,27,0,0,116,
+114,97,110,115,112,111,115,101,0,1,0,0,0,26,0,109,0,0,0,1,8,58,109,97,116,51,120,50,0,0,18,109,0,
+16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,
+0,16,10,49,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0,57,59,122,0,0,0,0,
+0,1,90,95,0,0,28,0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,29,0,109,0,0,0,1,8,58,109,97,116,
+50,120,52,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,
+0,57,59,120,0,0,18,109,0,16,10,51,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,
+49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,10,51,0,57,59,121,0,0,0,0,0,1,90,
+95,0,0,29,0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,28,0,109,0,0,0,1,8,58,109,97,116,52,120,
+50,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,
+121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0,57,
+59,122,0,0,18,109,0,16,8,48,0,57,59,119,0,0,18,109,0,16,10,49,0,57,59,119,0,0,0,0,0,1,90,95,0,0,30,
+0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,31,0,109,0,0,0,1,8,58,109,97,116,51,120,52,0,0,18,
+109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,
+18,109,0,16,10,51,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,
+0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,10,51,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,
+0,0,18,109,0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57,59,122,0,0,18,109,0,16,10,51,0,57,59,
+122,0,0,0,0,0,1,90,95,0,0,31,0,0,116,114,97,110,115,112,111,115,101,0,1,0,0,0,30,0,109,0,0,0,1,8,
+58,109,97,116,52,120,51,0,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,
+109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,
+18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0,57,59,122,0,
+0,18,109,0,16,10,50,0,57,59,122,0,0,18,109,0,16,8,48,0,57,59,119,0,0,18,109,0,16,10,49,0,57,59,119,
+0,0,18,109,0,16,10,50,0,57,59,119,0,0,0,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc
new file mode 100644
index 000000000..7d516046a
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc
@@ -0,0 +1,30 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// From Shader Spec, ver. 1.20, rev. 6
+//
+
+varying vec2 gl_PointCoord;
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h
new file mode 100644
index 000000000..add3b5aea
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h
@@ -0,0 +1,5 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_builtin_120_fragment.gc */
+
+5,2,2,90,95,3,0,10,0,1,103,108,95,80,111,105,110,116,67,111,111,114,100,0,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_common_builtin.gc b/mesalib/src/mesa/shader/slang/library/slang_common_builtin.gc
new file mode 100644
index 000000000..9764fc25b
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_common_builtin.gc
@@ -0,0 +1,1873 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+// Note: the values assigned to these constants here aren't actually used.
+// They're set by the compiler according to the GL context limits.
+// See slang_simplify.c
+const int gl_MaxLights = 8;
+const int gl_MaxClipPlanes = 6;
+const int gl_MaxTextureUnits = 8;
+const int gl_MaxTextureCoords = 8;
+const int gl_MaxVertexAttribs = 16;
+const int gl_MaxVertexUniformComponents = 512;
+const int gl_MaxVaryingFloats = 32;
+const int gl_MaxVertexTextureImageUnits = 0;
+const int gl_MaxCombinedTextureImageUnits = 2;
+const int gl_MaxTextureImageUnits = 2;
+const int gl_MaxFragmentUniformComponents = 64;
+const int gl_MaxDrawBuffers = 1;
+
+uniform mat4 gl_ModelViewMatrix;
+uniform mat4 gl_ProjectionMatrix;
+uniform mat4 gl_ModelViewProjectionMatrix;
+uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
+
+uniform mat3 gl_NormalMatrix;
+
+uniform mat4 gl_ModelViewMatrixInverse;
+uniform mat4 gl_ProjectionMatrixInverse;
+uniform mat4 gl_ModelViewProjectionMatrixInverse;
+uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixTranspose;
+uniform mat4 gl_ProjectionMatrixTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixTranspose;
+uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixInverseTranspose;
+uniform mat4 gl_ProjectionMatrixInverseTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
+uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
+
+uniform float gl_NormalScale;
+
+struct gl_DepthRangeParameters {
+ float near;
+ float far;
+ float diff;
+};
+
+uniform gl_DepthRangeParameters gl_DepthRange;
+
+uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
+
+struct gl_PointParameters {
+ float size;
+ float sizeMin;
+ float sizeMax;
+ float fadeThresholdSize;
+ float distanceConstantAttenuation;
+ float distanceLinearAttenuation;
+ float distanceQuadraticAttenuation;
+};
+
+uniform gl_PointParameters gl_Point;
+
+struct gl_MaterialParameters {
+ vec4 emission;
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ float shininess;
+};
+
+uniform gl_MaterialParameters gl_FrontMaterial;
+uniform gl_MaterialParameters gl_BackMaterial;
+
+/* NOTE: the order of these fields is significant!
+ * See the definition of the lighting state vars such as STATE_SPOT_DIRECTION.
+ */
+struct gl_LightSourceParameters {
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+ vec4 position;
+ vec4 halfVector;
+ vec3 spotDirection;
+ float spotCosCutoff;
+
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float spotExponent;
+
+ float spotCutoff;
+};
+
+uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
+
+struct gl_LightModelParameters {
+ vec4 ambient;
+};
+
+uniform gl_LightModelParameters gl_LightModel;
+
+struct gl_LightModelProducts {
+ vec4 sceneColor;
+};
+
+uniform gl_LightModelProducts gl_FrontLightModelProduct;
+uniform gl_LightModelProducts gl_BackLightModelProduct;
+
+struct gl_LightProducts {
+ vec4 ambient;
+ vec4 diffuse;
+ vec4 specular;
+};
+
+uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
+uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
+
+uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
+uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
+
+struct gl_FogParameters {
+ vec4 color;
+ float density;
+ float start;
+ float end;
+ float scale;
+};
+
+uniform gl_FogParameters gl_Fog;
+
+
+
+
+
+//
+// 8.1 Angle and Trigonometry Functions
+//
+
+//// radians
+
+float radians(const float deg)
+{
+ const float c = 3.1415926 / 180.0;
+ __asm vec4_multiply __retVal, deg, c;
+}
+
+vec2 radians(const vec2 deg)
+{
+ const float c = 3.1415926 / 180.0;
+ __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
+}
+
+vec3 radians(const vec3 deg)
+{
+ const float c = 3.1415926 / 180.0;
+ __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
+}
+
+vec4 radians(const vec4 deg)
+{
+ const float c = 3.1415926 / 180.0;
+ __asm vec4_multiply __retVal, deg, c.xxxx;
+}
+
+
+//// degrees
+
+float degrees(const float rad)
+{
+ const float c = 180.0 / 3.1415926;
+ __asm vec4_multiply __retVal, rad, c;
+}
+
+vec2 degrees(const vec2 rad)
+{
+ const float c = 180.0 / 3.1415926;
+ __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
+}
+
+vec3 degrees(const vec3 rad)
+{
+ const float c = 180.0 / 3.1415926;
+ __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
+}
+
+vec4 degrees(const vec4 rad)
+{
+ const float c = 180.0 / 3.1415926;
+ __asm vec4_multiply __retVal, rad, c.xxxx;
+}
+
+
+//// sin
+
+float sin(const float radians)
+{
+ __asm float_sine __retVal, radians;
+}
+
+vec2 sin(const vec2 radians)
+{
+ __asm float_sine __retVal.x, radians.x;
+ __asm float_sine __retVal.y, radians.y;
+}
+
+vec3 sin(const vec3 radians)
+{
+ __asm float_sine __retVal.x, radians.x;
+ __asm float_sine __retVal.y, radians.y;
+ __asm float_sine __retVal.z, radians.z;
+}
+
+vec4 sin(const vec4 radians)
+{
+ __asm float_sine __retVal.x, radians.x;
+ __asm float_sine __retVal.y, radians.y;
+ __asm float_sine __retVal.z, radians.z;
+ __asm float_sine __retVal.w, radians.w;
+}
+
+
+//// cos
+
+float cos(const float radians)
+{
+ __asm float_cosine __retVal, radians;
+}
+
+vec2 cos(const vec2 radians)
+{
+ __asm float_cosine __retVal.x, radians.x;
+ __asm float_cosine __retVal.y, radians.y;
+}
+
+vec3 cos(const vec3 radians)
+{
+ __asm float_cosine __retVal.x, radians.x;
+ __asm float_cosine __retVal.y, radians.y;
+ __asm float_cosine __retVal.z, radians.z;
+}
+
+vec4 cos(const vec4 radians)
+{
+ __asm float_cosine __retVal.x, radians.x;
+ __asm float_cosine __retVal.y, radians.y;
+ __asm float_cosine __retVal.z, radians.z;
+ __asm float_cosine __retVal.w, radians.w;
+}
+
+
+
+//// tan
+
+float tan(const float angle)
+{
+ const float s = sin(angle);
+ const float c = cos(angle);
+ return s / c;
+}
+
+vec2 tan(const vec2 angle)
+{
+ const vec2 s = sin(angle);
+ const vec2 c = cos(angle);
+ return s / c;
+}
+
+vec3 tan(const vec3 angle)
+{
+ const vec3 s = sin(angle);
+ const vec3 c = cos(angle);
+ return s / c;
+}
+
+vec4 tan(const vec4 angle)
+{
+ const vec4 s = sin(angle);
+ const vec4 c = cos(angle);
+ return s / c;
+}
+
+
+
+float asin(const float x)
+{
+ const float a0 = 1.5707288; // PI/2?
+ const float a1 = -0.2121144;
+ const float a2 = 0.0742610;
+ //const float a3 = -0.0187293;
+ const float halfPi = 3.1415926 * 0.5;
+ const float y = abs(x);
+ // three terms seem to be enough:
+ __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
+ // otherwise, try four:
+ //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
+}
+
+vec2 asin(const vec2 v)
+{
+ __retVal.x = asin(v.x);
+ __retVal.y = asin(v.y);
+}
+
+vec3 asin(const vec3 v)
+{
+ __retVal.x = asin(v.x);
+ __retVal.y = asin(v.y);
+ __retVal.z = asin(v.z);
+}
+
+vec4 asin(const vec4 v)
+{
+ __retVal.x = asin(v.x);
+ __retVal.y = asin(v.y);
+ __retVal.z = asin(v.z);
+ __retVal.w = asin(v.w);
+}
+
+float acos(const float x)
+{
+ const float halfPi = 3.1415926 * 0.5;
+ __retVal = halfPi - asin(x);
+}
+
+vec2 acos(const vec2 v)
+{
+ __retVal.x = acos(v.x);
+ __retVal.y = acos(v.y);
+}
+
+vec3 acos(const vec3 v)
+{
+ __retVal.x = acos(v.x);
+ __retVal.y = acos(v.y);
+ __retVal.z = acos(v.z);
+}
+
+vec4 acos(const vec4 v)
+{
+ __retVal.x = acos(v.x);
+ __retVal.y = acos(v.y);
+ __retVal.z = acos(v.z);
+ __retVal.w = acos(v.w);
+}
+
+float atan(const float x)
+{
+ __retVal = asin(x * inversesqrt(x * x + 1.0));
+}
+
+vec2 atan(const vec2 y_over_x)
+{
+ __retVal.x = atan(y_over_x.x);
+ __retVal.y = atan(y_over_x.y);
+}
+
+vec3 atan(const vec3 y_over_x)
+{
+ __retVal.x = atan(y_over_x.x);
+ __retVal.y = atan(y_over_x.y);
+ __retVal.z = atan(y_over_x.z);
+}
+
+vec4 atan(const vec4 y_over_x)
+{
+ __retVal.x = atan(y_over_x.x);
+ __retVal.y = atan(y_over_x.y);
+ __retVal.z = atan(y_over_x.z);
+ __retVal.w = atan(y_over_x.w);
+}
+
+float atan(const float y, const float x)
+{
+ float r;
+ if (abs(x) > 1.0e-4) {
+ r = atan(y / x);
+ if (x < 0.0) {
+ r = r + sign(y) * 3.141593;
+ }
+ }
+ else {
+ r = sign(y) * 1.5707965; // pi/2
+ }
+ return r;
+}
+
+vec2 atan(const vec2 u, const vec2 v)
+{
+ __retVal.x = atan(u.x, v.x);
+ __retVal.y = atan(u.y, v.y);
+}
+
+vec3 atan(const vec3 u, const vec3 v)
+{
+ __retVal.x = atan(u.x, v.x);
+ __retVal.y = atan(u.y, v.y);
+ __retVal.z = atan(u.z, v.z);
+}
+
+vec4 atan(const vec4 u, const vec4 v)
+{
+ __retVal.x = atan(u.x, v.x);
+ __retVal.y = atan(u.y, v.y);
+ __retVal.z = atan(u.z, v.z);
+ __retVal.w = atan(u.w, v.w);
+}
+
+
+//
+// 8.2 Exponential Functions
+//
+
+//// pow
+
+float pow(const float a, const float b)
+{
+ __asm float_power __retVal, a, b;
+}
+
+vec2 pow(const vec2 a, const vec2 b)
+{
+ __asm float_power __retVal.x, a.x, b.x;
+ __asm float_power __retVal.y, a.y, b.y;
+}
+
+vec3 pow(const vec3 a, const vec3 b)
+{
+ __asm float_power __retVal.x, a.x, b.x;
+ __asm float_power __retVal.y, a.y, b.y;
+ __asm float_power __retVal.z, a.z, b.z;
+}
+
+vec4 pow(const vec4 a, const vec4 b)
+{
+ __asm float_power __retVal.x, a.x, b.x;
+ __asm float_power __retVal.y, a.y, b.y;
+ __asm float_power __retVal.z, a.z, b.z;
+ __asm float_power __retVal.w, a.w, b.w;
+}
+
+
+//// exp
+
+float exp(const float a)
+{
+ // NOTE: log2(e) = 1.44269502
+ float t = a * 1.44269502;
+ __asm float_exp2 __retVal, t;
+}
+
+vec2 exp(const vec2 a)
+{
+ vec2 t = a * 1.44269502;
+ __asm float_exp2 __retVal.x, t.x;
+ __asm float_exp2 __retVal.y, t.y;
+}
+
+vec3 exp(const vec3 a)
+{
+ vec3 t = a * 1.44269502;
+ __asm float_exp2 __retVal.x, t.x;
+ __asm float_exp2 __retVal.y, t.y;
+ __asm float_exp2 __retVal.z, t.z;
+}
+
+vec4 exp(const vec4 a)
+{
+ vec4 t = a * 1.44269502;
+ __asm float_exp2 __retVal.x, t.x;
+ __asm float_exp2 __retVal.y, t.y;
+ __asm float_exp2 __retVal.z, t.z;
+ __asm float_exp2 __retVal.w, t.w;
+}
+
+
+
+//// log2
+
+float log2(const float x)
+{
+ __asm float_log2 __retVal, x;
+}
+
+vec2 log2(const vec2 v)
+{
+ __asm float_log2 __retVal.x, v.x;
+ __asm float_log2 __retVal.y, v.y;
+}
+
+vec3 log2(const vec3 v)
+{
+ __asm float_log2 __retVal.x, v.x;
+ __asm float_log2 __retVal.y, v.y;
+ __asm float_log2 __retVal.z, v.z;
+}
+
+vec4 log2(const vec4 v)
+{
+ __asm float_log2 __retVal.x, v.x;
+ __asm float_log2 __retVal.y, v.y;
+ __asm float_log2 __retVal.z, v.z;
+ __asm float_log2 __retVal.w, v.w;
+}
+
+
+//// log (natural log)
+
+float log(const float x)
+{
+ // note: logBaseB(x) = logBaseN(x) / logBaseN(B)
+ // compute log(x) = log2(x) / log2(e)
+ // c = 1.0 / log2(e) = 0.693147181
+ const float c = 0.693147181;
+ return log2(x) * c;
+}
+
+vec2 log(const vec2 v)
+{
+ const float c = 0.693147181;
+ return log2(v) * c;
+}
+
+vec3 log(const vec3 v)
+{
+ const float c = 0.693147181;
+ return log2(v) * c;
+}
+
+vec4 log(const vec4 v)
+{
+ const float c = 0.693147181;
+ return log2(v) * c;
+}
+
+
+//// exp2
+
+float exp2(const float a)
+{
+ __asm float_exp2 __retVal, a;
+}
+
+vec2 exp2(const vec2 a)
+{
+ __asm float_exp2 __retVal.x, a.x;
+ __asm float_exp2 __retVal.y, a.y;
+}
+
+vec3 exp2(const vec3 a)
+{
+ __asm float_exp2 __retVal.x, a.x;
+ __asm float_exp2 __retVal.y, a.y;
+ __asm float_exp2 __retVal.z, a.z;
+}
+
+vec4 exp2(const vec4 a)
+{
+ __asm float_exp2 __retVal.x, a.x;
+ __asm float_exp2 __retVal.y, a.y;
+ __asm float_exp2 __retVal.z, a.z;
+ __asm float_exp2 __retVal.w, a.w;
+}
+
+
+//// sqrt
+
+float sqrt(const float x)
+{
+ float r;
+ __asm float_rsq r, x;
+ __asm float_rcp __retVal, r;
+}
+
+vec2 sqrt(const vec2 v)
+{
+ float r;
+ __asm float_rsq r, v.x;
+ __asm float_rcp __retVal.x, r;
+ __asm float_rsq r, v.y;
+ __asm float_rcp __retVal.y, r;
+}
+
+vec3 sqrt(const vec3 v)
+{
+ float r;
+ __asm float_rsq r, v.x;
+ __asm float_rcp __retVal.x, r;
+ __asm float_rsq r, v.y;
+ __asm float_rcp __retVal.y, r;
+ __asm float_rsq r, v.z;
+ __asm float_rcp __retVal.z, r;
+}
+
+vec4 sqrt(const vec4 v)
+{
+ float r;
+ __asm float_rsq r, v.x;
+ __asm float_rcp __retVal.x, r;
+ __asm float_rsq r, v.y;
+ __asm float_rcp __retVal.y, r;
+ __asm float_rsq r, v.z;
+ __asm float_rcp __retVal.z, r;
+ __asm float_rsq r, v.w;
+ __asm float_rcp __retVal.w, r;
+}
+
+
+//// inversesqrt
+
+float inversesqrt(const float x)
+{
+ __asm float_rsq __retVal.x, x;
+}
+
+vec2 inversesqrt(const vec2 v)
+{
+ __asm float_rsq __retVal.x, v.x;
+ __asm float_rsq __retVal.y, v.y;
+}
+
+vec3 inversesqrt(const vec3 v)
+{
+ __asm float_rsq __retVal.x, v.x;
+ __asm float_rsq __retVal.y, v.y;
+ __asm float_rsq __retVal.z, v.z;
+}
+
+vec4 inversesqrt(const vec4 v)
+{
+ __asm float_rsq __retVal.x, v.x;
+ __asm float_rsq __retVal.y, v.y;
+ __asm float_rsq __retVal.z, v.z;
+ __asm float_rsq __retVal.w, v.w;
+}
+
+
+//// normalize
+
+float normalize(const float x)
+{
+ __retVal = 1.0;
+}
+
+vec2 normalize(const vec2 v)
+{
+ const float s = inversesqrt(dot(v, v));
+ __asm vec4_multiply __retVal.xy, v, s;
+}
+
+vec3 normalize(const vec3 v)
+{
+// const float s = inversesqrt(dot(v, v));
+// __retVal = v * s;
+// XXX note, we _could_ use __retVal.w instead of tmp and and save a
+// register, but that's actually a compilation error because v is a vec3
+// and the .w suffix is illegal. Oh well.
+ float tmp;
+ __asm vec3_dot tmp, v, v;
+ __asm float_rsq tmp, tmp;
+ __asm vec4_multiply __retVal.xyz, v, tmp;
+}
+
+vec4 normalize(const vec4 v)
+{
+ float tmp;
+ __asm vec4_dot tmp, v, v;
+ __asm float_rsq tmp, tmp;
+ __asm vec4_multiply __retVal.xyz, v, tmp;
+}
+
+
+
+//
+// 8.3 Common Functions
+//
+
+
+//// abs
+
+float abs(const float a)
+{
+ __asm vec4_abs __retVal, a;
+}
+
+vec2 abs(const vec2 a)
+{
+ __asm vec4_abs __retVal.xy, a;
+}
+
+vec3 abs(const vec3 a)
+{
+ __asm vec4_abs __retVal.xyz, a;
+}
+
+vec4 abs(const vec4 a)
+{
+ __asm vec4_abs __retVal, a;
+}
+
+
+//// sign
+
+float sign(const float x)
+{
+ float p, n;
+ __asm vec4_sgt p, x, 0.0; // p = (x > 0)
+ __asm vec4_sgt n, 0.0, x; // n = (x < 0)
+ __asm vec4_subtract __retVal, p, n; // sign = p - n
+}
+
+vec2 sign(const vec2 v)
+{
+ vec2 p, n;
+ __asm vec4_sgt p.xy, v, 0.0;
+ __asm vec4_sgt n.xy, 0.0, v;
+ __asm vec4_subtract __retVal.xy, p, n;
+}
+
+vec3 sign(const vec3 v)
+{
+ vec3 p, n;
+ __asm vec4_sgt p.xyz, v, 0.0;
+ __asm vec4_sgt n.xyz, 0.0, v;
+ __asm vec4_subtract __retVal.xyz, p, n;
+}
+
+vec4 sign(const vec4 v)
+{
+ vec4 p, n;
+ __asm vec4_sgt p, v, 0.0;
+ __asm vec4_sgt n, 0.0, v;
+ __asm vec4_subtract __retVal, p, n;
+}
+
+
+//// floor
+
+float floor(const float a)
+{
+ __asm vec4_floor __retVal, a;
+}
+
+vec2 floor(const vec2 a)
+{
+ __asm vec4_floor __retVal.xy, a;
+}
+
+vec3 floor(const vec3 a)
+{
+ __asm vec4_floor __retVal.xyz, a;
+}
+
+vec4 floor(const vec4 a)
+{
+ __asm vec4_floor __retVal, a;
+}
+
+
+//// ceil
+
+float ceil(const float a)
+{
+ // XXX this could be improved
+ float b = -a;
+ __asm vec4_floor b, b;
+ __retVal = -b;
+}
+
+vec2 ceil(const vec2 a)
+{
+ vec2 b = -a;
+ __asm vec4_floor b, b;
+ __retVal.xy = -b;
+}
+
+vec3 ceil(const vec3 a)
+{
+ vec3 b = -a;
+ __asm vec4_floor b, b;
+ __retVal.xyz = -b;
+}
+
+vec4 ceil(const vec4 a)
+{
+ vec4 b = -a;
+ __asm vec4_floor b, b;
+ __retVal = -b;
+}
+
+
+//// fract
+
+float fract(const float a)
+{
+ __asm vec4_frac __retVal, a;
+}
+
+vec2 fract(const vec2 a)
+{
+ __asm vec4_frac __retVal.xy, a;
+}
+
+vec3 fract(const vec3 a)
+{
+ __asm vec4_frac __retVal.xyz, a;
+}
+
+vec4 fract(const vec4 a)
+{
+ __asm vec4_frac __retVal, a;
+}
+
+
+//// mod (very untested!)
+
+float mod(const float a, const float b)
+{
+ float oneOverB;
+ __asm float_rcp oneOverB, b;
+ __retVal = a - b * floor(a * oneOverB);
+}
+
+vec2 mod(const vec2 a, const float b)
+{
+ float oneOverB;
+ __asm float_rcp oneOverB, b;
+ __retVal.xy = a - b * floor(a * oneOverB);
+}
+
+vec3 mod(const vec3 a, const float b)
+{
+ float oneOverB;
+ __asm float_rcp oneOverB, b;
+ __retVal.xyz = a - b * floor(a * oneOverB);
+}
+
+vec4 mod(const vec4 a, const float b)
+{
+ float oneOverB;
+ __asm float_rcp oneOverB, b;
+ __retVal = a - b * floor(a * oneOverB);
+}
+
+vec2 mod(const vec2 a, const vec2 b)
+{
+ vec2 oneOverB;
+ __asm float_rcp oneOverB.x, b.x;
+ __asm float_rcp oneOverB.y, b.y;
+ __retVal = a - b * floor(a * oneOverB);
+}
+
+vec3 mod(const vec3 a, const vec3 b)
+{
+ vec3 oneOverB;
+ __asm float_rcp oneOverB.x, b.x;
+ __asm float_rcp oneOverB.y, b.y;
+ __asm float_rcp oneOverB.z, b.z;
+ __retVal = a - b * floor(a * oneOverB);
+}
+
+vec4 mod(const vec4 a, const vec4 b)
+{
+ vec4 oneOverB;
+ __asm float_rcp oneOverB.x, b.x;
+ __asm float_rcp oneOverB.y, b.y;
+ __asm float_rcp oneOverB.z, b.z;
+ __asm float_rcp oneOverB.w, b.w;
+ __retVal = a - b * floor(a * oneOverB);
+}
+
+
+//// min
+
+float min(const float a, const float b)
+{
+ __asm vec4_min __retVal, a, b;
+}
+
+vec2 min(const vec2 a, const vec2 b)
+{
+ __asm vec4_min __retVal.xy, a.xy, b.xy;
+}
+
+vec3 min(const vec3 a, const vec3 b)
+{
+ __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
+}
+
+vec4 min(const vec4 a, const vec4 b)
+{
+ __asm vec4_min __retVal, a, b;
+}
+
+vec2 min(const vec2 a, const float b)
+{
+ __asm vec4_min __retVal, a.xy, b;
+}
+
+vec3 min(const vec3 a, const float b)
+{
+ __asm vec4_min __retVal, a.xyz, b;
+}
+
+vec4 min(const vec4 a, const float b)
+{
+ __asm vec4_min __retVal, a, b;
+}
+
+
+//// max
+
+float max(const float a, const float b)
+{
+ __asm vec4_max __retVal, a, b;
+}
+
+vec2 max(const vec2 a, const vec2 b)
+{
+ __asm vec4_max __retVal.xy, a.xy, b.xy;
+}
+
+vec3 max(const vec3 a, const vec3 b)
+{
+ __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
+}
+
+vec4 max(const vec4 a, const vec4 b)
+{
+ __asm vec4_max __retVal, a, b;
+}
+
+vec2 max(const vec2 a, const float b)
+{
+ __asm vec4_max __retVal, a.xy, b;
+}
+
+vec3 max(const vec3 a, const float b)
+{
+ __asm vec4_max __retVal, a.xyz, b;
+}
+
+vec4 max(const vec4 a, const float b)
+{
+ __asm vec4_max __retVal, a, b;
+}
+
+
+//// clamp
+
+float clamp(const float val, const float minVal, const float maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec2 clamp(const vec2 val, const float minVal, const float maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec3 clamp(const vec3 val, const float minVal, const float maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec4 clamp(const vec4 val, const float minVal, const float maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
+{
+ __asm vec4_clamp __retVal, val, minVal, maxVal;
+}
+
+
+//// mix
+
+float mix(const float x, const float y, const float a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec2 mix(const vec2 x, const vec2 y, const float a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec3 mix(const vec3 x, const vec3 y, const float a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec4 mix(const vec4 x, const vec4 y, const float a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec2 mix(const vec2 x, const vec2 y, const vec2 a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec3 mix(const vec3 x, const vec3 y, const vec3 a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+vec4 mix(const vec4 x, const vec4 y, const vec4 a)
+{
+ __asm vec4_lrp __retVal, a, y, x;
+}
+
+
+//// step
+
+float step(const float edge, const float x)
+{
+ __asm vec4_sge __retVal, x, edge;
+}
+
+vec2 step(const vec2 edge, const vec2 x)
+{
+ __asm vec4_sge __retVal.xy, x, edge;
+}
+
+vec3 step(const vec3 edge, const vec3 x)
+{
+ __asm vec4_sge __retVal.xyz, x, edge;
+}
+
+vec4 step(const vec4 edge, const vec4 x)
+{
+ __asm vec4_sge __retVal, x, edge;
+}
+
+vec2 step(const float edge, const vec2 v)
+{
+ __asm vec4_sge __retVal.xy, v, edge;
+}
+
+vec3 step(const float edge, const vec3 v)
+{
+ __asm vec4_sge __retVal.xyz, v, edge;
+}
+
+vec4 step(const float edge, const vec4 v)
+{
+ __asm vec4_sge __retVal, v, edge;
+}
+
+
+//// smoothstep
+
+float smoothstep(const float edge0, const float edge1, const float x)
+{
+ float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
+{
+ vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
+{
+ vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
+{
+ vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
+{
+ vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
+{
+ vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
+{
+ vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
+ return t * t * (3.0 - 2.0 * t);
+}
+
+
+
+//
+// 8.4 Geometric Functions
+//
+
+
+//// length
+
+float length(const float x)
+{
+ return abs(x);
+}
+
+float length(const vec2 v)
+{
+ float r;
+ const float p = dot(v, v); // p = v.x * v.x + v.y * v.y
+ __asm float_rsq r, p; // r = 1 / sqrt(p)
+ __asm float_rcp __retVal.x, r; // retVal = 1 / r
+}
+
+float length(const vec3 v)
+{
+ float r;
+ const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + v.z * v.z
+ __asm float_rsq r, p; // r = 1 / sqrt(p)
+ __asm float_rcp __retVal, r; // retVal = 1 / r
+}
+
+float length(const vec4 v)
+{
+ float r;
+ const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + ...
+ __asm float_rsq r, p; // r = 1 / sqrt(p)
+ __asm float_rcp __retVal, r; // retVal = 1 / r
+}
+
+
+//// distance
+
+float distance(const float x, const float y)
+{
+ const float d = x - y;
+ __retVal = length(d);
+}
+
+float distance(const vec2 v, const vec2 u)
+{
+ const vec2 d2 = v - u;
+ __retVal = length(d2);
+}
+
+float distance(const vec3 v, const vec3 u)
+{
+ const vec3 d3 = v - u;
+ __retVal = length(d3);
+}
+
+float distance(const vec4 v, const vec4 u)
+{
+ const vec4 d4 = v - u;
+ __retVal = length(d4);
+}
+
+
+//// cross
+
+vec3 cross(const vec3 v, const vec3 u)
+{
+ __asm vec3_cross __retVal.xyz, v, u;
+}
+
+
+//// faceforward
+
+float faceforward(const float N, const float I, const float Nref)
+{
+ // this could probably be done better
+ const float d = dot(Nref, I);
+ float s;
+ __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
+ return mix(-N, N, s);
+}
+
+vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
+{
+ // this could probably be done better
+ const float d = dot(Nref, I);
+ float s;
+ __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
+ return mix(-N, N, s);
+}
+
+vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
+{
+ // this could probably be done better
+ const float d = dot(Nref, I);
+ float s;
+ __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
+ return mix(-N, N, s);
+}
+
+vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
+{
+ // this could probably be done better
+ const float d = dot(Nref, I);
+ float s;
+ __asm vec4_sgt s, 0.0, d; // s = (0.0 > d) ? 1 : 0
+ return mix(-N, N, s);
+}
+
+
+//// reflect
+
+float reflect(const float I, const float N)
+{
+ return I - 2.0 * dot(N, I) * N;
+}
+
+vec2 reflect(const vec2 I, const vec2 N)
+{
+ return I - 2.0 * dot(N, I) * N;
+}
+
+vec3 reflect(const vec3 I, const vec3 N)
+{
+ return I - 2.0 * dot(N, I) * N;
+}
+
+vec4 reflect(const vec4 I, const vec4 N)
+{
+ return I - 2.0 * dot(N, I) * N;
+}
+
+//// refract
+
+float refract(const float I, const float N, const float eta)
+{
+ float n_dot_i = dot(N, I);
+ float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+ float retval;
+ if (k < 0.0)
+ retval = 0.0;
+ else
+ retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+ return retval;
+}
+
+vec2 refract(const vec2 I, const vec2 N, const float eta)
+{
+ float n_dot_i = dot(N, I);
+ float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+ vec2 retval;
+ if (k < 0.0)
+ retval = vec2(0.0);
+ else
+ retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+ return retval;
+}
+
+vec3 refract(const vec3 I, const vec3 N, const float eta)
+{
+ float n_dot_i = dot(N, I);
+ float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+ vec3 retval;
+ if (k < 0.0)
+ retval = vec3(0.0);
+ else
+ retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+ return retval;
+}
+
+vec4 refract(const vec4 I, const vec4 N, const float eta)
+{
+ float n_dot_i = dot(N, I);
+ float k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i);
+ vec4 retval;
+ if (k < 0.0)
+ retval = vec4(0.0);
+ else
+ retval = eta * I - (eta * n_dot_i + sqrt(k)) * N;
+ return retval;
+}
+
+
+
+
+//
+// 8.5 Matrix Functions
+//
+
+mat2 matrixCompMult (mat2 m, mat2 n) {
+ return mat2 (m[0] * n[0], m[1] * n[1]);
+}
+
+mat3 matrixCompMult (mat3 m, mat3 n) {
+ return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
+}
+
+mat4 matrixCompMult (mat4 m, mat4 n) {
+ return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
+}
+
+
+
+
+//
+// 8.6 Vector Relational Functions
+//
+
+//// lessThan
+
+bvec2 lessThan(const vec2 u, const vec2 v)
+{
+ __asm vec4_slt __retVal.xy, u, v;
+}
+
+bvec3 lessThan(const vec3 u, const vec3 v)
+{
+ __asm vec4_slt __retVal.xyz, u, v;
+}
+
+bvec4 lessThan(const vec4 u, const vec4 v)
+{
+ __asm vec4_slt __retVal, u, v;
+}
+
+bvec2 lessThan(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_slt __retVal.xy, u, v;
+}
+
+bvec3 lessThan(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_slt __retVal.xyz, u, v;
+}
+
+bvec4 lessThan(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_slt __retVal, u, v;
+}
+
+
+//// lessThanEqual
+
+bvec2 lessThanEqual(const vec2 u, const vec2 v)
+{
+ __asm vec4_sle __retVal.xy, u, v;
+}
+
+bvec3 lessThanEqual(const vec3 u, const vec3 v)
+{
+ __asm vec4_sle __retVal.xyz, u, v;
+}
+
+bvec4 lessThanEqual(const vec4 u, const vec4 v)
+{
+ __asm vec4_sle __retVal, u, v;
+}
+
+bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_sle __retVal.xy, u, v;
+}
+
+bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_sle __retVal.xyz, u, v;
+}
+
+bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_sle __retVal, u, v;
+}
+
+
+//// greaterThan
+
+bvec2 greaterThan(const vec2 u, const vec2 v)
+{
+ __asm vec4_sgt __retVal.xy, u, v;
+}
+
+bvec3 greaterThan(const vec3 u, const vec3 v)
+{
+ __asm vec4_sgt __retVal.xyz, u, v;
+}
+
+bvec4 greaterThan(const vec4 u, const vec4 v)
+{
+ __asm vec4_sgt __retVal, u, v;
+}
+
+bvec2 greaterThan(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_sgt __retVal.xy, u.xy, v.xy;
+}
+
+bvec3 greaterThan(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_sgt __retVal.xyz, u, v;
+}
+
+bvec4 greaterThan(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_sgt __retVal, u, v;
+}
+
+
+//// greaterThanEqual
+
+bvec2 greaterThanEqual(const vec2 u, const vec2 v)
+{
+ __asm vec4_sge __retVal.xy, u, v;
+}
+
+bvec3 greaterThanEqual(const vec3 u, const vec3 v)
+{
+ __asm vec4_sge __retVal.xyz, u, v;
+}
+
+bvec4 greaterThanEqual(const vec4 u, const vec4 v)
+{
+ __asm vec4_sge __retVal, u, v;
+}
+
+bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_sge __retVal.xy, u, v;
+}
+
+bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_sge __retVal.xyz, u, v;
+}
+
+bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_sge __retVal, u, v;
+}
+
+
+//// equal
+
+bvec2 equal(const vec2 u, const vec2 v)
+{
+ __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const vec3 u, const vec3 v)
+{
+ __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const vec4 u, const vec4 v)
+{
+ __asm vec4_seq __retVal, u, v;
+}
+
+bvec2 equal(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_seq __retVal, u, v;
+}
+
+bvec2 equal(const bvec2 u, const bvec2 v)
+{
+ __asm vec4_seq __retVal.xy, u, v;
+}
+
+bvec3 equal(const bvec3 u, const bvec3 v)
+{
+ __asm vec4_seq __retVal.xyz, u, v;
+}
+
+bvec4 equal(const bvec4 u, const bvec4 v)
+{
+ __asm vec4_seq __retVal, u, v;
+}
+
+
+
+
+//// notEqual
+
+bvec2 notEqual(const vec2 u, const vec2 v)
+{
+ __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const vec3 u, const vec3 v)
+{
+ __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const vec4 u, const vec4 v)
+{
+ __asm vec4_sne __retVal, u, v;
+}
+
+bvec2 notEqual(const ivec2 u, const ivec2 v)
+{
+ __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const ivec3 u, const ivec3 v)
+{
+ __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const ivec4 u, const ivec4 v)
+{
+ __asm vec4_sne __retVal, u, v;
+}
+
+bvec2 notEqual(const bvec2 u, const bvec2 v)
+{
+ __asm vec4_sne __retVal.xy, u, v;
+}
+
+bvec3 notEqual(const bvec3 u, const bvec3 v)
+{
+ __asm vec4_sne __retVal.xyz, u, v;
+}
+
+bvec4 notEqual(const bvec4 u, const bvec4 v)
+{
+ __asm vec4_sne __retVal, u, v;
+}
+
+
+
+//// any
+
+bool any(const bvec2 v)
+{
+ float sum;
+ __asm vec4_add sum.x, v.x, v.y;
+ __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+bool any(const bvec3 v)
+{
+ float sum;
+ __asm vec4_add sum.x, v.x, v.y;
+ __asm vec4_add sum.x, sum.x, v.z;
+ __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+bool any(const bvec4 v)
+{
+ float sum;
+ __asm vec4_add sum.x, v.x, v.y;
+ __asm vec4_add sum.x, sum.x, v.z;
+ __asm vec4_add sum.x, sum.x, v.w;
+ __asm vec4_sne __retVal.x, sum.x, 0.0;
+}
+
+
+//// all
+
+bool all (const bvec2 v)
+{
+ float prod;
+ __asm vec4_multiply prod, v.x, v.y;
+ __asm vec4_sne __retVal, prod, 0.0;
+}
+
+bool all (const bvec3 v)
+{
+ float prod;
+ __asm vec4_multiply prod, v.x, v.y;
+ __asm vec4_multiply prod, prod, v.z;
+ __asm vec4_sne __retVal, prod, 0.0;
+}
+
+bool all (const bvec4 v)
+{
+ float prod;
+ __asm vec4_multiply prod, v.x, v.y;
+ __asm vec4_multiply prod, prod, v.z;
+ __asm vec4_multiply prod, prod, v.w;
+ __asm vec4_sne __retVal, prod, 0.0;
+}
+
+
+
+//// not
+
+bvec2 not (const bvec2 v)
+{
+ __asm vec4_seq __retVal.xy, v, 0.0;
+}
+
+bvec3 not (const bvec3 v)
+{
+ __asm vec4_seq __retVal.xyz, v, 0.0;
+}
+
+bvec4 not (const bvec4 v)
+{
+ __asm vec4_seq __retVal, v, 0.0;
+}
+
+
+
+//// Texture Lookup Functions (for both fragment and vertex shaders)
+
+vec4 texture1D(const sampler1D sampler, const float coord)
+{
+ __asm vec4_tex_1d __retVal, sampler, coord;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
+{
+ // need to swizzle .y into .w
+ __asm vec4_tex_1d_proj __retVal, sampler, coord.xyyy;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
+{
+ __asm vec4_tex_1d_proj __retVal, sampler, coord;
+}
+
+
+vec4 texture2D(const sampler2D sampler, const vec2 coord)
+{
+ __asm vec4_tex_2d __retVal, sampler, coord;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
+{
+ // need to swizzle 'z' into 'w'.
+ __asm vec4_tex_2d_proj __retVal, sampler, coord.xyzz;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
+{
+ __asm vec4_tex_2d_proj __retVal, sampler, coord;
+}
+
+
+vec4 texture3D(const sampler3D sampler, const vec3 coord)
+{
+ __asm vec4_tex_3d __retVal, sampler, coord;
+}
+
+vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
+{
+ __asm vec4_tex_3d_proj __retVal, sampler, coord;
+}
+
+
+vec4 textureCube(const samplerCube sampler, const vec3 coord)
+{
+ __asm vec4_tex_cube __retVal, sampler, coord;
+}
+
+
+
+vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
+{
+ __asm vec4_tex_1d_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
+{
+ // .s and .p will be divided by .q
+ __asm vec4_tex_1d_proj_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
+{
+ __asm vec4_tex_2d_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
+{
+ // .s, .t and .p will be divided by .q
+ __asm vec4_tex_2d_proj_shadow __retVal, sampler, coord;
+}
+
+
+//// GL_ARB_texture_rectangle:
+vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
+{
+ __asm vec4_tex_rect __retVal, sampler, coord;
+}
+
+vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
+{
+ // need to swizzle .y into .w
+ __asm vec4_tex_rect_proj __retVal, sampler, coord.xyzz;
+}
+
+vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
+{
+ __asm vec4_tex_rect_proj __retVal, sampler, ccoord;
+}
+
+vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
+{
+ __asm vec4_tex_rect_shadow __retVal, sampler, coord;
+}
+
+vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
+{
+ __asm vec4_tex_rect_proj_shadow __retVal, sampler, coord;
+}
+
+
+
+//
+// 8.9 Noise Functions
+//
+// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
+//
+
+float noise1(const float x)
+{
+ __asm float_noise1 __retVal, x;
+}
+
+
+float noise1(const vec2 x)
+{
+ __asm float_noise2 __retVal, x;
+}
+
+float noise1(const vec3 x)
+{
+ __asm float_noise3 __retVal, x;
+}
+
+float noise1(const vec4 x)
+{
+ __asm float_noise4 __retVal, x;
+}
+
+vec2 noise2(const float x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + 19.34);
+}
+
+vec2 noise2(const vec2 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec2(19.34, 7.66));
+}
+
+vec2 noise2(const vec3 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+}
+
+vec2 noise2(const vec4 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+}
+
+vec3 noise3(const float x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + 19.34);
+ __retVal.z = noise1(x + 5.47);
+}
+
+vec3 noise3(const vec2 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec2(19.34, 7.66));
+ __retVal.z = noise1(x + vec2(5.47, 17.85));
+}
+
+vec3 noise3(const vec3 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+ __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
+}
+
+vec3 noise3(const vec4 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+ __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
+}
+
+vec4 noise4(const float x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + 19.34);
+ __retVal.z = noise1(x + 5.47);
+ __retVal.w = noise1(x + 23.54);
+}
+
+vec4 noise4(const vec2 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec2 (19.34, 7.66));
+ __retVal.z = noise1(x + vec2 (5.47, 17.85));
+ __retVal.w = noise1(x + vec2 (23.54, 29.11));
+}
+
+vec4 noise4(const vec3 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
+ __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
+ __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
+}
+
+vec4 noise4(const vec4 x)
+{
+ __retVal.x = noise1(x);
+ __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
+ __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
+ __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
+}
diff --git a/mesalib/src/mesa/shader/slang/library/slang_common_builtin_gc.h b/mesalib/src/mesa/shader/slang/library/slang_common_builtin_gc.h
new file mode 100644
index 000000000..78a7b83ec
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_common_builtin_gc.h
@@ -0,0 +1,872 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_common_builtin.gc */
+
+5,2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,76,105,103,104,116,115,0,2,16,10,56,0,0,0,2,2,90,95,1,0,
+5,0,1,103,108,95,77,97,120,67,108,105,112,80,108,97,110,101,115,0,2,16,10,54,0,0,0,2,2,90,95,1,0,5,
+0,1,103,108,95,77,97,120,84,101,120,116,117,114,101,85,110,105,116,115,0,2,16,10,56,0,0,0,2,2,90,
+95,1,0,5,0,1,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,2,16,10,56,0,
+0,0,2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,86,101,114,116,101,120,65,116,116,114,105,98,115,0,2,
+16,10,49,54,0,0,0,2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,86,101,114,116,101,120,85,110,105,102,
+111,114,109,67,111,109,112,111,110,101,110,116,115,0,2,16,10,53,49,50,0,0,0,2,2,90,95,1,0,5,0,1,
+103,108,95,77,97,120,86,97,114,121,105,110,103,70,108,111,97,116,115,0,2,16,10,51,50,0,0,0,2,2,90,
+95,1,0,5,0,1,103,108,95,77,97,120,86,101,114,116,101,120,84,101,120,116,117,114,101,73,109,97,103,
+101,85,110,105,116,115,0,2,16,8,48,0,0,0,2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,67,111,109,98,
+105,110,101,100,84,101,120,116,117,114,101,73,109,97,103,101,85,110,105,116,115,0,2,16,10,50,0,0,0,
+2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,84,101,120,116,117,114,101,73,109,97,103,101,85,110,105,
+116,115,0,2,16,10,50,0,0,0,2,2,90,95,1,0,5,0,1,103,108,95,77,97,120,70,114,97,103,109,101,110,116,
+85,110,105,102,111,114,109,67,111,109,112,111,110,101,110,116,115,0,2,16,10,54,52,0,0,0,2,2,90,95,
+1,0,5,0,1,103,108,95,77,97,120,68,114,97,119,66,117,102,102,101,114,115,0,2,16,10,49,0,0,0,2,2,90,
+95,4,0,15,0,1,103,108,95,77,111,100,101,108,86,105,101,119,77,97,116,114,105,120,0,0,0,2,2,90,95,4,
+0,15,0,1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,0,0,2,2,90,95,4,
+0,15,0,1,103,108,95,77,111,100,101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,
+116,114,105,120,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,84,101,120,116,117,114,101,77,97,116,114,105,
+120,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,
+4,0,14,0,1,103,108,95,78,111,114,109,97,108,77,97,116,114,105,120,0,0,0,2,2,90,95,4,0,15,0,1,103,
+108,95,77,111,100,101,108,86,105,101,119,77,97,116,114,105,120,73,110,118,101,114,115,101,0,0,0,2,
+2,90,95,4,0,15,0,1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,
+118,101,114,115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,77,111,100,101,108,86,105,101,119,80,114,
+111,106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,118,101,114,115,101,0,0,0,2,2,90,95,4,
+0,15,0,1,103,108,95,84,101,120,116,117,114,101,77,97,116,114,105,120,73,110,118,101,114,115,101,0,
+3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,15,
+0,1,103,108,95,77,111,100,101,108,86,105,101,119,77,97,116,114,105,120,84,114,97,110,115,112,111,
+115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,
+105,120,84,114,97,110,115,112,111,115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,77,111,100,101,108,
+86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,84,114,97,110,115,112,
+111,115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,84,101,120,116,117,114,101,77,97,116,114,105,120,
+84,114,97,110,115,112,111,115,101,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,
+111,114,100,115,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,77,111,100,101,108,86,105,101,119,77,97,116,
+114,105,120,73,110,118,101,114,115,101,84,114,97,110,115,112,111,115,101,0,0,0,2,2,90,95,4,0,15,0,
+1,103,108,95,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,118,101,114,115,
+101,84,114,97,110,115,112,111,115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,77,111,100,101,108,86,
+105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,73,110,118,101,114,115,101,
+84,114,97,110,115,112,111,115,101,0,0,0,2,2,90,95,4,0,15,0,1,103,108,95,84,101,120,116,117,114,101,
+77,97,116,114,105,120,73,110,118,101,114,115,101,84,114,97,110,115,112,111,115,101,0,3,18,103,108,
+95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,9,0,1,103,108,
+95,78,111,114,109,97,108,83,99,97,108,101,0,0,0,2,2,90,95,0,0,24,103,108,95,68,101,112,116,104,82,
+97,110,103,101,80,97,114,97,109,101,116,101,114,115,0,9,0,110,101,97,114,0,0,0,1,9,0,102,97,114,0,
+0,0,1,9,0,100,105,102,102,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,68,101,112,116,104,82,97,110,
+103,101,80,97,114,97,109,101,116,101,114,115,0,0,1,103,108,95,68,101,112,116,104,82,97,110,103,101,
+0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,67,108,105,112,80,108,97,110,101,0,3,18,103,108,95,77,97,120,
+67,108,105,112,80,108,97,110,101,115,0,0,0,2,2,90,95,0,0,24,103,108,95,80,111,105,110,116,80,97,
+114,97,109,101,116,101,114,115,0,9,0,115,105,122,101,0,0,0,1,9,0,115,105,122,101,77,105,110,0,0,0,
+1,9,0,115,105,122,101,77,97,120,0,0,0,1,9,0,102,97,100,101,84,104,114,101,115,104,111,108,100,83,
+105,122,101,0,0,0,1,9,0,100,105,115,116,97,110,99,101,67,111,110,115,116,97,110,116,65,116,116,101,
+110,117,97,116,105,111,110,0,0,0,1,9,0,100,105,115,116,97,110,99,101,76,105,110,101,97,114,65,116,
+116,101,110,117,97,116,105,111,110,0,0,0,1,9,0,100,105,115,116,97,110,99,101,81,117,97,100,114,97,
+116,105,99,65,116,116,101,110,117,97,116,105,111,110,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,80,
+111,105,110,116,80,97,114,97,109,101,116,101,114,115,0,0,1,103,108,95,80,111,105,110,116,0,0,0,2,2,
+90,95,0,0,24,103,108,95,77,97,116,101,114,105,97,108,80,97,114,97,109,101,116,101,114,115,0,12,0,
+101,109,105,115,115,105,111,110,0,0,0,1,12,0,97,109,98,105,101,110,116,0,0,0,1,12,0,100,105,102,
+102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97,114,0,0,0,1,9,0,115,104,105,110,105,110,101,
+115,115,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,77,97,116,101,114,105,97,108,80,97,114,97,109,
+101,116,101,114,115,0,0,1,103,108,95,70,114,111,110,116,77,97,116,101,114,105,97,108,0,0,0,2,2,90,
+95,4,0,25,103,108,95,77,97,116,101,114,105,97,108,80,97,114,97,109,101,116,101,114,115,0,0,1,103,
+108,95,66,97,99,107,77,97,116,101,114,105,97,108,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,
+116,83,111,117,114,99,101,80,97,114,97,109,101,116,101,114,115,0,12,0,97,109,98,105,101,110,116,0,
+0,0,1,12,0,100,105,102,102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97,114,0,0,0,1,12,0,112,
+111,115,105,116,105,111,110,0,0,0,1,12,0,104,97,108,102,86,101,99,116,111,114,0,0,0,1,11,0,115,112,
+111,116,68,105,114,101,99,116,105,111,110,0,0,0,1,9,0,115,112,111,116,67,111,115,67,117,116,111,
+102,102,0,0,0,1,9,0,99,111,110,115,116,97,110,116,65,116,116,101,110,117,97,116,105,111,110,0,0,0,
+1,9,0,108,105,110,101,97,114,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,0,113,117,97,100,
+114,97,116,105,99,65,116,116,101,110,117,97,116,105,111,110,0,0,0,1,9,0,115,112,111,116,69,120,112,
+111,110,101,110,116,0,0,0,1,9,0,115,112,111,116,67,117,116,111,102,102,0,0,0,0,0,0,0,2,2,90,95,4,0,
+25,103,108,95,76,105,103,104,116,83,111,117,114,99,101,80,97,114,97,109,101,116,101,114,115,0,0,1,
+103,108,95,76,105,103,104,116,83,111,117,114,99,101,0,3,18,103,108,95,77,97,120,76,105,103,104,116,
+115,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101,108,80,97,114,97,109,101,
+116,101,114,115,0,12,0,97,109,98,105,101,110,116,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,
+103,104,116,77,111,100,101,108,80,97,114,97,109,101,116,101,114,115,0,0,1,103,108,95,76,105,103,
+104,116,77,111,100,101,108,0,0,0,2,2,90,95,0,0,24,103,108,95,76,105,103,104,116,77,111,100,101,108,
+80,114,111,100,117,99,116,115,0,12,0,115,99,101,110,101,67,111,108,111,114,0,0,0,0,0,0,0,2,2,90,95,
+4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,0,1,103,
+108,95,70,114,111,110,116,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2,
+2,90,95,4,0,25,103,108,95,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,115,0,0,
+1,103,108,95,66,97,99,107,76,105,103,104,116,77,111,100,101,108,80,114,111,100,117,99,116,0,0,0,2,
+2,90,95,0,0,24,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,12,0,97,109,98,105,
+101,110,116,0,0,0,1,12,0,100,105,102,102,117,115,101,0,0,0,1,12,0,115,112,101,99,117,108,97,114,0,
+0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100,117,99,116,115,0,0,1,103,
+108,95,70,114,111,110,116,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18,103,108,95,77,97,120,
+76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,25,103,108,95,76,105,103,104,116,80,114,111,100,117,99,
+116,115,0,0,1,103,108,95,66,97,99,107,76,105,103,104,116,80,114,111,100,117,99,116,0,3,18,103,108,
+95,77,97,120,76,105,103,104,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,84,101,120,116,117,114,
+101,69,110,118,67,111,108,111,114,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,73,109,97,
+103,101,85,110,105,116,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,83,0,
+3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,
+0,1,103,108,95,69,121,101,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,
+101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,69,121,101,80,108,97,110,101,82,0,
+3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,
+0,1,103,108,95,69,121,101,80,108,97,110,101,81,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,
+101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,
+110,101,83,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,
+90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,84,0,3,18,103,108,95,77,97,120,
+84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,
+101,99,116,80,108,97,110,101,82,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,
+114,100,115,0,0,0,2,2,90,95,4,0,12,0,1,103,108,95,79,98,106,101,99,116,80,108,97,110,101,81,0,3,18,
+103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,114,100,115,0,0,0,2,2,90,95,0,0,24,103,
+108,95,70,111,103,80,97,114,97,109,101,116,101,114,115,0,12,0,99,111,108,111,114,0,0,0,1,9,0,100,
+101,110,115,105,116,121,0,0,0,1,9,0,115,116,97,114,116,0,0,0,1,9,0,101,110,100,0,0,0,1,9,0,115,99,
+97,108,101,0,0,0,0,0,0,0,2,2,90,95,4,0,25,103,108,95,70,111,103,80,97,114,97,109,101,116,101,114,
+115,0,0,1,103,108,95,70,111,103,0,0,0,1,90,95,0,0,9,0,0,114,97,100,105,97,110,115,0,1,1,0,0,9,0,
+100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,
+0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,
+18,100,101,103,0,0,18,99,0,0,0,0,1,90,95,0,0,10,0,0,114,97,100,105,97,110,115,0,1,1,0,0,10,0,100,
+101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,0,
+49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,0,0,18,100,101,103,0,59,120,121,0,0,18,99,0,59,120,120,0,0,0,0,1,90,95,0,0,11,0,0,114,97,
+100,105,97,110,115,0,1,1,0,0,11,0,100,101,103,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,
+53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,
+18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,100,101,103,0,59,120,121,122,0,0,18,99,0,59,
+120,120,120,0,0,0,0,1,90,95,0,0,12,0,0,114,97,100,105,97,110,115,0,1,1,0,0,12,0,100,101,103,0,0,0,
+1,3,2,90,95,1,0,9,0,1,99,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,49,56,48,0,48,0,0,49,0,0,4,118,
+101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,100,101,103,0,
+0,18,99,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,9,0,0,100,101,103,114,101,101,115,0,1,1,0,0,9,0,
+114,97,100,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,49,56,48,0,48,0,0,17,51,0,49,52,49,53,57,50,54,0,
+0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,
+18,114,97,100,0,0,18,99,0,0,0,0,1,90,95,0,0,10,0,0,100,101,103,114,101,101,115,0,1,1,0,0,10,0,114,
+97,100,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,49,56,48,0,48,0,0,17,51,0,49,52,49,53,57,50,54,0,0,49,
+0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,0,0,18,114,97,100,0,59,120,121,0,0,18,99,0,59,120,120,0,0,0,0,1,90,95,0,0,11,0,0,100,101,103,
+114,101,101,115,0,1,1,0,0,11,0,114,97,100,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,49,56,48,0,48,0,0,
+17,51,0,49,52,49,53,57,50,54,0,0,49,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,
+95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,114,97,100,0,59,120,121,122,0,0,18,99,0,59,120,
+120,120,0,0,0,0,1,90,95,0,0,12,0,0,100,101,103,114,101,101,115,0,1,1,0,0,12,0,114,97,100,0,0,0,1,3,
+2,90,95,1,0,9,0,1,99,0,2,17,49,56,48,0,48,0,0,17,51,0,49,52,49,53,57,50,54,0,0,49,0,0,4,118,101,99,
+52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,114,97,100,0,0,18,99,
+0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,9,0,0,115,105,110,0,1,1,0,0,9,0,114,97,100,105,97,110,115,
+0,0,0,1,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,114,97,100,
+105,97,110,115,0,0,0,0,1,90,95,0,0,10,0,0,115,105,110,0,1,1,0,0,10,0,114,97,100,105,97,110,115,0,0,
+0,1,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,114,
+97,100,105,97,110,115,0,59,120,0,0,0,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,
+116,86,97,108,0,59,121,0,0,18,114,97,100,105,97,110,115,0,59,121,0,0,0,0,1,90,95,0,0,11,0,0,115,
+105,110,0,1,1,0,0,11,0,114,97,100,105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,115,105,110,101,0,
+18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,114,97,100,105,97,110,115,0,59,120,0,0,0,4,102,108,
+111,97,116,95,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,97,100,105,97,
+110,115,0,59,121,0,0,0,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,
+59,122,0,0,18,114,97,100,105,97,110,115,0,59,122,0,0,0,0,1,90,95,0,0,12,0,0,115,105,110,0,1,1,0,0,
+12,0,114,97,100,105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,
+116,86,97,108,0,59,120,0,0,18,114,97,100,105,97,110,115,0,59,120,0,0,0,4,102,108,111,97,116,95,115,
+105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,97,100,105,97,110,115,0,59,121,0,
+0,0,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,114,
+97,100,105,97,110,115,0,59,122,0,0,0,4,102,108,111,97,116,95,115,105,110,101,0,18,95,95,114,101,
+116,86,97,108,0,59,119,0,0,18,114,97,100,105,97,110,115,0,59,119,0,0,0,0,1,90,95,0,0,9,0,0,99,111,
+115,0,1,1,0,0,9,0,114,97,100,105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,99,111,115,105,110,101,
+0,18,95,95,114,101,116,86,97,108,0,0,18,114,97,100,105,97,110,115,0,0,0,0,1,90,95,0,0,10,0,0,99,
+111,115,0,1,1,0,0,10,0,114,97,100,105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,99,111,115,105,
+110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,114,97,100,105,97,110,115,0,59,120,0,0,0,
+4,102,108,111,97,116,95,99,111,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,
+114,97,100,105,97,110,115,0,59,121,0,0,0,0,1,90,95,0,0,11,0,0,99,111,115,0,1,1,0,0,11,0,114,97,100,
+105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,99,111,115,105,110,101,0,18,95,95,114,101,116,86,97,
+108,0,59,120,0,0,18,114,97,100,105,97,110,115,0,59,120,0,0,0,4,102,108,111,97,116,95,99,111,115,
+105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,97,100,105,97,110,115,0,59,121,0,
+0,0,4,102,108,111,97,116,95,99,111,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,
+18,114,97,100,105,97,110,115,0,59,122,0,0,0,0,1,90,95,0,0,12,0,0,99,111,115,0,1,1,0,0,12,0,114,97,
+100,105,97,110,115,0,0,0,1,4,102,108,111,97,116,95,99,111,115,105,110,101,0,18,95,95,114,101,116,
+86,97,108,0,59,120,0,0,18,114,97,100,105,97,110,115,0,59,120,0,0,0,4,102,108,111,97,116,95,99,111,
+115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,97,100,105,97,110,115,0,59,
+121,0,0,0,4,102,108,111,97,116,95,99,111,115,105,110,101,0,18,95,95,114,101,116,86,97,108,0,59,122,
+0,0,18,114,97,100,105,97,110,115,0,59,122,0,0,0,4,102,108,111,97,116,95,99,111,115,105,110,101,0,
+18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,114,97,100,105,97,110,115,0,59,119,0,0,0,0,1,90,95,
+0,0,9,0,0,116,97,110,0,1,1,0,0,9,0,97,110,103,108,101,0,0,0,1,3,2,90,95,1,0,9,0,1,115,0,2,58,115,
+105,110,0,0,18,97,110,103,108,101,0,0,0,0,0,3,2,90,95,1,0,9,0,1,99,0,2,58,99,111,115,0,0,18,97,110,
+103,108,101,0,0,0,0,0,8,18,115,0,18,99,0,49,0,0,1,90,95,0,0,10,0,0,116,97,110,0,1,1,0,0,10,0,97,
+110,103,108,101,0,0,0,1,3,2,90,95,1,0,10,0,1,115,0,2,58,115,105,110,0,0,18,97,110,103,108,101,0,0,
+0,0,0,3,2,90,95,1,0,10,0,1,99,0,2,58,99,111,115,0,0,18,97,110,103,108,101,0,0,0,0,0,8,18,115,0,18,
+99,0,49,0,0,1,90,95,0,0,11,0,0,116,97,110,0,1,1,0,0,11,0,97,110,103,108,101,0,0,0,1,3,2,90,95,1,0,
+11,0,1,115,0,2,58,115,105,110,0,0,18,97,110,103,108,101,0,0,0,0,0,3,2,90,95,1,0,11,0,1,99,0,2,58,
+99,111,115,0,0,18,97,110,103,108,101,0,0,0,0,0,8,18,115,0,18,99,0,49,0,0,1,90,95,0,0,12,0,0,116,97,
+110,0,1,1,0,0,12,0,97,110,103,108,101,0,0,0,1,3,2,90,95,1,0,12,0,1,115,0,2,58,115,105,110,0,0,18,
+97,110,103,108,101,0,0,0,0,0,3,2,90,95,1,0,12,0,1,99,0,2,58,99,111,115,0,0,18,97,110,103,108,101,0,
+0,0,0,0,8,18,115,0,18,99,0,49,0,0,1,90,95,0,0,9,0,0,97,115,105,110,0,1,1,0,0,9,0,120,0,0,0,1,3,2,
+90,95,1,0,9,0,1,97,48,0,2,17,49,0,53,55,48,55,50,56,56,0,0,0,0,3,2,90,95,1,0,9,0,1,97,49,0,2,17,48,
+0,50,49,50,49,49,52,52,0,0,54,0,0,3,2,90,95,1,0,9,0,1,97,50,0,2,17,48,0,48,55,52,50,54,49,48,0,0,0,
+0,3,2,90,95,1,0,9,0,1,104,97,108,102,80,105,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,48,0,53,0,0,48,
+0,0,3,2,90,95,1,0,9,0,1,121,0,2,58,97,98,115,0,0,18,120,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,
+0,18,104,97,108,102,80,105,0,58,115,113,114,116,0,0,17,49,0,48,0,0,18,121,0,47,0,0,18,97,48,0,18,
+121,0,18,97,49,0,18,97,50,0,18,121,0,48,46,48,46,48,47,58,115,105,103,110,0,0,18,120,0,0,0,48,20,0,
+0,1,90,95,0,0,10,0,0,97,115,105,110,0,1,1,0,0,10,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+59,120,0,58,97,115,105,110,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,
+121,0,58,97,115,105,110,0,0,18,118,0,59,121,0,0,0,20,0,0,1,90,95,0,0,11,0,0,97,115,105,110,0,1,1,0,
+0,11,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,97,115,105,110,0,0,18,118,0,59,
+120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,115,105,110,0,0,18,118,0,59,121,0,
+0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,97,115,105,110,0,0,18,118,0,59,122,0,0,0,
+20,0,0,1,90,95,0,0,12,0,0,97,115,105,110,0,1,1,0,0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,59,120,0,58,97,115,105,110,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+59,121,0,58,97,115,105,110,0,0,18,118,0,59,121,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,
+122,0,58,97,115,105,110,0,0,18,118,0,59,122,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,
+58,97,115,105,110,0,0,18,118,0,59,119,0,0,0,20,0,0,1,90,95,0,0,9,0,0,97,99,111,115,0,1,1,0,0,9,0,
+120,0,0,0,1,3,2,90,95,1,0,9,0,1,104,97,108,102,80,105,0,2,17,51,0,49,52,49,53,57,50,54,0,0,17,48,0,
+53,0,0,48,0,0,9,18,95,95,114,101,116,86,97,108,0,18,104,97,108,102,80,105,0,58,97,115,105,110,0,0,
+18,120,0,0,0,47,20,0,0,1,90,95,0,0,10,0,0,97,99,111,115,0,1,1,0,0,10,0,118,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,59,120,0,58,97,99,111,115,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,121,0,58,97,99,111,115,0,0,18,118,0,59,121,0,0,0,20,0,0,1,90,95,0,0,11,0,0,97,
+99,111,115,0,1,1,0,0,11,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,97,99,111,115,
+0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,99,111,115,0,0,18,
+118,0,59,121,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,97,99,111,115,0,0,18,118,0,
+59,122,0,0,0,20,0,0,1,90,95,0,0,12,0,0,97,99,111,115,0,1,1,0,0,12,0,118,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,59,120,0,58,97,99,111,115,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,
+97,108,0,59,121,0,58,97,99,111,115,0,0,18,118,0,59,121,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,
+0,59,122,0,58,97,99,111,115,0,0,18,118,0,59,122,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,
+119,0,58,97,99,111,115,0,0,18,118,0,59,119,0,0,0,20,0,0,1,90,95,0,0,9,0,0,97,116,97,110,0,1,1,0,0,
+9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,97,115,105,110,0,0,18,120,0,58,105,110,118,
+101,114,115,101,115,113,114,116,0,0,18,120,0,18,120,0,48,17,49,0,48,0,0,46,0,0,48,0,0,20,0,0,1,90,
+95,0,0,10,0,0,97,116,97,110,0,1,1,0,0,10,0,121,95,111,118,101,114,95,120,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,59,120,0,58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,120,0,59,120,0,0,0,
+20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,
+120,0,59,121,0,0,0,20,0,0,1,90,95,0,0,11,0,0,97,116,97,110,0,1,1,0,0,11,0,121,95,111,118,101,114,
+95,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,97,116,97,110,0,0,18,121,95,111,118,
+101,114,95,120,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,116,97,110,0,
+0,18,121,95,111,118,101,114,95,120,0,59,121,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,
+58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,120,0,59,122,0,0,0,20,0,0,1,90,95,0,0,12,0,0,97,
+116,97,110,0,1,1,0,0,12,0,121,95,111,118,101,114,95,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+59,120,0,58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,120,0,59,120,0,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,120,0,59,121,0,0,0,
+20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,97,116,97,110,0,0,18,121,95,111,118,101,114,95,
+120,0,59,122,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,97,116,97,110,0,0,18,121,95,
+111,118,101,114,95,120,0,59,119,0,0,0,20,0,0,1,90,95,0,0,9,0,0,97,116,97,110,0,1,1,0,0,9,0,121,0,0,
+1,1,0,0,9,0,120,0,0,0,1,3,2,90,95,0,0,9,0,1,114,0,0,0,10,58,97,98,115,0,0,18,120,0,0,0,17,49,0,48,
+0,45,52,0,41,0,2,9,18,114,0,58,97,116,97,110,0,0,18,121,0,18,120,0,49,0,0,20,0,10,18,120,0,17,48,0,
+48,0,0,40,0,2,9,18,114,0,18,114,0,58,115,105,103,110,0,0,18,121,0,0,0,17,51,0,49,52,49,53,57,51,0,
+0,48,46,20,0,0,9,14,0,0,2,9,18,114,0,58,115,105,103,110,0,0,18,121,0,0,0,17,49,0,53,55,48,55,57,54,
+53,0,0,48,20,0,0,8,18,114,0,0,0,1,90,95,0,0,10,0,0,97,116,97,110,0,1,1,0,0,10,0,117,0,0,1,1,0,0,10,
+0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,97,116,97,110,0,0,18,117,0,59,120,0,0,
+18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,116,97,110,0,0,18,117,
+0,59,121,0,0,18,118,0,59,121,0,0,0,20,0,0,1,90,95,0,0,11,0,0,97,116,97,110,0,1,1,0,0,11,0,117,0,0,
+1,1,0,0,11,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,97,116,97,110,0,0,18,117,0,
+59,120,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,97,116,97,110,
+0,0,18,117,0,59,121,0,0,18,118,0,59,121,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,
+97,116,97,110,0,0,18,117,0,59,122,0,0,18,118,0,59,122,0,0,0,20,0,0,1,90,95,0,0,12,0,0,97,116,97,
+110,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,
+97,116,97,110,0,0,18,117,0,59,120,0,0,18,118,0,59,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,
+0,59,121,0,58,97,116,97,110,0,0,18,117,0,59,121,0,0,18,118,0,59,121,0,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,122,0,58,97,116,97,110,0,0,18,117,0,59,122,0,0,18,118,0,59,122,0,0,0,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,119,0,58,97,116,97,110,0,0,18,117,0,59,119,0,0,18,118,0,59,119,0,
+0,0,20,0,0,1,90,95,0,0,9,0,0,112,111,119,0,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,102,108,111,
+97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,
+0,0,10,0,0,112,111,119,0,1,1,0,0,10,0,97,0,0,1,1,0,0,10,0,98,0,0,0,1,4,102,108,111,97,116,95,112,
+111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,97,0,59,120,0,0,18,98,0,59,120,0,
+0,0,4,102,108,111,97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,
+97,0,59,121,0,0,18,98,0,59,121,0,0,0,0,1,90,95,0,0,11,0,0,112,111,119,0,1,1,0,0,11,0,97,0,0,1,1,0,
+0,11,0,98,0,0,0,1,4,102,108,111,97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,
+59,120,0,0,18,97,0,59,120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,112,111,119,101,114,0,
+18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,97,0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,
+97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,97,0,59,122,0,0,18,
+98,0,59,122,0,0,0,0,1,90,95,0,0,12,0,0,112,111,119,0,1,1,0,0,12,0,97,0,0,1,1,0,0,12,0,98,0,0,0,1,4,
+102,108,111,97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,97,0,59,
+120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,
+97,108,0,59,121,0,0,18,97,0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,97,116,95,112,111,119,
+101,114,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,97,0,59,122,0,0,18,98,0,59,122,0,0,0,4,
+102,108,111,97,116,95,112,111,119,101,114,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,97,0,59,
+119,0,0,18,98,0,59,119,0,0,0,0,1,90,95,0,0,9,0,0,101,120,112,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,
+0,9,0,1,116,0,2,18,97,0,17,49,0,52,52,50,54,57,53,48,50,0,0,48,0,0,4,102,108,111,97,116,95,101,120,
+112,50,0,18,95,95,114,101,116,86,97,108,0,0,18,116,0,0,0,0,1,90,95,0,0,10,0,0,101,120,112,0,1,1,0,
+0,10,0,97,0,0,0,1,3,2,90,95,0,0,10,0,1,116,0,2,18,97,0,17,49,0,52,52,50,54,57,53,48,50,0,0,48,0,0,
+4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,116,0,59,
+120,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,
+116,0,59,121,0,0,0,0,1,90,95,0,0,11,0,0,101,120,112,0,1,1,0,0,11,0,97,0,0,0,1,3,2,90,95,0,0,11,0,1,
+116,0,2,18,97,0,17,49,0,52,52,50,54,57,53,48,50,0,0,48,0,0,4,102,108,111,97,116,95,101,120,112,50,
+0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,116,0,59,120,0,0,0,4,102,108,111,97,116,95,101,
+120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,116,0,59,121,0,0,0,4,102,108,111,97,
+116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,116,0,59,122,0,0,0,0,1,90,
+95,0,0,12,0,0,101,120,112,0,1,1,0,0,12,0,97,0,0,0,1,3,2,90,95,0,0,12,0,1,116,0,2,18,97,0,17,49,0,
+52,52,50,54,57,53,48,50,0,0,48,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,
+86,97,108,0,59,120,0,0,18,116,0,59,120,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,
+101,116,86,97,108,0,59,121,0,0,18,116,0,59,121,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,
+95,95,114,101,116,86,97,108,0,59,122,0,0,18,116,0,59,122,0,0,0,4,102,108,111,97,116,95,101,120,112,
+50,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,116,0,59,119,0,0,0,0,1,90,95,0,0,9,0,0,108,111,
+103,50,0,1,1,0,0,9,0,120,0,0,0,1,4,102,108,111,97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,
+97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,108,111,103,50,0,1,1,0,0,10,0,118,0,0,0,1,4,102,108,
+111,97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,4,
+102,108,111,97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,
+0,0,0,0,1,90,95,0,0,11,0,0,108,111,103,50,0,1,1,0,0,11,0,118,0,0,0,1,4,102,108,111,97,116,95,108,
+111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,4,102,108,111,97,
+116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,0,0,0,4,102,
+108,111,97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,118,0,59,122,0,0,
+0,0,1,90,95,0,0,12,0,0,108,111,103,50,0,1,1,0,0,12,0,118,0,0,0,1,4,102,108,111,97,116,95,108,111,
+103,50,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,4,102,108,111,97,116,95,
+108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,0,0,0,4,102,108,111,
+97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,118,0,59,122,0,0,0,4,102,
+108,111,97,116,95,108,111,103,50,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,118,0,59,119,0,0,
+0,0,1,90,95,0,0,9,0,0,108,111,103,0,1,1,0,0,9,0,120,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,48,0,54,
+57,51,49,52,55,49,56,49,0,0,0,0,8,58,108,111,103,50,0,0,18,120,0,0,0,18,99,0,48,0,0,1,90,95,0,0,10,
+0,0,108,111,103,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,48,0,54,57,51,49,52,55,49,
+56,49,0,0,0,0,8,58,108,111,103,50,0,0,18,118,0,0,0,18,99,0,48,0,0,1,90,95,0,0,11,0,0,108,111,103,0,
+1,1,0,0,11,0,118,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,48,0,54,57,51,49,52,55,49,56,49,0,0,0,0,8,
+58,108,111,103,50,0,0,18,118,0,0,0,18,99,0,48,0,0,1,90,95,0,0,12,0,0,108,111,103,0,1,1,0,0,12,0,
+118,0,0,0,1,3,2,90,95,1,0,9,0,1,99,0,2,17,48,0,54,57,51,49,52,55,49,56,49,0,0,0,0,8,58,108,111,103,
+50,0,0,18,118,0,0,0,18,99,0,48,0,0,1,90,95,0,0,9,0,0,101,120,112,50,0,1,1,0,0,9,0,97,0,0,0,1,4,102,
+108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,0,0,1,90,95,0,0,10,
+0,0,101,120,112,50,0,1,1,0,0,10,0,97,0,0,0,1,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,
+101,116,86,97,108,0,59,120,0,0,18,97,0,59,120,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,
+95,114,101,116,86,97,108,0,59,121,0,0,18,97,0,59,121,0,0,0,0,1,90,95,0,0,11,0,0,101,120,112,50,0,1,
+1,0,0,11,0,97,0,0,0,1,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,
+120,0,0,18,97,0,59,120,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,
+108,0,59,121,0,0,18,97,0,59,121,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,
+116,86,97,108,0,59,122,0,0,18,97,0,59,122,0,0,0,0,1,90,95,0,0,12,0,0,101,120,112,50,0,1,1,0,0,12,0,
+97,0,0,0,1,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,
+97,0,59,120,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,59,121,
+0,0,18,97,0,59,121,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,97,108,0,
+59,122,0,0,18,97,0,59,122,0,0,0,4,102,108,111,97,116,95,101,120,112,50,0,18,95,95,114,101,116,86,
+97,108,0,59,119,0,0,18,97,0,59,119,0,0,0,0,1,90,95,0,0,9,0,0,115,113,114,116,0,1,1,0,0,9,0,120,0,0,
+0,1,3,2,90,95,0,0,9,0,1,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,120,0,0,0,4,
+102,108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,0,18,114,0,0,0,0,1,90,95,0,0,
+10,0,0,115,113,114,116,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,114,0,0,0,4,102,108,111,97,
+116,95,114,115,113,0,18,114,0,0,18,118,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,95,
+95,114,101,116,86,97,108,0,59,120,0,0,18,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,
+0,18,118,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,
+121,0,0,18,114,0,0,0,0,1,90,95,0,0,11,0,0,115,113,114,116,0,1,1,0,0,11,0,118,0,0,0,1,3,2,90,95,0,0,
+9,0,1,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,118,0,59,120,0,0,0,4,102,108,
+111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,114,0,0,0,4,102,108,111,
+97,116,95,114,115,113,0,18,114,0,0,18,118,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,
+95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,
+0,0,18,118,0,59,122,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,
+122,0,0,18,114,0,0,0,0,1,90,95,0,0,12,0,0,115,113,114,116,0,1,1,0,0,12,0,118,0,0,0,1,3,2,90,95,0,0,
+9,0,1,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,118,0,59,120,0,0,0,4,102,108,
+111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,114,0,0,0,4,102,108,111,
+97,116,95,114,115,113,0,18,114,0,0,18,118,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,
+95,95,114,101,116,86,97,108,0,59,121,0,0,18,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,
+0,0,18,118,0,59,122,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,
+122,0,0,18,114,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,118,0,59,119,0,0,0,4,102,
+108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,114,0,0,0,0,1,90,95,
+0,0,9,0,0,105,110,118,101,114,115,101,115,113,114,116,0,1,1,0,0,9,0,120,0,0,0,1,4,102,108,111,97,
+116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,
+105,110,118,101,114,115,101,115,113,114,116,0,1,1,0,0,10,0,118,0,0,0,1,4,102,108,111,97,116,95,114,
+115,113,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,4,102,108,111,97,116,
+95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,0,0,0,0,1,90,95,0,0,
+11,0,0,105,110,118,101,114,115,101,115,113,114,116,0,1,1,0,0,11,0,118,0,0,0,1,4,102,108,111,97,116,
+95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,4,102,108,111,
+97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,0,0,0,4,102,
+108,111,97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,118,0,59,122,0,0,0,
+0,1,90,95,0,0,12,0,0,105,110,118,101,114,115,101,115,113,114,116,0,1,1,0,0,12,0,118,0,0,0,1,4,102,
+108,111,97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,118,0,59,120,0,0,0,
+4,102,108,111,97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,118,0,59,121,
+0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,118,0,
+59,122,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,
+118,0,59,119,0,0,0,0,1,90,95,0,0,9,0,0,110,111,114,109,97,108,105,122,101,0,1,1,0,0,9,0,120,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,17,49,0,48,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,114,109,97,
+108,105,122,101,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,1,0,9,0,1,115,0,2,58,105,110,118,101,114,115,
+101,115,113,114,116,0,0,58,100,111,116,0,0,18,118,0,0,18,118,0,0,0,0,0,0,0,4,118,101,99,52,95,109,
+117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,18,115,0,
+0,0,0,1,90,95,0,0,11,0,0,110,111,114,109,97,108,105,122,101,0,1,1,0,0,11,0,118,0,0,0,1,3,2,90,95,0,
+0,9,0,1,116,109,112,0,0,0,4,118,101,99,51,95,100,111,116,0,18,116,109,112,0,0,18,118,0,0,18,118,0,
+0,0,4,102,108,111,97,116,95,114,115,113,0,18,116,109,112,0,0,18,116,109,112,0,0,0,4,118,101,99,52,
+95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,
+0,18,116,109,112,0,0,0,0,1,90,95,0,0,12,0,0,110,111,114,109,97,108,105,122,101,0,1,1,0,0,12,0,118,
+0,0,0,1,3,2,90,95,0,0,9,0,1,116,109,112,0,0,0,4,118,101,99,52,95,100,111,116,0,18,116,109,112,0,0,
+18,118,0,0,18,118,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,116,109,112,0,0,18,116,109,112,0,
+0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,122,0,0,18,118,0,0,18,116,109,112,0,0,0,0,1,90,95,0,0,9,0,0,97,98,115,0,1,1,0,0,9,0,97,0,0,0,1,
+4,118,101,99,52,95,97,98,115,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,0,0,1,90,95,0,0,10,0,0,
+97,98,115,0,1,1,0,0,10,0,97,0,0,0,1,4,118,101,99,52,95,97,98,115,0,18,95,95,114,101,116,86,97,108,
+0,59,120,121,0,0,18,97,0,0,0,0,1,90,95,0,0,11,0,0,97,98,115,0,1,1,0,0,11,0,97,0,0,0,1,4,118,101,99,
+52,95,97,98,115,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,0,0,0,1,90,95,0,0,12,
+0,0,97,98,115,0,1,1,0,0,12,0,97,0,0,0,1,4,118,101,99,52,95,97,98,115,0,18,95,95,114,101,116,86,97,
+108,0,0,18,97,0,0,0,0,1,90,95,0,0,9,0,0,115,105,103,110,0,1,1,0,0,9,0,120,0,0,0,1,3,2,90,95,0,0,9,
+0,1,112,0,0,1,1,110,0,0,0,4,118,101,99,52,95,115,103,116,0,18,112,0,0,18,120,0,0,17,48,0,48,0,0,0,
+0,4,118,101,99,52,95,115,103,116,0,18,110,0,0,17,48,0,48,0,0,0,18,120,0,0,0,4,118,101,99,52,95,115,
+117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,18,110,0,0,0,0,1,90,95,0,
+0,10,0,0,115,105,103,110,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,0,0,10,0,1,112,0,0,1,1,110,0,0,0,4,
+118,101,99,52,95,115,103,116,0,18,112,0,59,120,121,0,0,18,118,0,0,17,48,0,48,0,0,0,0,4,118,101,99,
+52,95,115,103,116,0,18,110,0,59,120,121,0,0,17,48,0,48,0,0,0,18,118,0,0,0,4,118,101,99,52,95,115,
+117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,112,0,0,18,110,0,0,0,
+0,1,90,95,0,0,11,0,0,115,105,103,110,0,1,1,0,0,11,0,118,0,0,0,1,3,2,90,95,0,0,11,0,1,112,0,0,1,1,
+110,0,0,0,4,118,101,99,52,95,115,103,116,0,18,112,0,59,120,121,122,0,0,18,118,0,0,17,48,0,48,0,0,0,
+0,4,118,101,99,52,95,115,103,116,0,18,110,0,59,120,121,122,0,0,17,48,0,48,0,0,0,18,118,0,0,0,4,118,
+101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,
+112,0,0,18,110,0,0,0,0,1,90,95,0,0,12,0,0,115,105,103,110,0,1,1,0,0,12,0,118,0,0,0,1,3,2,90,95,0,0,
+12,0,1,112,0,0,1,1,110,0,0,0,4,118,101,99,52,95,115,103,116,0,18,112,0,0,18,118,0,0,17,48,0,48,0,0,
+0,0,4,118,101,99,52,95,115,103,116,0,18,110,0,0,17,48,0,48,0,0,0,18,118,0,0,0,4,118,101,99,52,95,
+115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,18,110,0,0,0,0,1,90,
+95,0,0,9,0,0,102,108,111,111,114,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,102,108,111,111,114,0,
+18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,0,0,1,90,95,0,0,10,0,0,102,108,111,111,114,0,1,1,0,0,
+10,0,97,0,0,0,1,4,118,101,99,52,95,102,108,111,111,114,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,0,0,18,97,0,0,0,0,1,90,95,0,0,11,0,0,102,108,111,111,114,0,1,1,0,0,11,0,97,0,0,0,1,4,118,101,
+99,52,95,102,108,111,111,114,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,0,0,0,1,
+90,95,0,0,12,0,0,102,108,111,111,114,0,1,1,0,0,12,0,97,0,0,0,1,4,118,101,99,52,95,102,108,111,111,
+114,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,0,0,1,90,95,0,0,9,0,0,99,101,105,108,0,1,1,0,0,
+9,0,97,0,0,0,1,3,2,90,95,0,0,9,0,1,98,0,2,18,97,0,54,0,0,4,118,101,99,52,95,102,108,111,111,114,0,
+18,98,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,98,0,54,20,0,0,1,90,95,0,0,10,0,0,99,
+101,105,108,0,1,1,0,0,10,0,97,0,0,0,1,3,2,90,95,0,0,10,0,1,98,0,2,18,97,0,54,0,0,4,118,101,99,52,
+95,102,108,111,111,114,0,18,98,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,0,59,120,121,0,18,
+98,0,54,20,0,0,1,90,95,0,0,11,0,0,99,101,105,108,0,1,1,0,0,11,0,97,0,0,0,1,3,2,90,95,0,0,11,0,1,98,
+0,2,18,97,0,54,0,0,4,118,101,99,52,95,102,108,111,111,114,0,18,98,0,0,18,98,0,0,0,9,18,95,95,114,
+101,116,86,97,108,0,59,120,121,122,0,18,98,0,54,20,0,0,1,90,95,0,0,12,0,0,99,101,105,108,0,1,1,0,0,
+12,0,97,0,0,0,1,3,2,90,95,0,0,12,0,1,98,0,2,18,97,0,54,0,0,4,118,101,99,52,95,102,108,111,111,114,
+0,18,98,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,98,0,54,20,0,0,1,90,95,0,0,9,0,0,102,
+114,97,99,116,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,102,114,97,99,0,18,95,95,114,101,116,86,
+97,108,0,0,18,97,0,0,0,0,1,90,95,0,0,10,0,0,102,114,97,99,116,0,1,1,0,0,10,0,97,0,0,0,1,4,118,101,
+99,52,95,102,114,97,99,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,97,0,0,0,0,1,90,95,0,0,
+11,0,0,102,114,97,99,116,0,1,1,0,0,11,0,97,0,0,0,1,4,118,101,99,52,95,102,114,97,99,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,0,0,0,1,90,95,0,0,12,0,0,102,114,97,99,116,0,1,1,0,
+0,12,0,97,0,0,0,1,4,118,101,99,52,95,102,114,97,99,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,
+0,0,1,90,95,0,0,9,0,0,109,111,100,0,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,
+111,110,101,79,118,101,114,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,
+114,66,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,18,98,0,58,102,108,111,111,114,0,
+0,18,97,0,18,111,110,101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,95,0,0,10,0,0,109,111,100,0,
+1,1,0,0,10,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,111,110,101,79,118,101,114,66,0,0,0,
+4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,66,0,0,18,98,0,0,0,9,18,95,95,
+114,101,116,86,97,108,0,59,120,121,0,18,97,0,18,98,0,58,102,108,111,111,114,0,0,18,97,0,18,111,110,
+101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,95,0,0,11,0,0,109,111,100,0,1,1,0,0,11,0,97,0,0,1,
+1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,111,110,101,79,118,101,114,66,0,0,0,4,102,108,111,97,116,
+95,114,99,112,0,18,111,110,101,79,118,101,114,66,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,
+0,59,120,121,122,0,18,97,0,18,98,0,58,102,108,111,111,114,0,0,18,97,0,18,111,110,101,79,118,101,
+114,66,0,48,0,0,48,47,20,0,0,1,90,95,0,0,12,0,0,109,111,100,0,1,1,0,0,12,0,97,0,0,1,1,0,0,9,0,98,0,
+0,0,1,3,2,90,95,0,0,9,0,1,111,110,101,79,118,101,114,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,
+18,111,110,101,79,118,101,114,66,0,0,18,98,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,18,98,
+0,58,102,108,111,111,114,0,0,18,97,0,18,111,110,101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,
+95,0,0,10,0,0,109,111,100,0,1,1,0,0,10,0,97,0,0,1,1,0,0,10,0,98,0,0,0,1,3,2,90,95,0,0,10,0,1,111,
+110,101,79,118,101,114,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,
+66,0,59,120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,
+101,114,66,0,59,121,0,0,18,98,0,59,121,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,18,98,0,58,
+102,108,111,111,114,0,0,18,97,0,18,111,110,101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,95,0,0,
+11,0,0,109,111,100,0,1,1,0,0,11,0,97,0,0,1,1,0,0,11,0,98,0,0,0,1,3,2,90,95,0,0,11,0,1,111,110,101,
+79,118,101,114,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,66,0,59,
+120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,66,
+0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,
+114,66,0,59,122,0,0,18,98,0,59,122,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,18,98,0,58,102,
+108,111,111,114,0,0,18,97,0,18,111,110,101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,95,0,0,12,
+0,0,109,111,100,0,1,1,0,0,12,0,97,0,0,1,1,0,0,12,0,98,0,0,0,1,3,2,90,95,0,0,12,0,1,111,110,101,79,
+118,101,114,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,66,0,59,
+120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,114,66,
+0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,118,101,
+114,66,0,59,122,0,0,18,98,0,59,122,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,111,110,101,79,
+118,101,114,66,0,59,119,0,0,18,98,0,59,119,0,0,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,18,98,
+0,58,102,108,111,111,114,0,0,18,97,0,18,111,110,101,79,118,101,114,66,0,48,0,0,48,47,20,0,0,1,90,
+95,0,0,9,0,0,109,105,110,0,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,105,
+110,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,10,0,0,109,105,110,0,
+1,1,0,0,10,0,97,0,0,1,1,0,0,10,0,98,0,0,0,1,4,118,101,99,52,95,109,105,110,0,18,95,95,114,101,116,
+86,97,108,0,59,120,121,0,0,18,97,0,59,120,121,0,0,18,98,0,59,120,121,0,0,0,0,1,90,95,0,0,11,0,0,
+109,105,110,0,1,1,0,0,11,0,97,0,0,1,1,0,0,11,0,98,0,0,0,1,4,118,101,99,52,95,109,105,110,0,18,95,
+95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,59,120,121,122,0,0,18,98,0,59,120,121,122,0,
+0,0,0,1,90,95,0,0,12,0,0,109,105,110,0,1,1,0,0,12,0,97,0,0,1,1,0,0,12,0,98,0,0,0,1,4,118,101,99,52,
+95,109,105,110,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,10,0,0,109,
+105,110,0,1,1,0,0,10,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,105,110,0,18,95,95,114,
+101,116,86,97,108,0,0,18,97,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,0,109,105,110,0,1,1,0,
+0,11,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,105,110,0,18,95,95,114,101,116,86,97,
+108,0,0,18,97,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,12,0,0,109,105,110,0,1,1,0,0,12,0,97,
+0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,105,110,0,18,95,95,114,101,116,86,97,108,0,0,18,
+97,0,0,18,98,0,0,0,0,1,90,95,0,0,9,0,0,109,97,120,0,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,
+118,101,99,52,95,109,97,120,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,
+0,10,0,0,109,97,120,0,1,1,0,0,10,0,97,0,0,1,1,0,0,10,0,98,0,0,0,1,4,118,101,99,52,95,109,97,120,0,
+18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,97,0,59,120,121,0,0,18,98,0,59,120,121,0,0,0,0,
+1,90,95,0,0,11,0,0,109,97,120,0,1,1,0,0,11,0,97,0,0,1,1,0,0,11,0,98,0,0,0,1,4,118,101,99,52,95,109,
+97,120,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,59,120,121,122,0,0,18,98,0,59,
+120,121,122,0,0,0,0,1,90,95,0,0,12,0,0,109,97,120,0,1,1,0,0,12,0,97,0,0,1,1,0,0,12,0,98,0,0,0,1,4,
+118,101,99,52,95,109,97,120,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,
+0,10,0,0,109,97,120,0,1,1,0,0,10,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,97,120,0,
+18,95,95,114,101,116,86,97,108,0,0,18,97,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,0,109,97,
+120,0,1,1,0,0,11,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,97,120,0,18,95,95,114,101,
+116,86,97,108,0,0,18,97,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,12,0,0,109,97,120,0,1,1,0,0,
+12,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,97,120,0,18,95,95,114,101,116,86,97,108,
+0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,9,0,0,99,108,97,109,112,0,1,1,0,0,9,0,118,97,108,0,0,1,1,0,
+0,9,0,109,105,110,86,97,108,0,0,1,1,0,0,9,0,109,97,120,86,97,108,0,0,0,1,4,118,101,99,52,95,99,108,
+97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,105,110,86,97,108,0,0,18,
+109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,10,0,0,99,108,97,109,112,0,1,1,0,0,10,0,118,97,108,0,0,1,
+1,0,0,9,0,109,105,110,86,97,108,0,0,1,1,0,0,9,0,109,97,120,86,97,108,0,0,0,1,4,118,101,99,52,95,99,
+108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,105,110,86,97,108,0,0,
+18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,11,0,0,99,108,97,109,112,0,1,1,0,0,11,0,118,97,108,0,0,
+1,1,0,0,9,0,109,105,110,86,97,108,0,0,1,1,0,0,9,0,109,97,120,86,97,108,0,0,0,1,4,118,101,99,52,95,
+99,108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,105,110,86,97,108,
+0,0,18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,12,0,0,99,108,97,109,112,0,1,1,0,0,12,0,118,97,108,
+0,0,1,1,0,0,9,0,109,105,110,86,97,108,0,0,1,1,0,0,9,0,109,97,120,86,97,108,0,0,0,1,4,118,101,99,52,
+95,99,108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,105,110,86,97,
+108,0,0,18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,10,0,0,99,108,97,109,112,0,1,1,0,0,10,0,118,97,
+108,0,0,1,1,0,0,10,0,109,105,110,86,97,108,0,0,1,1,0,0,10,0,109,97,120,86,97,108,0,0,0,1,4,118,101,
+99,52,95,99,108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,105,110,
+86,97,108,0,0,18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,11,0,0,99,108,97,109,112,0,1,1,0,0,11,0,
+118,97,108,0,0,1,1,0,0,11,0,109,105,110,86,97,108,0,0,1,1,0,0,11,0,109,97,120,86,97,108,0,0,0,1,4,
+118,101,99,52,95,99,108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,109,
+105,110,86,97,108,0,0,18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,12,0,0,99,108,97,109,112,0,1,1,0,
+0,12,0,118,97,108,0,0,1,1,0,0,12,0,109,105,110,86,97,108,0,0,1,1,0,0,12,0,109,97,120,86,97,108,0,0,
+0,1,4,118,101,99,52,95,99,108,97,109,112,0,18,95,95,114,101,116,86,97,108,0,0,18,118,97,108,0,0,18,
+109,105,110,86,97,108,0,0,18,109,97,120,86,97,108,0,0,0,0,1,90,95,0,0,9,0,0,109,105,120,0,1,1,0,0,
+9,0,120,0,0,1,1,0,0,9,0,121,0,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,108,114,112,0,18,95,95,
+114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,109,105,120,0,1,1,
+0,0,10,0,120,0,0,1,1,0,0,10,0,121,0,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,108,114,112,0,18,
+95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,95,0,0,11,0,0,109,105,120,
+0,1,1,0,0,11,0,120,0,0,1,1,0,0,11,0,121,0,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,108,114,112,
+0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,95,0,0,12,0,0,109,
+105,120,0,1,1,0,0,12,0,120,0,0,1,1,0,0,12,0,121,0,0,1,1,0,0,9,0,97,0,0,0,1,4,118,101,99,52,95,108,
+114,112,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,
+0,109,105,120,0,1,1,0,0,10,0,120,0,0,1,1,0,0,10,0,121,0,0,1,1,0,0,10,0,97,0,0,0,1,4,118,101,99,52,
+95,108,114,112,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,95,0,
+0,11,0,0,109,105,120,0,1,1,0,0,11,0,120,0,0,1,1,0,0,11,0,121,0,0,1,1,0,0,11,0,97,0,0,0,1,4,118,101,
+99,52,95,108,114,112,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,0,0,1,90,
+95,0,0,12,0,0,109,105,120,0,1,1,0,0,12,0,120,0,0,1,1,0,0,12,0,121,0,0,1,1,0,0,12,0,97,0,0,0,1,4,
+118,101,99,52,95,108,114,112,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,121,0,0,18,120,0,0,
+0,0,1,90,95,0,0,9,0,0,115,116,101,112,0,1,1,0,0,9,0,101,100,103,101,0,0,1,1,0,0,9,0,120,0,0,0,1,4,
+118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,18,101,100,103,101,0,
+0,0,0,1,90,95,0,0,10,0,0,115,116,101,112,0,1,1,0,0,10,0,101,100,103,101,0,0,1,1,0,0,10,0,120,0,0,0,
+1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,120,0,0,18,
+101,100,103,101,0,0,0,0,1,90,95,0,0,11,0,0,115,116,101,112,0,1,1,0,0,11,0,101,100,103,101,0,0,1,1,
+0,0,11,0,120,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,
+122,0,0,18,120,0,0,18,101,100,103,101,0,0,0,0,1,90,95,0,0,12,0,0,115,116,101,112,0,1,1,0,0,12,0,
+101,100,103,101,0,0,1,1,0,0,12,0,120,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,
+86,97,108,0,0,18,120,0,0,18,101,100,103,101,0,0,0,0,1,90,95,0,0,10,0,0,115,116,101,112,0,1,1,0,0,9,
+0,101,100,103,101,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,
+116,86,97,108,0,59,120,121,0,0,18,118,0,0,18,101,100,103,101,0,0,0,0,1,90,95,0,0,11,0,0,115,116,
+101,112,0,1,1,0,0,9,0,101,100,103,101,0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,
+0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,0,18,101,100,103,101,0,0,0,0,1,90,
+95,0,0,12,0,0,115,116,101,112,0,1,1,0,0,9,0,101,100,103,101,0,0,1,1,0,0,12,0,118,0,0,0,1,4,118,101,
+99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,101,100,103,101,0,0,0,0,1,
+90,95,0,0,9,0,0,115,109,111,111,116,104,115,116,101,112,0,1,1,0,0,9,0,101,100,103,101,48,0,0,1,1,0,
+0,9,0,101,100,103,101,49,0,0,1,1,0,0,9,0,120,0,0,0,1,3,2,90,95,0,0,9,0,1,116,0,2,58,99,108,97,109,
+112,0,0,18,120,0,18,101,100,103,101,48,0,47,18,101,100,103,101,49,0,18,101,100,103,101,48,0,47,49,
+0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,18,116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,0,18,
+116,0,48,47,48,0,0,1,90,95,0,0,10,0,0,115,109,111,111,116,104,115,116,101,112,0,1,1,0,0,10,0,101,
+100,103,101,48,0,0,1,1,0,0,10,0,101,100,103,101,49,0,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,0,0,10,0,
+1,116,0,2,58,99,108,97,109,112,0,0,18,118,0,18,101,100,103,101,48,0,47,18,101,100,103,101,49,0,18,
+101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,18,116,0,18,116,0,48,17,51,
+0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,0,1,90,95,0,0,11,0,0,115,109,111,111,116,104,115,116,
+101,112,0,1,1,0,0,11,0,101,100,103,101,48,0,0,1,1,0,0,11,0,101,100,103,101,49,0,0,1,1,0,0,11,0,118,
+0,0,0,1,3,2,90,95,0,0,11,0,1,116,0,2,58,99,108,97,109,112,0,0,18,118,0,18,101,100,103,101,48,0,47,
+18,101,100,103,101,49,0,18,101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,
+18,116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,0,1,90,95,0,0,12,0,0,115,
+109,111,111,116,104,115,116,101,112,0,1,1,0,0,12,0,101,100,103,101,48,0,0,1,1,0,0,12,0,101,100,103,
+101,49,0,0,1,1,0,0,12,0,118,0,0,0,1,3,2,90,95,0,0,12,0,1,116,0,2,58,99,108,97,109,112,0,0,18,118,0,
+18,101,100,103,101,48,0,47,18,101,100,103,101,49,0,18,101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,
+0,17,49,0,48,0,0,0,0,0,0,8,18,116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,
+0,1,90,95,0,0,10,0,0,115,109,111,111,116,104,115,116,101,112,0,1,1,0,0,9,0,101,100,103,101,48,0,0,
+1,1,0,0,9,0,101,100,103,101,49,0,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,0,0,10,0,1,116,0,2,58,99,108,
+97,109,112,0,0,18,118,0,18,101,100,103,101,48,0,47,18,101,100,103,101,49,0,18,101,100,103,101,48,0,
+47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,18,116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,
+0,18,116,0,48,47,48,0,0,1,90,95,0,0,11,0,0,115,109,111,111,116,104,115,116,101,112,0,1,1,0,0,9,0,
+101,100,103,101,48,0,0,1,1,0,0,9,0,101,100,103,101,49,0,0,1,1,0,0,11,0,118,0,0,0,1,3,2,90,95,0,0,
+11,0,1,116,0,2,58,99,108,97,109,112,0,0,18,118,0,18,101,100,103,101,48,0,47,18,101,100,103,101,49,
+0,18,101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,8,18,116,0,18,116,0,48,
+17,51,0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,0,1,90,95,0,0,12,0,0,115,109,111,111,116,104,115,
+116,101,112,0,1,1,0,0,9,0,101,100,103,101,48,0,0,1,1,0,0,9,0,101,100,103,101,49,0,0,1,1,0,0,12,0,
+118,0,0,0,1,3,2,90,95,0,0,12,0,1,116,0,2,58,99,108,97,109,112,0,0,18,118,0,18,101,100,103,101,48,0,
+47,18,101,100,103,101,49,0,18,101,100,103,101,48,0,47,49,0,17,48,0,48,0,0,0,17,49,0,48,0,0,0,0,0,0,
+8,18,116,0,18,116,0,48,17,51,0,48,0,0,17,50,0,48,0,0,18,116,0,48,47,48,0,0,1,90,95,0,0,9,0,0,108,
+101,110,103,116,104,0,1,1,0,0,9,0,120,0,0,0,1,8,58,97,98,115,0,0,18,120,0,0,0,0,0,1,90,95,0,0,9,0,
+0,108,101,110,103,116,104,0,1,1,0,0,10,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,114,0,0,0,3,2,90,95,1,0,9,
+0,1,112,0,2,58,100,111,116,0,0,18,118,0,0,18,118,0,0,0,0,0,4,102,108,111,97,116,95,114,115,113,0,
+18,114,0,0,18,112,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,59,
+120,0,0,18,114,0,0,0,0,1,90,95,0,0,9,0,0,108,101,110,103,116,104,0,1,1,0,0,11,0,118,0,0,0,1,3,2,90,
+95,0,0,9,0,1,114,0,0,0,3,2,90,95,1,0,9,0,1,112,0,2,58,100,111,116,0,0,18,118,0,0,18,118,0,0,0,0,0,
+4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,112,0,0,0,4,102,108,111,97,116,95,114,99,112,0,
+18,95,95,114,101,116,86,97,108,0,0,18,114,0,0,0,0,1,90,95,0,0,9,0,0,108,101,110,103,116,104,0,1,1,
+0,0,12,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,114,0,0,0,3,2,90,95,1,0,9,0,1,112,0,2,58,100,111,116,0,0,
+18,118,0,0,18,118,0,0,0,0,0,4,102,108,111,97,116,95,114,115,113,0,18,114,0,0,18,112,0,0,0,4,102,
+108,111,97,116,95,114,99,112,0,18,95,95,114,101,116,86,97,108,0,0,18,114,0,0,0,0,1,90,95,0,0,9,0,0,
+100,105,115,116,97,110,99,101,0,1,1,0,0,9,0,120,0,0,1,1,0,0,9,0,121,0,0,0,1,3,2,90,95,1,0,9,0,1,
+100,0,2,18,120,0,18,121,0,47,0,0,9,18,95,95,114,101,116,86,97,108,0,58,108,101,110,103,116,104,0,0,
+18,100,0,0,0,20,0,0,1,90,95,0,0,9,0,0,100,105,115,116,97,110,99,101,0,1,1,0,0,10,0,118,0,0,1,1,0,0,
+10,0,117,0,0,0,1,3,2,90,95,1,0,10,0,1,100,50,0,2,18,118,0,18,117,0,47,0,0,9,18,95,95,114,101,116,
+86,97,108,0,58,108,101,110,103,116,104,0,0,18,100,50,0,0,0,20,0,0,1,90,95,0,0,9,0,0,100,105,115,
+116,97,110,99,101,0,1,1,0,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,0,1,3,2,90,95,1,0,11,0,1,100,51,0,2,
+18,118,0,18,117,0,47,0,0,9,18,95,95,114,101,116,86,97,108,0,58,108,101,110,103,116,104,0,0,18,100,
+51,0,0,0,20,0,0,1,90,95,0,0,9,0,0,100,105,115,116,97,110,99,101,0,1,1,0,0,12,0,118,0,0,1,1,0,0,12,
+0,117,0,0,0,1,3,2,90,95,1,0,12,0,1,100,52,0,2,18,118,0,18,117,0,47,0,0,9,18,95,95,114,101,116,86,
+97,108,0,58,108,101,110,103,116,104,0,0,18,100,52,0,0,0,20,0,0,1,90,95,0,0,11,0,0,99,114,111,115,
+115,0,1,1,0,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,0,1,4,118,101,99,51,95,99,114,111,115,115,0,18,95,
+95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,9,0,0,102,97,
+99,101,102,111,114,119,97,114,100,0,1,1,0,0,9,0,78,0,0,1,1,0,0,9,0,73,0,0,1,1,0,0,9,0,78,114,101,
+102,0,0,0,1,3,2,90,95,1,0,9,0,1,100,0,2,58,100,111,116,0,0,18,78,114,101,102,0,0,18,73,0,0,0,0,0,3,
+2,90,95,0,0,9,0,1,115,0,0,0,4,118,101,99,52,95,115,103,116,0,18,115,0,0,17,48,0,48,0,0,0,18,100,0,
+0,0,8,58,109,105,120,0,0,18,78,0,54,0,18,78,0,0,18,115,0,0,0,0,0,1,90,95,0,0,10,0,0,102,97,99,101,
+102,111,114,119,97,114,100,0,1,1,0,0,10,0,78,0,0,1,1,0,0,10,0,73,0,0,1,1,0,0,10,0,78,114,101,102,0,
+0,0,1,3,2,90,95,1,0,9,0,1,100,0,2,58,100,111,116,0,0,18,78,114,101,102,0,0,18,73,0,0,0,0,0,3,2,90,
+95,0,0,9,0,1,115,0,0,0,4,118,101,99,52,95,115,103,116,0,18,115,0,0,17,48,0,48,0,0,0,18,100,0,0,0,8,
+58,109,105,120,0,0,18,78,0,54,0,18,78,0,0,18,115,0,0,0,0,0,1,90,95,0,0,11,0,0,102,97,99,101,102,
+111,114,119,97,114,100,0,1,1,0,0,11,0,78,0,0,1,1,0,0,11,0,73,0,0,1,1,0,0,11,0,78,114,101,102,0,0,0,
+1,3,2,90,95,1,0,9,0,1,100,0,2,58,100,111,116,0,0,18,78,114,101,102,0,0,18,73,0,0,0,0,0,3,2,90,95,0,
+0,9,0,1,115,0,0,0,4,118,101,99,52,95,115,103,116,0,18,115,0,0,17,48,0,48,0,0,0,18,100,0,0,0,8,58,
+109,105,120,0,0,18,78,0,54,0,18,78,0,0,18,115,0,0,0,0,0,1,90,95,0,0,12,0,0,102,97,99,101,102,111,
+114,119,97,114,100,0,1,1,0,0,12,0,78,0,0,1,1,0,0,12,0,73,0,0,1,1,0,0,12,0,78,114,101,102,0,0,0,1,3,
+2,90,95,1,0,9,0,1,100,0,2,58,100,111,116,0,0,18,78,114,101,102,0,0,18,73,0,0,0,0,0,3,2,90,95,0,0,9,
+0,1,115,0,0,0,4,118,101,99,52,95,115,103,116,0,18,115,0,0,17,48,0,48,0,0,0,18,100,0,0,0,8,58,109,
+105,120,0,0,18,78,0,54,0,18,78,0,0,18,115,0,0,0,0,0,1,90,95,0,0,9,0,0,114,101,102,108,101,99,116,0,
+1,1,0,0,9,0,73,0,0,1,1,0,0,9,0,78,0,0,0,1,8,18,73,0,17,50,0,48,0,0,58,100,111,116,0,0,18,78,0,0,18,
+73,0,0,0,48,18,78,0,48,47,0,0,1,90,95,0,0,10,0,0,114,101,102,108,101,99,116,0,1,1,0,0,10,0,73,0,0,
+1,1,0,0,10,0,78,0,0,0,1,8,18,73,0,17,50,0,48,0,0,58,100,111,116,0,0,18,78,0,0,18,73,0,0,0,48,18,78,
+0,48,47,0,0,1,90,95,0,0,11,0,0,114,101,102,108,101,99,116,0,1,1,0,0,11,0,73,0,0,1,1,0,0,11,0,78,0,
+0,0,1,8,18,73,0,17,50,0,48,0,0,58,100,111,116,0,0,18,78,0,0,18,73,0,0,0,48,18,78,0,48,47,0,0,1,90,
+95,0,0,12,0,0,114,101,102,108,101,99,116,0,1,1,0,0,12,0,73,0,0,1,1,0,0,12,0,78,0,0,0,1,8,18,73,0,
+17,50,0,48,0,0,58,100,111,116,0,0,18,78,0,0,18,73,0,0,0,48,18,78,0,48,47,0,0,1,90,95,0,0,9,0,0,114,
+101,102,114,97,99,116,0,1,1,0,0,9,0,73,0,0,1,1,0,0,9,0,78,0,0,1,1,0,0,9,0,101,116,97,0,0,0,1,3,2,
+90,95,0,0,9,0,1,110,95,100,111,116,95,105,0,2,58,100,111,116,0,0,18,78,0,0,18,73,0,0,0,0,0,3,2,90,
+95,0,0,9,0,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,0,48,17,49,0,48,0,0,18,110,95,
+100,111,116,95,105,0,18,110,95,100,111,116,95,105,0,48,47,48,47,0,0,3,2,90,95,0,0,9,0,1,114,101,
+116,118,97,108,0,0,0,10,18,107,0,17,48,0,48,0,0,40,0,9,18,114,101,116,118,97,108,0,17,48,0,48,0,0,
+20,0,9,18,114,101,116,118,97,108,0,18,101,116,97,0,18,73,0,48,18,101,116,97,0,18,110,95,100,111,
+116,95,105,0,48,58,115,113,114,116,0,0,18,107,0,0,0,46,18,78,0,48,47,20,0,8,18,114,101,116,118,97,
+108,0,0,0,1,90,95,0,0,10,0,0,114,101,102,114,97,99,116,0,1,1,0,0,10,0,73,0,0,1,1,0,0,10,0,78,0,0,1,
+1,0,0,9,0,101,116,97,0,0,0,1,3,2,90,95,0,0,9,0,1,110,95,100,111,116,95,105,0,2,58,100,111,116,0,0,
+18,78,0,0,18,73,0,0,0,0,0,3,2,90,95,0,0,9,0,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,
+0,48,17,49,0,48,0,0,18,110,95,100,111,116,95,105,0,18,110,95,100,111,116,95,105,0,48,47,48,47,0,0,
+3,2,90,95,0,0,10,0,1,114,101,116,118,97,108,0,0,0,10,18,107,0,17,48,0,48,0,0,40,0,9,18,114,101,116,
+118,97,108,0,58,118,101,99,50,0,0,17,48,0,48,0,0,0,0,20,0,9,18,114,101,116,118,97,108,0,18,101,116,
+97,0,18,73,0,48,18,101,116,97,0,18,110,95,100,111,116,95,105,0,48,58,115,113,114,116,0,0,18,107,0,
+0,0,46,18,78,0,48,47,20,0,8,18,114,101,116,118,97,108,0,0,0,1,90,95,0,0,11,0,0,114,101,102,114,97,
+99,116,0,1,1,0,0,11,0,73,0,0,1,1,0,0,11,0,78,0,0,1,1,0,0,9,0,101,116,97,0,0,0,1,3,2,90,95,0,0,9,0,
+1,110,95,100,111,116,95,105,0,2,58,100,111,116,0,0,18,78,0,0,18,73,0,0,0,0,0,3,2,90,95,0,0,9,0,1,
+107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,101,116,97,0,48,17,49,0,48,0,0,18,110,95,100,111,116,95,
+105,0,18,110,95,100,111,116,95,105,0,48,47,48,47,0,0,3,2,90,95,0,0,11,0,1,114,101,116,118,97,108,0,
+0,0,10,18,107,0,17,48,0,48,0,0,40,0,9,18,114,101,116,118,97,108,0,58,118,101,99,51,0,0,17,48,0,48,
+0,0,0,0,20,0,9,18,114,101,116,118,97,108,0,18,101,116,97,0,18,73,0,48,18,101,116,97,0,18,110,95,
+100,111,116,95,105,0,48,58,115,113,114,116,0,0,18,107,0,0,0,46,18,78,0,48,47,20,0,8,18,114,101,116,
+118,97,108,0,0,0,1,90,95,0,0,12,0,0,114,101,102,114,97,99,116,0,1,1,0,0,12,0,73,0,0,1,1,0,0,12,0,
+78,0,0,1,1,0,0,9,0,101,116,97,0,0,0,1,3,2,90,95,0,0,9,0,1,110,95,100,111,116,95,105,0,2,58,100,111,
+116,0,0,18,78,0,0,18,73,0,0,0,0,0,3,2,90,95,0,0,9,0,1,107,0,2,17,49,0,48,0,0,18,101,116,97,0,18,
+101,116,97,0,48,17,49,0,48,0,0,18,110,95,100,111,116,95,105,0,18,110,95,100,111,116,95,105,0,48,47,
+48,47,0,0,3,2,90,95,0,0,12,0,1,114,101,116,118,97,108,0,0,0,10,18,107,0,17,48,0,48,0,0,40,0,9,18,
+114,101,116,118,97,108,0,58,118,101,99,52,0,0,17,48,0,48,0,0,0,0,20,0,9,18,114,101,116,118,97,108,
+0,18,101,116,97,0,18,73,0,48,18,101,116,97,0,18,110,95,100,111,116,95,105,0,48,58,115,113,114,116,
+0,0,18,107,0,0,0,46,18,78,0,48,47,20,0,8,18,114,101,116,118,97,108,0,0,0,1,90,95,0,0,13,0,0,109,97,
+116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,0,13,0,109,0,0,1,0,0,0,13,0,110,0,0,0,1,8,58,
+109,97,116,50,0,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,
+16,10,49,0,57,48,0,0,0,0,1,90,95,0,0,14,0,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,
+1,0,0,0,14,0,109,0,0,1,0,0,0,14,0,110,0,0,0,1,8,58,109,97,116,51,0,0,18,109,0,16,8,48,0,57,18,110,
+0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,
+110,0,16,10,50,0,57,48,0,0,0,0,1,90,95,0,0,15,0,0,109,97,116,114,105,120,67,111,109,112,77,117,108,
+116,0,1,0,0,0,15,0,109,0,0,1,0,0,0,15,0,110,0,0,0,1,8,58,109,97,116,52,0,0,18,109,0,16,8,48,0,57,
+18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,
+57,18,110,0,16,10,50,0,57,48,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,48,0,0,0,0,1,90,95,0,
+0,2,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,10,0,117,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,
+52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,
+95,0,0,3,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,11,0,117,0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,
+101,99,52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,
+0,0,0,1,90,95,0,0,4,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,
+0,1,4,118,101,99,52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,
+1,90,95,0,0,2,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,118,0,0,0,1,4,
+118,101,99,52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,
+0,0,0,1,90,95,0,0,3,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,7,0,117,0,0,1,1,0,0,7,0,118,0,0,0,
+1,4,118,101,99,52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,
+18,118,0,0,0,0,1,90,95,0,0,4,0,0,108,101,115,115,84,104,97,110,0,1,1,0,0,8,0,117,0,0,1,1,0,0,8,0,
+118,0,0,0,1,4,118,101,99,52,95,115,108,116,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,
+0,0,0,0,1,90,95,0,0,2,0,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,1,0,0,10,0,117,0,0,1,
+1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,115,108,101,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,3,0,0,108,101,115,115,84,104,97,110,69,113,117,97,
+108,0,1,1,0,0,11,0,117,0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,115,108,101,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,108,101,115,115,
+84,104,97,110,69,113,117,97,108,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,0,1,4,118,101,99,52,95,
+115,108,101,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,108,
+101,115,115,84,104,97,110,69,113,117,97,108,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,118,0,0,0,1,4,118,
+101,99,52,95,115,108,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,
+0,1,90,95,0,0,3,0,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,1,0,0,7,0,117,0,0,1,1,0,0,
+7,0,118,0,0,0,1,4,118,101,99,52,95,115,108,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,
+0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,108,101,115,115,84,104,97,110,69,113,117,97,108,0,1,
+1,0,0,8,0,117,0,0,1,1,0,0,8,0,118,0,0,0,1,4,118,101,99,52,95,115,108,101,0,18,95,95,114,101,116,86,
+97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,103,114,101,97,116,101,114,84,104,97,110,0,
+1,1,0,0,10,0,117,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,115,103,116,0,18,95,95,114,101,
+116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,3,0,0,103,114,101,97,116,101,
+114,84,104,97,110,0,1,1,0,0,11,0,117,0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,115,103,116,0,
+18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,
+103,114,101,97,116,101,114,84,104,97,110,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,0,1,4,118,101,
+99,52,95,115,103,116,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,
+0,0,103,114,101,97,116,101,114,84,104,97,110,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,118,0,0,0,1,4,118,
+101,99,52,95,115,103,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,59,120,121,0,0,
+18,118,0,59,120,121,0,0,0,0,1,90,95,0,0,3,0,0,103,114,101,97,116,101,114,84,104,97,110,0,1,1,0,0,7,
+0,117,0,0,1,1,0,0,7,0,118,0,0,0,1,4,118,101,99,52,95,115,103,116,0,18,95,95,114,101,116,86,97,108,
+0,59,120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,103,114,101,97,116,101,114,84,104,
+97,110,0,1,1,0,0,8,0,117,0,0,1,1,0,0,8,0,118,0,0,0,1,4,118,101,99,52,95,115,103,116,0,18,95,95,114,
+101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,103,114,101,97,116,101,114,84,
+104,97,110,69,113,117,97,108,0,1,1,0,0,10,0,117,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,
+115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,
+0,3,0,0,103,114,101,97,116,101,114,84,104,97,110,69,113,117,97,108,0,1,1,0,0,11,0,117,0,0,1,1,0,0,
+11,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,
+0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,103,114,101,97,116,101,114,84,104,97,110,69,113,
+117,97,108,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,
+95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,103,114,101,97,116,101,
+114,84,104,97,110,69,113,117,97,108,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,118,0,0,0,1,4,118,101,99,52,
+95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,
+0,0,3,0,0,103,114,101,97,116,101,114,84,104,97,110,69,113,117,97,108,0,1,1,0,0,7,0,117,0,0,1,1,0,0,
+7,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,
+0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,103,114,101,97,116,101,114,84,104,97,110,69,113,117,
+97,108,0,1,1,0,0,8,0,117,0,0,1,1,0,0,8,0,118,0,0,0,1,4,118,101,99,52,95,115,103,101,0,18,95,95,114,
+101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,101,113,117,97,108,0,1,1,0,0,10,
+0,117,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,
+0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,3,0,0,101,113,117,97,108,0,1,1,0,0,11,0,117,
+0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,101,113,117,97,108,0,1,1,0,0,12,0,117,
+0,0,1,1,0,0,12,0,118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,0,
+18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,101,113,117,97,108,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,
+118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,
+117,0,0,18,118,0,0,0,0,1,90,95,0,0,3,0,0,101,113,117,97,108,0,1,1,0,0,7,0,117,0,0,1,1,0,0,7,0,118,
+0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,
+117,0,0,18,118,0,0,0,0,1,90,95,0,0,4,0,0,101,113,117,97,108,0,1,1,0,0,8,0,117,0,0,1,1,0,0,8,0,118,
+0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,
+0,0,1,90,95,0,0,2,0,0,101,113,117,97,108,0,1,1,0,0,2,0,117,0,0,1,1,0,0,2,0,118,0,0,0,1,4,118,101,
+99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,
+90,95,0,0,3,0,0,101,113,117,97,108,0,1,1,0,0,3,0,117,0,0,1,1,0,0,3,0,118,0,0,0,1,4,118,101,99,52,
+95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,1,
+90,95,0,0,4,0,0,101,113,117,97,108,0,1,1,0,0,4,0,117,0,0,1,1,0,0,4,0,118,0,0,0,1,4,118,101,99,52,
+95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,0,2,0,0,
+110,111,116,69,113,117,97,108,0,1,1,0,0,10,0,117,0,0,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,
+115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,90,95,0,
+0,3,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,11,0,117,0,0,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,
+52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,0,0,0,
+1,90,95,0,0,4,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,12,0,117,0,0,1,1,0,0,12,0,118,0,0,0,1,4,
+118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,90,
+95,0,0,2,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,6,0,117,0,0,1,1,0,0,6,0,118,0,0,0,1,4,118,101,
+99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,0,1,
+90,95,0,0,3,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,7,0,117,0,0,1,1,0,0,7,0,118,0,0,0,1,4,118,
+101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,118,0,
+0,0,0,1,90,95,0,0,4,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,8,0,117,0,0,1,1,0,0,8,0,118,0,0,0,
+1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,0,0,1,
+90,95,0,0,2,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,2,0,117,0,0,1,1,0,0,2,0,118,0,0,0,1,4,118,
+101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,117,0,0,18,118,0,0,0,
+0,1,90,95,0,0,3,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,3,0,117,0,0,1,1,0,0,3,0,118,0,0,0,1,4,
+118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,117,0,0,18,
+118,0,0,0,0,1,90,95,0,0,4,0,0,110,111,116,69,113,117,97,108,0,1,1,0,0,4,0,117,0,0,1,1,0,0,4,0,118,
+0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,117,0,0,18,118,0,0,
+0,0,1,90,95,0,0,1,0,0,97,110,121,0,1,1,0,0,2,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,115,117,109,0,0,0,4,
+118,101,99,52,95,97,100,100,0,18,115,117,109,0,59,120,0,0,18,118,0,59,120,0,0,18,118,0,59,121,0,0,
+0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,115,117,109,0,59,
+120,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,0,97,110,121,0,1,1,0,0,3,0,118,0,0,0,1,3,2,90,95,0,0,
+9,0,1,115,117,109,0,0,0,4,118,101,99,52,95,97,100,100,0,18,115,117,109,0,59,120,0,0,18,118,0,59,
+120,0,0,18,118,0,59,121,0,0,0,4,118,101,99,52,95,97,100,100,0,18,115,117,109,0,59,120,0,0,18,115,
+117,109,0,59,120,0,0,18,118,0,59,122,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,
+86,97,108,0,59,120,0,0,18,115,117,109,0,59,120,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,0,97,110,
+121,0,1,1,0,0,4,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,115,117,109,0,0,0,4,118,101,99,52,95,97,100,100,
+0,18,115,117,109,0,59,120,0,0,18,118,0,59,120,0,0,18,118,0,59,121,0,0,0,4,118,101,99,52,95,97,100,
+100,0,18,115,117,109,0,59,120,0,0,18,115,117,109,0,59,120,0,0,18,118,0,59,122,0,0,0,4,118,101,99,
+52,95,97,100,100,0,18,115,117,109,0,59,120,0,0,18,115,117,109,0,59,120,0,0,18,118,0,59,119,0,0,0,4,
+118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,115,117,109,0,59,120,
+0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,0,97,108,108,0,1,1,0,0,2,0,118,0,0,0,1,3,2,90,95,0,0,9,0,
+1,112,114,111,100,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,112,114,111,100,0,
+0,18,118,0,59,120,0,0,18,118,0,59,121,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,
+86,97,108,0,0,18,112,114,111,100,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,0,97,108,108,0,1,1,0,0,3,
+0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,112,114,111,100,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,
+108,121,0,18,112,114,111,100,0,0,18,118,0,59,120,0,0,18,118,0,59,121,0,0,0,4,118,101,99,52,95,109,
+117,108,116,105,112,108,121,0,18,112,114,111,100,0,0,18,112,114,111,100,0,0,18,118,0,59,122,0,0,0,
+4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,112,114,111,100,0,0,17,48,0,
+48,0,0,0,0,0,1,90,95,0,0,1,0,0,97,108,108,0,1,1,0,0,4,0,118,0,0,0,1,3,2,90,95,0,0,9,0,1,112,114,
+111,100,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,112,114,111,100,0,0,18,118,0,
+59,120,0,0,18,118,0,59,121,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,112,114,
+111,100,0,0,18,112,114,111,100,0,0,18,118,0,59,122,0,0,0,4,118,101,99,52,95,109,117,108,116,105,
+112,108,121,0,18,112,114,111,100,0,0,18,112,114,111,100,0,0,18,118,0,59,119,0,0,0,4,118,101,99,52,
+95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,112,114,111,100,0,0,17,48,0,48,0,0,0,0,0,1,
+90,95,0,0,2,0,0,110,111,116,0,1,1,0,0,2,0,118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,
+114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,3,0,0,110,111,
+116,0,1,1,0,0,3,0,118,0,0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,122,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,4,0,0,110,111,116,0,1,1,0,0,4,0,118,0,
+0,0,1,4,118,101,99,52,95,115,101,113,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,17,48,0,48,0,
+0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,0,1,1,0,0,16,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,9,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,49,100,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,16,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,49,100,95,112,
+114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,
+114,100,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,
+111,106,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,
+118,101,99,52,95,116,101,120,95,49,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,
+115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,
+117,114,101,50,68,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,
+0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,
+50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,
+0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,120,121,122,122,0,0,0,0,1,90,
+95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,
+101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,
+112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,
+111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,0,1,1,0,0,18,0,115,97,109,
+112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,51,
+100,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,
+0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,115,97,
+109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,
+51,100,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,
+18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,0,1,1,0,
+0,19,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,
+116,101,120,95,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,
+0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,0,1,1,0,0,20,0,115,
+97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,
+95,49,100,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,
+106,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,
+101,99,52,95,116,101,120,95,49,100,95,112,114,111,106,95,115,104,97,100,111,119,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,
+0,115,104,97,100,111,119,50,68,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,
+111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,115,104,97,100,111,119,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,
+0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,50,100,95,112,114,111,
+106,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,
+0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,99,116,
+0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,0,1,4,118,101,99,
+52,95,116,101,120,95,114,101,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,
+99,116,80,114,111,106,0,1,1,0,0,22,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,
+100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,95,112,114,111,106,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,59,120,121,122,122,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,22,
+0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,
+101,120,95,114,101,99,116,95,112,114,111,106,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,
+68,82,101,99,116,0,1,1,0,0,23,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,
+0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,95,115,104,97,100,111,119,0,18,95,95,114,101,
+116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,
+0,115,104,97,100,111,119,50,68,82,101,99,116,80,114,111,106,0,1,1,0,0,23,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,0,1,4,118,101,99,52,95,116,101,120,95,114,101,99,116,
+95,112,114,111,106,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,
+112,108,101,114,0,0,18,99,111,111,114,100,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,
+0,9,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,101,49,0,18,95,95,114,101,116,86,97,108,
+0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,10,0,120,0,0,0,1,4,102,108,
+111,97,116,95,110,111,105,115,101,50,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,
+0,9,0,0,110,111,105,115,101,49,0,1,1,0,0,11,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,
+101,51,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,0,110,111,105,115,101,
+49,0,1,1,0,0,12,0,120,0,0,0,1,4,102,108,111,97,116,95,110,111,105,115,101,52,0,18,95,95,114,101,
+116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,9,0,120,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,
+95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,
+46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,
+52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,
+11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,
+0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,
+118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,0,46,0,0,20,0,0,1,
+90,95,0,0,10,0,0,110,111,105,115,101,50,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,0,51,52,0,0,0,17,55,
+0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,
+105,115,101,51,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,111,
+105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,105,
+115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,
+0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,
+111,105,115,101,51,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,
+111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,
+105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,
+0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,
+101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,
+111,105,115,101,51,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,110,
+111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,111,
+105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,
+0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,
+0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,
+0,0,46,0,0,20,0,0,1,90,95,0,0,11,0,0,110,111,105,115,101,51,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,
+0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,53,
+0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,20,0,0,
+1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,9,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,
+59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,17,49,57,0,51,52,0,0,46,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,17,53,0,52,55,0,0,46,0,0,20,0,
+9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,17,50,51,0,53,
+52,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,10,0,120,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,49,57,
+0,51,52,0,0,0,17,55,0,54,54,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,
+111,105,115,101,49,0,0,18,120,0,58,118,101,99,50,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,0,
+46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,58,
+118,101,99,50,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,0,46,0,0,20,0,0,1,90,95,0,0,12,0,0,
+110,111,105,115,101,52,0,1,1,0,0,11,0,120,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,
+110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,110,
+111,105,115,101,49,0,0,18,120,0,58,118,101,99,51,0,0,17,49,57,0,51,52,0,0,0,17,55,0,54,54,0,0,0,17,
+51,0,50,51,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,110,111,105,115,101,
+49,0,0,18,120,0,58,118,101,99,51,0,0,17,53,0,52,55,0,0,0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,
+0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,
+0,58,118,101,99,51,0,0,17,50,51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,0,46,0,
+0,20,0,0,1,90,95,0,0,12,0,0,110,111,105,115,101,52,0,1,1,0,0,12,0,120,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,59,120,0,58,110,111,105,115,101,49,0,0,18,120,0,0,0,20,0,9,18,95,95,114,101,116,86,
+97,108,0,59,121,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,49,57,0,51,52,0,0,
+0,17,55,0,54,54,0,0,0,17,51,0,50,51,0,0,0,17,50,0,55,55,0,0,0,0,46,0,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,59,122,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,53,0,52,55,0,0,
+0,17,49,55,0,56,53,0,0,0,17,49,49,0,48,52,0,0,0,17,49,51,0,49,57,0,0,0,0,46,0,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,59,119,0,58,110,111,105,115,101,49,0,0,18,120,0,58,118,101,99,52,0,0,17,50,
+51,0,53,52,0,0,0,17,50,57,0,49,49,0,0,0,17,51,49,0,57,49,0,0,0,17,51,55,0,52,56,0,0,0,0,46,0,0,20,
+0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_core.gc b/mesalib/src/mesa/shader/slang/library/slang_core.gc
new file mode 100644
index 000000000..0a0d15903
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_core.gc
@@ -0,0 +1,2619 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// This file defines nearly all constructors and operators for built-in data
+// types, using extended language syntax. In general, compiler treats
+// constructors and operators as ordinary functions with some exceptions.
+// For example, the language does not allow functions to be called in
+// constant expressions - here the exception is made to allow it.
+//
+// Each implementation provides its own version of this file. Each
+// implementation can define the required set of operators and constructors
+// in its own fashion.
+//
+// The extended language syntax is only present when compiling this file.
+// It is implicitly included at the very beginning of the compiled shader,
+// so no built-in functions can be used.
+//
+// To communicate with the implementation, a special extended "__asm" keyword
+// is used, followed by an instruction name (any valid identifier), a
+// destination variable identifier and a list of zero or more source
+// variable identifiers.
+//
+// A variable identifier is a variable name declared earlier in the code
+// (as a function parameter, local or global variable).
+//
+// An instruction name designates an instruction that must be exported
+// by the implementation. Each instruction receives data from source
+// variable identifiers and returns data in the destination variable
+// identifier.
+//
+// It is up to the implementation how to define a particular operator
+// or constructor. If it is expected to being used rarely, it can be
+// defined in terms of other operators and constructors,
+// for example:
+//
+// ivec2 __operator + (const ivec2 x, const ivec2 y) {
+// return ivec2 (x[0] + y[0], x[1] + y[1]);
+// }
+//
+// If a particular operator or constructor is expected to be used very
+// often or is an atomic operation (that is, an operation that cannot be
+// expressed in terms of other operations or would create a dependency
+// cycle) it must be defined using one or more __asm constructs.
+//
+// Each implementation must define constructors for all scalar types
+// (bool, float, int). There are 9 scalar-to-scalar constructors
+// (including identity constructors). However, since the language
+// introduces special constructors (like matrix constructor with a single
+// scalar value), implementations must also implement these cases.
+// The compiler provides the following algorithm when resolving a constructor:
+// - try to find a constructor with a prototype matching ours,
+// - if no constructor is found and this is a scalar-to-scalar constructor,
+// raise an error,
+// - if a constructor is found, execute it and return,
+// - count the size of the constructor parameter list - if it is less than
+// the size of our constructor's type, raise an error,
+// - for each parameter in the list do a recursive constructor matching for
+// appropriate scalar fields in the constructed variable,
+//
+// Each implementation must also define a set of operators that deal with
+// built-in data types.
+// There are four kinds of operators:
+// 1) Operators that are implemented only by the compiler: "()" (function
+// call), "," (sequence) and "?:" (selection).
+// 2) Operators that are implemented by the compiler by expressing it in
+// terms of other operators:
+// - "." (field selection) - translated to subscript access,
+// - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
+// false",
+// - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
+// 3) Operators that can be defined by the implementation and if the required
+// prototype is not found, standard behaviour is used:
+// - "==", "!=", "=" (equality, assignment) - compare or assign
+// matching fields one-by-one;
+// note that at least operators for scalar data types must be defined
+// by the implementation to get it work,
+// 4) All other operators not mentioned above. If no required prototype is
+// found, an error is raised. An implementation must follow the language
+// specification to provide all valid operator prototypes.
+//
+
+
+
+//// Basic, scalar constructors/casts
+
+int __constructor(const float f)
+{
+ __asm vec4_to_ivec4 __retVal, f;
+}
+
+int __constructor(const bool b)
+{
+ __retVal = b;
+}
+
+int __constructor(const int i)
+{
+ __retVal = i;
+}
+
+bool __constructor(const int i)
+{
+ __asm vec4_sne __retVal, i, 0.0;
+}
+
+bool __constructor(const float f)
+{
+ __asm vec4_sne __retVal, f, 0.0;
+}
+
+bool __constructor(const bool b)
+{
+ __retVal = b;
+}
+
+float __constructor(const int i)
+{
+ __asm ivec4_to_vec4 __retVal, i;
+}
+
+float __constructor(const bool b)
+{
+ __asm ivec4_to_vec4 __retVal, b;
+}
+
+float __constructor(const float f)
+{
+ __retVal = f;
+}
+
+
+//// vec2 constructors
+
+vec2 __constructor(const float x, const float y)
+{
+ __retVal.x = x;
+ __retVal.y = y;
+}
+
+vec2 __constructor(const float f)
+{
+ __asm vec4_move __retVal.xy, f;
+}
+
+vec2 __constructor(const int i)
+{
+ __asm ivec4_to_vec4 __retVal.xy, i;
+}
+
+vec2 __constructor(const bool b)
+{
+ __asm ivec4_to_vec4 __retVal.xy, b;
+}
+
+vec2 __constructor(const bvec2 b)
+{
+// __retVal = b;
+ __asm ivec4_to_vec4 __retVal.xy, b;
+}
+
+vec2 __constructor(const vec3 v)
+{
+ __asm vec4_move __retVal.xy, v.xy;
+}
+
+vec2 __constructor(const vec4 v)
+{
+ __asm vec4_move __retVal.xy, v.xy;
+}
+
+
+//// vec3 constructors
+
+vec3 __constructor(const float x, const float y, const float z)
+{
+ __retVal.x = x;
+ __retVal.y = y;
+ __retVal.z = z;
+}
+
+vec3 __constructor(const float f)
+{
+ // Note: this could be "__retVal.xyz = f" but that's an illegal assignment
+ __asm vec4_move __retVal.xyz, f;
+}
+
+vec3 __constructor(const int i)
+{
+ __asm ivec4_to_vec4 __retVal.xyz, i;
+}
+
+vec3 __constructor(const bool b)
+{
+ __asm ivec4_to_vec4 __retVal.xyz, b;
+}
+
+vec3 __constructor(const bvec3 b)
+{
+ __asm ivec4_to_vec4 __retVal.xyz, b;
+}
+
+vec3 __constructor(const vec4 v)
+{
+ __asm vec4_move __retVal.xyz, v;
+}
+
+
+//// vec4 constructors
+
+vec4 __constructor(const float x, const float y, const float z, const float w)
+{
+ __retVal.x = x;
+ __retVal.y = y;
+ __retVal.z = z;
+ __retVal.w = w;
+}
+
+vec4 __constructor(const float f)
+{
+ // Note: this could be "__retVal = f" but that's an illegal assignment
+ __asm vec4_move __retVal, f;
+}
+
+vec4 __constructor(const int i)
+{
+ __asm ivec4_to_vec4 __retVal, i;
+}
+
+vec4 __constructor(const bool b)
+{
+ __asm ivec4_to_vec4 __retVal, b;
+}
+
+vec4 __constructor(const bvec4 b)
+{
+ __asm ivec4_to_vec4 __retVal, b;
+}
+
+vec4 __constructor(const ivec4 i)
+{
+ __asm ivec4_to_vec4 __retVal, i;
+}
+
+vec4 __constructor(const vec3 v3, const float f)
+{
+ // XXX this constructor shouldn't be needed anymore
+ __retVal.xyz = v3;
+ __retVal.w = f;
+}
+
+vec4 __constructor(const vec2 v2, const float f1, const float f2)
+{
+ // XXX this constructor shouldn't be needed anymore
+ __retVal.xy = v2;
+ __retVal.z = f1;
+ __retVal.w = f2;
+}
+
+
+//// ivec2 constructors
+
+ivec2 __constructor(const int i, const int j)
+{
+ __retVal.x = i;
+ __retVal.y = j;
+}
+
+ivec2 __constructor(const int i)
+{
+ __asm vec4_move __retVal.xy, i;
+}
+
+ivec2 __constructor(const float f)
+{
+ __asm vec4_to_ivec4 __retVal.xy, f;
+}
+
+ivec2 __constructor(const bool b)
+{
+ __asm vec4_to_ivec4 __retVal.xy, b;
+}
+
+
+//// ivec3 constructors
+
+ivec3 __constructor(const int i, const int j, const int k)
+{
+ __retVal.x = i;
+ __retVal.y = j;
+ __retVal.z = k;
+}
+
+ivec3 __constructor(const int i)
+{
+ __asm vec4_move __retVal.xyz, i;
+}
+
+ivec3 __constructor(const float f)
+{
+ __asm vec4_to_ivec4 __retVal.xyz, f;
+}
+
+ivec3 __constructor(const bool b)
+{
+ __asm vec4_move __retVal.xyz, b;
+}
+
+
+//// ivec4 constructors
+
+ivec4 __constructor(const int x, const int y, const int z, const int w)
+{
+ __retVal.x = x;
+ __retVal.y = y;
+ __retVal.z = z;
+ __retVal.w = w;
+}
+
+ivec4 __constructor(const int i)
+{
+ __asm vec4_move __retVal, i;
+}
+
+ivec4 __constructor(const float f)
+{
+ __asm vec4_to_ivec4 __retVal, f;
+}
+
+ivec4 __constructor(const bool b)
+{
+ __asm vec4_to_ivec4 __retVal, b;
+}
+
+
+//// bvec2 constructors
+
+bvec2 __constructor(const bool b1, const bool b2)
+{
+ __retVal.x = b1;
+ __retVal.y = b2;
+}
+
+bvec2 __constructor(const int i1, const int i2)
+{
+ __asm vec4_sne __retVal.x, i1, 0.0;
+ __asm vec4_sne __retVal.y, i2, 0.0;
+}
+
+
+bvec2 __constructor(const bool b)
+{
+ __asm vec4_move __retVal.xy, b;
+}
+
+bvec2 __constructor(const float f)
+{
+ __asm vec4_sne __retVal.xy, f, 0.0;
+}
+
+bvec2 __constructor(const int i)
+{
+ __asm vec4_sne __retVal.xy, i, 0.0;
+}
+
+bvec2 __constructor(const vec2 v)
+{
+ __asm vec4_sne __retVal.xy, v, 0.0;
+}
+
+bvec2 __constructor(const ivec2 v)
+{
+ __asm vec4_sne __retVal.xy, v, 0.0;
+}
+
+
+
+//// bvec3 constructors
+
+bvec3 __constructor(const bool b1, const bool b2, const bool b3)
+{
+ __retVal.x = b1;
+ __retVal.y = b2;
+ __retVal.z = b3;
+}
+
+bvec3 __constructor(const float f1, const float f2, const float f3)
+{
+ __asm vec4_sne __retVal.x, f1, 0.0;
+ __asm vec4_sne __retVal.y, f2, 0.0;
+ __asm vec4_sne __retVal.z, f3, 0.0;
+}
+
+bvec3 __constructor(const bool b)
+{
+ __asm vec4_move __retVal.xyz, b;
+}
+
+bvec3 __constructor(const float f)
+{
+ __asm vec4_sne __retVal.xyz, f, 0.0;
+}
+
+bvec3 __constructor(const int i)
+{
+ __asm vec4_sne __retVal.xyz, i, 0.0;
+}
+
+bvec3 __constructor(const vec3 v)
+{
+ __asm vec4_sne __retVal.xyz, v, 0.0;
+}
+
+bvec3 __constructor(const ivec3 v)
+{
+ __asm vec4_sne __retVal.xyz, v, 0.0;
+}
+
+
+
+//// bvec4 constructors
+
+bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
+{
+ __retVal.x = b1;
+ __retVal.y = b2;
+ __retVal.z = b3;
+ __retVal.w = b4;
+}
+
+bvec4 __constructor(const float f1, const float f2, const float f3, const float f4)
+{
+ const float zero = 0.0;
+ __asm vec4_sne __retVal.x, f1, zero;
+ __asm vec4_sne __retVal.y, f2, zero;
+ __asm vec4_sne __retVal.z, f3, zero;
+ __asm vec4_sne __retVal.w, f4, zero;
+}
+
+bvec4 __constructor(const bool b)
+{
+ __asm vec4_move __retVal.xyzw, b;
+}
+
+bvec4 __constructor(const float f)
+{
+ __asm vec4_sne __retVal.xyzw, f, 0.0;
+}
+
+bvec4 __constructor(const int i)
+{
+ __asm vec4_sne __retVal.xyzw, i, 0.0;
+}
+
+bvec4 __constructor(const vec4 v)
+{
+ __asm vec4_sne __retVal.xyzw, v, 0.0;
+}
+
+bvec4 __constructor(const ivec4 v)
+{
+ __asm vec4_sne __retVal.xyzw, v, 0.0;
+}
+
+
+
+//// mat2 constructors
+
+mat2 __constructor(const float m00, const float m10,
+ const float m01, const float m11)
+{
+ __retVal[0].x = m00;
+ __retVal[0].y = m10;
+ __retVal[1].x = m01;
+ __retVal[1].y = m11;
+}
+
+mat2 __constructor(const float f)
+{
+ __retVal[0].x = f;
+ __retVal[0].y = 0.0;
+ __retVal[1].x = 0.0;
+ __retVal[1].y = f;
+}
+
+mat2 __constructor(const int i)
+{
+ return mat2(float(i));
+}
+
+mat2 __constructor(const bool b)
+{
+ return mat2(float(b));
+}
+
+mat2 __constructor(const vec2 c0, const vec2 c1)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+}
+
+
+//// mat3 constructors
+
+mat3 __constructor(const float m00, const float m10, const float m20,
+ const float m01, const float m11, const float m21,
+ const float m02, const float m12, const float m22)
+{
+ __retVal[0].x = m00;
+ __retVal[0].y = m10;
+ __retVal[0].z = m20;
+ __retVal[1].x = m01;
+ __retVal[1].y = m11;
+ __retVal[1].z = m21;
+ __retVal[2].x = m02;
+ __retVal[2].y = m12;
+ __retVal[2].z = m22;
+}
+
+mat3 __constructor(const float f)
+{
+ vec2 v = vec2(f, 0.0);
+ __retVal[0] = v.xyy;
+ __retVal[1] = v.yxy;
+ __retVal[2] = v.yyx;
+}
+
+mat3 __constructor(const int i)
+{
+ return mat3(float(i));
+}
+
+mat3 __constructor(const bool b)
+{
+ return mat3(float(b));
+}
+
+mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+}
+
+
+//// mat4 constructors
+
+mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
+ const float m01, const float m11, const float m21, const float m31,
+ const float m02, const float m12, const float m22, const float m32,
+ const float m03, const float m13, const float m23, const float m33)
+{
+ __retVal[0].x = m00;
+ __retVal[0].y = m10;
+ __retVal[0].z = m20;
+ __retVal[0].w = m30;
+ __retVal[1].x = m01;
+ __retVal[1].y = m11;
+ __retVal[1].z = m21;
+ __retVal[1].w = m31;
+ __retVal[2].x = m02;
+ __retVal[2].y = m12;
+ __retVal[2].z = m22;
+ __retVal[2].w = m32;
+ __retVal[3].x = m03;
+ __retVal[3].y = m13;
+ __retVal[3].z = m23;
+ __retVal[3].w = m33;
+}
+
+
+mat4 __constructor(const float f)
+{
+ vec2 v = vec2(f, 0.0);
+ __retVal[0] = v.xyyy;
+ __retVal[1] = v.yxyy;
+ __retVal[2] = v.yyxy;
+ __retVal[3] = v.yyyx;
+}
+
+mat4 __constructor(const int i)
+{
+ return mat4(float(i));
+}
+
+mat4 __constructor(const bool b)
+{
+ return mat4(float(b));
+}
+
+mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
+{
+ __retVal[0] = c0;
+ __retVal[1] = c1;
+ __retVal[2] = c2;
+ __retVal[3] = c3;
+}
+
+
+
+//// Basic int operators
+
+int __operator + (const int a, const int b)
+{
+ __asm vec4_add __retVal, a, b;
+}
+
+int __operator - (const int a, const int b)
+{
+ __asm vec4_subtract __retVal, a, b;
+}
+
+int __operator * (const int a, const int b)
+{
+ __asm vec4_multiply __retVal, a, b;
+}
+
+int __operator / (const int a, const int b)
+{
+ float bInv, x;
+ __asm float_rcp bInv, b;
+ __asm vec4_multiply x, a, bInv;
+ __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec2 operators
+
+ivec2 __operator + (const ivec2 a, const ivec2 b)
+{
+ __asm vec4_add __retVal, a, b;
+}
+
+ivec2 __operator - (const ivec2 a, const ivec2 b)
+{
+ __asm vec4_subtract __retVal, a, b;
+}
+
+ivec2 __operator * (const ivec2 a, const ivec2 b)
+{
+ __asm vec4_multiply __retVal, a, b;
+}
+
+ivec2 __operator / (const ivec2 a, const ivec2 b)
+{
+ vec2 bInv, x;
+ __asm float_rcp bInv.x, b.x;
+ __asm float_rcp bInv.y, b.y;
+ __asm vec4_multiply x, a, bInv;
+ __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec3 operators
+
+ivec3 __operator + (const ivec3 a, const ivec3 b)
+{
+ __asm vec4_add __retVal, a, b;
+}
+
+ivec3 __operator - (const ivec3 a, const ivec3 b)
+{
+ __asm vec4_subtract __retVal, a, b;
+}
+
+ivec3 __operator * (const ivec3 a, const ivec3 b)
+{
+ __asm vec4_multiply __retVal, a, b;
+}
+
+ivec3 __operator / (const ivec3 a, const ivec3 b)
+{
+ vec3 bInv, x;
+ __asm float_rcp bInv.x, b.x;
+ __asm float_rcp bInv.y, b.y;
+ __asm float_rcp bInv.z, b.z;
+ __asm vec4_multiply x, a, bInv;
+ __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic ivec4 operators
+
+ivec4 __operator + (const ivec4 a, const ivec4 b)
+{
+ __asm vec4_add __retVal, a, b;
+}
+
+ivec4 __operator - (const ivec4 a, const ivec4 b)
+{
+ __asm vec4_subtract __retVal, a, b;
+}
+
+ivec4 __operator * (const ivec4 a, const ivec4 b)
+{
+ __asm vec4_multiply __retVal, a, b;
+}
+
+ivec4 __operator / (const ivec4 a, const ivec4 b)
+{
+ vec4 bInv, x;
+ __asm float_rcp bInv.x, b.x;
+ __asm float_rcp bInv.y, b.y;
+ __asm float_rcp bInv.z, b.z;
+ __asm float_rcp bInv.w, b.w;
+ __asm vec4_multiply x, a, bInv;
+ __asm vec4_to_ivec4 __retVal, x;
+}
+
+
+//// Basic float operators
+
+float __operator + (const float a, const float b)
+{
+ __asm vec4_add __retVal, a, b;
+}
+
+float __operator - (const float a, const float b)
+{
+ __asm vec4_subtract __retVal, a, b;
+}
+
+float __operator * (const float a, const float b)
+{
+ __asm vec4_multiply __retVal, a, b;
+}
+
+float __operator / (const float a, const float b)
+{
+ float bInv;
+ __asm float_rcp bInv.x, b;
+ __asm vec4_multiply __retVal, a, bInv;
+}
+
+
+//// Basic vec2 operators
+
+vec2 __operator + (const vec2 v, const vec2 u)
+{
+ __asm vec4_add __retVal.xy, v, u;
+}
+
+vec2 __operator - (const vec2 v, const vec2 u)
+{
+ __asm vec4_subtract __retVal.xy, v, u;
+}
+
+vec2 __operator * (const vec2 v, const vec2 u)
+{
+ __asm vec4_multiply __retVal.xy, v, u;
+}
+
+vec2 __operator / (const vec2 v, const vec2 u)
+{
+ vec2 w; // = 1 / u
+ __asm float_rcp w.x, u.x;
+ __asm float_rcp w.y, u.y;
+ __asm vec4_multiply __retVal.xy, v, w;
+}
+
+
+//// Basic vec3 operators
+
+vec3 __operator + (const vec3 v, const vec3 u)
+{
+ __asm vec4_add __retVal.xyz, v, u;
+}
+
+vec3 __operator - (const vec3 v, const vec3 u)
+{
+ __asm vec4_subtract __retVal.xyz, v, u;
+}
+
+vec3 __operator * (const vec3 v, const vec3 u)
+{
+ __asm vec4_multiply __retVal.xyz, v, u;
+}
+
+vec3 __operator / (const vec3 v, const vec3 u)
+{
+ vec3 w; // = 1 / u
+ __asm float_rcp w.x, u.x;
+ __asm float_rcp w.y, u.y;
+ __asm float_rcp w.z, u.z;
+ __asm vec4_multiply __retVal.xyz, v, w;
+}
+
+
+//// Basic vec4 operators
+
+vec4 __operator + (const vec4 v, const vec4 u)
+{
+ __asm vec4_add __retVal, v, u;
+}
+
+vec4 __operator - (const vec4 v, const vec4 u)
+{
+ __asm vec4_subtract __retVal, v, u;
+}
+
+vec4 __operator * (const vec4 v, const vec4 u)
+{
+ __asm vec4_multiply __retVal, v, u;
+}
+
+vec4 __operator / (const vec4 v, const vec4 u)
+{
+ vec4 w; // = 1 / u
+ __asm float_rcp w.x, u.x;
+ __asm float_rcp w.y, u.y;
+ __asm float_rcp w.z, u.z;
+ __asm float_rcp w.w, u.w;
+ __asm vec4_multiply __retVal, v, w;
+}
+
+
+
+
+//// Basic vec2/float operators
+
+vec2 __operator + (const float a, const vec2 u)
+{
+ __asm vec4_add __retVal.xy, a, u.xy;
+}
+
+vec2 __operator + (const vec2 v, const float b)
+{
+ __asm vec4_add __retVal.xy, v.xy, b;
+}
+
+vec2 __operator - (const float a, const vec2 u)
+{
+ __asm vec4_subtract __retVal.xy, a, u.xy;
+}
+
+vec2 __operator - (const vec2 v, const float b)
+{
+ __asm vec4_subtract __retVal.xy, v.xy, b;
+}
+
+vec2 __operator * (const float a, const vec2 u)
+{
+ __asm vec4_multiply __retVal.xy, a, u.xy;
+}
+
+vec2 __operator * (const vec2 v, const float b)
+{
+ __asm vec4_multiply __retVal.xy, v.xy, b;
+}
+
+vec2 __operator / (const float a, const vec2 u)
+{
+ vec2 invU;
+ __asm float_rcp invU.x, u.x;
+ __asm float_rcp invU.y, u.y;
+ __asm vec4_multiply __retVal.xy, a, invU.xy;
+}
+
+vec2 __operator / (const vec2 v, const float b)
+{
+ float invB;
+ __asm float_rcp invB, b;
+ __asm vec4_multiply __retVal.xy, v.xy, invB;
+}
+
+
+//// Basic vec3/float operators
+
+vec3 __operator + (const float a, const vec3 u)
+{
+ __asm vec4_add __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator + (const vec3 v, const float b)
+{
+ __asm vec4_add __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator - (const float a, const vec3 u)
+{
+ __asm vec4_subtract __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator - (const vec3 v, const float b)
+{
+ __asm vec4_subtract __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator * (const float a, const vec3 u)
+{
+ __asm vec4_multiply __retVal.xyz, a, u.xyz;
+}
+
+vec3 __operator * (const vec3 v, const float b)
+{
+ __asm vec4_multiply __retVal.xyz, v.xyz, b;
+}
+
+vec3 __operator / (const float a, const vec3 u)
+{
+ vec3 invU;
+ __asm float_rcp invU.x, u.x;
+ __asm float_rcp invU.y, u.y;
+ __asm float_rcp invU.z, u.z;
+ __asm vec4_multiply __retVal.xyz, a, invU.xyz;
+}
+
+vec3 __operator / (const vec3 v, const float b)
+{
+ float invB;
+ __asm float_rcp invB, b;
+ __asm vec4_multiply __retVal.xyz, v.xyz, invB;
+}
+
+
+//// Basic vec4/float operators
+
+vec4 __operator + (const float a, const vec4 u)
+{
+ __asm vec4_add __retVal, a, u;
+}
+
+vec4 __operator + (const vec4 v, const float b)
+{
+ __asm vec4_add __retVal, v, b;
+}
+
+vec4 __operator - (const float a, const vec4 u)
+{
+ __asm vec4_subtract __retVal, a, u;
+}
+
+vec4 __operator - (const vec4 v, const float b)
+{
+ __asm vec4_subtract __retVal, v, b;
+}
+
+vec4 __operator * (const float a, const vec4 u)
+{
+ __asm vec4_multiply __retVal, a, u;
+}
+
+vec4 __operator * (const vec4 v, const float b)
+{
+ __asm vec4_multiply __retVal, v, b;
+}
+
+vec4 __operator / (const float a, const vec4 u)
+{
+ vec4 invU;
+ __asm float_rcp invU.x, u.x;
+ __asm float_rcp invU.y, u.y;
+ __asm float_rcp invU.z, u.z;
+ __asm float_rcp invU.w, u.w;
+ __asm vec4_multiply __retVal, a, invU;
+}
+
+vec4 __operator / (const vec4 v, const float b)
+{
+ float invB;
+ __asm float_rcp invB, b;
+ __asm vec4_multiply __retVal, v, invB;
+}
+
+
+
+//// Basic ivec2/int operators
+
+ivec2 __operator + (const int a, const ivec2 u)
+{
+ __retVal = ivec2(a) + u;
+}
+
+ivec2 __operator + (const ivec2 v, const int b)
+{
+ __retVal = v + ivec2(b);
+}
+
+ivec2 __operator - (const int a, const ivec2 u)
+{
+ __retVal = ivec2(a) - u;
+}
+
+ivec2 __operator - (const ivec2 v, const int b)
+{
+ __retVal = v - ivec2(b);
+}
+
+ivec2 __operator * (const int a, const ivec2 u)
+{
+ __retVal = ivec2(a) * u;
+}
+
+ivec2 __operator * (const ivec2 v, const int b)
+{
+ __retVal = v * ivec2(b);
+}
+
+ivec2 __operator / (const int a, const ivec2 u)
+{
+ __retVal = ivec2(a) / u;
+}
+
+ivec2 __operator / (const ivec2 v, const int b)
+{
+ __retVal = v / ivec2(b);
+}
+
+
+//// Basic ivec3/int operators
+
+ivec3 __operator + (const int a, const ivec3 u)
+{
+ __retVal = ivec3(a) + u;
+}
+
+ivec3 __operator + (const ivec3 v, const int b)
+{
+ __retVal = v + ivec3(b);
+}
+
+ivec3 __operator - (const int a, const ivec3 u)
+{
+ __retVal = ivec3(a) - u;
+}
+
+ivec3 __operator - (const ivec3 v, const int b)
+{
+ __retVal = v - ivec3(b);
+}
+
+ivec3 __operator * (const int a, const ivec3 u)
+{
+ __retVal = ivec3(a) * u;
+}
+
+ivec3 __operator * (const ivec3 v, const int b)
+{
+ __retVal = v * ivec3(b);
+}
+
+ivec3 __operator / (const int a, const ivec3 u)
+{
+ __retVal = ivec3(a) / u;
+}
+
+ivec3 __operator / (const ivec3 v, const int b)
+{
+ __retVal = v / ivec3(b);
+}
+
+
+//// Basic ivec4/int operators
+
+ivec4 __operator + (const int a, const ivec4 u)
+{
+ __retVal = ivec4(a) + u;
+}
+
+ivec4 __operator + (const ivec4 v, const int b)
+{
+ __retVal = v + ivec4(b);
+}
+
+ivec4 __operator - (const int a, const ivec4 u)
+{
+ __retVal = ivec4(a) - u;
+}
+
+ivec4 __operator - (const ivec4 v, const int b)
+{
+ __retVal = v - ivec4(b);
+}
+
+ivec4 __operator * (const int a, const ivec4 u)
+{
+ __retVal = ivec4(a) * u;
+}
+
+ivec4 __operator * (const ivec4 v, const int b)
+{
+ __retVal = v * ivec4(b);
+}
+
+ivec4 __operator / (const int a, const ivec4 u)
+{
+ __retVal = ivec4(a) / u;
+}
+
+ivec4 __operator / (const ivec4 v, const int b)
+{
+ __retVal = v / ivec4(b);
+}
+
+
+
+
+//// Unary negation operator
+
+int __operator - (const int a)
+{
+ __asm vec4_negate __retVal.x, a;
+}
+
+ivec2 __operator - (const ivec2 v)
+{
+ __asm vec4_negate __retVal, v;
+}
+
+ivec3 __operator - (const ivec3 v)
+{
+ __asm vec4_negate __retVal, v;
+}
+
+ivec4 __operator - (const ivec4 v)
+{
+ __asm vec4_negate __retVal, v;
+}
+
+float __operator - (const float a)
+{
+ __asm vec4_negate __retVal.x, a;
+}
+
+vec2 __operator - (const vec2 v)
+{
+ __asm vec4_negate __retVal.xy, v.xy;
+}
+
+vec3 __operator - (const vec3 v)
+{
+ __asm vec4_negate __retVal.xyz, v.xyz;
+}
+
+vec4 __operator - (const vec4 v)
+{
+ __asm vec4_negate __retVal, v;
+}
+
+mat2 __operator - (const mat2 m)
+{
+ __retVal[0] = -m[0];
+ __retVal[1] = -m[1];
+}
+
+mat3 __operator - (const mat3 m)
+{
+ __retVal[0] = -m[0];
+ __retVal[1] = -m[1];
+ __retVal[2] = -m[2];
+}
+
+mat4 __operator - (const mat4 m)
+{
+ __retVal[0] = -m[0];
+ __retVal[1] = -m[1];
+ __retVal[2] = -m[2];
+ __retVal[3] = -m[3];
+}
+
+
+
+//// dot product
+
+float dot(const float a, const float b)
+{
+ __retVal = a * b;
+}
+
+float dot(const vec2 a, const vec2 b)
+{
+ __retVal = a.x * b.x + a.y * b.y;
+}
+
+float dot(const vec3 a, const vec3 b)
+{
+ __asm vec3_dot __retVal, a, b;
+}
+
+float dot(const vec4 a, const vec4 b)
+{
+ __asm vec4_dot __retVal, a, b;
+}
+
+
+
+//// int assignment operators
+
+int __operator += (inout int a, const int b)
+{
+ a = a + b;
+ return a;
+}
+
+int __operator -= (inout int a, const int b)
+{
+ a = a - b;
+ return a;
+}
+
+int __operator *= (inout int a, const int b)
+{
+ a = a * b;
+ return a;
+}
+
+int __operator /= (inout int a, const int b)
+{
+ a = a / b;
+ return a;
+}
+
+
+//// ivec2 assignment operators
+
+ivec2 __operator += (inout ivec2 v, const ivec2 u)
+{
+ v = v + u;
+ return v;
+}
+
+ivec2 __operator -= (inout ivec2 v, const ivec2 u)
+{
+ v = v - u;
+ return v;
+}
+
+ivec2 __operator *= (inout ivec2 v, const ivec2 u)
+{
+ v = v * u;
+ return v;
+}
+
+ivec2 __operator /= (inout ivec2 v, const ivec2 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+//// ivec3 assignment operators
+
+ivec3 __operator += (inout ivec3 v, const ivec3 u)
+{
+ v = v + u;
+ return v;
+}
+
+ivec3 __operator -= (inout ivec3 v, const ivec3 u)
+{
+ v = v - u;
+ return v;
+}
+
+ivec3 __operator *= (inout ivec3 v, const ivec3 u)
+{
+ v = v * u;
+ return v;
+}
+
+ivec3 __operator /= (inout ivec3 v, const ivec3 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+//// ivec4 assignment operators
+
+ivec4 __operator += (inout ivec4 v, const ivec4 u)
+{
+ v = v + u;
+ return v;
+}
+
+ivec4 __operator -= (inout ivec4 v, const ivec4 u)
+{
+ v = v - u;
+ return v;
+}
+
+ivec4 __operator *= (inout ivec4 v, const ivec4 u)
+{
+ v = v * u;
+ return v;
+}
+
+ivec4 __operator /= (inout ivec4 v, const ivec4 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+//// float assignment operators
+
+float __operator += (inout float a, const float b)
+{
+ a = a + b;
+ return a;
+}
+
+float __operator -= (inout float a, const float b)
+{
+ a = a - b;
+ return a;
+}
+
+float __operator *= (inout float a, const float b)
+{
+ a = a * b;
+ return a;
+}
+
+float __operator /= (inout float a, const float b)
+{
+ a = a / b;
+ return a;
+}
+
+
+//// vec2 assignment operators
+
+vec2 __operator += (inout vec2 v, const vec2 u)
+{
+ v = v + u;
+ return v;
+}
+
+vec2 __operator -= (inout vec2 v, const vec2 u)
+{
+ v = v - u;
+ return v;
+}
+
+vec2 __operator *= (inout vec2 v, const vec2 u)
+{
+ v = v * u;
+ return v;
+}
+
+vec2 __operator /= (inout vec2 v, const vec2 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+//// vec3 assignment operators
+
+vec3 __operator += (inout vec3 v, const vec3 u)
+{
+ v = v + u;
+ return v;
+}
+
+vec3 __operator -= (inout vec3 v, const vec3 u)
+{
+ v = v - u;
+ return v;
+}
+
+vec3 __operator *= (inout vec3 v, const vec3 u)
+{
+ v = v * u;
+ return v;
+}
+
+vec3 __operator /= (inout vec3 v, const vec3 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+//// vec4 assignment operators
+
+vec4 __operator += (inout vec4 v, const vec4 u)
+{
+ v = v + u;
+ return v;
+}
+
+vec4 __operator -= (inout vec4 v, const vec4 u)
+{
+ v = v - u;
+ return v;
+}
+
+vec4 __operator *= (inout vec4 v, const vec4 u)
+{
+ v = v * u;
+ return v;
+}
+
+vec4 __operator /= (inout vec4 v, const vec4 u)
+{
+ v = v / u;
+ return v;
+}
+
+
+
+//// ivec2/int assignment operators
+
+ivec2 __operator += (inout ivec2 v, const int a)
+{
+ v = v + ivec2(a);
+ return v;
+}
+
+ivec2 __operator -= (inout ivec2 v, const int a)
+{
+ v = v - ivec2(a);
+ return v;
+}
+
+ivec2 __operator *= (inout ivec2 v, const int a)
+{
+ v = v * ivec2(a);
+ return v;
+}
+
+ivec2 __operator /= (inout ivec2 v, const int a)
+{
+ v = v / ivec2(a);
+ return v;
+}
+
+
+//// ivec3/int assignment operators
+
+ivec3 __operator += (inout ivec3 v, const int a)
+{
+ v = v + ivec3(a);
+ return v;
+}
+
+ivec3 __operator -= (inout ivec3 v, const int a)
+{
+ v = v - ivec3(a);
+ return v;
+}
+
+ivec3 __operator *= (inout ivec3 v, const int a)
+{
+ v = v * ivec3(a);
+ return v;
+}
+
+ivec4 __operator /= (inout ivec3 v, const int a)
+{
+ v = v / ivec3(a);
+ return v;
+}
+
+
+//// ivec4/int assignment operators
+
+ivec4 __operator += (inout ivec4 v, const int a)
+{
+ v = v + ivec4(a);
+ return v;
+}
+
+ivec4 __operator -= (inout ivec4 v, const int a)
+{
+ v = v - ivec4(a);
+ return v;
+}
+
+ivec4 __operator *= (inout ivec4 v, const int a)
+{
+ v = v * ivec4(a);
+ return v;
+}
+
+ivec4 __operator /= (inout ivec4 v, const int a)
+{
+ v = v / ivec4(a);
+ return v;
+}
+
+
+
+//// vec2/float assignment operators
+
+vec2 __operator += (inout vec2 v, const float a)
+{
+ v = v + vec2(a);
+ return v;
+}
+
+vec2 __operator -= (inout vec2 v, const float a)
+{
+ v = v - vec2(a);
+ return v;
+}
+
+vec2 __operator *= (inout vec2 v, const float a)
+{
+ v = v * vec2(a);
+ return v;
+}
+
+vec2 __operator /= (inout vec2 v, const float a)
+{
+ v = v / vec2(a);
+ return v;
+}
+
+
+//// vec3/float assignment operators
+
+vec3 __operator += (inout vec3 v, const float a)
+{
+ v = v + vec3(a);
+ return v;
+}
+
+vec3 __operator -= (inout vec3 v, const float a)
+{
+ v = v - vec3(a);
+ return v;
+}
+
+vec3 __operator *= (inout vec3 v, const float a)
+{
+ v = v * vec3(a);
+ return v;
+}
+
+vec3 __operator /= (inout vec3 v, const float a)
+{
+ v = v / vec3(a);
+ return v;
+}
+
+
+//// vec4/float assignment operators
+
+vec4 __operator += (inout vec4 v, const float a)
+{
+ v = v + vec4(a);
+ return v;
+}
+
+vec4 __operator -= (inout vec4 v, const float a)
+{
+ v = v - vec4(a);
+ return v;
+}
+
+vec4 __operator *= (inout vec4 v, const float a)
+{
+ v = v * vec4(a);
+ return v;
+}
+
+vec4 __operator /= (inout vec4 v, const float a)
+{
+ v = v / vec4(a);
+ return v;
+}
+
+
+
+
+
+//// Basic mat2 operations
+
+mat2 __operator + (const mat2 m, const mat2 n)
+{
+ __retVal[0] = m[0] + n[0];
+ __retVal[1] = m[1] + n[1];
+}
+
+mat2 __operator - (const mat2 m, const mat2 n)
+{
+ __retVal[0] = m[0] - n[0];
+ __retVal[1] = m[1] - n[1];
+}
+
+mat2 __operator * (const mat2 m, const mat2 n)
+{
+ __retVal[0] = m[0] * n[0].xx + m[1] * n[0].yy;
+ __retVal[1] = m[0] * n[1].xx + m[1] * n[1].yy;
+}
+
+mat2 __operator / (const mat2 m, const mat2 n)
+{
+ __retVal[0] = m[0] / n[0];
+ __retVal[1] = m[1] / n[1];
+}
+
+
+//// Basic mat3 operations
+
+mat3 __operator + (const mat3 m, const mat3 n)
+{
+ __retVal[0] = m[0] + n[0];
+ __retVal[1] = m[1] + n[1];
+ __retVal[2] = m[2] + n[2];
+}
+
+mat3 __operator - (const mat3 m, const mat3 n)
+{
+ __retVal[0] = m[0] - n[0];
+ __retVal[1] = m[1] - n[1];
+ __retVal[2] = m[2] - n[2];
+}
+
+mat3 __operator * (const mat3 m, const mat3 n)
+{
+ __retVal[0] = m[0] * n[0].xxx + m[1] * n[0].yyy + m[2] * n[0].zzz;
+ __retVal[1] = m[0] * n[1].xxx + m[1] * n[1].yyy + m[2] * n[1].zzz;
+ __retVal[2] = m[0] * n[2].xxx + m[1] * n[2].yyy + m[2] * n[2].zzz;
+}
+
+mat3 __operator / (const mat3 m, const mat3 n)
+{
+ __retVal[0] = m[0] / n[0];
+ __retVal[1] = m[1] / n[1];
+ __retVal[2] = m[2] / n[2];
+}
+
+
+//// Basic mat4 operations
+
+mat4 __operator + (const mat4 m, const mat4 n)
+{
+ __retVal[0] = m[0] + n[0];
+ __retVal[1] = m[1] + n[1];
+ __retVal[2] = m[2] + n[2];
+ __retVal[3] = m[3] + n[3];
+}
+
+mat4 __operator - (const mat4 m, const mat4 n)
+{
+ __retVal[0] = m[0] - n[0];
+ __retVal[1] = m[1] - n[1];
+ __retVal[2] = m[2] - n[2];
+ __retVal[3] = m[3] - n[3];
+}
+
+mat4 __operator * (const mat4 m, const mat4 n)
+{
+ __retVal[0] = m[0] * n[0].xxxx + m[1] * n[0].yyyy + m[2] * n[0].zzzz + m[3] * n[0].wwww;
+ __retVal[1] = m[0] * n[1].xxxx + m[1] * n[1].yyyy + m[2] * n[1].zzzz + m[3] * n[1].wwww;
+ __retVal[2] = m[0] * n[2].xxxx + m[1] * n[2].yyyy + m[2] * n[2].zzzz + m[3] * n[2].wwww;
+ __retVal[3] = m[0] * n[3].xxxx + m[1] * n[3].yyyy + m[2] * n[3].zzzz + m[3] * n[3].wwww;
+}
+
+mat4 __operator / (const mat4 m, const mat4 n)
+{
+ __retVal[0] = m[0] / n[0];
+ __retVal[1] = m[1] / n[1];
+ __retVal[2] = m[2] / n[2];
+ __retVal[3] = m[3] / n[3];
+}
+
+
+//// mat2/float operations
+
+mat2 __operator + (const float a, const mat2 n)
+{
+ __retVal[0] = a + n[0];
+ __retVal[1] = a + n[1];
+}
+
+mat2 __operator + (const mat2 m, const float b)
+{
+ __retVal[0] = m[0] + b;
+ __retVal[1] = m[1] + b;
+}
+
+mat2 __operator - (const float a, const mat2 n)
+{
+ __retVal[0] = a - n[0];
+ __retVal[1] = a - n[1];
+}
+
+mat2 __operator - (const mat2 m, const float b)
+{
+ __retVal[0] = m[0] - b;
+ __retVal[1] = m[1] - b;
+}
+
+mat2 __operator * (const float a, const mat2 n)
+{
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+}
+
+mat2 __operator * (const mat2 m, const float b)
+{
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+}
+
+mat2 __operator / (const float a, const mat2 n)
+{
+ __retVal[0] = a / n[0];
+ __retVal[1] = a / n[1];
+}
+
+mat2 __operator / (const mat2 m, const float b)
+{
+ __retVal[0] = m[0] / b;
+ __retVal[1] = m[1] / b;
+}
+
+
+//// mat3/float operations
+
+mat3 __operator + (const float a, const mat3 n)
+{
+ __retVal[0] = a + n[0];
+ __retVal[1] = a + n[1];
+ __retVal[2] = a + n[2];
+}
+
+mat3 __operator + (const mat3 m, const float b)
+{
+ __retVal[0] = m[0] + b;
+ __retVal[1] = m[1] + b;
+ __retVal[2] = m[2] + b;
+}
+
+mat3 __operator - (const float a, const mat3 n)
+{
+ __retVal[0] = a - n[0];
+ __retVal[1] = a - n[1];
+ __retVal[2] = a - n[2];
+}
+
+mat3 __operator - (const mat3 m, const float b)
+{
+ __retVal[0] = m[0] - b;
+ __retVal[1] = m[1] - b;
+ __retVal[2] = m[2] - b;
+}
+
+mat3 __operator * (const float a, const mat3 n)
+{
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+}
+
+mat3 __operator * (const mat3 m, const float b)
+{
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+}
+
+mat3 __operator / (const float a, const mat3 n)
+{
+ __retVal[0] = a / n[0];
+ __retVal[1] = a / n[1];
+ __retVal[2] = a / n[2];
+}
+
+mat3 __operator / (const mat3 m, const float b)
+{
+ __retVal[0] = m[0] / b;
+ __retVal[1] = m[1] / b;
+ __retVal[2] = m[2] / b;
+}
+
+
+//// mat4/float operations
+
+mat4 __operator + (const float a, const mat4 n)
+{
+ __retVal[0] = a + n[0];
+ __retVal[1] = a + n[1];
+ __retVal[2] = a + n[2];
+ __retVal[3] = a + n[3];
+}
+
+mat4 __operator + (const mat4 m, const float b)
+{
+ __retVal[0] = m[0] + b;
+ __retVal[1] = m[1] + b;
+ __retVal[2] = m[2] + b;
+ __retVal[3] = m[3] + b;
+}
+
+mat4 __operator - (const float a, const mat4 n)
+{
+ __retVal[0] = a - n[0];
+ __retVal[1] = a - n[1];
+ __retVal[2] = a - n[2];
+ __retVal[3] = a - n[3];
+}
+
+mat4 __operator - (const mat4 m, const float b)
+{
+ __retVal[0] = m[0] - b;
+ __retVal[1] = m[1] - b;
+ __retVal[2] = m[2] - b;
+ __retVal[3] = m[3] - b;
+}
+
+mat4 __operator * (const float a, const mat4 n)
+{
+ __retVal[0] = a * n[0];
+ __retVal[1] = a * n[1];
+ __retVal[2] = a * n[2];
+ __retVal[3] = a * n[3];
+}
+
+mat4 __operator * (const mat4 m, const float b)
+{
+ __retVal[0] = m[0] * b;
+ __retVal[1] = m[1] * b;
+ __retVal[2] = m[2] * b;
+ __retVal[3] = m[3] * b;
+}
+
+mat4 __operator / (const float a, const mat4 n)
+{
+ __retVal[0] = a / n[0];
+ __retVal[1] = a / n[1];
+ __retVal[2] = a / n[2];
+ __retVal[3] = a / n[3];
+}
+
+mat4 __operator / (const mat4 m, const float b)
+{
+ __retVal[0] = m[0] / b;
+ __retVal[1] = m[1] / b;
+ __retVal[2] = m[2] / b;
+ __retVal[3] = m[3] / b;
+}
+
+
+
+//// matrix / vector products
+
+vec2 __operator * (const mat2 m, const vec2 v)
+{
+ __retVal = m[0] * v.xx
+ + m[1] * v.yy;
+}
+
+vec2 __operator * (const vec2 v, const mat2 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+}
+
+vec3 __operator * (const mat3 m, const vec3 v)
+{
+ __retVal = m[0] * v.xxx
+ + m[1] * v.yyy
+ + m[2] * v.zzz;
+}
+
+vec3 __operator * (const vec3 v, const mat3 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+}
+
+vec4 __operator * (const mat4 m, const vec4 v)
+{
+ __retVal = m[0] * v.xxxx
+ + m[1] * v.yyyy
+ + m[2] * v.zzzz
+ + m[3] * v.wwww;
+}
+
+vec4 __operator * (const vec4 v, const mat4 m)
+{
+ __retVal.x = dot(v, m[0]);
+ __retVal.y = dot(v, m[1]);
+ __retVal.z = dot(v, m[2]);
+ __retVal.w = dot(v, m[3]);
+}
+
+
+
+//// mat2 assignment operators
+
+mat2 __operator += (inout mat2 m, const mat2 n)
+{
+ m[0] = m[0] + n[0];
+ m[1] = m[1] + n[1];
+ return m;
+}
+
+mat2 __operator -= (inout mat2 m, const mat2 n)
+{
+ m[0] = m[0] - n[0];
+ m[1] = m[1] - n[1];
+ return m;
+}
+
+mat2 __operator *= (inout mat2 m, const mat2 n)
+{
+ m = m * n;
+ return m;
+}
+
+mat2 __operator /= (inout mat2 m, const mat2 n)
+{
+ m[0] = m[0] / n[0];
+ m[1] = m[1] / n[1];
+ return m;
+}
+
+
+//// mat3 assignment operators
+
+mat3 __operator += (inout mat3 m, const mat3 n)
+{
+ m[0] = m[0] + n[0];
+ m[1] = m[1] + n[1];
+ m[2] = m[2] + n[2];
+ return m;
+}
+
+mat3 __operator -= (inout mat3 m, const mat3 n)
+{
+ m[0] = m[0] - n[0];
+ m[1] = m[1] - n[1];
+ m[2] = m[2] - n[2];
+ return m;
+}
+
+mat3 __operator *= (inout mat3 m, const mat3 n)
+{
+ m = m * n;
+ return m;
+}
+
+mat3 __operator /= (inout mat3 m, const mat3 n)
+{
+ m[0] = m[0] / n[0];
+ m[1] = m[1] / n[1];
+ m[2] = m[2] / n[2];
+ return m;
+}
+
+
+// mat4 assignment operators
+
+mat4 __operator += (inout mat4 m, const mat4 n)
+{
+ m[0] = m[0] + n[0];
+ m[1] = m[1] + n[1];
+ m[2] = m[2] + n[2];
+ m[3] = m[3] + n[3];
+ return m;
+}
+
+mat4 __operator -= (inout mat4 m, const mat4 n)
+{
+ m[0] = m[0] - n[0];
+ m[1] = m[1] - n[1];
+ m[2] = m[2] - n[2];
+ m[3] = m[3] - n[3];
+ return m;
+}
+
+mat4 __operator *= (inout mat4 m, const mat4 n)
+{
+ m = m * n;
+ return m;
+}
+
+mat4 __operator /= (inout mat4 m, const mat4 n)
+{
+ m[0] = m[0] / n[0];
+ m[1] = m[1] / n[1];
+ m[2] = m[2] / n[2];
+ m[3] = m[3] / n[3];
+ return m;
+}
+
+
+//// mat2/float assignment operators
+
+mat2 __operator += (inout mat2 m, const float a)
+{
+ vec2 v = vec2(a);
+ m[0] = m[0] + v;
+ m[1] = m[1] + v;
+ return m;
+}
+
+mat2 __operator -= (inout mat2 m, const float a)
+{
+ vec2 v = vec2(a);
+ m[0] = m[0] - v;
+ m[1] = m[1] - v;
+ return m;
+}
+
+mat2 __operator *= (inout mat2 m, const float a)
+{
+ vec2 v = vec2(a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ return m;
+}
+
+mat2 __operator /= (inout mat2 m, const float a)
+{
+ vec2 v = vec2(1.0 / a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ return m;
+}
+
+
+//// mat3/float assignment operators
+
+mat3 __operator += (inout mat3 m, const float a)
+{
+ vec3 v = vec3(a);
+ m[0] = m[0] + v;
+ m[1] = m[1] + v;
+ m[2] = m[2] + v;
+ return m;
+}
+
+mat3 __operator -= (inout mat3 m, const float a)
+{
+ vec3 v = vec3(a);
+ m[0] = m[0] - v;
+ m[1] = m[1] - v;
+ m[2] = m[2] - v;
+ return m;
+}
+
+mat3 __operator *= (inout mat3 m, const float a)
+{
+ vec3 v = vec3(a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ m[2] = m[2] * v;
+ return m;
+}
+
+mat3 __operator /= (inout mat3 m, const float a)
+{
+ vec3 v = vec3(1.0 / a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ m[2] = m[2] * v;
+ return m;
+}
+
+
+//// mat4/float assignment operators
+
+mat4 __operator += (inout mat4 m, const float a)
+{
+ vec4 v = vec4(a);
+ m[0] = m[0] + v;
+ m[1] = m[1] + v;
+ m[2] = m[2] + v;
+ m[3] = m[3] + v;
+ return m;
+}
+
+mat4 __operator -= (inout mat4 m, const float a)
+{
+ vec4 v = vec4(a);
+ m[0] = m[0] - v;
+ m[1] = m[1] - v;
+ m[2] = m[2] - v;
+ m[3] = m[3] - v;
+ return m;
+}
+
+mat4 __operator *= (inout mat4 m, const float a)
+{
+ vec4 v = vec4(a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ m[2] = m[2] * v;
+ m[3] = m[3] * v;
+ return m;
+}
+
+mat4 __operator /= (inout mat4 m, const float a)
+{
+ vec4 v = vec4(1.0 / a);
+ m[0] = m[0] * v;
+ m[1] = m[1] * v;
+ m[2] = m[2] * v;
+ m[3] = m[3] * v;
+ return m;
+}
+
+
+
+//// vec/mat assignment operators
+
+vec2 __operator *= (inout vec2 v, const mat2 m)
+{
+ v = v * m;
+ return v;
+}
+
+vec3 __operator *= (inout vec3 v, const mat3 m)
+{
+ v = v * m;
+ return v;
+}
+
+vec4 __operator *= (inout vec4 v, const mat4 m)
+{
+ v = v * m;
+ return v;
+}
+
+
+
+//// pre-decrement operators
+
+int __operator --(inout int a)
+{
+ a = a - 1;
+ __retVal = a;
+}
+
+ivec2 __operator --(inout ivec2 v)
+{
+ v = v - ivec2(1);
+ __retVal = v;
+}
+
+ivec3 __operator --(inout ivec3 v)
+{
+ v = v - ivec3(1);
+ __retVal = v;
+}
+
+ivec4 __operator --(inout ivec4 v)
+{
+ v = v - ivec4(1);
+ __retVal = v;
+}
+
+
+float __operator --(inout float a)
+{
+ a = a - 1.0;
+ __retVal = a;
+}
+
+vec2 __operator --(inout vec2 v)
+{
+ v = v - vec2(1.0);
+ __retVal = v;
+}
+
+vec3 __operator --(inout vec3 v)
+{
+ v = v - vec3(1.0);
+ __retVal = v;
+}
+
+vec4 __operator --(inout vec4 v)
+{
+ v = v - vec4(1.0);
+ __retVal = v;
+}
+
+
+mat2 __operator --(inout mat2 m)
+{
+ m[0] = m[0] - vec2(1.0);
+ m[1] = m[1] - vec2(1.0);
+ __retVal = m;
+}
+
+mat3 __operator --(inout mat3 m)
+{
+ m[0] = m[0] - vec3(1.0);
+ m[1] = m[1] - vec3(1.0);
+ m[2] = m[2] - vec3(1.0);
+ __retVal = m;
+}
+
+mat4 __operator --(inout mat4 m)
+{
+ m[0] = m[0] - vec4(1.0);
+ m[1] = m[1] - vec4(1.0);
+ m[2] = m[2] - vec4(1.0);
+ m[3] = m[3] - vec4(1.0);
+ __retVal = m;
+}
+
+
+//// pre-increment operators
+
+int __operator ++(inout int a)
+{
+ a = a + 1;
+ __retVal = a;
+}
+
+ivec2 __operator ++(inout ivec2 v)
+{
+ v = v + ivec2(1);
+ __retVal = v;
+}
+
+ivec3 __operator ++(inout ivec3 v)
+{
+ v = v + ivec3(1);
+ __retVal = v;
+}
+
+ivec4 __operator ++(inout ivec4 v)
+{
+ v = v + ivec4(1);
+ __retVal = v;
+}
+
+
+float __operator ++(inout float a)
+{
+ a = a + 1.0;
+ __retVal = a;
+}
+
+vec2 __operator ++(inout vec2 v)
+{
+ v = v + vec2(1.0);
+ __retVal = v;
+}
+
+vec3 __operator ++(inout vec3 v)
+{
+ v = v + vec3(1.0);
+ __retVal = v;
+}
+
+vec4 __operator ++(inout vec4 v)
+{
+ v = v + vec4(1.0);
+ __retVal = v;
+}
+
+
+mat2 __operator ++(inout mat2 m)
+{
+ m[0] = m[0] + vec2(1.0);
+ m[1] = m[1] + vec2(1.0);
+ __retVal = m;
+}
+
+mat3 __operator ++(inout mat3 m)
+{
+ m[0] = m[0] + vec3(1.0);
+ m[1] = m[1] + vec3(1.0);
+ m[2] = m[2] + vec3(1.0);
+ __retVal = m;
+}
+
+mat4 __operator ++(inout mat4 m)
+{
+ m[0] = m[0] + vec4(1.0);
+ m[1] = m[1] + vec4(1.0);
+ m[2] = m[2] + vec4(1.0);
+ m[3] = m[3] + vec4(1.0);
+ __retVal = m;
+}
+
+
+
+//// post-decrement
+
+int __postDecr(inout int a)
+{
+ __retVal = a;
+ a = a - 1;
+}
+
+ivec2 __postDecr(inout ivec2 v)
+{
+ __retVal = v;
+ v = v - ivec2(1);
+}
+
+ivec3 __postDecr(inout ivec3 v)
+{
+ __retVal = v;
+ v = v - ivec3(1);
+}
+
+ivec4 __postDecr(inout ivec4 v)
+{
+ __retVal = v;
+ v = v - ivec4(1);
+}
+
+
+float __postDecr(inout float a)
+{
+ __retVal = a;
+ a = a - 1.0;
+}
+
+vec2 __postDecr(inout vec2 v)
+{
+ __retVal = v;
+ v = v - vec2(1.0);
+}
+
+vec3 __postDecr(inout vec3 v)
+{
+ __retVal = v;
+ v = v - vec3(1.0);
+}
+
+vec4 __postDecr(inout vec4 v)
+{
+ __retVal = v;
+ v = v - vec4(1.0);
+}
+
+
+mat2 __postDecr(inout mat2 m)
+{
+ __retVal = m;
+ m[0] = m[0] - vec2(1.0);
+ m[1] = m[1] - vec2(1.0);
+}
+
+mat3 __postDecr(inout mat3 m)
+{
+ __retVal = m;
+ m[0] = m[0] - vec3(1.0);
+ m[1] = m[1] - vec3(1.0);
+ m[2] = m[2] - vec3(1.0);
+}
+
+mat4 __postDecr(inout mat4 m)
+{
+ __retVal = m;
+ m[0] = m[0] - vec4(1.0);
+ m[1] = m[1] - vec4(1.0);
+ m[2] = m[2] - vec4(1.0);
+ m[3] = m[3] - vec4(1.0);
+}
+
+
+//// post-increment
+
+float __postIncr(inout float a)
+{
+ __retVal = a;
+ a = a + 1;
+}
+
+vec2 __postIncr(inout vec2 v)
+{
+ __retVal = v;
+ v = v + vec2(1.0);
+}
+
+vec3 __postIncr(inout vec3 v)
+{
+ __retVal = v;
+ v = v + vec3(1.0);
+}
+
+vec4 __postIncr(inout vec4 v)
+{
+ __retVal = v;
+ v = v + vec4(1.0);
+}
+
+
+int __postIncr(inout int a)
+{
+ __retVal = a;
+ a = a + 1;
+}
+
+ivec2 __postIncr(inout ivec2 v)
+{
+ __retVal = v;
+ v = v + ivec2(1);
+}
+
+ivec3 __postIncr(inout ivec3 v)
+{
+ __retVal = v;
+ v = v + ivec3(1);
+}
+
+ivec4 __postIncr(inout ivec4 v)
+{
+ __retVal = v;
+ v = v + ivec3(1);
+}
+
+
+mat2 __postIncr(inout mat2 m)
+{
+ mat2 n = m;
+ m[0] = m[0] + vec2(1.0);
+ m[1] = m[1] + vec2(1.0);
+ return n;
+}
+
+mat3 __postIncr(inout mat3 m)
+{
+ mat3 n = m;
+ m[0] = m[0] + vec3(1.0);
+ m[1] = m[1] + vec3(1.0);
+ m[2] = m[2] + vec3(1.0);
+ return n;
+}
+
+mat4 __postIncr(inout mat4 m)
+{
+ mat4 n = m;
+ m[0] = m[0] + vec4(1.0);
+ m[1] = m[1] + vec4(1.0);
+ m[2] = m[2] + vec4(1.0);
+ m[3] = m[3] + vec4(1.0);
+ return n;
+}
+
+
+
+//// inequality operators
+
+
+// XXX are the inequality operators for floats/ints really needed????
+bool __operator < (const float a, const float b)
+{
+ __asm vec4_sgt __retVal.x, b, a;
+}
+
+
+bool __operator < (const int a, const int b) {
+ return float (a) < float (b);
+}
+
+bool __operator > (const float a, const float b) {
+ bool c;
+ __asm float_less c, b, a;
+ return c;
+}
+
+bool __operator > (const int a, const int b) {
+ return float (a) > float (b);
+}
+
+bool __operator >= (const float a, const float b) {
+ bool g, e;
+ __asm float_less g, b, a;
+ __asm float_equal e, a, b;
+ return g || e;
+}
+
+bool __operator >= (const int a, const int b) {
+ return float (a) >= float (b);
+}
+
+bool __operator <= (const float a, const float b) {
+ bool g, e;
+ __asm float_less g, a, b;
+ __asm float_equal e, a, b;
+ return g || e;
+}
+
+bool __operator <= (const int a, const int b) {
+ return float (a) <= float (b);
+}
+
+
+
+//
+// MESA-specific extension functions.
+//
+
+void printMESA (const float f) {
+ __asm float_print f;
+}
+
+void printMESA (const int i) {
+ __asm int_print i;
+}
+
+void printMESA (const bool b) {
+ __asm bool_print b;
+}
+
+void printMESA (const vec2 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+}
+
+void printMESA (const vec3 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+}
+
+void printMESA (const vec4 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+ printMESA (v.w);
+}
+
+void printMESA (const ivec2 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+}
+
+void printMESA (const ivec3 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+}
+
+void printMESA (const ivec4 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+ printMESA (v.w);
+}
+
+void printMESA (const bvec2 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+}
+
+void printMESA (const bvec3 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+}
+
+void printMESA (const bvec4 v) {
+ printMESA (v.x);
+ printMESA (v.y);
+ printMESA (v.z);
+ printMESA (v.w);
+}
+
+void printMESA (const mat2 m) {
+ printMESA (m[0]);
+ printMESA (m[1]);
+}
+
+void printMESA (const mat3 m) {
+ printMESA (m[0]);
+ printMESA (m[1]);
+ printMESA (m[2]);
+}
+
+void printMESA (const mat4 m) {
+ printMESA (m[0]);
+ printMESA (m[1]);
+ printMESA (m[2]);
+ printMESA (m[3]);
+}
+
+void printMESA (const sampler1D e) {
+ __asm int_print e;
+}
+
+void printMESA (const sampler2D e) {
+ __asm int_print e;
+}
+
+void printMESA (const sampler3D e) {
+ __asm int_print e;
+}
+
+void printMESA (const samplerCube e) {
+ __asm int_print e;
+}
+
+void printMESA (const sampler1DShadow e) {
+ __asm int_print e;
+}
+
+void printMESA (const sampler2DShadow e) {
+ __asm int_print e;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_core_gc.h b/mesalib/src/mesa/shader/slang/library/slang_core_gc.h
new file mode 100644
index 000000000..b3d3e87cf
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_core_gc.h
@@ -0,0 +1,869 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_core.gc */
+
+5,1,90,95,0,0,5,0,1,1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,116,111,95,105,118,101,99,52,0,18,
+95,95,114,101,116,86,97,108,0,0,18,102,0,0,0,0,1,90,95,0,0,5,0,1,1,1,0,0,1,0,98,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,18,98,0,20,0,0,1,90,95,0,0,5,0,1,1,1,0,0,5,0,105,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,18,105,0,20,0,0,1,90,95,0,0,1,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,52,95,
+115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,105,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,1,
+1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,0,18,102,
+0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,1,0,1,1,1,0,0,1,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,18,98,0,20,0,0,1,90,95,0,0,9,0,1,1,1,0,0,5,0,105,0,0,0,1,4,105,118,101,99,52,95,116,111,95,118,
+101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,105,0,0,0,0,1,90,95,0,0,9,0,1,1,1,0,0,1,0,98,0,0,
+0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,98,0,0,
+0,0,1,90,95,0,0,9,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,102,0,20,0,0,1,
+90,95,0,0,10,0,1,1,1,0,0,9,0,120,0,0,1,1,0,0,9,0,121,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,
+120,0,18,120,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,121,0,20,0,0,1,90,95,0,0,10,0,1,
+1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,109,111,118,101,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,0,0,18,102,0,0,0,0,1,90,95,0,0,10,0,1,1,1,0,0,5,0,105,0,0,0,1,4,105,118,101,99,52,95,116,
+111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,105,0,0,0,0,1,90,95,0,0,
+10,0,1,1,1,0,0,1,0,98,0,0,0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,
+116,86,97,108,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,10,0,1,1,1,0,0,2,0,98,0,0,0,1,4,105,118,
+101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,98,0,0,
+0,0,1,90,95,0,0,10,0,1,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,109,111,118,101,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,0,0,1,90,95,0,0,10,0,1,1,1,0,0,12,0,118,
+0,0,0,1,4,118,101,99,52,95,109,111,118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,
+118,0,59,120,121,0,0,0,0,1,90,95,0,0,11,0,1,1,1,0,0,9,0,120,0,0,1,1,0,0,9,0,121,0,0,1,1,0,0,9,0,
+122,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,120,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,59,121,0,18,121,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,122,0,20,0,0,1,90,95,0,
+0,11,0,1,1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,109,111,118,101,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,122,0,0,18,102,0,0,0,0,1,90,95,0,0,11,0,1,1,1,0,0,5,0,105,0,0,0,1,4,105,118,101,
+99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,105,0,0,
+0,0,1,90,95,0,0,11,0,1,1,1,0,0,1,0,98,0,0,0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,
+95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,1,1,1,0,0,3,0,98,0,
+0,0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,1,1,1,0,0,12,0,118,0,0,0,1,4,118,101,99,52,95,109,111,
+118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,0,0,0,1,90,95,0,0,12,0,1,1,
+1,0,0,9,0,120,0,0,1,1,0,0,9,0,121,0,0,1,1,0,0,9,0,122,0,0,1,1,0,0,9,0,119,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,59,120,0,18,120,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,121,0,20,
+0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,122,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,
+119,0,18,119,0,20,0,0,1,90,95,0,0,12,0,1,1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,109,111,118,
+101,0,18,95,95,114,101,116,86,97,108,0,0,18,102,0,0,0,0,1,90,95,0,0,12,0,1,1,1,0,0,5,0,105,0,0,0,1,
+4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,105,0,0,0,
+0,1,90,95,0,0,12,0,1,1,1,0,0,1,0,98,0,0,0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,
+95,95,114,101,116,86,97,108,0,0,18,98,0,0,0,0,1,90,95,0,0,12,0,1,1,1,0,0,4,0,98,0,0,0,1,4,105,118,
+101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,98,0,0,0,0,1,90,95,0,
+0,12,0,1,1,1,0,0,8,0,105,0,0,0,1,4,105,118,101,99,52,95,116,111,95,118,101,99,52,0,18,95,95,114,
+101,116,86,97,108,0,0,18,105,0,0,0,0,1,90,95,0,0,12,0,1,1,1,0,0,11,0,118,51,0,0,1,1,0,0,9,0,102,0,
+0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,18,118,51,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,59,119,0,18,102,0,20,0,0,1,90,95,0,0,12,0,1,1,1,0,0,10,0,118,50,0,0,1,1,0,0,9,0,102,49,
+0,0,1,1,0,0,9,0,102,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,121,0,18,118,50,0,20,0,9,
+18,95,95,114,101,116,86,97,108,0,59,122,0,18,102,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,
+119,0,18,102,50,0,20,0,0,1,90,95,0,0,6,0,1,1,1,0,0,5,0,105,0,0,1,1,0,0,5,0,106,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,59,120,0,18,105,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,106,
+0,20,0,0,1,90,95,0,0,6,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,52,95,109,111,118,101,0,18,95,95,
+114,101,116,86,97,108,0,59,120,121,0,0,18,105,0,0,0,0,1,90,95,0,0,6,0,1,1,1,0,0,9,0,102,0,0,0,1,4,
+118,101,99,52,95,116,111,95,105,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,
+102,0,0,0,0,1,90,95,0,0,6,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,52,95,116,111,95,105,118,101,99,
+52,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,7,0,1,1,1,0,0,5,0,
+105,0,0,1,1,0,0,5,0,106,0,0,1,1,0,0,5,0,107,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,
+105,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,106,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,59,122,0,18,107,0,20,0,0,1,90,95,0,0,7,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,52,95,109,
+111,118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,105,0,0,0,0,1,90,95,0,0,7,0,1,
+1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,116,111,95,105,118,101,99,52,0,18,95,95,114,101,116,86,
+97,108,0,59,120,121,122,0,0,18,102,0,0,0,0,1,90,95,0,0,7,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,
+52,95,109,111,118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,
+0,0,8,0,1,1,1,0,0,5,0,120,0,0,1,1,0,0,5,0,121,0,0,1,1,0,0,5,0,122,0,0,1,1,0,0,5,0,119,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,59,120,0,18,120,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,
+18,121,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,122,0,20,0,9,18,95,95,114,101,116,86,
+97,108,0,59,119,0,18,119,0,20,0,0,1,90,95,0,0,8,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,52,95,109,
+111,118,101,0,18,95,95,114,101,116,86,97,108,0,0,18,105,0,0,0,0,1,90,95,0,0,8,0,1,1,1,0,0,9,0,102,
+0,0,0,1,4,118,101,99,52,95,116,111,95,105,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,
+102,0,0,0,0,1,90,95,0,0,8,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,52,95,116,111,95,105,118,101,99,
+52,0,18,95,95,114,101,116,86,97,108,0,0,18,98,0,0,0,0,1,90,95,0,0,2,0,1,1,1,0,0,1,0,98,49,0,0,1,1,
+0,0,1,0,98,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,98,49,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,121,0,18,98,50,0,20,0,0,1,90,95,0,0,2,0,1,1,1,0,0,5,0,105,49,0,0,1,1,0,0,5,
+0,105,50,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,
+105,49,0,0,17,48,0,48,0,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,
+121,0,0,18,105,50,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,2,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,
+52,95,109,111,118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,
+2,0,1,1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,0,0,18,102,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,2,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,
+52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,105,0,0,17,48,0,48,0,0,0,0,
+0,1,90,95,0,0,2,0,1,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,
+86,97,108,0,59,120,121,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,2,0,1,1,1,0,0,6,0,118,0,0,0,
+1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,17,
+48,0,48,0,0,0,0,0,1,90,95,0,0,3,0,1,1,1,0,0,1,0,98,49,0,0,1,1,0,0,1,0,98,50,0,0,1,1,0,0,1,0,98,51,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,98,49,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,59,121,0,18,98,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,98,51,0,20,0,0,1,90,
+95,0,0,3,0,1,1,1,0,0,9,0,102,49,0,0,1,1,0,0,9,0,102,50,0,0,1,1,0,0,9,0,102,51,0,0,0,1,4,118,101,99,
+52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,102,49,0,0,17,48,0,48,0,0,0,0,4,
+118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,102,50,0,0,17,48,0,
+48,0,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,102,51,
+0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,3,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,52,95,109,111,118,
+101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,3,0,1,1,1,0,0,
+9,0,102,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,
+0,18,102,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,3,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,101,99,52,95,115,
+110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,105,0,0,17,48,0,48,0,0,0,0,0,1,90,
+95,0,0,3,0,1,1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,122,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,3,0,1,1,1,0,0,7,0,118,0,0,0,1,
+4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,0,17,
+48,0,48,0,0,0,0,0,1,90,95,0,0,4,0,1,1,1,0,0,1,0,98,49,0,0,1,1,0,0,1,0,98,50,0,0,1,1,0,0,1,0,98,51,
+0,0,1,1,0,0,1,0,98,52,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,98,49,0,20,0,9,18,95,
+95,114,101,116,86,97,108,0,59,121,0,18,98,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,
+98,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,18,98,52,0,20,0,0,1,90,95,0,0,4,0,1,1,1,0,
+0,9,0,102,49,0,0,1,1,0,0,9,0,102,50,0,0,1,1,0,0,9,0,102,51,0,0,1,1,0,0,9,0,102,52,0,0,0,1,3,2,90,
+95,1,0,9,0,1,122,101,114,111,0,2,17,48,0,48,0,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,
+101,116,86,97,108,0,59,120,0,0,18,102,49,0,0,18,122,101,114,111,0,0,0,4,118,101,99,52,95,115,110,
+101,0,18,95,95,114,101,116,86,97,108,0,59,121,0,0,18,102,50,0,0,18,122,101,114,111,0,0,0,4,118,101,
+99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,122,0,0,18,102,51,0,0,18,122,101,114,
+111,0,0,0,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,119,0,0,18,102,52,0,
+0,18,122,101,114,111,0,0,0,0,1,90,95,0,0,4,0,1,1,1,0,0,1,0,98,0,0,0,1,4,118,101,99,52,95,109,111,
+118,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,119,0,0,18,98,0,0,0,0,1,90,95,0,0,4,0,1,
+1,1,0,0,9,0,102,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,122,119,0,0,18,102,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,4,0,1,1,1,0,0,5,0,105,0,0,0,1,4,118,
+101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,119,0,0,18,105,0,0,17,
+48,0,48,0,0,0,0,0,1,90,95,0,0,4,0,1,1,1,0,0,12,0,118,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,
+95,95,114,101,116,86,97,108,0,59,120,121,122,119,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,4,
+0,1,1,1,0,0,8,0,118,0,0,0,1,4,118,101,99,52,95,115,110,101,0,18,95,95,114,101,116,86,97,108,0,59,
+120,121,122,119,0,0,18,118,0,0,17,48,0,48,0,0,0,0,0,1,90,95,0,0,13,0,1,1,1,0,0,9,0,109,48,48,0,0,1,
+1,0,0,9,0,109,49,48,0,0,1,1,0,0,9,0,109,48,49,0,0,1,1,0,0,9,0,109,49,49,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,16,8,48,0,57,59,120,0,18,109,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,
+48,0,57,59,121,0,18,109,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,
+109,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,109,49,49,0,20,0,0,1,
+90,95,0,0,13,0,1,1,1,0,0,9,0,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,
+18,102,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,17,48,0,48,0,0,20,0,9,18,95,
+95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,17,48,0,48,0,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,49,0,57,59,121,0,18,102,0,20,0,0,1,90,95,0,0,13,0,1,1,1,0,0,5,0,105,0,0,0,1,8,58,109,
+97,116,50,0,0,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,0,0,1,90,95,0,0,13,0,1,1,1,0,0,1,0,98,0,0,
+0,1,8,58,109,97,116,50,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,0,0,1,90,95,0,0,13,0,1,1,1,0,
+0,10,0,99,48,0,0,1,1,0,0,10,0,99,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,
+48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,0,1,90,95,0,0,14,0,1,1,
+1,0,0,9,0,109,48,48,0,0,1,1,0,0,9,0,109,49,48,0,0,1,1,0,0,9,0,109,50,48,0,0,1,1,0,0,9,0,109,48,49,
+0,0,1,1,0,0,9,0,109,49,49,0,0,1,1,0,0,9,0,109,50,49,0,0,1,1,0,0,9,0,109,48,50,0,0,1,1,0,0,9,0,109,
+49,50,0,0,1,1,0,0,9,0,109,50,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,
+18,109,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,109,49,48,0,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,18,109,50,48,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,10,49,0,57,59,120,0,18,109,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,
+0,57,59,121,0,18,109,49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,122,0,18,109,
+50,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,109,48,50,0,20,0,9,18,95,
+95,114,101,116,86,97,108,0,16,10,50,0,57,59,121,0,18,109,49,50,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,59,122,0,18,109,50,50,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,9,0,102,0,0,0,1,3,2,
+90,95,0,0,10,0,1,118,0,2,58,118,101,99,50,0,0,18,102,0,0,17,48,0,48,0,0,0,0,0,0,9,18,95,95,114,101,
+116,86,97,108,0,16,8,48,0,57,18,118,0,59,120,121,121,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,49,0,57,18,118,0,59,121,120,121,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,118,
+0,59,121,121,120,0,20,0,0,1,90,95,0,0,14,0,1,1,1,0,0,5,0,105,0,0,0,1,8,58,109,97,116,51,0,0,58,102,
+108,111,97,116,0,0,18,105,0,0,0,0,0,0,0,1,90,95,0,0,14,0,1,1,1,0,0,1,0,98,0,0,0,1,8,58,109,97,116,
+51,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,0,0,1,90,95,0,0,14,0,1,1,1,0,0,11,0,99,48,0,0,1,1,
+0,0,11,0,99,49,0,0,1,1,0,0,11,0,99,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,9,0,109,48,48,0,0,1,1,0,
+0,9,0,109,49,48,0,0,1,1,0,0,9,0,109,50,48,0,0,1,1,0,0,9,0,109,51,48,0,0,1,1,0,0,9,0,109,48,49,0,0,
+1,1,0,0,9,0,109,49,49,0,0,1,1,0,0,9,0,109,50,49,0,0,1,1,0,0,9,0,109,51,49,0,0,1,1,0,0,9,0,109,48,
+50,0,0,1,1,0,0,9,0,109,49,50,0,0,1,1,0,0,9,0,109,50,50,0,0,1,1,0,0,9,0,109,51,50,0,0,1,1,0,0,9,0,
+109,48,51,0,0,1,1,0,0,9,0,109,49,51,0,0,1,1,0,0,9,0,109,50,51,0,0,1,1,0,0,9,0,109,51,51,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,109,48,48,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,16,8,48,0,57,59,121,0,18,109,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,
+57,59,122,0,18,109,50,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,119,0,18,109,51,
+48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,109,48,49,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,109,49,49,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,49,0,57,59,122,0,18,109,50,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,
+59,119,0,18,109,51,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,109,48,
+50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,121,0,18,109,49,50,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,50,0,57,59,122,0,18,109,50,50,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,59,119,0,18,109,51,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,
+59,120,0,18,109,48,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,121,0,18,109,49,
+51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,122,0,18,109,50,51,0,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,51,0,57,59,119,0,18,109,51,51,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,9,
+0,102,0,0,0,1,3,2,90,95,0,0,10,0,1,118,0,2,58,118,101,99,50,0,0,18,102,0,0,17,48,0,48,0,0,0,0,0,0,
+9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,118,0,59,120,121,121,121,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,18,118,0,59,121,120,121,121,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,18,118,0,59,121,121,120,121,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,
+0,57,18,118,0,59,121,121,121,120,0,20,0,0,1,90,95,0,0,15,0,1,1,1,0,0,5,0,105,0,0,0,1,8,58,109,97,
+116,52,0,0,58,102,108,111,97,116,0,0,18,105,0,0,0,0,0,0,0,1,90,95,0,0,15,0,1,1,1,0,0,1,0,98,0,0,0,
+1,8,58,109,97,116,52,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,0,0,0,0,1,90,95,0,0,15,0,1,1,1,0,0,
+12,0,99,48,0,0,1,1,0,0,12,0,99,49,0,0,1,1,0,0,12,0,99,50,0,0,1,1,0,0,12,0,99,51,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,99,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,51,0,57,18,99,51,0,20,0,0,1,90,95,0,0,5,0,2,26,1,1,0,0,5,0,97,0,0,1,1,0,
+0,5,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,
+98,0,0,0,0,1,90,95,0,0,5,0,2,27,1,1,0,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,4,118,101,99,52,95,115,
+117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,
+5,0,2,21,1,1,0,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,
+121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,5,0,2,22,1,1,0,0,5,0,
+97,0,0,1,1,0,0,5,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,98,73,110,118,0,0,1,1,120,0,0,0,4,102,108,111,97,
+116,95,114,99,112,0,18,98,73,110,118,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,
+108,121,0,18,120,0,0,18,97,0,0,18,98,73,110,118,0,0,0,4,118,101,99,52,95,116,111,95,105,118,101,99,
+52,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,6,0,2,26,1,1,0,0,6,0,97,0,0,1,1,
+0,0,6,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,
+98,0,0,0,0,1,90,95,0,0,6,0,2,27,1,1,0,0,6,0,97,0,0,1,1,0,0,6,0,98,0,0,0,1,4,118,101,99,52,95,115,
+117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,
+6,0,2,21,1,1,0,0,6,0,97,0,0,1,1,0,0,6,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,
+121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,6,0,2,22,1,1,0,0,6,0,
+97,0,0,1,1,0,0,6,0,98,0,0,0,1,3,2,90,95,0,0,10,0,1,98,73,110,118,0,0,1,1,120,0,0,0,4,102,108,111,
+97,116,95,114,99,112,0,18,98,73,110,118,0,59,120,0,0,18,98,0,59,120,0,0,0,4,102,108,111,97,116,95,
+114,99,112,0,18,98,73,110,118,0,59,121,0,0,18,98,0,59,121,0,0,0,4,118,101,99,52,95,109,117,108,116,
+105,112,108,121,0,18,120,0,0,18,97,0,0,18,98,73,110,118,0,0,0,4,118,101,99,52,95,116,111,95,105,
+118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,7,0,2,26,1,1,0,0,7,0,
+97,0,0,1,1,0,0,7,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,
+18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,7,0,2,27,1,1,0,0,7,0,97,0,0,1,1,0,0,7,0,98,0,0,0,1,4,118,101,
+99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,
+1,90,95,0,0,7,0,2,21,1,1,0,0,7,0,97,0,0,1,1,0,0,7,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,
+105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,7,0,2,22,
+1,1,0,0,7,0,97,0,0,1,1,0,0,7,0,98,0,0,0,1,3,2,90,95,0,0,11,0,1,98,73,110,118,0,0,1,1,120,0,0,0,4,
+102,108,111,97,116,95,114,99,112,0,18,98,73,110,118,0,59,120,0,0,18,98,0,59,120,0,0,0,4,102,108,
+111,97,116,95,114,99,112,0,18,98,73,110,118,0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,97,116,
+95,114,99,112,0,18,98,73,110,118,0,59,122,0,0,18,98,0,59,122,0,0,0,4,118,101,99,52,95,109,117,108,
+116,105,112,108,121,0,18,120,0,0,18,97,0,0,18,98,73,110,118,0,0,0,4,118,101,99,52,95,116,111,95,
+105,118,101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,8,0,2,26,1,1,0,0,
+8,0,97,0,0,1,1,0,0,8,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,
+0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,8,0,2,27,1,1,0,0,8,0,97,0,0,1,1,0,0,8,0,98,0,0,0,1,4,118,101,
+99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,
+1,90,95,0,0,8,0,2,21,1,1,0,0,8,0,97,0,0,1,1,0,0,8,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,
+105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,8,0,2,22,
+1,1,0,0,8,0,97,0,0,1,1,0,0,8,0,98,0,0,0,1,3,2,90,95,0,0,12,0,1,98,73,110,118,0,0,1,1,120,0,0,0,4,
+102,108,111,97,116,95,114,99,112,0,18,98,73,110,118,0,59,120,0,0,18,98,0,59,120,0,0,0,4,102,108,
+111,97,116,95,114,99,112,0,18,98,73,110,118,0,59,121,0,0,18,98,0,59,121,0,0,0,4,102,108,111,97,116,
+95,114,99,112,0,18,98,73,110,118,0,59,122,0,0,18,98,0,59,122,0,0,0,4,102,108,111,97,116,95,114,99,
+112,0,18,98,73,110,118,0,59,119,0,0,18,98,0,59,119,0,0,0,4,118,101,99,52,95,109,117,108,116,105,
+112,108,121,0,18,120,0,0,18,97,0,0,18,98,73,110,118,0,0,0,4,118,101,99,52,95,116,111,95,105,118,
+101,99,52,0,18,95,95,114,101,116,86,97,108,0,0,18,120,0,0,0,0,1,90,95,0,0,9,0,2,26,1,1,0,0,9,0,97,
+0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,18,
+97,0,0,18,98,0,0,0,0,1,90,95,0,0,9,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,
+52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,
+90,95,0,0,9,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,
+105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,9,0,2,22,
+1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,98,73,110,118,0,0,0,4,102,108,111,97,
+116,95,114,99,112,0,18,98,73,110,118,0,59,120,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,
+105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,73,110,118,0,0,0,0,1,90,95,0,
+0,10,0,2,26,1,1,0,0,10,0,118,0,0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,
+114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,10,0,2,27,1,1,0,0,10,
+0,118,0,0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,10,0,2,21,1,1,0,0,10,0,
+118,0,0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,10,0,2,22,1,1,0,0,10,0,
+118,0,0,1,1,0,0,10,0,117,0,0,0,1,3,2,90,95,0,0,10,0,1,119,0,0,0,4,102,108,111,97,116,95,114,99,112,
+0,18,119,0,59,120,0,0,18,117,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,121,0,
+0,18,117,0,59,121,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,
+86,97,108,0,59,120,121,0,0,18,118,0,0,18,119,0,0,0,0,1,90,95,0,0,11,0,2,26,1,1,0,0,11,0,118,0,0,1,
+1,0,0,11,0,117,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,59,120,121,
+122,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,11,0,2,27,1,1,0,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,
+0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,59,120,121,
+122,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,11,0,2,21,1,1,0,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,
+0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,
+121,122,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,11,0,2,22,1,1,0,0,11,0,118,0,0,1,1,0,0,11,0,117,
+0,0,0,1,3,2,90,95,0,0,11,0,1,119,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,120,0,0,18,
+117,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,121,0,0,18,117,0,59,121,0,0,0,
+4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,122,0,0,18,117,0,59,122,0,0,0,4,118,101,99,52,95,
+109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,0,
+18,119,0,0,0,0,1,90,95,0,0,12,0,2,26,1,1,0,0,12,0,118,0,0,1,1,0,0,12,0,117,0,0,0,1,4,118,101,99,52,
+95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,12,0,2,27,
+1,1,0,0,12,0,118,0,0,1,1,0,0,12,0,117,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,
+95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,12,0,118,0,
+0,1,1,0,0,12,0,117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,
+116,86,97,108,0,0,18,118,0,0,18,117,0,0,0,0,1,90,95,0,0,12,0,2,22,1,1,0,0,12,0,118,0,0,1,1,0,0,12,
+0,117,0,0,0,1,3,2,90,95,0,0,12,0,1,119,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,120,
+0,0,18,117,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,121,0,0,18,117,0,59,121,
+0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,119,0,59,122,0,0,18,117,0,59,122,0,0,0,4,102,108,111,
+97,116,95,114,99,112,0,18,119,0,59,119,0,0,18,117,0,59,119,0,0,0,4,118,101,99,52,95,109,117,108,
+116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,119,0,0,0,0,1,90,95,0,0,10,
+0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,0,0,18,97,0,0,18,117,0,59,120,121,0,0,0,0,1,90,95,0,0,10,0,2,26,1,1,
+0,0,10,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,10,0,2,27,1,1,0,0,9,0,97,0,
+0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,
+86,97,108,0,59,120,121,0,0,18,97,0,0,18,117,0,59,120,121,0,0,0,0,1,90,95,0,0,10,0,2,27,1,1,0,0,10,
+0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,
+101,116,86,97,108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,0,10,0,2,21,1,1,
+0,0,9,0,97,0,0,1,1,0,0,10,0,117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,
+95,114,101,116,86,97,108,0,59,120,121,0,0,18,97,0,0,18,117,0,59,120,121,0,0,0,0,1,90,95,0,0,10,0,2,
+21,1,1,0,0,10,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,108,121,
+0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,18,98,0,0,0,0,1,90,95,0,
+0,10,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,10,0,117,0,0,0,1,3,2,90,95,0,0,10,0,1,105,110,118,85,0,0,0,
+4,102,108,111,97,116,95,114,99,112,0,18,105,110,118,85,0,59,120,0,0,18,117,0,59,120,0,0,0,4,102,
+108,111,97,116,95,114,99,112,0,18,105,110,118,85,0,59,121,0,0,18,117,0,59,121,0,0,0,4,118,101,99,
+52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,97,0,0,
+18,105,110,118,85,0,59,120,121,0,0,0,0,1,90,95,0,0,10,0,2,22,1,1,0,0,10,0,118,0,0,1,1,0,0,9,0,98,0,
+0,0,1,3,2,90,95,0,0,9,0,1,105,110,118,66,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,105,110,118,
+66,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,18,105,110,118,66,0,0,0,0,1,90,95,0,0,11,0,2,26,1,1,0,
+0,9,0,97,0,0,1,1,0,0,11,0,117,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,122,0,0,18,97,0,0,18,117,0,59,120,121,122,0,0,0,0,1,90,95,0,0,11,0,2,26,1,1,0,0,
+11,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,
+0,59,120,121,122,0,0,18,118,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,2,27,1,1,0,0,9,0,
+97,0,0,1,1,0,0,11,0,117,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,
+116,86,97,108,0,59,120,121,122,0,0,18,97,0,0,18,117,0,59,120,121,122,0,0,0,0,1,90,95,0,0,11,0,2,27,
+1,1,0,0,11,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,
+95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,59,120,121,122,0,0,18,98,0,0,0,0,1,90,95,
+0,0,11,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,11,0,117,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,
+112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,97,0,0,18,117,0,59,120,121,
+122,0,0,0,0,1,90,95,0,0,11,0,2,21,1,1,0,0,11,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,
+109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,59,
+120,121,122,0,0,18,98,0,0,0,0,1,90,95,0,0,11,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,11,0,117,0,0,0,1,3,
+2,90,95,0,0,11,0,1,105,110,118,85,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,105,110,118,85,0,
+59,120,0,0,18,117,0,59,120,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,105,110,118,85,0,59,121,0,
+0,18,117,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,105,110,118,85,0,59,122,0,0,18,117,
+0,59,122,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,
+0,59,120,121,122,0,0,18,97,0,0,18,105,110,118,85,0,59,120,121,122,0,0,0,0,1,90,95,0,0,11,0,2,22,1,
+1,0,0,11,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,105,110,118,66,0,0,0,4,102,108,111,
+97,116,95,114,99,112,0,18,105,110,118,66,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,105,
+112,108,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,118,0,59,120,121,122,0,0,18,
+105,110,118,66,0,0,0,0,1,90,95,0,0,12,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,12,0,117,0,0,0,1,4,118,101,
+99,52,95,97,100,100,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,117,0,0,0,0,1,90,95,0,0,12,0,
+2,26,1,1,0,0,12,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,97,100,100,0,18,95,95,114,101,
+116,86,97,108,0,0,18,118,0,0,18,98,0,0,0,0,1,90,95,0,0,12,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,12,0,
+117,0,0,0,1,4,118,101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,
+18,97,0,0,18,117,0,0,0,0,1,90,95,0,0,12,0,2,27,1,1,0,0,12,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,
+101,99,52,95,115,117,98,116,114,97,99,116,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,98,0,
+0,0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,12,0,117,0,0,0,1,4,118,101,99,52,95,109,117,
+108,116,105,112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,117,0,0,0,0,1,90,95,0,0,
+12,0,2,21,1,1,0,0,12,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,109,117,108,116,105,112,
+108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,98,0,0,0,0,1,90,95,0,0,12,0,2,22,1,1,0,
+0,9,0,97,0,0,1,1,0,0,12,0,117,0,0,0,1,3,2,90,95,0,0,12,0,1,105,110,118,85,0,0,0,4,102,108,111,97,
+116,95,114,99,112,0,18,105,110,118,85,0,59,120,0,0,18,117,0,59,120,0,0,0,4,102,108,111,97,116,95,
+114,99,112,0,18,105,110,118,85,0,59,121,0,0,18,117,0,59,121,0,0,0,4,102,108,111,97,116,95,114,99,
+112,0,18,105,110,118,85,0,59,122,0,0,18,117,0,59,122,0,0,0,4,102,108,111,97,116,95,114,99,112,0,18,
+105,110,118,85,0,59,119,0,0,18,117,0,59,119,0,0,0,4,118,101,99,52,95,109,117,108,116,105,112,108,
+121,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,105,110,118,85,0,0,0,0,1,90,95,0,0,12,0,2,22,
+1,1,0,0,12,0,118,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,9,0,1,105,110,118,66,0,0,0,4,102,108,111,
+97,116,95,114,99,112,0,18,105,110,118,66,0,0,18,98,0,0,0,4,118,101,99,52,95,109,117,108,116,105,
+112,108,121,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,18,105,110,118,66,0,0,0,0,1,90,95,0,0,
+6,0,2,26,1,1,0,0,5,0,97,0,0,1,1,0,0,6,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,
+101,99,50,0,0,18,97,0,0,0,18,117,0,46,20,0,0,1,90,95,0,0,6,0,2,26,1,1,0,0,6,0,118,0,0,1,1,0,0,5,0,
+98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,50,0,0,18,98,0,0,0,46,20,
+0,0,1,90,95,0,0,6,0,2,27,1,1,0,0,5,0,97,0,0,1,1,0,0,6,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,58,105,118,101,99,50,0,0,18,97,0,0,0,18,117,0,47,20,0,0,1,90,95,0,0,6,0,2,27,1,1,0,0,6,0,118,
+0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,50,0,0,18,
+98,0,0,0,47,20,0,0,1,90,95,0,0,6,0,2,21,1,1,0,0,5,0,97,0,0,1,1,0,0,6,0,117,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,58,105,118,101,99,50,0,0,18,97,0,0,0,18,117,0,48,20,0,0,1,90,95,0,0,6,0,2,21,1,
+1,0,0,6,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,
+101,99,50,0,0,18,98,0,0,0,48,20,0,0,1,90,95,0,0,6,0,2,22,1,1,0,0,5,0,97,0,0,1,1,0,0,6,0,117,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,99,50,0,0,18,97,0,0,0,18,117,0,49,20,0,0,1,90,
+95,0,0,6,0,2,22,1,1,0,0,6,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,
+118,0,58,105,118,101,99,50,0,0,18,98,0,0,0,49,20,0,0,1,90,95,0,0,7,0,2,26,1,1,0,0,5,0,97,0,0,1,1,0,
+0,7,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,99,51,0,0,18,97,0,0,0,18,117,0,
+46,20,0,0,1,90,95,0,0,7,0,2,26,1,1,0,0,7,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,18,118,0,58,105,118,101,99,51,0,0,18,98,0,0,0,46,20,0,0,1,90,95,0,0,7,0,2,27,1,1,0,0,5,
+0,97,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,99,51,0,0,18,97,
+0,0,0,18,117,0,47,20,0,0,1,90,95,0,0,7,0,2,27,1,1,0,0,7,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,51,0,0,18,98,0,0,0,47,20,0,0,1,90,95,0,0,7,0,
+2,21,1,1,0,0,5,0,97,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,
+99,51,0,0,18,97,0,0,0,18,117,0,48,20,0,0,1,90,95,0,0,7,0,2,21,1,1,0,0,7,0,118,0,0,1,1,0,0,5,0,98,0,
+0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,51,0,0,18,98,0,0,0,48,20,0,0,1,
+90,95,0,0,7,0,2,22,1,1,0,0,5,0,97,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+58,105,118,101,99,51,0,0,18,97,0,0,0,18,117,0,49,20,0,0,1,90,95,0,0,7,0,2,22,1,1,0,0,7,0,118,0,0,1,
+1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,51,0,0,18,98,0,
+0,0,49,20,0,0,1,90,95,0,0,8,0,2,26,1,1,0,0,5,0,97,0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,58,105,118,101,99,52,0,0,18,97,0,0,0,18,117,0,46,20,0,0,1,90,95,0,0,8,0,2,26,1,1,0,
+0,8,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,
+52,0,0,18,98,0,0,0,46,20,0,0,1,90,95,0,0,8,0,2,27,1,1,0,0,5,0,97,0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,58,105,118,101,99,52,0,0,18,97,0,0,0,18,117,0,47,20,0,0,1,90,95,0,0,
+8,0,2,27,1,1,0,0,8,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,58,
+105,118,101,99,52,0,0,18,98,0,0,0,47,20,0,0,1,90,95,0,0,8,0,2,21,1,1,0,0,5,0,97,0,0,1,1,0,0,8,0,
+117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,99,52,0,0,18,97,0,0,0,18,117,0,48,20,
+0,0,1,90,95,0,0,8,0,2,21,1,1,0,0,8,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,18,118,0,58,105,118,101,99,52,0,0,18,98,0,0,0,48,20,0,0,1,90,95,0,0,8,0,2,22,1,1,0,0,5,0,97,
+0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,105,118,101,99,52,0,0,18,97,0,0,
+0,18,117,0,49,20,0,0,1,90,95,0,0,8,0,2,22,1,1,0,0,8,0,118,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,18,118,0,58,105,118,101,99,52,0,0,18,98,0,0,0,49,20,0,0,1,90,95,0,0,5,0,2,
+27,1,1,0,0,5,0,97,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,95,95,114,101,116,86,97,
+108,0,59,120,0,0,18,97,0,0,0,0,1,90,95,0,0,6,0,2,27,1,1,0,0,6,0,118,0,0,0,1,4,118,101,99,52,95,110,
+101,103,97,116,101,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,0,0,1,90,95,0,0,7,0,2,27,1,1,0,
+0,7,0,118,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,95,95,114,101,116,86,97,108,0,0,
+18,118,0,0,0,0,1,90,95,0,0,8,0,2,27,1,1,0,0,8,0,118,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,
+101,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,0,0,1,90,95,0,0,9,0,2,27,1,1,0,0,9,0,97,0,0,0,
+1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,95,95,114,101,116,86,97,108,0,59,120,0,0,18,97,0,
+0,0,0,1,90,95,0,0,10,0,2,27,1,1,0,0,10,0,118,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,
+18,95,95,114,101,116,86,97,108,0,59,120,121,0,0,18,118,0,59,120,121,0,0,0,0,1,90,95,0,0,11,0,2,27,
+1,1,0,0,11,0,118,0,0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,95,95,114,101,116,86,97,
+108,0,59,120,121,122,0,0,18,118,0,59,120,121,122,0,0,0,0,1,90,95,0,0,12,0,2,27,1,1,0,0,12,0,118,0,
+0,0,1,4,118,101,99,52,95,110,101,103,97,116,101,0,18,95,95,114,101,116,86,97,108,0,0,18,118,0,0,0,
+0,1,90,95,0,0,13,0,2,27,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,
+18,109,0,16,8,48,0,57,54,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,
+57,54,20,0,0,1,90,95,0,0,14,0,2,27,1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,
+8,48,0,57,18,109,0,16,8,48,0,57,54,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,
+16,10,49,0,57,54,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,54,
+20,0,0,1,90,95,0,0,15,0,2,27,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,
+57,18,109,0,16,8,48,0,57,54,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,
+49,0,57,54,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,54,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,54,20,0,0,1,90,95,0,0,9,0,0,
+100,111,116,0,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,97,0,
+18,98,0,48,20,0,0,1,90,95,0,0,9,0,0,100,111,116,0,1,1,0,0,10,0,97,0,0,1,1,0,0,10,0,98,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,18,97,0,59,120,0,18,98,0,59,120,0,48,18,97,0,59,121,0,18,98,0,59,121,
+0,48,46,20,0,0,1,90,95,0,0,9,0,0,100,111,116,0,1,1,0,0,11,0,97,0,0,1,1,0,0,11,0,98,0,0,0,1,4,118,
+101,99,51,95,100,111,116,0,18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,
+9,0,0,100,111,116,0,1,1,0,0,12,0,97,0,0,1,1,0,0,12,0,98,0,0,0,1,4,118,101,99,52,95,100,111,116,0,
+18,95,95,114,101,116,86,97,108,0,0,18,97,0,0,18,98,0,0,0,0,1,90,95,0,0,5,0,2,1,1,0,2,0,5,0,97,0,0,
+1,1,0,0,5,0,98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,46,20,0,8,18,97,0,0,0,1,90,95,0,0,5,0,2,2,1,0,2,0,
+5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,47,20,0,8,18,97,0,0,0,1,90,95,0,0,5,0,
+2,3,1,0,2,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,48,20,0,8,18,97,0,0,0,1,90,
+95,0,0,5,0,2,4,1,0,2,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,49,20,0,8,18,97,
+0,0,0,1,90,95,0,0,6,0,2,1,1,0,2,0,6,0,118,0,0,1,1,0,0,6,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,
+46,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,2,1,0,2,0,6,0,118,0,0,1,1,0,0,6,0,117,0,0,0,1,9,18,118,0,
+18,118,0,18,117,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,3,1,0,2,0,6,0,118,0,0,1,1,0,0,6,0,117,0,
+0,0,1,9,18,118,0,18,118,0,18,117,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,4,1,0,2,0,6,0,118,0,0,
+1,1,0,0,6,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,7,0,2,1,1,
+0,2,0,7,0,118,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,46,20,0,8,18,118,0,0,0,1,90,
+95,0,0,7,0,2,2,1,0,2,0,7,0,118,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,47,20,0,8,
+18,118,0,0,0,1,90,95,0,0,7,0,2,3,1,0,2,0,7,0,118,0,0,1,1,0,0,7,0,117,0,0,0,1,9,18,118,0,18,118,0,
+18,117,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,7,0,2,4,1,0,2,0,7,0,118,0,0,1,1,0,0,7,0,117,0,0,0,1,9,
+18,118,0,18,118,0,18,117,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,8,0,2,1,1,0,2,0,8,0,118,0,0,1,1,0,0,
+8,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,8,0,2,2,1,0,2,0,8,
+0,118,0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,
+8,0,2,3,1,0,2,0,8,0,118,0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,48,20,0,8,18,118,
+0,0,0,1,90,95,0,0,8,0,2,4,1,0,2,0,8,0,118,0,0,1,1,0,0,8,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,
+49,20,0,8,18,118,0,0,0,1,90,95,0,0,9,0,2,1,1,0,2,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,97,0,18,
+97,0,18,98,0,46,20,0,8,18,97,0,0,0,1,90,95,0,0,9,0,2,2,1,0,2,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,9,
+18,97,0,18,97,0,18,98,0,47,20,0,8,18,97,0,0,0,1,90,95,0,0,9,0,2,3,1,0,2,0,9,0,97,0,0,1,1,0,0,9,0,
+98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,48,20,0,8,18,97,0,0,0,1,90,95,0,0,9,0,2,4,1,0,2,0,9,0,97,0,0,
+1,1,0,0,9,0,98,0,0,0,1,9,18,97,0,18,97,0,18,98,0,49,20,0,8,18,97,0,0,0,1,90,95,0,0,10,0,2,1,1,0,2,
+0,10,0,118,0,0,1,1,0,0,10,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,46,20,0,8,18,118,0,0,0,1,90,
+95,0,0,10,0,2,2,1,0,2,0,10,0,118,0,0,1,1,0,0,10,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,47,20,0,
+8,18,118,0,0,0,1,90,95,0,0,10,0,2,3,1,0,2,0,10,0,118,0,0,1,1,0,0,10,0,117,0,0,0,1,9,18,118,0,18,
+118,0,18,117,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,10,0,2,4,1,0,2,0,10,0,118,0,0,1,1,0,0,10,0,117,0,
+0,0,1,9,18,118,0,18,118,0,18,117,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,11,0,2,1,1,0,2,0,11,0,118,0,
+0,1,1,0,0,11,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,11,0,2,
+2,1,0,2,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,47,20,0,8,18,118,0,0,
+0,1,90,95,0,0,11,0,2,3,1,0,2,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,
+48,20,0,8,18,118,0,0,0,1,90,95,0,0,11,0,2,4,1,0,2,0,11,0,118,0,0,1,1,0,0,11,0,117,0,0,0,1,9,18,118,
+0,18,118,0,18,117,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,12,0,2,1,1,0,2,0,12,0,118,0,0,1,1,0,0,12,0,
+117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,12,0,2,2,1,0,2,0,12,0,
+118,0,0,1,1,0,0,12,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,
+12,0,2,3,1,0,2,0,12,0,118,0,0,1,1,0,0,12,0,117,0,0,0,1,9,18,118,0,18,118,0,18,117,0,48,20,0,8,18,
+118,0,0,0,1,90,95,0,0,12,0,2,4,1,0,2,0,12,0,118,0,0,1,1,0,0,12,0,117,0,0,0,1,9,18,118,0,18,118,0,
+18,117,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,1,1,0,2,0,6,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,
+18,118,0,18,118,0,58,105,118,101,99,50,0,0,18,97,0,0,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,2,
+1,0,2,0,6,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,50,0,0,18,97,0,0,
+0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,3,1,0,2,0,6,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,
+18,118,0,58,105,118,101,99,50,0,0,18,97,0,0,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,6,0,2,4,1,0,2,0,6,
+0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,50,0,0,18,97,0,0,0,49,20,0,
+8,18,118,0,0,0,1,90,95,0,0,7,0,2,1,1,0,2,0,7,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,
+58,105,118,101,99,51,0,0,18,97,0,0,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,7,0,2,2,1,0,2,0,7,0,118,0,
+0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,51,0,0,18,97,0,0,0,47,20,0,8,18,118,
+0,0,0,1,90,95,0,0,7,0,2,3,1,0,2,0,7,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,
+118,101,99,51,0,0,18,97,0,0,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,8,0,2,4,1,0,2,0,7,0,118,0,0,1,1,0,
+0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,51,0,0,18,97,0,0,0,49,20,0,8,18,118,0,0,0,1,
+90,95,0,0,8,0,2,1,1,0,2,0,8,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,
+52,0,0,18,97,0,0,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,8,0,2,2,1,0,2,0,8,0,118,0,0,1,1,0,0,5,0,97,0,
+0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,52,0,0,18,97,0,0,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,
+8,0,2,3,1,0,2,0,8,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,52,0,0,18,
+97,0,0,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,8,0,2,4,1,0,2,0,8,0,118,0,0,1,1,0,0,5,0,97,0,0,0,1,9,
+18,118,0,18,118,0,58,105,118,101,99,52,0,0,18,97,0,0,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,10,0,2,1,
+1,0,2,0,10,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,50,0,0,18,97,0,0,0,
+46,20,0,8,18,118,0,0,0,1,90,95,0,0,10,0,2,2,1,0,2,0,10,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,
+18,118,0,58,118,101,99,50,0,0,18,97,0,0,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,10,0,2,3,1,0,2,0,10,0,
+118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,50,0,0,18,97,0,0,0,48,20,0,8,18,
+118,0,0,0,1,90,95,0,0,10,0,2,4,1,0,2,0,10,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,
+118,101,99,50,0,0,18,97,0,0,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,11,0,2,1,1,0,2,0,11,0,118,0,0,1,1,
+0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,51,0,0,18,97,0,0,0,46,20,0,8,18,118,0,0,0,1,
+90,95,0,0,11,0,2,2,1,0,2,0,11,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,
+51,0,0,18,97,0,0,0,47,20,0,8,18,118,0,0,0,1,90,95,0,0,11,0,2,3,1,0,2,0,11,0,118,0,0,1,1,0,0,9,0,97,
+0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,51,0,0,18,97,0,0,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,11,
+0,2,4,1,0,2,0,11,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,51,0,0,18,97,0,
+0,0,49,20,0,8,18,118,0,0,0,1,90,95,0,0,12,0,2,1,1,0,2,0,12,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,
+118,0,18,118,0,58,118,101,99,52,0,0,18,97,0,0,0,46,20,0,8,18,118,0,0,0,1,90,95,0,0,12,0,2,2,1,0,2,
+0,12,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,52,0,0,18,97,0,0,0,47,20,0,
+8,18,118,0,0,0,1,90,95,0,0,12,0,2,3,1,0,2,0,12,0,118,0,0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,
+0,58,118,101,99,52,0,0,18,97,0,0,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,12,0,2,4,1,0,2,0,12,0,118,0,
+0,1,1,0,0,9,0,97,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,52,0,0,18,97,0,0,0,49,20,0,8,18,118,0,0,
+0,1,90,95,0,0,13,0,2,26,1,1,0,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,20,0,0,1,90,95,0,0,13,0,2,
+27,1,1,0,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,
+18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,20,0,0,1,90,95,0,0,13,0,2,21,1,1,0,0,13,0,109,
+0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,
+18,110,0,16,8,48,0,57,59,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,8,48,0,57,59,121,121,0,48,
+46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,8,48,0,57,18,110,0,16,10,49,0,
+57,59,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,59,121,121,0,48,46,20,0,0,1,90,95,
+0,0,13,0,2,22,1,1,0,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,
+8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,20,0,0,1,90,95,0,0,14,0,2,26,1,1,0,
+0,14,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,
+16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,
+0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,20,0,0,1,90,95,0,0,14,0,2,27,1,1,0,0,14,0,109,0,0,1,
+1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,
+110,0,16,8,48,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,
+18,110,0,16,10,49,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,
+0,57,18,110,0,16,10,50,0,57,47,20,0,0,1,90,95,0,0,14,0,2,21,1,1,0,0,14,0,109,0,0,1,1,0,0,14,0,110,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,
+57,59,120,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,8,48,0,57,59,121,121,121,0,48,46,18,109,
+0,16,10,50,0,57,18,110,0,16,8,48,0,57,59,122,122,122,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,
+0,16,10,49,0,57,18,109,0,16,8,48,0,57,18,110,0,16,10,49,0,57,59,120,120,120,0,48,18,109,0,16,10,49,
+0,57,18,110,0,16,10,49,0,57,59,121,121,121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,10,49,0,57,
+59,122,122,122,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,8,48,0,57,
+18,110,0,16,10,50,0,57,59,120,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,10,50,0,57,59,121,
+121,121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,59,122,122,122,0,48,46,20,0,0,1,90,
+95,0,0,14,0,2,22,1,1,0,0,14,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,
+0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,20,0,0,1,90,95,0,0,15,0,2,26,
+1,1,0,0,15,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,
+18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,
+0,57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,51,0,57,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,46,20,0,0,1,90,95,0,0,15,0,2,27,1,1,0,0,
+15,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,
+8,48,0,57,18,110,0,16,8,48,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,
+16,10,49,0,57,18,110,0,16,10,49,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,
+57,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,47,20,0,0,1,90,95,0,0,15,0,2,21,1,1,0,0,15,0,109,
+0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,
+18,110,0,16,8,48,0,57,59,120,120,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,8,48,0,57,59,121,
+121,121,121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,8,48,0,57,59,122,122,122,122,0,48,46,18,109,
+0,16,10,51,0,57,18,110,0,16,8,48,0,57,59,119,119,119,119,0,48,46,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,49,0,57,18,109,0,16,8,48,0,57,18,110,0,16,10,49,0,57,59,120,120,120,120,0,48,18,109,0,
+16,10,49,0,57,18,110,0,16,10,49,0,57,59,121,121,121,121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,
+10,49,0,57,59,122,122,122,122,0,48,46,18,109,0,16,10,51,0,57,18,110,0,16,10,49,0,57,59,119,119,119,
+119,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,8,48,0,57,18,110,0,
+16,10,50,0,57,59,120,120,120,120,0,48,18,109,0,16,10,49,0,57,18,110,0,16,10,50,0,57,59,121,121,121,
+121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,59,122,122,122,122,0,48,46,18,109,0,16,
+10,51,0,57,18,110,0,16,10,50,0,57,59,119,119,119,119,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,
+0,16,10,51,0,57,18,109,0,16,8,48,0,57,18,110,0,16,10,51,0,57,59,120,120,120,120,0,48,18,109,0,16,
+10,49,0,57,18,110,0,16,10,51,0,57,59,121,121,121,121,0,48,46,18,109,0,16,10,50,0,57,18,110,0,16,10,
+51,0,57,59,122,122,122,122,0,48,46,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,59,119,119,119,
+119,0,48,46,20,0,0,1,90,95,0,0,15,0,2,22,1,1,0,0,15,0,109,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,
+114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,20,0,9,18,95,
+95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,20,
+0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,
+49,20,0,0,1,90,95,0,0,13,0,2,26,1,1,0,0,9,0,97,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,
+86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,46,20,0,0,1,90,95,0,0,13,0,2,26,1,1,0,0,13,0,109,0,0,
+1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,
+0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,46,20,0,
+0,1,90,95,0,0,13,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,
+49,0,57,18,97,0,18,110,0,16,10,49,0,57,47,20,0,0,1,90,95,0,0,13,0,2,27,1,1,0,0,13,0,109,0,0,1,1,0,
+0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,47,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,47,20,0,0,1,
+90,95,0,0,13,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,0,1,90,95,0,0,13,0,2,21,1,1,0,0,13,0,109,0,0,1,1,0,0,9,0,
+98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,0,1,90,95,0,
+0,13,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,
+0,57,18,97,0,18,110,0,16,8,48,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,
+0,18,110,0,16,10,49,0,57,49,20,0,0,1,90,95,0,0,13,0,2,22,1,1,0,0,13,0,109,0,0,1,1,0,0,9,0,98,0,0,0,
+1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,49,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,49,20,0,0,1,90,95,0,0,14,0,2,
+26,1,1,0,0,9,0,97,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+97,0,18,110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,
+0,16,10,49,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,
+0,57,46,20,0,0,1,90,95,0,0,14,0,2,26,1,1,0,0,14,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,46,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,46,20,0,0,1,90,95,0,0,14,0,2,27,1,1,0,0,9,0,97,0,0,1,
+1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,
+57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,47,20,0,
+9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,47,20,0,0,1,90,95,
+0,0,14,0,2,27,1,1,0,0,14,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,
+48,0,57,18,109,0,16,8,48,0,57,18,98,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,
+109,0,16,10,49,0,57,18,98,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,
+10,50,0,57,18,98,0,47,20,0,0,1,90,95,0,0,14,0,2,21,1,1,0,0,9,0,97,0,0,1,1,0,0,14,0,110,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,48,20,0,0,1,90,95,0,0,14,0,2,21,1,1,0,0,14,0,
+109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,
+57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,
+48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,20,0,0,
+1,90,95,0,0,14,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,97,0,18,110,0,16,10,49,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,
+18,110,0,16,10,50,0,57,49,20,0,0,1,90,95,0,0,14,0,2,22,1,1,0,0,14,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,49,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,49,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,49,20,0,0,1,90,95,0,0,15,0,2,26,1,1,0,
+0,9,0,97,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,
+110,0,16,8,48,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,
+49,0,57,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,46,
+20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0,16,10,51,0,57,46,20,0,0,1,
+90,95,0,0,15,0,2,26,1,1,0,0,15,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,
+57,18,109,0,16,10,49,0,57,18,98,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,
+0,16,10,50,0,57,18,98,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,
+0,57,18,98,0,46,20,0,0,1,90,95,0,0,15,0,2,27,1,1,0,0,9,0,97,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,47,20,0,9,18,95,95,114,101,
+116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,47,20,0,9,18,95,95,114,101,116,86,97,
+108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,
+10,51,0,57,18,97,0,18,110,0,16,10,51,0,57,47,20,0,0,1,90,95,0,0,15,0,2,27,1,1,0,0,15,0,109,0,0,1,1,
+0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,
+47,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,47,20,0,9,
+18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,47,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,98,0,47,20,0,0,1,90,95,0,0,15,0,2,
+21,1,1,0,0,9,0,97,0,0,1,1,0,0,15,0,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,
+97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,
+0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,
+0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0,16,10,51,0,57,48,20,
+0,0,1,90,95,0,0,15,0,2,21,1,1,0,0,15,0,109,0,0,1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,
+49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,
+109,0,16,10,50,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,
+10,51,0,57,18,98,0,48,20,0,0,1,90,95,0,0,15,0,2,22,1,1,0,0,9,0,97,0,0,1,1,0,0,15,0,110,0,0,0,1,9,
+18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,49,20,0,9,18,95,95,114,
+101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,49,20,0,9,18,95,95,114,101,116,86,
+97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,49,20,0,9,18,95,95,114,101,116,86,97,108,0,
+16,10,51,0,57,18,97,0,18,110,0,16,10,51,0,57,49,20,0,0,1,90,95,0,0,15,0,2,22,1,1,0,0,15,0,109,0,0,
+1,1,0,0,9,0,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,
+0,49,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,49,20,0,
+9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,49,20,0,9,18,95,95,
+114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,98,0,49,20,0,0,1,90,95,0,0,10,0,2,
+21,1,1,0,0,13,0,109,0,0,1,1,0,0,10,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,16,8,
+48,0,57,18,118,0,59,120,120,0,48,18,109,0,16,10,49,0,57,18,118,0,59,121,121,0,48,46,20,0,0,1,90,95,
+0,0,10,0,2,21,1,1,0,0,10,0,118,0,0,1,1,0,0,13,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,
+120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,
+108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,90,95,0,0,11,0,2,
+21,1,1,0,0,14,0,109,0,0,1,1,0,0,11,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,16,8,
+48,0,57,18,118,0,59,120,120,120,0,48,18,109,0,16,10,49,0,57,18,118,0,59,121,121,121,0,48,46,18,109,
+0,16,10,50,0,57,18,118,0,59,122,122,122,0,48,46,20,0,0,1,90,95,0,0,11,0,2,21,1,1,0,0,11,0,118,0,0,
+1,1,0,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,
+18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,0,18,
+118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100,111,116,
+0,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,90,95,0,0,12,0,2,21,1,1,0,0,15,0,109,0,0,1,1,0,
+0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,16,8,48,0,57,18,118,0,59,120,120,
+120,120,0,48,18,109,0,16,10,49,0,57,18,118,0,59,121,121,121,121,0,48,46,18,109,0,16,10,50,0,57,18,
+118,0,59,122,122,122,122,0,48,46,18,109,0,16,10,51,0,57,18,118,0,59,119,119,119,119,0,48,46,20,0,0,
+1,90,95,0,0,12,0,2,21,1,1,0,0,12,0,118,0,0,1,1,0,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,59,120,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,
+86,97,108,0,59,121,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,114,
+101,116,86,97,108,0,59,122,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,9,18,95,
+95,114,101,116,86,97,108,0,59,119,0,58,100,111,116,0,0,18,118,0,0,18,109,0,16,10,51,0,57,0,0,20,0,
+0,1,90,95,0,0,13,0,2,1,1,0,2,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,
+18,110,0,16,10,49,0,57,46,20,0,8,18,109,0,0,0,1,90,95,0,0,13,0,2,2,1,0,2,0,13,0,109,0,0,1,1,0,0,13,
+0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,20,0,9,18,109,
+0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,20,0,8,18,109,0,0,0,1,90,95,0,0,
+13,0,2,3,1,0,2,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,8,18,
+109,0,0,0,1,90,95,0,0,13,0,2,4,1,0,2,0,13,0,109,0,0,1,1,0,0,13,0,110,0,0,0,1,9,18,109,0,16,8,48,0,
+57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,
+0,57,18,110,0,16,10,49,0,57,49,20,0,8,18,109,0,0,0,1,90,95,0,0,14,0,2,1,1,0,2,0,14,0,109,0,0,1,1,0,
+0,14,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,
+18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,20,0,9,18,109,0,16,10,50,0,
+57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,20,0,8,18,109,0,0,0,1,90,95,0,0,14,0,2,2,1,0,2,
+0,14,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,
+8,48,0,57,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,20,0,9,
+18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,20,0,8,18,109,0,0,0,1,90,
+95,0,0,14,0,2,3,1,0,2,0,14,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,
+8,18,109,0,0,0,1,90,95,0,0,14,0,2,4,1,0,2,0,14,0,109,0,0,1,1,0,0,14,0,110,0,0,0,1,9,18,109,0,16,8,
+48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,
+10,49,0,57,18,110,0,16,10,49,0,57,49,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,110,0,
+16,10,50,0,57,49,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,1,1,0,2,0,15,0,109,0,0,1,1,0,0,15,0,110,0,
+0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,20,0,9,18,109,0,16,10,
+49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,
+10,50,0,57,18,110,0,16,10,50,0,57,46,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,110,0,
+16,10,51,0,57,46,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,2,1,0,2,0,15,0,109,0,0,1,1,0,0,15,0,110,0,
+0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,20,0,9,18,109,0,16,10,
+49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,
+10,50,0,57,18,110,0,16,10,50,0,57,47,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,110,0,
+16,10,51,0,57,47,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,3,1,0,2,0,15,0,109,0,0,1,1,0,0,15,0,110,0,
+0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,4,1,0,2,0,15,0,109,0,
+0,1,1,0,0,15,0,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,
+20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,20,0,9,18,109,0,16,
+10,50,0,57,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,20,0,9,18,109,0,16,10,51,0,57,18,109,0,
+16,10,51,0,57,18,110,0,16,10,51,0,57,49,20,0,8,18,109,0,0,0,1,90,95,0,0,13,0,2,1,1,0,2,0,13,0,109,
+0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,10,0,1,118,0,2,58,118,101,99,50,0,0,18,97,0,0,0,0,0,9,18,
+109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,
+49,0,57,18,118,0,46,20,0,8,18,109,0,0,0,1,90,95,0,0,13,0,2,2,1,0,2,0,13,0,109,0,0,1,1,0,0,9,0,97,0,
+0,0,1,3,2,90,95,0,0,10,0,1,118,0,2,58,118,101,99,50,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,
+109,0,16,8,48,0,57,18,118,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,47,20,
+0,8,18,109,0,0,0,1,90,95,0,0,13,0,2,3,1,0,2,0,13,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,10,
+0,1,118,0,2,58,118,101,99,50,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,
+118,0,48,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,48,20,0,8,18,109,0,0,0,1,90,
+95,0,0,13,0,2,4,1,0,2,0,13,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,10,0,1,118,0,2,58,118,
+101,99,50,0,0,17,49,0,48,0,0,18,97,0,49,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,
+118,0,48,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,48,20,0,8,18,109,0,0,0,1,90,
+95,0,0,14,0,2,1,1,0,2,0,14,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,11,0,1,118,0,2,58,118,
+101,99,51,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,46,20,0,9,18,
+109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,
+10,50,0,57,18,118,0,46,20,0,8,18,109,0,0,0,1,90,95,0,0,14,0,2,2,1,0,2,0,14,0,109,0,0,1,1,0,0,9,0,
+97,0,0,0,1,3,2,90,95,0,0,11,0,1,118,0,2,58,118,101,99,51,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,
+57,18,109,0,16,8,48,0,57,18,118,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,
+47,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,118,0,47,20,0,8,18,109,0,0,0,1,90,95,0,
+0,14,0,2,3,1,0,2,0,14,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,11,0,1,118,0,2,58,118,101,99,
+51,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,48,20,0,9,18,109,0,
+16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,48,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,
+57,18,118,0,48,20,0,8,18,109,0,0,0,1,90,95,0,0,14,0,2,4,1,0,2,0,14,0,109,0,0,1,1,0,0,9,0,97,0,0,0,
+1,3,2,90,95,0,0,11,0,1,118,0,2,58,118,101,99,51,0,0,17,49,0,48,0,0,18,97,0,49,0,0,0,0,9,18,109,0,
+16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,48,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,
+57,18,118,0,48,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,118,0,48,20,0,8,18,109,0,0,
+0,1,90,95,0,0,15,0,2,1,1,0,2,0,15,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,12,0,1,118,0,2,58,
+118,101,99,52,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,46,20,0,9,
+18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,
+16,10,50,0,57,18,118,0,46,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,118,0,46,20,0,8,
+18,109,0,0,0,1,90,95,0,0,15,0,2,2,1,0,2,0,15,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,95,0,0,12,0,1,
+118,0,2,58,118,101,99,52,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,
+0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,47,20,0,9,18,109,0,16,10,50,0,
+57,18,109,0,16,10,50,0,57,18,118,0,47,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,118,
+0,47,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,3,1,0,2,0,15,0,109,0,0,1,1,0,0,9,0,97,0,0,0,1,3,2,90,
+95,0,0,12,0,1,118,0,2,58,118,101,99,52,0,0,18,97,0,0,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,
+48,0,57,18,118,0,48,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,118,0,48,20,0,9,18,109,
+0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,118,0,48,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,
+0,57,18,118,0,48,20,0,8,18,109,0,0,0,1,90,95,0,0,15,0,2,4,1,0,2,0,15,0,109,0,0,1,1,0,0,9,0,97,0,0,
+0,1,3,2,90,95,0,0,12,0,1,118,0,2,58,118,101,99,52,0,0,17,49,0,48,0,0,18,97,0,49,0,0,0,0,9,18,109,0,
+16,8,48,0,57,18,109,0,16,8,48,0,57,18,118,0,48,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,
+57,18,118,0,48,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,118,0,48,20,0,9,18,109,0,16,
+10,51,0,57,18,109,0,16,10,51,0,57,18,118,0,48,20,0,8,18,109,0,0,0,1,90,95,0,0,10,0,2,3,1,0,2,0,10,
+0,118,0,0,1,1,0,0,13,0,109,0,0,0,1,9,18,118,0,18,118,0,18,109,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,
+11,0,2,3,1,0,2,0,11,0,118,0,0,1,1,0,0,14,0,109,0,0,0,1,9,18,118,0,18,118,0,18,109,0,48,20,0,8,18,
+118,0,0,0,1,90,95,0,0,12,0,2,3,1,0,2,0,12,0,118,0,0,1,1,0,0,15,0,109,0,0,0,1,9,18,118,0,18,118,0,
+18,109,0,48,20,0,8,18,118,0,0,0,1,90,95,0,0,5,0,2,25,1,0,2,0,5,0,97,0,0,0,1,9,18,97,0,18,97,0,16,
+10,49,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,20,0,0,1,90,95,0,0,6,0,2,25,1,0,2,0,6,0,
+118,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,50,0,0,16,10,49,0,0,0,47,20,0,9,18,95,95,114,101,
+116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,7,0,2,25,1,0,2,0,7,0,118,0,0,0,1,9,18,118,0,18,118,0,
+58,105,118,101,99,51,0,0,16,10,49,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,
+1,90,95,0,0,8,0,2,25,1,0,2,0,8,0,118,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,52,0,0,16,10,49,
+0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,9,0,2,25,1,0,2,0,9,0,
+97,0,0,0,1,9,18,97,0,18,97,0,17,49,0,48,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,20,
+0,0,1,90,95,0,0,10,0,2,25,1,0,2,0,10,0,118,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,50,0,0,17,49,
+0,48,0,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,11,0,2,25,1,0,
+2,0,11,0,118,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,95,
+95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,12,0,2,25,1,0,2,0,12,0,118,0,0,0,1,9,18,118,
+0,18,118,0,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,
+118,0,20,0,0,1,90,95,0,0,13,0,2,25,1,0,2,0,13,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,
+48,0,57,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,
+0,57,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,109,0,
+20,0,0,1,90,95,0,0,14,0,2,25,1,0,2,0,14,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,
+57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,
+58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,
+118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,
+90,95,0,0,15,0,2,25,1,0,2,0,15,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,
+101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,
+101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,118,
+101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,58,118,
+101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,
+95,0,0,5,0,2,24,1,0,2,0,5,0,97,0,0,0,1,9,18,97,0,18,97,0,16,10,49,0,46,20,0,9,18,95,95,114,101,116,
+86,97,108,0,18,97,0,20,0,0,1,90,95,0,0,6,0,2,24,1,0,2,0,6,0,118,0,0,0,1,9,18,118,0,18,118,0,58,105,
+118,101,99,50,0,0,16,10,49,0,0,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,
+95,0,0,7,0,2,24,1,0,2,0,7,0,118,0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,51,0,0,16,10,49,0,0,
+0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,8,0,2,24,1,0,2,0,8,0,118,
+0,0,0,1,9,18,118,0,18,118,0,58,105,118,101,99,52,0,0,16,10,49,0,0,0,46,20,0,9,18,95,95,114,101,116,
+86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,9,0,2,24,1,0,2,0,9,0,97,0,0,0,1,9,18,97,0,18,97,0,17,49,0,
+48,0,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,97,0,20,0,0,1,90,95,0,0,10,0,2,24,1,0,2,0,10,
+0,118,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,95,95,114,
+101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,11,0,2,24,1,0,2,0,11,0,118,0,0,0,1,9,18,118,0,18,
+118,0,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,
+20,0,0,1,90,95,0,0,12,0,2,24,1,0,2,0,12,0,118,0,0,0,1,9,18,118,0,18,118,0,58,118,101,99,52,0,0,17,
+49,0,48,0,0,0,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,0,1,90,95,0,0,13,0,2,24,1,
+0,2,0,13,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,50,0,0,17,49,0,
+48,0,0,0,0,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,50,0,0,17,49,0,48,
+0,0,0,0,46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,14,0,2,24,1,0,2,0,
+14,0,109,0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,
+0,0,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,
+0,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,
+46,20,0,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,15,0,2,24,1,0,2,0,15,0,109,
+0,0,0,1,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,
+20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,
+0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,
+9,18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,9,
+18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,90,95,0,0,5,0,0,95,95,112,111,115,116,68,101,99,
+114,0,1,0,2,0,5,0,97,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,97,0,20,0,9,18,97,0,18,97,0,16,
+10,49,0,47,20,0,0,1,90,95,0,0,6,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,6,0,118,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,105,118,101,99,50,0,0,16,
+10,49,0,0,0,47,20,0,0,1,90,95,0,0,7,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,7,0,118,0,0,
+0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,105,118,101,99,51,0,0,
+16,10,49,0,0,0,47,20,0,0,1,90,95,0,0,8,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,8,0,118,0,
+0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,105,118,101,99,52,0,
+0,16,10,49,0,0,0,47,20,0,0,1,90,95,0,0,9,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,9,0,97,
+0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,97,0,20,0,9,18,97,0,18,97,0,17,49,0,48,0,0,47,20,0,0,
+1,90,95,0,0,10,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,10,0,118,0,0,0,1,9,18,95,95,114,
+101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,47,
+20,0,0,1,90,95,0,0,11,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,11,0,118,0,0,0,1,9,18,95,
+95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,118,101,99,51,0,0,17,49,0,48,0,0,0,
+0,47,20,0,0,1,90,95,0,0,12,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,12,0,118,0,0,0,1,9,18,
+95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,0,18,118,0,58,118,101,99,52,0,0,17,49,0,48,0,
+0,0,0,47,20,0,0,1,90,95,0,0,13,0,0,95,95,112,111,115,116,68,101,99,114,0,1,0,2,0,13,0,109,0,0,0,1,
+9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,
+118,101,99,50,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,
+118,101,99,50,0,0,17,49,0,48,0,0,0,0,47,20,0,0,1,90,95,0,0,14,0,0,95,95,112,111,115,116,68,101,99,
+114,0,1,0,2,0,14,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,9,18,109,0,16,8,48,
+0,57,18,109,0,16,8,48,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,49,0,
+57,18,109,0,16,10,49,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,9,18,109,0,16,10,50,0,57,
+18,109,0,16,10,50,0,57,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,47,20,0,0,1,90,95,0,0,15,0,0,95,95,
+112,111,115,116,68,101,99,114,0,1,0,2,0,15,0,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,
+0,20,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,
+0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,
+9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,9,
+18,109,0,16,10,51,0,57,18,109,0,16,10,51,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,47,20,0,0,1,
+90,95,0,0,9,0,0,95,95,112,111,115,116,73,110,99,114,0,1,0,2,0,9,0,97,0,0,0,1,9,18,95,95,114,101,
+116,86,97,108,0,18,97,0,20,0,9,18,97,0,18,97,0,16,10,49,0,46,20,0,0,1,90,95,0,0,10,0,0,95,95,112,
+111,115,116,73,110,99,114,0,1,0,2,0,10,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,
+20,0,9,18,118,0,18,118,0,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,46,20,0,0,1,90,95,0,0,11,0,0,95,
+95,112,111,115,116,73,110,99,114,0,1,0,2,0,11,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,
+118,0,20,0,9,18,118,0,18,118,0,58,118,101,99,51,0,0,17,49,0,48,0,0,0,0,46,20,0,0,1,90,95,0,0,12,0,
+0,95,95,112,111,115,116,73,110,99,114,0,1,0,2,0,12,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,
+0,18,118,0,20,0,9,18,118,0,18,118,0,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,0,1,90,95,0,0,
+5,0,0,95,95,112,111,115,116,73,110,99,114,0,1,0,2,0,5,0,97,0,0,0,1,9,18,95,95,114,101,116,86,97,
+108,0,18,97,0,20,0,9,18,97,0,18,97,0,16,10,49,0,46,20,0,0,1,90,95,0,0,6,0,0,95,95,112,111,115,116,
+73,110,99,114,0,1,0,2,0,6,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,118,
+0,18,118,0,58,105,118,101,99,50,0,0,16,10,49,0,0,0,46,20,0,0,1,90,95,0,0,7,0,0,95,95,112,111,115,
+116,73,110,99,114,0,1,0,2,0,7,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,18,
+118,0,18,118,0,58,105,118,101,99,51,0,0,16,10,49,0,0,0,46,20,0,0,1,90,95,0,0,8,0,0,95,95,112,111,
+115,116,73,110,99,114,0,1,0,2,0,8,0,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,118,0,20,0,9,
+18,118,0,18,118,0,58,105,118,101,99,51,0,0,16,10,49,0,0,0,46,20,0,0,1,90,95,0,0,13,0,0,95,95,112,
+111,115,116,73,110,99,114,0,1,0,2,0,13,0,109,0,0,0,1,3,2,90,95,0,0,13,0,1,110,0,2,18,109,0,0,0,9,
+18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,
+109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,50,0,0,17,49,0,48,0,0,0,0,46,20,0,8,18,
+110,0,0,0,1,90,95,0,0,14,0,0,95,95,112,111,115,116,73,110,99,114,0,1,0,2,0,14,0,109,0,0,0,1,3,2,90,
+95,0,0,14,0,1,110,0,2,18,109,0,0,0,9,18,109,0,16,8,48,0,57,18,109,0,16,8,48,0,57,58,118,101,99,51,
+0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,16,10,49,0,57,58,118,101,99,51,0,
+0,17,49,0,48,0,0,0,0,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,10,50,0,57,58,118,101,99,51,0,0,
+17,49,0,48,0,0,0,0,46,20,0,8,18,110,0,0,0,1,90,95,0,0,15,0,0,95,95,112,111,115,116,73,110,99,114,0,
+1,0,2,0,15,0,109,0,0,0,1,3,2,90,95,0,0,15,0,1,110,0,2,18,109,0,0,0,9,18,109,0,16,8,48,0,57,18,109,
+0,16,8,48,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,109,0,16,10,49,0,57,18,109,0,
+16,10,49,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,109,0,16,10,50,0,57,18,109,0,16,
+10,50,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,9,18,109,0,16,10,51,0,57,18,109,0,16,10,
+51,0,57,58,118,101,99,52,0,0,17,49,0,48,0,0,0,0,46,20,0,8,18,110,0,0,0,1,90,95,0,0,1,0,2,15,1,1,0,
+0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,4,118,101,99,52,95,115,103,116,0,18,95,95,114,101,116,86,97,
+108,0,59,120,0,0,18,98,0,0,18,97,0,0,0,0,1,90,95,0,0,1,0,2,15,1,1,0,0,5,0,97,0,0,1,1,0,0,5,0,98,0,
+0,0,1,8,58,102,108,111,97,116,0,0,18,97,0,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,40,0,0,1,90,95,
+0,0,1,0,2,16,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,1,0,1,99,0,0,0,4,102,108,111,
+97,116,95,108,101,115,115,0,18,99,0,0,18,98,0,0,18,97,0,0,0,8,18,99,0,0,0,1,90,95,0,0,1,0,2,16,1,1,
+0,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,8,58,102,108,111,97,116,0,0,18,97,0,0,0,58,102,108,111,97,
+116,0,0,18,98,0,0,0,41,0,0,1,90,95,0,0,1,0,2,18,1,1,0,0,9,0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,
+95,0,0,1,0,1,103,0,0,1,1,101,0,0,0,4,102,108,111,97,116,95,108,101,115,115,0,18,103,0,0,18,98,0,0,
+18,97,0,0,0,4,102,108,111,97,116,95,101,113,117,97,108,0,18,101,0,0,18,97,0,0,18,98,0,0,0,8,18,103,
+0,18,101,0,32,0,0,1,90,95,0,0,1,0,2,18,1,1,0,0,5,0,97,0,0,1,1,0,0,5,0,98,0,0,0,1,8,58,102,108,111,
+97,116,0,0,18,97,0,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,43,0,0,1,90,95,0,0,1,0,2,17,1,1,0,0,9,
+0,97,0,0,1,1,0,0,9,0,98,0,0,0,1,3,2,90,95,0,0,1,0,1,103,0,0,1,1,101,0,0,0,4,102,108,111,97,116,95,
+108,101,115,115,0,18,103,0,0,18,97,0,0,18,98,0,0,0,4,102,108,111,97,116,95,101,113,117,97,108,0,18,
+101,0,0,18,97,0,0,18,98,0,0,0,8,18,103,0,18,101,0,32,0,0,1,90,95,0,0,1,0,2,17,1,1,0,0,5,0,97,0,0,1,
+1,0,0,5,0,98,0,0,0,1,8,58,102,108,111,97,116,0,0,18,97,0,0,0,58,102,108,111,97,116,0,0,18,98,0,0,0,
+42,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,9,0,102,0,0,0,1,4,102,108,111,
+97,116,95,112,114,105,110,116,0,18,102,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,
+1,1,0,0,5,0,105,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,105,0,0,0,0,1,90,95,0,0,0,0,0,
+112,114,105,110,116,77,69,83,65,0,1,1,0,0,1,0,98,0,0,0,1,4,98,111,111,108,95,112,114,105,110,116,0,
+18,98,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,10,0,118,0,0,0,1,9,58,
+112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,
+0,18,118,0,59,121,0,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,11,0,118,0,
+0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,
+69,83,65,0,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,122,0,0,
+0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,12,0,118,0,0,0,1,9,58,112,114,
+105,110,116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,
+118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,122,0,0,0,0,9,58,112,114,
+105,110,116,77,69,83,65,0,0,18,118,0,59,119,0,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,
+83,65,0,1,1,0,0,6,0,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,
+58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,121,0,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,
+116,77,69,83,65,0,1,1,0,0,7,0,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,120,
+0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,
+77,69,83,65,0,0,18,118,0,59,122,0,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,
+0,0,8,0,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,
+105,110,116,77,69,83,65,0,0,18,118,0,59,121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,
+118,0,59,122,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,119,0,0,0,0,0,1,90,95,0,
+0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,2,0,118,0,0,0,1,9,58,112,114,105,110,116,77,69,
+83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,121,0,0,0,0,
+0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,3,0,118,0,0,0,1,9,58,112,114,105,110,
+116,77,69,83,65,0,0,18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,
+121,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,122,0,0,0,0,0,1,90,95,0,0,0,0,0,
+112,114,105,110,116,77,69,83,65,0,1,1,0,0,4,0,118,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,
+18,118,0,59,120,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,118,0,59,121,0,0,0,0,9,58,112,
+114,105,110,116,77,69,83,65,0,0,18,118,0,59,122,0,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,
+18,118,0,59,119,0,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,13,0,109,0,0,
+0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,109,0,16,8,48,0,57,0,0,0,9,58,112,114,105,110,116,
+77,69,83,65,0,0,18,109,0,16,10,49,0,57,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,
+1,1,0,0,14,0,109,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,109,0,16,8,48,0,57,0,0,0,9,58,
+112,114,105,110,116,77,69,83,65,0,0,18,109,0,16,10,49,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,
+65,0,0,18,109,0,16,10,50,0,57,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,
+15,0,109,0,0,0,1,9,58,112,114,105,110,116,77,69,83,65,0,0,18,109,0,16,8,48,0,57,0,0,0,9,58,112,114,
+105,110,116,77,69,83,65,0,0,18,109,0,16,10,49,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,
+18,109,0,16,10,50,0,57,0,0,0,9,58,112,114,105,110,116,77,69,83,65,0,0,18,109,0,16,10,51,0,57,0,0,0,
+0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,16,0,101,0,0,0,1,4,105,110,116,95,
+112,114,105,110,116,0,18,101,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,
+17,0,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0,0,1,90,95,0,0,0,0,0,112,114,
+105,110,116,77,69,83,65,0,1,1,0,0,18,0,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,
+0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,0,19,0,101,0,0,0,1,4,105,110,116,
+95,112,114,105,110,116,0,18,101,0,0,0,0,1,90,95,0,0,0,0,0,112,114,105,110,116,77,69,83,65,0,1,1,0,
+0,20,0,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,0,0,0,1,90,95,0,0,0,0,0,112,114,
+105,110,116,77,69,83,65,0,1,1,0,0,21,0,101,0,0,0,1,4,105,110,116,95,112,114,105,110,116,0,18,101,0,
+0,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin.gc b/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin.gc
new file mode 100644
index 000000000..2e063e641
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin.gc
@@ -0,0 +1,235 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+__fixed_input vec4 gl_FragCoord;
+__fixed_input bool gl_FrontFacing;
+__fixed_output vec4 gl_FragColor;
+__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers];
+__fixed_output float gl_FragDepth;
+
+varying vec4 gl_Color;
+varying vec4 gl_SecondaryColor;
+varying vec4 gl_TexCoord[gl_MaxTextureCoords];
+varying float gl_FogFragCoord;
+
+
+
+//// 8.7 Texture Lookup Functions (with bias)
+
+vec4 texture1D(const sampler1D sampler, const float coord, const float bias)
+{
+ vec4 coord4;
+ coord4.x = coord;
+ coord4.w = bias;
+ __asm vec4_tex_1d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias)
+{
+ // do projection here (there's no vec4_texbp1d instruction)
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.y;
+ pcoord.w = bias;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias)
+{
+ // do projection here (there's no vec4_texbp1d instruction)
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.z;
+ pcoord.w = bias;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias)
+{
+ vec4 coord4;
+ coord4.xy = coord.xy;
+ coord4.w = bias;
+ __asm vec4_tex_2d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias)
+{
+ // do projection here (there's no vec4_texbp2d instruction)
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.z;
+ pcoord.w = bias;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias)
+{
+ // do projection here (there's no vec4_texbp2d instruction)
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.w;
+ pcoord.w = bias;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias)
+{
+ vec4 coord4;
+ coord4.xyz = coord.xyz;
+ coord4.w = bias;
+ __asm vec4_tex_3d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias)
+{
+ // do projection here (there's no vec4_texbp3d instruction)
+ vec4 pcoord;
+ pcoord.xyz = coord.xyz / coord.w;
+ pcoord.w = bias;
+ __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
+}
+
+
+
+
+vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = bias;
+ __asm vec4_tex_cube __retVal, sampler, coord4;
+}
+
+
+
+vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = bias;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias)
+{
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.w;
+ pcoord.z = coord.z;
+ pcoord.w = bias;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
+}
+
+vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = bias;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias)
+{
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.w;
+ pcoord.z = coord.z;
+ pcoord.w = bias;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
+}
+
+
+
+//
+// 8.8 Fragment Processing Functions
+//
+
+float dFdx(const float p)
+{
+ __asm vec4_ddx __retVal.x, p.xxxx;
+}
+
+vec2 dFdx(const vec2 p)
+{
+ __asm vec4_ddx __retVal.xy, p.xyyy;
+}
+
+vec3 dFdx(const vec3 p)
+{
+ __asm vec4_ddx __retVal.xyz, p.xyzz;
+}
+
+vec4 dFdx(const vec4 p)
+{
+ __asm vec4_ddx __retVal, p;
+}
+
+float dFdy(const float p)
+{
+ __asm vec4_ddy __retVal.x, p.xxxx;
+}
+
+vec2 dFdy(const vec2 p)
+{
+ __asm vec4_ddy __retVal.xy, p.xyyy;
+}
+
+vec3 dFdy(const vec3 p)
+{
+ __asm vec4_ddy __retVal.xyz, p.xyzz;
+}
+
+vec4 dFdy(const vec4 p)
+{
+ __asm vec4_ddy __retVal, p;
+}
+
+float fwidth (const float p)
+{
+ // XXX hand-write with __asm
+ return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec2 fwidth(const vec2 p)
+{
+ // XXX hand-write with __asm
+ return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec3 fwidth(const vec3 p)
+{
+ // XXX hand-write with __asm
+ return abs(dFdx(p)) + abs(dFdy(p));
+}
+
+vec4 fwidth(const vec4 p)
+{
+ // XXX hand-write with __asm
+ return abs(dFdx(p)) + abs(dFdy(p));
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h b/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h
new file mode 100644
index 000000000..c5a1cce2a
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_fragment_builtin_gc.h
@@ -0,0 +1,110 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_fragment_builtin.gc */
+
+5,2,2,90,95,6,0,12,0,1,103,108,95,70,114,97,103,67,111,111,114,100,0,0,0,2,2,90,95,6,0,1,0,1,103,
+108,95,70,114,111,110,116,70,97,99,105,110,103,0,0,0,2,2,90,95,5,0,12,0,1,103,108,95,70,114,97,103,
+67,111,108,111,114,0,0,0,2,2,90,95,5,0,12,0,1,103,108,95,70,114,97,103,68,97,116,97,0,3,18,103,108,
+95,77,97,120,68,114,97,119,66,117,102,102,101,114,115,0,0,0,2,2,90,95,5,0,9,0,1,103,108,95,70,114,
+97,103,68,101,112,116,104,0,0,0,2,2,90,95,3,0,12,0,1,103,108,95,67,111,108,111,114,0,0,0,2,2,90,95,
+3,0,12,0,1,103,108,95,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,90,95,3,0,12,0,
+1,103,108,95,84,101,120,67,111,111,114,100,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,
+67,111,111,114,100,115,0,0,0,2,2,90,95,3,0,9,0,1,103,108,95,70,111,103,70,114,97,103,67,111,111,
+114,100,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,0,1,1,0,0,16,0,115,97,109,112,
+108,101,114,0,0,1,1,0,0,9,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,
+12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,0,18,99,111,111,114,100,0,
+20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,
+95,49,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,
+18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,
+106,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,
+98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,
+100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,
+99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,
+98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,
+111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,0,1,1,0,0,
+16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,
+0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,
+18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,
+100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,
+18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,0,1,1,0,0,17,0,115,97,109,112,108,101,114,
+0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,
+111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,0,18,99,111,111,114,100,0,59,120,
+121,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,
+0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,
+111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,122,0,
+49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,
+120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,
+0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,114,
+111,106,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,
+9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,
+114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,
+0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,
+50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,
+112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,0,1,1,0,0,18,0,
+115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,
+1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,
+18,99,111,111,114,100,0,59,120,121,122,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,
+115,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,
+101,120,116,117,114,101,51,68,80,114,111,106,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,
+12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,
+114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,
+122,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,
+115,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,
+108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,
+101,120,116,117,114,101,67,117,98,101,0,1,1,0,0,19,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,
+99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,
+52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,
+111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,99,117,98,101,
+0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,
+0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,
+0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,
+111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,
+0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,
+49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,
+109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,
+49,68,80,114,111,106,0,1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,
+0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,119,0,49,
+20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,
+111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,
+97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,0,1,1,0,
+0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,
+115,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,
+121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,98,105,97,115,0,20,
+0,4,118,101,99,52,95,116,101,120,95,50,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,
+95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,114,111,106,0,1,1,0,0,21,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,98,105,97,115,0,0,0,1,3,2,90,95,0,0,12,0,1,
+112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+120,121,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,
+111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,98,105,97,115,0,20,0,4,
+118,101,99,52,95,116,101,120,95,50,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,
+101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,9,0,0,100,70,100,120,0,1,1,0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,
+101,116,86,97,108,0,59,120,0,0,18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,
+120,0,1,1,0,0,10,0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,
+59,120,121,0,0,18,112,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,120,0,1,1,0,0,11,
+0,112,0,0,0,1,4,118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,
+18,112,0,59,120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,100,70,100,120,0,1,1,0,0,12,0,112,0,0,0,1,4,
+118,101,99,52,95,100,100,120,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,
+100,70,100,121,0,1,1,0,0,9,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,
+97,108,0,59,120,0,0,18,112,0,59,120,120,120,120,0,0,0,0,1,90,95,0,0,10,0,0,100,70,100,121,0,1,1,0,
+0,10,0,112,0,0,0,1,4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,0,
+0,18,112,0,59,120,121,121,121,0,0,0,0,1,90,95,0,0,11,0,0,100,70,100,121,0,1,1,0,0,11,0,112,0,0,0,1,
+4,118,101,99,52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,59,120,121,122,0,0,18,112,0,59,
+120,121,122,122,0,0,0,0,1,90,95,0,0,12,0,0,100,70,100,121,0,1,1,0,0,12,0,112,0,0,0,1,4,118,101,99,
+52,95,100,100,121,0,18,95,95,114,101,116,86,97,108,0,0,18,112,0,0,0,0,1,90,95,0,0,9,0,0,102,119,
+105,100,116,104,0,1,1,0,0,9,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,
+0,58,97,98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,10,0,0,102,119,105,
+100,116,104,0,1,1,0,0,10,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,
+58,97,98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,11,0,0,102,119,105,100,
+116,104,0,1,1,0,0,11,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,
+98,115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,1,90,95,0,0,12,0,0,102,119,105,100,116,
+104,0,1,1,0,0,12,0,112,0,0,0,1,8,58,97,98,115,0,0,58,100,70,100,120,0,0,18,112,0,0,0,0,0,58,97,98,
+115,0,0,58,100,70,100,121,0,0,18,112,0,0,0,0,0,46,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_directives.syn b/mesalib/src/mesa/shader/slang/library/slang_pp_directives.syn
new file mode 100644
index 000000000..b51d168cc
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_directives.syn
@@ -0,0 +1,405 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 2006 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.
+ */
+
+/**
+ * \file slang_pp_directives.syn
+ * slang preprocessor directives parser
+ * \author Michal Krol
+ */
+
+.syntax source;
+
+/*
+ * This syntax script preprocesses a GLSL shader.
+ * It is assumed, that the #version directive has been parsed. Separate pass for parsing
+ * version gives better control on behavior depending on the version number given.
+ *
+ * The output is a source string with comments and directives removed. White spaces and comments
+ * are replaced with on or more spaces. All new-lines are preserved and converted to Linux format.
+ * Directives are escaped with a null character. The end of the source string is marked by
+ * two consecutive null characters. The consumer is responsible for executing the escaped
+ * directives, removing dead portions of code and expanding macros.
+ */
+
+.emtcode ESCAPE_TOKEN 0
+
+/*
+ * The TOKEN_* symbols follow the ESCAPE_TOKEN.
+ *
+ * NOTE:
+ * There is no TOKEN_IFDEF and neither is TOKEN_IFNDEF. They are handled with TOKEN_IF and
+ * operator defined.
+ * The "#ifdef SYMBOL" is replaced with "#if defined SYMBOL"
+ * The "#ifndef SYMBOL" is replaced with "#if !defined SYMBOL"
+ */
+.emtcode TOKEN_END 0
+.emtcode TOKEN_DEFINE 1
+.emtcode TOKEN_UNDEF 2
+.emtcode TOKEN_IF 3
+.emtcode TOKEN_ELSE 4
+.emtcode TOKEN_ELIF 5
+.emtcode TOKEN_ENDIF 6
+.emtcode TOKEN_ERROR 7
+.emtcode TOKEN_PRAGMA 8
+.emtcode TOKEN_EXTENSION 9
+.emtcode TOKEN_LINE 10
+
+/*
+ * The PARAM_* symbols follow the TOKEN_DEFINE.
+ */
+.emtcode PARAM_END 0
+.emtcode PARAM_PARAMETER 1
+
+/*
+ * The BEHAVIOR_* symbols follow the TOKEN_EXTENSION.
+ */
+.emtcode BEHAVIOR_REQUIRE 1
+.emtcode BEHAVIOR_ENABLE 2
+.emtcode BEHAVIOR_WARN 3
+.emtcode BEHAVIOR_DISABLE 4
+
+/*
+ * The PRAGMA_* symbols follow TOKEN_PRAGMA
+ */
+.emtcode PRAGMA_NO_PARAM 0
+.emtcode PRAGMA_PARAM 1
+
+source
+ optional_directive .and .loop source_element .and '\0' .emit ESCAPE_TOKEN .emit TOKEN_END;
+
+source_element
+ c_style_comment_block .or cpp_style_comment_block .or new_line_directive .or source_token;
+
+c_style_comment_block
+ '/' .and '*' .and c_style_comment_rest .and .true .emit ' ';
+
+c_style_comment_rest
+ .loop c_style_comment_body .and c_style_comment_end;
+
+c_style_comment_body
+ c_style_comment_char_nostar .or c_style_comment_char_star_noslashstar;
+
+c_style_comment_char_nostar
+ new_line .or '\x2B'-'\xFF' .or '\x01'-'\x29';
+
+c_style_comment_char_star_noslashstar
+ '*' .and c_style_comment_char_star_noslashstar_1;
+c_style_comment_char_star_noslashstar_1
+ c_style_comment_char_noslashstar .or c_style_comment_char_star_noslashstar;
+
+c_style_comment_char_noslashstar
+ new_line .or '\x30'-'\xFF' .or '\x01'-'\x29' .or '\x2B'-'\x2E';
+
+c_style_comment_end
+ '*' .and .loop c_style_comment_char_star .and '/';
+
+c_style_comment_char_star
+ '*';
+
+cpp_style_comment_block
+ '/' .and '/' .and cpp_style_comment_block_1;
+cpp_style_comment_block_1
+ cpp_style_comment_block_2 .or cpp_style_comment_block_3;
+cpp_style_comment_block_2
+ .loop cpp_style_comment_char .and new_line_directive;
+cpp_style_comment_block_3
+ .loop cpp_style_comment_char;
+
+cpp_style_comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+new_line_directive
+ new_line .and optional_directive;
+
+new_line
+ generic_new_line .emit '\n';
+
+generic_new_line
+ carriage_return_line_feed .or line_feed_carriage_return .or '\n' .or '\r';
+
+carriage_return_line_feed
+ '\r' .and '\n';
+
+line_feed_carriage_return
+ '\n' .and '\r';
+
+optional_directive
+ directive .emit ESCAPE_TOKEN .or .true;
+
+directive
+ dir_define .emit TOKEN_DEFINE .or
+ dir_undef .emit TOKEN_UNDEF .or
+ dir_if .emit TOKEN_IF .or
+ dir_ifdef .emit TOKEN_IF .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' .emit 'd'
+ .emit ' ' .or
+ dir_ifndef .emit TOKEN_IF .emit '!' .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e'
+ .emit 'd' .emit ' ' .or
+ dir_else .emit TOKEN_ELSE .or
+ dir_elif .emit TOKEN_ELIF .or
+ dir_endif .emit TOKEN_ENDIF .or
+ dir_ext .emit TOKEN_EXTENSION .or
+ dir_pragma .emit TOKEN_PRAGMA .or
+ dir_line .emit TOKEN_LINE;
+
+dir_define
+ optional_space .and '#' .and optional_space .and "define" .and symbol .and opt_parameters .and
+ definition;
+
+dir_undef
+ optional_space .and '#' .and optional_space .and "undef" .and symbol;
+
+dir_if
+ optional_space .and '#' .and optional_space .and "if" .and expression;
+
+dir_ifdef
+ optional_space .and '#' .and optional_space .and "ifdef" .and symbol;
+
+dir_ifndef
+ optional_space .and '#' .and optional_space .and "ifndef" .and symbol;
+
+dir_else
+ optional_space .and '#' .and optional_space .and "else";
+
+dir_elif
+ optional_space .and '#' .and optional_space .and "elif" .and expression;
+
+dir_endif
+ optional_space .and '#' .and optional_space .and "endif";
+
+dir_ext
+ optional_space .and '#' .and optional_space .and "extension" .and space .and extension_name .and
+ optional_space .and ':' .and optional_space .and extension_behavior;
+
+dir_line
+ optional_space .and '#' .and optional_space .and "line" .and expression;
+
+dir_pragma
+ optional_space .and '#' .and optional_space .and "pragma" .and symbol .and opt_pragma_param;
+
+
+opt_pragma_param
+ pragma_param .or .true .emit PRAGMA_NO_PARAM;
+
+pragma_param
+ optional_space .and '(' .emit PRAGMA_PARAM .and optional_space .and symbol_no_space .and optional_space .and ')';
+
+symbol_no_space
+ symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0';
+
+symbol
+ space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0';
+
+opt_parameters
+ parameters .or .true .emit PARAM_END;
+
+parameters
+ '(' .and parameters_1 .and optional_space .and ')' .emit PARAM_END;
+parameters_1
+ parameters_2 .or .true;
+parameters_2
+ parameter .emit PARAM_PARAMETER .and .loop parameters_3;
+parameters_3
+ optional_space .and ',' .and parameter .emit PARAM_PARAMETER;
+
+parameter
+ optional_space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and
+ .true .emit '\0';
+
+definition
+ .loop definition_character .emit * .and .true .emit '\0';
+
+definition_character
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+expression
+ expression_element .and .loop expression_element .and .true .emit '\0';
+
+expression_element
+ expression_character .emit *;
+
+expression_character
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+extension_name
+ symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0';
+
+extension_behavior
+ "require" .emit BEHAVIOR_REQUIRE .or
+ "enable" .emit BEHAVIOR_ENABLE .or
+ "warn" .emit BEHAVIOR_WARN .or
+ "disable" .emit BEHAVIOR_DISABLE;
+
+optional_space
+ .loop single_space;
+
+space
+ single_space .and .loop single_space;
+
+single_space
+ ' ' .or '\t';
+
+source_token
+ space .emit ' ' .or complex_token .or source_token_1;
+source_token_1
+ simple_token .emit ' ' .and .true .emit ' ';
+
+/*
+ * All possible tokens.
+ */
+
+complex_token
+ identifier .or number;
+
+simple_token
+ increment .or decrement .or lequal .or gequal .or equal .or nequal .or and .or xor .or or .or
+ addto .or subtractfrom .or multiplyto .or divideto .or other;
+
+identifier
+ identifier_char1 .emit * .and .loop identifier_char2 .emit *;
+identifier_char1
+ 'a'-'z' .or 'A'-'Z' .or '_';
+identifier_char2
+ 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';
+
+number
+ float .or integer;
+
+digit_oct
+ '0'-'7';
+
+digit_dec
+ '0'-'9';
+
+digit_hex
+ '0'-'9' .or 'A'-'F' .or 'a'-'f';
+
+float
+ float_1 .or float_2;
+float_1
+ float_fractional_constant .and float_optional_exponent_part;
+float_2
+ float_digit_sequence .and float_exponent_part;
+
+float_fractional_constant
+ float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;
+float_fractional_constant_1
+ float_digit_sequence .and '.' .emit '.' .and float_digit_sequence;
+float_fractional_constant_2
+ float_digit_sequence .and '.' .emit '.';
+float_fractional_constant_3
+ '.' .emit '.' .and float_digit_sequence;
+
+float_optional_exponent_part
+ float_exponent_part .or .true;
+
+float_digit_sequence
+ digit_dec .emit * .and .loop digit_dec .emit *;
+
+float_exponent_part
+ float_exponent_part_1 .or float_exponent_part_2;
+float_exponent_part_1
+ 'e' .emit 'e' .and float_optional_sign .and float_digit_sequence;
+float_exponent_part_2
+ 'E' .emit 'E' .and float_optional_sign .and float_digit_sequence;
+
+float_optional_sign
+ '+' .emit '+' .or '-' .emit '-' .or .true;
+
+integer
+ integer_hex .or integer_oct .or integer_dec;
+
+integer_hex
+ '0' .emit '0' .and integer_hex_1 .emit * .and digit_hex .emit * .and
+ .loop digit_hex .emit *;
+integer_hex_1
+ 'x' .or 'X';
+
+integer_oct
+ '0' .emit '0' .and .loop digit_oct .emit *;
+
+integer_dec
+ digit_dec .emit * .and .loop digit_dec .emit *;
+
+increment
+ '+' .emit * .and '+' .emit *;
+
+decrement
+ '-' .emit * .and '-' .emit *;
+
+lequal
+ '<' .emit * .and '=' .emit *;
+
+gequal
+ '>' .emit * .and '=' .emit *;
+
+equal
+ '=' .emit * .and '=' .emit *;
+
+nequal
+ '!' .emit * .and '=' .emit *;
+
+and
+ '&' .emit * .and '&' .emit *;
+
+xor
+ '^' .emit * .and '^' .emit *;
+
+or
+ '|' .emit * .and '|' .emit *;
+
+addto
+ '+' .emit * .and '=' .emit *;
+
+subtractfrom
+ '-' .emit * .and '=' .emit *;
+
+multiplyto
+ '*' .emit * .and '=' .emit *;
+
+divideto
+ '/' .emit * .and '=' .emit *;
+
+/*
+ * All characters except '\0' and '#'.
+ */
+other
+ '\x24'-'\xFF' .emit * .or '\x01'-'\x22' .emit *;
+
+symbol_character
+ 'A'-'Z' .or 'a'-'z' .or '_';
+
+symbol_character2
+ 'A'-'Z' .or 'a'-'z' .or '0'-'9' .or '_';
+
+.string string_lexer;
+
+string_lexer
+ lex_first_identifier_character .and .loop lex_next_identifier_character;
+
+lex_first_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '_';
+
+lex_next_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_directives_syn.h b/mesalib/src/mesa/shader/slang/library/slang_pp_directives_syn.h
new file mode 100644
index 000000000..430f8d821
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_directives_syn.h
@@ -0,0 +1,250 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */
+
+".syntax source;\n"
+".emtcode ESCAPE_TOKEN 0\n"
+".emtcode TOKEN_END 0\n"
+".emtcode TOKEN_DEFINE 1\n"
+".emtcode TOKEN_UNDEF 2\n"
+".emtcode TOKEN_IF 3\n"
+".emtcode TOKEN_ELSE 4\n"
+".emtcode TOKEN_ELIF 5\n"
+".emtcode TOKEN_ENDIF 6\n"
+".emtcode TOKEN_ERROR 7\n"
+".emtcode TOKEN_PRAGMA 8\n"
+".emtcode TOKEN_EXTENSION 9\n"
+".emtcode TOKEN_LINE 10\n"
+".emtcode PARAM_END 0\n"
+".emtcode PARAM_PARAMETER 1\n"
+".emtcode BEHAVIOR_REQUIRE 1\n"
+".emtcode BEHAVIOR_ENABLE 2\n"
+".emtcode BEHAVIOR_WARN 3\n"
+".emtcode BEHAVIOR_DISABLE 4\n"
+".emtcode PRAGMA_NO_PARAM 0\n"
+".emtcode PRAGMA_PARAM 1\n"
+"source\n"
+" optional_directive .and .loop source_element .and '\\0' .emit ESCAPE_TOKEN .emit TOKEN_END;\n"
+"source_element\n"
+" c_style_comment_block .or cpp_style_comment_block .or new_line_directive .or source_token;\n"
+"c_style_comment_block\n"
+" '/' .and '*' .and c_style_comment_rest .and .true .emit ' ';\n"
+"c_style_comment_rest\n"
+" .loop c_style_comment_body .and c_style_comment_end;\n"
+"c_style_comment_body\n"
+" c_style_comment_char_nostar .or c_style_comment_char_star_noslashstar;\n"
+"c_style_comment_char_nostar\n"
+" new_line .or '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"c_style_comment_char_star_noslashstar\n"
+" '*' .and c_style_comment_char_star_noslashstar_1;\n"
+"c_style_comment_char_star_noslashstar_1\n"
+" c_style_comment_char_noslashstar .or c_style_comment_char_star_noslashstar;\n"
+"c_style_comment_char_noslashstar\n"
+" new_line .or '\\x30'-'\\xFF' .or '\\x01'-'\\x29' .or '\\x2B'-'\\x2E';\n"
+"c_style_comment_end\n"
+" '*' .and .loop c_style_comment_char_star .and '/';\n"
+"c_style_comment_char_star\n"
+" '*';\n"
+"cpp_style_comment_block\n"
+" '/' .and '/' .and cpp_style_comment_block_1;\n"
+"cpp_style_comment_block_1\n"
+" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n"
+"cpp_style_comment_block_2\n"
+" .loop cpp_style_comment_char .and new_line_directive;\n"
+"cpp_style_comment_block_3\n"
+" .loop cpp_style_comment_char;\n"
+"cpp_style_comment_char\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"new_line_directive\n"
+" new_line .and optional_directive;\n"
+"new_line\n"
+" generic_new_line .emit '\\n';\n"
+"generic_new_line\n"
+" carriage_return_line_feed .or line_feed_carriage_return .or '\\n' .or '\\r';\n"
+"carriage_return_line_feed\n"
+" '\\r' .and '\\n';\n"
+"line_feed_carriage_return\n"
+" '\\n' .and '\\r';\n"
+"optional_directive\n"
+" directive .emit ESCAPE_TOKEN .or .true;\n"
+"directive\n"
+" dir_define .emit TOKEN_DEFINE .or\n"
+" dir_undef .emit TOKEN_UNDEF .or\n"
+" dir_if .emit TOKEN_IF .or\n"
+" dir_ifdef .emit TOKEN_IF .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' .emit 'd'\n"
+" .emit ' ' .or\n"
+" dir_ifndef .emit TOKEN_IF .emit '!' .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e'\n"
+" .emit 'd' .emit ' ' .or\n"
+" dir_else .emit TOKEN_ELSE .or\n"
+" dir_elif .emit TOKEN_ELIF .or\n"
+" dir_endif .emit TOKEN_ENDIF .or\n"
+" dir_ext .emit TOKEN_EXTENSION .or\n"
+" dir_pragma .emit TOKEN_PRAGMA .or\n"
+" dir_line .emit TOKEN_LINE;\n"
+"dir_define\n"
+" optional_space .and '#' .and optional_space .and \"define\" .and symbol .and opt_parameters .and\n"
+" definition;\n"
+"dir_undef\n"
+" optional_space .and '#' .and optional_space .and \"undef\" .and symbol;\n"
+"dir_if\n"
+" optional_space .and '#' .and optional_space .and \"if\" .and expression;\n"
+"dir_ifdef\n"
+" optional_space .and '#' .and optional_space .and \"ifdef\" .and symbol;\n"
+"dir_ifndef\n"
+" optional_space .and '#' .and optional_space .and \"ifndef\" .and symbol;\n"
+"dir_else\n"
+" optional_space .and '#' .and optional_space .and \"else\";\n"
+"dir_elif\n"
+" optional_space .and '#' .and optional_space .and \"elif\" .and expression;\n"
+"dir_endif\n"
+" optional_space .and '#' .and optional_space .and \"endif\";\n"
+"dir_ext\n"
+" optional_space .and '#' .and optional_space .and \"extension\" .and space .and extension_name .and\n"
+" optional_space .and ':' .and optional_space .and extension_behavior;\n"
+"dir_line\n"
+" optional_space .and '#' .and optional_space .and \"line\" .and expression;\n"
+"dir_pragma\n"
+" optional_space .and '#' .and optional_space .and \"pragma\" .and symbol .and opt_pragma_param;\n"
+"opt_pragma_param\n"
+" pragma_param .or .true .emit PRAGMA_NO_PARAM;\n"
+"pragma_param\n"
+" optional_space .and '(' .emit PRAGMA_PARAM .and optional_space .and symbol_no_space .and optional_space .and ')';\n"
+"symbol_no_space\n"
+" symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n"
+"symbol\n"
+" space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n"
+"opt_parameters\n"
+" parameters .or .true .emit PARAM_END;\n"
+"parameters\n"
+" '(' .and parameters_1 .and optional_space .and ')' .emit PARAM_END;\n"
+"parameters_1\n"
+" parameters_2 .or .true;\n"
+"parameters_2\n"
+" parameter .emit PARAM_PARAMETER .and .loop parameters_3;\n"
+"parameters_3\n"
+" optional_space .and ',' .and parameter .emit PARAM_PARAMETER;\n"
+"parameter\n"
+" optional_space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and\n"
+" .true .emit '\\0';\n"
+"definition\n"
+" .loop definition_character .emit * .and .true .emit '\\0';\n"
+"definition_character\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"expression\n"
+" expression_element .and .loop expression_element .and .true .emit '\\0';\n"
+"expression_element\n"
+" expression_character .emit *;\n"
+"expression_character\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"extension_name\n"
+" symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\\0';\n"
+"extension_behavior\n"
+" \"require\" .emit BEHAVIOR_REQUIRE .or\n"
+" \"enable\" .emit BEHAVIOR_ENABLE .or\n"
+" \"warn\" .emit BEHAVIOR_WARN .or\n"
+" \"disable\" .emit BEHAVIOR_DISABLE;\n"
+"optional_space\n"
+" .loop single_space;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" ' ' .or '\\t';\n"
+"source_token\n"
+" space .emit ' ' .or complex_token .or source_token_1;\n"
+"source_token_1\n"
+" simple_token .emit ' ' .and .true .emit ' ';\n"
+"complex_token\n"
+" identifier .or number;\n"
+"simple_token\n"
+" increment .or decrement .or lequal .or gequal .or equal .or nequal .or and .or xor .or or .or\n"
+" addto .or subtractfrom .or multiplyto .or divideto .or other;\n"
+"identifier\n"
+" identifier_char1 .emit * .and .loop identifier_char2 .emit *;\n"
+"identifier_char1\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"identifier_char2\n"
+" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n"
+"number\n"
+" float .or integer;\n"
+"digit_oct\n"
+" '0'-'7';\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"digit_hex\n"
+" '0'-'9' .or 'A'-'F' .or 'a'-'f';\n"
+"float\n"
+" float_1 .or float_2;\n"
+"float_1\n"
+" float_fractional_constant .and float_optional_exponent_part;\n"
+"float_2\n"
+" float_digit_sequence .and float_exponent_part;\n"
+"float_fractional_constant\n"
+" float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;\n"
+"float_fractional_constant_1\n"
+" float_digit_sequence .and '.' .emit '.' .and float_digit_sequence;\n"
+"float_fractional_constant_2\n"
+" float_digit_sequence .and '.' .emit '.';\n"
+"float_fractional_constant_3\n"
+" '.' .emit '.' .and float_digit_sequence;\n"
+"float_optional_exponent_part\n"
+" float_exponent_part .or .true;\n"
+"float_digit_sequence\n"
+" digit_dec .emit * .and .loop digit_dec .emit *;\n"
+"float_exponent_part\n"
+" float_exponent_part_1 .or float_exponent_part_2;\n"
+"float_exponent_part_1\n"
+" 'e' .emit 'e' .and float_optional_sign .and float_digit_sequence;\n"
+"float_exponent_part_2\n"
+" 'E' .emit 'E' .and float_optional_sign .and float_digit_sequence;\n"
+"float_optional_sign\n"
+" '+' .emit '+' .or '-' .emit '-' .or .true;\n"
+"integer\n"
+" integer_hex .or integer_oct .or integer_dec;\n"
+"integer_hex\n"
+" '0' .emit '0' .and integer_hex_1 .emit * .and digit_hex .emit * .and\n"
+" .loop digit_hex .emit *;\n"
+"integer_hex_1\n"
+" 'x' .or 'X';\n"
+"integer_oct\n"
+" '0' .emit '0' .and .loop digit_oct .emit *;\n"
+"integer_dec\n"
+" digit_dec .emit * .and .loop digit_dec .emit *;\n"
+"increment\n"
+" '+' .emit * .and '+' .emit *;\n"
+"decrement\n"
+" '-' .emit * .and '-' .emit *;\n"
+"lequal\n"
+" '<' .emit * .and '=' .emit *;\n"
+"gequal\n"
+" '>' .emit * .and '=' .emit *;\n"
+"equal\n"
+" '=' .emit * .and '=' .emit *;\n"
+"nequal\n"
+" '!' .emit * .and '=' .emit *;\n"
+"and\n"
+" '&' .emit * .and '&' .emit *;\n"
+"xor\n"
+" '^' .emit * .and '^' .emit *;\n"
+"or\n"
+" '|' .emit * .and '|' .emit *;\n"
+"addto\n"
+" '+' .emit * .and '=' .emit *;\n"
+"subtractfrom\n"
+" '-' .emit * .and '=' .emit *;\n"
+"multiplyto\n"
+" '*' .emit * .and '=' .emit *;\n"
+"divideto\n"
+" '/' .emit * .and '=' .emit *;\n"
+"other\n"
+" '\\x24'-'\\xFF' .emit * .or '\\x01'-'\\x22' .emit *;\n"
+"symbol_character\n"
+" 'A'-'Z' .or 'a'-'z' .or '_';\n"
+"symbol_character2\n"
+" 'A'-'Z' .or 'a'-'z' .or '0'-'9' .or '_';\n"
+".string string_lexer;\n"
+"string_lexer\n"
+" lex_first_identifier_character .and .loop lex_next_identifier_character;\n"
+"lex_first_identifier_character\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"lex_next_identifier_character\n"
+" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n"
+""
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_expression.syn b/mesalib/src/mesa/shader/slang/library/slang_pp_expression.syn
new file mode 100644
index 000000000..bfdb220bf
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_expression.syn
@@ -0,0 +1,265 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 2006 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.
+ */
+
+/**
+ * \file slang_pp_expression.syn
+ * slang preprocessor expression parser
+ * \author Michal Krol
+ */
+
+/*
+ * Parses one or two (optional) expressions on literal integer constants. Those expressions come
+ * from #if #elif and #line directives. The preprocessor already parsed those directives and
+ * expanded the expression (expressions). All occurences of the operator "defined" are already
+ * replaced with either "0" or "1" literals.
+ */
+
+.syntax expression;
+
+/*
+ * Those separate individual expressions.
+ * For #if/#elif case it is: EXP_EXPRESSION ... EXP_END
+ * For #line case it may be: EXP_EXPRESSION ... EXP_EXPRESSION ... EXP_END
+ */
+.emtcode EXP_END 0
+.emtcode EXP_EXPRESSION 1
+
+.emtcode OP_END 0
+.emtcode OP_PUSHINT 1
+.emtcode OP_LOGICALOR 2
+.emtcode OP_LOGICALAND 3
+.emtcode OP_OR 4
+.emtcode OP_XOR 5
+.emtcode OP_AND 6
+.emtcode OP_EQUAL 7
+.emtcode OP_NOTEQUAL 8
+.emtcode OP_LESSEQUAL 9
+.emtcode OP_GREATEREQUAL 10
+.emtcode OP_LESS 11
+.emtcode OP_GREATER 12
+.emtcode OP_LEFTSHIFT 13
+.emtcode OP_RIGHTSHIFT 14
+.emtcode OP_ADD 15
+.emtcode OP_SUBTRACT 16
+.emtcode OP_MULTIPLY 17
+.emtcode OP_DIVIDE 18
+.emtcode OP_MODULUS 19
+.emtcode OP_PLUS 20
+.emtcode OP_MINUS 21
+.emtcode OP_NEGATE 22
+.emtcode OP_COMPLEMENT 23
+
+expression
+ first_expression .and optional_second_expression .and optional_space .and '\0' .emit EXP_END;
+
+first_expression
+ optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;
+
+optional_second_expression
+ second_expression .or .true;
+
+second_expression
+ space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;
+
+logical_or_expression
+ logical_and_expression .and .loop logical_or_expression_1;
+logical_or_expression_1
+ barbar .and logical_and_expression .and .true .emit OP_LOGICALOR;
+
+logical_and_expression
+ or_expression .and .loop logical_and_expression_1;
+logical_and_expression_1
+ ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND;
+
+or_expression
+ xor_expression .and .loop or_expression_1;
+or_expression_1
+ bar .and xor_expression .and .true .emit OP_OR;
+
+xor_expression
+ and_expression .and .loop xor_expression_1;
+xor_expression_1
+ caret .and and_expression .and .true .emit OP_XOR;
+
+and_expression
+ equality_expression .and .loop and_expression_1;
+and_expression_1
+ ampersand .and equality_expression .and .true .emit OP_AND;
+
+equality_expression
+ relational_expression .and .loop equality_expression_1;
+equality_expression_1
+ equality_expression_2 .or equality_expression_3;
+equality_expression_2
+ equalsequals .and relational_expression .and .true .emit OP_EQUAL;
+equality_expression_3
+ bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;
+
+relational_expression
+ shift_expression .and .loop relational_expression_1;
+relational_expression_1
+ relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or
+ relational_expression_5;
+relational_expression_2
+ lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;
+relational_expression_3
+ greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;
+relational_expression_4
+ less .and shift_expression .and .true .emit OP_LESS;
+relational_expression_5
+ greater .and shift_expression .and .true .emit OP_GREATER;
+
+shift_expression
+ additive_expression .and .loop shift_expression_1;
+shift_expression_1
+ shift_expression_2 .or shift_expression_3;
+shift_expression_2
+ lessless .and additive_expression .and .true .emit OP_LEFTSHIFT;
+shift_expression_3
+ greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT;
+
+additive_expression
+ multiplicative_expression .and .loop additive_expression_1;
+additive_expression_1
+ additive_expression_2 .or additive_expression_3;
+additive_expression_2
+ plus .and multiplicative_expression .and .true .emit OP_ADD;
+additive_expression_3
+ dash .and multiplicative_expression .and .true .emit OP_SUBTRACT;
+
+multiplicative_expression
+ unary_expression .and .loop multiplicative_expression_1;
+multiplicative_expression_1
+ multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4;
+multiplicative_expression_2
+ star .and unary_expression .and .true .emit OP_MULTIPLY;
+multiplicative_expression_3
+ slash .and unary_expression .and .true .emit OP_DIVIDE;
+multiplicative_expression_4
+ percent .and unary_expression .and .true .emit OP_MODULUS;
+
+unary_expression
+ primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or
+ unary_expression_4;
+unary_expression_1
+ plus .and unary_expression .and .true .emit OP_PLUS;
+unary_expression_2
+ dash .and unary_expression .and .true .emit OP_MINUS;
+unary_expression_3
+ bang .and unary_expression .and .true .emit OP_NEGATE;
+unary_expression_4
+ tilda .and unary_expression .and .true .emit OP_COMPLEMENT;
+
+primary_expression
+ intconstant .or primary_expression_1;
+primary_expression_1
+ lparen .and logical_or_expression .and rparen;
+
+intconstant
+ integer .emit OP_PUSHINT;
+
+integer
+ integer_dec;
+
+integer_dec
+ digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0';
+
+digit_dec
+ '0'-'9';
+
+optional_space
+ .loop single_space;
+
+space
+ single_space .and .loop single_space;
+
+single_space
+ ' ' .or '\t';
+
+ampersand
+ optional_space .and '&' .and optional_space;
+
+ampersandampersand
+ optional_space .and '&' .and '&' .and optional_space;
+
+bang
+ optional_space .and '!' .and optional_space;
+
+bangequals
+ optional_space .and '!' .and '=' .and optional_space;
+
+bar
+ optional_space .and '|' .and optional_space;
+
+barbar
+ optional_space .and '|' .and '|' .and optional_space;
+
+caret
+ optional_space .and '^' .and optional_space;
+
+dash
+ optional_space .and '-' .and optional_space;
+
+equalsequals
+ optional_space .and '=' .and '=' .and optional_space;
+
+greater
+ optional_space .and '>' .and optional_space;
+
+greaterequals
+ optional_space .and '>' .and '=' .and optional_space;
+
+greatergreater
+ optional_space .and '>' .and '>' .and optional_space;
+
+less
+ optional_space .and '<' .and optional_space;
+
+lessequals
+ optional_space .and '<' .and '=' .and optional_space;
+
+lessless
+ optional_space .and '<' .and '<' .and optional_space;
+
+lparen
+ optional_space .and '(' .and optional_space;
+
+percent
+ optional_space .and '%' .and optional_space;
+
+plus
+ optional_space .and '+' .and optional_space;
+
+rparen
+ optional_space .and ')' .and optional_space;
+
+slash
+ optional_space .and '/' .and optional_space;
+
+star
+ optional_space .and '*' .and optional_space;
+
+tilda
+ optional_space .and '~' .and optional_space;
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_expression_syn.h b/mesalib/src/mesa/shader/slang/library/slang_pp_expression_syn.h
new file mode 100644
index 000000000..f3e9ef6b2
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_expression_syn.h
@@ -0,0 +1,179 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */
+
+".syntax expression;\n"
+".emtcode EXP_END 0\n"
+".emtcode EXP_EXPRESSION 1\n"
+".emtcode OP_END 0\n"
+".emtcode OP_PUSHINT 1\n"
+".emtcode OP_LOGICALOR 2\n"
+".emtcode OP_LOGICALAND 3\n"
+".emtcode OP_OR 4\n"
+".emtcode OP_XOR 5\n"
+".emtcode OP_AND 6\n"
+".emtcode OP_EQUAL 7\n"
+".emtcode OP_NOTEQUAL 8\n"
+".emtcode OP_LESSEQUAL 9\n"
+".emtcode OP_GREATEREQUAL 10\n"
+".emtcode OP_LESS 11\n"
+".emtcode OP_GREATER 12\n"
+".emtcode OP_LEFTSHIFT 13\n"
+".emtcode OP_RIGHTSHIFT 14\n"
+".emtcode OP_ADD 15\n"
+".emtcode OP_SUBTRACT 16\n"
+".emtcode OP_MULTIPLY 17\n"
+".emtcode OP_DIVIDE 18\n"
+".emtcode OP_MODULUS 19\n"
+".emtcode OP_PLUS 20\n"
+".emtcode OP_MINUS 21\n"
+".emtcode OP_NEGATE 22\n"
+".emtcode OP_COMPLEMENT 23\n"
+"expression\n"
+" first_expression .and optional_second_expression .and optional_space .and '\\0' .emit EXP_END;\n"
+"first_expression\n"
+" optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;\n"
+"optional_second_expression\n"
+" second_expression .or .true;\n"
+"second_expression\n"
+" space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END;\n"
+"logical_or_expression\n"
+" logical_and_expression .and .loop logical_or_expression_1;\n"
+"logical_or_expression_1\n"
+" barbar .and logical_and_expression .and .true .emit OP_LOGICALOR;\n"
+"logical_and_expression\n"
+" or_expression .and .loop logical_and_expression_1;\n"
+"logical_and_expression_1\n"
+" ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND;\n"
+"or_expression\n"
+" xor_expression .and .loop or_expression_1;\n"
+"or_expression_1\n"
+" bar .and xor_expression .and .true .emit OP_OR;\n"
+"xor_expression\n"
+" and_expression .and .loop xor_expression_1;\n"
+"xor_expression_1\n"
+" caret .and and_expression .and .true .emit OP_XOR;\n"
+"and_expression\n"
+" equality_expression .and .loop and_expression_1;\n"
+"and_expression_1\n"
+" ampersand .and equality_expression .and .true .emit OP_AND;\n"
+"equality_expression\n"
+" relational_expression .and .loop equality_expression_1;\n"
+"equality_expression_1\n"
+" equality_expression_2 .or equality_expression_3;\n"
+"equality_expression_2\n"
+" equalsequals .and relational_expression .and .true .emit OP_EQUAL;\n"
+"equality_expression_3\n"
+" bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;\n"
+"relational_expression\n"
+" shift_expression .and .loop relational_expression_1;\n"
+"relational_expression_1\n"
+" relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or\n"
+" relational_expression_5;\n"
+"relational_expression_2\n"
+" lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;\n"
+"relational_expression_3\n"
+" greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;\n"
+"relational_expression_4\n"
+" less .and shift_expression .and .true .emit OP_LESS;\n"
+"relational_expression_5\n"
+" greater .and shift_expression .and .true .emit OP_GREATER;\n"
+"shift_expression\n"
+" additive_expression .and .loop shift_expression_1;\n"
+"shift_expression_1\n"
+" shift_expression_2 .or shift_expression_3;\n"
+"shift_expression_2\n"
+" lessless .and additive_expression .and .true .emit OP_LEFTSHIFT;\n"
+"shift_expression_3\n"
+" greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT;\n"
+"additive_expression\n"
+" multiplicative_expression .and .loop additive_expression_1;\n"
+"additive_expression_1\n"
+" additive_expression_2 .or additive_expression_3;\n"
+"additive_expression_2\n"
+" plus .and multiplicative_expression .and .true .emit OP_ADD;\n"
+"additive_expression_3\n"
+" dash .and multiplicative_expression .and .true .emit OP_SUBTRACT;\n"
+"multiplicative_expression\n"
+" unary_expression .and .loop multiplicative_expression_1;\n"
+"multiplicative_expression_1\n"
+" multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4;\n"
+"multiplicative_expression_2\n"
+" star .and unary_expression .and .true .emit OP_MULTIPLY;\n"
+"multiplicative_expression_3\n"
+" slash .and unary_expression .and .true .emit OP_DIVIDE;\n"
+"multiplicative_expression_4\n"
+" percent .and unary_expression .and .true .emit OP_MODULUS;\n"
+"unary_expression\n"
+" primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or\n"
+" unary_expression_4;\n"
+"unary_expression_1\n"
+" plus .and unary_expression .and .true .emit OP_PLUS;\n"
+"unary_expression_2\n"
+" dash .and unary_expression .and .true .emit OP_MINUS;\n"
+"unary_expression_3\n"
+" bang .and unary_expression .and .true .emit OP_NEGATE;\n"
+"unary_expression_4\n"
+" tilda .and unary_expression .and .true .emit OP_COMPLEMENT;\n"
+"primary_expression\n"
+" intconstant .or primary_expression_1;\n"
+"primary_expression_1\n"
+" lparen .and logical_or_expression .and rparen;\n"
+"intconstant\n"
+" integer .emit OP_PUSHINT;\n"
+"integer\n"
+" integer_dec;\n"
+"integer_dec\n"
+" digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"optional_space\n"
+" .loop single_space;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" ' ' .or '\\t';\n"
+"ampersand\n"
+" optional_space .and '&' .and optional_space;\n"
+"ampersandampersand\n"
+" optional_space .and '&' .and '&' .and optional_space;\n"
+"bang\n"
+" optional_space .and '!' .and optional_space;\n"
+"bangequals\n"
+" optional_space .and '!' .and '=' .and optional_space;\n"
+"bar\n"
+" optional_space .and '|' .and optional_space;\n"
+"barbar\n"
+" optional_space .and '|' .and '|' .and optional_space;\n"
+"caret\n"
+" optional_space .and '^' .and optional_space;\n"
+"dash\n"
+" optional_space .and '-' .and optional_space;\n"
+"equalsequals\n"
+" optional_space .and '=' .and '=' .and optional_space;\n"
+"greater\n"
+" optional_space .and '>' .and optional_space;\n"
+"greaterequals\n"
+" optional_space .and '>' .and '=' .and optional_space;\n"
+"greatergreater\n"
+" optional_space .and '>' .and '>' .and optional_space;\n"
+"less\n"
+" optional_space .and '<' .and optional_space;\n"
+"lessequals\n"
+" optional_space .and '<' .and '=' .and optional_space;\n"
+"lessless\n"
+" optional_space .and '<' .and '<' .and optional_space;\n"
+"lparen\n"
+" optional_space .and '(' .and optional_space;\n"
+"percent\n"
+" optional_space .and '%' .and optional_space;\n"
+"plus\n"
+" optional_space .and '+' .and optional_space;\n"
+"rparen\n"
+" optional_space .and ')' .and optional_space;\n"
+"slash\n"
+" optional_space .and '/' .and optional_space;\n"
+"star\n"
+" optional_space .and '*' .and optional_space;\n"
+"tilda\n"
+" optional_space .and '~' .and optional_space;\n"
+""
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_version.syn b/mesalib/src/mesa/shader/slang/library/slang_pp_version.syn
new file mode 100644
index 000000000..3fe1a57ba
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_version.syn
@@ -0,0 +1,122 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_pp_version.syn
+ * slang #version directive syntax
+ * \author Michal Krol
+ */
+
+.syntax version_directive;
+
+version_directive
+ version_directive_1;
+version_directive_1
+ prior_optional_spaces .and optional_version_directive .and .true .emit $;
+
+optional_version_directive
+ version_directive_body .or .true .emit 10 .emit 1;
+
+version_directive_body
+ '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and
+ new_line;
+
+version_number
+ version_number_100 .or version_number_110 .or version_number_120;
+
+version_number_100
+ leading_zeroes .and "100" .emit 0 .emit 1;
+
+version_number_110
+ leading_zeroes .and "110" .emit 10 .emit 1;
+
+version_number_120
+ leading_zeroes .and "120" .emit 20 .emit 1;
+
+leading_zeroes
+ .loop zero;
+
+zero
+ '0';
+
+space
+ single_space .and .loop single_space;
+
+optional_space
+ .loop single_space;
+
+single_space
+ ' ' .or '\t';
+
+prior_optional_spaces
+ .loop prior_space;
+
+prior_space
+ c_style_comment_block .or cpp_style_comment_block .or space .or new_line;
+
+c_style_comment_block
+ '/' .and '*' .and c_style_comment_rest;
+
+c_style_comment_rest
+ .loop c_style_comment_char_no_star .and c_style_comment_rest_1;
+c_style_comment_rest_1
+ c_style_comment_end .or c_style_comment_rest_2;
+c_style_comment_rest_2
+ '*' .and c_style_comment_rest;
+
+c_style_comment_char_no_star
+ '\x2B'-'\xFF' .or '\x01'-'\x29';
+
+c_style_comment_end
+ '*' .and '/';
+
+cpp_style_comment_block
+ '/' .and '/' .and cpp_style_comment_block_1;
+cpp_style_comment_block_1
+ cpp_style_comment_block_2 .or cpp_style_comment_block_3;
+cpp_style_comment_block_2
+ .loop cpp_style_comment_char .and new_line;
+cpp_style_comment_block_3
+ .loop cpp_style_comment_char;
+
+cpp_style_comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+new_line
+ cr_lf .or lf_cr .or '\n' .or '\r';
+
+cr_lf
+ '\r' .and '\n';
+
+lf_cr
+ '\n' .and '\r';
+
+.string __string_filter;
+
+__string_filter
+ .loop __identifier_char;
+
+__identifier_char
+ 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_pp_version_syn.h b/mesalib/src/mesa/shader/slang/library/slang_pp_version_syn.h
new file mode 100644
index 000000000..54aee3ff2
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_pp_version_syn.h
@@ -0,0 +1,69 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */
+
+".syntax version_directive;\n"
+"version_directive\n"
+" version_directive_1;\n"
+"version_directive_1\n"
+" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n"
+"optional_version_directive\n"
+" version_directive_body .or .true .emit 10 .emit 1;\n"
+"version_directive_body\n"
+" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n"
+" new_line;\n"
+"version_number\n"
+" version_number_100 .or version_number_110 .or version_number_120;\n"
+"version_number_100\n"
+" leading_zeroes .and \"100\" .emit 0 .emit 1;\n"
+"version_number_110\n"
+" leading_zeroes .and \"110\" .emit 10 .emit 1;\n"
+"version_number_120\n"
+" leading_zeroes .and \"120\" .emit 20 .emit 1;\n"
+"leading_zeroes\n"
+" .loop zero;\n"
+"zero\n"
+" '0';\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"optional_space\n"
+" .loop single_space;\n"
+"single_space\n"
+" ' ' .or '\\t';\n"
+"prior_optional_spaces\n"
+" .loop prior_space;\n"
+"prior_space\n"
+" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n"
+"c_style_comment_block\n"
+" '/' .and '*' .and c_style_comment_rest;\n"
+"c_style_comment_rest\n"
+" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n"
+"c_style_comment_rest_1\n"
+" c_style_comment_end .or c_style_comment_rest_2;\n"
+"c_style_comment_rest_2\n"
+" '*' .and c_style_comment_rest;\n"
+"c_style_comment_char_no_star\n"
+" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"c_style_comment_end\n"
+" '*' .and '/';\n"
+"cpp_style_comment_block\n"
+" '/' .and '/' .and cpp_style_comment_block_1;\n"
+"cpp_style_comment_block_1\n"
+" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n"
+"cpp_style_comment_block_2\n"
+" .loop cpp_style_comment_char .and new_line;\n"
+"cpp_style_comment_block_3\n"
+" .loop cpp_style_comment_char;\n"
+"cpp_style_comment_char\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"new_line\n"
+" cr_lf .or lf_cr .or '\\n' .or '\\r';\n"
+"cr_lf\n"
+" '\\r' .and '\\n';\n"
+"lf_cr\n"
+" '\\n' .and '\\r';\n"
+".string __string_filter;\n"
+"__string_filter\n"
+" .loop __identifier_char;\n"
+"__identifier_char\n"
+" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n"
+""
diff --git a/mesalib/src/mesa/shader/slang/library/slang_shader.syn b/mesalib/src/mesa/shader/slang/library/slang_shader.syn
new file mode 100644
index 000000000..cc5c70a02
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_shader.syn
@@ -0,0 +1,1716 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/*
+ * \file slang_shader.syn
+ * slang vertex/fragment shader syntax
+ * \author Michal Krol
+ */
+
+/*
+ * usage:
+ * syn2c slang_shader.syn > slang_shader_syn.h
+ *
+ * when modifying or extending this file, several things must be taken into
+ * consideration:
+ *
+ * - when adding new operators that were marked as reserved in the
+ * initial specification, one must only uncomment particular lines of
+ * code that refer to operators being added;
+ *
+ * - when adding new shader targets, one must reserve a new value for
+ * shader_type register and use it in .if constructs for symbols that
+ * are exclusive for that shader;
+ *
+ * - some symbols mimic output of other symbols - the best example is
+ * the "for" construct: expression "for (foo(); ; bar())" is seen as
+ * "for (foo(); true; bar())" by the output processor - hence, special
+ * care must be taken when rearranging output of essential symbols;
+ *
+ * - order of single-quoted tokens does matter in alternatives - so do not
+ * parse "<" operator before "<<" and "<<" before "<<=";
+ *
+ * - all double-quoted tokens are internally preprocessed to eliminate
+ * problems with parsing strings that are prefixes of other strings,
+ * like "sampler1D" and "sampler1DShadow";
+ */
+
+.syntax translation_unit;
+
+/* revision number - increment after each change affecting emitted output */
+.emtcode REVISION 5
+
+/* external declaration (or precision or invariant stmt) */
+.emtcode EXTERNAL_NULL 0
+.emtcode EXTERNAL_FUNCTION_DEFINITION 1
+.emtcode EXTERNAL_DECLARATION 2
+.emtcode DEFAULT_PRECISION 3
+.emtcode INVARIANT_STMT 4
+
+/* precision */
+.emtcode PRECISION_DEFAULT 0
+.emtcode PRECISION_LOW 1
+.emtcode PRECISION_MEDIUM 2
+.emtcode PRECISION_HIGH 3
+
+/* declaration */
+.emtcode DECLARATION_FUNCTION_PROTOTYPE 1
+.emtcode DECLARATION_INIT_DECLARATOR_LIST 2
+
+/* function type */
+.emtcode FUNCTION_ORDINARY 0
+.emtcode FUNCTION_CONSTRUCTOR 1
+.emtcode FUNCTION_OPERATOR 2
+
+/* function call type */
+.emtcode FUNCTION_CALL_NONARRAY 0
+.emtcode FUNCTION_CALL_ARRAY 1
+
+/* operator type */
+.emtcode OPERATOR_ADDASSIGN 1
+.emtcode OPERATOR_SUBASSIGN 2
+.emtcode OPERATOR_MULASSIGN 3
+.emtcode OPERATOR_DIVASSIGN 4
+/*.emtcode OPERATOR_MODASSIGN 5*/
+/*.emtcode OPERATOR_LSHASSIGN 6*/
+/*.emtcode OPERATOR_RSHASSIGN 7*/
+/*.emtcode OPERATOR_ORASSIGN 8*/
+/*.emtcode OPERATOR_XORASSIGN 9*/
+/*.emtcode OPERATOR_ANDASSIGN 10*/
+.emtcode OPERATOR_LOGICALXOR 11
+/*.emtcode OPERATOR_BITOR 12*/
+/*.emtcode OPERATOR_BITXOR 13*/
+/*.emtcode OPERATOR_BITAND 14*/
+.emtcode OPERATOR_LESS 15
+.emtcode OPERATOR_GREATER 16
+.emtcode OPERATOR_LESSEQUAL 17
+.emtcode OPERATOR_GREATEREQUAL 18
+/*.emtcode OPERATOR_LSHIFT 19*/
+/*.emtcode OPERATOR_RSHIFT 20*/
+.emtcode OPERATOR_MULTIPLY 21
+.emtcode OPERATOR_DIVIDE 22
+/*.emtcode OPERATOR_MODULUS 23*/
+.emtcode OPERATOR_INCREMENT 24
+.emtcode OPERATOR_DECREMENT 25
+.emtcode OPERATOR_PLUS 26
+.emtcode OPERATOR_MINUS 27
+/*.emtcode OPERATOR_COMPLEMENT 28*/
+.emtcode OPERATOR_NOT 29
+
+/* init declarator list */
+.emtcode DECLARATOR_NONE 0
+.emtcode DECLARATOR_NEXT 1
+
+/* variable declaration */
+.emtcode VARIABLE_NONE 0
+.emtcode VARIABLE_IDENTIFIER 1
+.emtcode VARIABLE_INITIALIZER 2
+.emtcode VARIABLE_ARRAY_EXPLICIT 3
+.emtcode VARIABLE_ARRAY_UNKNOWN 4
+
+/* type qualifier */
+.emtcode TYPE_QUALIFIER_NONE 0
+.emtcode TYPE_QUALIFIER_CONST 1
+.emtcode TYPE_QUALIFIER_ATTRIBUTE 2
+.emtcode TYPE_QUALIFIER_VARYING 3
+.emtcode TYPE_QUALIFIER_UNIFORM 4
+.emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5
+.emtcode TYPE_QUALIFIER_FIXEDINPUT 6
+
+/* invariant qualifier */
+.emtcode TYPE_VARIANT 90
+.emtcode TYPE_INVARIANT 91
+
+/* centroid qualifier */
+.emtcode TYPE_CENTER 95
+.emtcode TYPE_CENTROID 96
+
+/* type specifier */
+.emtcode TYPE_SPECIFIER_VOID 0
+.emtcode TYPE_SPECIFIER_BOOL 1
+.emtcode TYPE_SPECIFIER_BVEC2 2
+.emtcode TYPE_SPECIFIER_BVEC3 3
+.emtcode TYPE_SPECIFIER_BVEC4 4
+.emtcode TYPE_SPECIFIER_INT 5
+.emtcode TYPE_SPECIFIER_IVEC2 6
+.emtcode TYPE_SPECIFIER_IVEC3 7
+.emtcode TYPE_SPECIFIER_IVEC4 8
+.emtcode TYPE_SPECIFIER_FLOAT 9
+.emtcode TYPE_SPECIFIER_VEC2 10
+.emtcode TYPE_SPECIFIER_VEC3 11
+.emtcode TYPE_SPECIFIER_VEC4 12
+.emtcode TYPE_SPECIFIER_MAT2 13
+.emtcode TYPE_SPECIFIER_MAT3 14
+.emtcode TYPE_SPECIFIER_MAT4 15
+.emtcode TYPE_SPECIFIER_SAMPLER1D 16
+.emtcode TYPE_SPECIFIER_SAMPLER2D 17
+.emtcode TYPE_SPECIFIER_SAMPLER3D 18
+.emtcode TYPE_SPECIFIER_SAMPLERCUBE 19
+.emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20
+.emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21
+.emtcode TYPE_SPECIFIER_SAMPLER2DRECT 22
+.emtcode TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
+.emtcode TYPE_SPECIFIER_STRUCT 24
+.emtcode TYPE_SPECIFIER_TYPENAME 25
+
+/* OpenGL 2.1 */
+.emtcode TYPE_SPECIFIER_MAT23 26
+.emtcode TYPE_SPECIFIER_MAT32 27
+.emtcode TYPE_SPECIFIER_MAT24 28
+.emtcode TYPE_SPECIFIER_MAT42 29
+.emtcode TYPE_SPECIFIER_MAT34 30
+.emtcode TYPE_SPECIFIER_MAT43 31
+
+/* type specifier array */
+.emtcode TYPE_SPECIFIER_NONARRAY 0
+.emtcode TYPE_SPECIFIER_ARRAY 1
+
+/* structure field */
+.emtcode FIELD_NONE 0
+.emtcode FIELD_NEXT 1
+.emtcode FIELD_ARRAY 2
+
+/* operation */
+.emtcode OP_END 0
+.emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+.emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2
+.emtcode OP_DECLARE 3
+.emtcode OP_ASM 4
+.emtcode OP_BREAK 5
+.emtcode OP_CONTINUE 6
+.emtcode OP_DISCARD 7
+.emtcode OP_RETURN 8
+.emtcode OP_EXPRESSION 9
+.emtcode OP_IF 10
+.emtcode OP_WHILE 11
+.emtcode OP_DO 12
+.emtcode OP_FOR 13
+.emtcode OP_PUSH_VOID 14
+.emtcode OP_PUSH_BOOL 15
+.emtcode OP_PUSH_INT 16
+.emtcode OP_PUSH_FLOAT 17
+.emtcode OP_PUSH_IDENTIFIER 18
+.emtcode OP_SEQUENCE 19
+.emtcode OP_ASSIGN 20
+.emtcode OP_ADDASSIGN 21
+.emtcode OP_SUBASSIGN 22
+.emtcode OP_MULASSIGN 23
+.emtcode OP_DIVASSIGN 24
+/*.emtcode OP_MODASSIGN 25*/
+/*.emtcode OP_LSHASSIGN 26*/
+/*.emtcode OP_RSHASSIGN 27*/
+/*.emtcode OP_ORASSIGN 28*/
+/*.emtcode OP_XORASSIGN 29*/
+/*.emtcode OP_ANDASSIGN 30*/
+.emtcode OP_SELECT 31
+.emtcode OP_LOGICALOR 32
+.emtcode OP_LOGICALXOR 33
+.emtcode OP_LOGICALAND 34
+/*.emtcode OP_BITOR 35*/
+/*.emtcode OP_BITXOR 36*/
+/*.emtcode OP_BITAND 37*/
+.emtcode OP_EQUAL 38
+.emtcode OP_NOTEQUAL 39
+.emtcode OP_LESS 40
+.emtcode OP_GREATER 41
+.emtcode OP_LESSEQUAL 42
+.emtcode OP_GREATEREQUAL 43
+/*.emtcode OP_LSHIFT 44*/
+/*.emtcode OP_RSHIFT 45*/
+.emtcode OP_ADD 46
+.emtcode OP_SUBTRACT 47
+.emtcode OP_MULTIPLY 48
+.emtcode OP_DIVIDE 49
+/*.emtcode OP_MODULUS 50*/
+.emtcode OP_PREINCREMENT 51
+.emtcode OP_PREDECREMENT 52
+.emtcode OP_PLUS 53
+.emtcode OP_MINUS 54
+/*.emtcode OP_COMPLEMENT 55*/
+.emtcode OP_NOT 56
+.emtcode OP_SUBSCRIPT 57
+.emtcode OP_CALL 58
+.emtcode OP_FIELD 59
+.emtcode OP_POSTINCREMENT 60
+.emtcode OP_POSTDECREMENT 61
+.emtcode OP_PRECISION 62
+.emtcode OP_METHOD 63
+
+/* parameter qualifier */
+.emtcode PARAM_QUALIFIER_IN 0
+.emtcode PARAM_QUALIFIER_OUT 1
+.emtcode PARAM_QUALIFIER_INOUT 2
+
+/* function parameter */
+.emtcode PARAMETER_NONE 0
+.emtcode PARAMETER_NEXT 1
+
+/* function parameter array presence */
+.emtcode PARAMETER_ARRAY_NOT_PRESENT 0
+.emtcode PARAMETER_ARRAY_PRESENT 1
+
+/* INVALID_EXTERNAL_DECLARATION seems to be reported when there's */
+/* any syntax errors... */
+.errtext INVALID_EXTERNAL_DECLARATION "2001: Syntax error."
+.errtext INVALID_OPERATOR_OVERRIDE "2002: Invalid operator override."
+.errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found."
+.errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found."
+.errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found."
+.errtext INVALID_PRECISION "2006: Invalid precision specifier '$err_token$'."
+.errtext INVALID_PRECISION_TYPE "2007: Invalid precision type '$err_token$'."
+
+
+/*
+ * tells whether the shader that is being parsed is a built-in shader or not
+ * 0 - normal behaviour
+ * 1 - accepts constructor and operator definitions and __asm statements
+ * the implementation will set it to 1 when compiling internal built-in shaders
+ */
+.regbyte parsing_builtin 0
+
+/*
+ * holds the type of the shader being parsed; possible values are
+ * listed below.
+ * FRAGMENT_SHADER 1
+ * VERTEX_SHADER 2
+ * shader type is set by the caller before parsing
+ */
+.regbyte shader_type 0
+
+/*
+ * <variable_identifier> ::= <identifier>
+ */
+variable_identifier
+ identifier .emit OP_PUSH_IDENTIFIER;
+
+/*
+ * <primary_expression> ::= <variable_identifier>
+ * | <intconstant>
+ * | <floatconstant>
+ * | <boolconstant>
+ * | "(" <expression> ")"
+ */
+primary_expression
+ floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1;
+primary_expression_1
+ lparen .and expression .and rparen;
+
+/*
+ * <postfix_expression> ::= <primary_expression>
+ * | <postfix_expression> "[" <integer_expression> "]"
+ * | <function_call>
+ * | <postfix_expression> "." <field_selection>
+ * | <postfix_expression> "++"
+ * | <postfix_expression> "--"
+ */
+postfix_expression
+ postfix_expression_1 .and .loop postfix_expression_2;
+postfix_expression_1
+ function_call .or primary_expression;
+postfix_expression_2
+ postfix_expression_3 .or postfix_expression_4 .or
+ plusplus .emit OP_POSTINCREMENT .or
+ minusminus .emit OP_POSTDECREMENT;
+postfix_expression_3
+ lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT;
+postfix_expression_4
+ dot .and field_selection .emit OP_FIELD;
+
+/*
+ * <integer_expression> ::= <expression>
+ */
+integer_expression
+ expression;
+
+/*
+ * <function_call> ::= <function_call_generic>
+ */
+function_call
+ function_call_or_method;
+
+/*
+ * <function_call_or_method> ::= <regular_function_call>
+ * | <postfix_expression> "." <function_call_generic>
+ */
+function_call_or_method
+ regular_function_call .or method_call;
+
+/*
+ * <method_call> ::= <identifier> "." <function_call_generic>
+ */
+method_call
+ identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END;
+
+/*
+ * <regular_function_call> ::= <function_call_generic>
+ */
+regular_function_call
+ function_call_generic .emit OP_CALL .and .true .emit OP_END;
+
+/*
+ * <function_call_generic> ::= <function_call_header_with_parameters> ")"
+ * | <function_call_header_no_parameters> ")"
+ */
+function_call_generic
+ function_call_generic_1 .or function_call_generic_2;
+function_call_generic_1
+ function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED;
+function_call_generic_2
+ function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED;
+
+/*
+ * <function_call_header_no_parameters>::= <function_call_header> "void"
+ * | <function_call_header>
+ */
+function_call_header_no_parameters
+ function_call_header .and function_call_header_no_parameters_1;
+function_call_header_no_parameters_1
+ "void" .or .true;
+
+/*
+ * <function_call_header_with_parameters> ::= <function_call_header> <assignment_expression>
+ * | <function_call_header_with_parameters> "," <assignment_expression>
+ */
+function_call_header_with_parameters
+ function_call_header .and assignment_expression .and .true .emit OP_END .and
+ .loop function_call_header_with_parameters_1;
+function_call_header_with_parameters_1
+ comma .and assignment_expression .and .true .emit OP_END;
+
+/*
+ * <function_call_header> ::= <function_identifier> "("
+ */
+function_call_header
+ function_identifier .and lparen;
+
+/*
+ * <function_identifier> ::= <constructor_identifier>
+ * | <identifier>
+ * | <type_specifier>
+ *
+ * note: <constructor_identifier> and <type_specifier> have been deleted
+ */
+function_identifier
+ identifier .and function_identifier_opt_array;
+function_identifier_opt_array
+ function_identifier_array .emit FUNCTION_CALL_ARRAY .or
+ .true .emit FUNCTION_CALL_NONARRAY;
+function_identifier_array
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <unary_expression> ::= <postfix_expression>
+ * | "++" <unary_expression>
+ * | "--" <unary_expression>
+ * | <unary_operator> <unary_expression>
+ *
+ * <unary_operator> ::= "+"
+ * | "-"
+ * | "!"
+ * | "~" // reserved
+ */
+unary_expression
+ postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or
+ unary_expression_4 .or unary_expression_5/* .or unary_expression_6*/;
+unary_expression_1
+ plusplus .and unary_expression .and .true .emit OP_PREINCREMENT;
+unary_expression_2
+ minusminus .and unary_expression .and .true .emit OP_PREDECREMENT;
+unary_expression_3
+ plus .and unary_expression .and .true .emit OP_PLUS;
+unary_expression_4
+ minus .and unary_expression .and .true .emit OP_MINUS;
+unary_expression_5
+ bang .and unary_expression .and .true .emit OP_NOT;
+/*unary_expression_6
+ tilde .and unary_expression .and .true .emit OP_COMPLEMENT;*/
+
+/*
+ * <multiplicative_expression> ::= <unary_expression>
+ * | <multiplicative_expression> "*" <unary_expression>
+ * | <multiplicative_expression> "/" <unary_expression>
+ * | <multiplicative_expression> "%" <unary_expression> // reserved
+ */
+multiplicative_expression
+ unary_expression .and .loop multiplicative_expression_1;
+multiplicative_expression_1
+ multiplicative_expression_2 .or multiplicative_expression_3/* .or multiplicative_expression_4*/;
+multiplicative_expression_2
+ star .and unary_expression .and .true .emit OP_MULTIPLY;
+multiplicative_expression_3
+ slash .and unary_expression .and .true .emit OP_DIVIDE;
+/*multiplicative_expression_4
+ percent .and unary_expression .and .true .emit OP_MODULUS;*/
+
+/*
+ * <additive_expression> ::= <multiplicative_expression>
+ * | <additive_expression> "+" <multiplicative_expression>
+ * | <additive_expression> "-" <multiplicative_expression>
+ */
+additive_expression
+ multiplicative_expression .and .loop additive_expression_1;
+additive_expression_1
+ additive_expression_2 .or additive_expression_3;
+additive_expression_2
+ plus .and multiplicative_expression .and .true .emit OP_ADD;
+additive_expression_3
+ minus .and multiplicative_expression .and .true .emit OP_SUBTRACT;
+
+/*
+ * <shift_expression> ::= <additive_expression>
+ * | <shift_expression> "<<" <additive_expression> // reserved
+ * | <shift_expression> ">>" <additive_expression> // reserved
+ */
+shift_expression
+ additive_expression/* .and .loop shift_expression_1*/;
+/*shift_expression_1
+ shift_expression_2 .or shift_expression_3;*/
+/*shift_expression_2
+ lessless .and additive_expression .and .true .emit OP_LSHIFT;*/
+/*shift_expression_3
+ greatergreater .and additive_expression .and .true .emit OP_RSHIFT;*/
+
+/*
+ * <relational_expression> ::= <shift_expression>
+ * | <relational_expression> "<" <shift_expression>
+ * | <relational_expression> ">" <shift_expression>
+ * | <relational_expression> "<=" <shift_expression>
+ * | <relational_expression> ">=" <shift_expression>
+ */
+relational_expression
+ shift_expression .and .loop relational_expression_1;
+relational_expression_1
+ relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or
+ relational_expression_5;
+relational_expression_2
+ lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;
+relational_expression_3
+ greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;
+relational_expression_4
+ less .and shift_expression .and .true .emit OP_LESS;
+relational_expression_5
+ greater .and shift_expression .and .true .emit OP_GREATER;
+
+/*
+ * <equality_expression> ::= <relational_expression>
+ * | <equality_expression> "==" <relational_expression>
+ * | <equality_expression> "!=" <relational_expression>
+ */
+equality_expression
+ relational_expression .and .loop equality_expression_1;
+equality_expression_1
+ equality_expression_2 .or equality_expression_3;
+equality_expression_2
+ equalsequals .and relational_expression .and .true .emit OP_EQUAL;
+equality_expression_3
+ bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;
+
+/*
+ * <and_expression> ::= <equality_expression>
+ * | <and_expression> "&" <equality_expression> // reserved
+ */
+and_expression
+ equality_expression/* .and .loop and_expression_1*/;
+/*and_expression_1
+ ampersand .and equality_expression .and .true .emit OP_BITAND;*/
+
+/*
+ * <exclusive_or_expression> ::= <and_expression>
+ * | <exclusive_or_expression> "^" <and_expression> // reserved
+ */
+exclusive_or_expression
+ and_expression/* .and .loop exclusive_or_expression_1*/;
+/*exclusive_or_expression_1
+ caret .and and_expression .and .true .emit OP_BITXOR;*/
+
+/*
+ * <inclusive_or_expression> ::= <exclusive_or_expression>
+ * | <inclusive_or_expression> "|" <exclusive_or_expression> // reserved
+ */
+inclusive_or_expression
+ exclusive_or_expression/* .and .loop inclusive_or_expression_1*/;
+/*inclusive_or_expression_1
+ bar .and exclusive_or_expression .and .true .emit OP_BITOR;*/
+
+/*
+ * <logical_and_expression> ::= <inclusive_or_expression>
+ * | <logical_and_expression> "&&" <inclusive_or_expression>
+ */
+logical_and_expression
+ inclusive_or_expression .and .loop logical_and_expression_1;
+logical_and_expression_1
+ ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND;
+
+/*
+ * <logical_xor_expression> ::= <logical_and_expression>
+ * | <logical_xor_expression> "^^" <logical_and_expression>
+ */
+logical_xor_expression
+ logical_and_expression .and .loop logical_xor_expression_1;
+logical_xor_expression_1
+ caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR;
+
+/*
+ * <logical_or_expression> ::= <logical_xor_expression>
+ * | <logical_or_expression> "||" <logical_xor_expression>
+ */
+logical_or_expression
+ logical_xor_expression .and .loop logical_or_expression_1;
+logical_or_expression_1
+ barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR;
+
+/*
+ * <conditional_expression> ::= <logical_or_expression>
+ * | <logical_or_expression> "?" <expression> ":" <conditional_expression>
+ */
+conditional_expression
+ logical_or_expression .and .loop conditional_expression_1;
+conditional_expression_1
+ question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT;
+
+/*
+ * <assignment_expression> ::= <conditional_expression>
+ * | <unary_expression> <assignment_operator> <assignment_expression>
+ *
+ * <assignment_operator> ::= "="
+ * | "*="
+ * | "/="
+ * | "+="
+ * | "-="
+ * | "%=" // reserved
+ * | "<<=" // reserved
+ * | ">>=" // reserved
+ * | "&=" // reserved
+ * | "^=" // reserved
+ * | "|=" // reserved
+ */
+assignment_expression
+ assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or
+ assignment_expression_4 .or assignment_expression_5/* .or assignment_expression_6 .or
+ assignment_expression_7 .or assignment_expression_8 .or assignment_expression_9 .or
+ assignment_expression_10 .or assignment_expression_11*/ .or conditional_expression;
+assignment_expression_1
+ unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN;
+assignment_expression_2
+ unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN;
+assignment_expression_3
+ unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN;
+assignment_expression_4
+ unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN;
+assignment_expression_5
+ unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN;
+/*assignment_expression_6
+ unary_expression .and percentequals .and assignment_expression .and .true .emit OP_MODASSIGN;*/
+/*assignment_expression_7
+ unary_expression .and lesslessequals .and assignment_expression .and .true .emit OP_LSHASSIGN;*/
+/*assignment_expression_8
+ unary_expression .and greatergreaterequals .and assignment_expression .and
+ .true .emit OP_RSHASSIGN;*/
+/*assignment_expression_9
+ unary_expression .and ampersandequals .and assignment_expression .and .true .emit OP_ANDASSIGN;*/
+/*assignment_expression_10
+ unary_expression .and caretequals .and assignment_expression .and .true .emit OP_XORASSIGN;*/
+/*assignment_expression_11
+ unary_expression .and barequals .and assignment_expression .and .true .emit OP_ORASSIGN;*/
+
+/*
+ * <expression> ::= <assignment_expression>
+ * | <expression> "," <assignment_expression>
+ */
+expression
+ assignment_expression .and .loop expression_1;
+expression_1
+ comma .and assignment_expression .and .true .emit OP_SEQUENCE;
+
+/*
+ * <constant_expression> ::= <conditional_expression>
+ */
+constant_expression
+ conditional_expression .and .true .emit OP_END;
+
+/*
+ * <declaration> ::= <function_prototype> ";"
+ * | <init_declarator_list> ";"
+ */
+declaration
+ declaration_1 .or declaration_2;
+declaration_1
+ function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon;
+declaration_2
+ init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon;
+
+/*
+ * <function_prototype> ::= <function_header> "void" ")"
+ * | <function_declarator> ")"
+ */
+function_prototype
+ function_prototype_1 .or function_prototype_2;
+function_prototype_1
+ function_header .and "void" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;
+function_prototype_2
+ function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;
+
+/*
+ * <function_declarator> ::= <function_header>
+ * | <function_header_with_parameters>
+ */
+function_declarator
+ function_header_with_parameters .or function_header;
+
+/*
+ * <function_header_with_parameters> ::= <function_header> <parameter_declaration>
+ * | <function_header_with_parameters> ","
+ * <parameter_declaration>
+ */
+function_header_with_parameters
+ function_header .and parameter_declaration .and .loop function_header_with_parameters_1;
+function_header_with_parameters_1
+ comma .and parameter_declaration;
+
+/*
+ * <function_header> ::= <fully_specified_type> <identifier> "("
+ */
+function_header
+ function_header_nospace .or function_header_space;
+function_header_space
+ fully_specified_type_space .and space .and function_decl_identifier .and lparen;
+function_header_nospace
+ fully_specified_type_nospace .and function_decl_identifier .and lparen;
+
+/*
+ * <function_decl_identifier> ::= "__constructor"
+ * | <__operator>
+ * | <identifier>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator and constructor prototypes and definitions
+ */
+function_decl_identifier
+ .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or
+ .if (parsing_builtin != 0) "__constructor" .emit FUNCTION_CONSTRUCTOR .or
+ identifier .emit FUNCTION_ORDINARY;
+
+/*
+ * <__operator> ::= "__operator" <overriden_op>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator prototypes and definitions
+ */
+__operator
+ "__operator" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE;
+
+/*
+ * <overriden_op> ::= "="
+ * | "+="
+ * | "-="
+ * | "*="
+ * | "/="
+ * | "%=" // reserved
+ * | "<<=" // reserved
+ * | ">>=" // reserved
+ * | "&=" // reserved
+ * | "^=" // reserved
+ * | "|=" // reserved
+ * | "^^"
+ * | "|" // reserved
+ * | "^" // reserved
+ * | "&" // reserved
+ * | "=="
+ * | "!="
+ * | "<"
+ * | ">"
+ * | "<="
+ * | ">="
+ * | "<<" // reserved
+ * | ">>" // reserved
+ * | "*"
+ * | "/"
+ * | "%" // reserved
+ * | "++"
+ * | "--"
+ * | "+"
+ * | "-"
+ * | "~" // reserved
+ * | "!"
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows operator prototypes and definitions
+ */
+overriden_operator
+ plusplus .emit OPERATOR_INCREMENT .or
+ plusequals .emit OPERATOR_ADDASSIGN .or
+ plus .emit OPERATOR_PLUS .or
+ minusminus .emit OPERATOR_DECREMENT .or
+ minusequals .emit OPERATOR_SUBASSIGN .or
+ minus .emit OPERATOR_MINUS .or
+ bang .emit OPERATOR_NOT .or
+ starequals .emit OPERATOR_MULASSIGN .or
+ star .emit OPERATOR_MULTIPLY .or
+ slashequals .emit OPERATOR_DIVASSIGN .or
+ slash .emit OPERATOR_DIVIDE .or
+ lessequals .emit OPERATOR_LESSEQUAL .or
+ /*lesslessequals .emit OPERATOR_LSHASSIGN .or*/
+ /*lessless .emit OPERATOR_LSHIFT .or*/
+ less .emit OPERATOR_LESS .or
+ greaterequals .emit OPERATOR_GREATEREQUAL .or
+ /*greatergreaterequals .emit OPERATOR_RSHASSIGN .or*/
+ /*greatergreater .emit OPERATOR_RSHIFT .or*/
+ greater .emit OPERATOR_GREATER .or
+ /*percentequals .emit OPERATOR_MODASSIGN .or*/
+ /*percent .emit OPERATOR_MODULUS .or*/
+ /*ampersandequals .emit OPERATOR_ANDASSIGN */
+ /*ampersand .emit OPERATOR_BITAND .or*/
+ /*barequals .emit OPERATOR_ORASSIGN .or*/
+ /*bar .emit OPERATOR_BITOR .or*/
+ /*tilde .emit OPERATOR_COMPLEMENT .or*/
+ /*caretequals .emit OPERATOR_XORASSIGN .or*/
+ caretcaret .emit OPERATOR_LOGICALXOR /*.or
+ caret .emit OPERATOR_BITXOR*/;
+
+/*
+ * <parameter_declarator> ::= <type_specifier> <identifier>
+ * | <type_specifier> <identifier> "[" <constant_expression> "]"
+ */
+parameter_declarator
+ parameter_declarator_nospace .or parameter_declarator_space;
+parameter_declarator_nospace
+ type_specifier_nospace .and identifier .and parameter_declarator_1;
+parameter_declarator_space
+ type_specifier_space .and space .and identifier .and parameter_declarator_1;
+parameter_declarator_1
+ parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or
+ .true .emit PARAMETER_ARRAY_NOT_PRESENT;
+parameter_declarator_2
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <parameter_declaration> ::= <type_qualifier> <parameter_qualifier>
+ * <precision> <parameter_declarator>
+ * | <type_qualifier> <parameter_qualifier>
+ * <precision> <parameter_type_specifier>
+ * | <type_qualifier> <parameter_qualifier>
+ * <parameter_declarator>
+ * | <type_qualifier> <parameter_qualifier>
+ * <parameter_type_specifier>
+ * | <parameter_qualifier> <precision>
+ * <parameter_declarator>
+ * | <parameter_qualifier> <precision>
+ * <parameter_type_specifier>
+ * | <parameter_qualifier> <parameter_declarator>
+ * | <parameter_qualifier> <parameter_type_specifier>
+ */
+parameter_declaration
+ parameter_declaration_1 .emit PARAMETER_NEXT;
+parameter_declaration_1
+ parameter_declaration_2 .or parameter_declaration_3;
+parameter_declaration_2
+ type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4;
+parameter_declaration_3
+ parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4;
+parameter_declaration_4
+ parameter_declaration_optprec .and parameter_declaration_rest;
+parameter_declaration_optprec
+ parameter_declaration_prec .or .true .emit PRECISION_DEFAULT;
+parameter_declaration_prec
+ precision .and space;
+parameter_declaration_rest
+ parameter_declarator .or parameter_type_specifier;
+
+/*
+ * <parameter_qualifier> ::= "in"
+ * | "out"
+ * | "inout"
+ * | ""
+ */
+parameter_qualifier
+ parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN;
+parameter_qualifier_1
+ parameter_qualifier_2 .and space;
+parameter_qualifier_2
+ "in" .emit PARAM_QUALIFIER_IN .or
+ "out" .emit PARAM_QUALIFIER_OUT .or
+ "inout" .emit PARAM_QUALIFIER_INOUT;
+
+/*
+ * <parameter_type_specifier> ::= <type_specifier>
+ * | <type_specifier> "[" <constant_expression> "]"
+ */
+parameter_type_specifier
+ parameter_type_specifier_1 .and .true .emit '\0' .and parameter_type_specifier_2;
+parameter_type_specifier_1
+ type_specifier_nospace .or type_specifier_space;
+parameter_type_specifier_2
+ parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or
+ .true .emit PARAMETER_ARRAY_NOT_PRESENT;
+parameter_type_specifier_3
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <init_declarator_list> ::= <single_declaration>
+ * | <init_declarator_list> "," <identifier>
+ * | <init_declarator_list> "," <identifier> "[" "]"
+ * | <init_declarator_list> "," <identifier> "[" <constant_expression> "]"
+ * | <init_declarator_list> "," <identifier> "=" <initializer>
+ */
+init_declarator_list
+ single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and
+ .true .emit DECLARATOR_NONE;
+init_declarator_list_1
+ comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2;
+init_declarator_list_2
+ init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE;
+init_declarator_list_3
+ equals .and initializer .emit VARIABLE_INITIALIZER;
+init_declarator_list_4
+ lbracket .and init_declarator_list_5 .and rbracket;
+init_declarator_list_5
+ constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;
+
+/*
+ * <single_declaration> ::= <fully_specified_type>
+ * | <fully_specified_type> <identifier>
+ * | <fully_specified_type> <identifier> "[" "]"
+ * | <fully_specified_type> <identifier> "[" <constant_expression> "]"
+ * | <fully_specified_type> <identifier> "=" <initializer>
+ */
+single_declaration
+ single_declaration_nospace .or single_declaration_space;
+single_declaration_space
+ fully_specified_type_space .and single_declaration_space_1;
+single_declaration_nospace
+ fully_specified_type_nospace .and single_declaration_nospace_1;
+single_declaration_space_1
+ single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;
+single_declaration_nospace_1
+ single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;
+single_declaration_space_2
+ space .and identifier .and single_declaration_3;
+single_declaration_nospace_2
+ identifier .and single_declaration_3;
+single_declaration_3
+ single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE;
+single_declaration_4
+ equals .and initializer .emit VARIABLE_INITIALIZER;
+single_declaration_5
+ lbracket .and single_declaration_6 .and rbracket;
+single_declaration_6
+ constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;
+
+/*
+ * <fully_specified_type> ::= <opt_invariant> <opt_centroid> <opt_qualifer> <opt_precision> <type_specifier>
+ *
+ * Example: "invariant varying highp vec3"
+ */
+fully_specified_type_space
+ fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_space;
+fully_specified_type_nospace
+ fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_nospace;
+fully_specified_type_optinvariant
+ fully_specified_type_invariant .or .true .emit TYPE_VARIANT;
+fully_specified_type_invariant
+ invariant_qualifier .and space;
+fully_specified_type_optcentroid
+ fully_specified_type_centroid .or .true .emit TYPE_CENTER;
+fully_specified_type_centroid
+ centroid_qualifier .and space;
+fully_specified_type_optqual
+ fully_specified_type_qual .or .true .emit TYPE_QUALIFIER_NONE;
+fully_specified_type_qual
+ type_qualifier .and space;
+fully_specified_type_optprec
+ fully_specified_type_prec .or .true .emit PRECISION_DEFAULT;
+fully_specified_type_prec
+ precision .and space;
+
+/*
+ * <invariant_qualifier> ::= "invariant"
+ */
+invariant_qualifier
+ "invariant" .emit TYPE_INVARIANT;
+
+centroid_qualifier
+ "centroid" .emit TYPE_CENTROID;
+
+
+/*
+ * <type_qualifier> ::= "const"
+ * | "attribute" // Vertex only.
+ * | "varying"
+ * | "uniform"
+ * | "__fixed_output"
+ * | "__fixed_input"
+ *
+ * note: this is an extension to the standard language specification,
+ * normally slang disallows __fixed_output and __fixed_input type qualifiers
+ */
+type_qualifier
+ "const" .emit TYPE_QUALIFIER_CONST .or
+ .if (shader_type == 2) "attribute" .emit TYPE_QUALIFIER_ATTRIBUTE .or
+ "varying" .emit TYPE_QUALIFIER_VARYING .or
+ "uniform" .emit TYPE_QUALIFIER_UNIFORM .or
+ .if (parsing_builtin != 0) "__fixed_output" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or
+ .if (parsing_builtin != 0) "__fixed_input" .emit TYPE_QUALIFIER_FIXEDINPUT;
+
+/*
+ * <type_specifier_nonarray> ::= "void"
+ * | "float"
+ * | "int"
+ * | "bool"
+ * | "vec2"
+ * | "vec3"
+ * | "vec4"
+ * | "bvec2"
+ * | "bvec3"
+ * | "bvec4"
+ * | "ivec2"
+ * | "ivec3"
+ * | "ivec4"
+ * | "mat2"
+ * | "mat3"
+ * | "mat4"
+ * | "mat2x3"
+ * | "mat3x2"
+ * | "mat2x4"
+ * | "mat4x2"
+ * | "mat3x4"
+ * | "mat4x3"
+ * | "sampler1D"
+ * | "sampler2D"
+ * | "sampler3D"
+ * | "samplerCube"
+ * | "sampler1DShadow"
+ * | "sampler2DShadow"
+ * | "sampler2DRect"
+ * | "sampler2DRectShadow"
+ * | <struct_specifier>
+ * | <type_name>
+ */
+type_specifier_nonarray_space
+ "void" .emit TYPE_SPECIFIER_VOID .or
+ "float" .emit TYPE_SPECIFIER_FLOAT .or
+ "int" .emit TYPE_SPECIFIER_INT .or
+ "bool" .emit TYPE_SPECIFIER_BOOL .or
+ "vec2" .emit TYPE_SPECIFIER_VEC2 .or
+ "vec3" .emit TYPE_SPECIFIER_VEC3 .or
+ "vec4" .emit TYPE_SPECIFIER_VEC4 .or
+ "bvec2" .emit TYPE_SPECIFIER_BVEC2 .or
+ "bvec3" .emit TYPE_SPECIFIER_BVEC3 .or
+ "bvec4" .emit TYPE_SPECIFIER_BVEC4 .or
+ "ivec2" .emit TYPE_SPECIFIER_IVEC2 .or
+ "ivec3" .emit TYPE_SPECIFIER_IVEC3 .or
+ "ivec4" .emit TYPE_SPECIFIER_IVEC4 .or
+ "mat2" .emit TYPE_SPECIFIER_MAT2 .or
+ "mat3" .emit TYPE_SPECIFIER_MAT3 .or
+ "mat4" .emit TYPE_SPECIFIER_MAT4 .or
+ "mat2x3" .emit TYPE_SPECIFIER_MAT23 .or
+ "mat3x2" .emit TYPE_SPECIFIER_MAT32 .or
+ "mat2x4" .emit TYPE_SPECIFIER_MAT24 .or
+ "mat4x2" .emit TYPE_SPECIFIER_MAT42 .or
+ "mat3x4" .emit TYPE_SPECIFIER_MAT34 .or
+ "mat4x3" .emit TYPE_SPECIFIER_MAT43 .or
+ "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or
+ "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or
+ "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or
+ "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or
+ "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or
+ "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or
+ "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or
+ "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW .or
+ type_name .emit TYPE_SPECIFIER_TYPENAME;
+type_specifier_nonarray_nospace
+ struct_specifier .emit TYPE_SPECIFIER_STRUCT;
+type_specifier_nonarray
+ type_specifier_nonarray_nospace .or type_specifier_nonarray_space;
+
+/*
+ * <type_specifier> ::= <type_specifier_nonarray>
+ * | <type_specifier_nonarray> "[" <constant_expression> "]"
+ */
+type_specifier_space
+ type_specifier_nonarray_space .and .true .emit TYPE_SPECIFIER_NONARRAY;
+type_specifier_nospace
+ type_specifier_nospace_array .or type_specifier_nospace_1;
+type_specifier_nospace_1
+ type_specifier_nonarray_nospace .and .true .emit TYPE_SPECIFIER_NONARRAY;
+type_specifier_nospace_array
+ type_specifier_nonarray .and lbracket .emit TYPE_SPECIFIER_ARRAY .and constant_expression .and rbracket;
+
+/*
+ * <struct_specifier> ::= "struct" <identifier> "{" <struct_declaration_list> "}"
+ * | "struct" "{" <struct_declaration_list> "}"
+ */
+struct_specifier
+ "struct" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and
+ struct_declaration_list .and rbrace .emit FIELD_NONE;
+struct_specifier_1
+ struct_specifier_2 .or .true .emit '\0';
+struct_specifier_2
+ space .and identifier;
+
+/*
+ * <struct_declaration_list> ::= <struct_declaration>
+ * | <struct_declaration_list> <struct_declaration>
+ */
+struct_declaration_list
+ struct_declaration .and .loop struct_declaration .emit FIELD_NEXT;
+
+/*
+ * <struct_declaration> ::= <type_specifier> <struct_declarator_list> ";"
+ */
+struct_declaration
+ struct_declaration_nospace .or struct_declaration_space;
+struct_declaration_space
+ type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE;
+struct_declaration_nospace
+ type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE;
+
+/*
+ * <struct_declarator_list> ::= <struct_declarator>
+ * | <struct_declarator_list> "," <struct_declarator>
+ */
+struct_declarator_list
+ struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT;
+struct_declarator_list_1
+ comma .and struct_declarator;
+
+/*
+ * <struct_declarator> ::= <identifier>
+ * | <identifier> "[" <constant_expression> "]"
+ */
+struct_declarator
+ identifier .and struct_declarator_1;
+struct_declarator_1
+ struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE;
+struct_declarator_2
+ lbracket .and constant_expression .and rbracket;
+
+/*
+ * <initializer> ::= <assignment_expression>
+ */
+initializer
+ assignment_expression .and .true .emit OP_END;
+
+/*
+ * <declaration_statement> ::= <declaration>
+ */
+declaration_statement
+ declaration;
+
+/*
+ * <statement> ::= <compound_statement>
+ * | <simple_statement>
+ */
+statement
+ compound_statement .or simple_statement;
+statement_space
+ compound_statement .or statement_space_1;
+statement_space_1
+ space .and simple_statement;
+
+/*
+ * <simple_statement> ::= <__asm_statement>
+ * | <selection_statement>
+ * | <iteration_statement>
+ * | <jump_statement>
+ * | <expression_statement>
+ * | <declaration_statement>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows use of __asm statements
+ */
+simple_statement
+ .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or
+ selection_statement .or
+ iteration_statement .or
+ precision_stmt .emit OP_PRECISION .or
+ jump_statement .or
+ expression_statement .emit OP_EXPRESSION .or
+ declaration_statement .emit OP_DECLARE;
+
+/*
+ * <compound_statement> ::= "{" "}"
+ * | "{" <statement_list> "}"
+ */
+compound_statement
+ compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END;
+compound_statement_1
+ compound_statement_2 .or compound_statement_3;
+compound_statement_2
+ lbrace .and rbrace;
+compound_statement_3
+ lbrace .and statement_list .and rbrace;
+
+/*
+ * <compound_statement_no_new_scope> ::= "{" "}"
+ * | "{" <statement_list> "}"
+ */
+compound_statement_no_new_scope
+ compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END;
+compound_statement_no_new_scope_1
+ compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3;
+compound_statement_no_new_scope_2
+ lbrace .and rbrace;
+compound_statement_no_new_scope_3
+ lbrace .and statement_list .and rbrace;
+
+
+/*
+ * <statement_list> ::= <statement>
+ * | <statement_list> <statement>
+ */
+statement_list
+ statement .and .loop statement;
+
+/*
+ * <expression_statement> ::= ";"
+ * | <expression> ";"
+ */
+expression_statement
+ expression_statement_1 .or expression_statement_2;
+expression_statement_1
+ semicolon .emit OP_PUSH_VOID .emit OP_END;
+expression_statement_2
+ expression .and semicolon .emit OP_END;
+
+/*
+ * <selection_statement> ::= "if" "(" <expression> ")" <selection_rest_statement>
+ */
+selection_statement
+ "if" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and
+ rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement;
+
+/*
+ * <selection_rest_statement> ::= <statement> "else" <statement>
+ * | <statement>
+ */
+selection_rest_statement
+ statement .and selection_rest_statement_1;
+selection_rest_statement_1
+ selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END;
+selection_rest_statement_2
+ "else" .and optional_space .and statement;
+
+/*
+ * <condition> ::= <expression>
+ * | <fully_specified_type> <identifier> "=" <initializer>
+ *
+ * note: if <condition_1> is executed, the emit format must
+ * match <declaration> emit format
+ */
+condition
+ condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or
+ condition_3 .emit OP_EXPRESSION;
+condition_1
+ condition_1_nospace .or condition_1_space;
+condition_1_nospace
+ fully_specified_type_nospace .and condition_2;
+condition_1_space
+ fully_specified_type_space .and space .and condition_2;
+condition_2
+ identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and
+ initializer .and .true .emit DECLARATOR_NONE;
+condition_3
+ expression .and .true .emit OP_END;
+
+/*
+ * <iteration_statement> ::= "while" "(" <condition> ")" <statement>
+ * | "do" <statement> "while" "(" <expression> ")" ";"
+ * | "for" "(" <for_init_statement> <for_rest_statement> ")" <statement>
+ */
+iteration_statement
+ iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3;
+iteration_statement_1
+ "while" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and
+ rparen .error RPAREN_EXPECTED .and statement;
+iteration_statement_2
+ "do" .emit OP_DO .and statement_space .and "while" .and lparen .error LPAREN_EXPECTED .and
+ expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon;
+iteration_statement_3
+ "for" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and
+ for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement;
+
+/*
+ * <for_init_statement> ::= <expression_statement>
+ * | <declaration_statement>
+ */
+for_init_statement
+ expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE;
+
+/*
+ * <conditionopt> ::= <condition>
+ * | ""
+ *
+ * note: <conditionopt> is used only by "for" statement.
+ * if <condition> is ommitted, parser simulates default behaviour,
+ * that is simulates "true" expression
+ */
+conditionopt
+ condition .or
+ .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\0' .emit OP_END;
+
+/*
+ * <for_rest_statement> ::= <conditionopt> ";"
+ * | <conditionopt> ";" <expression>
+ */
+for_rest_statement
+ conditionopt .and semicolon .and for_rest_statement_1;
+for_rest_statement_1
+ for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END;
+for_rest_statement_2
+ expression .and .true .emit OP_END;
+
+/*
+ * <jump_statement> ::= "continue" ";"
+ * | "break" ";"
+ * | "return" ";"
+ * | "return" <expression> ";"
+ * | "discard" ";" // Fragment shader only.
+ */
+jump_statement
+ jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or
+ .if (shader_type == 1) jump_statement_5;
+jump_statement_1
+ "continue" .and semicolon .emit OP_CONTINUE;
+jump_statement_2
+ "break" .and semicolon .emit OP_BREAK;
+jump_statement_3
+ "return" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END;
+jump_statement_4
+ "return" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END;
+jump_statement_5
+ "discard" .and semicolon .emit OP_DISCARD;
+
+/*
+ * <__asm_statement> ::= "__asm" <identifier> <asm_arguments> ";"
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+__asm_statement
+ "__asm" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END;
+
+/*
+ * <asm_arguments> ::= <asm_argument>
+ * | <asm_arguments> "," <asm_argument>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+asm_arguments
+ asm_argument .and .true .emit OP_END .and .loop asm_arguments_1;
+asm_arguments_1
+ comma .and asm_argument .and .true .emit OP_END;
+
+/*
+ * <asm_argument> ::= <variable_identifier>
+ * | <floatconstant>
+ *
+ * note: this is an extension to the standard language specification.
+ * normally slang disallows __asm statements
+ */
+asm_argument
+ var_with_field .or
+ variable_identifier .or
+ floatconstant;
+
+var_with_field
+ variable_identifier .and dot .and field_selection .emit OP_FIELD;
+
+
+/*
+ * <translation_unit> ::= <external_declaration>
+ * | <translation_unit> <external_declaration>
+ */
+translation_unit
+ optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and
+ .loop external_declaration .and optional_space .and
+ '\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;
+
+
+/*
+ * <external_declaration> ::= <function_definition>
+ * | <declaration>
+ */
+external_declaration
+ precision_stmt .emit DEFAULT_PRECISION .or
+ function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or
+ invariant_stmt .emit INVARIANT_STMT .or
+ declaration .emit EXTERNAL_DECLARATION;
+
+
+/*
+ * <precision_stmt> ::= "precision" <precision> <prectype>
+ */
+precision_stmt
+ "precision" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;
+
+/*
+ * <precision> ::= "lowp"
+ * | "mediump"
+ * | "highp"
+ */
+precision
+ "lowp" .emit PRECISION_LOW .or
+ "mediump" .emit PRECISION_MEDIUM .or
+ "highp" .emit PRECISION_HIGH;
+
+/*
+ * <prectype> ::= "int"
+ * | "float"
+ * | "a sampler type"
+ */
+prectype
+ "int" .emit TYPE_SPECIFIER_INT .or
+ "float" .emit TYPE_SPECIFIER_FLOAT .or
+ "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or
+ "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or
+ "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or
+ "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or
+ "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or
+ "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or
+ "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or
+ "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;
+
+
+/*
+ * <invariant_stmt> ::= "invariant" identifier;
+ */
+invariant_stmt
+ "invariant" .and space .and identifier .and semicolon;
+
+
+/*
+ * <function_definition> :: <function_prototype> <compound_statement_no_new_scope>
+ */
+function_definition
+ function_prototype .and compound_statement_no_new_scope;
+
+
+
+/*
+ * helper rules, not part of the official language syntax
+ */
+
+digit_oct
+ '0'-'7';
+
+digit_dec
+ '0'-'9';
+
+digit_hex
+ '0'-'9' .or 'A'-'F' .or 'a'-'f';
+
+id_character_first
+ 'a'-'z' .or 'A'-'Z' .or '_';
+
+id_character_next
+ id_character_first .or digit_dec;
+
+identifier
+ id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\0';
+
+float
+ float_1 .or float_2 .or float_3;
+float_1
+ float_fractional_constant .and float_optional_exponent_part .and optional_f_suffix;
+float_2
+ float_digit_sequence .and .true .emit '\0' .and float_exponent_part .and optional_f_suffix;
+float_3
+ float_digit_sequence .and .true .emit '\0' .and 'f' .emit '\0';
+
+float_fractional_constant
+ float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;
+float_fractional_constant_1
+ float_digit_sequence .and '.' .and float_digit_sequence;
+float_fractional_constant_2
+ float_digit_sequence .and '.' .and .true .emit '\0';
+float_fractional_constant_3
+ '.' .emit '\0' .and float_digit_sequence;
+
+float_optional_exponent_part
+ float_exponent_part .or .true .emit '\0';
+
+float_digit_sequence
+ digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\0';
+
+float_exponent_part
+ float_exponent_part_1 .or float_exponent_part_2;
+float_exponent_part_1
+ 'e' .and float_optional_sign .and float_digit_sequence;
+float_exponent_part_2
+ 'E' .and float_optional_sign .and float_digit_sequence;
+
+float_optional_sign
+ float_sign .or .true;
+
+float_sign
+ '+' .or '-' .emit '-';
+
+optional_f_suffix
+ 'f' .or .true;
+
+
+integer
+ integer_hex .or integer_oct .or integer_dec;
+
+integer_hex
+ '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and
+ .true .emit '\0';
+integer_hex_1
+ 'x' .or 'X';
+
+integer_oct
+ '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\0';
+
+integer_dec
+ digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0';
+
+boolean
+ "true" .emit 2 .emit '1' .emit '\0' .or
+ "false" .emit 2 .emit '0' .emit '\0';
+
+type_name
+ identifier;
+
+field_selection
+ identifier;
+
+floatconstant
+ float .emit OP_PUSH_FLOAT;
+
+intconstant
+ integer .emit OP_PUSH_INT;
+
+boolconstant
+ boolean .emit OP_PUSH_BOOL;
+
+optional_space
+ .loop single_space;
+
+space
+ single_space .and .loop single_space;
+
+single_space
+ white_char .or c_style_comment_block .or cpp_style_comment_block;
+
+white_char
+ ' ' .or '\t' .or new_line .or '\v' .or '\f';
+
+new_line
+ cr_lf .or lf_cr .or '\n' .or '\r';
+
+cr_lf
+ '\r' .and '\n';
+
+lf_cr
+ '\n' .and '\r';
+
+c_style_comment_block
+ '/' .and '*' .and c_style_comment_rest;
+
+c_style_comment_rest
+ .loop c_style_comment_char_no_star .and c_style_comment_rest_1;
+c_style_comment_rest_1
+ c_style_comment_end .or c_style_comment_rest_2;
+c_style_comment_rest_2
+ '*' .and c_style_comment_rest;
+
+c_style_comment_char_no_star
+ '\x2B'-'\xFF' .or '\x01'-'\x29';
+
+c_style_comment_end
+ '*' .and '/';
+
+cpp_style_comment_block
+ '/' .and '/' .and cpp_style_comment_block_1;
+cpp_style_comment_block_1
+ cpp_style_comment_block_2 .or cpp_style_comment_block_3;
+cpp_style_comment_block_2
+ .loop cpp_style_comment_char .and new_line;
+cpp_style_comment_block_3
+ .loop cpp_style_comment_char;
+
+cpp_style_comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+/* lexical rules */
+
+/*ampersand
+ optional_space .and '&' .and optional_space;*/
+
+ampersandampersand
+ optional_space .and '&' .and '&' .and optional_space;
+
+/*ampersandequals
+ optional_space .and '&' .and '=' .and optional_space;*/
+
+/*bar
+ optional_space .and '|' .and optional_space;*/
+
+barbar
+ optional_space .and '|' .and '|' .and optional_space;
+
+/*barequals
+ optional_space .and '|' .and '=' .and optional_space;*/
+
+bang
+ optional_space .and '!' .and optional_space;
+
+bangequals
+ optional_space .and '!' .and '=' .and optional_space;
+
+/*caret
+ optional_space .and '^' .and optional_space;*/
+
+caretcaret
+ optional_space .and '^' .and '^' .and optional_space;
+
+/*caretequals
+ optional_space .and '^' .and '=' .and optional_space;*/
+
+colon
+ optional_space .and ':' .and optional_space;
+
+comma
+ optional_space .and ',' .and optional_space;
+
+dot
+ optional_space .and '.' .and optional_space;
+
+equals
+ optional_space .and '=' .and optional_space;
+
+equalsequals
+ optional_space .and '=' .and '=' .and optional_space;
+
+greater
+ optional_space .and '>' .and optional_space;
+
+greaterequals
+ optional_space .and '>' .and '=' .and optional_space;
+
+/*greatergreater
+ optional_space .and '>' .and '>' .and optional_space;*/
+
+/*greatergreaterequals
+ optional_space .and '>' .and '>' .and '=' .and optional_space;*/
+
+lbrace
+ optional_space .and '{' .and optional_space;
+
+lbracket
+ optional_space .and '[' .and optional_space;
+
+less
+ optional_space .and '<' .and optional_space;
+
+lessequals
+ optional_space .and '<' .and '=' .and optional_space;
+
+/*lessless
+ optional_space .and '<' .and '<' .and optional_space;*/
+
+/*lesslessequals
+ optional_space .and '<' .and '<' .and '=' .and optional_space;*/
+
+lparen
+ optional_space .and '(' .and optional_space;
+
+minus
+ optional_space .and '-' .and optional_space;
+
+minusequals
+ optional_space .and '-' .and '=' .and optional_space;
+
+minusminus
+ optional_space .and '-' .and '-' .and optional_space;
+
+/*percent
+ optional_space .and '%' .and optional_space;*/
+
+/*percentequals
+ optional_space .and '%' .and '=' .and optional_space;*/
+
+plus
+ optional_space .and '+' .and optional_space;
+
+plusequals
+ optional_space .and '+' .and '=' .and optional_space;
+
+plusplus
+ optional_space .and '+' .and '+' .and optional_space;
+
+question
+ optional_space .and '?' .and optional_space;
+
+rbrace
+ optional_space .and '}' .and optional_space;
+
+rbracket
+ optional_space .and ']' .and optional_space;
+
+rparen
+ optional_space .and ')' .and optional_space;
+
+semicolon
+ optional_space .and ';' .and optional_space;
+
+slash
+ optional_space .and '/' .and optional_space;
+
+slashequals
+ optional_space .and '/' .and '=' .and optional_space;
+
+star
+ optional_space .and '*' .and optional_space;
+
+starequals
+ optional_space .and '*' .and '=' .and optional_space;
+
+/*tilde
+ optional_space .and '~' .and optional_space;*/
+
+/* string rules - these are used internally by the parser when parsing quoted strings */
+
+.string string_lexer;
+
+string_lexer
+ lex_first_identifier_character .and .loop lex_next_identifier_character;
+
+lex_first_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '_';
+
+lex_next_identifier_character
+ 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';
+
+/* error rules - these are used by error messages */
+
+err_token
+ '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or
+ '-' .or '+' .or '=' .or '|' .or '\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '"' .or
+ '\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier;
+
+err_identifier
+ id_character_first .and .loop id_character_next;
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_shader_syn.h b/mesalib/src/mesa/shader/slang/library/slang_shader_syn.h
new file mode 100644
index 000000000..6a382970e
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_shader_syn.h
@@ -0,0 +1,866 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */
+
+".syntax translation_unit;\n"
+".emtcode REVISION 5\n"
+".emtcode EXTERNAL_NULL 0\n"
+".emtcode EXTERNAL_FUNCTION_DEFINITION 1\n"
+".emtcode EXTERNAL_DECLARATION 2\n"
+".emtcode DEFAULT_PRECISION 3\n"
+".emtcode INVARIANT_STMT 4\n"
+".emtcode PRECISION_DEFAULT 0\n"
+".emtcode PRECISION_LOW 1\n"
+".emtcode PRECISION_MEDIUM 2\n"
+".emtcode PRECISION_HIGH 3\n"
+".emtcode DECLARATION_FUNCTION_PROTOTYPE 1\n"
+".emtcode DECLARATION_INIT_DECLARATOR_LIST 2\n"
+".emtcode FUNCTION_ORDINARY 0\n"
+".emtcode FUNCTION_CONSTRUCTOR 1\n"
+".emtcode FUNCTION_OPERATOR 2\n"
+".emtcode FUNCTION_CALL_NONARRAY 0\n"
+".emtcode FUNCTION_CALL_ARRAY 1\n"
+".emtcode OPERATOR_ADDASSIGN 1\n"
+".emtcode OPERATOR_SUBASSIGN 2\n"
+".emtcode OPERATOR_MULASSIGN 3\n"
+".emtcode OPERATOR_DIVASSIGN 4\n"
+".emtcode OPERATOR_LOGICALXOR 11\n"
+".emtcode OPERATOR_LESS 15\n"
+".emtcode OPERATOR_GREATER 16\n"
+".emtcode OPERATOR_LESSEQUAL 17\n"
+".emtcode OPERATOR_GREATEREQUAL 18\n"
+".emtcode OPERATOR_MULTIPLY 21\n"
+".emtcode OPERATOR_DIVIDE 22\n"
+".emtcode OPERATOR_INCREMENT 24\n"
+".emtcode OPERATOR_DECREMENT 25\n"
+".emtcode OPERATOR_PLUS 26\n"
+".emtcode OPERATOR_MINUS 27\n"
+".emtcode OPERATOR_NOT 29\n"
+".emtcode DECLARATOR_NONE 0\n"
+".emtcode DECLARATOR_NEXT 1\n"
+".emtcode VARIABLE_NONE 0\n"
+".emtcode VARIABLE_IDENTIFIER 1\n"
+".emtcode VARIABLE_INITIALIZER 2\n"
+".emtcode VARIABLE_ARRAY_EXPLICIT 3\n"
+".emtcode VARIABLE_ARRAY_UNKNOWN 4\n"
+".emtcode TYPE_QUALIFIER_NONE 0\n"
+".emtcode TYPE_QUALIFIER_CONST 1\n"
+".emtcode TYPE_QUALIFIER_ATTRIBUTE 2\n"
+".emtcode TYPE_QUALIFIER_VARYING 3\n"
+".emtcode TYPE_QUALIFIER_UNIFORM 4\n"
+".emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5\n"
+".emtcode TYPE_QUALIFIER_FIXEDINPUT 6\n"
+".emtcode TYPE_VARIANT 90\n"
+".emtcode TYPE_INVARIANT 91\n"
+".emtcode TYPE_CENTER 95\n"
+".emtcode TYPE_CENTROID 96\n"
+".emtcode TYPE_SPECIFIER_VOID 0\n"
+".emtcode TYPE_SPECIFIER_BOOL 1\n"
+".emtcode TYPE_SPECIFIER_BVEC2 2\n"
+".emtcode TYPE_SPECIFIER_BVEC3 3\n"
+".emtcode TYPE_SPECIFIER_BVEC4 4\n"
+".emtcode TYPE_SPECIFIER_INT 5\n"
+".emtcode TYPE_SPECIFIER_IVEC2 6\n"
+".emtcode TYPE_SPECIFIER_IVEC3 7\n"
+".emtcode TYPE_SPECIFIER_IVEC4 8\n"
+".emtcode TYPE_SPECIFIER_FLOAT 9\n"
+".emtcode TYPE_SPECIFIER_VEC2 10\n"
+".emtcode TYPE_SPECIFIER_VEC3 11\n"
+".emtcode TYPE_SPECIFIER_VEC4 12\n"
+".emtcode TYPE_SPECIFIER_MAT2 13\n"
+".emtcode TYPE_SPECIFIER_MAT3 14\n"
+".emtcode TYPE_SPECIFIER_MAT4 15\n"
+".emtcode TYPE_SPECIFIER_SAMPLER1D 16\n"
+".emtcode TYPE_SPECIFIER_SAMPLER2D 17\n"
+".emtcode TYPE_SPECIFIER_SAMPLER3D 18\n"
+".emtcode TYPE_SPECIFIER_SAMPLERCUBE 19\n"
+".emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20\n"
+".emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21\n"
+".emtcode TYPE_SPECIFIER_SAMPLER2DRECT 22\n"
+".emtcode TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23\n"
+".emtcode TYPE_SPECIFIER_STRUCT 24\n"
+".emtcode TYPE_SPECIFIER_TYPENAME 25\n"
+".emtcode TYPE_SPECIFIER_MAT23 26\n"
+".emtcode TYPE_SPECIFIER_MAT32 27\n"
+".emtcode TYPE_SPECIFIER_MAT24 28\n"
+".emtcode TYPE_SPECIFIER_MAT42 29\n"
+".emtcode TYPE_SPECIFIER_MAT34 30\n"
+".emtcode TYPE_SPECIFIER_MAT43 31\n"
+".emtcode TYPE_SPECIFIER_NONARRAY 0\n"
+".emtcode TYPE_SPECIFIER_ARRAY 1\n"
+".emtcode FIELD_NONE 0\n"
+".emtcode FIELD_NEXT 1\n"
+".emtcode FIELD_ARRAY 2\n"
+".emtcode OP_END 0\n"
+".emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1\n"
+".emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2\n"
+".emtcode OP_DECLARE 3\n"
+".emtcode OP_ASM 4\n"
+".emtcode OP_BREAK 5\n"
+".emtcode OP_CONTINUE 6\n"
+".emtcode OP_DISCARD 7\n"
+".emtcode OP_RETURN 8\n"
+".emtcode OP_EXPRESSION 9\n"
+".emtcode OP_IF 10\n"
+".emtcode OP_WHILE 11\n"
+".emtcode OP_DO 12\n"
+".emtcode OP_FOR 13\n"
+".emtcode OP_PUSH_VOID 14\n"
+".emtcode OP_PUSH_BOOL 15\n"
+".emtcode OP_PUSH_INT 16\n"
+".emtcode OP_PUSH_FLOAT 17\n"
+".emtcode OP_PUSH_IDENTIFIER 18\n"
+".emtcode OP_SEQUENCE 19\n"
+".emtcode OP_ASSIGN 20\n"
+".emtcode OP_ADDASSIGN 21\n"
+".emtcode OP_SUBASSIGN 22\n"
+".emtcode OP_MULASSIGN 23\n"
+".emtcode OP_DIVASSIGN 24\n"
+".emtcode OP_SELECT 31\n"
+".emtcode OP_LOGICALOR 32\n"
+".emtcode OP_LOGICALXOR 33\n"
+".emtcode OP_LOGICALAND 34\n"
+".emtcode OP_EQUAL 38\n"
+".emtcode OP_NOTEQUAL 39\n"
+".emtcode OP_LESS 40\n"
+".emtcode OP_GREATER 41\n"
+".emtcode OP_LESSEQUAL 42\n"
+".emtcode OP_GREATEREQUAL 43\n"
+".emtcode OP_ADD 46\n"
+".emtcode OP_SUBTRACT 47\n"
+".emtcode OP_MULTIPLY 48\n"
+".emtcode OP_DIVIDE 49\n"
+".emtcode OP_PREINCREMENT 51\n"
+".emtcode OP_PREDECREMENT 52\n"
+".emtcode OP_PLUS 53\n"
+".emtcode OP_MINUS 54\n"
+".emtcode OP_NOT 56\n"
+".emtcode OP_SUBSCRIPT 57\n"
+".emtcode OP_CALL 58\n"
+".emtcode OP_FIELD 59\n"
+".emtcode OP_POSTINCREMENT 60\n"
+".emtcode OP_POSTDECREMENT 61\n"
+".emtcode OP_PRECISION 62\n"
+".emtcode OP_METHOD 63\n"
+".emtcode PARAM_QUALIFIER_IN 0\n"
+".emtcode PARAM_QUALIFIER_OUT 1\n"
+".emtcode PARAM_QUALIFIER_INOUT 2\n"
+".emtcode PARAMETER_NONE 0\n"
+".emtcode PARAMETER_NEXT 1\n"
+".emtcode PARAMETER_ARRAY_NOT_PRESENT 0\n"
+".emtcode PARAMETER_ARRAY_PRESENT 1\n"
+".errtext INVALID_EXTERNAL_DECLARATION \"2001: Syntax error.\"\n"
+".errtext INVALID_OPERATOR_OVERRIDE \"2002: Invalid operator override.\"\n"
+".errtext LBRACE_EXPECTED \"2003: '{' expected but '$err_token$' found.\"\n"
+".errtext LPAREN_EXPECTED \"2004: '(' expected but '$err_token$' found.\"\n"
+".errtext RPAREN_EXPECTED \"2005: ')' expected but '$err_token$' found.\"\n"
+".errtext INVALID_PRECISION \"2006: Invalid precision specifier '$err_token$'.\"\n"
+".errtext INVALID_PRECISION_TYPE \"2007: Invalid precision type '$err_token$'.\"\n"
+".regbyte parsing_builtin 0\n"
+".regbyte shader_type 0\n"
+"variable_identifier\n"
+" identifier .emit OP_PUSH_IDENTIFIER;\n"
+"primary_expression\n"
+" floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1;\n"
+"primary_expression_1\n"
+" lparen .and expression .and rparen;\n"
+"postfix_expression\n"
+" postfix_expression_1 .and .loop postfix_expression_2;\n"
+"postfix_expression_1\n"
+" function_call .or primary_expression;\n"
+"postfix_expression_2\n"
+" postfix_expression_3 .or postfix_expression_4 .or\n"
+" plusplus .emit OP_POSTINCREMENT .or\n"
+" minusminus .emit OP_POSTDECREMENT;\n"
+"postfix_expression_3\n"
+" lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT;\n"
+"postfix_expression_4\n"
+" dot .and field_selection .emit OP_FIELD;\n"
+"integer_expression\n"
+" expression;\n"
+"function_call\n"
+" function_call_or_method;\n"
+"function_call_or_method\n"
+" regular_function_call .or method_call;\n"
+"method_call\n"
+" identifier .emit OP_METHOD .and dot .and function_call_generic .and .true .emit OP_END;\n"
+"regular_function_call\n"
+" function_call_generic .emit OP_CALL .and .true .emit OP_END;\n"
+"function_call_generic\n"
+" function_call_generic_1 .or function_call_generic_2;\n"
+"function_call_generic_1\n"
+" function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED;\n"
+"function_call_generic_2\n"
+" function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED;\n"
+"function_call_header_no_parameters\n"
+" function_call_header .and function_call_header_no_parameters_1;\n"
+"function_call_header_no_parameters_1\n"
+" \"void\" .or .true;\n"
+"function_call_header_with_parameters\n"
+" function_call_header .and assignment_expression .and .true .emit OP_END .and\n"
+" .loop function_call_header_with_parameters_1;\n"
+"function_call_header_with_parameters_1\n"
+" comma .and assignment_expression .and .true .emit OP_END;\n"
+"function_call_header\n"
+" function_identifier .and lparen;\n"
+"function_identifier\n"
+" identifier .and function_identifier_opt_array;\n"
+"function_identifier_opt_array\n"
+" function_identifier_array .emit FUNCTION_CALL_ARRAY .or\n"
+" .true .emit FUNCTION_CALL_NONARRAY;\n"
+"function_identifier_array\n"
+" lbracket .and constant_expression .and rbracket;\n"
+"unary_expression\n"
+" postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or\n"
+" unary_expression_4 .or unary_expression_5;\n"
+"unary_expression_1\n"
+" plusplus .and unary_expression .and .true .emit OP_PREINCREMENT;\n"
+"unary_expression_2\n"
+" minusminus .and unary_expression .and .true .emit OP_PREDECREMENT;\n"
+"unary_expression_3\n"
+" plus .and unary_expression .and .true .emit OP_PLUS;\n"
+"unary_expression_4\n"
+" minus .and unary_expression .and .true .emit OP_MINUS;\n"
+"unary_expression_5\n"
+" bang .and unary_expression .and .true .emit OP_NOT;\n"
+"multiplicative_expression\n"
+" unary_expression .and .loop multiplicative_expression_1;\n"
+"multiplicative_expression_1\n"
+" multiplicative_expression_2 .or multiplicative_expression_3;\n"
+"multiplicative_expression_2\n"
+" star .and unary_expression .and .true .emit OP_MULTIPLY;\n"
+"multiplicative_expression_3\n"
+" slash .and unary_expression .and .true .emit OP_DIVIDE;\n"
+"additive_expression\n"
+" multiplicative_expression .and .loop additive_expression_1;\n"
+"additive_expression_1\n"
+" additive_expression_2 .or additive_expression_3;\n"
+"additive_expression_2\n"
+" plus .and multiplicative_expression .and .true .emit OP_ADD;\n"
+"additive_expression_3\n"
+" minus .and multiplicative_expression .and .true .emit OP_SUBTRACT;\n"
+"shift_expression\n"
+" additive_expression;\n"
+"relational_expression\n"
+" shift_expression .and .loop relational_expression_1;\n"
+"relational_expression_1\n"
+" relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or\n"
+" relational_expression_5;\n"
+"relational_expression_2\n"
+" lessequals .and shift_expression .and .true .emit OP_LESSEQUAL;\n"
+"relational_expression_3\n"
+" greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL;\n"
+"relational_expression_4\n"
+" less .and shift_expression .and .true .emit OP_LESS;\n"
+"relational_expression_5\n"
+" greater .and shift_expression .and .true .emit OP_GREATER;\n"
+"equality_expression\n"
+" relational_expression .and .loop equality_expression_1;\n"
+"equality_expression_1\n"
+" equality_expression_2 .or equality_expression_3;\n"
+"equality_expression_2\n"
+" equalsequals .and relational_expression .and .true .emit OP_EQUAL;\n"
+"equality_expression_3\n"
+" bangequals .and relational_expression .and .true .emit OP_NOTEQUAL;\n"
+"and_expression\n"
+" equality_expression;\n"
+"exclusive_or_expression\n"
+" and_expression;\n"
+"inclusive_or_expression\n"
+" exclusive_or_expression;\n"
+"logical_and_expression\n"
+" inclusive_or_expression .and .loop logical_and_expression_1;\n"
+"logical_and_expression_1\n"
+" ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND;\n"
+"logical_xor_expression\n"
+" logical_and_expression .and .loop logical_xor_expression_1;\n"
+"logical_xor_expression_1\n"
+" caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR;\n"
+"logical_or_expression\n"
+" logical_xor_expression .and .loop logical_or_expression_1;\n"
+"logical_or_expression_1\n"
+" barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR;\n"
+"conditional_expression\n"
+" logical_or_expression .and .loop conditional_expression_1;\n"
+"conditional_expression_1\n"
+" question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT;\n"
+"assignment_expression\n"
+" assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or\n"
+" assignment_expression_4 .or assignment_expression_5 .or conditional_expression;\n"
+"assignment_expression_1\n"
+" unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN;\n"
+"assignment_expression_2\n"
+" unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN;\n"
+"assignment_expression_3\n"
+" unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN;\n"
+"assignment_expression_4\n"
+" unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN;\n"
+"assignment_expression_5\n"
+" unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN;\n"
+"expression\n"
+" assignment_expression .and .loop expression_1;\n"
+"expression_1\n"
+" comma .and assignment_expression .and .true .emit OP_SEQUENCE;\n"
+"constant_expression\n"
+" conditional_expression .and .true .emit OP_END;\n"
+"declaration\n"
+" declaration_1 .or declaration_2;\n"
+"declaration_1\n"
+" function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon;\n"
+"declaration_2\n"
+" init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon;\n"
+"function_prototype\n"
+" function_prototype_1 .or function_prototype_2;\n"
+"function_prototype_1\n"
+" function_header .and \"void\" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;\n"
+"function_prototype_2\n"
+" function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE;\n"
+"function_declarator\n"
+" function_header_with_parameters .or function_header;\n"
+"function_header_with_parameters\n"
+" function_header .and parameter_declaration .and .loop function_header_with_parameters_1;\n"
+"function_header_with_parameters_1\n"
+" comma .and parameter_declaration;\n"
+"function_header\n"
+" function_header_nospace .or function_header_space;\n"
+"function_header_space\n"
+" fully_specified_type_space .and space .and function_decl_identifier .and lparen;\n"
+"function_header_nospace\n"
+" fully_specified_type_nospace .and function_decl_identifier .and lparen;\n"
+"function_decl_identifier\n"
+" .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or\n"
+" .if (parsing_builtin != 0) \"__constructor\" .emit FUNCTION_CONSTRUCTOR .or\n"
+" identifier .emit FUNCTION_ORDINARY;\n"
+"__operator\n"
+" \"__operator\" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE;\n"
+"overriden_operator\n"
+" plusplus .emit OPERATOR_INCREMENT .or\n"
+" plusequals .emit OPERATOR_ADDASSIGN .or\n"
+" plus .emit OPERATOR_PLUS .or\n"
+" minusminus .emit OPERATOR_DECREMENT .or\n"
+" minusequals .emit OPERATOR_SUBASSIGN .or\n"
+" minus .emit OPERATOR_MINUS .or\n"
+" bang .emit OPERATOR_NOT .or\n"
+" starequals .emit OPERATOR_MULASSIGN .or\n"
+" star .emit OPERATOR_MULTIPLY .or\n"
+" slashequals .emit OPERATOR_DIVASSIGN .or\n"
+" slash .emit OPERATOR_DIVIDE .or\n"
+" lessequals .emit OPERATOR_LESSEQUAL .or\n"
+" \n"
+" \n"
+" less .emit OPERATOR_LESS .or\n"
+" greaterequals .emit OPERATOR_GREATEREQUAL .or\n"
+" \n"
+" \n"
+" greater .emit OPERATOR_GREATER .or\n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" \n"
+" caretcaret .emit OPERATOR_LOGICALXOR ;\n"
+"parameter_declarator\n"
+" parameter_declarator_nospace .or parameter_declarator_space;\n"
+"parameter_declarator_nospace\n"
+" type_specifier_nospace .and identifier .and parameter_declarator_1;\n"
+"parameter_declarator_space\n"
+" type_specifier_space .and space .and identifier .and parameter_declarator_1;\n"
+"parameter_declarator_1\n"
+" parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or\n"
+" .true .emit PARAMETER_ARRAY_NOT_PRESENT;\n"
+"parameter_declarator_2\n"
+" lbracket .and constant_expression .and rbracket;\n"
+"parameter_declaration\n"
+" parameter_declaration_1 .emit PARAMETER_NEXT;\n"
+"parameter_declaration_1\n"
+" parameter_declaration_2 .or parameter_declaration_3;\n"
+"parameter_declaration_2\n"
+" type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4;\n"
+"parameter_declaration_3\n"
+" parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4;\n"
+"parameter_declaration_4\n"
+" parameter_declaration_optprec .and parameter_declaration_rest;\n"
+"parameter_declaration_optprec\n"
+" parameter_declaration_prec .or .true .emit PRECISION_DEFAULT;\n"
+"parameter_declaration_prec\n"
+" precision .and space;\n"
+"parameter_declaration_rest\n"
+" parameter_declarator .or parameter_type_specifier;\n"
+"parameter_qualifier\n"
+" parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN;\n"
+"parameter_qualifier_1\n"
+" parameter_qualifier_2 .and space;\n"
+"parameter_qualifier_2\n"
+" \"in\" .emit PARAM_QUALIFIER_IN .or\n"
+" \"out\" .emit PARAM_QUALIFIER_OUT .or\n"
+" \"inout\" .emit PARAM_QUALIFIER_INOUT;\n"
+"parameter_type_specifier\n"
+" parameter_type_specifier_1 .and .true .emit '\\0' .and parameter_type_specifier_2;\n"
+"parameter_type_specifier_1\n"
+" type_specifier_nospace .or type_specifier_space;\n"
+"parameter_type_specifier_2\n"
+" parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or\n"
+" .true .emit PARAMETER_ARRAY_NOT_PRESENT;\n"
+"parameter_type_specifier_3\n"
+" lbracket .and constant_expression .and rbracket;\n"
+"init_declarator_list\n"
+" single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and\n"
+" .true .emit DECLARATOR_NONE;\n"
+"init_declarator_list_1\n"
+" comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2;\n"
+"init_declarator_list_2\n"
+" init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE;\n"
+"init_declarator_list_3\n"
+" equals .and initializer .emit VARIABLE_INITIALIZER;\n"
+"init_declarator_list_4\n"
+" lbracket .and init_declarator_list_5 .and rbracket;\n"
+"init_declarator_list_5\n"
+" constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;\n"
+"single_declaration\n"
+" single_declaration_nospace .or single_declaration_space;\n"
+"single_declaration_space\n"
+" fully_specified_type_space .and single_declaration_space_1;\n"
+"single_declaration_nospace\n"
+" fully_specified_type_nospace .and single_declaration_nospace_1;\n"
+"single_declaration_space_1\n"
+" single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;\n"
+"single_declaration_nospace_1\n"
+" single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE;\n"
+"single_declaration_space_2\n"
+" space .and identifier .and single_declaration_3;\n"
+"single_declaration_nospace_2\n"
+" identifier .and single_declaration_3;\n"
+"single_declaration_3\n"
+" single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE;\n"
+"single_declaration_4\n"
+" equals .and initializer .emit VARIABLE_INITIALIZER;\n"
+"single_declaration_5\n"
+" lbracket .and single_declaration_6 .and rbracket;\n"
+"single_declaration_6\n"
+" constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN;\n"
+"fully_specified_type_space\n"
+" fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_space;\n"
+"fully_specified_type_nospace\n"
+" fully_specified_type_optinvariant .and fully_specified_type_optcentroid .and fully_specified_type_optqual .and fully_specified_type_optprec .and type_specifier_nospace;\n"
+"fully_specified_type_optinvariant\n"
+" fully_specified_type_invariant .or .true .emit TYPE_VARIANT;\n"
+"fully_specified_type_invariant\n"
+" invariant_qualifier .and space;\n"
+"fully_specified_type_optcentroid\n"
+" fully_specified_type_centroid .or .true .emit TYPE_CENTER;\n"
+"fully_specified_type_centroid\n"
+" centroid_qualifier .and space;\n"
+"fully_specified_type_optqual\n"
+" fully_specified_type_qual .or .true .emit TYPE_QUALIFIER_NONE;\n"
+"fully_specified_type_qual\n"
+" type_qualifier .and space;\n"
+"fully_specified_type_optprec\n"
+" fully_specified_type_prec .or .true .emit PRECISION_DEFAULT;\n"
+"fully_specified_type_prec\n"
+" precision .and space;\n"
+"invariant_qualifier\n"
+" \"invariant\" .emit TYPE_INVARIANT;\n"
+"centroid_qualifier\n"
+" \"centroid\" .emit TYPE_CENTROID;\n"
+"type_qualifier\n"
+" \"const\" .emit TYPE_QUALIFIER_CONST .or\n"
+" .if (shader_type == 2) \"attribute\" .emit TYPE_QUALIFIER_ATTRIBUTE .or\n"
+" \"varying\" .emit TYPE_QUALIFIER_VARYING .or\n"
+" \"uniform\" .emit TYPE_QUALIFIER_UNIFORM .or\n"
+" .if (parsing_builtin != 0) \"__fixed_output\" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or\n"
+" .if (parsing_builtin != 0) \"__fixed_input\" .emit TYPE_QUALIFIER_FIXEDINPUT;\n"
+"type_specifier_nonarray_space\n"
+" \"void\" .emit TYPE_SPECIFIER_VOID .or\n"
+" \"float\" .emit TYPE_SPECIFIER_FLOAT .or\n"
+" \"int\" .emit TYPE_SPECIFIER_INT .or\n"
+" \"bool\" .emit TYPE_SPECIFIER_BOOL .or\n"
+" \"vec2\" .emit TYPE_SPECIFIER_VEC2 .or\n"
+" \"vec3\" .emit TYPE_SPECIFIER_VEC3 .or\n"
+" \"vec4\" .emit TYPE_SPECIFIER_VEC4 .or\n"
+" \"bvec2\" .emit TYPE_SPECIFIER_BVEC2 .or\n"
+" \"bvec3\" .emit TYPE_SPECIFIER_BVEC3 .or\n"
+" \"bvec4\" .emit TYPE_SPECIFIER_BVEC4 .or\n"
+" \"ivec2\" .emit TYPE_SPECIFIER_IVEC2 .or\n"
+" \"ivec3\" .emit TYPE_SPECIFIER_IVEC3 .or\n"
+" \"ivec4\" .emit TYPE_SPECIFIER_IVEC4 .or\n"
+" \"mat2\" .emit TYPE_SPECIFIER_MAT2 .or\n"
+" \"mat3\" .emit TYPE_SPECIFIER_MAT3 .or\n"
+" \"mat4\" .emit TYPE_SPECIFIER_MAT4 .or\n"
+" \"mat2x3\" .emit TYPE_SPECIFIER_MAT23 .or\n"
+" \"mat3x2\" .emit TYPE_SPECIFIER_MAT32 .or\n"
+" \"mat2x4\" .emit TYPE_SPECIFIER_MAT24 .or\n"
+" \"mat4x2\" .emit TYPE_SPECIFIER_MAT42 .or\n"
+" \"mat3x4\" .emit TYPE_SPECIFIER_MAT34 .or\n"
+" \"mat4x3\" .emit TYPE_SPECIFIER_MAT43 .or\n"
+" \"sampler1D\" .emit TYPE_SPECIFIER_SAMPLER1D .or\n"
+" \"sampler2D\" .emit TYPE_SPECIFIER_SAMPLER2D .or\n"
+" \"sampler3D\" .emit TYPE_SPECIFIER_SAMPLER3D .or\n"
+" \"samplerCube\" .emit TYPE_SPECIFIER_SAMPLERCUBE .or\n"
+" \"sampler1DShadow\" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or\n"
+" \"sampler2DShadow\" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or\n"
+" \"sampler2DRect\" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or\n"
+" \"sampler2DRectShadow\" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW .or\n"
+" type_name .emit TYPE_SPECIFIER_TYPENAME;\n"
+"type_specifier_nonarray_nospace\n"
+" struct_specifier .emit TYPE_SPECIFIER_STRUCT;\n"
+"type_specifier_nonarray\n"
+" type_specifier_nonarray_nospace .or type_specifier_nonarray_space;\n"
+"type_specifier_space\n"
+" type_specifier_nonarray_space .and .true .emit TYPE_SPECIFIER_NONARRAY;\n"
+"type_specifier_nospace\n"
+" type_specifier_nospace_array .or type_specifier_nospace_1;\n"
+"type_specifier_nospace_1\n"
+" type_specifier_nonarray_nospace .and .true .emit TYPE_SPECIFIER_NONARRAY;\n"
+"type_specifier_nospace_array\n"
+" type_specifier_nonarray .and lbracket .emit TYPE_SPECIFIER_ARRAY .and constant_expression .and rbracket;\n"
+"struct_specifier\n"
+" \"struct\" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and\n"
+" struct_declaration_list .and rbrace .emit FIELD_NONE;\n"
+"struct_specifier_1\n"
+" struct_specifier_2 .or .true .emit '\\0';\n"
+"struct_specifier_2\n"
+" space .and identifier;\n"
+"struct_declaration_list\n"
+" struct_declaration .and .loop struct_declaration .emit FIELD_NEXT;\n"
+"struct_declaration\n"
+" struct_declaration_nospace .or struct_declaration_space;\n"
+"struct_declaration_space\n"
+" type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE;\n"
+"struct_declaration_nospace\n"
+" type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE;\n"
+"struct_declarator_list\n"
+" struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT;\n"
+"struct_declarator_list_1\n"
+" comma .and struct_declarator;\n"
+"struct_declarator\n"
+" identifier .and struct_declarator_1;\n"
+"struct_declarator_1\n"
+" struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE;\n"
+"struct_declarator_2\n"
+" lbracket .and constant_expression .and rbracket;\n"
+"initializer\n"
+" assignment_expression .and .true .emit OP_END;\n"
+"declaration_statement\n"
+" declaration;\n"
+"statement\n"
+" compound_statement .or simple_statement;\n"
+"statement_space\n"
+" compound_statement .or statement_space_1;\n"
+"statement_space_1\n"
+" space .and simple_statement;\n"
+"simple_statement\n"
+" .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or\n"
+" selection_statement .or\n"
+" iteration_statement .or\n"
+" precision_stmt .emit OP_PRECISION .or\n"
+" jump_statement .or\n"
+" expression_statement .emit OP_EXPRESSION .or\n"
+" declaration_statement .emit OP_DECLARE;\n"
+"compound_statement\n"
+" compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END;\n"
+"compound_statement_1\n"
+" compound_statement_2 .or compound_statement_3;\n"
+"compound_statement_2\n"
+" lbrace .and rbrace;\n"
+"compound_statement_3\n"
+" lbrace .and statement_list .and rbrace;\n"
+"compound_statement_no_new_scope\n"
+" compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END;\n"
+"compound_statement_no_new_scope_1\n"
+" compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3;\n"
+"compound_statement_no_new_scope_2\n"
+" lbrace .and rbrace;\n"
+"compound_statement_no_new_scope_3\n"
+" lbrace .and statement_list .and rbrace;\n"
+"statement_list\n"
+" statement .and .loop statement;\n"
+"expression_statement\n"
+" expression_statement_1 .or expression_statement_2;\n"
+"expression_statement_1\n"
+" semicolon .emit OP_PUSH_VOID .emit OP_END;\n"
+"expression_statement_2\n"
+" expression .and semicolon .emit OP_END;\n"
+"selection_statement\n"
+" \"if\" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and\n"
+" rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement;\n"
+"selection_rest_statement\n"
+" statement .and selection_rest_statement_1;\n"
+"selection_rest_statement_1\n"
+" selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END;\n"
+"selection_rest_statement_2\n"
+" \"else\" .and optional_space .and statement;\n"
+"condition\n"
+" condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or\n"
+" condition_3 .emit OP_EXPRESSION;\n"
+"condition_1\n"
+" condition_1_nospace .or condition_1_space;\n"
+"condition_1_nospace\n"
+" fully_specified_type_nospace .and condition_2;\n"
+"condition_1_space\n"
+" fully_specified_type_space .and space .and condition_2;\n"
+"condition_2\n"
+" identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and\n"
+" initializer .and .true .emit DECLARATOR_NONE;\n"
+"condition_3\n"
+" expression .and .true .emit OP_END;\n"
+"iteration_statement\n"
+" iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3;\n"
+"iteration_statement_1\n"
+" \"while\" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and\n"
+" rparen .error RPAREN_EXPECTED .and statement;\n"
+"iteration_statement_2\n"
+" \"do\" .emit OP_DO .and statement_space .and \"while\" .and lparen .error LPAREN_EXPECTED .and\n"
+" expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon;\n"
+"iteration_statement_3\n"
+" \"for\" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and\n"
+" for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement;\n"
+"for_init_statement\n"
+" expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE;\n"
+"conditionopt\n"
+" condition .or\n"
+" .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\\0' .emit OP_END;\n"
+"for_rest_statement\n"
+" conditionopt .and semicolon .and for_rest_statement_1;\n"
+"for_rest_statement_1\n"
+" for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END;\n"
+"for_rest_statement_2\n"
+" expression .and .true .emit OP_END;\n"
+"jump_statement\n"
+" jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or\n"
+" .if (shader_type == 1) jump_statement_5;\n"
+"jump_statement_1\n"
+" \"continue\" .and semicolon .emit OP_CONTINUE;\n"
+"jump_statement_2\n"
+" \"break\" .and semicolon .emit OP_BREAK;\n"
+"jump_statement_3\n"
+" \"return\" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END;\n"
+"jump_statement_4\n"
+" \"return\" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END;\n"
+"jump_statement_5\n"
+" \"discard\" .and semicolon .emit OP_DISCARD;\n"
+"__asm_statement\n"
+" \"__asm\" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END;\n"
+"asm_arguments\n"
+" asm_argument .and .true .emit OP_END .and .loop asm_arguments_1;\n"
+"asm_arguments_1\n"
+" comma .and asm_argument .and .true .emit OP_END;\n"
+"asm_argument\n"
+" var_with_field .or\n"
+" variable_identifier .or\n"
+" floatconstant;\n"
+"var_with_field\n"
+" variable_identifier .and dot .and field_selection .emit OP_FIELD;\n"
+"translation_unit\n"
+" optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and\n"
+" .loop external_declaration .and optional_space .and\n"
+" '\\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL;\n"
+"external_declaration\n"
+" precision_stmt .emit DEFAULT_PRECISION .or\n"
+" function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or\n"
+" invariant_stmt .emit INVARIANT_STMT .or\n"
+" declaration .emit EXTERNAL_DECLARATION;\n"
+"precision_stmt\n"
+" \"precision\" .and space .and precision .error INVALID_PRECISION .and space .and prectype .error INVALID_PRECISION_TYPE .and semicolon;\n"
+"precision\n"
+" \"lowp\" .emit PRECISION_LOW .or\n"
+" \"mediump\" .emit PRECISION_MEDIUM .or\n"
+" \"highp\" .emit PRECISION_HIGH;\n"
+"prectype\n"
+" \"int\" .emit TYPE_SPECIFIER_INT .or\n"
+" \"float\" .emit TYPE_SPECIFIER_FLOAT .or\n"
+" \"sampler1D\" .emit TYPE_SPECIFIER_SAMPLER1D .or\n"
+" \"sampler2D\" .emit TYPE_SPECIFIER_SAMPLER2D .or\n"
+" \"sampler3D\" .emit TYPE_SPECIFIER_SAMPLER3D .or\n"
+" \"samplerCube\" .emit TYPE_SPECIFIER_SAMPLERCUBE .or\n"
+" \"sampler1DShadow\" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or\n"
+" \"sampler2DShadow\" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or\n"
+" \"sampler2DRect\" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or\n"
+" \"sampler2DRectShadow\" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW;\n"
+"invariant_stmt\n"
+" \"invariant\" .and space .and identifier .and semicolon;\n"
+"function_definition\n"
+" function_prototype .and compound_statement_no_new_scope;\n"
+"digit_oct\n"
+" '0'-'7';\n"
+"digit_dec\n"
+" '0'-'9';\n"
+"digit_hex\n"
+" '0'-'9' .or 'A'-'F' .or 'a'-'f';\n"
+"id_character_first\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"id_character_next\n"
+" id_character_first .or digit_dec;\n"
+"identifier\n"
+" id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\\0';\n"
+"float\n"
+" float_1 .or float_2 .or float_3;\n"
+"float_1\n"
+" float_fractional_constant .and float_optional_exponent_part .and optional_f_suffix;\n"
+"float_2\n"
+" float_digit_sequence .and .true .emit '\\0' .and float_exponent_part .and optional_f_suffix;\n"
+"float_3\n"
+" float_digit_sequence .and .true .emit '\\0' .and 'f' .emit '\\0';\n"
+"float_fractional_constant\n"
+" float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3;\n"
+"float_fractional_constant_1\n"
+" float_digit_sequence .and '.' .and float_digit_sequence;\n"
+"float_fractional_constant_2\n"
+" float_digit_sequence .and '.' .and .true .emit '\\0';\n"
+"float_fractional_constant_3\n"
+" '.' .emit '\\0' .and float_digit_sequence;\n"
+"float_optional_exponent_part\n"
+" float_exponent_part .or .true .emit '\\0';\n"
+"float_digit_sequence\n"
+" digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n"
+"float_exponent_part\n"
+" float_exponent_part_1 .or float_exponent_part_2;\n"
+"float_exponent_part_1\n"
+" 'e' .and float_optional_sign .and float_digit_sequence;\n"
+"float_exponent_part_2\n"
+" 'E' .and float_optional_sign .and float_digit_sequence;\n"
+"float_optional_sign\n"
+" float_sign .or .true;\n"
+"float_sign\n"
+" '+' .or '-' .emit '-';\n"
+"optional_f_suffix\n"
+" 'f' .or .true;\n"
+"integer\n"
+" integer_hex .or integer_oct .or integer_dec;\n"
+"integer_hex\n"
+" '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and\n"
+" .true .emit '\\0';\n"
+"integer_hex_1\n"
+" 'x' .or 'X';\n"
+"integer_oct\n"
+" '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\\0';\n"
+"integer_dec\n"
+" digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\\0';\n"
+"boolean\n"
+" \"true\" .emit 2 .emit '1' .emit '\\0' .or\n"
+" \"false\" .emit 2 .emit '0' .emit '\\0';\n"
+"type_name\n"
+" identifier;\n"
+"field_selection\n"
+" identifier;\n"
+"floatconstant\n"
+" float .emit OP_PUSH_FLOAT;\n"
+"intconstant\n"
+" integer .emit OP_PUSH_INT;\n"
+"boolconstant\n"
+" boolean .emit OP_PUSH_BOOL;\n"
+"optional_space\n"
+" .loop single_space;\n"
+"space\n"
+" single_space .and .loop single_space;\n"
+"single_space\n"
+" white_char .or c_style_comment_block .or cpp_style_comment_block;\n"
+"white_char\n"
+" ' ' .or '\\t' .or new_line .or '\\v' .or '\\f';\n"
+"new_line\n"
+" cr_lf .or lf_cr .or '\\n' .or '\\r';\n"
+"cr_lf\n"
+" '\\r' .and '\\n';\n"
+"lf_cr\n"
+" '\\n' .and '\\r';\n"
+"c_style_comment_block\n"
+" '/' .and '*' .and c_style_comment_rest;\n"
+"c_style_comment_rest\n"
+" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n"
+"c_style_comment_rest_1\n"
+" c_style_comment_end .or c_style_comment_rest_2;\n"
+"c_style_comment_rest_2\n"
+" '*' .and c_style_comment_rest;\n"
+"c_style_comment_char_no_star\n"
+" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n"
+"c_style_comment_end\n"
+" '*' .and '/';\n"
+"cpp_style_comment_block\n"
+" '/' .and '/' .and cpp_style_comment_block_1;\n"
+"cpp_style_comment_block_1\n"
+" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n"
+"cpp_style_comment_block_2\n"
+" .loop cpp_style_comment_char .and new_line;\n"
+"cpp_style_comment_block_3\n"
+" .loop cpp_style_comment_char;\n"
+"cpp_style_comment_char\n"
+" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n"
+"ampersandampersand\n"
+" optional_space .and '&' .and '&' .and optional_space;\n"
+"barbar\n"
+" optional_space .and '|' .and '|' .and optional_space;\n"
+"bang\n"
+" optional_space .and '!' .and optional_space;\n"
+"bangequals\n"
+" optional_space .and '!' .and '=' .and optional_space;\n"
+"caretcaret\n"
+" optional_space .and '^' .and '^' .and optional_space;\n"
+"colon\n"
+" optional_space .and ':' .and optional_space;\n"
+"comma\n"
+" optional_space .and ',' .and optional_space;\n"
+"dot\n"
+" optional_space .and '.' .and optional_space;\n"
+"equals\n"
+" optional_space .and '=' .and optional_space;\n"
+"equalsequals\n"
+" optional_space .and '=' .and '=' .and optional_space;\n"
+"greater\n"
+" optional_space .and '>' .and optional_space;\n"
+"greaterequals\n"
+" optional_space .and '>' .and '=' .and optional_space;\n"
+"lbrace\n"
+" optional_space .and '{' .and optional_space;\n"
+"lbracket\n"
+" optional_space .and '[' .and optional_space;\n"
+"less\n"
+" optional_space .and '<' .and optional_space;\n"
+"lessequals\n"
+" optional_space .and '<' .and '=' .and optional_space;\n"
+"lparen\n"
+" optional_space .and '(' .and optional_space;\n"
+"minus\n"
+" optional_space .and '-' .and optional_space;\n"
+"minusequals\n"
+" optional_space .and '-' .and '=' .and optional_space;\n"
+"minusminus\n"
+" optional_space .and '-' .and '-' .and optional_space;\n"
+"plus\n"
+" optional_space .and '+' .and optional_space;\n"
+"plusequals\n"
+" optional_space .and '+' .and '=' .and optional_space;\n"
+"plusplus\n"
+" optional_space .and '+' .and '+' .and optional_space;\n"
+"question\n"
+" optional_space .and '?' .and optional_space;\n"
+"rbrace\n"
+" optional_space .and '}' .and optional_space;\n"
+"rbracket\n"
+" optional_space .and ']' .and optional_space;\n"
+"rparen\n"
+" optional_space .and ')' .and optional_space;\n"
+"semicolon\n"
+" optional_space .and ';' .and optional_space;\n"
+"slash\n"
+" optional_space .and '/' .and optional_space;\n"
+"slashequals\n"
+" optional_space .and '/' .and '=' .and optional_space;\n"
+"star\n"
+" optional_space .and '*' .and optional_space;\n"
+"starequals\n"
+" optional_space .and '*' .and '=' .and optional_space;\n"
+".string string_lexer;\n"
+"string_lexer\n"
+" lex_first_identifier_character .and .loop lex_next_identifier_character;\n"
+"lex_first_identifier_character\n"
+" 'a'-'z' .or 'A'-'Z' .or '_';\n"
+"lex_next_identifier_character\n"
+" 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_';\n"
+"err_token\n"
+" '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or\n"
+" '-' .or '+' .or '=' .or '|' .or '\\\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '\"' .or\n"
+" '\\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier;\n"
+"err_identifier\n"
+" id_character_first .and .loop id_character_next;\n"
+""
diff --git a/mesalib/src/mesa/shader/slang/library/slang_version.syn b/mesalib/src/mesa/shader/slang/library/slang_version.syn
new file mode 100644
index 000000000..aaf8bef34
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_version.syn
@@ -0,0 +1,118 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 2005 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.
+ */
+
+/**
+ * \file slang_version.syn
+ * slang #version directive syntax
+ * \author Michal Krol
+ */
+
+.syntax version_directive;
+
+version_directive
+ version_directive_1 .and .loop version_directive_2;
+version_directive_1
+ prior_optional_spaces .and optional_version_directive .and .true .emit $;
+version_directive_2
+ prior_optional_spaces .and version_directive_body .and .true .emit $;
+
+optional_version_directive
+ version_directive_body .or .true .emit 10 .emit 1;
+
+version_directive_body
+ '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and
+ new_line;
+
+version_number
+ version_number_110;
+
+version_number_110
+ leading_zeroes .and "110" .emit 10 .emit 1;
+
+leading_zeroes
+ .loop zero;
+
+zero
+ '0';
+
+space
+ single_space .and .loop single_space;
+
+optional_space
+ .loop single_space;
+
+single_space
+ ' ' .or '\t';
+
+prior_optional_spaces
+ .loop prior_space;
+
+prior_space
+ c_style_comment_block .or cpp_style_comment_block .or space .or new_line;
+
+c_style_comment_block
+ '/' .and '*' .and c_style_comment_rest;
+
+c_style_comment_rest
+ .loop c_style_comment_char_no_star .and c_style_comment_rest_1;
+c_style_comment_rest_1
+ c_style_comment_end .or c_style_comment_rest_2;
+c_style_comment_rest_2
+ '*' .and c_style_comment_rest;
+
+c_style_comment_char_no_star
+ '\x2B'-'\xFF' .or '\x01'-'\x29';
+
+c_style_comment_end
+ '*' .and '/';
+
+cpp_style_comment_block
+ '/' .and '/' .and cpp_style_comment_block_1;
+cpp_style_comment_block_1
+ cpp_style_comment_block_2 .or cpp_style_comment_block_3;
+cpp_style_comment_block_2
+ .loop cpp_style_comment_char .and new_line;
+cpp_style_comment_block_3
+ .loop cpp_style_comment_char;
+
+cpp_style_comment_char
+ '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C';
+
+new_line
+ cr_lf .or lf_cr .or '\n' .or '\r';
+
+cr_lf
+ '\r' .and '\n';
+
+lf_cr
+ '\n' .and '\r';
+
+.string __string_filter;
+
+__string_filter
+ .loop __identifier_char;
+
+__identifier_char
+ 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin.gc b/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin.gc
new file mode 100644
index 000000000..9ad5f3542
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin.gc
@@ -0,0 +1,190 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2006 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.
+ */
+
+//
+// From Shader Spec, ver. 1.10, rev. 59
+//
+
+__fixed_output vec4 gl_Position;
+__fixed_output float gl_PointSize;
+__fixed_output vec4 gl_ClipVertex;
+
+attribute vec4 gl_Color;
+attribute vec4 gl_SecondaryColor;
+attribute vec3 gl_Normal;
+attribute vec4 gl_Vertex;
+attribute vec4 gl_MultiTexCoord0;
+attribute vec4 gl_MultiTexCoord1;
+attribute vec4 gl_MultiTexCoord2;
+attribute vec4 gl_MultiTexCoord3;
+attribute vec4 gl_MultiTexCoord4;
+attribute vec4 gl_MultiTexCoord5;
+attribute vec4 gl_MultiTexCoord6;
+attribute vec4 gl_MultiTexCoord7;
+attribute float gl_FogCoord;
+
+varying vec4 gl_FrontColor;
+varying vec4 gl_BackColor;
+varying vec4 gl_FrontSecondaryColor;
+varying vec4 gl_BackSecondaryColor;
+varying vec4 gl_TexCoord[gl_MaxTextureCoords];
+varying float gl_FogFragCoord;
+
+//
+// Geometric Functions
+//
+
+vec4 ftransform()
+{
+ __retVal = gl_ModelViewProjectionMatrix[0] * gl_Vertex.xxxx
+ + gl_ModelViewProjectionMatrix[1] * gl_Vertex.yyyy
+ + gl_ModelViewProjectionMatrix[2] * gl_Vertex.zzzz
+ + gl_ModelViewProjectionMatrix[3] * gl_Vertex.wwww;
+}
+
+
+
+//
+// 8.7 Texture Lookup Functions
+// These are pretty much identical to the ones in slang_fragment_builtin.gc
+// When used in a vertex program, the texture sample instructions should not
+// be using a LOD term so it's effectively zero. Adding 'lod' to that does
+// what we want.
+//
+
+vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod)
+{
+ vec4 coord4;
+ coord4.x = coord;
+ coord4.w = lod;
+ __asm vec4_tex_1d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod)
+{
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.y;
+ pcoord.w = lod;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod)
+{
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.z;
+ pcoord.w = lod;
+ __asm vec4_tex_1d_bias __retVal, sampler, pcoord;
+}
+
+
+
+vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod)
+{
+ vec4 coord4;
+ coord4.xy = coord.xy;
+ coord4.w = lod;
+ __asm vec4_tex_2d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod)
+{
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.z;
+ pcoord.w = lod;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod)
+{
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.z;
+ pcoord.w = lod;
+ __asm vec4_tex_2d_bias __retVal, sampler, pcoord;
+}
+
+
+vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod)
+{
+ vec4 coord4;
+ coord4.xyz = coord.xyz;
+ coord4.w = lod;
+ __asm vec4_tex_3d_bias __retVal, sampler, coord4;
+}
+
+vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod)
+{
+ // do projection here (there's no vec4_tex_3d_bias_proj instruction)
+ vec4 pcoord;
+ pcoord.xyz = coord.xyz / coord.w;
+ pcoord.w = lod;
+ __asm vec4_tex_3d_bias __retVal, sampler, pcoord;
+}
+
+
+vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = lod;
+ __asm vec4_tex_cube __retVal, sampler, coord4;
+}
+
+
+vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = lod;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord,
+ const float lod)
+{
+ vec4 pcoord;
+ pcoord.x = coord.x / coord.w;
+ pcoord.z = coord.z;
+ pcoord.w = lod;
+ __asm vec4_tex_1d_bias_shadow __retVal, sampler, pcoord;
+}
+
+
+vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod)
+{
+ vec4 coord4;
+ coord4.xyz = coord;
+ coord4.w = lod;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, coord4;
+}
+
+vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord,
+ const float lod)
+{
+ vec4 pcoord;
+ pcoord.xy = coord.xy / coord.w;
+ pcoord.z = coord.z;
+ pcoord.w = lod;
+ __asm vec4_tex_2d_bias_shadow __retVal, sampler, pcoord;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h b/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
new file mode 100644
index 000000000..e5a252b01
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
@@ -0,0 +1,109 @@
+
+/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */
+/* slang_vertex_builtin.gc */
+
+5,2,2,90,95,5,0,12,0,1,103,108,95,80,111,115,105,116,105,111,110,0,0,0,2,2,90,95,5,0,9,0,1,103,108,
+95,80,111,105,110,116,83,105,122,101,0,0,0,2,2,90,95,5,0,12,0,1,103,108,95,67,108,105,112,86,101,
+114,116,101,120,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,67,111,108,111,114,0,0,0,2,2,90,95,2,0,12,0,
+1,103,108,95,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,90,95,2,0,11,0,1,103,
+108,95,78,111,114,109,97,108,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,86,101,114,116,101,120,0,0,0,2,
+2,90,95,2,0,12,0,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,48,0,0,0,2,2,90,95,
+2,0,12,0,1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,49,0,0,0,2,2,90,95,2,0,12,0,
+1,103,108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,50,0,0,0,2,2,90,95,2,0,12,0,1,103,
+108,95,77,117,108,116,105,84,101,120,67,111,111,114,100,51,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,
+77,117,108,116,105,84,101,120,67,111,111,114,100,52,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,77,117,
+108,116,105,84,101,120,67,111,111,114,100,53,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,77,117,108,116,
+105,84,101,120,67,111,111,114,100,54,0,0,0,2,2,90,95,2,0,12,0,1,103,108,95,77,117,108,116,105,84,
+101,120,67,111,111,114,100,55,0,0,0,2,2,90,95,2,0,9,0,1,103,108,95,70,111,103,67,111,111,114,100,0,
+0,0,2,2,90,95,3,0,12,0,1,103,108,95,70,114,111,110,116,67,111,108,111,114,0,0,0,2,2,90,95,3,0,12,0,
+1,103,108,95,66,97,99,107,67,111,108,111,114,0,0,0,2,2,90,95,3,0,12,0,1,103,108,95,70,114,111,110,
+116,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,90,95,3,0,12,0,1,103,108,95,66,
+97,99,107,83,101,99,111,110,100,97,114,121,67,111,108,111,114,0,0,0,2,2,90,95,3,0,12,0,1,103,108,
+95,84,101,120,67,111,111,114,100,0,3,18,103,108,95,77,97,120,84,101,120,116,117,114,101,67,111,111,
+114,100,115,0,0,0,2,2,90,95,3,0,9,0,1,103,108,95,70,111,103,70,114,97,103,67,111,111,114,100,0,0,0,
+1,90,95,0,0,12,0,0,102,116,114,97,110,115,102,111,114,109,0,0,1,9,18,95,95,114,101,116,86,97,108,0,
+18,103,108,95,77,111,100,101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,
+114,105,120,0,16,8,48,0,57,18,103,108,95,86,101,114,116,101,120,0,59,120,120,120,120,0,48,18,103,
+108,95,77,111,100,101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,
+120,0,16,10,49,0,57,18,103,108,95,86,101,114,116,101,120,0,59,121,121,121,121,0,48,46,18,103,108,
+95,77,111,100,101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,
+16,10,50,0,57,18,103,108,95,86,101,114,116,101,120,0,59,122,122,122,122,0,48,46,18,103,108,95,77,
+111,100,101,108,86,105,101,119,80,114,111,106,101,99,116,105,111,110,77,97,116,114,105,120,0,16,10,
+51,0,57,18,103,108,95,86,101,114,116,101,120,0,59,119,119,119,119,0,48,46,20,0,0,1,90,95,0,0,12,0,
+0,116,101,120,116,117,114,101,49,68,76,111,100,0,1,1,0,0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,
+0,9,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,
+100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,
+114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,
+115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,
+52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,
+0,16,0,115,97,109,112,108,101,114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,
+0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,
+18,99,111,111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,121,0,49,20,0,9,18,112,99,111,111,114,
+100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,
+18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,
+0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,49,68,80,114,111,106,76,111,100,0,1,1,0,0,16,0,
+115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,
+3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,
+111,114,100,0,59,120,0,18,99,111,111,114,100,0,59,122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,
+119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,0,18,95,95,
+114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,
+95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,
+114,0,0,1,1,0,0,10,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,
+99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,0,18,99,111,111,114,100,0,59,
+120,121,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,17,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+122,0,49,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,
+101,120,95,50,100,95,98,105,97,115,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,
+114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,76,
+111,100,0,1,1,0,0,18,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,
+9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,
+52,0,59,120,121,122,0,18,99,111,111,114,100,0,59,120,121,122,0,20,0,9,18,99,111,111,114,100,52,0,
+59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,0,18,95,
+95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,
+90,95,0,0,12,0,0,116,101,120,116,117,114,101,51,68,80,114,111,106,76,111,100,0,1,1,0,0,18,0,115,97,
+109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,
+95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,121,122,0,18,99,
+111,111,114,100,0,59,120,121,122,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,
+114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,51,100,95,98,105,97,115,
+0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,
+0,0,0,1,90,95,0,0,12,0,0,116,101,120,116,117,114,101,67,117,98,101,76,111,100,0,1,1,0,0,19,0,115,
+97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,
+90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,
+111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,
+95,116,101,120,95,99,117,98,101,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,
+0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,76,111,100,0,
+1,1,0,0,20,0,115,97,109,112,108,101,114,0,0,1,1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,
+111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,
+120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,
+20,0,4,118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,
+95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,
+90,95,0,0,12,0,0,115,104,97,100,111,119,49,68,80,114,111,106,76,111,100,0,1,1,0,0,20,0,115,97,109,
+112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,
+0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,99,111,111,114,100,0,59,120,0,18,99,111,111,114,
+100,0,59,120,0,18,99,111,111,114,100,0,59,119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,
+99,111,111,114,100,0,59,122,0,20,0,9,18,112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,
+118,101,99,52,95,116,101,120,95,49,100,95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,
+101,116,86,97,108,0,0,18,115,97,109,112,108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,1,90,95,
+0,0,12,0,0,115,104,97,100,111,119,50,68,76,111,100,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,
+1,0,0,11,0,99,111,111,114,100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,99,111,111,
+114,100,52,0,0,0,9,18,99,111,111,114,100,52,0,59,120,121,122,0,18,99,111,111,114,100,0,20,0,9,18,
+99,111,111,114,100,52,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,50,100,95,
+98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,108,
+101,114,0,0,18,99,111,111,114,100,52,0,0,0,0,1,90,95,0,0,12,0,0,115,104,97,100,111,119,50,68,80,
+114,111,106,76,111,100,0,1,1,0,0,21,0,115,97,109,112,108,101,114,0,0,1,1,0,0,12,0,99,111,111,114,
+100,0,0,1,1,0,0,9,0,108,111,100,0,0,0,1,3,2,90,95,0,0,12,0,1,112,99,111,111,114,100,0,0,0,9,18,112,
+99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,120,121,0,18,99,111,111,114,100,0,59,
+119,0,49,20,0,9,18,112,99,111,111,114,100,0,59,122,0,18,99,111,111,114,100,0,59,122,0,20,0,9,18,
+112,99,111,111,114,100,0,59,119,0,18,108,111,100,0,20,0,4,118,101,99,52,95,116,101,120,95,50,100,
+95,98,105,97,115,95,115,104,97,100,111,119,0,18,95,95,114,101,116,86,97,108,0,0,18,115,97,109,112,
+108,101,114,0,0,18,112,99,111,111,114,100,0,0,0,0,0
diff --git a/mesalib/src/mesa/shader/slang/library/syn_to_c.c b/mesalib/src/mesa/shader/slang/library/syn_to_c.c
new file mode 100644
index 000000000..f997edfd8
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/library/syn_to_c.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+
+static int was_space = 0;
+static int first_char = 1;
+
+static void put_char (int c)
+{
+ if (c == '\n') {
+ if (!first_char) {
+ fputs ("\\n\"\n\"", stdout);
+ first_char = 1;
+ }
+ }
+ else {
+ first_char = 0;
+ if (c == '\\')
+ fputs ("\\\\", stdout);
+ else if (c == '\"')
+ fputs ("\\\"", stdout);
+ else if (!was_space || !(c == ' ' || c == '\t'))
+ fputc (c, stdout);
+ was_space = (c == ' ' || c == '\t');
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ int c;
+ FILE *f;
+
+ if (argc == 1)
+ return 1;
+ f = fopen (argv[1], "r");
+ if (f == NULL)
+ return 1;
+
+ fputs ("\n", stdout);
+ fputs ("/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE .syn FILE */\n", stdout);
+ fputs ("\n", stdout);
+ fputs ("\"", stdout);
+ c = getc (f);
+ while (c != EOF) {
+ if (c == '/') {
+ int c2 = getc (f);
+ if (c2 == '*') {
+ was_space = 0;
+ c = getc (f);
+ for (;;) {
+ if (c == '*') {
+ c2 = getc (f);
+ if (c2 == '/')
+ break;
+ }
+ c = getc (f);
+ }
+ }
+ else {
+ put_char (c);
+ put_char (c2);
+ }
+ }
+ else {
+ put_char (c);
+ }
+ c = getc (f);
+ }
+ fputs ("\"\n", stdout);
+
+ fclose (f);
+ return 0;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_builtin.c b/mesalib/src/mesa/shader/slang/slang_builtin.c
new file mode 100644
index 000000000..e5809509c
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_builtin.c
@@ -0,0 +1,895 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_builtin.c
+ * Resolve built-in uniform vars.
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "shader/slang/slang_ir.h"
+#include "shader/slang/slang_emit.h"
+#include "shader/slang/slang_builtin.h"
+
+
+/** special state token (see below) */
+#define STATE_ARRAY ((gl_state_index) 0xfffff)
+
+
+/**
+ * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field.
+ * Allocate room for the state in the given param list and return position
+ * in the list.
+ * Yes, this is kind of ugly, but it works.
+ */
+static GLint
+lookup_statevar(const char *var, GLint index1, GLint index2, const char *field,
+ GLuint *swizzleOut,
+ struct gl_program_parameter_list *paramList)
+{
+ /*
+ * NOTE: The ARB_vertex_program extension specified that matrices get
+ * loaded in registers in row-major order. With GLSL, we want column-
+ * major order. So, we need to transpose all matrices here...
+ */
+ static const struct {
+ const char *name;
+ gl_state_index matrix;
+ gl_state_index modifier;
+ } matrices[] = {
+ { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 },
+ { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 },
+ { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 },
+ { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE },
+ { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS },
+ { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 },
+ { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE },
+
+ { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE },
+
+ { NULL, 0, 0 }
+ };
+ gl_state_index tokens[STATE_LENGTH];
+ GLuint i;
+ GLboolean isMatrix = GL_FALSE;
+
+ for (i = 0; i < STATE_LENGTH; i++) {
+ tokens[i] = 0;
+ }
+ *swizzleOut = SWIZZLE_NOOP;
+
+ /* first, look if var is a pre-defined matrix */
+ for (i = 0; matrices[i].name; i++) {
+ if (strcmp(var, matrices[i].name) == 0) {
+ tokens[0] = matrices[i].matrix;
+ /* tokens[1], [2] and [3] filled below */
+ tokens[4] = matrices[i].modifier;
+ isMatrix = GL_TRUE;
+ break;
+ }
+ }
+
+ if (isMatrix) {
+ if (tokens[0] == STATE_TEXTURE_MATRIX) {
+ /* texture_matrix[index1][index2] */
+ tokens[1] = index1 >= 0 ? index1 : 0; /* which texture matrix */
+ index1 = index2; /* move matrix row value to index1 */
+ }
+ if (index1 < 0) {
+ /* index1 is unused: prevent extra addition at end of function */
+ index1 = 0;
+ }
+ }
+ else if (strcmp(var, "gl_DepthRange") == 0) {
+ tokens[0] = STATE_DEPTH_RANGE;
+ if (strcmp(field, "near") == 0) {
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "far") == 0) {
+ *swizzleOut = SWIZZLE_YYYY;
+ }
+ else if (strcmp(field, "diff") == 0) {
+ *swizzleOut = SWIZZLE_ZZZZ;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_ClipPlane") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_CLIPPLANE;
+ tokens[1] = index1;
+ }
+ else if (strcmp(var, "gl_Point") == 0) {
+ if (strcmp(field, "size") == 0) {
+ tokens[0] = STATE_POINT_SIZE;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "sizeMin") == 0) {
+ tokens[0] = STATE_POINT_SIZE;
+ *swizzleOut = SWIZZLE_YYYY;
+ }
+ else if (strcmp(field, "sizeMax") == 0) {
+ tokens[0] = STATE_POINT_SIZE;
+ *swizzleOut = SWIZZLE_ZZZZ;
+ }
+ else if (strcmp(field, "fadeThresholdSize") == 0) {
+ tokens[0] = STATE_POINT_SIZE;
+ *swizzleOut = SWIZZLE_WWWW;
+ }
+ else if (strcmp(field, "distanceConstantAttenuation") == 0) {
+ tokens[0] = STATE_POINT_ATTENUATION;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "distanceLinearAttenuation") == 0) {
+ tokens[0] = STATE_POINT_ATTENUATION;
+ *swizzleOut = SWIZZLE_YYYY;
+ }
+ else if (strcmp(field, "distanceQuadraticAttenuation") == 0) {
+ tokens[0] = STATE_POINT_ATTENUATION;
+ *swizzleOut = SWIZZLE_ZZZZ;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_FrontMaterial") == 0 ||
+ strcmp(var, "gl_BackMaterial") == 0) {
+ tokens[0] = STATE_MATERIAL;
+ if (strcmp(var, "gl_FrontMaterial") == 0)
+ tokens[1] = 0;
+ else
+ tokens[1] = 1;
+ if (strcmp(field, "emission") == 0) {
+ tokens[2] = STATE_EMISSION;
+ }
+ else if (strcmp(field, "ambient") == 0) {
+ tokens[2] = STATE_AMBIENT;
+ }
+ else if (strcmp(field, "diffuse") == 0) {
+ tokens[2] = STATE_DIFFUSE;
+ }
+ else if (strcmp(field, "specular") == 0) {
+ tokens[2] = STATE_SPECULAR;
+ }
+ else if (strcmp(field, "shininess") == 0) {
+ tokens[2] = STATE_SHININESS;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_LightSource") == 0) {
+ if (!field || index1 < 0)
+ return -1;
+
+ tokens[0] = STATE_LIGHT;
+ tokens[1] = index1;
+
+ if (strcmp(field, "ambient") == 0) {
+ tokens[2] = STATE_AMBIENT;
+ }
+ else if (strcmp(field, "diffuse") == 0) {
+ tokens[2] = STATE_DIFFUSE;
+ }
+ else if (strcmp(field, "specular") == 0) {
+ tokens[2] = STATE_SPECULAR;
+ }
+ else if (strcmp(field, "position") == 0) {
+ tokens[2] = STATE_POSITION;
+ }
+ else if (strcmp(field, "halfVector") == 0) {
+ tokens[2] = STATE_HALF_VECTOR;
+ }
+ else if (strcmp(field, "spotDirection") == 0) {
+ tokens[2] = STATE_SPOT_DIRECTION;
+ }
+ else if (strcmp(field, "spotCosCutoff") == 0) {
+ tokens[2] = STATE_SPOT_DIRECTION;
+ *swizzleOut = SWIZZLE_WWWW;
+ }
+ else if (strcmp(field, "spotCutoff") == 0) {
+ tokens[2] = STATE_SPOT_CUTOFF;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "spotExponent") == 0) {
+ tokens[2] = STATE_ATTENUATION;
+ *swizzleOut = SWIZZLE_WWWW;
+ }
+ else if (strcmp(field, "constantAttenuation") == 0) {
+ tokens[2] = STATE_ATTENUATION;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "linearAttenuation") == 0) {
+ tokens[2] = STATE_ATTENUATION;
+ *swizzleOut = SWIZZLE_YYYY;
+ }
+ else if (strcmp(field, "quadraticAttenuation") == 0) {
+ tokens[2] = STATE_ATTENUATION;
+ *swizzleOut = SWIZZLE_ZZZZ;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_LightModel") == 0) {
+ if (strcmp(field, "ambient") == 0) {
+ tokens[0] = STATE_LIGHTMODEL_AMBIENT;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_FrontLightModelProduct") == 0) {
+ if (strcmp(field, "sceneColor") == 0) {
+ tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ tokens[1] = 0;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_BackLightModelProduct") == 0) {
+ if (strcmp(field, "sceneColor") == 0) {
+ tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
+ tokens[1] = 1;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_FrontLightProduct") == 0 ||
+ strcmp(var, "gl_BackLightProduct") == 0) {
+ if (index1 < 0 || !field)
+ return -1;
+
+ tokens[0] = STATE_LIGHTPROD;
+ tokens[1] = index1; /* light number */
+ if (strcmp(var, "gl_FrontLightProduct") == 0) {
+ tokens[2] = 0; /* front */
+ }
+ else {
+ tokens[2] = 1; /* back */
+ }
+ if (strcmp(field, "ambient") == 0) {
+ tokens[3] = STATE_AMBIENT;
+ }
+ else if (strcmp(field, "diffuse") == 0) {
+ tokens[3] = STATE_DIFFUSE;
+ }
+ else if (strcmp(field, "specular") == 0) {
+ tokens[3] = STATE_SPECULAR;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (strcmp(var, "gl_TextureEnvColor") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXENV_COLOR;
+ tokens[1] = index1;
+ }
+ else if (strcmp(var, "gl_EyePlaneS") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_EYE_S;
+ }
+ else if (strcmp(var, "gl_EyePlaneT") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_EYE_T;
+ }
+ else if (strcmp(var, "gl_EyePlaneR") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_EYE_R;
+ }
+ else if (strcmp(var, "gl_EyePlaneQ") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_EYE_Q;
+ }
+ else if (strcmp(var, "gl_ObjectPlaneS") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_OBJECT_S;
+ }
+ else if (strcmp(var, "gl_ObjectPlaneT") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_OBJECT_T;
+ }
+ else if (strcmp(var, "gl_ObjectPlaneR") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_OBJECT_R;
+ }
+ else if (strcmp(var, "gl_ObjectPlaneQ") == 0) {
+ if (index1 < 0)
+ return -1;
+ tokens[0] = STATE_TEXGEN;
+ tokens[1] = index1; /* tex unit */
+ tokens[2] = STATE_TEXGEN_OBJECT_Q;
+ }
+ else if (strcmp(var, "gl_Fog") == 0) {
+ if (strcmp(field, "color") == 0) {
+ tokens[0] = STATE_FOG_COLOR;
+ }
+ else if (strcmp(field, "density") == 0) {
+ tokens[0] = STATE_FOG_PARAMS;
+ *swizzleOut = SWIZZLE_XXXX;
+ }
+ else if (strcmp(field, "start") == 0) {
+ tokens[0] = STATE_FOG_PARAMS;
+ *swizzleOut = SWIZZLE_YYYY;
+ }
+ else if (strcmp(field, "end") == 0) {
+ tokens[0] = STATE_FOG_PARAMS;
+ *swizzleOut = SWIZZLE_ZZZZ;
+ }
+ else if (strcmp(field, "scale") == 0) {
+ tokens[0] = STATE_FOG_PARAMS;
+ *swizzleOut = SWIZZLE_WWWW;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+
+ if (isMatrix) {
+ /* load all four columns of matrix */
+ GLint pos[4];
+ GLuint j;
+ for (j = 0; j < 4; j++) {
+ tokens[2] = tokens[3] = j; /* jth row of matrix */
+ pos[j] = _mesa_add_state_reference(paramList, tokens);
+ assert(pos[j] >= 0);
+ ASSERT(pos[j] >= 0);
+ }
+ return pos[0] + index1;
+ }
+ else {
+ /* allocate a single register */
+ GLint pos = _mesa_add_state_reference(paramList, tokens);
+ ASSERT(pos >= 0);
+ return pos;
+ }
+}
+
+
+
+/**
+ * Given a variable name and datatype, emit uniform/constant buffer
+ * entries which will store that state variable.
+ * For example, if name="gl_LightSource" we'll emit 64 state variable
+ * vectors/references and return position where that data starts. This will
+ * allow run-time array indexing into the light source array.
+ *
+ * Note that this is a recursive function.
+ *
+ * \return -1 if error, else index of start of data in the program parameter list
+ */
+static GLint
+emit_statevars(const char *name, int array_len,
+ const slang_type_specifier *type,
+ gl_state_index tokens[STATE_LENGTH],
+ struct gl_program_parameter_list *paramList)
+{
+ if (type->type == SLANG_SPEC_ARRAY) {
+ GLint i, pos = -1;
+ assert(array_len > 0);
+ if (strcmp(name, "gl_ClipPlane") == 0) {
+ tokens[0] = STATE_CLIPPLANE;
+ }
+ else if (strcmp(name, "gl_LightSource") == 0) {
+ tokens[0] = STATE_LIGHT;
+ }
+ else if (strcmp(name, "gl_FrontLightProduct") == 0) {
+ tokens[0] = STATE_LIGHTPROD;
+ tokens[2] = 0; /* front */
+ }
+ else if (strcmp(name, "gl_BackLightProduct") == 0) {
+ tokens[0] = STATE_LIGHTPROD;
+ tokens[2] = 1; /* back */
+ }
+ else if (strcmp(name, "gl_TextureEnvColor") == 0) {
+ tokens[0] = STATE_TEXENV_COLOR;
+ }
+ else if (strcmp(name, "gl_EyePlaneS") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_S;
+ }
+ else if (strcmp(name, "gl_EyePlaneT") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_T;
+ }
+ else if (strcmp(name, "gl_EyePlaneR") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_R;
+ }
+ else if (strcmp(name, "gl_EyePlaneQ") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_EYE_Q;
+ }
+ else if (strcmp(name, "gl_ObjectPlaneS") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_S;
+ }
+ else if (strcmp(name, "gl_ObjectPlaneT") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_T;
+ }
+ else if (strcmp(name, "gl_ObjectPlaneR") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_R;
+ }
+ else if (strcmp(name, "gl_ObjectPlaneQ") == 0) {
+ tokens[0] = STATE_TEXGEN;
+ tokens[2] = STATE_TEXGEN_OBJECT_Q;
+ }
+ else {
+ return -1; /* invalid array name */
+ }
+ for (i = 0; i < array_len; i++) {
+ GLint p;
+ tokens[1] = i;
+ p = emit_statevars(NULL, 0, type->_array, tokens, paramList);
+ if (i == 0)
+ pos = p;
+ }
+ return pos;
+ }
+ else if (type->type == SLANG_SPEC_STRUCT) {
+ const slang_variable_scope *fields = type->_struct->fields;
+ GLuint i, pos = 0;
+ for (i = 0; i < fields->num_variables; i++) {
+ const slang_variable *var = fields->variables[i];
+ GLint p = emit_statevars(var->a_name, 0, &var->type.specifier,
+ tokens, paramList);
+ if (i == 0)
+ pos = p;
+ }
+ return pos;
+ }
+ else {
+ GLint pos;
+ assert(type->type == SLANG_SPEC_VEC4 ||
+ type->type == SLANG_SPEC_VEC3 ||
+ type->type == SLANG_SPEC_VEC2 ||
+ type->type == SLANG_SPEC_FLOAT ||
+ type->type == SLANG_SPEC_IVEC4 ||
+ type->type == SLANG_SPEC_IVEC3 ||
+ type->type == SLANG_SPEC_IVEC2 ||
+ type->type == SLANG_SPEC_INT);
+ if (name) {
+ GLint t;
+
+ if (tokens[0] == STATE_LIGHT)
+ t = 2;
+ else if (tokens[0] == STATE_LIGHTPROD)
+ t = 3;
+ else
+ return -1; /* invalid array name */
+
+ if (strcmp(name, "ambient") == 0) {
+ tokens[t] = STATE_AMBIENT;
+ }
+ else if (strcmp(name, "diffuse") == 0) {
+ tokens[t] = STATE_DIFFUSE;
+ }
+ else if (strcmp(name, "specular") == 0) {
+ tokens[t] = STATE_SPECULAR;
+ }
+ else if (strcmp(name, "position") == 0) {
+ tokens[t] = STATE_POSITION;
+ }
+ else if (strcmp(name, "halfVector") == 0) {
+ tokens[t] = STATE_HALF_VECTOR;
+ }
+ else if (strcmp(name, "spotDirection") == 0) {
+ tokens[t] = STATE_SPOT_DIRECTION; /* xyz components */
+ }
+ else if (strcmp(name, "spotCosCutoff") == 0) {
+ tokens[t] = STATE_SPOT_DIRECTION; /* w component */
+ }
+
+ else if (strcmp(name, "constantAttenuation") == 0) {
+ tokens[t] = STATE_ATTENUATION; /* x component */
+ }
+ else if (strcmp(name, "linearAttenuation") == 0) {
+ tokens[t] = STATE_ATTENUATION; /* y component */
+ }
+ else if (strcmp(name, "quadraticAttenuation") == 0) {
+ tokens[t] = STATE_ATTENUATION; /* z component */
+ }
+ else if (strcmp(name, "spotExponent") == 0) {
+ tokens[t] = STATE_ATTENUATION; /* w = spot exponent */
+ }
+
+ else if (strcmp(name, "spotCutoff") == 0) {
+ tokens[t] = STATE_SPOT_CUTOFF; /* x component */
+ }
+
+ else {
+ return -1; /* invalid field name */
+ }
+ }
+
+ pos = _mesa_add_state_reference(paramList, tokens);
+ return pos;
+ }
+
+ return 1;
+}
+
+
+/**
+ * Unroll the named built-in uniform variable into a sequence of state
+ * vars in the given parameter list.
+ */
+static GLint
+alloc_state_var_array(const slang_variable *var,
+ struct gl_program_parameter_list *paramList)
+{
+ gl_state_index tokens[STATE_LENGTH];
+ GLuint i;
+ GLint pos;
+
+ /* Initialize the state tokens array. This is very important.
+ * When we call _mesa_add_state_reference() it'll searches the parameter
+ * list to see if the given statevar token sequence is already present.
+ * This is normally a good thing since it prevents redundant values in the
+ * constant buffer.
+ *
+ * But when we're building arrays of state this can be bad. For example,
+ * consider this fragment of GLSL code:
+ * foo = gl_LightSource[3].diffuse;
+ * ...
+ * bar = gl_LightSource[i].diffuse;
+ *
+ * When we unroll the gl_LightSource array (for "bar") we want to re-emit
+ * gl_LightSource[3].diffuse and not re-use the first instance (from "foo")
+ * since that would upset the array layout. We handle this situation by
+ * setting the last token in the state var token array to the special
+ * value STATE_ARRAY.
+ * This token will only be set for array state. We can hijack the last
+ * element in the array for this since it's never used for light, clipplane
+ * or texture env array state.
+ */
+ for (i = 0; i < STATE_LENGTH; i++)
+ tokens[i] = 0;
+ tokens[STATE_LENGTH - 1] = STATE_ARRAY;
+
+ pos = emit_statevars(var->a_name, var->array_len, &var->type.specifier,
+ tokens, paramList);
+
+ return pos;
+}
+
+
+
+/**
+ * Allocate storage for a pre-defined uniform (a GL state variable).
+ * As a memory-saving optimization, we try to only allocate storage for
+ * state vars that are actually used.
+ *
+ * Arrays such as gl_LightSource are handled specially. For an expression
+ * like "gl_LightSource[2].diffuse", we can allocate a single uniform/constant
+ * slot and return the index. In this case, we return direct=TRUE.
+ *
+ * Buf for something like "gl_LightSource[i].diffuse" we don't know the value
+ * of 'i' at compile time so we need to "unroll" the gl_LightSource array
+ * into a consecutive sequence of uniform/constant slots so it can be indexed
+ * at runtime. In this case, we return direct=FALSE.
+ *
+ * Currently, all pre-defined uniforms are in one of these forms:
+ * var
+ * var[i]
+ * var.field
+ * var[i].field
+ * var[i][j]
+ *
+ * \return -1 upon error, else position in paramList of the state variable/data
+ */
+GLint
+_slang_alloc_statevar(slang_ir_node *n,
+ struct gl_program_parameter_list *paramList,
+ GLboolean *direct)
+{
+ slang_ir_node *n0 = n;
+ const char *field = NULL;
+ GLint index1 = -1, index2 = -1;
+ GLuint swizzle;
+
+ *direct = GL_TRUE;
+
+ if (n->Opcode == IR_FIELD) {
+ field = n->Field;
+ n = n->Children[0];
+ }
+
+ if (n->Opcode == IR_ELEMENT) {
+ if (n->Children[1]->Opcode == IR_FLOAT) {
+ index1 = (GLint) n->Children[1]->Value[0];
+ }
+ else {
+ *direct = GL_FALSE;
+ }
+ n = n->Children[0];
+ }
+
+ if (n->Opcode == IR_ELEMENT) {
+ /* XXX can only handle constant indexes for now */
+ if (n->Children[1]->Opcode == IR_FLOAT) {
+ /* two-dimensional array index: mat[i][j] */
+ index2 = index1;
+ index1 = (GLint) n->Children[1]->Value[0];
+ }
+ else {
+ *direct = GL_FALSE;
+ }
+ n = n->Children[0];
+ }
+
+ assert(n->Opcode == IR_VAR);
+
+ if (*direct) {
+ const char *var = (const char *) n->Var->a_name;
+ GLint pos =
+ lookup_statevar(var, index1, index2, field, &swizzle, paramList);
+ if (pos >= 0) {
+ /* newly resolved storage for the statevar/constant/uniform */
+ n0->Store->File = PROGRAM_STATE_VAR;
+ n0->Store->Index = pos;
+ n0->Store->Swizzle = swizzle;
+ n0->Store->Parent = NULL;
+ return pos;
+ }
+ }
+
+ *direct = GL_FALSE;
+ return alloc_state_var_array(n->Var, paramList);
+}
+
+
+
+
+#define SWIZZLE_ZWWW MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W)
+
+
+/** Predefined shader inputs */
+struct input_info
+{
+ const char *Name;
+ GLuint Attrib;
+ GLenum Type;
+ GLuint Swizzle;
+};
+
+/** Predefined vertex shader inputs/attributes */
+static const struct input_info vertInputs[] = {
+ { "gl_Vertex", VERT_ATTRIB_POS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_Normal", VERT_ATTRIB_NORMAL, GL_FLOAT_VEC3, SWIZZLE_NOOP },
+ { "gl_Color", VERT_ATTRIB_COLOR0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_FogCoord", VERT_ATTRIB_FOG, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { NULL, 0, GL_NONE, SWIZZLE_NOOP }
+};
+
+/** Predefined fragment shader inputs */
+static const struct input_info fragInputs[] = {
+ { "gl_FragCoord", FRAG_ATTRIB_WPOS, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_Color", FRAG_ATTRIB_COL0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_SecondaryColor", FRAG_ATTRIB_COL1, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ { "gl_TexCoord", FRAG_ATTRIB_TEX0, GL_FLOAT_VEC4, SWIZZLE_NOOP },
+ /* note: we're packing several quantities into the fogcoord vector */
+ { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_FrontFacing", FRAG_ATTRIB_FACE, GL_FLOAT, SWIZZLE_XXXX },
+ { "gl_PointCoord", FRAG_ATTRIB_PNTC, GL_FLOAT_VEC2, SWIZZLE_XYZW },
+ { NULL, 0, GL_NONE, SWIZZLE_NOOP }
+};
+
+
+/**
+ * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to
+ * a vertex or fragment program input variable. Return -1 if the input
+ * name is invalid.
+ * XXX return size too
+ */
+GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut)
+{
+ const struct input_info *inputs;
+ GLuint i;
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ inputs = vertInputs;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ inputs = fragInputs;
+ break;
+ /* XXX geom program */
+ default:
+ _mesa_problem(NULL, "bad target in _slang_input_index");
+ return -1;
+ }
+
+ ASSERT(MAX_TEXTURE_COORD_UNITS == 8); /* if this fails, fix vertInputs above */
+
+ for (i = 0; inputs[i].Name; i++) {
+ if (strcmp(inputs[i].Name, name) == 0) {
+ /* found */
+ *swizzleOut = inputs[i].Swizzle;
+ return inputs[i].Attrib;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Return name of the given vertex attribute (VERT_ATTRIB_x).
+ */
+const char *
+_slang_vert_attrib_name(GLuint attrib)
+{
+ GLuint i;
+ assert(attrib < VERT_ATTRIB_GENERIC0);
+ for (i = 0; vertInputs[i].Name; i++) {
+ if (vertInputs[i].Attrib == attrib)
+ return vertInputs[i].Name;
+ }
+ return NULL;
+}
+
+
+/**
+ * Return type (GL_FLOAT, GL_FLOAT_VEC2, etc) of the given vertex
+ * attribute (VERT_ATTRIB_x).
+ */
+GLenum
+_slang_vert_attrib_type(GLuint attrib)
+{
+ GLuint i;
+ assert(attrib < VERT_ATTRIB_GENERIC0);
+ for (i = 0; vertInputs[i].Name; i++) {
+ if (vertInputs[i].Attrib == attrib)
+ return vertInputs[i].Type;
+ }
+ return GL_NONE;
+}
+
+
+
+
+
+/** Predefined shader output info */
+struct output_info
+{
+ const char *Name;
+ GLuint Attrib;
+};
+
+/** Predefined vertex shader outputs */
+static const struct output_info vertOutputs[] = {
+ { "gl_Position", VERT_RESULT_HPOS },
+ { "gl_FrontColor", VERT_RESULT_COL0 },
+ { "gl_BackColor", VERT_RESULT_BFC0 },
+ { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
+ { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
+ { "gl_TexCoord", VERT_RESULT_TEX0 },
+ { "gl_FogFragCoord", VERT_RESULT_FOGC },
+ { "gl_PointSize", VERT_RESULT_PSIZ },
+ { NULL, 0 }
+};
+
+/** Predefined fragment shader outputs */
+static const struct output_info fragOutputs[] = {
+ { "gl_FragColor", FRAG_RESULT_COLOR },
+ { "gl_FragDepth", FRAG_RESULT_DEPTH },
+ { "gl_FragData", FRAG_RESULT_DATA0 },
+ { NULL, 0 }
+};
+
+
+/**
+ * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to
+ * a vertex or fragment program output variable. Return -1 for an invalid
+ * output name.
+ */
+GLint
+_slang_output_index(const char *name, GLenum target)
+{
+ const struct output_info *outputs;
+ GLuint i;
+
+ switch (target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ outputs = vertOutputs;
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ outputs = fragOutputs;
+ break;
+ /* XXX geom program */
+ default:
+ _mesa_problem(NULL, "bad target in _slang_output_index");
+ return -1;
+ }
+
+ for (i = 0; outputs[i].Name; i++) {
+ if (strcmp(outputs[i].Name, name) == 0) {
+ /* found */
+ return outputs[i].Attrib;
+ }
+ }
+ return -1;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_builtin.h b/mesalib/src/mesa/shader/slang/slang_builtin.h
new file mode 100644
index 000000000..f814d11ac
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_builtin.h
@@ -0,0 +1,54 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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 SLANG_BUILTIN_H
+#define SLANG_BUILTIN_H
+
+#include "shader/prog_parameter.h"
+#include "slang_utility.h"
+#include "slang_ir.h"
+
+
+extern GLint
+_slang_alloc_statevar(slang_ir_node *n,
+ struct gl_program_parameter_list *paramList,
+ GLboolean *direct);
+
+
+extern GLint
+_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut);
+
+extern GLint
+_slang_output_index(const char *name, GLenum target);
+
+
+extern const char *
+_slang_vert_attrib_name(GLuint attrib);
+
+extern GLenum
+_slang_vert_attrib_type(GLuint attrib);
+
+
+#endif /* SLANG_BUILTIN_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_codegen.c b/mesalib/src/mesa/shader/slang/slang_codegen.c
new file mode 100644
index 000000000..703af9f87
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_codegen.c
@@ -0,0 +1,5319 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_codegen.c
+ * Generate IR tree from AST.
+ * \author Brian Paul
+ */
+
+
+/***
+ *** NOTES:
+ *** The new_() functions return a new instance of a simple IR node.
+ *** The gen_() functions generate larger IR trees from the simple nodes.
+ ***/
+
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "slang_typeinfo.h"
+#include "slang_builtin.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_label.h"
+#include "slang_mem.h"
+#include "slang_simplify.h"
+#include "slang_emit.h"
+#include "slang_vartable.h"
+#include "slang_ir.h"
+#include "slang_print.h"
+
+
+/** Max iterations to unroll */
+const GLuint MAX_FOR_LOOP_UNROLL_ITERATIONS = 32;
+
+/** Max for-loop body size (in slang operations) to unroll */
+const GLuint MAX_FOR_LOOP_UNROLL_BODY_SIZE = 50;
+
+/** Max for-loop body complexity to unroll.
+ * We'll compute complexity as the product of the number of iterations
+ * and the size of the body. So long-ish loops with very simple bodies
+ * can be unrolled, as well as short loops with larger bodies.
+ */
+const GLuint MAX_FOR_LOOP_UNROLL_COMPLEXITY = 256;
+
+
+
+static slang_ir_node *
+_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
+
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+ GLuint substCount, slang_variable **substOld,
+ slang_operation **substNew, GLboolean isLHS);
+
+
+/**
+ * Retrieves type information about an operation.
+ * Returns GL_TRUE on success.
+ * Returns GL_FALSE otherwise.
+ */
+static GLboolean
+typeof_operation(const struct slang_assemble_ctx_ *A,
+ slang_operation *op,
+ slang_typeinfo *ti)
+{
+ return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
+}
+
+
+static GLboolean
+is_sampler_type(const slang_fully_specified_type *t)
+{
+ switch (t->specifier.type) {
+ case SLANG_SPEC_SAMPLER1D:
+ case SLANG_SPEC_SAMPLER2D:
+ case SLANG_SPEC_SAMPLER3D:
+ case SLANG_SPEC_SAMPLERCUBE:
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ case SLANG_SPEC_SAMPLER2DRECT:
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Return the offset (in floats or ints) of the named field within
+ * the given struct. Return -1 if field not found.
+ * If field is NULL, return the size of the struct instead.
+ */
+static GLint
+_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
+{
+ GLint offset = 0;
+ GLuint i;
+ for (i = 0; i < spec->_struct->fields->num_variables; i++) {
+ const slang_variable *v = spec->_struct->fields->variables[i];
+ const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
+ if (sz > 1) {
+ /* types larger than 1 float are register (4-float) aligned */
+ offset = (offset + 3) & ~3;
+ }
+ if (field && v->a_name == field) {
+ return offset;
+ }
+ offset += sz;
+ }
+ if (field)
+ return -1; /* field not found */
+ else
+ return offset; /* struct size */
+}
+
+
+/**
+ * Return the size (in floats) of the given type specifier.
+ * If the size is greater than 4, the size should be a multiple of 4
+ * so that the correct number of 4-float registers are allocated.
+ * For example, a mat3x2 is size 12 because we want to store the
+ * 3 columns in 3 float[4] registers.
+ */
+GLuint
+_slang_sizeof_type_specifier(const slang_type_specifier *spec)
+{
+ GLuint sz;
+ switch (spec->type) {
+ case SLANG_SPEC_VOID:
+ sz = 0;
+ break;
+ case SLANG_SPEC_BOOL:
+ sz = 1;
+ break;
+ case SLANG_SPEC_BVEC2:
+ sz = 2;
+ break;
+ case SLANG_SPEC_BVEC3:
+ sz = 3;
+ break;
+ case SLANG_SPEC_BVEC4:
+ sz = 4;
+ break;
+ case SLANG_SPEC_INT:
+ sz = 1;
+ break;
+ case SLANG_SPEC_IVEC2:
+ sz = 2;
+ break;
+ case SLANG_SPEC_IVEC3:
+ sz = 3;
+ break;
+ case SLANG_SPEC_IVEC4:
+ sz = 4;
+ break;
+ case SLANG_SPEC_FLOAT:
+ sz = 1;
+ break;
+ case SLANG_SPEC_VEC2:
+ sz = 2;
+ break;
+ case SLANG_SPEC_VEC3:
+ sz = 3;
+ break;
+ case SLANG_SPEC_VEC4:
+ sz = 4;
+ break;
+ case SLANG_SPEC_MAT2:
+ sz = 2 * 4; /* 2 columns (regs) */
+ break;
+ case SLANG_SPEC_MAT3:
+ sz = 3 * 4;
+ break;
+ case SLANG_SPEC_MAT4:
+ sz = 4 * 4;
+ break;
+ case SLANG_SPEC_MAT23:
+ sz = 2 * 4; /* 2 columns (regs) */
+ break;
+ case SLANG_SPEC_MAT32:
+ sz = 3 * 4; /* 3 columns (regs) */
+ break;
+ case SLANG_SPEC_MAT24:
+ sz = 2 * 4;
+ break;
+ case SLANG_SPEC_MAT42:
+ sz = 4 * 4; /* 4 columns (regs) */
+ break;
+ case SLANG_SPEC_MAT34:
+ sz = 3 * 4;
+ break;
+ case SLANG_SPEC_MAT43:
+ sz = 4 * 4; /* 4 columns (regs) */
+ break;
+ case SLANG_SPEC_SAMPLER1D:
+ case SLANG_SPEC_SAMPLER2D:
+ case SLANG_SPEC_SAMPLER3D:
+ case SLANG_SPEC_SAMPLERCUBE:
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ case SLANG_SPEC_SAMPLER2DRECT:
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ sz = 1; /* a sampler is basically just an integer index */
+ break;
+ case SLANG_SPEC_STRUCT:
+ sz = _slang_field_offset(spec, 0); /* special use */
+ if (sz == 1) {
+ /* 1-float structs are actually troublesome to deal with since they
+ * might get placed at R.x, R.y, R.z or R.z. Return size=2 to
+ * ensure the object is placed at R.x
+ */
+ sz = 2;
+ }
+ else if (sz > 4) {
+ sz = (sz + 3) & ~0x3; /* round up to multiple of four */
+ }
+ break;
+ case SLANG_SPEC_ARRAY:
+ sz = _slang_sizeof_type_specifier(spec->_array);
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()");
+ sz = 0;
+ }
+
+ if (sz > 4) {
+ /* if size is > 4, it should be a multiple of four */
+ assert((sz & 0x3) == 0);
+ }
+ return sz;
+}
+
+
+/**
+ * Query variable/array length (number of elements).
+ * This is slightly non-trivial because there are two ways to express
+ * arrays: "float x[3]" vs. "float[3] x".
+ * \return the length of the array for the given variable, or 0 if not an array
+ */
+static GLint
+_slang_array_length(const slang_variable *var)
+{
+ if (var->type.array_len > 0) {
+ /* Ex: float[4] x; */
+ return var->type.array_len;
+ }
+ if (var->array_len > 0) {
+ /* Ex: float x[4]; */
+ return var->array_len;
+ }
+ return 0;
+}
+
+
+/**
+ * Compute total size of array give size of element, number of elements.
+ * \return size in floats
+ */
+static GLint
+_slang_array_size(GLint elemSize, GLint arrayLen)
+{
+ GLint total;
+ assert(elemSize > 0);
+ if (arrayLen > 1) {
+ /* round up base type to multiple of 4 */
+ total = ((elemSize + 3) & ~0x3) * MAX2(arrayLen, 1);
+ }
+ else {
+ total = elemSize;
+ }
+ return total;
+}
+
+
+/**
+ * Return the TEXTURE_*_INDEX value that corresponds to a sampler type,
+ * or -1 if the type is not a sampler.
+ */
+static GLint
+sampler_to_texture_index(const slang_type_specifier_type type)
+{
+ switch (type) {
+ case SLANG_SPEC_SAMPLER1D:
+ return TEXTURE_1D_INDEX;
+ case SLANG_SPEC_SAMPLER2D:
+ return TEXTURE_2D_INDEX;
+ case SLANG_SPEC_SAMPLER3D:
+ return TEXTURE_3D_INDEX;
+ case SLANG_SPEC_SAMPLERCUBE:
+ return TEXTURE_CUBE_INDEX;
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ return TEXTURE_1D_INDEX; /* XXX fix */
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ return TEXTURE_2D_INDEX; /* XXX fix */
+ case SLANG_SPEC_SAMPLER2DRECT:
+ return TEXTURE_RECT_INDEX;
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return TEXTURE_RECT_INDEX; /* XXX fix */
+ default:
+ return -1;
+ }
+}
+
+
+/** helper to build a SLANG_OPER_IDENTIFIER node */
+static void
+slang_operation_identifier(slang_operation *oper,
+ slang_assemble_ctx *A,
+ const char *name)
+{
+ oper->type = SLANG_OPER_IDENTIFIER;
+ oper->a_id = slang_atom_pool_atom(A->atoms, name);
+}
+
+
+/**
+ * Called when we begin code/IR generation for a new while/do/for loop.
+ */
+static void
+push_loop(slang_assemble_ctx *A, slang_operation *loopOper, slang_ir_node *loopIR)
+{
+ A->LoopOperStack[A->LoopDepth] = loopOper;
+ A->LoopIRStack[A->LoopDepth] = loopIR;
+ A->LoopDepth++;
+}
+
+
+/**
+ * Called when we end code/IR generation for a new while/do/for loop.
+ */
+static void
+pop_loop(slang_assemble_ctx *A)
+{
+ assert(A->LoopDepth > 0);
+ A->LoopDepth--;
+}
+
+
+/**
+ * Return pointer to slang_operation for the loop we're currently inside,
+ * or NULL if not in a loop.
+ */
+static const slang_operation *
+current_loop_oper(const slang_assemble_ctx *A)
+{
+ if (A->LoopDepth > 0)
+ return A->LoopOperStack[A->LoopDepth - 1];
+ else
+ return NULL;
+}
+
+
+/**
+ * Return pointer to slang_ir_node for the loop we're currently inside,
+ * or NULL if not in a loop.
+ */
+static slang_ir_node *
+current_loop_ir(const slang_assemble_ctx *A)
+{
+ if (A->LoopDepth > 0)
+ return A->LoopIRStack[A->LoopDepth - 1];
+ else
+ return NULL;
+}
+
+
+/**********************************************************************/
+
+
+/**
+ * Map "_asm foo" to IR_FOO, etc.
+ */
+typedef struct
+{
+ const char *Name;
+ slang_ir_opcode Opcode;
+ GLuint HaveRetValue, NumParams;
+} slang_asm_info;
+
+
+static slang_asm_info AsmInfo[] = {
+ /* vec4 binary op */
+ { "vec4_add", IR_ADD, 1, 2 },
+ { "vec4_subtract", IR_SUB, 1, 2 },
+ { "vec4_multiply", IR_MUL, 1, 2 },
+ { "vec4_dot", IR_DOT4, 1, 2 },
+ { "vec3_dot", IR_DOT3, 1, 2 },
+ { "vec2_dot", IR_DOT2, 1, 2 },
+ { "vec3_nrm", IR_NRM3, 1, 1 },
+ { "vec4_nrm", IR_NRM4, 1, 1 },
+ { "vec3_cross", IR_CROSS, 1, 2 },
+ { "vec4_lrp", IR_LRP, 1, 3 },
+ { "vec4_min", IR_MIN, 1, 2 },
+ { "vec4_max", IR_MAX, 1, 2 },
+ { "vec4_clamp", IR_CLAMP, 1, 3 },
+ { "vec4_seq", IR_SEQUAL, 1, 2 },
+ { "vec4_sne", IR_SNEQUAL, 1, 2 },
+ { "vec4_sge", IR_SGE, 1, 2 },
+ { "vec4_sgt", IR_SGT, 1, 2 },
+ { "vec4_sle", IR_SLE, 1, 2 },
+ { "vec4_slt", IR_SLT, 1, 2 },
+ /* vec4 unary */
+ { "vec4_move", IR_MOVE, 1, 1 },
+ { "vec4_floor", IR_FLOOR, 1, 1 },
+ { "vec4_frac", IR_FRAC, 1, 1 },
+ { "vec4_abs", IR_ABS, 1, 1 },
+ { "vec4_negate", IR_NEG, 1, 1 },
+ { "vec4_ddx", IR_DDX, 1, 1 },
+ { "vec4_ddy", IR_DDY, 1, 1 },
+ /* float binary op */
+ { "float_power", IR_POW, 1, 2 },
+ /* texture / sampler */
+ { "vec4_tex_1d", IR_TEX, 1, 2 },
+ { "vec4_tex_1d_bias", IR_TEXB, 1, 2 }, /* 1d w/ bias */
+ { "vec4_tex_1d_proj", IR_TEXP, 1, 2 }, /* 1d w/ projection */
+ { "vec4_tex_2d", IR_TEX, 1, 2 },
+ { "vec4_tex_2d_bias", IR_TEXB, 1, 2 }, /* 2d w/ bias */
+ { "vec4_tex_2d_proj", IR_TEXP, 1, 2 }, /* 2d w/ projection */
+ { "vec4_tex_3d", IR_TEX, 1, 2 },
+ { "vec4_tex_3d_bias", IR_TEXB, 1, 2 }, /* 3d w/ bias */
+ { "vec4_tex_3d_proj", IR_TEXP, 1, 2 }, /* 3d w/ projection */
+ { "vec4_tex_cube", IR_TEX, 1, 2 }, /* cubemap */
+ { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */
+ { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */
+
+ /* texture / sampler but with shadow comparison */
+ { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 },
+ { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 },
+ { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 },
+ { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 },
+ { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 },
+ { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 },
+
+ /* unary op */
+ { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */
+ { "vec4_to_ivec4", IR_F_TO_I, 1, 1 }, /* float[4] to int[4] */
+ { "float_exp", IR_EXP, 1, 1 },
+ { "float_exp2", IR_EXP2, 1, 1 },
+ { "float_log2", IR_LOG2, 1, 1 },
+ { "float_rsq", IR_RSQ, 1, 1 },
+ { "float_rcp", IR_RCP, 1, 1 },
+ { "float_sine", IR_SIN, 1, 1 },
+ { "float_cosine", IR_COS, 1, 1 },
+ { "float_noise1", IR_NOISE1, 1, 1},
+ { "float_noise2", IR_NOISE2, 1, 1},
+ { "float_noise3", IR_NOISE3, 1, 1},
+ { "float_noise4", IR_NOISE4, 1, 1},
+
+ { NULL, IR_NOP, 0, 0 }
+};
+
+
+static slang_ir_node *
+new_node3(slang_ir_opcode op,
+ slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2)
+{
+ slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node));
+ if (n) {
+ n->Opcode = op;
+ n->Children[0] = c0;
+ n->Children[1] = c1;
+ n->Children[2] = c2;
+ n->InstLocation = -1;
+ }
+ return n;
+}
+
+static slang_ir_node *
+new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1)
+{
+ return new_node3(op, c0, c1, NULL);
+}
+
+static slang_ir_node *
+new_node1(slang_ir_opcode op, slang_ir_node *c0)
+{
+ return new_node3(op, c0, NULL, NULL);
+}
+
+static slang_ir_node *
+new_node0(slang_ir_opcode op)
+{
+ return new_node3(op, NULL, NULL, NULL);
+}
+
+
+/**
+ * Create sequence of two nodes.
+ */
+static slang_ir_node *
+new_seq(slang_ir_node *left, slang_ir_node *right)
+{
+ if (!left)
+ return right;
+ if (!right)
+ return left;
+ return new_node2(IR_SEQ, left, right);
+}
+
+static slang_ir_node *
+new_label(slang_label *label)
+{
+ slang_ir_node *n = new_node0(IR_LABEL);
+ assert(label);
+ if (n)
+ n->Label = label;
+ return n;
+}
+
+static slang_ir_node *
+new_float_literal(const float v[4], GLuint size)
+{
+ slang_ir_node *n = new_node0(IR_FLOAT);
+ assert(size <= 4);
+ COPY_4V(n->Value, v);
+ /* allocate a storage object, but compute actual location (Index) later */
+ n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
+ return n;
+}
+
+
+static slang_ir_node *
+new_not(slang_ir_node *n)
+{
+ return new_node1(IR_NOT, n);
+}
+
+
+/**
+ * Non-inlined function call.
+ */
+static slang_ir_node *
+new_function_call(slang_ir_node *code, slang_label *name)
+{
+ slang_ir_node *n = new_node1(IR_CALL, code);
+ assert(name);
+ if (n)
+ n->Label = name;
+ return n;
+}
+
+
+/**
+ * Unconditional jump.
+ */
+static slang_ir_node *
+new_return(slang_label *dest)
+{
+ slang_ir_node *n = new_node0(IR_RETURN);
+ assert(dest);
+ if (n)
+ n->Label = dest;
+ return n;
+}
+
+
+static slang_ir_node *
+new_loop(slang_ir_node *body)
+{
+ return new_node1(IR_LOOP, body);
+}
+
+
+static slang_ir_node *
+new_break(slang_ir_node *loopNode)
+{
+ slang_ir_node *n = new_node0(IR_BREAK);
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+ if (n) {
+ /* insert this node at head of linked list of cont/break instructions */
+ n->List = loopNode->List;
+ loopNode->List = n;
+ }
+ return n;
+}
+
+
+/**
+ * Make new IR_BREAK_IF_TRUE.
+ */
+static slang_ir_node *
+new_break_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
+{
+ slang_ir_node *loopNode = current_loop_ir(A);
+ slang_ir_node *n;
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+ n = new_node1(IR_BREAK_IF_TRUE, cond);
+ if (n) {
+ /* insert this node at head of linked list of cont/break instructions */
+ n->List = loopNode->List;
+ loopNode->List = n;
+ }
+ return n;
+}
+
+
+/**
+ * Make new IR_CONT_IF_TRUE node.
+ */
+static slang_ir_node *
+new_cont_if_true(slang_assemble_ctx *A, slang_ir_node *cond)
+{
+ slang_ir_node *loopNode = current_loop_ir(A);
+ slang_ir_node *n;
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+ n = new_node1(IR_CONT_IF_TRUE, cond);
+ if (n) {
+ n->Parent = loopNode; /* pointer to containing loop */
+ /* insert this node at head of linked list of cont/break instructions */
+ n->List = loopNode->List;
+ loopNode->List = n;
+ }
+ return n;
+}
+
+
+static slang_ir_node *
+new_cond(slang_ir_node *n)
+{
+ slang_ir_node *c = new_node1(IR_COND, n);
+ return c;
+}
+
+
+static slang_ir_node *
+new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
+{
+ return new_node3(IR_IF, cond, ifPart, elsePart);
+}
+
+
+/**
+ * New IR_VAR node - a reference to a previously declared variable.
+ */
+static slang_ir_node *
+new_var(slang_assemble_ctx *A, slang_variable *var)
+{
+ slang_ir_node *n = new_node0(IR_VAR);
+ if (n) {
+ ASSERT(var);
+ ASSERT(var->store);
+ ASSERT(!n->Store);
+ ASSERT(!n->Var);
+
+ /* Set IR node's Var and Store pointers */
+ n->Var = var;
+ n->Store = var->store;
+ }
+ return n;
+}
+
+
+/**
+ * Check if the given function is really just a wrapper for a
+ * basic assembly instruction.
+ */
+static GLboolean
+slang_is_asm_function(const slang_function *fun)
+{
+ if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE &&
+ fun->body->num_children == 1 &&
+ fun->body->children[0].type == SLANG_OPER_ASM) {
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+ if (!oper ||
+ oper->type == SLANG_OPER_VOID ||
+ (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+/**
+ * Recursively search tree for a node of the given type.
+ */
+#if 0
+static slang_operation *
+_slang_find_node_type(slang_operation *oper, slang_operation_type type)
+{
+ GLuint i;
+ if (oper->type == type)
+ return oper;
+ for (i = 0; i < oper->num_children; i++) {
+ slang_operation *p = _slang_find_node_type(&oper->children[i], type);
+ if (p)
+ return p;
+ }
+ return NULL;
+}
+#endif
+
+
+/**
+ * Count the number of operations of the given time rooted at 'oper'.
+ */
+static GLuint
+_slang_count_node_type(const slang_operation *oper, slang_operation_type type)
+{
+ GLuint i, count = 0;
+ if (oper->type == type) {
+ return 1;
+ }
+ for (i = 0; i < oper->num_children; i++) {
+ count += _slang_count_node_type(&oper->children[i], type);
+ }
+ return count;
+}
+
+
+/**
+ * Check if the 'return' statement found under 'oper' is a "tail return"
+ * that can be no-op'd. For example:
+ *
+ * void func(void)
+ * {
+ * .. do something ..
+ * return; // this is a no-op
+ * }
+ *
+ * This is used when determining if a function can be inlined. If the
+ * 'return' is not the last statement, we can't inline the function since
+ * we still need the semantic behaviour of the 'return' but we don't want
+ * to accidentally return from the _calling_ function. We'd need to use an
+ * unconditional branch, but we don't have such a GPU instruction (not
+ * always, at least).
+ */
+static GLboolean
+_slang_is_tail_return(const slang_operation *oper)
+{
+ GLuint k = oper->num_children;
+
+ while (k > 0) {
+ const slang_operation *last = &oper->children[k - 1];
+ if (last->type == SLANG_OPER_RETURN)
+ return GL_TRUE;
+ else if (last->type == SLANG_OPER_IDENTIFIER ||
+ last->type == SLANG_OPER_LABEL)
+ k--; /* try prev child */
+ else if (last->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+ last->type == SLANG_OPER_BLOCK_NEW_SCOPE)
+ /* try sub-children */
+ return _slang_is_tail_return(last);
+ else
+ break;
+ }
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Generate a variable declaration opeartion.
+ * I.e.: generate AST code for "bool flag = false;"
+ */
+static void
+slang_generate_declaration(slang_assemble_ctx *A,
+ slang_variable_scope *scope,
+ slang_operation *decl,
+ slang_type_specifier_type type,
+ const char *name,
+ GLint initValue)
+{
+ slang_variable *var;
+
+ assert(type == SLANG_SPEC_BOOL ||
+ type == SLANG_SPEC_INT);
+
+ decl->type = SLANG_OPER_VARIABLE_DECL;
+
+ var = slang_variable_scope_grow(scope);
+
+ slang_fully_specified_type_construct(&var->type);
+
+ var->type.specifier.type = type;
+ var->a_name = slang_atom_pool_atom(A->atoms, name);
+ decl->a_id = var->a_name;
+ var->initializer = slang_operation_new(1);
+ slang_operation_literal_bool(var->initializer, initValue);
+}
+
+
+static void
+slang_resolve_variable(slang_operation *oper)
+{
+ if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
+ oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ }
+}
+
+
+/**
+ * Rewrite AST code for "return expression;".
+ *
+ * We return values from functions by assinging the returned value to
+ * the hidden __retVal variable which is an extra 'out' parameter we add
+ * to the function signature.
+ * This code basically converts "return expr;" into "__retVal = expr; return;"
+ *
+ * \return the new AST code.
+ */
+static slang_operation *
+gen_return_with_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *blockOper, *assignOper;
+
+ assert(oper->type == SLANG_OPER_RETURN);
+
+ if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "illegal return expression");
+ return NULL;
+ }
+
+ blockOper = slang_operation_new(1);
+ blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ blockOper->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(blockOper, 2);
+
+ if (A->UseReturnFlag) {
+ /* Emit:
+ * {
+ * if (__notRetFlag)
+ * __retVal = expr;
+ * __notRetFlag = 0;
+ * }
+ */
+ {
+ slang_operation *ifOper = slang_oper_child(blockOper, 0);
+ ifOper->type = SLANG_OPER_IF;
+ slang_operation_add_children(ifOper, 3);
+ {
+ slang_operation *cond = slang_oper_child(ifOper, 0);
+ cond->type = SLANG_OPER_IDENTIFIER;
+ cond->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *elseOper = slang_oper_child(ifOper, 2);
+ elseOper->type = SLANG_OPER_VOID;
+ }
+ assignOper = slang_oper_child(ifOper, 1);
+ }
+ {
+ slang_operation *setOper = slang_oper_child(blockOper, 1);
+ setOper->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(setOper, 2);
+ {
+ slang_operation *lhs = slang_oper_child(setOper, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(setOper, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ }
+ else {
+ /* Emit:
+ * {
+ * __retVal = expr;
+ * return_inlined;
+ * }
+ */
+ assignOper = slang_oper_child(blockOper, 0);
+ {
+ slang_operation *returnOper = slang_oper_child(blockOper, 1);
+ returnOper->type = SLANG_OPER_RETURN_INLINED;
+ assert(returnOper->num_children == 0);
+ }
+ }
+
+ /* __retVal = expression; */
+ assignOper->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(assignOper, 2);
+ {
+ slang_operation *lhs = slang_oper_child(assignOper, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__retVal");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(assignOper, 1);
+ slang_operation_copy(rhs, &oper->children[0]);
+ }
+
+ ///blockOper->locals->outer_scope = oper->locals->outer_scope;
+
+ /*slang_print_tree(blockOper, 0);*/
+
+ return blockOper;
+}
+
+
+/**
+ * Rewrite AST code for "return;" (no expression).
+ */
+static slang_operation *
+gen_return_without_expression(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *newRet;
+
+ assert(oper->type == SLANG_OPER_RETURN);
+
+ if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+ slang_info_log_error(A->log, "return statement requires an expression");
+ return NULL;
+ }
+
+ if (A->UseReturnFlag) {
+ /* Emit:
+ * __notRetFlag = 0;
+ */
+ {
+ newRet = slang_operation_new(1);
+ newRet->locals->outer_scope = oper->locals->outer_scope;
+ newRet->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(newRet, 2);
+ {
+ slang_operation *lhs = slang_oper_child(newRet, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(newRet, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ }
+ else {
+ /* Emit:
+ * return_inlined;
+ */
+ newRet = slang_operation_new(1);
+ newRet->locals->outer_scope = oper->locals->outer_scope;
+ newRet->type = SLANG_OPER_RETURN_INLINED;
+ }
+
+ /*slang_print_tree(newRet, 0);*/
+
+ return newRet;
+}
+
+
+
+
+/**
+ * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions.
+ */
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+ GLuint substCount, slang_variable **substOld,
+ slang_operation **substNew, GLboolean isLHS)
+{
+ switch (oper->type) {
+ case SLANG_OPER_VARIABLE_DECL:
+ {
+ slang_variable *v = _slang_variable_locate(oper->locals,
+ oper->a_id, GL_TRUE);
+ assert(v);
+ if (v->initializer && oper->num_children == 0) {
+ /* set child of oper to copy of initializer */
+ oper->num_children = 1;
+ oper->children = slang_operation_new(1);
+ slang_operation_copy(&oper->children[0], v->initializer);
+ }
+ if (oper->num_children == 1) {
+ /* the initializer */
+ slang_substitute(A, &oper->children[0], substCount,
+ substOld, substNew, GL_FALSE);
+ }
+ }
+ break;
+ case SLANG_OPER_IDENTIFIER:
+ assert(oper->num_children == 0);
+ if (1/**!isLHS XXX FIX */) {
+ slang_atom id = oper->a_id;
+ slang_variable *v;
+ GLuint i;
+ v = _slang_variable_locate(oper->locals, id, GL_TRUE);
+ if (!v) {
+ if (_mesa_strcmp((char *) oper->a_id, "__notRetFlag"))
+ _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
+ return;
+ }
+
+ /* look for a substitution */
+ for (i = 0; i < substCount; i++) {
+ if (v == substOld[i]) {
+ /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */
+#if 0 /* DEBUG only */
+ if (substNew[i]->type == SLANG_OPER_IDENTIFIER) {
+ assert(substNew[i]->var);
+ assert(substNew[i]->var->a_name);
+ printf("Substitute %s with %s in id node %p\n",
+ (char*)v->a_name, (char*) substNew[i]->var->a_name,
+ (void*) oper);
+ }
+ else {
+ printf("Substitute %s with %f in id node %p\n",
+ (char*)v->a_name, substNew[i]->literal[0],
+ (void*) oper);
+ }
+#endif
+ slang_operation_copy(oper, substNew[i]);
+ break;
+ }
+ }
+ }
+ break;
+
+ case SLANG_OPER_RETURN:
+ {
+ slang_operation *newReturn;
+ /* generate new 'return' code' */
+ if (slang_oper_child(oper, 0)->type == SLANG_OPER_VOID)
+ newReturn = gen_return_without_expression(A, oper);
+ else
+ newReturn = gen_return_with_expression(A, oper);
+
+ if (!newReturn)
+ return;
+
+ /* do substitutions on the new 'return' code */
+ slang_substitute(A, newReturn,
+ substCount, substOld, substNew, GL_FALSE);
+
+ /* install new 'return' code */
+ slang_operation_copy(oper, newReturn);
+ slang_operation_destruct(newReturn);
+ }
+ break;
+
+ case SLANG_OPER_ASSIGN:
+ case SLANG_OPER_SUBSCRIPT:
+ /* special case:
+ * child[0] can't have substitutions but child[1] can.
+ */
+ slang_substitute(A, &oper->children[0],
+ substCount, substOld, substNew, GL_TRUE);
+ slang_substitute(A, &oper->children[1],
+ substCount, substOld, substNew, GL_FALSE);
+ break;
+ case SLANG_OPER_FIELD:
+ /* XXX NEW - test */
+ slang_substitute(A, &oper->children[0],
+ substCount, substOld, substNew, GL_TRUE);
+ break;
+ default:
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++)
+ slang_substitute(A, &oper->children[i],
+ substCount, substOld, substNew, GL_FALSE);
+ }
+ }
+}
+
+
+/**
+ * Produce inline code for a call to an assembly instruction.
+ * This is typically used to compile a call to a built-in function like this:
+ *
+ * vec4 mix(const vec4 x, const vec4 y, const vec4 a)
+ * {
+ * __asm vec4_lrp __retVal, a, y, x;
+ * }
+ *
+ *
+ * A call to
+ * r = mix(p1, p2, p3);
+ *
+ * Becomes:
+ *
+ * mov
+ * / \
+ * r vec4_lrp
+ * / | \
+ * p3 p2 p1
+ *
+ * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM.
+ */
+static slang_operation *
+slang_inline_asm_function(slang_assemble_ctx *A,
+ slang_function *fun, slang_operation *oper)
+{
+ const GLuint numArgs = oper->num_children;
+ GLuint i;
+ slang_operation *inlined;
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ slang_variable **substOld;
+ slang_operation **substNew;
+
+ ASSERT(slang_is_asm_function(fun));
+ ASSERT(fun->param_count == numArgs + haveRetValue);
+
+ /*
+ printf("Inline %s as %s\n",
+ (char*) fun->header.a_name,
+ (char*) fun->body->children[0].a_id);
+ */
+
+ /*
+ * We'll substitute formal params with actual args in the asm call.
+ */
+ substOld = (slang_variable **)
+ _slang_alloc(numArgs * sizeof(slang_variable *));
+ substNew = (slang_operation **)
+ _slang_alloc(numArgs * sizeof(slang_operation *));
+ for (i = 0; i < numArgs; i++) {
+ substOld[i] = fun->parameters->variables[i];
+ substNew[i] = oper->children + i;
+ }
+
+ /* make a copy of the code to inline */
+ inlined = slang_operation_new(1);
+ slang_operation_copy(inlined, &fun->body->children[0]);
+ if (haveRetValue) {
+ /* get rid of the __retVal child */
+ inlined->num_children--;
+ for (i = 0; i < inlined->num_children; i++) {
+ inlined->children[i] = inlined->children[i + 1];
+ }
+ }
+
+ /* now do formal->actual substitutions */
+ slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);
+
+ _slang_free(substOld);
+ _slang_free(substNew);
+
+#if 0
+ printf("+++++++++++++ inlined asm function %s +++++++++++++\n",
+ (char *) fun->header.a_name);
+ slang_print_tree(inlined, 3);
+ printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
+#endif
+
+ return inlined;
+}
+
+
+/**
+ * Inline the given function call operation.
+ * Return a new slang_operation that corresponds to the inlined code.
+ */
+static slang_operation *
+slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
+ slang_operation *oper, slang_operation *returnOper)
+{
+ typedef enum {
+ SUBST = 1,
+ COPY_IN,
+ COPY_OUT
+ } ParamMode;
+ ParamMode *paramMode;
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ const GLuint numArgs = oper->num_children;
+ const GLuint totalArgs = numArgs + haveRetValue;
+ slang_operation *args = oper->children;
+ slang_operation *inlined, *top;
+ slang_variable **substOld;
+ slang_operation **substNew;
+ GLuint substCount, numCopyIn, i;
+ slang_function *prevFunction;
+ slang_variable_scope *newScope = NULL;
+
+ /* save / push */
+ prevFunction = A->CurFunction;
+ A->CurFunction = fun;
+
+ /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
+ assert(fun->param_count == totalArgs);
+
+ /* allocate temporary arrays */
+ paramMode = (ParamMode *)
+ _slang_alloc(totalArgs * sizeof(ParamMode));
+ substOld = (slang_variable **)
+ _slang_alloc(totalArgs * sizeof(slang_variable *));
+ substNew = (slang_operation **)
+ _slang_alloc(totalArgs * sizeof(slang_operation *));
+
+#if 0
+ printf("\nInline call to %s (total vars=%d nparams=%d)\n",
+ (char *) fun->header.a_name,
+ fun->parameters->num_variables, numArgs);
+#endif
+
+ if (haveRetValue && !returnOper) {
+ /* Create 3-child comma sequence for inlined code:
+ * child[0]: declare __resultTmp
+ * child[1]: inlined function body
+ * child[2]: __resultTmp
+ */
+ slang_operation *commaSeq;
+ slang_operation *declOper = NULL;
+ slang_variable *resultVar;
+
+ commaSeq = slang_operation_new(1);
+ commaSeq->type = SLANG_OPER_SEQUENCE;
+ assert(commaSeq->locals);
+ commaSeq->locals->outer_scope = oper->locals->outer_scope;
+ commaSeq->num_children = 3;
+ commaSeq->children = slang_operation_new(3);
+ /* allocate the return var */
+ resultVar = slang_variable_scope_grow(commaSeq->locals);
+ /*
+ printf("Alloc __resultTmp in scope %p for retval of calling %s\n",
+ (void*)commaSeq->locals, (char *) fun->header.a_name);
+ */
+
+ resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
+ resultVar->type = fun->header.type; /* XXX copy? */
+ resultVar->isTemp = GL_TRUE;
+
+ /* child[0] = __resultTmp declaration */
+ declOper = &commaSeq->children[0];
+ declOper->type = SLANG_OPER_VARIABLE_DECL;
+ declOper->a_id = resultVar->a_name;
+ declOper->locals->outer_scope = commaSeq->locals;
+
+ /* child[1] = function body */
+ inlined = &commaSeq->children[1];
+ inlined->locals->outer_scope = commaSeq->locals;
+
+ /* child[2] = __resultTmp reference */
+ returnOper = &commaSeq->children[2];
+ returnOper->type = SLANG_OPER_IDENTIFIER;
+ returnOper->a_id = resultVar->a_name;
+ returnOper->locals->outer_scope = commaSeq->locals;
+
+ top = commaSeq;
+ }
+ else {
+ top = inlined = slang_operation_new(1);
+ /* XXXX this may be inappropriate!!!! */
+ inlined->locals->outer_scope = oper->locals->outer_scope;
+ }
+
+
+ assert(inlined->locals);
+
+ /* Examine the parameters, look for inout/out params, look for possible
+ * substitutions, etc:
+ * param type behaviour
+ * in copy actual to local
+ * const in substitute param with actual
+ * out copy out
+ */
+ substCount = 0;
+ for (i = 0; i < totalArgs; i++) {
+ slang_variable *p = fun->parameters->variables[i];
+ /*
+ printf("Param %d: %s %s \n", i,
+ slang_type_qual_string(p->type.qualifier),
+ (char *) p->a_name);
+ */
+ if (p->type.qualifier == SLANG_QUAL_INOUT ||
+ p->type.qualifier == SLANG_QUAL_OUT) {
+ /* an output param */
+ slang_operation *arg;
+ if (i < numArgs)
+ arg = &args[i];
+ else
+ arg = returnOper;
+ paramMode[i] = SUBST;
+
+ if (arg->type == SLANG_OPER_IDENTIFIER)
+ slang_resolve_variable(arg);
+
+ /* replace parameter 'p' with argument 'arg' */
+ substOld[substCount] = p;
+ substNew[substCount] = arg; /* will get copied */
+ substCount++;
+ }
+ else if (p->type.qualifier == SLANG_QUAL_CONST) {
+ /* a constant input param */
+ if (args[i].type == SLANG_OPER_IDENTIFIER ||
+ args[i].type == SLANG_OPER_LITERAL_FLOAT ||
+ args[i].type == SLANG_OPER_SUBSCRIPT) {
+ /* replace all occurances of this parameter variable with the
+ * actual argument variable or a literal.
+ */
+ paramMode[i] = SUBST;
+ slang_resolve_variable(&args[i]);
+ substOld[substCount] = p;
+ substNew[substCount] = &args[i]; /* will get copied */
+ substCount++;
+ }
+ else {
+ paramMode[i] = COPY_IN;
+ }
+ }
+ else {
+ paramMode[i] = COPY_IN;
+ }
+ assert(paramMode[i]);
+ }
+
+ /* actual code inlining: */
+ slang_operation_copy(inlined, fun->body);
+
+ /*** XXX review this */
+ assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+ inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
+ inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+
+#if 0
+ printf("======================= orig body code ======================\n");
+ printf("=== params scope = %p\n", (void*) fun->parameters);
+ slang_print_tree(fun->body, 8);
+ printf("======================= copied code =========================\n");
+ slang_print_tree(inlined, 8);
+#endif
+
+ /* do parameter substitution in inlined code: */
+ slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
+
+#if 0
+ printf("======================= subst code ==========================\n");
+ slang_print_tree(inlined, 8);
+ printf("=============================================================\n");
+#endif
+
+ /* New prolog statements: (inserted before the inlined code)
+ * Copy the 'in' arguments.
+ */
+ numCopyIn = 0;
+ for (i = 0; i < numArgs; i++) {
+ if (paramMode[i] == COPY_IN) {
+ slang_variable *p = fun->parameters->variables[i];
+ /* declare parameter 'p' */
+ slang_operation *decl = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ numCopyIn);
+
+ decl->type = SLANG_OPER_VARIABLE_DECL;
+ assert(decl->locals);
+ decl->locals->outer_scope = inlined->locals;
+ decl->a_id = p->a_name;
+ decl->num_children = 1;
+ decl->children = slang_operation_new(1);
+
+ /* child[0] is the var's initializer */
+ slang_operation_copy(&decl->children[0], args + i);
+
+ /* add parameter 'p' to the local variable scope here */
+ {
+ slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
+ pCopy->type = p->type;
+ pCopy->a_name = p->a_name;
+ pCopy->array_len = p->array_len;
+ }
+
+ newScope = inlined->locals;
+ numCopyIn++;
+ }
+ }
+
+ /* Now add copies of the function's local vars to the new variable scope */
+ for (i = totalArgs; i < fun->parameters->num_variables; i++) {
+ slang_variable *p = fun->parameters->variables[i];
+ slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);
+ pCopy->type = p->type;
+ pCopy->a_name = p->a_name;
+ pCopy->array_len = p->array_len;
+ }
+
+
+ /* New epilog statements:
+ * 1. Create end of function label to jump to from return statements.
+ * 2. Copy the 'out' parameter vars
+ */
+ {
+ slang_operation *lab = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ inlined->num_children);
+ lab->type = SLANG_OPER_LABEL;
+ lab->label = A->curFuncEndLabel;
+ }
+
+ for (i = 0; i < totalArgs; i++) {
+ if (paramMode[i] == COPY_OUT) {
+ const slang_variable *p = fun->parameters->variables[i];
+ /* actualCallVar = outParam */
+ /*if (i > 0 || !haveRetValue)*/
+ slang_operation *ass = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ inlined->num_children);
+ ass->type = SLANG_OPER_ASSIGN;
+ ass->num_children = 2;
+ ass->locals->outer_scope = inlined->locals;
+ ass->children = slang_operation_new(2);
+ ass->children[0] = args[i]; /*XXX copy */
+ ass->children[1].type = SLANG_OPER_IDENTIFIER;
+ ass->children[1].a_id = p->a_name;
+ ass->children[1].locals->outer_scope = ass->locals;
+ }
+ }
+
+ _slang_free(paramMode);
+ _slang_free(substOld);
+ _slang_free(substNew);
+
+ /* Update scoping to use the new local vars instead of the
+ * original function's vars. This is especially important
+ * for nested inlining.
+ */
+ if (newScope)
+ slang_replace_scope(inlined, fun->parameters, newScope);
+
+#if 0
+ printf("Done Inline call to %s (total vars=%d nparams=%d)\n\n",
+ (char *) fun->header.a_name,
+ fun->parameters->num_variables, numArgs);
+ slang_print_tree(top, 0);
+#endif
+
+ /* pop */
+ A->CurFunction = prevFunction;
+
+ return top;
+}
+
+
+/**
+ * Insert declaration for "bool __notRetFlag" in given block operation.
+ * This is used when we can't emit "early" return statements in subroutines.
+ */
+static void
+declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *decl;
+
+ assert(oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ oper->type == SLANG_OPER_SEQUENCE);
+
+ decl = slang_operation_insert_child(oper, 1);
+
+ slang_generate_declaration(A, oper->locals, decl,
+ SLANG_SPEC_BOOL, "__notRetFlag", GL_TRUE);
+
+ /*slang_print_tree(oper, 0);*/
+}
+
+
+/**
+ * Recursively replace instances of the old node type with the new type.
+ */
+static void
+replace_node_type(slang_operation *oper, slang_operation_type oldType,
+ slang_operation_type newType)
+{
+ GLuint i;
+
+ if (oper->type == oldType)
+ oper->type = newType;
+
+ for (i = 0; i < slang_oper_num_children(oper); i++) {
+ replace_node_type(slang_oper_child(oper, i), oldType, newType);
+ }
+}
+
+
+
+/**
+ * Test if the given function body has an "early return". That is, there's
+ * a 'return' statement that's not the very last instruction in the body.
+ */
+static GLboolean
+has_early_return(const slang_operation *funcBody)
+{
+ GLuint retCount = _slang_count_node_type(funcBody, SLANG_OPER_RETURN);
+ if (retCount == 0)
+ return GL_FALSE;
+ else if (retCount == 1 && _slang_is_tail_return(funcBody))
+ return GL_FALSE;
+ else
+ return GL_TRUE;
+}
+
+
+/**
+ * Emit IR code for a function call. This does one of two things:
+ * 1. Inline the function's code
+ * 2. Create an IR for the function's body and create a real call to it.
+ */
+static slang_ir_node *
+_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
+ slang_operation *oper, slang_operation *dest)
+{
+ slang_ir_node *n;
+ slang_operation *instance;
+ slang_label *prevFuncEndLabel;
+ char name[200];
+
+ prevFuncEndLabel = A->curFuncEndLabel;
+ sprintf(name, "__endOfFunc_%s_", (char *) fun->header.a_name);
+ A->curFuncEndLabel = _slang_label_new(name);
+ assert(A->curFuncEndLabel);
+
+ /*
+ * 'instance' is basically a copy of the function's body with various
+ * transformations.
+ */
+
+ if (slang_is_asm_function(fun) && !dest) {
+ /* assemble assembly function - tree style */
+ instance = slang_inline_asm_function(A, fun, oper);
+ }
+ else {
+ /* non-assembly function */
+ /* We always generate an "inline-able" block of code here.
+ * We may either:
+ * 1. insert the inline code
+ * 2. Generate a call to the "inline" code as a subroutine
+ */
+ const GLboolean earlyReturn = has_early_return(fun->body);
+
+ if (earlyReturn && !A->EmitContReturn) {
+ A->UseReturnFlag = GL_TRUE;
+ }
+
+ instance = slang_inline_function_call(A, fun, oper, dest);
+ if (!instance)
+ return NULL;
+
+ if (earlyReturn) {
+ /* The function we're calling has one or more 'return' statements
+ * that prevent us from inlining the function's code.
+ *
+ * In this case, change the function's body type from
+ * SLANG_OPER_BLOCK_NEW_SCOPE to SLANG_OPER_NON_INLINED_CALL.
+ * During code emit this will result in a true subroutine call.
+ *
+ * Also, convert SLANG_OPER_RETURN_INLINED nodes to SLANG_OPER_RETURN.
+ */
+ slang_operation *callOper;
+
+ assert(instance->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ instance->type == SLANG_OPER_SEQUENCE);
+
+ if (_slang_function_has_return_value(fun) && !dest) {
+ assert(instance->children[0].type == SLANG_OPER_VARIABLE_DECL);
+ assert(instance->children[2].type == SLANG_OPER_IDENTIFIER);
+ callOper = &instance->children[1];
+ }
+ else {
+ callOper = instance;
+ }
+
+ if (A->UseReturnFlag) {
+ /* Early returns not supported. Create a _returnFlag variable
+ * that's set upon 'return' and tested elsewhere to no-op any
+ * remaining instructions in the subroutine.
+ */
+ assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ callOper->type == SLANG_OPER_SEQUENCE);
+ declare_return_flag(A, callOper);
+ }
+ else {
+ /* We can emit real 'return' statements. If we generated any
+ * 'inline return' statements during function instantiation,
+ * change them back to regular 'return' statements.
+ */
+ replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+ SLANG_OPER_RETURN);
+ }
+
+ callOper->type = SLANG_OPER_NON_INLINED_CALL;
+ callOper->fun = fun;
+ callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
+ }
+ else {
+ /* If there are any 'return' statements remaining, they're at the
+ * very end of the function and can effectively become no-ops.
+ */
+ replace_node_type(instance, SLANG_OPER_RETURN_INLINED,
+ SLANG_OPER_VOID);
+ }
+ }
+
+ if (!instance)
+ return NULL;
+
+ /* Replace the function call with the instance block (or new CALL stmt) */
+ slang_operation_destruct(oper);
+ *oper = *instance;
+ _slang_free(instance);
+
+#if 0
+ assert(instance->locals);
+ printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name);
+ slang_print_tree(oper, 10);
+ printf("\n");
+#endif
+
+ n = _slang_gen_operation(A, oper);
+
+ /*_slang_label_delete(A->curFuncEndLabel);*/
+ A->curFuncEndLabel = prevFuncEndLabel;
+
+ if (A->pragmas->Debug) {
+ char s[1000];
+ _mesa_snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name);
+ n->Comment = _slang_strdup(s);
+ }
+
+ A->UseReturnFlag = GL_FALSE;
+
+ return n;
+}
+
+
+static slang_asm_info *
+slang_find_asm_info(const char *name)
+{
+ GLuint i;
+ for (i = 0; AsmInfo[i].Name; i++) {
+ if (_mesa_strcmp(AsmInfo[i].Name, name) == 0) {
+ return AsmInfo + i;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Some write-masked assignments are simple, but others are hard.
+ * Simple example:
+ * vec3 v;
+ * v.xy = vec2(a, b);
+ * Hard example:
+ * vec3 v;
+ * v.zy = vec2(a, b);
+ * this gets transformed/swizzled into:
+ * v.zy = vec2(a, b).*yx* (* = don't care)
+ * This function helps to determine simple vs. non-simple.
+ */
+static GLboolean
+_slang_simple_writemask(GLuint writemask, GLuint swizzle)
+{
+ switch (writemask) {
+ case WRITEMASK_X:
+ return GET_SWZ(swizzle, 0) == SWIZZLE_X;
+ case WRITEMASK_Y:
+ return GET_SWZ(swizzle, 1) == SWIZZLE_Y;
+ case WRITEMASK_Z:
+ return GET_SWZ(swizzle, 2) == SWIZZLE_Z;
+ case WRITEMASK_W:
+ return GET_SWZ(swizzle, 3) == SWIZZLE_W;
+ case WRITEMASK_XY:
+ return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
+ && (GET_SWZ(swizzle, 1) == SWIZZLE_Y);
+ case WRITEMASK_XYZ:
+ return (GET_SWZ(swizzle, 0) == SWIZZLE_X)
+ && (GET_SWZ(swizzle, 1) == SWIZZLE_Y)
+ && (GET_SWZ(swizzle, 2) == SWIZZLE_Z);
+ case WRITEMASK_XYZW:
+ return swizzle == SWIZZLE_NOOP;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Convert the given swizzle into a writemask. In some cases this
+ * is trivial, in other cases, we'll need to also swizzle the right
+ * hand side to put components in the right places.
+ * See comment above for more info.
+ * XXX this function could be simplified and should probably be renamed.
+ * \param swizzle the incoming swizzle
+ * \param writemaskOut returns the writemask
+ * \param swizzleOut swizzle to apply to the right-hand-side
+ * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple
+ */
+static GLboolean
+swizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle,
+ GLuint *writemaskOut, GLuint *swizzleOut)
+{
+ GLuint mask = 0x0, newSwizzle[4];
+ GLint i, size;
+
+ /* make new dst writemask, compute size */
+ for (i = 0; i < 4; i++) {
+ const GLuint swz = GET_SWZ(swizzle, i);
+ if (swz == SWIZZLE_NIL) {
+ /* end */
+ break;
+ }
+ assert(swz >= 0 && swz <= 3);
+
+ if (swizzle != SWIZZLE_XXXX &&
+ swizzle != SWIZZLE_YYYY &&
+ swizzle != SWIZZLE_ZZZZ &&
+ swizzle != SWIZZLE_WWWW &&
+ (mask & (1 << swz))) {
+ /* a channel can't be specified twice (ex: ".xyyz") */
+ slang_info_log_error(A->log, "Invalid writemask '%s'",
+ _mesa_swizzle_string(swizzle, 0, 0));
+ return GL_FALSE;
+ }
+
+ mask |= (1 << swz);
+ }
+ assert(mask <= 0xf);
+ size = i; /* number of components in mask/swizzle */
+
+ *writemaskOut = mask;
+
+ /* make new src swizzle, by inversion */
+ for (i = 0; i < 4; i++) {
+ newSwizzle[i] = i; /*identity*/
+ }
+ for (i = 0; i < size; i++) {
+ const GLuint swz = GET_SWZ(swizzle, i);
+ newSwizzle[swz] = i;
+ }
+ *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0],
+ newSwizzle[1],
+ newSwizzle[2],
+ newSwizzle[3]);
+
+ if (_slang_simple_writemask(mask, *swizzleOut)) {
+ if (size >= 1)
+ assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X);
+ if (size >= 2)
+ assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y);
+ if (size >= 3)
+ assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z);
+ if (size >= 4)
+ assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W);
+ return GL_TRUE;
+ }
+ else
+ return GL_FALSE;
+}
+
+
+#if 0 /* not used, but don't remove just yet */
+/**
+ * Recursively traverse 'oper' to produce a swizzle mask in the event
+ * of any vector subscripts and swizzle suffixes.
+ * Ex: for "vec4 v", "v[2].x" resolves to v.z
+ */
+static GLuint
+resolve_swizzle(const slang_operation *oper)
+{
+ if (oper->type == SLANG_OPER_FIELD) {
+ /* writemask from .xyzw suffix */
+ slang_swizzle swz;
+ if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
+ GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+ swz.swizzle[1],
+ swz.swizzle[2],
+ swz.swizzle[3]);
+ GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
+ GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
+ return s;
+ }
+ else
+ return SWIZZLE_XYZW;
+ }
+ else if (oper->type == SLANG_OPER_SUBSCRIPT &&
+ oper->children[1].type == SLANG_OPER_LITERAL_INT) {
+ /* writemask from [index] */
+ GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
+ GLuint i = (GLuint) oper->children[1].literal[0];
+ GLuint swizzle;
+ GLuint s;
+ switch (i) {
+ case 0:
+ swizzle = SWIZZLE_XXXX;
+ break;
+ case 1:
+ swizzle = SWIZZLE_YYYY;
+ break;
+ case 2:
+ swizzle = SWIZZLE_ZZZZ;
+ break;
+ case 3:
+ swizzle = SWIZZLE_WWWW;
+ break;
+ default:
+ swizzle = SWIZZLE_XYZW;
+ }
+ s = _slang_swizzle_swizzle(child_swizzle, swizzle);
+ return s;
+ }
+ else {
+ return SWIZZLE_XYZW;
+ }
+}
+#endif
+
+
+#if 0
+/**
+ * Recursively descend through swizzle nodes to find the node's storage info.
+ */
+static slang_ir_storage *
+get_store(const slang_ir_node *n)
+{
+ if (n->Opcode == IR_SWIZZLE) {
+ return get_store(n->Children[0]);
+ }
+ return n->Store;
+}
+#endif
+
+
+/**
+ * Generate IR tree for an asm instruction/operation such as:
+ * __asm vec4_dot __retVal.x, v1, v2;
+ */
+static slang_ir_node *
+_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
+ slang_operation *dest)
+{
+ const slang_asm_info *info;
+ slang_ir_node *kids[3], *n;
+ GLuint j, firstOperand;
+
+ assert(oper->type == SLANG_OPER_ASM);
+
+ info = slang_find_asm_info((char *) oper->a_id);
+ if (!info) {
+ _mesa_problem(NULL, "undefined __asm function %s\n",
+ (char *) oper->a_id);
+ assert(info);
+ }
+ assert(info->NumParams <= 3);
+
+ if (info->NumParams == oper->num_children) {
+ /* Storage for result is not specified.
+ * Children[0], [1], [2] are the operands.
+ */
+ firstOperand = 0;
+ }
+ else {
+ /* Storage for result (child[0]) is specified.
+ * Children[1], [2], [3] are the operands.
+ */
+ firstOperand = 1;
+ }
+
+ /* assemble child(ren) */
+ kids[0] = kids[1] = kids[2] = NULL;
+ for (j = 0; j < info->NumParams; j++) {
+ kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]);
+ if (!kids[j])
+ return NULL;
+ }
+
+ n = new_node3(info->Opcode, kids[0], kids[1], kids[2]);
+
+ if (firstOperand) {
+ /* Setup n->Store to be a particular location. Otherwise, storage
+ * for the result (a temporary) will be allocated later.
+ */
+ slang_operation *dest_oper;
+ slang_ir_node *n0;
+
+ dest_oper = &oper->children[0];
+
+ n0 = _slang_gen_operation(A, dest_oper);
+ if (!n0)
+ return NULL;
+
+ assert(!n->Store);
+ n->Store = n0->Store;
+
+ assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent);
+
+ _slang_free(n0);
+ }
+
+ return n;
+}
+
+
+#if 0
+static void
+print_funcs(struct slang_function_scope_ *scope, const char *name)
+{
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (!name || strcmp(name, (char*) f->header.a_name) == 0)
+ printf(" %s (%d args)\n", name, f->param_count);
+
+ }
+ if (scope->outer_scope)
+ print_funcs(scope->outer_scope, name);
+}
+#endif
+
+
+/**
+ * Find a function of the given name, taking 'numArgs' arguments.
+ * This is the function we'll try to call when there is no exact match
+ * between function parameters and call arguments.
+ *
+ * XXX we should really create a list of candidate functions and try
+ * all of them...
+ */
+static slang_function *
+_slang_find_function_by_argc(slang_function_scope *scope,
+ const char *name, int numArgs)
+{
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ int haveRetValue = _slang_function_has_return_value(f);
+ if (numArgs == f->param_count - haveRetValue)
+ return f;
+ }
+ }
+ scope = scope->outer_scope;
+ }
+
+ return NULL;
+}
+
+
+static slang_function *
+_slang_find_function_by_max_argc(slang_function_scope *scope,
+ const char *name)
+{
+ slang_function *maxFunc = NULL;
+ GLuint maxArgs = 0;
+
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ if (f->param_count > maxArgs) {
+ maxArgs = f->param_count;
+ maxFunc = f;
+ }
+ }
+ }
+ scope = scope->outer_scope;
+ }
+
+ return maxFunc;
+}
+
+
+/**
+ * Generate a new slang_function which is a constructor for a user-defined
+ * struct type.
+ */
+static slang_function *
+_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
+{
+ const GLint numFields = str->fields->num_variables;
+ slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
+
+ /* function header (name, return type) */
+ fun->header.a_name = str->a_name;
+ fun->header.type.qualifier = SLANG_QUAL_NONE;
+ fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
+ fun->header.type.specifier._struct = str;
+
+ /* function parameters (= struct's fields) */
+ {
+ GLint i;
+ for (i = 0; i < numFields; i++) {
+ /*
+ printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
+ */
+ slang_variable *p = slang_variable_scope_grow(fun->parameters);
+ *p = *str->fields->variables[i]; /* copy the variable and type */
+ p->type.qualifier = SLANG_QUAL_CONST;
+ }
+ fun->param_count = fun->parameters->num_variables;
+ }
+
+ /* Add __retVal to params */
+ {
+ slang_variable *p = slang_variable_scope_grow(fun->parameters);
+ slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+ assert(a_retVal);
+ p->a_name = a_retVal;
+ p->type = fun->header.type;
+ p->type.qualifier = SLANG_QUAL_OUT;
+ fun->param_count++;
+ }
+
+ /* function body is:
+ * block:
+ * declare T;
+ * T.f1 = p1;
+ * T.f2 = p2;
+ * ...
+ * T.fn = pn;
+ * return T;
+ */
+ {
+ slang_variable_scope *scope;
+ slang_variable *var;
+ GLint i;
+
+ fun->body = slang_operation_new(1);
+ fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ fun->body->num_children = numFields + 2;
+ fun->body->children = slang_operation_new(numFields + 2);
+
+ scope = fun->body->locals;
+ scope->outer_scope = fun->parameters;
+
+ /* create local var 't' */
+ var = slang_variable_scope_grow(scope);
+ var->a_name = slang_atom_pool_atom(A->atoms, "t");
+ var->type = fun->header.type;
+
+ /* declare t */
+ {
+ slang_operation *decl;
+
+ decl = &fun->body->children[0];
+ decl->type = SLANG_OPER_VARIABLE_DECL;
+ decl->locals = _slang_variable_scope_new(scope);
+ decl->a_id = var->a_name;
+ }
+
+ /* assign params to fields of t */
+ for (i = 0; i < numFields; i++) {
+ slang_operation *assign = &fun->body->children[1 + i];
+
+ assign->type = SLANG_OPER_ASSIGN;
+ assign->locals = _slang_variable_scope_new(scope);
+ assign->num_children = 2;
+ assign->children = slang_operation_new(2);
+
+ {
+ slang_operation *lhs = &assign->children[0];
+
+ lhs->type = SLANG_OPER_FIELD;
+ lhs->locals = _slang_variable_scope_new(scope);
+ lhs->num_children = 1;
+ lhs->children = slang_operation_new(1);
+ lhs->a_id = str->fields->variables[i]->a_name;
+
+ lhs->children[0].type = SLANG_OPER_IDENTIFIER;
+ lhs->children[0].a_id = var->a_name;
+ lhs->children[0].locals = _slang_variable_scope_new(scope);
+
+#if 0
+ lhs->children[1].num_children = 1;
+ lhs->children[1].children = slang_operation_new(1);
+ lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
+ lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
+ lhs->children[1].children->locals = _slang_variable_scope_new(scope);
+#endif
+ }
+
+ {
+ slang_operation *rhs = &assign->children[1];
+
+ rhs->type = SLANG_OPER_IDENTIFIER;
+ rhs->locals = _slang_variable_scope_new(scope);
+ rhs->a_id = str->fields->variables[i]->a_name;
+ }
+ }
+
+ /* return t; */
+ {
+ slang_operation *ret = &fun->body->children[numFields + 1];
+
+ ret->type = SLANG_OPER_RETURN;
+ ret->locals = _slang_variable_scope_new(scope);
+ ret->num_children = 1;
+ ret->children = slang_operation_new(1);
+ ret->children[0].type = SLANG_OPER_IDENTIFIER;
+ ret->children[0].a_id = var->a_name;
+ ret->children[0].locals = _slang_variable_scope_new(scope);
+ }
+ }
+ /*
+ slang_print_function(fun, 1);
+ */
+ return fun;
+}
+
+
+/**
+ * Find/create a function (constructor) for the given structure name.
+ */
+static slang_function *
+_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < A->space.structs->num_structs; i++) {
+ slang_struct *str = &A->space.structs->structs[i];
+ if (strcmp(name, (const char *) str->a_name) == 0) {
+ /* found a structure type that matches the function name */
+ if (!str->constructor) {
+ /* create the constructor function now */
+ str->constructor = _slang_make_struct_constructor(A, str);
+ }
+ return str->constructor;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Generate a new slang_function to satisfy a call to an array constructor.
+ * Ex: float[3](1., 2., 3.)
+ */
+static slang_function *
+_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_type_specifier_type baseType;
+ slang_function *fun;
+ int num_elements;
+
+ fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
+ if (!fun)
+ return NULL;
+
+ baseType = slang_type_specifier_type_from_string((char *) oper->a_id);
+
+ num_elements = oper->num_children;
+
+ /* function header, return type */
+ {
+ fun->header.a_name = oper->a_id;
+ fun->header.type.qualifier = SLANG_QUAL_NONE;
+ fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
+ fun->header.type.specifier._array =
+ slang_type_specifier_new(baseType, NULL, NULL);
+ fun->header.type.array_len = num_elements;
+ }
+
+ /* function parameters (= number of elements) */
+ {
+ GLint i;
+ for (i = 0; i < num_elements; i++) {
+ /*
+ printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
+ */
+ slang_variable *p = slang_variable_scope_grow(fun->parameters);
+ char name[10];
+ _mesa_snprintf(name, sizeof(name), "p%d", i);
+ p->a_name = slang_atom_pool_atom(A->atoms, name);
+ p->type.qualifier = SLANG_QUAL_CONST;
+ p->type.specifier.type = baseType;
+ }
+ fun->param_count = fun->parameters->num_variables;
+ }
+
+ /* Add __retVal to params */
+ {
+ slang_variable *p = slang_variable_scope_grow(fun->parameters);
+ slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+ assert(a_retVal);
+ p->a_name = a_retVal;
+ p->type = fun->header.type;
+ p->type.qualifier = SLANG_QUAL_OUT;
+ p->type.specifier.type = baseType;
+ fun->param_count++;
+ }
+
+ /* function body is:
+ * block:
+ * declare T;
+ * T[0] = p0;
+ * T[1] = p1;
+ * ...
+ * T[n] = pn;
+ * return T;
+ */
+ {
+ slang_variable_scope *scope;
+ slang_variable *var;
+ GLint i;
+
+ fun->body = slang_operation_new(1);
+ fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ fun->body->num_children = num_elements + 2;
+ fun->body->children = slang_operation_new(num_elements + 2);
+
+ scope = fun->body->locals;
+ scope->outer_scope = fun->parameters;
+
+ /* create local var 't' */
+ var = slang_variable_scope_grow(scope);
+ var->a_name = slang_atom_pool_atom(A->atoms, "ttt");
+ var->type = fun->header.type;/*XXX copy*/
+
+ /* declare t */
+ {
+ slang_operation *decl;
+
+ decl = &fun->body->children[0];
+ decl->type = SLANG_OPER_VARIABLE_DECL;
+ decl->locals = _slang_variable_scope_new(scope);
+ decl->a_id = var->a_name;
+ }
+
+ /* assign params to elements of t */
+ for (i = 0; i < num_elements; i++) {
+ slang_operation *assign = &fun->body->children[1 + i];
+
+ assign->type = SLANG_OPER_ASSIGN;
+ assign->locals = _slang_variable_scope_new(scope);
+ assign->num_children = 2;
+ assign->children = slang_operation_new(2);
+
+ {
+ slang_operation *lhs = &assign->children[0];
+
+ lhs->type = SLANG_OPER_SUBSCRIPT;
+ lhs->locals = _slang_variable_scope_new(scope);
+ lhs->num_children = 2;
+ lhs->children = slang_operation_new(2);
+
+ lhs->children[0].type = SLANG_OPER_IDENTIFIER;
+ lhs->children[0].a_id = var->a_name;
+ lhs->children[0].locals = _slang_variable_scope_new(scope);
+
+ lhs->children[1].type = SLANG_OPER_LITERAL_INT;
+ lhs->children[1].literal[0] = (GLfloat) i;
+ }
+
+ {
+ slang_operation *rhs = &assign->children[1];
+
+ rhs->type = SLANG_OPER_IDENTIFIER;
+ rhs->locals = _slang_variable_scope_new(scope);
+ rhs->a_id = fun->parameters->variables[i]->a_name;
+ }
+ }
+
+ /* return t; */
+ {
+ slang_operation *ret = &fun->body->children[num_elements + 1];
+
+ ret->type = SLANG_OPER_RETURN;
+ ret->locals = _slang_variable_scope_new(scope);
+ ret->num_children = 1;
+ ret->children = slang_operation_new(1);
+ ret->children[0].type = SLANG_OPER_IDENTIFIER;
+ ret->children[0].a_id = var->a_name;
+ ret->children[0].locals = _slang_variable_scope_new(scope);
+ }
+ }
+
+ /*
+ slang_print_function(fun, 1);
+ */
+
+ return fun;
+}
+
+
+static GLboolean
+_slang_is_vec_mat_type(const char *name)
+{
+ static const char *vecmat_types[] = {
+ "float", "int", "bool",
+ "vec2", "vec3", "vec4",
+ "ivec2", "ivec3", "ivec4",
+ "bvec2", "bvec3", "bvec4",
+ "mat2", "mat3", "mat4",
+ "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
+ NULL
+ };
+ int i;
+ for (i = 0; vecmat_types[i]; i++)
+ if (_mesa_strcmp(name, vecmat_types[i]) == 0)
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
+
+/**
+ * Assemble a function call, given a particular function name.
+ * \param name the function's name (operators like '*' are possible).
+ */
+static slang_ir_node *
+_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
+ slang_operation *oper, slang_operation *dest)
+{
+ slang_operation *params = oper->children;
+ const GLuint param_count = oper->num_children;
+ slang_atom atom;
+ slang_function *fun;
+ slang_ir_node *n;
+
+ atom = slang_atom_pool_atom(A->atoms, name);
+ if (atom == SLANG_ATOM_NULL)
+ return NULL;
+
+ if (oper->array_constructor) {
+ /* this needs special handling */
+ fun = _slang_make_array_constructor(A, oper);
+ }
+ else {
+ /* Try to find function by name and exact argument type matching */
+ GLboolean error = GL_FALSE;
+ fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
+ &A->space, A->atoms, A->log, &error);
+ if (error) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+ }
+
+ if (!fun) {
+ /* Next, try locating a constructor function for a user-defined type */
+ fun = _slang_locate_struct_constructor(A, name);
+ }
+
+ /*
+ * At this point, some heuristics are used to try to find a function
+ * that matches the calling signature by means of casting or "unrolling"
+ * of constructors.
+ */
+
+ if (!fun && _slang_is_vec_mat_type(name)) {
+ /* Next, if this call looks like a vec() or mat() constructor call,
+ * try "unwinding" the args to satisfy a constructor.
+ */
+ fun = _slang_find_function_by_max_argc(A->space.funcs, name);
+ if (fun) {
+ if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+ }
+ }
+
+ if (!fun && _slang_is_vec_mat_type(name)) {
+ /* Next, try casting args to the types of the formal parameters */
+ int numArgs = oper->num_children;
+ fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
+ if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+ assert(fun);
+ }
+
+ if (!fun) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+
+ if (!fun->body) {
+ /* The function body may be in another compilation unit.
+ * We'll try concatenating the shaders and recompile at link time.
+ */
+ A->UnresolvedRefs = GL_TRUE;
+ return new_node1(IR_NOP, NULL);
+ }
+
+ /* type checking to be sure function's return type matches 'dest' type */
+ if (dest) {
+ slang_typeinfo t0;
+
+ slang_typeinfo_construct(&t0);
+ typeof_operation(A, dest, &t0);
+
+ if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
+ slang_info_log_error(A->log,
+ "Incompatible type returned by call to '%s'",
+ name);
+ return NULL;
+ }
+ }
+
+ n = _slang_gen_function_call(A, fun, oper, dest);
+
+ if (n && !n->Store && !dest
+ && fun->header.type.specifier.type != SLANG_SPEC_VOID) {
+ /* setup n->Store for the result of the function call */
+ GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier);
+ n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
+ /*printf("Alloc storage for function result, size %d \n", size);*/
+ }
+
+ if (oper->array_constructor) {
+ /* free the temporary array constructor function now */
+ slang_function_destruct(fun);
+ }
+
+ return n;
+}
+
+
+static slang_ir_node *
+_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
+ slang_ir_node *n;
+ slang_variable *var;
+
+ /* NOTE: In GLSL 1.20, there's only one kind of method
+ * call: array.length(). Anything else is an error.
+ */
+ if (oper->a_id != a_length) {
+ slang_info_log_error(A->log,
+ "Undefined method call '%s'", (char *) oper->a_id);
+ return NULL;
+ }
+
+ /* length() takes no arguments */
+ if (oper->num_children > 0) {
+ slang_info_log_error(A->log, "Invalid arguments to length() method");
+ return NULL;
+ }
+
+ /* lookup the object/variable */
+ var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
+ if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
+ slang_info_log_error(A->log,
+ "Undefined object '%s'", (char *) oper->a_obj);
+ return NULL;
+ }
+
+ /* Create a float/literal IR node encoding the array length */
+ n = new_node0(IR_FLOAT);
+ if (n) {
+ n->Value[0] = (float) _slang_array_length(var);
+ n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
+ }
+ return n;
+}
+
+
+static GLboolean
+_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
+{
+ if (oper->type == SLANG_OPER_LITERAL_FLOAT ||
+ oper->type == SLANG_OPER_LITERAL_INT ||
+ oper->type == SLANG_OPER_LITERAL_BOOL) {
+ if (oper->literal[0])
+ *value = GL_TRUE;
+ else
+ *value = GL_FALSE;
+ return GL_TRUE;
+ }
+ else if (oper->type == SLANG_OPER_EXPRESSION &&
+ oper->num_children == 1) {
+ return _slang_is_constant_cond(&oper->children[0], value);
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Test if an operation is a scalar or boolean.
+ */
+static GLboolean
+_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_typeinfo type;
+ GLint size;
+
+ slang_typeinfo_construct(&type);
+ typeof_operation(A, oper, &type);
+ size = _slang_sizeof_type_specifier(&type.spec);
+ slang_typeinfo_destruct(&type);
+ return size == 1;
+}
+
+
+/**
+ * Test if an operation is boolean.
+ */
+static GLboolean
+_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_typeinfo type;
+ GLboolean isBool;
+
+ slang_typeinfo_construct(&type);
+ typeof_operation(A, oper, &type);
+ isBool = (type.spec.type == SLANG_SPEC_BOOL);
+ slang_typeinfo_destruct(&type);
+ return isBool;
+}
+
+
+/**
+ * Check if a loop contains a 'continue' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue(const slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ return GL_TRUE;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ return GL_FALSE;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ const slang_operation *child = slang_oper_child_const(oper, i);
+ if (_slang_loop_contains_continue(child))
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if a loop contains a 'continue' or 'break' statement.
+ * Stop looking if we find a nested loop.
+ */
+static GLboolean
+_slang_loop_contains_continue_or_break(const slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ case SLANG_OPER_BREAK:
+ return GL_TRUE;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ return GL_FALSE;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ const slang_operation *child = slang_oper_child_const(oper, i);
+ if (_slang_loop_contains_continue_or_break(child))
+ return GL_TRUE;
+ }
+ }
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Replace 'break' and 'continue' statements inside a do and while loops.
+ * This is a recursive helper function used by
+ * _slang_gen_do/while_without_continue().
+ */
+static void
+replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_BREAK:
+ /* replace 'break' with "_notBreakFlag = false; break" */
+ {
+ slang_operation *block = oper;
+ block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ slang_operation_add_children(block, 2);
+ {
+ slang_operation *assign = slang_oper_child(block, 0);
+ assign->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(assign, 2);
+ {
+ slang_operation *lhs = slang_oper_child(assign, 0);
+ slang_operation_identifier(lhs, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(assign, 1);
+ slang_operation_literal_bool(rhs, GL_FALSE);
+ }
+ }
+ {
+ slang_operation *brk = slang_oper_child(block, 1);
+ brk->type = SLANG_OPER_BREAK;
+ assert(!brk->children);
+ }
+ }
+ break;
+ case SLANG_OPER_CONTINUE:
+ /* convert continue into a break */
+ oper->type = SLANG_OPER_BREAK;
+ break;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ break;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ replace_break_and_cont(A, slang_oper_child(oper, i));
+ }
+ }
+ }
+}
+
+
+/**
+ * Transform a while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * while (LOOPCOND) {
+ * A;
+ * if (IFCOND)
+ * continue;
+ * B;
+ * break;
+ * C;
+ * }
+ *
+ * After:
+ *
+ * {
+ * bool _notBreakFlag = 1;
+ * while (_notBreakFlag && LOOPCOND) {
+ * do {
+ * A;
+ * if (IFCOND) {
+ * break; // was continue
+ * }
+ * B;
+ * _notBreakFlag = 0; // was
+ * break; // break
+ * C;
+ * } while (0)
+ * }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *innerBody;
+
+ assert(oper->type == SLANG_OPER_WHILE);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _notBreakFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+ }
+
+ /* build outer while-loop: while (_notBreakFlag && LOOPCOND) { ... } */
+ {
+ slang_operation *outerWhile = slang_oper_child(top, 1);
+ outerWhile->type = SLANG_OPER_WHILE;
+ slang_operation_add_children(outerWhile, 2);
+
+ /* _notBreakFlag && LOOPCOND */
+ {
+ slang_operation *cond = slang_oper_child(outerWhile, 0);
+ cond->type = SLANG_OPER_LOGICALAND;
+ slang_operation_add_children(cond, 2);
+ {
+ slang_operation *notBreak = slang_oper_child(cond, 0);
+ slang_operation_identifier(notBreak, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *origCond = slang_oper_child(cond, 1);
+ slang_operation_copy(origCond, slang_oper_child(oper, 0));
+ }
+ }
+
+ /* inner loop */
+ {
+ slang_operation *innerDo = slang_oper_child(outerWhile, 1);
+ innerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(innerDo, 2);
+
+ /* copy original do-loop body into inner do-loop's body */
+ innerBody = slang_oper_child(innerDo, 0);
+ slang_operation_copy(innerBody, slang_oper_child(oper, 1));
+ innerBody->locals->outer_scope = innerDo->locals;
+
+ /* inner do-loop's condition is constant/false */
+ {
+ slang_operation *constFalse = slang_oper_child(innerDo, 1);
+ slang_operation_literal_bool(constFalse, GL_FALSE);
+ }
+ }
+ }
+
+ /* Finally, in innerBody,
+ * replace "break" with "_notBreakFlag = 0; break"
+ * replace "continue" with "break"
+ */
+ replace_break_and_cont(A, innerBody);
+
+ /*slang_print_tree(top, 0);*/
+
+ return _slang_gen_operation(A, top);
+
+ return NULL;
+}
+
+
+/**
+ * Generate loop code using high-level IR_LOOP instruction
+ */
+static slang_ir_node *
+_slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
+{
+ /*
+ * LOOP:
+ * BREAK if !expr (child[0])
+ * body code (child[1])
+ */
+ slang_ir_node *loop, *breakIf, *body;
+ GLboolean isConst, constTrue = GL_FALSE;
+
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this while-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 1))) {
+ return _slang_gen_while_without_continue(A, oper);
+ }
+ }
+
+ /* type-check expression */
+ if (!_slang_is_boolean(A, &oper->children[0])) {
+ slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'");
+ return NULL;
+ }
+
+ /* Check if loop condition is a constant */
+ isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
+
+ if (isConst && !constTrue) {
+ /* loop is never executed! */
+ return new_node0(IR_NOP);
+ }
+
+ /* Begin new loop */
+ loop = new_loop(NULL);
+
+ /* save loop state */
+ push_loop(A, oper, loop);
+
+ if (isConst && constTrue) {
+ /* while(nonzero constant), no conditional break */
+ breakIf = NULL;
+ }
+ else {
+ slang_ir_node *cond
+ = new_cond(new_not(_slang_gen_operation(A, &oper->children[0])));
+ breakIf = new_break_if_true(A, cond);
+ }
+ body = _slang_gen_operation(A, &oper->children[1]);
+ loop->Children[0] = new_seq(breakIf, body);
+
+ /* Do infinite loop detection */
+ /* loop->List is head of linked list of break/continue nodes */
+ if (!loop->List && isConst && constTrue) {
+ /* infinite loop detected */
+ pop_loop(A);
+ slang_info_log_error(A->log, "Infinite loop detected!");
+ return NULL;
+ }
+
+ /* restore loop state */
+ pop_loop(A);
+
+ return loop;
+}
+
+
+/**
+ * Transform a do-while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * do {
+ * A;
+ * if (IFCOND)
+ * continue;
+ * B;
+ * break;
+ * C;
+ * } while (LOOPCOND);
+ *
+ * After:
+ *
+ * {
+ * bool _notBreakFlag = 1;
+ * do {
+ * do {
+ * A;
+ * if (IFCOND) {
+ * break; // was continue
+ * }
+ * B;
+ * _notBreakFlag = 0; // was
+ * break; // break
+ * C;
+ * } while (0)
+ * } while (_notBreakFlag && LOOPCOND);
+ * }
+ */
+static slang_ir_node *
+_slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *innerBody;
+
+ assert(oper->type == SLANG_OPER_DO);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _notBreakFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_notBreakFlag", GL_TRUE);
+ }
+
+ /* build outer do-loop: do { ... } while (_notBreakFlag && LOOPCOND) */
+ {
+ slang_operation *outerDo = slang_oper_child(top, 1);
+ outerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(outerDo, 2);
+
+ /* inner do-loop */
+ {
+ slang_operation *innerDo = slang_oper_child(outerDo, 0);
+ innerDo->type = SLANG_OPER_DO;
+ slang_operation_add_children(innerDo, 2);
+
+ /* copy original do-loop body into inner do-loop's body */
+ innerBody = slang_oper_child(innerDo, 0);
+ slang_operation_copy(innerBody, slang_oper_child(oper, 0));
+ innerBody->locals->outer_scope = innerDo->locals;
+
+ /* inner do-loop's condition is constant/false */
+ {
+ slang_operation *constFalse = slang_oper_child(innerDo, 1);
+ slang_operation_literal_bool(constFalse, GL_FALSE);
+ }
+ }
+
+ /* _notBreakFlag && LOOPCOND */
+ {
+ slang_operation *cond = slang_oper_child(outerDo, 1);
+ cond->type = SLANG_OPER_LOGICALAND;
+ slang_operation_add_children(cond, 2);
+ {
+ slang_operation *notBreak = slang_oper_child(cond, 0);
+ slang_operation_identifier(notBreak, A, "_notBreakFlag");
+ }
+ {
+ slang_operation *origCond = slang_oper_child(cond, 1);
+ slang_operation_copy(origCond, slang_oper_child(oper, 1));
+ }
+ }
+ }
+
+ /* Finally, in innerBody,
+ * replace "break" with "_notBreakFlag = 0; break"
+ * replace "continue" with "break"
+ */
+ replace_break_and_cont(A, innerBody);
+
+ /*slang_print_tree(top, 0);*/
+
+ return _slang_gen_operation(A, top);
+}
+
+
+/**
+ * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
+ */
+static slang_ir_node *
+_slang_gen_do(slang_assemble_ctx * A, slang_operation *oper)
+{
+ /*
+ * LOOP:
+ * body code (child[0])
+ * tail code:
+ * BREAK if !expr (child[1])
+ */
+ slang_ir_node *loop;
+ GLboolean isConst, constTrue;
+
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this do-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 0))) {
+ return _slang_gen_do_without_continue(A, oper);
+ }
+ }
+
+ /* type-check expression */
+ if (!_slang_is_boolean(A, &oper->children[1])) {
+ slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'");
+ return NULL;
+ }
+
+ loop = new_loop(NULL);
+
+ /* save loop state */
+ push_loop(A, oper, loop);
+
+ /* loop body: */
+ loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
+
+ /* Check if loop condition is a constant */
+ isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
+ if (isConst && constTrue) {
+ /* do { } while(1) ==> no conditional break */
+ loop->Children[1] = NULL; /* no tail code */
+ }
+ else {
+ slang_ir_node *cond
+ = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
+ loop->Children[1] = new_break_if_true(A, cond);
+ }
+
+ /* XXX we should do infinite loop detection, as above */
+
+ /* restore loop state */
+ pop_loop(A);
+
+ return loop;
+}
+
+
+/**
+ * Recursively count the number of operations rooted at 'oper'.
+ * This gives some kind of indication of the size/complexity of an operation.
+ */
+static GLuint
+sizeof_operation(const slang_operation *oper)
+{
+ if (oper) {
+ GLuint count = 1; /* me */
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ count += sizeof_operation(&oper->children[i]);
+ }
+ return count;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+/**
+ * Determine if a for-loop can be unrolled.
+ * At this time, only a rather narrow class of for loops can be unrolled.
+ * See code for details.
+ * When a loop can't be unrolled because it's too large we'll emit a
+ * message to the log.
+ */
+static GLboolean
+_slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ GLuint bodySize;
+ GLint start, end;
+ const char *varName;
+ slang_atom varId;
+
+ if (oper->type != SLANG_OPER_FOR)
+ return GL_FALSE;
+
+ assert(oper->num_children == 4);
+
+ if (_slang_loop_contains_continue_or_break(slang_oper_child_const(oper, 3)))
+ return GL_FALSE;
+
+ /* children[0] must be either "int i=constant" or "i=constant" */
+ if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+ slang_variable *var;
+
+ if (oper->children[0].children[0].type != SLANG_OPER_VARIABLE_DECL)
+ return GL_FALSE;
+
+ varId = oper->children[0].children[0].a_id;
+
+ var = _slang_variable_locate(oper->children[0].children[0].locals,
+ varId, GL_TRUE);
+ if (!var)
+ return GL_FALSE;
+ if (!var->initializer)
+ return GL_FALSE;
+ if (var->initializer->type != SLANG_OPER_LITERAL_INT)
+ return GL_FALSE;
+ start = (GLint) var->initializer->literal[0];
+ }
+ else if (oper->children[0].type == SLANG_OPER_EXPRESSION) {
+ if (oper->children[0].children[0].type != SLANG_OPER_ASSIGN)
+ return GL_FALSE;
+ if (oper->children[0].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
+ return GL_FALSE;
+ if (oper->children[0].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+ return GL_FALSE;
+
+ varId = oper->children[0].children[0].children[0].a_id;
+
+ start = (GLint) oper->children[0].children[0].children[1].literal[0];
+ }
+ else {
+ return GL_FALSE;
+ }
+
+ /* children[1] must be "i<constant" */
+ if (oper->children[1].type != SLANG_OPER_EXPRESSION)
+ return GL_FALSE;
+ if (oper->children[1].children[0].type != SLANG_OPER_LESS)
+ return GL_FALSE;
+ if (oper->children[1].children[0].children[0].type != SLANG_OPER_IDENTIFIER)
+ return GL_FALSE;
+ if (oper->children[1].children[0].children[1].type != SLANG_OPER_LITERAL_INT)
+ return GL_FALSE;
+
+ end = (GLint) oper->children[1].children[0].children[1].literal[0];
+
+ /* children[2] must be "i++" or "++i" */
+ if (oper->children[2].type != SLANG_OPER_POSTINCREMENT &&
+ oper->children[2].type != SLANG_OPER_PREINCREMENT)
+ return GL_FALSE;
+ if (oper->children[2].children[0].type != SLANG_OPER_IDENTIFIER)
+ return GL_FALSE;
+
+ /* make sure the same variable name is used in all places */
+ if ((oper->children[1].children[0].children[0].a_id != varId) ||
+ (oper->children[2].children[0].a_id != varId))
+ return GL_FALSE;
+
+ varName = (const char *) varId;
+
+ /* children[3], the loop body, can't be too large */
+ bodySize = sizeof_operation(&oper->children[3]);
+ if (bodySize > MAX_FOR_LOOP_UNROLL_BODY_SIZE) {
+ slang_info_log_print(A->log,
+ "Note: 'for (%s ... )' body is too large/complex"
+ " to unroll",
+ varName);
+ return GL_FALSE;
+ }
+
+ if (start >= end)
+ return GL_FALSE; /* degenerate case */
+
+ if (end - start > MAX_FOR_LOOP_UNROLL_ITERATIONS) {
+ slang_info_log_print(A->log,
+ "Note: 'for (%s=%d; %s<%d; ++%s)' is too"
+ " many iterations to unroll",
+ varName, start, varName, end, varName);
+ return GL_FALSE;
+ }
+
+ if ((end - start) * bodySize > MAX_FOR_LOOP_UNROLL_COMPLEXITY) {
+ slang_info_log_print(A->log,
+ "Note: 'for (%s=%d; %s<%d; ++%s)' will generate"
+ " too much code to unroll",
+ varName, start, varName, end, varName);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE; /* we can unroll the loop */
+}
+
+
+/**
+ * Unroll a for-loop.
+ * First we determine the number of iterations to unroll.
+ * Then for each iteration:
+ * make a copy of the loop body
+ * replace instances of the loop variable with the current iteration value
+ * generate IR code for the body
+ * \return pointer to generated IR code or NULL if error, out of memory, etc.
+ */
+static slang_ir_node *
+_slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ GLint start, end, iter;
+ slang_ir_node *n, *root = NULL;
+ slang_atom varId;
+
+ if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) {
+ /* for (int i=0; ... */
+ slang_variable *var;
+
+ varId = oper->children[0].children[0].a_id;
+ var = _slang_variable_locate(oper->children[0].children[0].locals,
+ varId, GL_TRUE);
+ start = (GLint) var->initializer->literal[0];
+ }
+ else {
+ /* for (i=0; ... */
+ varId = oper->children[0].children[0].children[0].a_id;
+ start = (GLint) oper->children[0].children[0].children[1].literal[0];
+ }
+
+ end = (GLint) oper->children[1].children[0].children[1].literal[0];
+
+ for (iter = start; iter < end; iter++) {
+ slang_operation *body;
+
+ /* make a copy of the loop body */
+ body = slang_operation_new(1);
+ if (!body)
+ return NULL;
+
+ if (!slang_operation_copy(body, &oper->children[3]))
+ return NULL;
+
+ /* in body, replace instances of 'varId' with literal 'iter' */
+ {
+ slang_variable *oldVar;
+ slang_operation *newOper;
+
+ oldVar = _slang_variable_locate(oper->locals, varId, GL_TRUE);
+ if (!oldVar) {
+ /* undeclared loop variable */
+ slang_operation_delete(body);
+ return NULL;
+ }
+
+ newOper = slang_operation_new(1);
+ newOper->type = SLANG_OPER_LITERAL_INT;
+ newOper->literal_size = 1;
+ newOper->literal[0] = iter;
+
+ /* replace instances of the loop variable with newOper */
+ slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE);
+ }
+
+ /* do IR codegen for body */
+ n = _slang_gen_operation(A, body);
+ if (!n)
+ return NULL;
+
+ root = new_seq(root, n);
+
+ slang_operation_delete(body);
+ }
+
+ return root;
+}
+
+
+/**
+ * Replace 'continue' statement with 'break' inside a for-loop.
+ * This is a recursive helper function used by _slang_gen_for_without_continue().
+ */
+static void
+replace_continue_with_break(slang_assemble_ctx *A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_CONTINUE:
+ oper->type = SLANG_OPER_BREAK;
+ break;
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_WHILE:
+ /* stop upon finding a nested loop */
+ break;
+ default:
+ /* recurse */
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ replace_continue_with_break(A, slang_oper_child(oper, i));
+ }
+ }
+ }
+}
+
+
+/**
+ * Transform a for-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ *
+ * for (INIT; LOOPCOND; INCR) {
+ * A;
+ * if (IFCOND) {
+ * continue;
+ * }
+ * B;
+ * }
+ *
+ * After:
+ *
+ * {
+ * bool _condFlag = 1;
+ * for (INIT; _condFlag; ) {
+ * for ( ; _condFlag = LOOPCOND; INCR) {
+ * A;
+ * if (IFCOND) {
+ * break;
+ * }
+ * B;
+ * }
+ * if (_condFlag)
+ * INCR;
+ * }
+ * }
+ */
+static slang_ir_node *
+_slang_gen_for_without_continue(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_operation *top;
+ slang_operation *outerFor, *innerFor, *init, *cond, *incr;
+ slang_operation *lhs, *rhs;
+
+ assert(oper->type == SLANG_OPER_FOR);
+
+ top = slang_operation_new(1);
+ top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ top->locals->outer_scope = oper->locals->outer_scope;
+ slang_operation_add_children(top, 2);
+
+ /* declare: bool _condFlag = true */
+ {
+ slang_operation *condDecl = slang_oper_child(top, 0);
+ slang_generate_declaration(A, top->locals, condDecl,
+ SLANG_SPEC_BOOL, "_condFlag", GL_TRUE);
+ }
+
+ /* build outer loop: for (INIT; _condFlag; ) { */
+ outerFor = slang_oper_child(top, 1);
+ outerFor->type = SLANG_OPER_FOR;
+ slang_operation_add_children(outerFor, 4);
+
+ init = slang_oper_child(outerFor, 0);
+ slang_operation_copy(init, slang_oper_child(oper, 0));
+
+ cond = slang_oper_child(outerFor, 1);
+ cond->type = SLANG_OPER_IDENTIFIER;
+ cond->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+ incr = slang_oper_child(outerFor, 2);
+ incr->type = SLANG_OPER_VOID;
+
+ /* body of the outer loop */
+ {
+ slang_operation *block = slang_oper_child(outerFor, 3);
+
+ slang_operation_add_children(block, 2);
+ block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+
+ /* build inner loop: for ( ; _condFlag = LOOPCOND; INCR) { */
+ {
+ innerFor = slang_oper_child(block, 0);
+
+ /* make copy of orig loop */
+ slang_operation_copy(innerFor, oper);
+ assert(innerFor->type == SLANG_OPER_FOR);
+ innerFor->locals->outer_scope = block->locals;
+
+ init = slang_oper_child(innerFor, 0);
+ init->type = SLANG_OPER_VOID; /* leak? */
+
+ cond = slang_oper_child(innerFor, 1);
+ slang_operation_destruct(cond);
+ cond->type = SLANG_OPER_ASSIGN;
+ cond->locals = _slang_variable_scope_new(innerFor->locals);
+ slang_operation_add_children(cond, 2);
+
+ lhs = slang_oper_child(cond, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "_condFlag");
+
+ rhs = slang_oper_child(cond, 1);
+ slang_operation_copy(rhs, slang_oper_child(oper, 1));
+ }
+
+ /* if (_condFlag) INCR; */
+ {
+ slang_operation *ifop = slang_oper_child(block, 1);
+ ifop->type = SLANG_OPER_IF;
+ slang_operation_add_children(ifop, 2);
+
+ /* re-use cond node build above */
+ slang_operation_copy(slang_oper_child(ifop, 0), cond);
+
+ /* incr node from original for-loop operation */
+ slang_operation_copy(slang_oper_child(ifop, 1),
+ slang_oper_child(oper, 2));
+ }
+
+ /* finally, replace "continue" with "break" in the inner for-loop */
+ replace_continue_with_break(A, slang_oper_child(innerFor, 3));
+ }
+
+ return _slang_gen_operation(A, top);
+}
+
+
+
+/**
+ * Generate IR for a for-loop. Unrolling will be done when possible.
+ */
+static slang_ir_node *
+_slang_gen_for(slang_assemble_ctx * A, slang_operation *oper)
+{
+ GLboolean unroll;
+
+ if (!A->EmitContReturn) {
+ /* We don't want to emit CONT instructions. If this for-loop has
+ * a continue, translate it away.
+ */
+ if (_slang_loop_contains_continue(slang_oper_child(oper, 3))) {
+ return _slang_gen_for_without_continue(A, oper);
+ }
+ }
+
+ unroll = _slang_can_unroll_for_loop(A, oper);
+ if (unroll) {
+ slang_ir_node *code = _slang_unroll_for_loop(A, oper);
+ if (code)
+ return code;
+ }
+
+ assert(oper->type == SLANG_OPER_FOR);
+
+ /* conventional for-loop code generation */
+ {
+ /*
+ * init code (child[0])
+ * LOOP:
+ * BREAK if !expr (child[1])
+ * body code (child[3])
+ * tail code:
+ * incr code (child[2]) // XXX continue here
+ */
+ slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
+ init = _slang_gen_operation(A, &oper->children[0]);
+ loop = new_loop(NULL);
+
+ /* save loop state */
+ push_loop(A, oper, loop);
+
+ cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1])));
+ breakIf = new_break_if_true(A, cond);
+ body = _slang_gen_operation(A, &oper->children[3]);
+ incr = _slang_gen_operation(A, &oper->children[2]);
+
+ loop->Children[0] = new_seq(breakIf, body);
+ loop->Children[1] = incr; /* tail code */
+
+ /* restore loop state */
+ pop_loop(A);
+
+ return new_seq(init, loop);
+ }
+}
+
+
+static slang_ir_node *
+_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ slang_ir_node *n, *cont, *incr = NULL, *loopNode;
+
+ assert(oper->type == SLANG_OPER_CONTINUE);
+ loopNode = current_loop_ir(A);
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+
+ cont = new_node0(IR_CONT);
+ if (cont) {
+ cont->Parent = loopNode;
+ /* insert this node at head of linked list of cont/break instructions */
+ cont->List = loopNode->List;
+ loopNode->List = cont;
+ }
+
+ n = new_seq(incr, cont);
+ return n;
+}
+
+
+/**
+ * Determine if the given operation is of a specific type.
+ */
+static GLboolean
+is_operation_type(const slang_operation *oper, slang_operation_type type)
+{
+ if (oper->type == type)
+ return GL_TRUE;
+ else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) &&
+ oper->num_children == 1)
+ return is_operation_type(&oper->children[0], type);
+ else
+ return GL_FALSE;
+}
+
+
+/**
+ * Generate IR tree for an if/then/else conditional using high-level
+ * IR_IF instruction.
+ */
+static slang_ir_node *
+_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * eval expr (child[0])
+ * IF expr THEN
+ * if-body code
+ * ELSE
+ * else-body code
+ * ENDIF
+ */
+ const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+ slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
+ GLboolean isConst, constTrue;
+
+ /* type-check expression */
+ if (!_slang_is_boolean(A, &oper->children[0])) {
+ slang_info_log_error(A->log, "boolean expression expected for 'if'");
+ return NULL;
+ }
+
+ if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+ slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'");
+ return NULL;
+ }
+
+ isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
+ if (isConst) {
+ if (constTrue) {
+ /* if (true) ... */
+ return _slang_gen_operation(A, &oper->children[1]);
+ }
+ else {
+ /* if (false) ... */
+ return _slang_gen_operation(A, &oper->children[2]);
+ }
+ }
+
+ cond = _slang_gen_operation(A, &oper->children[0]);
+ cond = new_cond(cond);
+
+ if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
+ && !haveElseClause) {
+ /* Special case: generate a conditional break */
+ ifBody = new_break_if_true(A, cond);
+ return ifBody;
+ }
+ else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
+ && !haveElseClause
+ && current_loop_oper(A)
+ && current_loop_oper(A)->type != SLANG_OPER_FOR) {
+ /* Special case: generate a conditional continue */
+ ifBody = new_cont_if_true(A, cond);
+ return ifBody;
+ }
+ else {
+ /* general case */
+ ifBody = _slang_gen_operation(A, &oper->children[1]);
+ if (haveElseClause)
+ elseBody = _slang_gen_operation(A, &oper->children[2]);
+ else
+ elseBody = NULL;
+ ifNode = new_if(cond, ifBody, elseBody);
+ return ifNode;
+ }
+}
+
+
+
+static slang_ir_node *
+_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ slang_ir_node *n;
+
+ assert(oper->type == SLANG_OPER_NOT);
+
+ /* type-check expression */
+ if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+ slang_info_log_error(A->log,
+ "scalar/boolean expression expected for '!'");
+ return NULL;
+ }
+
+ n = _slang_gen_operation(A, &oper->children[0]);
+ if (n)
+ return new_not(n);
+ else
+ return NULL;
+}
+
+
+static slang_ir_node *
+_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ slang_ir_node *n1, *n2;
+
+ assert(oper->type == SLANG_OPER_LOGICALXOR);
+
+ if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) ||
+ !_slang_is_scalar_or_boolean(A, &oper->children[0])) {
+ slang_info_log_error(A->log,
+ "scalar/boolean expressions expected for '^^'");
+ return NULL;
+ }
+
+ n1 = _slang_gen_operation(A, &oper->children[0]);
+ if (!n1)
+ return NULL;
+ n2 = _slang_gen_operation(A, &oper->children[1]);
+ if (!n2)
+ return NULL;
+ return new_node2(IR_NOTEQUAL, n1, n2);
+}
+
+
+/**
+ * Generate IR node for storage of a temporary of given size.
+ */
+static slang_ir_node *
+_slang_gen_temporary(GLint size)
+{
+ slang_ir_storage *store;
+ slang_ir_node *n = NULL;
+
+ store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -2, size);
+ if (store) {
+ n = new_node0(IR_VAR_DECL);
+ if (n) {
+ n->Store = store;
+ }
+ else {
+ _slang_free(store);
+ }
+ }
+ return n;
+}
+
+
+/**
+ * Generate program constants for an array.
+ * Ex: const vec2[3] v = vec2[3](vec2(1,1), vec2(2,2), vec2(3,3));
+ * This will allocate and initialize three vector constants, storing
+ * the array in constant memory, not temporaries like a non-const array.
+ * This can also be used for uniform array initializers.
+ * \return GL_TRUE for success, GL_FALSE if failure (semantic error, etc).
+ */
+static GLboolean
+make_constant_array(slang_assemble_ctx *A,
+ slang_variable *var,
+ slang_operation *initializer)
+{
+ struct gl_program *prog = A->program;
+ const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+ const char *varName = (char *) var->a_name;
+ const GLuint numElements = initializer->num_children;
+ GLint size;
+ GLuint i, j;
+ GLfloat *values;
+
+ if (!var->store) {
+ var->store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -6, -6);
+ }
+ size = var->store->Size;
+
+ assert(var->type.qualifier == SLANG_QUAL_CONST ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM);
+ assert(initializer->type == SLANG_OPER_CALL);
+ assert(initializer->array_constructor);
+
+ values = (GLfloat *) _mesa_malloc(numElements * 4 * sizeof(GLfloat));
+
+ /* convert constructor params into ordinary floats */
+ for (i = 0; i < numElements; i++) {
+ const slang_operation *op = &initializer->children[i];
+ if (op->type != SLANG_OPER_LITERAL_FLOAT) {
+ /* unsupported type for this optimization */
+ free(values);
+ return GL_FALSE;
+ }
+ for (j = 0; j < op->literal_size; j++) {
+ values[i * 4 + j] = op->literal[j];
+ }
+ for ( ; j < 4; j++) {
+ values[i * 4 + j] = 0.0f;
+ }
+ }
+
+ /* slightly different paths for constants vs. uniforms */
+ if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+ var->store->File = PROGRAM_UNIFORM;
+ var->store->Index = _mesa_add_uniform(prog->Parameters, varName,
+ size, datatype, values);
+ }
+ else {
+ var->store->File = PROGRAM_CONSTANT;
+ var->store->Index = _mesa_add_named_constant(prog->Parameters, varName,
+ values, size);
+ }
+ assert(var->store->Size == size);
+
+ _mesa_free(values);
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Generate IR node for allocating/declaring a variable (either a local or
+ * a global).
+ * Generally, this involves allocating an slang_ir_storage instance for the
+ * variable, choosing a register file (temporary, constant, etc).
+ * For ordinary variables we do not yet allocate storage though. We do that
+ * when we find the first actual use of the variable to avoid allocating temp
+ * regs that will never get used.
+ * At this time, uniforms are always allocated space in this function.
+ *
+ * \param initializer Optional initializer expression for the variable.
+ */
+static slang_ir_node *
+_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
+ slang_operation *initializer)
+{
+ const char *varName = (const char *) var->a_name;
+ const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+ slang_ir_node *varDecl, *n;
+ slang_ir_storage *store;
+ GLint arrayLen, size, totalSize; /* if array then totalSize > size */
+ gl_register_file file;
+
+ /*assert(!var->declared);*/
+ var->declared = GL_TRUE;
+
+ /* determine GPU register file for simple cases */
+ if (is_sampler_type(&var->type)) {
+ file = PROGRAM_SAMPLER;
+ }
+ else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+ file = PROGRAM_UNIFORM;
+ }
+ else {
+ file = PROGRAM_TEMPORARY;
+ }
+
+ size = _slang_sizeof_type_specifier(&var->type.specifier);
+ if (size <= 0) {
+ slang_info_log_error(A->log, "invalid declaration for '%s'", varName);
+ return NULL;
+ }
+
+ arrayLen = _slang_array_length(var);
+ totalSize = _slang_array_size(size, arrayLen);
+
+ /* Allocate IR node for the declaration */
+ varDecl = new_node0(IR_VAR_DECL);
+ if (!varDecl)
+ return NULL;
+
+ /* Allocate slang_ir_storage for this variable if needed.
+ * Note that we may not actually allocate a constant or temporary register
+ * until later.
+ */
+ if (!var->store) {
+ GLint index = -7; /* TBD / unknown */
+ var->store = _slang_new_ir_storage(file, index, totalSize);
+ if (!var->store)
+ return NULL; /* out of memory */
+ }
+
+ /* set the IR node's Var and Store pointers */
+ varDecl->Var = var;
+ varDecl->Store = var->store;
+
+
+ store = var->store;
+
+ /* if there's an initializer, generate IR for the expression */
+ if (initializer) {
+ slang_ir_node *varRef, *init;
+
+ if (var->type.qualifier == SLANG_QUAL_CONST) {
+ /* if the variable is const, the initializer must be a const
+ * expression as well.
+ */
+#if 0
+ if (!_slang_is_constant_expr(initializer)) {
+ slang_info_log_error(A->log,
+ "initializer for %s not constant", varName);
+ return NULL;
+ }
+#endif
+ }
+
+ /* IR for the variable we're initializing */
+ varRef = new_var(A, var);
+ if (!varRef) {
+ slang_info_log_error(A->log, "out of memory");
+ return NULL;
+ }
+
+ /* constant-folding, etc here */
+ _slang_simplify(initializer, &A->space, A->atoms);
+
+ /* look for simple constant-valued variables and uniforms */
+ if (var->type.qualifier == SLANG_QUAL_CONST ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM) {
+
+ if (initializer->type == SLANG_OPER_CALL &&
+ initializer->array_constructor) {
+ /* array initializer */
+ if (make_constant_array(A, var, initializer))
+ return varRef;
+ }
+ else if (initializer->type == SLANG_OPER_LITERAL_FLOAT ||
+ initializer->type == SLANG_OPER_LITERAL_INT) {
+ /* simple float/vector initializer */
+ if (store->File == PROGRAM_UNIFORM) {
+ store->Index = _mesa_add_uniform(A->program->Parameters,
+ varName,
+ totalSize, datatype,
+ initializer->literal);
+ store->Swizzle = _slang_var_swizzle(size, 0);
+ return varRef;
+ }
+#if 0
+ else {
+ store->File = PROGRAM_CONSTANT;
+ store->Index = _mesa_add_named_constant(A->program->Parameters,
+ varName,
+ initializer->literal,
+ totalSize);
+ store->Swizzle = _slang_var_swizzle(size, 0);
+ return varRef;
+ }
+#endif
+ }
+ }
+
+ /* IR for initializer */
+ init = _slang_gen_operation(A, initializer);
+ if (!init)
+ return NULL;
+
+ /* XXX remove this when type checking is added above */
+ if (init->Store && init->Store->Size != totalSize) {
+ slang_info_log_error(A->log, "invalid assignment (wrong types)");
+ return NULL;
+ }
+
+ /* assign RHS to LHS */
+ n = new_node2(IR_COPY, varRef, init);
+ n = new_seq(varDecl, n);
+ }
+ else {
+ /* no initializer */
+ n = varDecl;
+ }
+
+ if (store->File == PROGRAM_UNIFORM && store->Index < 0) {
+ /* always need to allocate storage for uniforms at this point */
+ store->Index = _mesa_add_uniform(A->program->Parameters, varName,
+ totalSize, datatype, NULL);
+ store->Swizzle = _slang_var_swizzle(size, 0);
+ }
+
+#if 0
+ printf("%s var %p %s store=%p index=%d size=%d\n",
+ __FUNCTION__, (void *) var, (char *) varName,
+ (void *) store, store->Index, store->Size);
+#endif
+
+ return n;
+}
+
+
+/**
+ * Generate code for a selection expression: b ? x : y
+ * XXX In some cases we could implement a selection expression
+ * with an LRP instruction (use the boolean as the interpolant).
+ * Otherwise, we use an IF/ELSE/ENDIF construct.
+ */
+static slang_ir_node *
+_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode;
+ slang_ir_node *tmpDecl, *tmpVar, *tree;
+ slang_typeinfo type0, type1, type2;
+ int size, isBool, isEqual;
+
+ assert(oper->type == SLANG_OPER_SELECT);
+ assert(oper->num_children == 3);
+
+ /* type of children[0] must be boolean */
+ slang_typeinfo_construct(&type0);
+ typeof_operation(A, &oper->children[0], &type0);
+ isBool = (type0.spec.type == SLANG_SPEC_BOOL);
+ slang_typeinfo_destruct(&type0);
+ if (!isBool) {
+ slang_info_log_error(A->log, "selector type is not boolean");
+ return NULL;
+ }
+
+ slang_typeinfo_construct(&type1);
+ slang_typeinfo_construct(&type2);
+ typeof_operation(A, &oper->children[1], &type1);
+ typeof_operation(A, &oper->children[2], &type2);
+ isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
+ slang_typeinfo_destruct(&type1);
+ slang_typeinfo_destruct(&type2);
+ if (!isEqual) {
+ slang_info_log_error(A->log, "incompatible types for ?: operator");
+ return NULL;
+ }
+
+ /* size of x or y's type */
+ size = _slang_sizeof_type_specifier(&type1.spec);
+ assert(size > 0);
+
+ /* temporary var */
+ tmpDecl = _slang_gen_temporary(size);
+
+ /* the condition (child 0) */
+ cond = _slang_gen_operation(A, &oper->children[0]);
+ cond = new_cond(cond);
+
+ /* if-true body (child 1) */
+ tmpVar = new_node0(IR_VAR);
+ tmpVar->Store = tmpDecl->Store;
+ trueExpr = _slang_gen_operation(A, &oper->children[1]);
+ trueNode = new_node2(IR_COPY, tmpVar, trueExpr);
+
+ /* if-false body (child 2) */
+ tmpVar = new_node0(IR_VAR);
+ tmpVar->Store = tmpDecl->Store;
+ falseExpr = _slang_gen_operation(A, &oper->children[2]);
+ falseNode = new_node2(IR_COPY, tmpVar, falseExpr);
+
+ ifNode = new_if(cond, trueNode, falseNode);
+
+ /* tmp var value */
+ tmpVar = new_node0(IR_VAR);
+ tmpVar->Store = tmpDecl->Store;
+
+ tree = new_seq(ifNode, tmpVar);
+ tree = new_seq(tmpDecl, tree);
+
+ /*_slang_print_ir_tree(tree, 10);*/
+ return tree;
+}
+
+
+/**
+ * Generate code for &&.
+ */
+static slang_ir_node *
+_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper)
+{
+ /* rewrite "a && b" as "a ? b : false" */
+ slang_operation *select;
+ slang_ir_node *n;
+
+ select = slang_operation_new(1);
+ select->type = SLANG_OPER_SELECT;
+ slang_operation_add_children(select, 3);
+
+ slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+ slang_operation_copy(slang_oper_child(select, 1), &oper->children[1]);
+ slang_operation_literal_bool(slang_oper_child(select, 2), GL_FALSE);
+
+ n = _slang_gen_select(A, select);
+ return n;
+}
+
+
+/**
+ * Generate code for ||.
+ */
+static slang_ir_node *
+_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
+{
+ /* rewrite "a || b" as "a ? true : b" */
+ slang_operation *select;
+ slang_ir_node *n;
+
+ select = slang_operation_new(1);
+ select->type = SLANG_OPER_SELECT;
+ slang_operation_add_children(select, 3);
+
+ slang_operation_copy(slang_oper_child(select, 0), &oper->children[0]);
+ slang_operation_literal_bool(slang_oper_child(select, 1), GL_TRUE);
+ slang_operation_copy(slang_oper_child(select, 2), &oper->children[1]);
+
+ n = _slang_gen_select(A, select);
+ return n;
+}
+
+
+/**
+ * Generate IR tree for a return statement.
+ */
+static slang_ir_node *
+_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
+{
+ assert(oper->type == SLANG_OPER_RETURN);
+ return new_return(A->curFuncEndLabel);
+}
+
+
+#if 0
+/**
+ * Determine if the given operation/expression is const-valued.
+ */
+static GLboolean
+_slang_is_constant_expr(const slang_operation *oper)
+{
+ slang_variable *var;
+ GLuint i;
+
+ switch (oper->type) {
+ case SLANG_OPER_IDENTIFIER:
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ if (var && var->type.qualifier == SLANG_QUAL_CONST)
+ return GL_TRUE;
+ return GL_FALSE;
+ default:
+ for (i = 0; i < oper->num_children; i++) {
+ if (!_slang_is_constant_expr(&oper->children[i]))
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ }
+}
+#endif
+
+
+/**
+ * Check if an assignment of type t1 to t0 is legal.
+ * XXX more cases needed.
+ */
+static GLboolean
+_slang_assignment_compatible(slang_assemble_ctx *A,
+ slang_operation *op0,
+ slang_operation *op1)
+{
+ slang_typeinfo t0, t1;
+ GLuint sz0, sz1;
+
+ if (op0->type == SLANG_OPER_POSTINCREMENT ||
+ op0->type == SLANG_OPER_POSTDECREMENT) {
+ return GL_FALSE;
+ }
+
+ slang_typeinfo_construct(&t0);
+ typeof_operation(A, op0, &t0);
+
+ slang_typeinfo_construct(&t1);
+ typeof_operation(A, op1, &t1);
+
+ sz0 = _slang_sizeof_type_specifier(&t0.spec);
+ sz1 = _slang_sizeof_type_specifier(&t1.spec);
+
+#if 1
+ if (sz0 != sz1) {
+ /*printf("assignment size mismatch %u vs %u\n", sz0, sz1);*/
+ return GL_FALSE;
+ }
+#endif
+
+ if (t0.spec.type == SLANG_SPEC_STRUCT &&
+ t1.spec.type == SLANG_SPEC_STRUCT &&
+ t0.spec._struct->a_name != t1.spec._struct->a_name)
+ return GL_FALSE;
+
+ if (t0.spec.type == SLANG_SPEC_FLOAT &&
+ t1.spec.type == SLANG_SPEC_BOOL)
+ return GL_FALSE;
+
+#if 0 /* not used just yet - causes problems elsewhere */
+ if (t0.spec.type == SLANG_SPEC_INT &&
+ t1.spec.type == SLANG_SPEC_FLOAT)
+ return GL_FALSE;
+#endif
+
+ if (t0.spec.type == SLANG_SPEC_BOOL &&
+ t1.spec.type == SLANG_SPEC_FLOAT)
+ return GL_FALSE;
+
+ if (t0.spec.type == SLANG_SPEC_BOOL &&
+ t1.spec.type == SLANG_SPEC_INT)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Generate IR tree for a local variable declaration.
+ * Basically do some error checking and call _slang_gen_var_decl().
+ */
+static slang_ir_node *
+_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
+{
+ const char *varName = (char *) oper->a_id;
+ slang_variable *var;
+ slang_ir_node *varDecl;
+ slang_operation *initializer;
+
+ assert(oper->type == SLANG_OPER_VARIABLE_DECL);
+ assert(oper->num_children <= 1);
+
+
+ /* lookup the variable by name */
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ if (!var)
+ return NULL; /* "shouldn't happen" */
+
+ if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
+ var->type.qualifier == SLANG_QUAL_VARYING ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM) {
+ /* can't declare attribute/uniform vars inside functions */
+ slang_info_log_error(A->log,
+ "local variable '%s' cannot be an attribute/uniform/varying",
+ varName);
+ return NULL;
+ }
+
+#if 0
+ if (v->declared) {
+ slang_info_log_error(A->log, "variable '%s' redeclared", varName);
+ return NULL;
+ }
+#endif
+
+ /* check if the var has an initializer */
+ if (oper->num_children > 0) {
+ assert(oper->num_children == 1);
+ initializer = &oper->children[0];
+ }
+ else if (var->initializer) {
+ initializer = var->initializer;
+ }
+ else {
+ initializer = NULL;
+ }
+
+ if (initializer) {
+ /* check/compare var type and initializer type */
+ if (!_slang_assignment_compatible(A, oper, initializer)) {
+ slang_info_log_error(A->log, "incompatible types in assignment");
+ return NULL;
+ }
+ }
+ else {
+ if (var->type.qualifier == SLANG_QUAL_CONST) {
+ slang_info_log_error(A->log,
+ "const-qualified variable '%s' requires initializer",
+ varName);
+ return NULL;
+ }
+ }
+
+ /* Generate IR node */
+ varDecl = _slang_gen_var_decl(A, var, initializer);
+ if (!varDecl)
+ return NULL;
+
+ return varDecl;
+}
+
+
+/**
+ * Generate IR tree for a reference to a variable (such as in an expression).
+ * This is different from a variable declaration.
+ */
+static slang_ir_node *
+_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
+{
+ /* If there's a variable associated with this oper (from inlining)
+ * use it. Otherwise, use the oper's var id.
+ */
+ slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
+ slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
+ slang_ir_node *n;
+ if (!var) {
+ slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
+ return NULL;
+ }
+ assert(var->declared);
+ n = new_var(A, var);
+ return n;
+}
+
+
+
+/**
+ * Return the number of components actually named by the swizzle.
+ * Recall that swizzles may have undefined/don't-care values.
+ */
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+ GLuint size = 0, i;
+ for (i = 0; i < 4; i++) {
+ GLuint swz = GET_SWZ(swizzle, i);
+ size += (swz >= 0 && swz <= 3);
+ }
+ return size;
+}
+
+
+static slang_ir_node *
+_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle)
+{
+ slang_ir_node *n = new_node1(IR_SWIZZLE, child);
+ assert(child);
+ if (n) {
+ assert(!n->Store);
+ n->Store = _slang_new_ir_storage_relative(0,
+ swizzle_size(swizzle),
+ child->Store);
+ n->Store->Swizzle = swizzle;
+ }
+ return n;
+}
+
+
+static GLboolean
+is_store_writable(const slang_assemble_ctx *A, const slang_ir_storage *store)
+{
+ while (store->Parent)
+ store = store->Parent;
+
+ if (!(store->File == PROGRAM_OUTPUT ||
+ store->File == PROGRAM_TEMPORARY ||
+ (store->File == PROGRAM_VARYING &&
+ A->program->Target == GL_VERTEX_PROGRAM_ARB))) {
+ return GL_FALSE;
+ }
+ else {
+ return GL_TRUE;
+ }
+}
+
+
+/**
+ * Walk up an IR storage path to compute the final swizzle.
+ * This is used when we find an expression such as "foo.xz.yx".
+ */
+static GLuint
+root_swizzle(const slang_ir_storage *st)
+{
+ GLuint swizzle = st->Swizzle;
+ while (st->Parent) {
+ st = st->Parent;
+ swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+ }
+ return swizzle;
+}
+
+
+/**
+ * Generate IR tree for an assignment (=).
+ */
+static slang_ir_node *
+_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
+{
+ slang_operation *pred = NULL;
+ slang_ir_node *n = NULL;
+
+ if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
+ /* Check that var is writeable */
+ slang_variable *var
+ = _slang_variable_locate(oper->children[0].locals,
+ oper->children[0].a_id, GL_TRUE);
+ if (!var) {
+ slang_info_log_error(A->log, "undefined variable '%s'",
+ (char *) oper->children[0].a_id);
+ return NULL;
+ }
+ if (var->type.qualifier == SLANG_QUAL_CONST ||
+ var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM ||
+ (var->type.qualifier == SLANG_QUAL_VARYING &&
+ A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) {
+ slang_info_log_error(A->log,
+ "illegal assignment to read-only variable '%s'",
+ (char *) oper->children[0].a_id);
+ return NULL;
+ }
+
+ /* check if we need to predicate this assignment based on __notRetFlag */
+ if ((var->is_global ||
+ var->type.qualifier == SLANG_QUAL_OUT ||
+ var->type.qualifier == SLANG_QUAL_INOUT) && A->UseReturnFlag) {
+ /* create predicate, used below */
+ pred = slang_operation_new(1);
+ pred->type = SLANG_OPER_IDENTIFIER;
+ pred->a_id = slang_atom_pool_atom(A->atoms, "__notRetFlag");
+ pred->locals->outer_scope = oper->locals->outer_scope;
+ }
+ }
+
+ if (oper->children[0].type == SLANG_OPER_IDENTIFIER &&
+ oper->children[1].type == SLANG_OPER_CALL) {
+ /* Special case of: x = f(a, b)
+ * Replace with f(a, b, x) (where x == hidden __retVal out param)
+ *
+ * XXX this could be even more effective if we could accomodate
+ * cases such as "v.x = f();" - would help with typical vertex
+ * transformation.
+ */
+ n = _slang_gen_function_call_name(A,
+ (const char *) oper->children[1].a_id,
+ &oper->children[1], &oper->children[0]);
+ }
+ else {
+ slang_ir_node *lhs, *rhs;
+
+ /* lhs and rhs type checking */
+ if (!_slang_assignment_compatible(A,
+ &oper->children[0],
+ &oper->children[1])) {
+ slang_info_log_error(A->log, "incompatible types in assignment");
+ return NULL;
+ }
+
+ lhs = _slang_gen_operation(A, &oper->children[0]);
+ if (!lhs) {
+ return NULL;
+ }
+
+ if (!lhs->Store) {
+ slang_info_log_error(A->log,
+ "invalid left hand side for assignment");
+ return NULL;
+ }
+
+ /* check that lhs is writable */
+ if (!is_store_writable(A, lhs->Store)) {
+ slang_info_log_error(A->log,
+ "illegal assignment to read-only l-value");
+ return NULL;
+ }
+
+ rhs = _slang_gen_operation(A, &oper->children[1]);
+ if (lhs && rhs) {
+ /* convert lhs swizzle into writemask */
+ const GLuint swizzle = root_swizzle(lhs->Store);
+ GLuint writemask, newSwizzle = 0x0;
+ if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) {
+ /* Non-simple writemask, need to swizzle right hand side in
+ * order to put components into the right place.
+ */
+ rhs = _slang_gen_swizzle(rhs, newSwizzle);
+ }
+ n = new_node2(IR_COPY, lhs, rhs);
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ if (n && pred) {
+ /* predicate the assignment code on __notRetFlag */
+ slang_ir_node *top, *cond;
+
+ cond = _slang_gen_operation(A, pred);
+ top = new_if(cond, n, NULL);
+ return top;
+ }
+ return n;
+}
+
+
+/**
+ * Generate IR tree for referencing a field in a struct (or basic vector type)
+ */
+static slang_ir_node *
+_slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
+{
+ slang_typeinfo ti;
+
+ /* type of struct */
+ slang_typeinfo_construct(&ti);
+ typeof_operation(A, &oper->children[0], &ti);
+
+ if (_slang_type_is_vector(ti.spec.type)) {
+ /* the field should be a swizzle */
+ const GLuint rows = _slang_type_dim(ti.spec.type);
+ slang_swizzle swz;
+ slang_ir_node *n;
+ GLuint swizzle;
+ if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+ slang_info_log_error(A->log, "Bad swizzle");
+ return NULL;
+ }
+ swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+ swz.swizzle[1],
+ swz.swizzle[2],
+ swz.swizzle[3]);
+
+ n = _slang_gen_operation(A, &oper->children[0]);
+ /* create new parent node with swizzle */
+ if (n)
+ n = _slang_gen_swizzle(n, swizzle);
+ return n;
+ }
+ else if ( ti.spec.type == SLANG_SPEC_FLOAT
+ || ti.spec.type == SLANG_SPEC_INT
+ || ti.spec.type == SLANG_SPEC_BOOL) {
+ const GLuint rows = 1;
+ slang_swizzle swz;
+ slang_ir_node *n;
+ GLuint swizzle;
+ if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+ slang_info_log_error(A->log, "Bad swizzle");
+ }
+ swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+ swz.swizzle[1],
+ swz.swizzle[2],
+ swz.swizzle[3]);
+ n = _slang_gen_operation(A, &oper->children[0]);
+ /* create new parent node with swizzle */
+ n = _slang_gen_swizzle(n, swizzle);
+ return n;
+ }
+ else {
+ /* the field is a structure member (base.field) */
+ /* oper->children[0] is the base */
+ /* oper->a_id is the field name */
+ slang_ir_node *base, *n;
+ slang_typeinfo field_ti;
+ GLint fieldSize, fieldOffset = -1;
+
+ /* type of field */
+ slang_typeinfo_construct(&field_ti);
+ typeof_operation(A, oper, &field_ti);
+
+ fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
+ if (fieldSize > 0)
+ fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
+
+ if (fieldSize == 0 || fieldOffset < 0) {
+ const char *structName;
+ if (ti.spec._struct)
+ structName = (char *) ti.spec._struct->a_name;
+ else
+ structName = "unknown";
+ slang_info_log_error(A->log,
+ "\"%s\" is not a member of struct \"%s\"",
+ (char *) oper->a_id, structName);
+ return NULL;
+ }
+ assert(fieldSize >= 0);
+
+ base = _slang_gen_operation(A, &oper->children[0]);
+ if (!base) {
+ /* error msg should have already been logged */
+ return NULL;
+ }
+
+ n = new_node1(IR_FIELD, base);
+ if (!n)
+ return NULL;
+
+ n->Field = (char *) oper->a_id;
+
+ /* Store the field's offset in storage->Index */
+ n->Store = _slang_new_ir_storage(base->Store->File,
+ fieldOffset,
+ fieldSize);
+
+ return n;
+ }
+}
+
+
+/**
+ * Gen code for array indexing.
+ */
+static slang_ir_node *
+_slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
+{
+ slang_typeinfo array_ti;
+
+ /* get array's type info */
+ slang_typeinfo_construct(&array_ti);
+ typeof_operation(A, &oper->children[0], &array_ti);
+
+ if (_slang_type_is_vector(array_ti.spec.type)) {
+ /* indexing a simple vector type: "vec4 v; v[0]=p;" */
+ /* translate the index into a swizzle/writemask: "v.x=p" */
+ const GLuint max = _slang_type_dim(array_ti.spec.type);
+ GLint index;
+ slang_ir_node *n;
+
+ index = (GLint) oper->children[1].literal[0];
+ if (oper->children[1].type != SLANG_OPER_LITERAL_INT ||
+ index >= (GLint) max) {
+#if 0
+ slang_info_log_error(A->log, "Invalid array index for vector type");
+ printf("type = %d\n", oper->children[1].type);
+ printf("index = %d, max = %d\n", index, max);
+ printf("array = %s\n", (char*)oper->children[0].a_id);
+ printf("index = %s\n", (char*)oper->children[1].a_id);
+ return NULL;
+#else
+ index = 0;
+#endif
+ }
+
+ n = _slang_gen_operation(A, &oper->children[0]);
+ if (n) {
+ /* use swizzle to access the element */
+ GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index,
+ SWIZZLE_NIL,
+ SWIZZLE_NIL,
+ SWIZZLE_NIL);
+ n = _slang_gen_swizzle(n, swizzle);
+ }
+ assert(n->Store);
+ return n;
+ }
+ else {
+ /* conventional array */
+ slang_typeinfo elem_ti;
+ slang_ir_node *elem, *array, *index;
+ GLint elemSize, arrayLen;
+
+ /* size of array element */
+ slang_typeinfo_construct(&elem_ti);
+ typeof_operation(A, oper, &elem_ti);
+ elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
+
+ if (_slang_type_is_matrix(array_ti.spec.type))
+ arrayLen = _slang_type_dim(array_ti.spec.type);
+ else
+ arrayLen = array_ti.array_len;
+
+ slang_typeinfo_destruct(&array_ti);
+ slang_typeinfo_destruct(&elem_ti);
+
+ if (elemSize <= 0) {
+ /* unknown var or type */
+ slang_info_log_error(A->log, "Undefined variable or type");
+ return NULL;
+ }
+
+ array = _slang_gen_operation(A, &oper->children[0]);
+ index = _slang_gen_operation(A, &oper->children[1]);
+ if (array && index) {
+ /* bounds check */
+ GLint constIndex = -1;
+ if (index->Opcode == IR_FLOAT) {
+ constIndex = (int) index->Value[0];
+ if (constIndex < 0 || constIndex >= arrayLen) {
+ slang_info_log_error(A->log,
+ "Array index out of bounds (index=%d size=%d)",
+ constIndex, arrayLen);
+ _slang_free_ir_tree(array);
+ _slang_free_ir_tree(index);
+ return NULL;
+ }
+ }
+
+ if (!array->Store) {
+ slang_info_log_error(A->log, "Invalid array");
+ return NULL;
+ }
+
+ elem = new_node2(IR_ELEMENT, array, index);
+
+ /* The storage info here will be updated during code emit */
+ elem->Store = _slang_new_ir_storage(array->Store->File,
+ array->Store->Index,
+ elemSize);
+ elem->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
+ return elem;
+ }
+ else {
+ _slang_free_ir_tree(array);
+ _slang_free_ir_tree(index);
+ return NULL;
+ }
+ }
+}
+
+
+static slang_ir_node *
+_slang_gen_compare(slang_assemble_ctx *A, slang_operation *oper,
+ slang_ir_opcode opcode)
+{
+ slang_typeinfo t0, t1;
+ slang_ir_node *n;
+
+ slang_typeinfo_construct(&t0);
+ typeof_operation(A, &oper->children[0], &t0);
+
+ slang_typeinfo_construct(&t1);
+ typeof_operation(A, &oper->children[0], &t1);
+
+ if (t0.spec.type == SLANG_SPEC_ARRAY ||
+ t1.spec.type == SLANG_SPEC_ARRAY) {
+ slang_info_log_error(A->log, "Illegal array comparison");
+ return NULL;
+ }
+
+ if (oper->type != SLANG_OPER_EQUAL &&
+ oper->type != SLANG_OPER_NOTEQUAL) {
+ /* <, <=, >, >= can only be used with scalars */
+ if ((t0.spec.type != SLANG_SPEC_INT &&
+ t0.spec.type != SLANG_SPEC_FLOAT) ||
+ (t1.spec.type != SLANG_SPEC_INT &&
+ t1.spec.type != SLANG_SPEC_FLOAT)) {
+ slang_info_log_error(A->log, "Incompatible type(s) for inequality operator");
+ return NULL;
+ }
+ }
+
+ n = new_node2(opcode,
+ _slang_gen_operation(A, &oper->children[0]),
+ _slang_gen_operation(A, &oper->children[1]));
+
+ /* result is a bool (size 1) */
+ n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+
+ return n;
+}
+
+
+#if 0
+static void
+print_vars(slang_variable_scope *s)
+{
+ int i;
+ printf("vars: ");
+ for (i = 0; i < s->num_variables; i++) {
+ printf("%s %d, \n",
+ (char*) s->variables[i]->a_name,
+ s->variables[i]->declared);
+ }
+
+ printf("\n");
+}
+#endif
+
+
+#if 0
+static void
+_slang_undeclare_vars(slang_variable_scope *locals)
+{
+ if (locals->num_variables > 0) {
+ int i;
+ for (i = 0; i < locals->num_variables; i++) {
+ slang_variable *v = locals->variables[i];
+ printf("undeclare %s at %p\n", (char*) v->a_name, v);
+ v->declared = GL_FALSE;
+ }
+ }
+}
+#endif
+
+
+/**
+ * Generate IR tree for a slang_operation (AST node)
+ */
+static slang_ir_node *
+_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case SLANG_OPER_BLOCK_NEW_SCOPE:
+ {
+ slang_ir_node *n;
+
+ _slang_push_var_table(A->vartable);
+
+ oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */
+ n = _slang_gen_operation(A, oper);
+ oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */
+
+ _slang_pop_var_table(A->vartable);
+
+ /*_slang_undeclare_vars(oper->locals);*/
+ /*print_vars(oper->locals);*/
+
+ if (n)
+ n = new_node1(IR_SCOPE, n);
+ return n;
+ }
+ break;
+
+ case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+ /* list of operations */
+ if (oper->num_children > 0)
+ {
+ slang_ir_node *n, *tree = NULL;
+ GLuint i;
+
+ for (i = 0; i < oper->num_children; i++) {
+ n = _slang_gen_operation(A, &oper->children[i]);
+ if (!n) {
+ _slang_free_ir_tree(tree);
+ return NULL; /* error must have occured */
+ }
+ tree = new_seq(tree, n);
+ }
+
+ return tree;
+ }
+ else {
+ return new_node0(IR_NOP);
+ }
+
+ case SLANG_OPER_EXPRESSION:
+ return _slang_gen_operation(A, &oper->children[0]);
+
+ case SLANG_OPER_FOR:
+ return _slang_gen_for(A, oper);
+ case SLANG_OPER_DO:
+ return _slang_gen_do(A, oper);
+ case SLANG_OPER_WHILE:
+ return _slang_gen_while(A, oper);
+ case SLANG_OPER_BREAK:
+ if (!current_loop_oper(A)) {
+ slang_info_log_error(A->log, "'break' not in loop");
+ return NULL;
+ }
+ return new_break(current_loop_ir(A));
+ case SLANG_OPER_CONTINUE:
+ if (!current_loop_oper(A)) {
+ slang_info_log_error(A->log, "'continue' not in loop");
+ return NULL;
+ }
+ return _slang_gen_continue(A, oper);
+ case SLANG_OPER_DISCARD:
+ return new_node0(IR_KILL);
+
+ case SLANG_OPER_EQUAL:
+ return _slang_gen_compare(A, oper, IR_EQUAL);
+ case SLANG_OPER_NOTEQUAL:
+ return _slang_gen_compare(A, oper, IR_NOTEQUAL);
+ case SLANG_OPER_GREATER:
+ return _slang_gen_compare(A, oper, IR_SGT);
+ case SLANG_OPER_LESS:
+ return _slang_gen_compare(A, oper, IR_SLT);
+ case SLANG_OPER_GREATEREQUAL:
+ return _slang_gen_compare(A, oper, IR_SGE);
+ case SLANG_OPER_LESSEQUAL:
+ return _slang_gen_compare(A, oper, IR_SLE);
+ case SLANG_OPER_ADD:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "+", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_SUBTRACT:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "-", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_MULTIPLY:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "*", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_DIVIDE:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "/", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_MINUS:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 1);
+ n = _slang_gen_function_call_name(A, "-", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_PLUS:
+ /* +expr --> do nothing */
+ return _slang_gen_operation(A, &oper->children[0]);
+ case SLANG_OPER_VARIABLE_DECL:
+ return _slang_gen_declaration(A, oper);
+ case SLANG_OPER_ASSIGN:
+ return _slang_gen_assignment(A, oper);
+ case SLANG_OPER_ADDASSIGN:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "+=", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_SUBASSIGN:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "-=", oper, NULL);
+ return n;
+ }
+ break;
+ case SLANG_OPER_MULASSIGN:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "*=", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_DIVASSIGN:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_function_call_name(A, "/=", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_LOGICALAND:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_logical_and(A, oper);
+ return n;
+ }
+ case SLANG_OPER_LOGICALOR:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = _slang_gen_logical_or(A, oper);
+ return n;
+ }
+ case SLANG_OPER_LOGICALXOR:
+ return _slang_gen_xor(A, oper);
+ case SLANG_OPER_NOT:
+ return _slang_gen_not(A, oper);
+ case SLANG_OPER_SELECT: /* b ? x : y */
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 3);
+ n = _slang_gen_select(A, oper);
+ return n;
+ }
+
+ case SLANG_OPER_ASM:
+ return _slang_gen_asm(A, oper, NULL);
+ case SLANG_OPER_CALL:
+ return _slang_gen_function_call_name(A, (const char *) oper->a_id,
+ oper, NULL);
+ case SLANG_OPER_METHOD:
+ return _slang_gen_method_call(A, oper);
+ case SLANG_OPER_RETURN:
+ return _slang_gen_return(A, oper);
+ case SLANG_OPER_RETURN_INLINED:
+ return _slang_gen_return(A, oper);
+ case SLANG_OPER_LABEL:
+ return new_label(oper->label);
+ case SLANG_OPER_IDENTIFIER:
+ return _slang_gen_variable(A, oper);
+ case SLANG_OPER_IF:
+ return _slang_gen_if(A, oper);
+ case SLANG_OPER_FIELD:
+ return _slang_gen_struct_field(A, oper);
+ case SLANG_OPER_SUBSCRIPT:
+ return _slang_gen_array_element(A, oper);
+ case SLANG_OPER_LITERAL_FLOAT:
+ /* fall-through */
+ case SLANG_OPER_LITERAL_INT:
+ /* fall-through */
+ case SLANG_OPER_LITERAL_BOOL:
+ return new_float_literal(oper->literal, oper->literal_size);
+
+ case SLANG_OPER_POSTINCREMENT: /* var++ */
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 1);
+ n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_POSTDECREMENT: /* var-- */
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 1);
+ n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_PREINCREMENT: /* ++var */
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 1);
+ n = _slang_gen_function_call_name(A, "++", oper, NULL);
+ return n;
+ }
+ case SLANG_OPER_PREDECREMENT: /* --var */
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 1);
+ n = _slang_gen_function_call_name(A, "--", oper, NULL);
+ return n;
+ }
+
+ case SLANG_OPER_NON_INLINED_CALL:
+ case SLANG_OPER_SEQUENCE:
+ {
+ slang_ir_node *tree = NULL;
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
+ tree = new_seq(tree, n);
+ if (n)
+ tree->Store = n->Store;
+ }
+ if (oper->type == SLANG_OPER_NON_INLINED_CALL) {
+ tree = new_function_call(tree, oper->label);
+ }
+ return tree;
+ }
+
+ case SLANG_OPER_NONE:
+ case SLANG_OPER_VOID:
+ /* returning NULL here would generate an error */
+ return new_node0(IR_NOP);
+
+ default:
+ _mesa_problem(NULL, "bad node type %d in _slang_gen_operation",
+ oper->type);
+ return new_node0(IR_NOP);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Check if the given type specifier is a rectangular texture sampler.
+ */
+static GLboolean
+is_rect_sampler_spec(const slang_type_specifier *spec)
+{
+ while (spec->_array) {
+ spec = spec->_array;
+ }
+ return spec->type == SLANG_SPEC_SAMPLER2DRECT ||
+ spec->type == SLANG_SPEC_SAMPLER2DRECTSHADOW;
+}
+
+
+
+/**
+ * Called by compiler when a global variable has been parsed/compiled.
+ * Here we examine the variable's type to determine what kind of register
+ * storage will be used.
+ *
+ * A uniform such as "gl_Position" will become the register specification
+ * (PROGRAM_OUTPUT, VERT_RESULT_HPOS). Or, uniform "gl_FogFragCoord"
+ * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC).
+ *
+ * Samplers are interesting. For "uniform sampler2D tex;" we'll specify
+ * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an
+ * actual texture unit (as specified by the user calling glUniform1i()).
+ */
+GLboolean
+_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
+ slang_unit_type type)
+{
+ struct gl_program *prog = A->program;
+ const char *varName = (char *) var->a_name;
+ GLboolean success = GL_TRUE;
+ slang_ir_storage *store = NULL;
+ int dbg = 0;
+ const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
+ const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
+ const GLint arrayLen = _slang_array_length(var);
+ const GLint totalSize = _slang_array_size(size, arrayLen);
+ GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
+
+ var->is_global = GL_TRUE;
+
+ /* check for sampler2D arrays */
+ if (texIndex == -1 && var->type.specifier._array)
+ texIndex = sampler_to_texture_index(var->type.specifier._array->type);
+
+ if (texIndex != -1) {
+ /* This is a texture sampler variable...
+ * store->File = PROGRAM_SAMPLER
+ * store->Index = sampler number (0..7, typically)
+ * store->Size = texture type index (1D, 2D, 3D, cube, etc)
+ */
+ if (var->initializer) {
+ slang_info_log_error(A->log, "illegal assignment to '%s'", varName);
+ return GL_FALSE;
+ }
+#if FEATURE_es2_glsl /* XXX should use FEATURE_texture_rect */
+ /* disallow rect samplers */
+ if (is_rect_sampler_spec(&var->type.specifier)) {
+ slang_info_log_error(A->log, "invalid sampler type for '%s'", varName);
+ return GL_FALSE;
+ }
+#else
+ (void) is_rect_sampler_spec; /* silence warning */
+#endif
+ {
+ GLint sampNum = _mesa_add_sampler(prog->Parameters, varName, datatype);
+ store = _slang_new_ir_storage_sampler(sampNum, texIndex, totalSize);
+
+ /* If we have a sampler array, then we need to allocate the
+ * additional samplers to ensure we don't allocate them elsewhere.
+ * We can't directly use _mesa_add_sampler() as that checks the
+ * varName and gets a match, so we call _mesa_add_parameter()
+ * directly and use the last sampler number from the call above.
+ */
+ if (arrayLen > 0) {
+ GLint a = arrayLen - 1;
+ GLint i;
+ for (i = 0; i < a; i++) {
+ GLfloat value = (GLfloat)(i + sampNum + 1);
+ (void) _mesa_add_parameter(prog->Parameters, PROGRAM_SAMPLER,
+ varName, 1, datatype, &value, NULL, 0x0);
+ }
+ }
+ }
+ if (dbg) printf("SAMPLER ");
+ }
+ else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
+ /* Uniform variable */
+ const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
+
+ if (prog) {
+ /* user-defined uniform */
+ if (datatype == GL_NONE) {
+ if ((var->type.specifier.type == SLANG_SPEC_ARRAY &&
+ var->type.specifier._array->type == SLANG_SPEC_STRUCT) ||
+ (var->type.specifier.type == SLANG_SPEC_STRUCT)) {
+ /* temporary work-around */
+ GLenum datatype = GL_FLOAT;
+ GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
+ totalSize, datatype, NULL);
+ store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
+ totalSize, swizzle);
+
+ if (arrayLen > 0) {
+ GLint a = arrayLen - 1;
+ GLint i;
+ for (i = 0; i < a; i++) {
+ GLfloat value = (GLfloat)(i + uniformLoc + 1);
+ (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
+ varName, 1, datatype, &value, NULL, 0x0);
+ }
+ }
+
+ /* XXX what we need to do is unroll the struct into its
+ * basic types, creating a uniform variable for each.
+ * For example:
+ * struct foo {
+ * vec3 a;
+ * vec4 b;
+ * };
+ * uniform foo f;
+ *
+ * Should produce uniforms:
+ * "f.a" (GL_FLOAT_VEC3)
+ * "f.b" (GL_FLOAT_VEC4)
+ */
+
+ if (var->initializer) {
+ slang_info_log_error(A->log,
+ "unsupported initializer for uniform '%s'", varName);
+ return GL_FALSE;
+ }
+ }
+ else {
+ slang_info_log_error(A->log,
+ "invalid datatype for uniform variable %s",
+ varName);
+ return GL_FALSE;
+ }
+ }
+ else {
+ /* non-struct uniform */
+ if (!_slang_gen_var_decl(A, var, var->initializer))
+ return GL_FALSE;
+ store = var->store;
+ }
+ }
+ else {
+ /* pre-defined uniform, like gl_ModelviewMatrix */
+ /* We know it's a uniform, but don't allocate storage unless
+ * it's really used.
+ */
+ store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
+ totalSize, swizzle);
+ }
+ if (dbg) printf("UNIFORM (sz %d) ", totalSize);
+ }
+ else if (var->type.qualifier == SLANG_QUAL_VARYING) {
+ /* varyings must be float, vec or mat */
+ if (!_slang_type_is_float_vec_mat(var->type.specifier.type) &&
+ var->type.specifier.type != SLANG_SPEC_ARRAY) {
+ slang_info_log_error(A->log,
+ "varying '%s' must be float/vector/matrix",
+ varName);
+ return GL_FALSE;
+ }
+
+ if (var->initializer) {
+ slang_info_log_error(A->log, "illegal initializer for varying '%s'",
+ varName);
+ return GL_FALSE;
+ }
+
+ if (prog) {
+ /* user-defined varying */
+ GLbitfield flags;
+ GLint varyingLoc;
+ GLuint swizzle;
+
+ flags = 0x0;
+ if (var->type.centroid == SLANG_CENTROID)
+ flags |= PROG_PARAM_BIT_CENTROID;
+ if (var->type.variant == SLANG_INVARIANT)
+ flags |= PROG_PARAM_BIT_INVARIANT;
+
+ varyingLoc = _mesa_add_varying(prog->Varying, varName,
+ totalSize, flags);
+ swizzle = _slang_var_swizzle(size, 0);
+ store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
+ totalSize, swizzle);
+ }
+ else {
+ /* pre-defined varying, like gl_Color or gl_TexCoord */
+ if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+ /* fragment program input */
+ GLuint swizzle;
+ GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
+ &swizzle);
+ assert(index >= 0);
+ assert(index < FRAG_ATTRIB_MAX);
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
+ size, swizzle);
+ }
+ else {
+ /* vertex program output */
+ GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+ GLuint swizzle = _slang_var_swizzle(size, 0);
+ assert(index >= 0);
+ assert(index < VERT_RESULT_MAX);
+ assert(type == SLANG_UNIT_VERTEX_BUILTIN);
+ store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
+ size, swizzle);
+ }
+ if (dbg) printf("V/F ");
+ }
+ if (dbg) printf("VARYING ");
+ }
+ else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
+ GLuint swizzle;
+ GLint index;
+ /* attributes must be float, vec or mat */
+ if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
+ slang_info_log_error(A->log,
+ "attribute '%s' must be float/vector/matrix",
+ varName);
+ return GL_FALSE;
+ }
+
+ if (prog) {
+ /* user-defined vertex attribute */
+ const GLint attr = -1; /* unknown */
+ swizzle = _slang_var_swizzle(size, 0);
+ index = _mesa_add_attribute(prog->Attributes, varName,
+ size, datatype, attr);
+ assert(index >= 0);
+ index = VERT_ATTRIB_GENERIC0 + index;
+ }
+ else {
+ /* pre-defined vertex attrib */
+ index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle);
+ assert(index >= 0);
+ }
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+ if (dbg) printf("ATTRIB ");
+ }
+ else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
+ GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
+ GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
+ &swizzle);
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
+ if (dbg) printf("INPUT ");
+ }
+ else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
+ if (type == SLANG_UNIT_VERTEX_BUILTIN) {
+ GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+ store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
+ }
+ else {
+ GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
+ GLint specialSize = 4; /* treat all fragment outputs as float[4] */
+ assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
+ store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
+ }
+ if (dbg) printf("OUTPUT ");
+ }
+ else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
+ /* pre-defined global constant, like gl_MaxLights */
+ store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
+ if (dbg) printf("CONST ");
+ }
+ else {
+ /* ordinary variable (may be const) */
+ slang_ir_node *n;
+
+ /* IR node to declare the variable */
+ n = _slang_gen_var_decl(A, var, var->initializer);
+
+ /* emit GPU instructions */
+ success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_FALSE, A->log);
+
+ _slang_free_ir_tree(n);
+ }
+
+ if (dbg) printf("GLOBAL VAR %s idx %d\n", (char*) var->a_name,
+ store ? store->Index : -2);
+
+ if (store)
+ var->store = store; /* save var's storage info */
+
+ var->declared = GL_TRUE;
+
+ return success;
+}
+
+
+/**
+ * Produce an IR tree from a function AST (fun->body).
+ * Then call the code emitter to convert the IR tree into gl_program
+ * instructions.
+ */
+GLboolean
+_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
+{
+ slang_ir_node *n;
+ GLboolean success = GL_TRUE;
+
+ if (_mesa_strcmp((char *) fun->header.a_name, "main") != 0) {
+ /* we only really generate code for main, all other functions get
+ * inlined or codegen'd upon an actual call.
+ */
+#if 0
+ /* do some basic error checking though */
+ if (fun->header.type.specifier.type != SLANG_SPEC_VOID) {
+ /* check that non-void functions actually return something */
+ slang_operation *op
+ = _slang_find_node_type(fun->body, SLANG_OPER_RETURN);
+ if (!op) {
+ slang_info_log_error(A->log,
+ "function \"%s\" has no return statement",
+ (char *) fun->header.a_name);
+ printf(
+ "function \"%s\" has no return statement\n",
+ (char *) fun->header.a_name);
+ return GL_FALSE;
+ }
+ }
+#endif
+ return GL_TRUE; /* not an error */
+ }
+
+#if 0
+ printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name);
+ slang_print_function(fun, 1);
+#endif
+
+ /* should have been allocated earlier: */
+ assert(A->program->Parameters );
+ assert(A->program->Varying);
+ assert(A->vartable);
+
+ A->LoopDepth = 0;
+ A->UseReturnFlag = GL_FALSE;
+ A->CurFunction = fun;
+
+ /* fold constant expressions, etc. */
+ _slang_simplify(fun->body, &A->space, A->atoms);
+
+#if 0
+ printf("\n*********** simplified %s\n", (char *) fun->header.a_name);
+ slang_print_function(fun, 1);
+#endif
+
+ /* Create an end-of-function label */
+ A->curFuncEndLabel = _slang_label_new("__endOfFunc__main");
+
+ /* push new vartable scope */
+ _slang_push_var_table(A->vartable);
+
+ /* Generate IR tree for the function body code */
+ n = _slang_gen_operation(A, fun->body);
+ if (n)
+ n = new_node1(IR_SCOPE, n);
+
+ /* pop vartable, restore previous */
+ _slang_pop_var_table(A->vartable);
+
+ if (!n) {
+ /* XXX record error */
+ return GL_FALSE;
+ }
+
+ /* append an end-of-function-label to IR tree */
+ n = new_seq(n, new_label(A->curFuncEndLabel));
+
+ /*_slang_label_delete(A->curFuncEndLabel);*/
+ A->curFuncEndLabel = NULL;
+
+#if 0
+ printf("************* New AST for %s *****\n", (char*)fun->header.a_name);
+ slang_print_function(fun, 1);
+#endif
+#if 0
+ printf("************* IR for %s *******\n", (char*)fun->header.a_name);
+ _slang_print_ir_tree(n, 0);
+#endif
+#if 0
+ printf("************* End codegen function ************\n\n");
+#endif
+
+ if (A->UnresolvedRefs) {
+ /* Can't codegen at this time.
+ * At link time we'll concatenate all the vertex shaders and/or all
+ * the fragment shaders and try recompiling.
+ */
+ return GL_TRUE;
+ }
+
+ /* Emit program instructions */
+ success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);
+ _slang_free_ir_tree(n);
+
+ /* free codegen context */
+ /*
+ _mesa_free(A->codegen);
+ */
+
+ return success;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_codegen.h b/mesalib/src/mesa/shader/slang/slang_codegen.h
new file mode 100644
index 000000000..ee3be55a4
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_codegen.h
@@ -0,0 +1,72 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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 SLANG_CODEGEN_H
+#define SLANG_CODEGEN_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+
+
+#define MAX_LOOP_DEPTH 30
+
+
+typedef struct slang_assemble_ctx_
+{
+ slang_atom_pool *atoms;
+ slang_name_space space;
+ struct gl_program *program;
+ struct gl_sl_pragmas *pragmas;
+ slang_var_table *vartable;
+ slang_info_log *log;
+
+ /* current loop stack */
+ const slang_operation *LoopOperStack[MAX_LOOP_DEPTH];
+ struct slang_ir_node_ *LoopIRStack[MAX_LOOP_DEPTH];
+ GLuint LoopDepth;
+
+ /* current function */
+ struct slang_function_ *CurFunction;
+ struct slang_label_ *curFuncEndLabel;
+ GLboolean UseReturnFlag;
+
+ GLboolean UnresolvedRefs;
+ GLboolean EmitContReturn;
+} slang_assemble_ctx;
+
+
+extern GLuint
+_slang_sizeof_type_specifier(const slang_type_specifier *spec);
+
+extern GLboolean
+_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
+
+extern GLboolean
+_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
+ slang_unit_type type);
+
+
+#endif /* SLANG_CODEGEN_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_compile.c b/mesalib/src/mesa/shader/slang/slang_compile.c
new file mode 100644
index 000000000..c1b97c7cb
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile.c
@@ -0,0 +1,2825 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_compile.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+#include "shader/prog_optimize.h"
+#include "shader/prog_print.h"
+#include "shader/prog_parameter.h"
+#include "shader/grammar/grammar_mesa.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_preprocess.h"
+#include "slang_storage.h"
+#include "slang_emit.h"
+#include "slang_log.h"
+#include "slang_mem.h"
+#include "slang_vartable.h"
+#include "slang_simplify.h"
+
+#include "slang_print.h"
+
+/*
+ * This is a straightforward implementation of the slang front-end
+ * compiler. Lots of error-checking functionality is missing but
+ * every well-formed shader source should compile successfully and
+ * execute as expected. However, some semantically ill-formed shaders
+ * may be accepted resulting in undefined behaviour.
+ */
+
+
+/** re-defined below, should be the same though */
+#define TYPE_SPECIFIER_COUNT 32
+
+
+/**
+ * Check if the given identifier is legal.
+ */
+static GLboolean
+legal_identifier(slang_atom name)
+{
+ /* "gl_" is a reserved prefix */
+ if (_mesa_strncmp((char *) name, "gl_", 3) == 0) {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
+/*
+ * slang_code_unit
+ */
+
+GLvoid
+_slang_code_unit_ctr(slang_code_unit * self,
+ struct slang_code_object_ * object)
+{
+ _slang_variable_scope_ctr(&self->vars);
+ _slang_function_scope_ctr(&self->funs);
+ _slang_struct_scope_ctr(&self->structs);
+ self->object = object;
+}
+
+GLvoid
+_slang_code_unit_dtr(slang_code_unit * self)
+{
+ slang_variable_scope_destruct(&self->vars);
+ slang_function_scope_destruct(&self->funs);
+ slang_struct_scope_destruct(&self->structs);
+}
+
+/*
+ * slang_code_object
+ */
+
+GLvoid
+_slang_code_object_ctr(slang_code_object * self)
+{
+ GLuint i;
+
+ for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
+ _slang_code_unit_ctr(&self->builtin[i], self);
+ _slang_code_unit_ctr(&self->unit, self);
+ slang_atom_pool_construct(&self->atompool);
+}
+
+GLvoid
+_slang_code_object_dtr(slang_code_object * self)
+{
+ GLuint i;
+
+ for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
+ _slang_code_unit_dtr(&self->builtin[i]);
+ _slang_code_unit_dtr(&self->unit);
+ slang_atom_pool_destruct(&self->atompool);
+}
+
+
+/* slang_parse_ctx */
+
+typedef struct slang_parse_ctx_
+{
+ const byte *I;
+ slang_info_log *L;
+ int parsing_builtin;
+ GLboolean global_scope; /**< Is object being declared a global? */
+ slang_atom_pool *atoms;
+ slang_unit_type type; /**< Vertex vs. Fragment */
+ GLuint version; /**< user-specified (or default) #version */
+} slang_parse_ctx;
+
+/* slang_output_ctx */
+
+typedef struct slang_output_ctx_
+{
+ slang_variable_scope *vars;
+ slang_function_scope *funs;
+ slang_struct_scope *structs;
+ struct gl_program *program;
+ struct gl_sl_pragmas *pragmas;
+ slang_var_table *vartable;
+ GLuint default_precision[TYPE_SPECIFIER_COUNT];
+ GLboolean allow_precision;
+ GLboolean allow_invariant;
+ GLboolean allow_centroid;
+ GLboolean allow_array_types; /* float[] syntax */
+} slang_output_ctx;
+
+/* _slang_compile() */
+
+
+/* Debugging aid, print file/line where parsing error is detected */
+#define RETURN0 \
+ do { \
+ if (0) \
+ printf("slang error at %s:%d\n", __FILE__, __LINE__); \
+ return 0; \
+ } while (0)
+
+
+static void
+parse_identifier_str(slang_parse_ctx * C, char **id)
+{
+ *id = (char *) C->I;
+ C->I += _mesa_strlen(*id) + 1;
+}
+
+static slang_atom
+parse_identifier(slang_parse_ctx * C)
+{
+ const char *id;
+
+ id = (const char *) C->I;
+ C->I += _mesa_strlen(id) + 1;
+ return slang_atom_pool_atom(C->atoms, id);
+}
+
+static int
+parse_number(slang_parse_ctx * C, int *number)
+{
+ const int radix = (int) (*C->I++);
+ *number = 0;
+ while (*C->I != '\0') {
+ int digit;
+ if (*C->I >= '0' && *C->I <= '9')
+ digit = (int) (*C->I - '0');
+ else if (*C->I >= 'A' && *C->I <= 'Z')
+ digit = (int) (*C->I - 'A') + 10;
+ else
+ digit = (int) (*C->I - 'a') + 10;
+ *number = *number * radix + digit;
+ C->I++;
+ }
+ C->I++;
+ if (*number > 65535)
+ slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
+ return 1;
+}
+
+static int
+parse_float(slang_parse_ctx * C, float *number)
+{
+ char *integral = NULL;
+ char *fractional = NULL;
+ char *exponent = NULL;
+ char *whole = NULL;
+
+ parse_identifier_str(C, &integral);
+ parse_identifier_str(C, &fractional);
+ parse_identifier_str(C, &exponent);
+
+ whole = (char *) _slang_alloc((_mesa_strlen(integral) +
+ _mesa_strlen(fractional) +
+ _mesa_strlen(exponent) + 3) * sizeof(char));
+ if (whole == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+
+ slang_string_copy(whole, integral);
+ slang_string_concat(whole, ".");
+ slang_string_concat(whole, fractional);
+ slang_string_concat(whole, "E");
+ slang_string_concat(whole, exponent);
+
+ *number = (float) (_mesa_strtod(whole, (char **) NULL));
+
+ _slang_free(whole);
+
+ return 1;
+}
+
+/* revision number - increment after each change affecting emitted output */
+#define REVISION 5
+
+static int
+check_revision(slang_parse_ctx * C)
+{
+ if (*C->I != REVISION) {
+ slang_info_log_error(C->L, "Internal compiler error.");
+ RETURN0;
+ }
+ C->I++;
+ return 1;
+}
+
+static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
+ slang_operation *);
+static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
+ slang_operation *);
+static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
+ slang_type_specifier *);
+static int
+parse_type_array_size(slang_parse_ctx *C,
+ slang_output_ctx *O,
+ GLint *array_len);
+
+static GLboolean
+parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
+{
+ slang_operation array_size;
+ slang_name_space space;
+ GLboolean result;
+
+ if (!slang_operation_construct(&array_size))
+ return GL_FALSE;
+ if (!parse_expression(C, O, &array_size)) {
+ slang_operation_destruct(&array_size);
+ return GL_FALSE;
+ }
+
+ space.funcs = O->funs;
+ space.structs = O->structs;
+ space.vars = O->vars;
+
+ /* evaluate compile-time expression which is array size */
+ _slang_simplify(&array_size, &space, C->atoms);
+
+ if (array_size.type == SLANG_OPER_LITERAL_INT) {
+ result = GL_TRUE;
+ *len = (GLint) array_size.literal[0];
+ } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
+ slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
+ if (!var) {
+ slang_info_log_error(C->L, "undefined variable '%s'",
+ (char *) array_size.a_id);
+ result = GL_FALSE;
+ } else if (var->type.qualifier == SLANG_QUAL_CONST &&
+ var->type.specifier.type == SLANG_SPEC_INT) {
+ if (var->initializer &&
+ var->initializer->type == SLANG_OPER_LITERAL_INT) {
+ *len = (GLint) var->initializer->literal[0];
+ result = GL_TRUE;
+ } else {
+ slang_info_log_error(C->L, "unable to parse array size declaration");
+ result = GL_FALSE;
+ }
+ } else {
+ slang_info_log_error(C->L, "unable to parse array size declaration");
+ result = GL_FALSE;
+ }
+ } else {
+ result = GL_FALSE;
+ }
+
+ slang_operation_destruct(&array_size);
+ return result;
+}
+
+static GLboolean
+calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_variable * var)
+{
+ slang_storage_aggregate agg;
+
+ if (!slang_storage_aggregate_construct(&agg))
+ return GL_FALSE;
+ if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
+ O->funs, O->structs, O->vars, C->atoms)) {
+ slang_storage_aggregate_destruct(&agg);
+ return GL_FALSE;
+ }
+ var->size = _slang_sizeof_aggregate(&agg);
+ slang_storage_aggregate_destruct(&agg);
+ return GL_TRUE;
+}
+
+static void
+promote_type_to_array(slang_parse_ctx *C,
+ slang_fully_specified_type *type,
+ GLint array_len)
+{
+ slang_type_specifier *baseType =
+ slang_type_specifier_new(type->specifier.type, NULL, NULL);
+
+ type->specifier.type = SLANG_SPEC_ARRAY;
+ type->specifier._array = baseType;
+ type->array_len = array_len;
+}
+
+
+static GLboolean
+convert_to_array(slang_parse_ctx * C, slang_variable * var,
+ const slang_type_specifier * sp)
+{
+ /* sized array - mark it as array, copy the specifier to the array element
+ * and parse the expression */
+ var->type.specifier.type = SLANG_SPEC_ARRAY;
+ var->type.specifier._array = (slang_type_specifier *)
+ _slang_alloc(sizeof(slang_type_specifier));
+ if (var->type.specifier._array == NULL) {
+ slang_info_log_memory(C->L);
+ return GL_FALSE;
+ }
+ slang_type_specifier_ctr(var->type.specifier._array);
+ return slang_type_specifier_copy(var->type.specifier._array, sp);
+}
+
+/* structure field */
+#define FIELD_NONE 0
+#define FIELD_NEXT 1
+#define FIELD_ARRAY 2
+
+static GLboolean
+parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_variable * var, slang_atom a_name,
+ const slang_type_specifier * sp,
+ GLuint array_len)
+{
+ var->a_name = a_name;
+ if (var->a_name == SLANG_ATOM_NULL)
+ return GL_FALSE;
+
+ switch (*C->I++) {
+ case FIELD_NONE:
+ if (array_len != -1) {
+ if (!convert_to_array(C, var, sp))
+ return GL_FALSE;
+ var->array_len = array_len;
+ }
+ else {
+ if (!slang_type_specifier_copy(&var->type.specifier, sp))
+ return GL_FALSE;
+ }
+ break;
+ case FIELD_ARRAY:
+ if (array_len != -1)
+ return GL_FALSE;
+ if (!convert_to_array(C, var, sp))
+ return GL_FALSE;
+ if (!parse_array_len(C, O, &var->array_len))
+ return GL_FALSE;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ return calculate_var_size(C, O, var);
+}
+
+static int
+parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_struct * st, slang_type_specifier * sp)
+{
+ slang_output_ctx o = *O;
+ GLint array_len;
+
+ o.structs = st->structs;
+ if (!parse_type_specifier(C, &o, sp))
+ RETURN0;
+ if (!parse_type_array_size(C, &o, &array_len))
+ RETURN0;
+
+ do {
+ slang_atom a_name;
+ slang_variable *var = slang_variable_scope_grow(st->fields);
+ if (!var) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ a_name = parse_identifier(C);
+ if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
+ slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
+ RETURN0;
+ }
+
+ if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
+ RETURN0;
+ }
+ while (*C->I++ != FIELD_NONE);
+
+ return 1;
+}
+
+static int
+parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
+{
+ slang_atom a_name;
+ const char *name;
+
+ /* parse struct name (if any) and make sure it is unique in current scope */
+ a_name = parse_identifier(C);
+ if (a_name == SLANG_ATOM_NULL)
+ RETURN0;
+
+ name = slang_atom_pool_id(C->atoms, a_name);
+ if (name[0] != '\0'
+ && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
+ slang_info_log_error(C->L, "%s: duplicate type name.", name);
+ RETURN0;
+ }
+
+ /* set-up a new struct */
+ *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+ if (*st == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!slang_struct_construct(*st)) {
+ _slang_free(*st);
+ *st = NULL;
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ (**st).a_name = a_name;
+ (**st).structs->outer_scope = O->structs;
+
+ /* parse individual struct fields */
+ do {
+ slang_type_specifier sp;
+
+ slang_type_specifier_ctr(&sp);
+ if (!parse_struct_field(C, O, *st, &sp)) {
+ slang_type_specifier_dtr(&sp);
+ RETURN0;
+ }
+ slang_type_specifier_dtr(&sp);
+ }
+ while (*C->I++ != FIELD_NONE);
+
+ /* if named struct, copy it to current scope */
+ if (name[0] != '\0') {
+ slang_struct *s;
+
+ O->structs->structs =
+ (slang_struct *) _slang_realloc(O->structs->structs,
+ O->structs->num_structs
+ * sizeof(slang_struct),
+ (O->structs->num_structs + 1)
+ * sizeof(slang_struct));
+ if (O->structs->structs == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ s = &O->structs->structs[O->structs->num_structs];
+ if (!slang_struct_construct(s))
+ RETURN0;
+ O->structs->num_structs++;
+ if (!slang_struct_copy(s, *st))
+ RETURN0;
+ }
+
+ return 1;
+}
+
+
+/* invariant qualifer */
+#define TYPE_VARIANT 90
+#define TYPE_INVARIANT 91
+
+static int
+parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
+{
+ GLuint invariant = *C->I++;
+ switch (invariant) {
+ case TYPE_VARIANT:
+ *variant = SLANG_VARIANT;
+ return 1;
+ case TYPE_INVARIANT:
+ *variant = SLANG_INVARIANT;
+ return 1;
+ default:
+ RETURN0;
+ }
+}
+
+
+/* centroid qualifer */
+#define TYPE_CENTER 95
+#define TYPE_CENTROID 96
+
+static int
+parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
+{
+ GLuint c = *C->I++;
+ switch (c) {
+ case TYPE_CENTER:
+ *centroid = SLANG_CENTER;
+ return 1;
+ case TYPE_CENTROID:
+ *centroid = SLANG_CENTROID;
+ return 1;
+ default:
+ RETURN0;
+ }
+}
+
+
+/* type qualifier */
+#define TYPE_QUALIFIER_NONE 0
+#define TYPE_QUALIFIER_CONST 1
+#define TYPE_QUALIFIER_ATTRIBUTE 2
+#define TYPE_QUALIFIER_VARYING 3
+#define TYPE_QUALIFIER_UNIFORM 4
+#define TYPE_QUALIFIER_FIXEDOUTPUT 5
+#define TYPE_QUALIFIER_FIXEDINPUT 6
+
+static int
+parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
+{
+ GLuint qualifier = *C->I++;
+ switch (qualifier) {
+ case TYPE_QUALIFIER_NONE:
+ *qual = SLANG_QUAL_NONE;
+ break;
+ case TYPE_QUALIFIER_CONST:
+ *qual = SLANG_QUAL_CONST;
+ break;
+ case TYPE_QUALIFIER_ATTRIBUTE:
+ *qual = SLANG_QUAL_ATTRIBUTE;
+ break;
+ case TYPE_QUALIFIER_VARYING:
+ *qual = SLANG_QUAL_VARYING;
+ break;
+ case TYPE_QUALIFIER_UNIFORM:
+ *qual = SLANG_QUAL_UNIFORM;
+ break;
+ case TYPE_QUALIFIER_FIXEDOUTPUT:
+ *qual = SLANG_QUAL_FIXEDOUTPUT;
+ break;
+ case TYPE_QUALIFIER_FIXEDINPUT:
+ *qual = SLANG_QUAL_FIXEDINPUT;
+ break;
+ default:
+ RETURN0;
+ }
+ return 1;
+}
+
+/* type specifier */
+#define TYPE_SPECIFIER_VOID 0
+#define TYPE_SPECIFIER_BOOL 1
+#define TYPE_SPECIFIER_BVEC2 2
+#define TYPE_SPECIFIER_BVEC3 3
+#define TYPE_SPECIFIER_BVEC4 4
+#define TYPE_SPECIFIER_INT 5
+#define TYPE_SPECIFIER_IVEC2 6
+#define TYPE_SPECIFIER_IVEC3 7
+#define TYPE_SPECIFIER_IVEC4 8
+#define TYPE_SPECIFIER_FLOAT 9
+#define TYPE_SPECIFIER_VEC2 10
+#define TYPE_SPECIFIER_VEC3 11
+#define TYPE_SPECIFIER_VEC4 12
+#define TYPE_SPECIFIER_MAT2 13
+#define TYPE_SPECIFIER_MAT3 14
+#define TYPE_SPECIFIER_MAT4 15
+#define TYPE_SPECIFIER_SAMPLER1D 16
+#define TYPE_SPECIFIER_SAMPLER2D 17
+#define TYPE_SPECIFIER_SAMPLER3D 18
+#define TYPE_SPECIFIER_SAMPLERCUBE 19
+#define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
+#define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
+#define TYPE_SPECIFIER_SAMPLER2DRECT 22
+#define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
+#define TYPE_SPECIFIER_STRUCT 24
+#define TYPE_SPECIFIER_TYPENAME 25
+#define TYPE_SPECIFIER_MAT23 26
+#define TYPE_SPECIFIER_MAT32 27
+#define TYPE_SPECIFIER_MAT24 28
+#define TYPE_SPECIFIER_MAT42 29
+#define TYPE_SPECIFIER_MAT34 30
+#define TYPE_SPECIFIER_MAT43 31
+#define TYPE_SPECIFIER_COUNT 32
+
+static int
+parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_type_specifier * spec)
+{
+ switch (*C->I++) {
+ case TYPE_SPECIFIER_VOID:
+ spec->type = SLANG_SPEC_VOID;
+ break;
+ case TYPE_SPECIFIER_BOOL:
+ spec->type = SLANG_SPEC_BOOL;
+ break;
+ case TYPE_SPECIFIER_BVEC2:
+ spec->type = SLANG_SPEC_BVEC2;
+ break;
+ case TYPE_SPECIFIER_BVEC3:
+ spec->type = SLANG_SPEC_BVEC3;
+ break;
+ case TYPE_SPECIFIER_BVEC4:
+ spec->type = SLANG_SPEC_BVEC4;
+ break;
+ case TYPE_SPECIFIER_INT:
+ spec->type = SLANG_SPEC_INT;
+ break;
+ case TYPE_SPECIFIER_IVEC2:
+ spec->type = SLANG_SPEC_IVEC2;
+ break;
+ case TYPE_SPECIFIER_IVEC3:
+ spec->type = SLANG_SPEC_IVEC3;
+ break;
+ case TYPE_SPECIFIER_IVEC4:
+ spec->type = SLANG_SPEC_IVEC4;
+ break;
+ case TYPE_SPECIFIER_FLOAT:
+ spec->type = SLANG_SPEC_FLOAT;
+ break;
+ case TYPE_SPECIFIER_VEC2:
+ spec->type = SLANG_SPEC_VEC2;
+ break;
+ case TYPE_SPECIFIER_VEC3:
+ spec->type = SLANG_SPEC_VEC3;
+ break;
+ case TYPE_SPECIFIER_VEC4:
+ spec->type = SLANG_SPEC_VEC4;
+ break;
+ case TYPE_SPECIFIER_MAT2:
+ spec->type = SLANG_SPEC_MAT2;
+ break;
+ case TYPE_SPECIFIER_MAT3:
+ spec->type = SLANG_SPEC_MAT3;
+ break;
+ case TYPE_SPECIFIER_MAT4:
+ spec->type = SLANG_SPEC_MAT4;
+ break;
+ case TYPE_SPECIFIER_MAT23:
+ spec->type = SLANG_SPEC_MAT23;
+ break;
+ case TYPE_SPECIFIER_MAT32:
+ spec->type = SLANG_SPEC_MAT32;
+ break;
+ case TYPE_SPECIFIER_MAT24:
+ spec->type = SLANG_SPEC_MAT24;
+ break;
+ case TYPE_SPECIFIER_MAT42:
+ spec->type = SLANG_SPEC_MAT42;
+ break;
+ case TYPE_SPECIFIER_MAT34:
+ spec->type = SLANG_SPEC_MAT34;
+ break;
+ case TYPE_SPECIFIER_MAT43:
+ spec->type = SLANG_SPEC_MAT43;
+ break;
+ case TYPE_SPECIFIER_SAMPLER1D:
+ spec->type = SLANG_SPEC_SAMPLER1D;
+ break;
+ case TYPE_SPECIFIER_SAMPLER2D:
+ spec->type = SLANG_SPEC_SAMPLER2D;
+ break;
+ case TYPE_SPECIFIER_SAMPLER3D:
+ spec->type = SLANG_SPEC_SAMPLER3D;
+ break;
+ case TYPE_SPECIFIER_SAMPLERCUBE:
+ spec->type = SLANG_SPEC_SAMPLERCUBE;
+ break;
+ case TYPE_SPECIFIER_SAMPLER2DRECT:
+ spec->type = SLANG_SPEC_SAMPLER2DRECT;
+ break;
+ case TYPE_SPECIFIER_SAMPLER1DSHADOW:
+ spec->type = SLANG_SPEC_SAMPLER1DSHADOW;
+ break;
+ case TYPE_SPECIFIER_SAMPLER2DSHADOW:
+ spec->type = SLANG_SPEC_SAMPLER2DSHADOW;
+ break;
+ case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
+ spec->type = SLANG_SPEC_SAMPLER2DRECTSHADOW;
+ break;
+ case TYPE_SPECIFIER_STRUCT:
+ spec->type = SLANG_SPEC_STRUCT;
+ if (!parse_struct(C, O, &spec->_struct))
+ RETURN0;
+ break;
+ case TYPE_SPECIFIER_TYPENAME:
+ spec->type = SLANG_SPEC_STRUCT;
+ {
+ slang_atom a_name;
+ slang_struct *stru;
+
+ a_name = parse_identifier(C);
+ if (a_name == NULL)
+ RETURN0;
+
+ stru = slang_struct_scope_find(O->structs, a_name, 1);
+ if (stru == NULL) {
+ slang_info_log_error(C->L, "undeclared type name '%s'",
+ slang_atom_pool_id(C->atoms, a_name));
+ RETURN0;
+ }
+
+ spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+ if (spec->_struct == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!slang_struct_construct(spec->_struct)) {
+ _slang_free(spec->_struct);
+ spec->_struct = NULL;
+ RETURN0;
+ }
+ if (!slang_struct_copy(spec->_struct, stru))
+ RETURN0;
+ }
+ break;
+ default:
+ RETURN0;
+ }
+ return 1;
+}
+
+#define TYPE_SPECIFIER_NONARRAY 0
+#define TYPE_SPECIFIER_ARRAY 1
+
+static int
+parse_type_array_size(slang_parse_ctx *C,
+ slang_output_ctx *O,
+ GLint *array_len)
+{
+ GLuint size;
+
+ switch (*C->I++) {
+ case TYPE_SPECIFIER_NONARRAY:
+ *array_len = -1; /* -1 = not an array */
+ break;
+ case TYPE_SPECIFIER_ARRAY:
+ if (!parse_array_len(C, O, &size))
+ RETURN0;
+ *array_len = (GLint) size;
+ break;
+ default:
+ assert(0);
+ RETURN0;
+ }
+ return 1;
+}
+
+#define PRECISION_DEFAULT 0
+#define PRECISION_LOW 1
+#define PRECISION_MEDIUM 2
+#define PRECISION_HIGH 3
+
+static int
+parse_type_precision(slang_parse_ctx *C,
+ slang_type_precision *precision)
+{
+ GLint prec = *C->I++;
+ switch (prec) {
+ case PRECISION_DEFAULT:
+ *precision = SLANG_PREC_DEFAULT;
+ return 1;
+ case PRECISION_LOW:
+ *precision = SLANG_PREC_LOW;
+ return 1;
+ case PRECISION_MEDIUM:
+ *precision = SLANG_PREC_MEDIUM;
+ return 1;
+ case PRECISION_HIGH:
+ *precision = SLANG_PREC_HIGH;
+ return 1;
+ default:
+ RETURN0;
+ }
+}
+
+static int
+parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_fully_specified_type * type)
+{
+ if (!parse_type_variant(C, &type->variant))
+ RETURN0;
+
+ if (!parse_type_centroid(C, &type->centroid))
+ RETURN0;
+
+ if (!parse_type_qualifier(C, &type->qualifier))
+ RETURN0;
+
+ if (!parse_type_precision(C, &type->precision))
+ RETURN0;
+
+ if (!parse_type_specifier(C, O, &type->specifier))
+ RETURN0;
+
+ if (!parse_type_array_size(C, O, &type->array_len))
+ RETURN0;
+
+ if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
+ slang_info_log_error(C->L,
+ "'invariant' keyword not allowed (perhaps set #version 120)");
+ RETURN0;
+ }
+
+ if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
+ slang_info_log_error(C->L,
+ "'centroid' keyword not allowed (perhaps set #version 120)");
+ RETURN0;
+ }
+ else if (type->centroid == SLANG_CENTROID &&
+ type->qualifier != SLANG_QUAL_VARYING) {
+ slang_info_log_error(C->L,
+ "'centroid' keyword only allowed for varying vars");
+ RETURN0;
+ }
+
+
+ /* need this?
+ if (type->qualifier != SLANG_QUAL_VARYING &&
+ type->variant == SLANG_INVARIANT) {
+ slang_info_log_error(C->L,
+ "invariant qualifer only allowed for varying vars");
+ RETURN0;
+ }
+ */
+
+ if (O->allow_precision) {
+ if (type->precision == SLANG_PREC_DEFAULT) {
+ assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
+ /* use the default precision for this datatype */
+ type->precision = O->default_precision[type->specifier.type];
+ }
+ }
+ else {
+ /* only default is allowed */
+ if (type->precision != SLANG_PREC_DEFAULT) {
+ slang_info_log_error(C->L, "precision qualifiers not allowed");
+ RETURN0;
+ }
+ }
+
+ if (!O->allow_array_types && type->array_len >= 0) {
+ slang_info_log_error(C->L, "first-class array types not allowed");
+ RETURN0;
+ }
+
+ if (type->array_len >= 0) {
+ /* convert type to array type (ex: convert "int" to "array of int" */
+ promote_type_to_array(C, type, type->array_len);
+ }
+
+ return 1;
+}
+
+/* operation */
+#define OP_END 0
+#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+#define OP_BLOCK_BEGIN_NEW_SCOPE 2
+#define OP_DECLARE 3
+#define OP_ASM 4
+#define OP_BREAK 5
+#define OP_CONTINUE 6
+#define OP_DISCARD 7
+#define OP_RETURN 8
+#define OP_EXPRESSION 9
+#define OP_IF 10
+#define OP_WHILE 11
+#define OP_DO 12
+#define OP_FOR 13
+#define OP_PUSH_VOID 14
+#define OP_PUSH_BOOL 15
+#define OP_PUSH_INT 16
+#define OP_PUSH_FLOAT 17
+#define OP_PUSH_IDENTIFIER 18
+#define OP_SEQUENCE 19
+#define OP_ASSIGN 20
+#define OP_ADDASSIGN 21
+#define OP_SUBASSIGN 22
+#define OP_MULASSIGN 23
+#define OP_DIVASSIGN 24
+/*#define OP_MODASSIGN 25*/
+/*#define OP_LSHASSIGN 26*/
+/*#define OP_RSHASSIGN 27*/
+/*#define OP_ORASSIGN 28*/
+/*#define OP_XORASSIGN 29*/
+/*#define OP_ANDASSIGN 30*/
+#define OP_SELECT 31
+#define OP_LOGICALOR 32
+#define OP_LOGICALXOR 33
+#define OP_LOGICALAND 34
+/*#define OP_BITOR 35*/
+/*#define OP_BITXOR 36*/
+/*#define OP_BITAND 37*/
+#define OP_EQUAL 38
+#define OP_NOTEQUAL 39
+#define OP_LESS 40
+#define OP_GREATER 41
+#define OP_LESSEQUAL 42
+#define OP_GREATEREQUAL 43
+/*#define OP_LSHIFT 44*/
+/*#define OP_RSHIFT 45*/
+#define OP_ADD 46
+#define OP_SUBTRACT 47
+#define OP_MULTIPLY 48
+#define OP_DIVIDE 49
+/*#define OP_MODULUS 50*/
+#define OP_PREINCREMENT 51
+#define OP_PREDECREMENT 52
+#define OP_PLUS 53
+#define OP_MINUS 54
+/*#define OP_COMPLEMENT 55*/
+#define OP_NOT 56
+#define OP_SUBSCRIPT 57
+#define OP_CALL 58
+#define OP_FIELD 59
+#define OP_POSTINCREMENT 60
+#define OP_POSTDECREMENT 61
+#define OP_PRECISION 62
+#define OP_METHOD 63
+
+
+/**
+ * When parsing a compound production, this function is used to parse the
+ * children.
+ * For example, a while-loop compound will have two children, the
+ * while condition expression and the loop body. So, this function will
+ * be called twice to parse those two sub-expressions.
+ * \param C the parsing context
+ * \param O the output context
+ * \param oper the operation we're parsing
+ * \param statement indicates whether parsing a statement, or expression
+ * \return 1 if success, 0 if error
+ */
+static int
+parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_operation * oper, GLboolean statement)
+{
+ slang_operation *ch;
+
+ /* grow child array */
+ ch = slang_operation_grow(&oper->num_children, &oper->children);
+ if (statement)
+ return parse_statement(C, O, ch);
+ return parse_expression(C, O, ch);
+}
+
+static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
+
+static int
+parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_operation * oper)
+{
+ int op;
+
+ oper->locals->outer_scope = O->vars;
+
+ op = *C->I++;
+ switch (op) {
+ case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
+ /* parse child statements, do not create new variable scope */
+ oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ while (*C->I != OP_END)
+ if (!parse_child_operation(C, O, oper, GL_TRUE))
+ RETURN0;
+ C->I++;
+ break;
+ case OP_BLOCK_BEGIN_NEW_SCOPE:
+ /* parse child statements, create new variable scope */
+ {
+ slang_output_ctx o = *O;
+
+ oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+ o.vars = oper->locals;
+ while (*C->I != OP_END)
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ C->I++;
+ }
+ break;
+ case OP_DECLARE:
+ /* local variable declaration, individual declarators are stored as
+ * children identifiers
+ */
+ oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ {
+ const unsigned int first_var = O->vars->num_variables;
+
+ /* parse the declaration, note that there can be zero or more
+ * than one declarators
+ */
+ if (!parse_declaration(C, O))
+ RETURN0;
+ if (first_var < O->vars->num_variables) {
+ const unsigned int num_vars = O->vars->num_variables - first_var;
+ unsigned int i;
+ assert(oper->num_children == 0);
+ oper->num_children = num_vars;
+ oper->children = slang_operation_new(num_vars);
+ if (oper->children == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ for (i = first_var; i < O->vars->num_variables; i++) {
+ slang_operation *o = &oper->children[i - first_var];
+ slang_variable *var = O->vars->variables[i];
+ o->type = SLANG_OPER_VARIABLE_DECL;
+ o->locals->outer_scope = O->vars;
+ o->a_id = var->a_name;
+
+ /* new/someday...
+ calculate_var_size(C, O, var);
+ */
+
+ if (!legal_identifier(o->a_id)) {
+ slang_info_log_error(C->L, "illegal variable name '%s'",
+ (char *) o->a_id);
+ RETURN0;
+ }
+ }
+ }
+ }
+ break;
+ case OP_ASM:
+ /* the __asm statement, parse the mnemonic and all its arguments
+ * as expressions
+ */
+ oper->type = SLANG_OPER_ASM;
+ oper->a_id = parse_identifier(C);
+ if (oper->a_id == SLANG_ATOM_NULL)
+ RETURN0;
+ while (*C->I != OP_END) {
+ if (!parse_child_operation(C, O, oper, GL_FALSE))
+ RETURN0;
+ }
+ C->I++;
+ break;
+ case OP_BREAK:
+ oper->type = SLANG_OPER_BREAK;
+ break;
+ case OP_CONTINUE:
+ oper->type = SLANG_OPER_CONTINUE;
+ break;
+ case OP_DISCARD:
+ oper->type = SLANG_OPER_DISCARD;
+ break;
+ case OP_RETURN:
+ oper->type = SLANG_OPER_RETURN;
+ if (!parse_child_operation(C, O, oper, GL_FALSE))
+ RETURN0;
+ break;
+ case OP_EXPRESSION:
+ oper->type = SLANG_OPER_EXPRESSION;
+ if (!parse_child_operation(C, O, oper, GL_FALSE))
+ RETURN0;
+ break;
+ case OP_IF:
+ oper->type = SLANG_OPER_IF;
+ if (!parse_child_operation(C, O, oper, GL_FALSE))
+ RETURN0;
+ if (!parse_child_operation(C, O, oper, GL_TRUE))
+ RETURN0;
+ if (!parse_child_operation(C, O, oper, GL_TRUE))
+ RETURN0;
+ break;
+ case OP_WHILE:
+ {
+ slang_output_ctx o = *O;
+
+ oper->type = SLANG_OPER_WHILE;
+ o.vars = oper->locals;
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ }
+ break;
+ case OP_DO:
+ oper->type = SLANG_OPER_DO;
+ if (!parse_child_operation(C, O, oper, GL_TRUE))
+ RETURN0;
+ if (!parse_child_operation(C, O, oper, GL_FALSE))
+ RETURN0;
+ break;
+ case OP_FOR:
+ {
+ slang_output_ctx o = *O;
+
+ oper->type = SLANG_OPER_FOR;
+ o.vars = oper->locals;
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ if (!parse_child_operation(C, &o, oper, GL_FALSE))
+ RETURN0;
+ if (!parse_child_operation(C, &o, oper, GL_TRUE))
+ RETURN0;
+ }
+ break;
+ case OP_PRECISION:
+ {
+ /* set default precision for a type in this scope */
+ /* ignored at this time */
+ int prec_qual = *C->I++;
+ int datatype = *C->I++;
+ (void) prec_qual;
+ (void) datatype;
+ }
+ break;
+ default:
+ /*printf("Unexpected operation %d\n", op);*/
+ RETURN0;
+ }
+ return 1;
+}
+
+static int
+handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
+ slang_operation ** ops, unsigned int *total_ops,
+ unsigned int n)
+{
+ unsigned int i;
+
+ op->children = slang_operation_new(n);
+ if (op->children == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ op->num_children = n;
+
+ for (i = 0; i < n; i++) {
+ slang_operation_destruct(&op->children[i]);
+ op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
+ }
+
+ (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
+ *total_ops -= n;
+
+ *ops = (slang_operation *)
+ _slang_realloc(*ops,
+ (*total_ops + n) * sizeof(slang_operation),
+ *total_ops * sizeof(slang_operation));
+ if (*ops == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ return 1;
+}
+
+static int
+is_constructor_name(const char *name, slang_atom a_name,
+ slang_struct_scope * structs)
+{
+ if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
+ return 1;
+ return slang_struct_scope_find(structs, a_name, 1) != NULL;
+}
+
+#define FUNCTION_CALL_NONARRAY 0
+#define FUNCTION_CALL_ARRAY 1
+
+static int
+parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_operation * oper)
+{
+ slang_operation *ops = NULL;
+ unsigned int num_ops = 0;
+ int number;
+
+ while (*C->I != OP_END) {
+ slang_operation *op;
+ const unsigned int op_code = *C->I++;
+
+ /* allocate default operation, becomes a no-op if not used */
+ ops = (slang_operation *)
+ _slang_realloc(ops,
+ num_ops * sizeof(slang_operation),
+ (num_ops + 1) * sizeof(slang_operation));
+ if (ops == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ op = &ops[num_ops];
+ if (!slang_operation_construct(op)) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ num_ops++;
+ op->locals->outer_scope = O->vars;
+
+ switch (op_code) {
+ case OP_PUSH_VOID:
+ op->type = SLANG_OPER_VOID;
+ break;
+ case OP_PUSH_BOOL:
+ op->type = SLANG_OPER_LITERAL_BOOL;
+ if (!parse_number(C, &number))
+ RETURN0;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
+ op->literal_size = 1;
+ break;
+ case OP_PUSH_INT:
+ op->type = SLANG_OPER_LITERAL_INT;
+ if (!parse_number(C, &number))
+ RETURN0;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
+ op->literal_size = 1;
+ break;
+ case OP_PUSH_FLOAT:
+ op->type = SLANG_OPER_LITERAL_FLOAT;
+ if (!parse_float(C, &op->literal[0]))
+ RETURN0;
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = op->literal[0];
+ op->literal_size = 1;
+ break;
+ case OP_PUSH_IDENTIFIER:
+ op->type = SLANG_OPER_IDENTIFIER;
+ op->a_id = parse_identifier(C);
+ if (op->a_id == SLANG_ATOM_NULL)
+ RETURN0;
+ break;
+ case OP_SEQUENCE:
+ op->type = SLANG_OPER_SEQUENCE;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_ASSIGN:
+ op->type = SLANG_OPER_ASSIGN;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_ADDASSIGN:
+ op->type = SLANG_OPER_ADDASSIGN;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_SUBASSIGN:
+ op->type = SLANG_OPER_SUBASSIGN;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_MULASSIGN:
+ op->type = SLANG_OPER_MULASSIGN;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_DIVASSIGN:
+ op->type = SLANG_OPER_DIVASSIGN;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ /*case OP_MODASSIGN: */
+ /*case OP_LSHASSIGN: */
+ /*case OP_RSHASSIGN: */
+ /*case OP_ORASSIGN: */
+ /*case OP_XORASSIGN: */
+ /*case OP_ANDASSIGN: */
+ case OP_SELECT:
+ op->type = SLANG_OPER_SELECT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
+ RETURN0;
+ break;
+ case OP_LOGICALOR:
+ op->type = SLANG_OPER_LOGICALOR;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_LOGICALXOR:
+ op->type = SLANG_OPER_LOGICALXOR;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_LOGICALAND:
+ op->type = SLANG_OPER_LOGICALAND;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ /*case OP_BITOR: */
+ /*case OP_BITXOR: */
+ /*case OP_BITAND: */
+ case OP_EQUAL:
+ op->type = SLANG_OPER_EQUAL;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_NOTEQUAL:
+ op->type = SLANG_OPER_NOTEQUAL;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_LESS:
+ op->type = SLANG_OPER_LESS;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_GREATER:
+ op->type = SLANG_OPER_GREATER;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_LESSEQUAL:
+ op->type = SLANG_OPER_LESSEQUAL;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_GREATEREQUAL:
+ op->type = SLANG_OPER_GREATEREQUAL;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ /*case OP_LSHIFT: */
+ /*case OP_RSHIFT: */
+ case OP_ADD:
+ op->type = SLANG_OPER_ADD;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_SUBTRACT:
+ op->type = SLANG_OPER_SUBTRACT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_MULTIPLY:
+ op->type = SLANG_OPER_MULTIPLY;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_DIVIDE:
+ op->type = SLANG_OPER_DIVIDE;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ /*case OP_MODULUS: */
+ case OP_PREINCREMENT:
+ op->type = SLANG_OPER_PREINCREMENT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_PREDECREMENT:
+ op->type = SLANG_OPER_PREDECREMENT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_PLUS:
+ op->type = SLANG_OPER_PLUS;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_MINUS:
+ op->type = SLANG_OPER_MINUS;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_NOT:
+ op->type = SLANG_OPER_NOT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ /*case OP_COMPLEMENT: */
+ case OP_SUBSCRIPT:
+ op->type = SLANG_OPER_SUBSCRIPT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
+ RETURN0;
+ break;
+ case OP_METHOD:
+ op->type = SLANG_OPER_METHOD;
+ op->a_obj = parse_identifier(C);
+ if (op->a_obj == SLANG_ATOM_NULL)
+ RETURN0;
+
+ op->a_id = parse_identifier(C);
+ if (op->a_id == SLANG_ATOM_NULL)
+ RETURN0;
+
+ assert(*C->I == OP_END);
+ C->I++;
+
+ while (*C->I != OP_END)
+ if (!parse_child_operation(C, O, op, GL_FALSE))
+ RETURN0;
+ C->I++;
+#if 0
+ /* don't lookup the method (not yet anyway) */
+ if (!C->parsing_builtin
+ && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
+ const char *id;
+
+ id = slang_atom_pool_id(C->atoms, op->a_id);
+ if (!is_constructor_name(id, op->a_id, O->structs)) {
+ slang_info_log_error(C->L, "%s: undeclared function name.", id);
+ RETURN0;
+ }
+ }
+#endif
+ break;
+ case OP_CALL:
+ {
+ GLboolean array_constructor = GL_FALSE;
+ GLint array_constructor_size = 0;
+
+ op->type = SLANG_OPER_CALL;
+ op->a_id = parse_identifier(C);
+ if (op->a_id == SLANG_ATOM_NULL)
+ RETURN0;
+ switch (*C->I++) {
+ case FUNCTION_CALL_NONARRAY:
+ /* Nothing to do. */
+ break;
+ case FUNCTION_CALL_ARRAY:
+ /* Calling an array constructor. For example:
+ * float[3](1.1, 2.2, 3.3);
+ */
+ if (!O->allow_array_types) {
+ slang_info_log_error(C->L,
+ "array constructors not allowed "
+ "in this GLSL version");
+ RETURN0;
+ }
+ else {
+ /* parse the array constructor size */
+ slang_operation array_size;
+ array_constructor = GL_TRUE;
+ slang_operation_construct(&array_size);
+ if (!parse_expression(C, O, &array_size)) {
+ slang_operation_destruct(&array_size);
+ return GL_FALSE;
+ }
+ if (array_size.type != SLANG_OPER_LITERAL_INT) {
+ slang_info_log_error(C->L,
+ "constructor array size is not an integer");
+ slang_operation_destruct(&array_size);
+ RETURN0;
+ }
+ array_constructor_size = (int) array_size.literal[0];
+ op->array_constructor = GL_TRUE;
+ slang_operation_destruct(&array_size);
+ }
+ break;
+ default:
+ assert(0);
+ RETURN0;
+ }
+ while (*C->I != OP_END)
+ if (!parse_child_operation(C, O, op, GL_FALSE))
+ RETURN0;
+ C->I++;
+
+ if (array_constructor &&
+ array_constructor_size != op->num_children) {
+ slang_info_log_error(C->L, "number of parameters to array"
+ " constructor does not match array size");
+ RETURN0;
+ }
+
+ if (!C->parsing_builtin
+ && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
+ const char *id;
+
+ id = slang_atom_pool_id(C->atoms, op->a_id);
+ if (!is_constructor_name(id, op->a_id, O->structs)) {
+ slang_info_log_error(C->L, "%s: undeclared function name.", id);
+ RETURN0;
+ }
+ }
+ }
+ break;
+ case OP_FIELD:
+ op->type = SLANG_OPER_FIELD;
+ op->a_id = parse_identifier(C);
+ if (op->a_id == SLANG_ATOM_NULL)
+ RETURN0;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_POSTINCREMENT:
+ op->type = SLANG_OPER_POSTINCREMENT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ case OP_POSTDECREMENT:
+ op->type = SLANG_OPER_POSTDECREMENT;
+ if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
+ RETURN0;
+ break;
+ default:
+ RETURN0;
+ }
+ }
+ C->I++;
+
+ slang_operation_destruct(oper);
+ *oper = *ops; /* struct copy */
+ _slang_free(ops);
+
+ return 1;
+}
+
+/* parameter qualifier */
+#define PARAM_QUALIFIER_IN 0
+#define PARAM_QUALIFIER_OUT 1
+#define PARAM_QUALIFIER_INOUT 2
+
+/* function parameter array presence */
+#define PARAMETER_ARRAY_NOT_PRESENT 0
+#define PARAMETER_ARRAY_PRESENT 1
+
+static int
+parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_variable * param)
+{
+ int param_qual, precision_qual;
+
+ /* parse and validate the parameter's type qualifiers (there can be
+ * two at most) because not all combinations are valid
+ */
+ if (!parse_type_qualifier(C, &param->type.qualifier))
+ RETURN0;
+
+ param_qual = *C->I++;
+ switch (param_qual) {
+ case PARAM_QUALIFIER_IN:
+ if (param->type.qualifier != SLANG_QUAL_CONST
+ && param->type.qualifier != SLANG_QUAL_NONE) {
+ slang_info_log_error(C->L, "Invalid type qualifier.");
+ RETURN0;
+ }
+ break;
+ case PARAM_QUALIFIER_OUT:
+ if (param->type.qualifier == SLANG_QUAL_NONE)
+ param->type.qualifier = SLANG_QUAL_OUT;
+ else {
+ slang_info_log_error(C->L, "Invalid type qualifier.");
+ RETURN0;
+ }
+ break;
+ case PARAM_QUALIFIER_INOUT:
+ if (param->type.qualifier == SLANG_QUAL_NONE)
+ param->type.qualifier = SLANG_QUAL_INOUT;
+ else {
+ slang_info_log_error(C->L, "Invalid type qualifier.");
+ RETURN0;
+ }
+ break;
+ default:
+ RETURN0;
+ }
+
+ /* parse precision qualifier (lowp, mediump, highp */
+ precision_qual = *C->I++;
+ /* ignored at this time */
+ (void) precision_qual;
+
+ /* parse parameter's type specifier and name */
+ if (!parse_type_specifier(C, O, &param->type.specifier))
+ RETURN0;
+ if (!parse_type_array_size(C, O, &param->type.array_len))
+ RETURN0;
+ param->a_name = parse_identifier(C);
+ if (param->a_name == SLANG_ATOM_NULL)
+ RETURN0;
+
+ /* first-class array
+ */
+ if (param->type.array_len >= 0) {
+ slang_type_specifier p;
+
+ slang_type_specifier_ctr(&p);
+ if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
+ slang_type_specifier_dtr(&p);
+ RETURN0;
+ }
+ if (!convert_to_array(C, param, &p)) {
+ slang_type_specifier_dtr(&p);
+ RETURN0;
+ }
+ slang_type_specifier_dtr(&p);
+ param->array_len = param->type.array_len;
+ }
+
+ /* if the parameter is an array, parse its size (the size must be
+ * explicitly defined
+ */
+ if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
+ slang_type_specifier p;
+
+ if (param->type.array_len >= 0) {
+ slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+ RETURN0;
+ }
+ slang_type_specifier_ctr(&p);
+ if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
+ slang_type_specifier_dtr(&p);
+ RETURN0;
+ }
+ if (!convert_to_array(C, param, &p)) {
+ slang_type_specifier_dtr(&p);
+ RETURN0;
+ }
+ slang_type_specifier_dtr(&p);
+ if (!parse_array_len(C, O, &param->array_len))
+ RETURN0;
+ }
+
+#if 0
+ /* calculate the parameter size */
+ if (!calculate_var_size(C, O, param))
+ RETURN0;
+#endif
+ /* TODO: allocate the local address here? */
+ return 1;
+}
+
+/* function type */
+#define FUNCTION_ORDINARY 0
+#define FUNCTION_CONSTRUCTOR 1
+#define FUNCTION_OPERATOR 2
+
+/* function parameter */
+#define PARAMETER_NONE 0
+#define PARAMETER_NEXT 1
+
+/* operator type */
+#define OPERATOR_ADDASSIGN 1
+#define OPERATOR_SUBASSIGN 2
+#define OPERATOR_MULASSIGN 3
+#define OPERATOR_DIVASSIGN 4
+/*#define OPERATOR_MODASSIGN 5*/
+/*#define OPERATOR_LSHASSIGN 6*/
+/*#define OPERATOR_RSHASSIGN 7*/
+/*#define OPERATOR_ANDASSIGN 8*/
+/*#define OPERATOR_XORASSIGN 9*/
+/*#define OPERATOR_ORASSIGN 10*/
+#define OPERATOR_LOGICALXOR 11
+/*#define OPERATOR_BITOR 12*/
+/*#define OPERATOR_BITXOR 13*/
+/*#define OPERATOR_BITAND 14*/
+#define OPERATOR_LESS 15
+#define OPERATOR_GREATER 16
+#define OPERATOR_LESSEQUAL 17
+#define OPERATOR_GREATEREQUAL 18
+/*#define OPERATOR_LSHIFT 19*/
+/*#define OPERATOR_RSHIFT 20*/
+#define OPERATOR_MULTIPLY 21
+#define OPERATOR_DIVIDE 22
+/*#define OPERATOR_MODULUS 23*/
+#define OPERATOR_INCREMENT 24
+#define OPERATOR_DECREMENT 25
+#define OPERATOR_PLUS 26
+#define OPERATOR_MINUS 27
+/*#define OPERATOR_COMPLEMENT 28*/
+#define OPERATOR_NOT 29
+
+static const struct
+{
+ unsigned int o_code;
+ const char *o_name;
+} operator_names[] = {
+ {OPERATOR_INCREMENT, "++"},
+ {OPERATOR_ADDASSIGN, "+="},
+ {OPERATOR_PLUS, "+"},
+ {OPERATOR_DECREMENT, "--"},
+ {OPERATOR_SUBASSIGN, "-="},
+ {OPERATOR_MINUS, "-"},
+ {OPERATOR_NOT, "!"},
+ {OPERATOR_MULASSIGN, "*="},
+ {OPERATOR_MULTIPLY, "*"},
+ {OPERATOR_DIVASSIGN, "/="},
+ {OPERATOR_DIVIDE, "/"},
+ {OPERATOR_LESSEQUAL, "<="},
+ /*{ OPERATOR_LSHASSIGN, "<<=" }, */
+ /*{ OPERATOR_LSHIFT, "<<" }, */
+ {OPERATOR_LESS, "<"},
+ {OPERATOR_GREATEREQUAL, ">="},
+ /*{ OPERATOR_RSHASSIGN, ">>=" }, */
+ /*{ OPERATOR_RSHIFT, ">>" }, */
+ {OPERATOR_GREATER, ">"},
+ /*{ OPERATOR_MODASSIGN, "%=" }, */
+ /*{ OPERATOR_MODULUS, "%" }, */
+ /*{ OPERATOR_ANDASSIGN, "&=" }, */
+ /*{ OPERATOR_BITAND, "&" }, */
+ /*{ OPERATOR_ORASSIGN, "|=" }, */
+ /*{ OPERATOR_BITOR, "|" }, */
+ /*{ OPERATOR_COMPLEMENT, "~" }, */
+ /*{ OPERATOR_XORASSIGN, "^=" }, */
+ {OPERATOR_LOGICALXOR, "^^"},
+ /*{ OPERATOR_BITXOR, "^" } */
+};
+
+static slang_atom
+parse_operator_name(slang_parse_ctx * C)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
+ if (operator_names[i].o_code == (unsigned int) (*C->I)) {
+ slang_atom atom =
+ slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
+ if (atom == SLANG_ATOM_NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ C->I++;
+ return atom;
+ }
+ }
+ RETURN0;
+}
+
+
+static int
+parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_function * func)
+{
+ GLuint functype;
+ /* parse function type and name */
+ if (!parse_fully_specified_type(C, O, &func->header.type))
+ RETURN0;
+
+ functype = *C->I++;
+ switch (functype) {
+ case FUNCTION_ORDINARY:
+ func->kind = SLANG_FUNC_ORDINARY;
+ func->header.a_name = parse_identifier(C);
+ if (func->header.a_name == SLANG_ATOM_NULL)
+ RETURN0;
+ break;
+ case FUNCTION_CONSTRUCTOR:
+ func->kind = SLANG_FUNC_CONSTRUCTOR;
+ if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
+ RETURN0;
+ func->header.a_name =
+ slang_atom_pool_atom(C->atoms,
+ slang_type_specifier_type_to_string
+ (func->header.type.specifier.type));
+ if (func->header.a_name == SLANG_ATOM_NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ break;
+ case FUNCTION_OPERATOR:
+ func->kind = SLANG_FUNC_OPERATOR;
+ func->header.a_name = parse_operator_name(C);
+ if (func->header.a_name == SLANG_ATOM_NULL)
+ RETURN0;
+ break;
+ default:
+ RETURN0;
+ }
+
+ if (!legal_identifier(func->header.a_name)) {
+ slang_info_log_error(C->L, "illegal function name '%s'",
+ (char *) func->header.a_name);
+ RETURN0;
+ }
+
+ /* parse function parameters */
+ while (*C->I++ == PARAMETER_NEXT) {
+ slang_variable *p = slang_variable_scope_grow(func->parameters);
+ if (!p) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!parse_parameter_declaration(C, O, p))
+ RETURN0;
+ }
+
+ /* if the function returns a value, append a hidden __retVal 'out'
+ * parameter that corresponds to the return value.
+ */
+ if (_slang_function_has_return_value(func)) {
+ slang_variable *p = slang_variable_scope_grow(func->parameters);
+ slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
+ assert(a_retVal);
+ p->a_name = a_retVal;
+ p->type = func->header.type;
+ p->type.qualifier = SLANG_QUAL_OUT;
+ }
+
+ /* function formal parameters and local variables share the same
+ * scope, so save the information about param count in a seperate
+ * place also link the scope to the global variable scope so when a
+ * given identifier is not found here, the search process continues
+ * in the global space
+ */
+ func->param_count = func->parameters->num_variables;
+ func->parameters->outer_scope = O->vars;
+
+ return 1;
+}
+
+static int
+parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
+ slang_function * func)
+{
+ slang_output_ctx o = *O;
+
+ if (!parse_function_prototype(C, O, func))
+ RETURN0;
+
+ /* create function's body operation */
+ func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
+ if (func->body == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!slang_operation_construct(func->body)) {
+ _slang_free(func->body);
+ func->body = NULL;
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+
+ /* to parse the body the parse context is modified in order to
+ * capture parsed variables into function's local variable scope
+ */
+ C->global_scope = GL_FALSE;
+ o.vars = func->parameters;
+ if (!parse_statement(C, &o, func->body))
+ RETURN0;
+
+ C->global_scope = GL_TRUE;
+ return 1;
+}
+
+static GLboolean
+initialize_global(slang_assemble_ctx * A, slang_variable * var)
+{
+ slang_operation op_id, op_assign;
+ GLboolean result;
+
+ /* construct the left side of assignment */
+ if (!slang_operation_construct(&op_id))
+ return GL_FALSE;
+ op_id.type = SLANG_OPER_IDENTIFIER;
+ op_id.a_id = var->a_name;
+
+ /* put the variable into operation's scope */
+ op_id.locals->variables =
+ (slang_variable **) _slang_alloc(sizeof(slang_variable *));
+ if (op_id.locals->variables == NULL) {
+ slang_operation_destruct(&op_id);
+ return GL_FALSE;
+ }
+ op_id.locals->num_variables = 1;
+ op_id.locals->variables[0] = var;
+
+ /* construct the assignment expression */
+ if (!slang_operation_construct(&op_assign)) {
+ op_id.locals->num_variables = 0;
+ slang_operation_destruct(&op_id);
+ return GL_FALSE;
+ }
+ op_assign.type = SLANG_OPER_ASSIGN;
+ op_assign.children =
+ (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
+ if (op_assign.children == NULL) {
+ slang_operation_destruct(&op_assign);
+ op_id.locals->num_variables = 0;
+ slang_operation_destruct(&op_id);
+ return GL_FALSE;
+ }
+ op_assign.num_children = 2;
+ op_assign.children[0] = op_id;
+ op_assign.children[1] = *var->initializer;
+
+ result = 1;
+
+ /* carefully destroy the operations */
+ op_assign.num_children = 0;
+ _slang_free(op_assign.children);
+ op_assign.children = NULL;
+ slang_operation_destruct(&op_assign);
+ op_id.locals->num_variables = 0;
+ slang_operation_destruct(&op_id);
+
+ if (!result)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* init declarator list */
+#define DECLARATOR_NONE 0
+#define DECLARATOR_NEXT 1
+
+/* variable declaration */
+#define VARIABLE_NONE 0
+#define VARIABLE_IDENTIFIER 1
+#define VARIABLE_INITIALIZER 2
+#define VARIABLE_ARRAY_EXPLICIT 3
+#define VARIABLE_ARRAY_UNKNOWN 4
+
+
+/**
+ * Parse the initializer for a variable declaration.
+ */
+static int
+parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
+ const slang_fully_specified_type * type)
+{
+ GET_CURRENT_CONTEXT(ctx); /* a hack */
+ slang_variable *var;
+ slang_atom a_name;
+
+ /* empty init declatator (without name, e.g. "float ;") */
+ if (*C->I++ == VARIABLE_NONE)
+ return 1;
+
+ a_name = parse_identifier(C);
+
+ /* check if name is already in this scope */
+ if (_slang_variable_locate(O->vars, a_name, GL_FALSE)) {
+ slang_info_log_error(C->L,
+ "declaration of '%s' conflicts with previous declaration",
+ (char *) a_name);
+ RETURN0;
+ }
+
+ /* make room for the new variable and initialize it */
+ var = slang_variable_scope_grow(O->vars);
+ if (!var) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+
+ /* copy the declarator type qualifier/etc info, parse the identifier */
+ var->type.qualifier = type->qualifier;
+ var->type.centroid = type->centroid;
+ var->type.precision = type->precision;
+ var->type.variant = type->variant;
+ var->type.array_len = type->array_len;
+ var->a_name = a_name;
+ if (var->a_name == SLANG_ATOM_NULL)
+ RETURN0;
+
+ switch (*C->I++) {
+ case VARIABLE_NONE:
+ /* simple variable declarator - just copy the specifier */
+ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
+ RETURN0;
+ break;
+ case VARIABLE_INITIALIZER:
+ /* initialized variable - copy the specifier and parse the expression */
+ if (0 && type->array_len >= 0) {
+ /* The type was something like "float[4]" */
+ convert_to_array(C, var, &type->specifier);
+ var->array_len = type->array_len;
+ }
+ else {
+ if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
+ RETURN0;
+ }
+ var->initializer =
+ (slang_operation *) _slang_alloc(sizeof(slang_operation));
+ if (var->initializer == NULL) {
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!slang_operation_construct(var->initializer)) {
+ _slang_free(var->initializer);
+ var->initializer = NULL;
+ slang_info_log_memory(C->L);
+ RETURN0;
+ }
+ if (!parse_expression(C, O, var->initializer))
+ RETURN0;
+ break;
+ case VARIABLE_ARRAY_UNKNOWN:
+ /* unsized array - mark it as array and copy the specifier to
+ * the array element
+ */
+ if (type->array_len >= 0) {
+ slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+ RETURN0;
+ }
+ if (!convert_to_array(C, var, &type->specifier))
+ return GL_FALSE;
+ break;
+ case VARIABLE_ARRAY_EXPLICIT:
+ if (type->array_len >= 0) {
+ /* the user is trying to do something like: float[2] x[3]; */
+ slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
+ RETURN0;
+ }
+ if (!convert_to_array(C, var, &type->specifier))
+ return GL_FALSE;
+ if (!parse_array_len(C, O, &var->array_len))
+ return GL_FALSE;
+ break;
+ default:
+ RETURN0;
+ }
+
+ /* allocate global address space for a variable with a known size */
+ if (C->global_scope
+ && !(var->type.specifier.type == SLANG_SPEC_ARRAY
+ && var->array_len == 0)) {
+ if (!calculate_var_size(C, O, var))
+ return GL_FALSE;
+ }
+
+ /* emit code for global var decl */
+ if (C->global_scope) {
+ slang_assemble_ctx A;
+ memset(&A, 0, sizeof(slang_assemble_ctx));
+ A.atoms = C->atoms;
+ A.space.funcs = O->funs;
+ A.space.structs = O->structs;
+ A.space.vars = O->vars;
+ A.program = O->program;
+ A.pragmas = O->pragmas;
+ A.vartable = O->vartable;
+ A.log = C->L;
+ A.curFuncEndLabel = NULL;
+ A.EmitContReturn = ctx->Shader.EmitContReturn;
+ if (!_slang_codegen_global_variable(&A, var, C->type))
+ RETURN0;
+ }
+
+ /* initialize global variable */
+ if (C->global_scope) {
+ if (var->initializer != NULL) {
+ slang_assemble_ctx A;
+ memset(&A, 0, sizeof(slang_assemble_ctx));
+ A.atoms = C->atoms;
+ A.space.funcs = O->funs;
+ A.space.structs = O->structs;
+ A.space.vars = O->vars;
+ if (!initialize_global(&A, var))
+ RETURN0;
+ }
+ }
+ return 1;
+}
+
+/**
+ * Parse a list of variable declarations. Each variable may have an
+ * initializer.
+ */
+static int
+parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
+{
+ slang_fully_specified_type type;
+
+ /* parse the fully specified type, common to all declarators */
+ if (!slang_fully_specified_type_construct(&type))
+ RETURN0;
+ if (!parse_fully_specified_type(C, O, &type)) {
+ slang_fully_specified_type_destruct(&type);
+ RETURN0;
+ }
+
+ /* parse declarators, pass-in the parsed type */
+ do {
+ if (!parse_init_declarator(C, O, &type)) {
+ slang_fully_specified_type_destruct(&type);
+ RETURN0;
+ }
+ }
+ while (*C->I++ == DECLARATOR_NEXT);
+
+ slang_fully_specified_type_destruct(&type);
+ return 1;
+}
+
+
+/**
+ * Parse a function definition or declaration.
+ * \param C parsing context
+ * \param O output context
+ * \param definition if non-zero expect a definition, else a declaration
+ * \param parsed_func_ret returns the parsed function
+ * \return GL_TRUE if success, GL_FALSE if failure
+ */
+static GLboolean
+parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
+ slang_function ** parsed_func_ret)
+{
+ slang_function parsed_func, *found_func;
+
+ /* parse function definition/declaration */
+ if (!slang_function_construct(&parsed_func))
+ return GL_FALSE;
+ if (definition) {
+ if (!parse_function_definition(C, O, &parsed_func)) {
+ slang_function_destruct(&parsed_func);
+ return GL_FALSE;
+ }
+ }
+ else {
+ if (!parse_function_prototype(C, O, &parsed_func)) {
+ slang_function_destruct(&parsed_func);
+ return GL_FALSE;
+ }
+ }
+
+ /* find a function with a prototype matching the parsed one - only
+ * the current scope is being searched to allow built-in function
+ * overriding
+ */
+ found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
+ if (found_func == NULL) {
+ /* New function, add it to the function list */
+ O->funs->functions =
+ (slang_function *) _slang_realloc(O->funs->functions,
+ O->funs->num_functions
+ * sizeof(slang_function),
+ (O->funs->num_functions + 1)
+ * sizeof(slang_function));
+ if (O->funs->functions == NULL) {
+ /* Make sure that there are no functions marked, as the
+ * allocation is currently NULL, in order to avoid
+ * a potental segfault as we clean up later.
+ */
+ O->funs->num_functions = 0;
+
+ slang_info_log_memory(C->L);
+ slang_function_destruct(&parsed_func);
+ return GL_FALSE;
+ }
+ O->funs->functions[O->funs->num_functions] = parsed_func;
+ O->funs->num_functions++;
+
+ /* return the newly parsed function */
+ *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
+ }
+ else {
+ /* previously defined or declared */
+ /* TODO: check function return type qualifiers and specifiers */
+ if (definition) {
+ if (found_func->body != NULL) {
+ slang_info_log_error(C->L, "%s: function already has a body.",
+ slang_atom_pool_id(C->atoms,
+ parsed_func.header.
+ a_name));
+ slang_function_destruct(&parsed_func);
+ return GL_FALSE;
+ }
+
+ /* destroy the existing function declaration and replace it
+ * with the new one
+ */
+ slang_function_destruct(found_func);
+ *found_func = parsed_func;
+ }
+ else {
+ /* another declaration of the same function prototype - ignore it */
+ slang_function_destruct(&parsed_func);
+ }
+
+ /* return the found function */
+ *parsed_func_ret = found_func;
+ }
+
+ return GL_TRUE;
+}
+
+/* declaration */
+#define DECLARATION_FUNCTION_PROTOTYPE 1
+#define DECLARATION_INIT_DECLARATOR_LIST 2
+
+static int
+parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
+{
+ switch (*C->I++) {
+ case DECLARATION_INIT_DECLARATOR_LIST:
+ if (!parse_init_declarator_list(C, O))
+ RETURN0;
+ break;
+ case DECLARATION_FUNCTION_PROTOTYPE:
+ {
+ slang_function *dummy_func;
+
+ if (!parse_function(C, O, 0, &dummy_func))
+ RETURN0;
+ }
+ break;
+ default:
+ RETURN0;
+ }
+ return 1;
+}
+
+static int
+parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
+{
+ int precision, type;
+
+ if (!O->allow_precision) {
+ slang_info_log_error(C->L, "syntax error at \"precision\"");
+ RETURN0;
+ }
+
+ precision = *C->I++;
+ switch (precision) {
+ case PRECISION_LOW:
+ case PRECISION_MEDIUM:
+ case PRECISION_HIGH:
+ /* OK */
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
+ precision, __FILE__, __LINE__);
+ RETURN0;
+ }
+
+ type = *C->I++;
+ switch (type) {
+ case TYPE_SPECIFIER_FLOAT:
+ case TYPE_SPECIFIER_INT:
+ case TYPE_SPECIFIER_SAMPLER1D:
+ case TYPE_SPECIFIER_SAMPLER2D:
+ case TYPE_SPECIFIER_SAMPLER3D:
+ case TYPE_SPECIFIER_SAMPLERCUBE:
+ case TYPE_SPECIFIER_SAMPLER1DSHADOW:
+ case TYPE_SPECIFIER_SAMPLER2DSHADOW:
+ case TYPE_SPECIFIER_SAMPLER2DRECT:
+ case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
+ /* OK */
+ break;
+ default:
+ _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
+ type, __FILE__, __LINE__);
+ RETURN0;
+ }
+
+ assert(type < TYPE_SPECIFIER_COUNT);
+ O->default_precision[type] = precision;
+
+ return 1;
+}
+
+
+/**
+ * Initialize the default precision for all types.
+ * XXX this info isn't used yet.
+ */
+static void
+init_default_precision(slang_output_ctx *O, slang_unit_type type)
+{
+ GLuint i;
+ for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
+#if FEATURE_es2_glsl
+ O->default_precision[i] = PRECISION_LOW;
+#else
+ O->default_precision[i] = PRECISION_HIGH;
+#endif
+ }
+
+ if (type == SLANG_UNIT_VERTEX_SHADER) {
+ O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
+ O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
+ }
+ else {
+ O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
+ }
+}
+
+
+static int
+parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
+{
+ if (O->allow_invariant) {
+ slang_atom *a = parse_identifier(C);
+ /* XXX not doing anything with this var yet */
+ /*printf("ID: %s\n", (char*) a);*/
+ return a ? 1 : 0;
+ }
+ else {
+ slang_info_log_error(C->L, "syntax error at \"invariant\"");
+ RETURN0;
+ }
+}
+
+
+/* external declaration or default precision specifier */
+#define EXTERNAL_NULL 0
+#define EXTERNAL_FUNCTION_DEFINITION 1
+#define EXTERNAL_DECLARATION 2
+#define DEFAULT_PRECISION 3
+#define INVARIANT_STMT 4
+
+
+static GLboolean
+parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
+ struct gl_shader *shader)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ slang_output_ctx o;
+ GLboolean success;
+ GLuint maxRegs;
+ slang_function *mainFunc = NULL;
+
+ if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
+ unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
+ maxRegs = ctx->Const.FragmentProgram.MaxTemps;
+ }
+ else {
+ assert(unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
+ unit->type == SLANG_UNIT_VERTEX_SHADER);
+ maxRegs = ctx->Const.VertexProgram.MaxTemps;
+ }
+
+ /* setup output context */
+ o.funs = &unit->funs;
+ o.structs = &unit->structs;
+ o.vars = &unit->vars;
+ o.program = shader ? shader->Program : NULL;
+ o.pragmas = shader ? &shader->Pragmas : NULL;
+ o.vartable = _slang_new_var_table(maxRegs);
+ _slang_push_var_table(o.vartable);
+
+ /* allow 'invariant' keyword? */
+#if FEATURE_es2_glsl
+ o.allow_invariant = GL_TRUE;
+#else
+ o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+#endif
+
+ /* allow 'centroid' keyword? */
+ o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+
+ /* allow 'lowp/mediump/highp' keywords? */
+#if FEATURE_es2_glsl
+ o.allow_precision = GL_TRUE;
+#else
+ o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+#endif
+ init_default_precision(&o, unit->type);
+
+ /* allow 'float[]' keyword? */
+ o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
+
+ /* parse individual functions and declarations */
+ while (*C->I != EXTERNAL_NULL) {
+ switch (*C->I++) {
+ case EXTERNAL_FUNCTION_DEFINITION:
+ {
+ slang_function *func;
+ success = parse_function(C, &o, 1, &func);
+ if (success &&
+ _mesa_strcmp((char *) func->header.a_name, "main") == 0) {
+ /* found main() */
+ mainFunc = func;
+ }
+ }
+ break;
+ case EXTERNAL_DECLARATION:
+ success = parse_declaration(C, &o);
+ break;
+ case DEFAULT_PRECISION:
+ success = parse_default_precision(C, &o);
+ break;
+ case INVARIANT_STMT:
+ success = parse_invariant(C, &o);
+ break;
+ default:
+ success = GL_FALSE;
+ }
+
+ if (!success) {
+ /* xxx free codegen */
+ _slang_pop_var_table(o.vartable);
+ return GL_FALSE;
+ }
+ }
+ C->I++;
+
+ if (mainFunc) {
+ /* assemble (generate code) for main() */
+ slang_assemble_ctx A;
+ memset(&A, 0, sizeof(slang_assemble_ctx));
+ A.atoms = C->atoms;
+ A.space.funcs = o.funs;
+ A.space.structs = o.structs;
+ A.space.vars = o.vars;
+ A.program = o.program;
+ A.pragmas = &shader->Pragmas;
+ A.vartable = o.vartable;
+ A.EmitContReturn = ctx->Shader.EmitContReturn;
+ A.log = C->L;
+
+ /* main() takes no parameters */
+ if (mainFunc->param_count > 0) {
+ slang_info_log_error(A.log, "main() takes no arguments");
+ return GL_FALSE;
+ }
+
+ _slang_codegen_function(&A, mainFunc);
+
+ shader->Main = GL_TRUE; /* this shader defines main() */
+
+ shader->UnresolvedRefs = A.UnresolvedRefs;
+ }
+
+ _slang_pop_var_table(o.vartable);
+ _slang_delete_var_table(o.vartable);
+
+ return GL_TRUE;
+}
+
+static GLboolean
+compile_binary(const byte * prod, slang_code_unit * unit,
+ GLuint version,
+ slang_unit_type type, slang_info_log * infolog,
+ slang_code_unit * builtin, slang_code_unit * downlink,
+ struct gl_shader *shader)
+{
+ slang_parse_ctx C;
+
+ unit->type = type;
+
+ /* setup parse context */
+ C.I = prod;
+ C.L = infolog;
+ C.parsing_builtin = (builtin == NULL);
+ C.global_scope = GL_TRUE;
+ C.atoms = &unit->object->atompool;
+ C.type = type;
+ C.version = version;
+
+ if (!check_revision(&C))
+ return GL_FALSE;
+
+ if (downlink != NULL) {
+ unit->vars.outer_scope = &downlink->vars;
+ unit->funs.outer_scope = &downlink->funs;
+ unit->structs.outer_scope = &downlink->structs;
+ }
+
+ /* parse translation unit */
+ return parse_code_unit(&C, unit, shader);
+}
+
+static GLboolean
+compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
+ slang_unit_type type, slang_info_log * infolog,
+ slang_code_unit * builtin,
+ struct gl_shader *shader,
+ const struct gl_extensions *extensions,
+ struct gl_sl_pragmas *pragmas)
+{
+ byte *prod;
+ GLuint size, start, version;
+ slang_string preprocessed;
+ GLuint maxVersion;
+
+#if FEATURE_ARB_shading_language_120
+ maxVersion = 120;
+#elif FEATURE_es2_glsl
+ maxVersion = 100;
+#else
+ maxVersion = 110;
+#endif
+
+ /* First retrieve the version number. */
+ if (!_slang_preprocess_version(source, &version, &start, infolog))
+ return GL_FALSE;
+
+ if (version > maxVersion) {
+ slang_info_log_error(infolog,
+ "language version %.2f is not supported.",
+ version * 0.01);
+ return GL_FALSE;
+ }
+
+ /* Now preprocess the source string. */
+ slang_string_init(&preprocessed);
+ if (!_slang_preprocess_directives(&preprocessed, &source[start],
+ infolog, extensions, pragmas)) {
+ slang_string_free(&preprocessed);
+ slang_info_log_error(infolog, "failed to preprocess the source.");
+ return GL_FALSE;
+ }
+
+ /* Finally check the syntax and generate its binary representation. */
+ if (!grammar_fast_check(id,
+ (const byte *) (slang_string_cstr(&preprocessed)),
+ &prod, &size, 65536)) {
+ char buf[1024];
+ GLint pos;
+
+ slang_string_free(&preprocessed);
+ grammar_get_last_error((byte *) (buf), sizeof(buf), &pos);
+ slang_info_log_error(infolog, buf);
+ /* syntax error (possibly in library code) */
+#if 0
+ {
+ int line, col;
+ char *s;
+ s = (char *) _mesa_find_line_column((const GLubyte *) source,
+ (const GLubyte *) source + pos,
+ &line, &col);
+ printf("Error on line %d, col %d: %s\n", line, col, s);
+ }
+#endif
+ return GL_FALSE;
+ }
+ slang_string_free(&preprocessed);
+
+ /* Syntax is okay - translate it to internal representation. */
+ if (!compile_binary(prod, unit, version, type, infolog, builtin,
+ &builtin[SLANG_BUILTIN_TOTAL - 1],
+ shader)) {
+ grammar_alloc_free(prod);
+ return GL_FALSE;
+ }
+ grammar_alloc_free(prod);
+ return GL_TRUE;
+}
+
+LONGSTRING static const char *slang_shader_syn =
+#include "library/slang_shader_syn.h"
+ ;
+
+static const byte slang_core_gc[] = {
+#include "library/slang_core_gc.h"
+};
+
+static const byte slang_120_core_gc[] = {
+#include "library/slang_120_core_gc.h"
+};
+
+static const byte slang_120_fragment_gc[] = {
+#include "library/slang_builtin_120_fragment_gc.h"
+};
+
+static const byte slang_common_builtin_gc[] = {
+#include "library/slang_common_builtin_gc.h"
+};
+
+static const byte slang_fragment_builtin_gc[] = {
+#include "library/slang_fragment_builtin_gc.h"
+};
+
+static const byte slang_vertex_builtin_gc[] = {
+#include "library/slang_vertex_builtin_gc.h"
+};
+
+static GLboolean
+compile_object(grammar * id, const char *source, slang_code_object * object,
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_shader *shader,
+ const struct gl_extensions *extensions,
+ struct gl_sl_pragmas *pragmas)
+{
+ slang_code_unit *builtins = NULL;
+ GLuint base_version = 110;
+
+ /* load GLSL grammar */
+ *id = grammar_load_from_text((const byte *) (slang_shader_syn));
+ if (*id == 0) {
+ byte buf[1024];
+ int pos;
+
+ grammar_get_last_error(buf, 1024, &pos);
+ slang_info_log_error(infolog, (const char *) (buf));
+ return GL_FALSE;
+ }
+
+ /* set shader type - the syntax is slightly different for different shaders */
+ if (type == SLANG_UNIT_FRAGMENT_SHADER
+ || type == SLANG_UNIT_FRAGMENT_BUILTIN)
+ grammar_set_reg8(*id, (const byte *) "shader_type", 1);
+ else
+ grammar_set_reg8(*id, (const byte *) "shader_type", 2);
+
+ /* enable language extensions */
+ grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
+
+ /* if parsing user-specified shader, load built-in library */
+ if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER) {
+ /* compile core functionality first */
+ if (!compile_binary(slang_core_gc,
+ &object->builtin[SLANG_BUILTIN_CORE],
+ base_version,
+ SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
+ NULL, NULL, NULL))
+ return GL_FALSE;
+
+#if FEATURE_ARB_shading_language_120
+ if (!compile_binary(slang_120_core_gc,
+ &object->builtin[SLANG_BUILTIN_120_CORE],
+ 120,
+ SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
+ NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
+ return GL_FALSE;
+#endif
+
+ /* compile common functions and variables, link to core */
+ if (!compile_binary(slang_common_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_COMMON],
+#if FEATURE_ARB_shading_language_120
+ 120,
+#else
+ base_version,
+#endif
+ SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+#if FEATURE_ARB_shading_language_120
+ &object->builtin[SLANG_BUILTIN_120_CORE],
+#else
+ &object->builtin[SLANG_BUILTIN_CORE],
+#endif
+ NULL))
+ return GL_FALSE;
+
+ /* compile target-specific functions and variables, link to common */
+ if (type == SLANG_UNIT_FRAGMENT_SHADER) {
+ if (!compile_binary(slang_fragment_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ base_version,
+ SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+ return GL_FALSE;
+#if FEATURE_ARB_shading_language_120
+ if (!compile_binary(slang_120_fragment_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ 120,
+ SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+ return GL_FALSE;
+#endif
+ }
+ else if (type == SLANG_UNIT_VERTEX_SHADER) {
+ if (!compile_binary(slang_vertex_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ base_version,
+ SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
+ return GL_FALSE;
+ }
+
+ /* disable language extensions */
+#if NEW_SLANG /* allow-built-ins */
+ grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
+#else
+ grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0);
+#endif
+ builtins = object->builtin;
+ }
+
+ /* compile the actual shader - pass-in built-in library for external shader */
+ return compile_with_grammar(*id, source, &object->unit, type, infolog,
+ builtins, shader, extensions, pragmas);
+}
+
+
+static GLboolean
+compile_shader(GLcontext *ctx, slang_code_object * object,
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_shader *shader)
+{
+ GLboolean success;
+ grammar id = 0;
+
+#if 0 /* for debug */
+ _mesa_printf("********* COMPILE SHADER ***********\n");
+ _mesa_printf("%s\n", shader->Source);
+ _mesa_printf("************************************\n");
+#endif
+
+ assert(shader->Program);
+
+ _slang_code_object_dtr(object);
+ _slang_code_object_ctr(object);
+
+ success = compile_object(&id, shader->Source, object, type, infolog, shader,
+ &ctx->Extensions, &shader->Pragmas);
+ if (id != 0)
+ grammar_destroy(id);
+ if (!success)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+
+GLboolean
+_slang_compile(GLcontext *ctx, struct gl_shader *shader)
+{
+ GLboolean success;
+ slang_info_log info_log;
+ slang_code_object obj;
+ slang_unit_type type;
+
+ if (shader->Type == GL_VERTEX_SHADER) {
+ type = SLANG_UNIT_VERTEX_SHADER;
+ }
+ else {
+ assert(shader->Type == GL_FRAGMENT_SHADER);
+ type = SLANG_UNIT_FRAGMENT_SHADER;
+ }
+
+ if (!shader->Source)
+ return GL_FALSE;
+
+ ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
+
+ shader->Main = GL_FALSE;
+
+ if (!shader->Program) {
+ GLenum progTarget;
+ if (shader->Type == GL_VERTEX_SHADER)
+ progTarget = GL_VERTEX_PROGRAM_ARB;
+ else
+ progTarget = GL_FRAGMENT_PROGRAM_ARB;
+ shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
+ shader->Program->Parameters = _mesa_new_parameter_list();
+ shader->Program->Varying = _mesa_new_parameter_list();
+ shader->Program->Attributes = _mesa_new_parameter_list();
+ }
+
+ slang_info_log_construct(&info_log);
+ _slang_code_object_ctr(&obj);
+
+ success = compile_shader(ctx, &obj, type, &info_log, shader);
+
+ /* free shader's prev info log */
+ if (shader->InfoLog) {
+ _mesa_free(shader->InfoLog);
+ shader->InfoLog = NULL;
+ }
+
+ if (info_log.text) {
+ /* copy info-log string to shader object */
+ shader->InfoLog = _mesa_strdup(info_log.text);
+ }
+
+ if (info_log.error_flag) {
+ success = GL_FALSE;
+ }
+
+ slang_info_log_destruct(&info_log);
+ _slang_code_object_dtr(&obj);
+
+ _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
+ ctx->Shader.MemPool = NULL;
+
+ /* remove any reads of output registers */
+#if 0
+ printf("Pre-remove output reads:\n");
+ _mesa_print_program(shader->Program);
+#endif
+ _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
+ if (shader->Type == GL_VERTEX_SHADER) {
+ /* and remove writes to varying vars in vertex programs */
+ _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
+ }
+#if 0
+ printf("Post-remove output reads:\n");
+ _mesa_print_program(shader->Program);
+#endif
+
+ shader->CompileStatus = success;
+
+ if (success) {
+ if (shader->Pragmas.Optimize &&
+ (ctx->Shader.Flags & GLSL_NO_OPT) == 0) {
+ _mesa_optimize_program(ctx, shader->Program);
+ }
+ }
+
+ if (ctx->Shader.Flags & GLSL_LOG) {
+ _mesa_write_shader_to_file(shader);
+ }
+
+ return success;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_compile.h b/mesalib/src/mesa/shader/slang/slang_compile.h
new file mode 100644
index 000000000..7fb549d33
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile.h
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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 !defined SLANG_COMPILE_H
+#define SLANG_COMPILE_H
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "slang_typeinfo.h"
+#include "slang_compile_variable.h"
+#include "slang_compile_struct.h"
+#include "slang_compile_operation.h"
+#include "slang_compile_function.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+typedef struct slang_name_space_
+{
+ struct slang_function_scope_ *funcs;
+ struct slang_struct_scope_ *structs;
+ struct slang_variable_scope_ *vars;
+} slang_name_space;
+
+typedef enum slang_unit_type_
+{
+ SLANG_UNIT_FRAGMENT_SHADER,
+ SLANG_UNIT_VERTEX_SHADER,
+ SLANG_UNIT_FRAGMENT_BUILTIN,
+ SLANG_UNIT_VERTEX_BUILTIN
+} slang_unit_type;
+
+
+typedef struct slang_code_unit_
+{
+ slang_variable_scope vars;
+ slang_function_scope funs;
+ slang_struct_scope structs;
+ slang_unit_type type;
+ struct slang_code_object_ *object;
+} slang_code_unit;
+
+
+extern GLvoid
+_slang_code_unit_ctr (slang_code_unit *, struct slang_code_object_ *);
+
+extern GLvoid
+_slang_code_unit_dtr (slang_code_unit *);
+
+#define SLANG_BUILTIN_CORE 0
+#define SLANG_BUILTIN_120_CORE 1
+#define SLANG_BUILTIN_COMMON 2
+#define SLANG_BUILTIN_TARGET 3
+
+#define SLANG_BUILTIN_TOTAL 4
+
+typedef struct slang_code_object_
+{
+ slang_code_unit builtin[SLANG_BUILTIN_TOTAL];
+ slang_code_unit unit;
+ slang_atom_pool atompool;
+} slang_code_object;
+
+extern GLvoid
+_slang_code_object_ctr (slang_code_object *);
+
+extern GLvoid
+_slang_code_object_dtr (slang_code_object *);
+
+extern GLboolean
+_slang_compile (GLcontext *ctx, struct gl_shader *shader);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_function.c b/mesalib/src/mesa/shader/slang/slang_compile_function.c
new file mode 100644
index 000000000..4dd885176
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_function.c
@@ -0,0 +1,262 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_compile_function.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+int
+slang_function_construct(slang_function * func)
+{
+ func->kind = SLANG_FUNC_ORDINARY;
+ if (!slang_variable_construct(&func->header))
+ return 0;
+
+ func->parameters = (slang_variable_scope *)
+ _slang_alloc(sizeof(slang_variable_scope));
+ if (func->parameters == NULL) {
+ slang_variable_destruct(&func->header);
+ return 0;
+ }
+
+ _slang_variable_scope_ctr(func->parameters);
+ func->param_count = 0;
+ func->body = NULL;
+ return 1;
+}
+
+void
+slang_function_destruct(slang_function * func)
+{
+ slang_variable_destruct(&func->header);
+ slang_variable_scope_destruct(func->parameters);
+ _slang_free(func->parameters);
+ if (func->body != NULL) {
+ slang_operation_destruct(func->body);
+ _slang_free(func->body);
+ }
+}
+
+
+slang_function *
+slang_function_new(slang_function_kind kind)
+{
+ slang_function *fun = (slang_function *)
+ _slang_alloc(sizeof(slang_function));
+ if (fun) {
+ slang_function_construct(fun);
+ fun->kind = kind;
+ }
+ return fun;
+}
+
+
+/*
+ * slang_function_scope
+ */
+
+GLvoid
+_slang_function_scope_ctr(slang_function_scope * self)
+{
+ self->functions = NULL;
+ self->num_functions = 0;
+ self->outer_scope = NULL;
+}
+
+void
+slang_function_scope_destruct(slang_function_scope * scope)
+{
+ unsigned int i;
+
+ for (i = 0; i < scope->num_functions; i++)
+ slang_function_destruct(scope->functions + i);
+ _slang_free(scope->functions);
+}
+
+
+/**
+ * Does this function have a non-void return value?
+ */
+GLboolean
+_slang_function_has_return_value(const slang_function *fun)
+{
+ return fun->header.type.specifier.type != SLANG_SPEC_VOID;
+}
+
+
+/**
+ * Search a list of functions for a particular function by name.
+ * \param funcs the list of functions to search
+ * \param a_name the name to search for
+ * \param all_scopes if non-zero, search containing scopes too.
+ * \return pointer to found function, or NULL.
+ */
+int
+slang_function_scope_find_by_name(slang_function_scope * funcs,
+ slang_atom a_name, int all_scopes)
+{
+ unsigned int i;
+
+ for (i = 0; i < funcs->num_functions; i++)
+ if (a_name == funcs->functions[i].header.a_name)
+ return 1;
+ if (all_scopes && funcs->outer_scope != NULL)
+ return slang_function_scope_find_by_name(funcs->outer_scope, a_name, 1);
+ return 0;
+}
+
+
+/**
+ * Search a list of functions for a particular function (for implementing
+ * function calls. Matching is done by first comparing the function's name,
+ * then the function's parameter list.
+ *
+ * \param funcs the list of functions to search
+ * \param fun the function to search for
+ * \param all_scopes if non-zero, search containing scopes too.
+ * \return pointer to found function, or NULL.
+ */
+slang_function *
+slang_function_scope_find(slang_function_scope * funcs, slang_function * fun,
+ int all_scopes)
+{
+ unsigned int i;
+
+ for (i = 0; i < funcs->num_functions; i++) {
+ slang_function *f = &funcs->functions[i];
+ const GLuint haveRetValue = 0;
+#if 0
+ = (f->header.type.specifier.type != SLANG_SPEC_VOID);
+#endif
+ unsigned int j;
+
+ /*
+ printf("Compare name %s to %s (ret %u, %d, %d)\n",
+ (char *) fun->header.a_name, (char *) f->header.a_name,
+ haveRetValue,
+ fun->param_count, f->param_count);
+ */
+
+ if (fun->header.a_name != f->header.a_name)
+ continue;
+ if (fun->param_count != f->param_count)
+ continue;
+ for (j = haveRetValue; j < fun->param_count; j++) {
+ if (!slang_type_specifier_equal
+ (&fun->parameters->variables[j]->type.specifier,
+ &f->parameters->variables[j]->type.specifier))
+ break;
+ }
+ if (j == fun->param_count) {
+ /*
+ printf("Found match\n");
+ */
+ return f;
+ }
+ }
+ /*
+ printf("Not found\n");
+ */
+ if (all_scopes && funcs->outer_scope != NULL)
+ return slang_function_scope_find(funcs->outer_scope, fun, 1);
+ return NULL;
+}
+
+
+/**
+ * Lookup a function according to name and parameter count/types.
+ */
+slang_function *
+_slang_function_locate(const slang_function_scope * funcs, slang_atom a_name,
+ slang_operation * args, GLuint num_args,
+ const slang_name_space * space, slang_atom_pool * atoms,
+ slang_info_log *log, GLboolean *error)
+{
+ slang_typeinfo arg_ti[100];
+ GLuint i;
+
+ *error = GL_FALSE;
+
+ /* determine type of each argument */
+ assert(num_args < 100);
+ for (i = 0; i < num_args; i++) {
+ if (!slang_typeinfo_construct(&arg_ti[i]))
+ return NULL;
+ if (!_slang_typeof_operation(&args[i], space, &arg_ti[i], atoms, log)) {
+ return NULL;
+ }
+ }
+
+ /* loop over function scopes */
+ while (funcs) {
+
+ /* look for function with matching name and argument/param types */
+ for (i = 0; i < funcs->num_functions; i++) {
+ slang_function *f = &funcs->functions[i];
+ const GLuint haveRetValue = _slang_function_has_return_value(f);
+ GLuint j;
+
+ if (a_name != f->header.a_name)
+ continue;
+ if (f->param_count - haveRetValue != num_args)
+ continue;
+
+ /* compare parameter / argument types */
+ for (j = 0; j < num_args; j++) {
+ if (!slang_type_specifier_compatible(&arg_ti[j].spec,
+ &f->parameters->variables[j]->type.specifier)) {
+ /* param/arg types don't match */
+ break;
+ }
+
+ /* "out" and "inout" formal parameter requires the actual
+ * argument to be an l-value.
+ */
+ if (!arg_ti[j].can_be_referenced &&
+ (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
+ f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
+ /* param is not an lvalue! */
+ *error = GL_TRUE;
+ return NULL;
+ }
+ }
+
+ if (j == num_args) {
+ /* name and args match! */
+ return f;
+ }
+ }
+
+ funcs = funcs->outer_scope;
+ }
+
+ return NULL;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_function.h b/mesalib/src/mesa/shader/slang/slang_compile_function.h
new file mode 100644
index 000000000..a5445ec25
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_function.h
@@ -0,0 +1,92 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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 SLANG_COMPILE_FUNCTION_H
+#define SLANG_COMPILE_FUNCTION_H
+
+
+/**
+ * Types of functions.
+ */
+typedef enum slang_function_kind_
+{
+ SLANG_FUNC_ORDINARY,
+ SLANG_FUNC_CONSTRUCTOR,
+ SLANG_FUNC_OPERATOR
+} slang_function_kind;
+
+
+/**
+ * Description of a compiled shader function.
+ */
+typedef struct slang_function_
+{
+ slang_function_kind kind;
+ slang_variable header; /**< The function's name and return type */
+ slang_variable_scope *parameters; /**< formal parameters AND local vars */
+ unsigned int param_count; /**< number of formal params (no locals) */
+ slang_operation *body; /**< The instruction tree */
+} slang_function;
+
+extern int slang_function_construct(slang_function *);
+extern void slang_function_destruct(slang_function *);
+extern slang_function *slang_function_new(slang_function_kind kind);
+
+extern GLboolean
+_slang_function_has_return_value(const slang_function *fun);
+
+
+/**
+ * Basically, a list of compiled functions.
+ */
+typedef struct slang_function_scope_
+{
+ slang_function *functions;
+ GLuint num_functions;
+ struct slang_function_scope_ *outer_scope;
+} slang_function_scope;
+
+
+extern GLvoid
+_slang_function_scope_ctr(slang_function_scope *);
+
+extern void
+slang_function_scope_destruct(slang_function_scope *);
+
+extern int
+slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
+
+extern slang_function *
+slang_function_scope_find(slang_function_scope *, slang_function *, int);
+
+extern struct slang_function_ *
+_slang_function_locate(const struct slang_function_scope_ *funcs,
+ slang_atom name, struct slang_operation_ *params,
+ GLuint num_params,
+ const struct slang_name_space_ *space,
+ slang_atom_pool *atoms, slang_info_log *log,
+ GLboolean *error);
+
+
+#endif /* SLANG_COMPILE_FUNCTION_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_operation.c b/mesalib/src/mesa/shader/slang/slang_compile_operation.c
new file mode 100644
index 000000000..3e2bdbc91
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_operation.c
@@ -0,0 +1,332 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_compile_operation.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+/**
+ * Init a slang_operation object
+ */
+GLboolean
+slang_operation_construct(slang_operation * oper)
+{
+ oper->type = SLANG_OPER_NONE;
+ oper->children = NULL;
+ oper->num_children = 0;
+ oper->literal[0] = 0.0;
+ oper->literal_size = 1;
+ oper->array_constructor = GL_FALSE;
+ oper->a_id = SLANG_ATOM_NULL;
+ oper->locals = _slang_variable_scope_new(NULL);
+ if (oper->locals == NULL)
+ return GL_FALSE;
+ _slang_variable_scope_ctr(oper->locals);
+ oper->fun = NULL;
+ oper->var = NULL;
+ return GL_TRUE;
+}
+
+void
+slang_operation_destruct(slang_operation * oper)
+{
+ GLuint i;
+
+ for (i = 0; i < oper->num_children; i++)
+ slang_operation_destruct(oper->children + i);
+ _slang_free(oper->children);
+ slang_variable_scope_destruct(oper->locals);
+ _slang_free(oper->locals);
+ oper->children = NULL;
+ oper->num_children = 0;
+ oper->locals = NULL;
+}
+
+
+/**
+ * Recursively traverse 'oper', replacing occurances of 'oldScope' with
+ * 'newScope' in the oper->locals->outer_scope field.
+ */
+void
+slang_replace_scope(slang_operation *oper,
+ slang_variable_scope *oldScope,
+ slang_variable_scope *newScope)
+{
+ GLuint i;
+
+ if (oper->locals != newScope &&
+ oper->locals->outer_scope == oldScope) {
+ /* found. replace old w/ new */
+ oper->locals->outer_scope = newScope;
+ }
+
+ if (oper->type == SLANG_OPER_VARIABLE_DECL) {
+ /* search/replace in the initializer */
+ slang_variable *var;
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ if (var && var->initializer) {
+ slang_replace_scope(var->initializer, oldScope, newScope);
+ }
+ }
+
+ /* search/replace in children */
+ for (i = 0; i < oper->num_children; i++) {
+ slang_replace_scope(&oper->children[i], oldScope, newScope);
+ }
+}
+
+
+/**
+ * Recursively copy a slang_operation node.
+ * \param x copy target
+ * \param y copy source
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+GLboolean
+slang_operation_copy(slang_operation * x, const slang_operation * y)
+{
+ slang_operation z;
+ GLuint i;
+
+ if (!slang_operation_construct(&z))
+ return GL_FALSE;
+ z.type = y->type;
+ if (y->num_children > 0) {
+ z.children = (slang_operation *)
+ _slang_alloc(y->num_children * sizeof(slang_operation));
+ if (z.children == NULL) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
+ }
+ for (z.num_children = 0; z.num_children < y->num_children;
+ z.num_children++) {
+ if (!slang_operation_construct(&z.children[z.num_children])) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
+ }
+ for (i = 0; i < z.num_children; i++) {
+ if (!slang_operation_copy(&z.children[i], &y->children[i])) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
+ }
+ z.literal[0] = y->literal[0];
+ z.literal[1] = y->literal[1];
+ z.literal[2] = y->literal[2];
+ z.literal[3] = y->literal[3];
+ z.literal_size = y->literal_size;
+ assert(y->literal_size >= 1);
+ assert(y->literal_size <= 4);
+ z.a_id = y->a_id;
+ if (y->locals) {
+ if (!slang_variable_scope_copy(z.locals, y->locals)) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
+ }
+
+ /* update scoping for children */
+ for (i = 0; i < y->num_children; i++) {
+ if (y->children[i].locals &&
+ y->children[i].locals->outer_scope == y->locals) {
+ z.children[i].locals->outer_scope = z.locals;
+ }
+ }
+
+#if 0
+ z.var = y->var;
+ z.fun = y->fun;
+#endif
+ slang_operation_destruct(x);
+ *x = z;
+
+ /* If this operation declares a new scope, we need to make sure
+ * all children point to it, not the original operation's scope!
+ */
+ if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ x->type == SLANG_OPER_WHILE ||
+ x->type == SLANG_OPER_FOR) {
+ slang_replace_scope(x, y->locals, x->locals);
+ }
+
+ return GL_TRUE;
+}
+
+
+slang_operation *
+slang_operation_new(GLuint count)
+{
+ slang_operation *ops
+ = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
+ assert(count > 0);
+ if (ops) {
+ GLuint i;
+ for (i = 0; i < count; i++)
+ slang_operation_construct(ops + i);
+ }
+ return ops;
+}
+
+
+/**
+ * Delete operation and all children
+ */
+void
+slang_operation_delete(slang_operation *oper)
+{
+ slang_operation_destruct(oper);
+ _slang_free(oper);
+}
+
+
+void
+slang_operation_free_children(slang_operation *oper)
+{
+ GLuint i;
+ for (i = 0; i < slang_oper_num_children(oper); i++) {
+ slang_operation *child = slang_oper_child(oper, i);
+ slang_operation_destruct(child);
+ }
+ _slang_free(oper->children);
+ oper->children = NULL;
+ oper->num_children = 0;
+}
+
+
+slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children)
+{
+ slang_operation *ops;
+
+ ops = (slang_operation *)
+ _slang_realloc(*children,
+ *numChildren * sizeof(slang_operation),
+ (*numChildren + 1) * sizeof(slang_operation));
+ if (ops) {
+ slang_operation *newOp = ops + *numChildren;
+ if (!slang_operation_construct(newOp)) {
+ _slang_free(ops);
+ *children = NULL;
+ return NULL;
+ }
+ *children = ops;
+ (*numChildren)++;
+ return newOp;
+ }
+ return NULL;
+}
+
+/**
+ * Insert a new slang_operation into an array.
+ * \param numElements pointer to current array size (in/out)
+ * \param array address of the array (in/out)
+ * \param pos position to insert new element
+ * \return pointer to the new operation/element
+ */
+slang_operation *
+slang_operation_insert(GLuint *numElements, slang_operation **array,
+ GLuint pos)
+{
+ slang_operation *ops;
+
+ assert(pos <= *numElements);
+
+ ops = (slang_operation *)
+ _slang_alloc((*numElements + 1) * sizeof(slang_operation));
+ if (ops) {
+ slang_operation *newOp;
+ newOp = ops + pos;
+ if (pos > 0)
+ _mesa_memcpy(ops, *array, pos * sizeof(slang_operation));
+ if (pos < *numElements)
+ _mesa_memcpy(newOp + 1, (*array) + pos,
+ (*numElements - pos) * sizeof(slang_operation));
+
+ if (!slang_operation_construct(newOp)) {
+ _slang_free(ops);
+ *numElements = 0;
+ *array = NULL;
+ return NULL;
+ }
+ if (*array)
+ _slang_free(*array);
+ *array = ops;
+ (*numElements)++;
+ return newOp;
+ }
+ return NULL;
+}
+
+
+/**
+ * Add/insert new child into given node at given position.
+ * \return pointer to the new child node
+ */
+slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos)
+{
+ slang_operation *newOp;
+
+ newOp = slang_operation_insert(&oper->num_children,
+ &oper->children,
+ pos);
+ if (newOp) {
+ newOp->locals->outer_scope = oper->locals;
+ }
+
+ return newOp;
+}
+
+
+void
+_slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
+{
+ slang_operation tmp = *oper0;
+ *oper0 = *oper1;
+ *oper1 = tmp;
+}
+
+
+void
+slang_operation_add_children(slang_operation *oper, GLuint num_children)
+{
+ GLuint i;
+ assert(oper->num_children == 0);
+ assert(oper->children == NULL);
+ oper->num_children = num_children;
+ oper->children = slang_operation_new(num_children);
+ for (i = 0; i < num_children; i++) {
+ oper->children[i].locals = _slang_variable_scope_new(oper->locals);
+ }
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_operation.h b/mesalib/src/mesa/shader/slang/slang_compile_operation.h
new file mode 100644
index 000000000..58f1edeed
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_operation.h
@@ -0,0 +1,226 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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 SLANG_COMPILE_OPERATION_H
+#define SLANG_COMPILE_OPERATION_H
+
+
+/**
+ * Types of slang operations.
+ * These are the types of the AST (abstract syntax tree) nodes.
+ * [foo] indicates a sub-tree or reference to another type of node
+ */
+typedef enum slang_operation_type_
+{
+ SLANG_OPER_NONE,
+ SLANG_OPER_BLOCK_NO_NEW_SCOPE, /* "{" sequence "}" */
+ SLANG_OPER_BLOCK_NEW_SCOPE, /* "{" sequence "}" */
+ SLANG_OPER_VARIABLE_DECL, /* [type] [var] or [var] = [expr] */
+ SLANG_OPER_ASM,
+ SLANG_OPER_BREAK, /* "break" statement */
+ SLANG_OPER_CONTINUE, /* "continue" statement */
+ SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */
+ SLANG_OPER_RETURN, /* "return" [expr] */
+ SLANG_OPER_RETURN_INLINED, /* "return" [expr] from inlined function */
+ SLANG_OPER_LABEL, /* a jump target */
+ SLANG_OPER_EXPRESSION, /* [expr] */
+ SLANG_OPER_IF, /* "if" [0] then [1] else [2] */
+ SLANG_OPER_WHILE, /* "while" [cond] [body] */
+ SLANG_OPER_DO, /* "do" [body] "while" [cond] */
+ SLANG_OPER_FOR, /* "for" [init] [while] [incr] [body] */
+ SLANG_OPER_VOID, /* nop */
+ SLANG_OPER_LITERAL_BOOL, /* "true" or "false" */
+ SLANG_OPER_LITERAL_INT, /* integer literal */
+ SLANG_OPER_LITERAL_FLOAT, /* float literal */
+ SLANG_OPER_IDENTIFIER, /* var name, func name, etc */
+ SLANG_OPER_SEQUENCE, /* [expr] "," [expr] "," etc */
+ SLANG_OPER_ASSIGN, /* [var] "=" [expr] */
+ SLANG_OPER_ADDASSIGN, /* [var] "+=" [expr] */
+ SLANG_OPER_SUBASSIGN, /* [var] "-=" [expr] */
+ SLANG_OPER_MULASSIGN, /* [var] "*=" [expr] */
+ SLANG_OPER_DIVASSIGN, /* [var] "/=" [expr] */
+ /*SLANG_OPER_MODASSIGN, */
+ /*SLANG_OPER_LSHASSIGN, */
+ /*SLANG_OPER_RSHASSIGN, */
+ /*SLANG_OPER_ORASSIGN, */
+ /*SLANG_OPER_XORASSIGN, */
+ /*SLANG_OPER_ANDASSIGN, */
+ SLANG_OPER_SELECT, /* [expr] "?" [expr] ":" [expr] */
+ SLANG_OPER_LOGICALOR, /* [expr] "||" [expr] */
+ SLANG_OPER_LOGICALXOR, /* [expr] "^^" [expr] */
+ SLANG_OPER_LOGICALAND, /* [expr] "&&" [expr] */
+ /*SLANG_OPER_BITOR, */
+ /*SLANG_OPER_BITXOR, */
+ /*SLANG_OPER_BITAND, */
+ SLANG_OPER_EQUAL, /* [expr] "==" [expr] */
+ SLANG_OPER_NOTEQUAL, /* [expr] "!=" [expr] */
+ SLANG_OPER_LESS, /* [expr] "<" [expr] */
+ SLANG_OPER_GREATER, /* [expr] ">" [expr] */
+ SLANG_OPER_LESSEQUAL, /* [expr] "<=" [expr] */
+ SLANG_OPER_GREATEREQUAL, /* [expr] ">=" [expr] */
+ /*SLANG_OPER_LSHIFT, */
+ /*SLANG_OPER_RSHIFT, */
+ SLANG_OPER_ADD, /* [expr] "+" [expr] */
+ SLANG_OPER_SUBTRACT, /* [expr] "-" [expr] */
+ SLANG_OPER_MULTIPLY, /* [expr] "*" [expr] */
+ SLANG_OPER_DIVIDE, /* [expr] "/" [expr] */
+ /*SLANG_OPER_MODULUS, */
+ SLANG_OPER_PREINCREMENT, /* "++" [var] */
+ SLANG_OPER_PREDECREMENT, /* "--" [var] */
+ SLANG_OPER_PLUS, /* "-" [expr] */
+ SLANG_OPER_MINUS, /* "+" [expr] */
+ /*SLANG_OPER_COMPLEMENT, */
+ SLANG_OPER_NOT, /* "!" [expr] */
+ SLANG_OPER_SUBSCRIPT, /* [expr] "[" [expr] "]" */
+ SLANG_OPER_CALL, /* [func name] [param] [param] [...] */
+ SLANG_OPER_NON_INLINED_CALL, /* a real function call */
+ SLANG_OPER_METHOD, /* method call, such as v.length() */
+ SLANG_OPER_FIELD, /* i.e.: ".next" or ".xzy" or ".xxx" etc */
+ SLANG_OPER_POSTINCREMENT, /* [var] "++" */
+ SLANG_OPER_POSTDECREMENT /* [var] "--" */
+} slang_operation_type;
+
+
+/**
+ * A slang_operation is basically a compiled instruction (such as assignment,
+ * a while-loop, a conditional, a multiply, a function call, etc).
+ * The AST (abstract syntax tree) is built from these nodes.
+ * NOTE: This structure could have been implemented as a union of simpler
+ * structs which would correspond to the operation types above.
+ */
+typedef struct slang_operation_
+{
+ slang_operation_type type;
+ struct slang_operation_ *children;
+ GLuint num_children;
+ GLfloat literal[4]; /**< Used for float, int and bool values */
+ GLuint literal_size; /**< 1, 2, 3, or 4 */
+ slang_atom a_id; /**< type: asm, identifier, call, field */
+ slang_atom a_obj; /**< object in a method call */
+ slang_variable_scope *locals; /**< local vars for scope */
+ struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */
+ struct slang_variable_ *var; /**< If type == slang_oper_identier */
+ struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL */
+ /** If type==SLANG_OPER_CALL and we're calling an array constructor,
+ * for which there's no real function, we need to have a flag to
+ * indicate such. num_children indicates number of elements.
+ */
+ GLboolean array_constructor;
+ double x;
+} slang_operation;
+
+
+extern GLboolean
+slang_operation_construct(slang_operation *);
+
+extern void
+slang_operation_destruct(slang_operation *);
+
+extern void
+slang_replace_scope(slang_operation *oper,
+ slang_variable_scope *oldScope,
+ slang_variable_scope *newScope);
+
+extern GLboolean
+slang_operation_copy(slang_operation *, const slang_operation *);
+
+extern slang_operation *
+slang_operation_new(GLuint count);
+
+extern void
+slang_operation_delete(slang_operation *oper);
+
+extern void
+slang_operation_free_children(slang_operation *oper);
+
+extern slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children);
+
+extern slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+ GLuint pos);
+
+extern slang_operation *
+slang_operation_insert_child(slang_operation *oper, GLuint pos);
+
+extern void
+_slang_operation_swap(slang_operation *oper0, slang_operation *oper1);
+
+
+extern void
+slang_operation_add_children(slang_operation *oper, GLuint num_children);
+
+
+/** Return number of children of given node */
+static INLINE GLuint
+slang_oper_num_children(const slang_operation *oper)
+{
+ return oper->num_children;
+}
+
+/** Return child of given operation node */
+static INLINE slang_operation *
+slang_oper_child(slang_operation *oper, GLuint child)
+{
+ assert(child < oper->num_children);
+ return &oper->children[child];
+}
+
+
+/** Return child of given operation node, const version */
+static INLINE const slang_operation *
+slang_oper_child_const(const slang_operation *oper, GLuint child)
+{
+ assert(child < oper->num_children);
+ return &oper->children[child];
+}
+
+
+/** Init oper to a boolean literal. */
+static INLINE void
+slang_operation_literal_bool(slang_operation *oper, GLboolean value)
+{
+ oper->type = SLANG_OPER_LITERAL_BOOL;
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = (float) value;
+ oper->literal_size = 1;
+}
+
+
+/** Init oper to an int literal. */
+static INLINE void
+slang_operation_literal_int(slang_operation *oper, GLint value)
+{
+ oper->type = SLANG_OPER_LITERAL_INT;
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = (float) value;
+ oper->literal_size = 1;
+}
+
+
+#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_struct.c b/mesalib/src/mesa/shader/slang/slang_compile_struct.c
new file mode 100644
index 000000000..e6c38730d
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_struct.c
@@ -0,0 +1,174 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_compile_struct.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_mem.h"
+#include "slang_compile.h"
+
+
+GLvoid
+_slang_struct_scope_ctr(slang_struct_scope * self)
+{
+ self->structs = NULL;
+ self->num_structs = 0;
+ self->outer_scope = NULL;
+}
+
+void
+slang_struct_scope_destruct(slang_struct_scope * scope)
+{
+ GLuint i;
+
+ for (i = 0; i < scope->num_structs; i++)
+ slang_struct_destruct(scope->structs + i);
+ _slang_free(scope->structs);
+ /* do not free scope->outer_scope */
+}
+
+int
+slang_struct_scope_copy(slang_struct_scope * x, const slang_struct_scope * y)
+{
+ slang_struct_scope z;
+ GLuint i;
+
+ _slang_struct_scope_ctr(&z);
+ z.structs = (slang_struct *)
+ _slang_alloc(y->num_structs * sizeof(slang_struct));
+ if (z.structs == NULL) {
+ slang_struct_scope_destruct(&z);
+ return 0;
+ }
+ for (z.num_structs = 0; z.num_structs < y->num_structs; z.num_structs++)
+ if (!slang_struct_construct(&z.structs[z.num_structs])) {
+ slang_struct_scope_destruct(&z);
+ return 0;
+ }
+ for (i = 0; i < z.num_structs; i++)
+ if (!slang_struct_copy(&z.structs[i], &y->structs[i])) {
+ slang_struct_scope_destruct(&z);
+ return 0;
+ }
+ z.outer_scope = y->outer_scope;
+ slang_struct_scope_destruct(x);
+ *x = z;
+ return 1;
+}
+
+slang_struct *
+slang_struct_scope_find(slang_struct_scope * stru, slang_atom a_name,
+ int all_scopes)
+{
+ GLuint i;
+
+ for (i = 0; i < stru->num_structs; i++)
+ if (a_name == stru->structs[i].a_name)
+ return &stru->structs[i];
+ if (all_scopes && stru->outer_scope != NULL)
+ return slang_struct_scope_find(stru->outer_scope, a_name, 1);
+ return NULL;
+}
+
+/* slang_struct */
+
+int
+slang_struct_construct(slang_struct * stru)
+{
+ stru->a_name = SLANG_ATOM_NULL;
+ stru->fields = (slang_variable_scope *)
+ _slang_alloc(sizeof(slang_variable_scope));
+ if (stru->fields == NULL)
+ return 0;
+ _slang_variable_scope_ctr(stru->fields);
+
+ stru->structs =
+ (slang_struct_scope *) _slang_alloc(sizeof(slang_struct_scope));
+ if (stru->structs == NULL) {
+ slang_variable_scope_destruct(stru->fields);
+ _slang_free(stru->fields);
+ return 0;
+ }
+ _slang_struct_scope_ctr(stru->structs);
+ stru->constructor = NULL;
+ return 1;
+}
+
+void
+slang_struct_destruct(slang_struct * stru)
+{
+ slang_variable_scope_destruct(stru->fields);
+ _slang_free(stru->fields);
+ slang_struct_scope_destruct(stru->structs);
+ _slang_free(stru->structs);
+}
+
+int
+slang_struct_copy(slang_struct * x, const slang_struct * y)
+{
+ slang_struct z;
+
+ if (!slang_struct_construct(&z))
+ return 0;
+ z.a_name = y->a_name;
+ if (!slang_variable_scope_copy(z.fields, y->fields)) {
+ slang_struct_destruct(&z);
+ return 0;
+ }
+ if (!slang_struct_scope_copy(z.structs, y->structs)) {
+ slang_struct_destruct(&z);
+ return 0;
+ }
+ slang_struct_destruct(x);
+ *x = z;
+ return 1;
+}
+
+int
+slang_struct_equal(const slang_struct * x, const slang_struct * y)
+{
+ GLuint i;
+
+ if (x->fields->num_variables != y->fields->num_variables)
+ return 0;
+
+ for (i = 0; i < x->fields->num_variables; i++) {
+ const slang_variable *varx = x->fields->variables[i];
+ const slang_variable *vary = y->fields->variables[i];
+
+ if (varx->a_name != vary->a_name)
+ return 0;
+ if (!slang_type_specifier_equal(&varx->type.specifier,
+ &vary->type.specifier))
+ return 0;
+ if (varx->type.specifier.type == SLANG_SPEC_ARRAY)
+ if (varx->array_len != vary->array_len)
+ return GL_FALSE;
+ }
+ return 1;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_struct.h b/mesalib/src/mesa/shader/slang/slang_compile_struct.h
new file mode 100644
index 000000000..90c5512f4
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_struct.h
@@ -0,0 +1,66 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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 !defined SLANG_COMPILE_STRUCT_H
+#define SLANG_COMPILE_STRUCT_H
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+struct slang_function_;
+
+typedef struct slang_struct_scope_
+{
+ struct slang_struct_ *structs;
+ GLuint num_structs;
+ struct slang_struct_scope_ *outer_scope;
+} slang_struct_scope;
+
+extern GLvoid
+_slang_struct_scope_ctr (slang_struct_scope *);
+
+void slang_struct_scope_destruct (slang_struct_scope *);
+int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *);
+struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int);
+
+typedef struct slang_struct_
+{
+ slang_atom a_name;
+ struct slang_variable_scope_ *fields;
+ slang_struct_scope *structs;
+ struct slang_function_ *constructor;
+} slang_struct;
+
+int slang_struct_construct (slang_struct *);
+void slang_struct_destruct (slang_struct *);
+int slang_struct_copy (slang_struct *, const slang_struct *);
+int slang_struct_equal (const slang_struct *, const slang_struct *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_variable.c b/mesalib/src/mesa/shader/slang/slang_compile_variable.c
new file mode 100644
index 000000000..eab912710
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_variable.c
@@ -0,0 +1,247 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_compile_variable.c
+ * slang front-end compiler
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_mem.h"
+
+
+static slang_variable *
+slang_variable_new(void)
+{
+ slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
+ if (v) {
+ if (!slang_variable_construct(v)) {
+ _slang_free(v);
+ v = NULL;
+ }
+ }
+ return v;
+}
+
+
+static void
+slang_variable_delete(slang_variable * var)
+{
+ slang_variable_destruct(var);
+ _slang_free(var);
+}
+
+
+/*
+ * slang_variable_scope
+ */
+
+slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent)
+{
+ slang_variable_scope *s;
+ s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
+ if (s)
+ s->outer_scope = parent;
+ return s;
+}
+
+
+GLvoid
+_slang_variable_scope_ctr(slang_variable_scope * self)
+{
+ self->variables = NULL;
+ self->num_variables = 0;
+ self->outer_scope = NULL;
+}
+
+void
+slang_variable_scope_destruct(slang_variable_scope * scope)
+{
+ unsigned int i;
+
+ if (!scope)
+ return;
+ for (i = 0; i < scope->num_variables; i++) {
+ if (scope->variables[i])
+ slang_variable_delete(scope->variables[i]);
+ }
+ _slang_free(scope->variables);
+ /* do not free scope->outer_scope */
+}
+
+int
+slang_variable_scope_copy(slang_variable_scope * x,
+ const slang_variable_scope * y)
+{
+ slang_variable_scope z;
+ unsigned int i;
+
+ _slang_variable_scope_ctr(&z);
+ z.variables = (slang_variable **)
+ _slang_alloc(y->num_variables * sizeof(slang_variable *));
+ if (z.variables == NULL) {
+ slang_variable_scope_destruct(&z);
+ return 0;
+ }
+ for (z.num_variables = 0; z.num_variables < y->num_variables;
+ z.num_variables++) {
+ z.variables[z.num_variables] = slang_variable_new();
+ if (!z.variables[z.num_variables]) {
+ slang_variable_scope_destruct(&z);
+ return 0;
+ }
+ }
+ for (i = 0; i < z.num_variables; i++) {
+ if (!slang_variable_copy(z.variables[i], y->variables[i])) {
+ slang_variable_scope_destruct(&z);
+ return 0;
+ }
+ }
+ z.outer_scope = y->outer_scope;
+ slang_variable_scope_destruct(x);
+ *x = z;
+ return 1;
+}
+
+
+/**
+ * Grow the variable list by one.
+ * \return pointer to space for the new variable (will be initialized)
+ */
+slang_variable *
+slang_variable_scope_grow(slang_variable_scope *scope)
+{
+ const int n = scope->num_variables;
+ scope->variables = (slang_variable **)
+ _slang_realloc(scope->variables,
+ n * sizeof(slang_variable *),
+ (n + 1) * sizeof(slang_variable *));
+ if (!scope->variables)
+ return NULL;
+
+ scope->num_variables++;
+
+ scope->variables[n] = slang_variable_new();
+ if (!scope->variables[n])
+ return NULL;
+
+ return scope->variables[n];
+}
+
+
+
+/* slang_variable */
+
+int
+slang_variable_construct(slang_variable * var)
+{
+ if (!slang_fully_specified_type_construct(&var->type))
+ return 0;
+ var->a_name = SLANG_ATOM_NULL;
+ var->array_len = 0;
+ var->initializer = NULL;
+ var->size = 0;
+ var->isTemp = GL_FALSE;
+ var->store = NULL;
+ var->declared = 0;
+ return 1;
+}
+
+
+void
+slang_variable_destruct(slang_variable * var)
+{
+ slang_fully_specified_type_destruct(&var->type);
+ if (var->initializer != NULL) {
+ slang_operation_destruct(var->initializer);
+ _slang_free(var->initializer);
+ }
+#if 0
+ if (var->aux) {
+ _mesa_free(var->aux);
+ }
+#endif
+}
+
+
+int
+slang_variable_copy(slang_variable * x, const slang_variable * y)
+{
+ slang_variable z;
+
+ if (!slang_variable_construct(&z))
+ return 0;
+ if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
+ slang_variable_destruct(&z);
+ return 0;
+ }
+ z.a_name = y->a_name;
+ z.array_len = y->array_len;
+ if (y->initializer != NULL) {
+ z.initializer
+ = (slang_operation *) _slang_alloc(sizeof(slang_operation));
+ if (z.initializer == NULL) {
+ slang_variable_destruct(&z);
+ return 0;
+ }
+ if (!slang_operation_construct(z.initializer)) {
+ _slang_free(z.initializer);
+ slang_variable_destruct(&z);
+ return 0;
+ }
+ if (!slang_operation_copy(z.initializer, y->initializer)) {
+ slang_variable_destruct(&z);
+ return 0;
+ }
+ }
+ z.size = y->size;
+ slang_variable_destruct(x);
+ *x = z;
+ return 1;
+}
+
+
+/**
+ * Search for named variable in given scope.
+ * \param all if true, search parent scopes too.
+ */
+slang_variable *
+_slang_variable_locate(const slang_variable_scope * scope,
+ const slang_atom a_name, GLboolean all)
+{
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_variables; i++)
+ if (a_name == scope->variables[i]->a_name)
+ return scope->variables[i];
+ if (all)
+ scope = scope->outer_scope;
+ else
+ scope = NULL;
+ }
+ return NULL;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_compile_variable.h b/mesalib/src/mesa/shader/slang/slang_compile_variable.h
new file mode 100644
index 000000000..b4585599f
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_compile_variable.h
@@ -0,0 +1,90 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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 SLANG_COMPILE_VARIABLE_H
+#define SLANG_COMPILE_VARIABLE_H
+
+
+struct slang_ir_storage_;
+
+
+/**
+ * A shading language program variable.
+ */
+typedef struct slang_variable_
+{
+ slang_fully_specified_type type; /**< Variable's data type */
+ slang_atom a_name; /**< The variable's name (char *) */
+ GLuint array_len; /**< only if type == SLANG_SPEC_ARRAy */
+ struct slang_operation_ *initializer; /**< Optional initializer code */
+ GLuint size; /**< Variable's size in bytes */
+ GLboolean is_global;
+ GLboolean isTemp; /**< a named temporary (__resultTmp) */
+ GLboolean declared; /**< for debug */
+ struct slang_ir_storage_ *store; /**< Storage for this var */
+} slang_variable;
+
+
+/**
+ * Basically a list of variables, with a pointer to the parent scope.
+ */
+typedef struct slang_variable_scope_
+{
+ slang_variable **variables; /**< Array [num_variables] of ptrs to vars */
+ GLuint num_variables;
+ struct slang_variable_scope_ *outer_scope;
+} slang_variable_scope;
+
+
+extern slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent);
+
+extern GLvoid
+_slang_variable_scope_ctr(slang_variable_scope *);
+
+extern void
+slang_variable_scope_destruct(slang_variable_scope *);
+
+extern int
+slang_variable_scope_copy(slang_variable_scope *,
+ const slang_variable_scope *);
+
+extern slang_variable *
+slang_variable_scope_grow(slang_variable_scope *);
+
+extern int
+slang_variable_construct(slang_variable *);
+
+extern void
+slang_variable_destruct(slang_variable *);
+
+extern int
+slang_variable_copy(slang_variable *, const slang_variable *);
+
+extern slang_variable *
+_slang_variable_locate(const slang_variable_scope *, const slang_atom a_name,
+ GLboolean all);
+
+
+#endif /* SLANG_COMPILE_VARIABLE_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_emit.c b/mesalib/src/mesa/shader/slang/slang_emit.c
new file mode 100644
index 000000000..3f455e064
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_emit.c
@@ -0,0 +1,2518 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2008 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_emit.c
+ * Emit program instructions (PI code) from IR trees.
+ * \author Brian Paul
+ */
+
+/***
+ *** NOTES
+ ***
+ *** To emit GPU instructions, we basically just do an in-order traversal
+ *** of the IR tree.
+ ***/
+
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "slang_builtin.h"
+#include "slang_emit.h"
+#include "slang_mem.h"
+
+
+#define PEEPHOLE_OPTIMIZATIONS 1
+#define ANNOTATE 0
+
+
+typedef struct
+{
+ slang_info_log *log;
+ slang_var_table *vt;
+ struct gl_program *prog;
+ struct gl_program **Subroutines;
+ GLuint NumSubroutines;
+
+ GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */
+
+ GLboolean UnresolvedFunctions;
+
+ /* code-gen options */
+ GLboolean EmitHighLevelInstructions;
+ GLboolean EmitCondCodes;
+ GLboolean EmitComments;
+ GLboolean EmitBeginEndSub; /* XXX TEMPORARY */
+} slang_emit_info;
+
+
+
+static struct gl_program *
+new_subroutine(slang_emit_info *emitInfo, GLuint *id)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const GLuint n = emitInfo->NumSubroutines;
+
+ emitInfo->Subroutines = (struct gl_program **)
+ _mesa_realloc(emitInfo->Subroutines,
+ n * sizeof(struct gl_program),
+ (n + 1) * sizeof(struct gl_program));
+ emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);
+ emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;
+ emitInfo->NumSubroutines++;
+ *id = n;
+ return emitInfo->Subroutines[n];
+}
+
+
+/**
+ * Convert a writemask to a swizzle. Used for testing cond codes because
+ * we only want to test the cond code component(s) that was set by the
+ * previous instruction.
+ */
+static GLuint
+writemask_to_swizzle(GLuint writemask)
+{
+ if (writemask == WRITEMASK_X)
+ return SWIZZLE_XXXX;
+ if (writemask == WRITEMASK_Y)
+ return SWIZZLE_YYYY;
+ if (writemask == WRITEMASK_Z)
+ return SWIZZLE_ZZZZ;
+ if (writemask == WRITEMASK_W)
+ return SWIZZLE_WWWW;
+ return SWIZZLE_XYZW; /* shouldn't be hit */
+}
+
+
+/**
+ * Convert a swizzle mask to a writemask.
+ * Note that the slang_ir_storage->Swizzle field can represent either a
+ * swizzle mask or a writemask, depending on how it's used. For example,
+ * when we parse "direction.yz" alone, we don't know whether .yz is a
+ * writemask or a swizzle. In this case, we encode ".yz" in store->Swizzle
+ * as a swizzle mask (.yz?? actually). Later, if direction.yz is used as
+ * an R-value, we use store->Swizzle as-is. Otherwise, if direction.yz is
+ * used as an L-value, we convert it to a writemask.
+ */
+static GLuint
+swizzle_to_writemask(GLuint swizzle)
+{
+ GLuint i, writemask = 0x0;
+ for (i = 0; i < 4; i++) {
+ GLuint swz = GET_SWZ(swizzle, i);
+ if (swz <= SWIZZLE_W) {
+ writemask |= (1 << swz);
+ }
+ }
+ return writemask;
+}
+
+
+/**
+ * Swizzle a swizzle (function composition).
+ * That is, return swz2(swz1), or said another way: swz1.szw2
+ * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx"
+ */
+GLuint
+_slang_swizzle_swizzle(GLuint swz1, GLuint swz2)
+{
+ GLuint i, swz, s[4];
+ for (i = 0; i < 4; i++) {
+ GLuint c = GET_SWZ(swz2, i);
+ if (c <= SWIZZLE_W)
+ s[i] = GET_SWZ(swz1, c);
+ else
+ s[i] = c;
+ }
+ swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
+ return swz;
+}
+
+
+/**
+ * Return the default swizzle mask for accessing a variable of the
+ * given size (in floats). If size = 1, comp is used to identify
+ * which component [0..3] of the register holds the variable.
+ */
+GLuint
+_slang_var_swizzle(GLint size, GLint comp)
+{
+ switch (size) {
+ case 1:
+ return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL);
+ case 2:
+ return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
+ case 3:
+ return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
+ default:
+ return SWIZZLE_XYZW;
+ }
+}
+
+
+
+/**
+ * Allocate storage for the given node (if it hasn't already been allocated).
+ *
+ * Typically this is temporary storage for an intermediate result (such as
+ * for a multiply or add, etc).
+ *
+ * If n->Store does not exist it will be created and will be of the size
+ * specified by defaultSize.
+ */
+static GLboolean
+alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,
+ GLint defaultSize)
+{
+ assert(!n->Var);
+ if (!n->Store) {
+ assert(defaultSize > 0);
+ n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);
+ }
+
+ /* now allocate actual register(s). I.e. set n->Store->Index >= 0 */
+ if (n->Store->Index < 0) {
+ if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
+ slang_info_log_error(emitInfo->log,
+ "Ran out of registers, too many temporaries");
+ _slang_free(n->Store);
+ n->Store = NULL;
+ return GL_FALSE;
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Free temporary storage, if n->Store is, in fact, temp storage.
+ * Otherwise, no-op.
+ */
+static void
+free_node_storage(slang_var_table *vt, slang_ir_node *n)
+{
+ if (n->Store->File == PROGRAM_TEMPORARY &&
+ n->Store->Index >= 0 &&
+ n->Opcode != IR_SWIZZLE) {
+ if (_slang_is_temp(vt, n->Store)) {
+ _slang_free_temp(vt, n->Store);
+ n->Store->Index = -1;
+ n->Store = NULL; /* XXX this may not be needed */
+ }
+ }
+}
+
+
+/**
+ * Helper function to allocate a short-term temporary.
+ * Free it with _slang_free_temp().
+ */
+static GLboolean
+alloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size)
+{
+ assert(size >= 1);
+ assert(size <= 4);
+ _mesa_bzero(temp, sizeof(*temp));
+ temp->Size = size;
+ temp->File = PROGRAM_TEMPORARY;
+ temp->Index = -1;
+ return _slang_alloc_temp(emitInfo->vt, temp);
+}
+
+
+/**
+ * Remove any SWIZZLE_NIL terms from given swizzle mask.
+ * For a swizzle like .z??? generate .zzzz (replicate single component).
+ * Else, for .wx?? generate .wxzw (insert default component for the position).
+ */
+static GLuint
+fix_swizzle(GLuint swizzle)
+{
+ GLuint c0 = GET_SWZ(swizzle, 0),
+ c1 = GET_SWZ(swizzle, 1),
+ c2 = GET_SWZ(swizzle, 2),
+ c3 = GET_SWZ(swizzle, 3);
+ if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
+ /* smear first component across all positions */
+ c1 = c2 = c3 = c0;
+ }
+ else {
+ /* insert default swizzle components */
+ if (c0 == SWIZZLE_NIL)
+ c0 = SWIZZLE_X;
+ if (c1 == SWIZZLE_NIL)
+ c1 = SWIZZLE_Y;
+ if (c2 == SWIZZLE_NIL)
+ c2 = SWIZZLE_Z;
+ if (c3 == SWIZZLE_NIL)
+ c3 = SWIZZLE_W;
+ }
+ return MAKE_SWIZZLE4(c0, c1, c2, c3);
+}
+
+
+
+/**
+ * Convert IR storage to an instruction dst register.
+ */
+static void
+storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st)
+{
+ const GLboolean relAddr = st->RelAddr;
+ const GLint size = st->Size;
+ GLint index = st->Index;
+ GLuint swizzle = st->Swizzle;
+
+ assert(index >= 0);
+ /* if this is storage relative to some parent storage, walk up the tree */
+ while (st->Parent) {
+ st = st->Parent;
+ assert(st->Index >= 0);
+ index += st->Index;
+ swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
+ }
+
+ assert(st->File != PROGRAM_UNDEFINED);
+ dst->File = st->File;
+
+ assert(index >= 0);
+ dst->Index = index;
+
+ assert(size >= 1);
+ assert(size <= 4);
+
+ if (swizzle != SWIZZLE_XYZW) {
+ dst->WriteMask = swizzle_to_writemask(swizzle);
+ }
+ else {
+ switch (size) {
+ case 1:
+ dst->WriteMask = WRITEMASK_X << GET_SWZ(st->Swizzle, 0);
+ break;
+ case 2:
+ dst->WriteMask = WRITEMASK_XY;
+ break;
+ case 3:
+ dst->WriteMask = WRITEMASK_XYZ;
+ break;
+ case 4:
+ dst->WriteMask = WRITEMASK_XYZW;
+ break;
+ default:
+ ; /* error would have been caught above */
+ }
+ }
+
+ dst->RelAddr = relAddr;
+}
+
+
+/**
+ * Convert IR storage to an instruction src register.
+ */
+static void
+storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
+{
+ const GLboolean relAddr = st->RelAddr;
+ GLint index = st->Index;
+ GLuint swizzle = st->Swizzle;
+
+ /* if this is storage relative to some parent storage, walk up the tree */
+ assert(index >= 0);
+ while (st->Parent) {
+ st = st->Parent;
+ if (st->Index < 0) {
+ /* an error should have been reported already */
+ return;
+ }
+ assert(st->Index >= 0);
+ index += st->Index;
+ swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);
+ }
+
+ assert(st->File >= 0);
+#if 1 /* XXX temporary */
+ if (st->File == PROGRAM_UNDEFINED) {
+ slang_ir_storage *st0 = (slang_ir_storage *) st;
+ st0->File = PROGRAM_TEMPORARY;
+ }
+#endif
+ assert(st->File < PROGRAM_UNDEFINED);
+ src->File = st->File;
+
+ assert(index >= 0);
+ src->Index = index;
+
+ swizzle = fix_swizzle(swizzle);
+ assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
+ src->Swizzle = swizzle;
+
+ src->RelAddr = relAddr;
+}
+
+
+/*
+ * Setup storage pointing to a scalar constant/literal.
+ */
+static void
+constant_to_storage(slang_emit_info *emitInfo,
+ GLfloat val,
+ slang_ir_storage *store)
+{
+ GLuint swizzle;
+ GLint reg;
+ GLfloat value[4];
+
+ value[0] = val;
+ reg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
+ value, 1, &swizzle);
+
+ memset(store, 0, sizeof(*store));
+ store->File = PROGRAM_CONSTANT;
+ store->Index = reg;
+ store->Swizzle = swizzle;
+}
+
+
+/**
+ * Add new instruction at end of given program.
+ * \param prog the program to append instruction onto
+ * \param opcode opcode for the new instruction
+ * \return pointer to the new instruction
+ */
+static struct prog_instruction *
+new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
+{
+ struct gl_program *prog = emitInfo->prog;
+ struct prog_instruction *inst;
+
+#if 0
+ /* print prev inst */
+ if (prog->NumInstructions > 0) {
+ _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
+ }
+#endif
+ assert(prog->NumInstructions <= emitInfo->MaxInstructions);
+
+ if (prog->NumInstructions == emitInfo->MaxInstructions) {
+ /* grow the instruction buffer */
+ emitInfo->MaxInstructions += 20;
+ prog->Instructions =
+ _mesa_realloc_instructions(prog->Instructions,
+ prog->NumInstructions,
+ emitInfo->MaxInstructions);
+ }
+
+ inst = prog->Instructions + prog->NumInstructions;
+ prog->NumInstructions++;
+ _mesa_init_instructions(inst, 1);
+ inst->Opcode = opcode;
+ inst->BranchTarget = -1; /* invalid */
+ /*
+ printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,
+ _mesa_opcode_string(inst->Opcode));
+ */
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_arl_load(slang_emit_info *emitInfo,
+ gl_register_file file, GLint index, GLuint swizzle)
+{
+ struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL);
+ inst->SrcReg[0].File = file;
+ inst->SrcReg[0].Index = index;
+ inst->SrcReg[0].Swizzle = fix_swizzle(swizzle);
+ inst->DstReg.File = PROGRAM_ADDRESS;
+ inst->DstReg.Index = 0;
+ inst->DstReg.WriteMask = WRITEMASK_X;
+ return inst;
+}
+
+
+/**
+ * Emit a new instruction with given opcode, operands.
+ * At this point the instruction may have multiple indirect register
+ * loads/stores. We convert those into ARL loads and address-relative
+ * operands. See comments inside.
+ * At some point in the future we could directly emit indirectly addressed
+ * registers in Mesa GPU instructions.
+ */
+static struct prog_instruction *
+emit_instruction(slang_emit_info *emitInfo,
+ gl_inst_opcode opcode,
+ const slang_ir_storage *dst,
+ const slang_ir_storage *src0,
+ const slang_ir_storage *src1,
+ const slang_ir_storage *src2)
+{
+ struct prog_instruction *inst;
+ GLuint numIndirect = 0;
+ const slang_ir_storage *src[3];
+ slang_ir_storage newSrc[3], newDst;
+ GLuint i;
+ GLboolean isTemp[3];
+
+ isTemp[0] = isTemp[1] = isTemp[2] = GL_FALSE;
+
+ src[0] = src0;
+ src[1] = src1;
+ src[2] = src2;
+
+ /* count up how many operands are indirect loads */
+ for (i = 0; i < 3; i++) {
+ if (src[i] && src[i]->IsIndirect)
+ numIndirect++;
+ }
+ if (dst && dst->IsIndirect)
+ numIndirect++;
+
+ /* Take special steps for indirect register loads.
+ * If we had multiple address registers this would be simpler.
+ * For example, this GLSL code:
+ * x[i] = y[j] + z[k];
+ * would translate into something like:
+ * ARL ADDR.x, i;
+ * ARL ADDR.y, j;
+ * ARL ADDR.z, k;
+ * ADD TEMP[ADDR.x+5], TEMP[ADDR.y+9], TEMP[ADDR.z+4];
+ * But since we currently only have one address register we have to do this:
+ * ARL ADDR.x, i;
+ * MOV t1, TEMP[ADDR.x+9];
+ * ARL ADDR.x, j;
+ * MOV t2, TEMP[ADDR.x+4];
+ * ARL ADDR.x, k;
+ * ADD TEMP[ADDR.x+5], t1, t2;
+ * The code here figures this out...
+ */
+ if (numIndirect > 0) {
+ for (i = 0; i < 3; i++) {
+ if (src[i] && src[i]->IsIndirect) {
+ /* load the ARL register with the indirect register */
+ emit_arl_load(emitInfo,
+ src[i]->IndirectFile,
+ src[i]->IndirectIndex,
+ src[i]->IndirectSwizzle);
+
+ if (numIndirect > 1) {
+ /* Need to load src[i] into a temporary register */
+ slang_ir_storage srcRelAddr;
+ alloc_local_temp(emitInfo, &newSrc[i], src[i]->Size);
+ isTemp[i] = GL_TRUE;
+
+ /* set RelAddr flag on src register */
+ srcRelAddr = *src[i];
+ srcRelAddr.RelAddr = GL_TRUE;
+ srcRelAddr.IsIndirect = GL_FALSE; /* not really needed */
+
+ /* MOV newSrc, srcRelAddr; */
+ inst = emit_instruction(emitInfo,
+ OPCODE_MOV,
+ &newSrc[i],
+ &srcRelAddr,
+ NULL,
+ NULL);
+
+ src[i] = &newSrc[i];
+ }
+ else {
+ /* just rewrite the src[i] storage to be ARL-relative */
+ newSrc[i] = *src[i];
+ newSrc[i].RelAddr = GL_TRUE;
+ newSrc[i].IsIndirect = GL_FALSE; /* not really needed */
+ src[i] = &newSrc[i];
+ }
+ }
+ }
+ }
+
+ /* Take special steps for indirect dest register write */
+ if (dst && dst->IsIndirect) {
+ /* load the ARL register with the indirect register */
+ emit_arl_load(emitInfo,
+ dst->IndirectFile,
+ dst->IndirectIndex,
+ dst->IndirectSwizzle);
+ newDst = *dst;
+ newDst.RelAddr = GL_TRUE;
+ newDst.IsIndirect = GL_FALSE;
+ dst = &newDst;
+ }
+
+ /* OK, emit the instruction and its dst, src regs */
+ inst = new_instruction(emitInfo, opcode);
+ if (!inst)
+ return NULL;
+
+ if (dst)
+ storage_to_dst_reg(&inst->DstReg, dst);
+
+ for (i = 0; i < 3; i++) {
+ if (src[i])
+ storage_to_src_reg(&inst->SrcReg[i], src[i]);
+ }
+
+ /* Free any temp registers that we allocated above */
+ for (i = 0; i < 3; i++) {
+ if (isTemp[i])
+ _slang_free_temp(emitInfo->vt, &newSrc[i]);
+ }
+
+ return inst;
+}
+
+
+
+/**
+ * Put a comment on the given instruction.
+ */
+static void
+inst_comment(struct prog_instruction *inst, const char *comment)
+{
+ if (inst)
+ inst->Comment = _mesa_strdup(comment);
+}
+
+
+
+/**
+ * Return pointer to last instruction in program.
+ */
+static struct prog_instruction *
+prev_instruction(slang_emit_info *emitInfo)
+{
+ struct gl_program *prog = emitInfo->prog;
+ if (prog->NumInstructions == 0)
+ return NULL;
+ else
+ return prog->Instructions + prog->NumInstructions - 1;
+}
+
+
+static struct prog_instruction *
+emit(slang_emit_info *emitInfo, slang_ir_node *n);
+
+
+/**
+ * Return an annotation string for given node's storage.
+ */
+static char *
+storage_annotation(const slang_ir_node *n, const struct gl_program *prog)
+{
+#if ANNOTATE
+ const slang_ir_storage *st = n->Store;
+ static char s[100] = "";
+
+ if (!st)
+ return _mesa_strdup("");
+
+ switch (st->File) {
+ case PROGRAM_CONSTANT:
+ if (st->Index >= 0) {
+ const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
+ if (st->Swizzle == SWIZZLE_NOOP)
+ sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
+ else {
+ sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]);
+ }
+ }
+ break;
+ case PROGRAM_TEMPORARY:
+ if (n->Var)
+ sprintf(s, "%s", (char *) n->Var->a_name);
+ else
+ sprintf(s, "t[%d]", st->Index);
+ break;
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_UNIFORM:
+ sprintf(s, "%s", prog->Parameters->Parameters[st->Index].Name);
+ break;
+ case PROGRAM_VARYING:
+ sprintf(s, "%s", prog->Varying->Parameters[st->Index].Name);
+ break;
+ case PROGRAM_INPUT:
+ sprintf(s, "input[%d]", st->Index);
+ break;
+ case PROGRAM_OUTPUT:
+ sprintf(s, "output[%d]", st->Index);
+ break;
+ default:
+ s[0] = 0;
+ }
+ return _mesa_strdup(s);
+#else
+ return NULL;
+#endif
+}
+
+
+/**
+ * Return an annotation string for an instruction.
+ */
+static char *
+instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
+ char *srcAnnot0, char *srcAnnot1, char *srcAnnot2)
+{
+#if ANNOTATE
+ const char *operator;
+ char *s;
+ int len = 50;
+
+ if (dstAnnot)
+ len += strlen(dstAnnot);
+ else
+ dstAnnot = _mesa_strdup("");
+
+ if (srcAnnot0)
+ len += strlen(srcAnnot0);
+ else
+ srcAnnot0 = _mesa_strdup("");
+
+ if (srcAnnot1)
+ len += strlen(srcAnnot1);
+ else
+ srcAnnot1 = _mesa_strdup("");
+
+ if (srcAnnot2)
+ len += strlen(srcAnnot2);
+ else
+ srcAnnot2 = _mesa_strdup("");
+
+ switch (opcode) {
+ case OPCODE_ADD:
+ operator = "+";
+ break;
+ case OPCODE_SUB:
+ operator = "-";
+ break;
+ case OPCODE_MUL:
+ operator = "*";
+ break;
+ case OPCODE_DP2:
+ operator = "DP2";
+ break;
+ case OPCODE_DP3:
+ operator = "DP3";
+ break;
+ case OPCODE_DP4:
+ operator = "DP4";
+ break;
+ case OPCODE_XPD:
+ operator = "XPD";
+ break;
+ case OPCODE_RSQ:
+ operator = "RSQ";
+ break;
+ case OPCODE_SGT:
+ operator = ">";
+ break;
+ default:
+ operator = ",";
+ }
+
+ s = (char *) malloc(len);
+ sprintf(s, "%s = %s %s %s %s", dstAnnot,
+ srcAnnot0, operator, srcAnnot1, srcAnnot2);
+ assert(_mesa_strlen(s) < len);
+
+ free(dstAnnot);
+ free(srcAnnot0);
+ free(srcAnnot1);
+ free(srcAnnot2);
+
+ return s;
+#else
+ return NULL;
+#endif
+}
+
+
+/**
+ * Emit an instruction that's just a comment.
+ */
+static struct prog_instruction *
+emit_comment(slang_emit_info *emitInfo, const char *comment)
+{
+ struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
+ inst_comment(inst, comment);
+ return inst;
+}
+
+
+/**
+ * Generate code for a simple arithmetic instruction.
+ * Either 1, 2 or 3 operands.
+ */
+static struct prog_instruction *
+emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ const slang_ir_info *info = _slang_ir_info(n->Opcode);
+ struct prog_instruction *inst;
+ GLuint i;
+
+ assert(info);
+ assert(info->InstOpcode != OPCODE_NOP);
+
+#if PEEPHOLE_OPTIMIZATIONS
+ /* Look for MAD opportunity */
+ if (info->NumParams == 2 &&
+ n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) {
+ /* found pattern IR_ADD(IR_MUL(A, B), C) */
+ emit(emitInfo, n->Children[0]->Children[0]); /* A */
+ emit(emitInfo, n->Children[0]->Children[1]); /* B */
+ emit(emitInfo, n->Children[1]); /* C */
+ alloc_node_storage(emitInfo, n, -1); /* dest */
+
+ inst = emit_instruction(emitInfo,
+ OPCODE_MAD,
+ n->Store,
+ n->Children[0]->Children[0]->Store,
+ n->Children[0]->Children[1]->Store,
+ n->Children[1]->Store);
+
+ free_node_storage(emitInfo->vt, n->Children[0]->Children[0]);
+ free_node_storage(emitInfo->vt, n->Children[0]->Children[1]);
+ free_node_storage(emitInfo->vt, n->Children[1]);
+ return inst;
+ }
+
+ if (info->NumParams == 2 &&
+ n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) {
+ /* found pattern IR_ADD(A, IR_MUL(B, C)) */
+ emit(emitInfo, n->Children[0]); /* A */
+ emit(emitInfo, n->Children[1]->Children[0]); /* B */
+ emit(emitInfo, n->Children[1]->Children[1]); /* C */
+ alloc_node_storage(emitInfo, n, -1); /* dest */
+
+ inst = emit_instruction(emitInfo,
+ OPCODE_MAD,
+ n->Store,
+ n->Children[1]->Children[0]->Store,
+ n->Children[1]->Children[1]->Store,
+ n->Children[0]->Store);
+
+ free_node_storage(emitInfo->vt, n->Children[1]->Children[0]);
+ free_node_storage(emitInfo->vt, n->Children[1]->Children[1]);
+ free_node_storage(emitInfo->vt, n->Children[0]);
+ return inst;
+ }
+#endif
+
+ /* gen code for children, may involve temp allocation */
+ for (i = 0; i < info->NumParams; i++) {
+ emit(emitInfo, n->Children[i]);
+ if (!n->Children[i] || !n->Children[i]->Store) {
+ /* error recovery */
+ return NULL;
+ }
+ }
+
+ /* result storage */
+ alloc_node_storage(emitInfo, n, -1);
+
+ inst = emit_instruction(emitInfo,
+ info->InstOpcode,
+ n->Store, /* dest */
+ (info->NumParams > 0 ? n->Children[0]->Store : NULL),
+ (info->NumParams > 1 ? n->Children[1]->Store : NULL),
+ (info->NumParams > 2 ? n->Children[2]->Store : NULL)
+ );
+
+ /* free temps */
+ for (i = 0; i < info->NumParams; i++)
+ free_node_storage(emitInfo->vt, n->Children[i]);
+
+ return inst;
+}
+
+
+/**
+ * Emit code for == and != operators. These could normally be handled
+ * by emit_arith() except we need to be able to handle structure comparisons.
+ */
+static struct prog_instruction *
+emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst = NULL;
+ GLint size;
+
+ assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
+
+ /* gen code for children */
+ emit(emitInfo, n->Children[0]);
+ emit(emitInfo, n->Children[1]);
+
+ if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) {
+ /* XXX this error should have been caught in slang_codegen.c */
+ slang_info_log_error(emitInfo->log, "invalid operands to == or !=");
+ n->Store = NULL;
+ return NULL;
+ }
+
+ /* final result is 1 bool */
+ if (!alloc_node_storage(emitInfo, n, 1))
+ return NULL;
+
+ size = n->Children[0]->Store->Size;
+
+ if (size == 1) {
+ gl_inst_opcode opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
+ inst = emit_instruction(emitInfo,
+ opcode,
+ n->Store, /* dest */
+ n->Children[0]->Store,
+ n->Children[1]->Store,
+ NULL);
+ }
+ else if (size <= 4) {
+ /* compare two vectors.
+ * Unfortunately, there's no instruction to compare vectors and
+ * return a scalar result. Do it with some compare and dot product
+ * instructions...
+ */
+ GLuint swizzle;
+ gl_inst_opcode dotOp;
+ slang_ir_storage tempStore;
+
+ if (!alloc_local_temp(emitInfo, &tempStore, 4)) {
+ n->Store = NULL;
+ return NULL;
+ /* out of temps */
+ }
+
+ if (size == 4) {
+ dotOp = OPCODE_DP4;
+ swizzle = SWIZZLE_XYZW;
+ }
+ else if (size == 3) {
+ dotOp = OPCODE_DP3;
+ swizzle = SWIZZLE_XYZW;
+ }
+ else {
+ assert(size == 2);
+ dotOp = OPCODE_DP3; /* XXX use OPCODE_DP2 eventually */
+ swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
+ }
+
+ /* Compute inequality (temp = (A != B)) */
+ inst = emit_instruction(emitInfo,
+ OPCODE_SNE,
+ &tempStore,
+ n->Children[0]->Store,
+ n->Children[1]->Store,
+ NULL);
+ inst_comment(inst, "Compare values");
+
+ /* Compute val = DOT(temp, temp) (reduction) */
+ inst = emit_instruction(emitInfo,
+ dotOp,
+ n->Store,
+ &tempStore,
+ &tempStore,
+ NULL);
+ inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/
+ inst_comment(inst, "Reduce vec to bool");
+
+ _slang_free_temp(emitInfo->vt, &tempStore); /* free temp */
+
+ if (n->Opcode == IR_EQUAL) {
+ /* compute val = !val.x with SEQ val, val, 0; */
+ slang_ir_storage zero;
+ constant_to_storage(emitInfo, 0.0, &zero);
+ inst = emit_instruction(emitInfo,
+ OPCODE_SEQ,
+ n->Store, /* dest */
+ n->Store,
+ &zero,
+ NULL);
+ inst_comment(inst, "Invert true/false");
+ }
+ }
+ else {
+ /* size > 4, struct or array compare.
+ * XXX this won't work reliably for structs with padding!!
+ */
+ GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
+ slang_ir_storage accTemp, sneTemp;
+
+ if (!alloc_local_temp(emitInfo, &accTemp, 4))
+ return NULL;
+
+ if (!alloc_local_temp(emitInfo, &sneTemp, 4))
+ return NULL;
+
+ for (i = 0; i < num; i++) {
+ slang_ir_storage srcStore0 = *n->Children[0]->Store;
+ slang_ir_storage srcStore1 = *n->Children[1]->Store;
+ srcStore0.Index += i;
+ srcStore1.Index += i;
+
+ if (i == 0) {
+ /* SNE accTemp, left[i], right[i] */
+ inst = emit_instruction(emitInfo, OPCODE_SNE,
+ &accTemp, /* dest */
+ &srcStore0,
+ &srcStore1,
+ NULL);
+ inst_comment(inst, "Begin struct/array comparison");
+ }
+ else {
+ /* SNE sneTemp, left[i], right[i] */
+ inst = emit_instruction(emitInfo, OPCODE_SNE,
+ &sneTemp, /* dest */
+ &srcStore0,
+ &srcStore1,
+ NULL);
+ /* ADD accTemp, accTemp, sneTemp; # like logical-OR */
+ inst = emit_instruction(emitInfo, OPCODE_ADD,
+ &accTemp, /* dest */
+ &accTemp,
+ &sneTemp,
+ NULL);
+ }
+ }
+
+ /* compute accTemp.x || accTemp.y || accTemp.z || accTemp.w with DOT4 */
+ inst = emit_instruction(emitInfo, OPCODE_DP4,
+ n->Store,
+ &accTemp,
+ &accTemp,
+ NULL);
+ inst_comment(inst, "End struct/array comparison");
+
+ if (n->Opcode == IR_EQUAL) {
+ /* compute tmp.x = !tmp.x via tmp.x = (tmp.x == 0) */
+ slang_ir_storage zero;
+ constant_to_storage(emitInfo, 0.0, &zero);
+ inst = emit_instruction(emitInfo, OPCODE_SEQ,
+ n->Store, /* dest */
+ n->Store,
+ &zero,
+ NULL);
+ inst_comment(inst, "Invert true/false");
+ }
+
+ _slang_free_temp(emitInfo->vt, &accTemp);
+ _slang_free_temp(emitInfo->vt, &sneTemp);
+ }
+
+ /* free temps */
+ free_node_storage(emitInfo->vt, n->Children[0]);
+ free_node_storage(emitInfo->vt, n->Children[1]);
+
+ return inst;
+}
+
+
+
+/**
+ * Generate code for an IR_CLAMP instruction.
+ */
+static struct prog_instruction *
+emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+ slang_ir_node tmpNode;
+
+ assert(n->Opcode == IR_CLAMP);
+ /* ch[0] = value
+ * ch[1] = min limit
+ * ch[2] = max limit
+ */
+
+ inst = emit(emitInfo, n->Children[0]);
+
+ /* If lower limit == 0.0 and upper limit == 1.0,
+ * set prev instruction's SaturateMode field to SATURATE_ZERO_ONE.
+ * Else,
+ * emit OPCODE_MIN, OPCODE_MAX sequence.
+ */
+#if 0
+ /* XXX this isn't quite finished yet */
+ if (n->Children[1]->Opcode == IR_FLOAT &&
+ n->Children[1]->Value[0] == 0.0 &&
+ n->Children[1]->Value[1] == 0.0 &&
+ n->Children[1]->Value[2] == 0.0 &&
+ n->Children[1]->Value[3] == 0.0 &&
+ n->Children[2]->Opcode == IR_FLOAT &&
+ n->Children[2]->Value[0] == 1.0 &&
+ n->Children[2]->Value[1] == 1.0 &&
+ n->Children[2]->Value[2] == 1.0 &&
+ n->Children[2]->Value[3] == 1.0) {
+ if (!inst) {
+ inst = prev_instruction(prog);
+ }
+ if (inst && inst->Opcode != OPCODE_NOP) {
+ /* and prev instruction's DstReg matches n->Children[0]->Store */
+ inst->SaturateMode = SATURATE_ZERO_ONE;
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+ }
+#endif
+
+ if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+ return NULL;
+
+ emit(emitInfo, n->Children[1]);
+ emit(emitInfo, n->Children[2]);
+
+ /* Some GPUs don't allow reading from output registers. So if the
+ * dest for this clamp() is an output reg, we can't use that reg for
+ * the intermediate result. Use a temp register instead.
+ */
+ _mesa_bzero(&tmpNode, sizeof(tmpNode));
+ alloc_node_storage(emitInfo, &tmpNode, n->Store->Size);
+
+ /* tmp = max(ch[0], ch[1]) */
+ inst = emit_instruction(emitInfo, OPCODE_MAX,
+ tmpNode.Store, /* dest */
+ n->Children[0]->Store,
+ n->Children[1]->Store,
+ NULL);
+
+ /* n->dest = min(tmp, ch[2]) */
+ inst = emit_instruction(emitInfo, OPCODE_MIN,
+ n->Store, /* dest */
+ tmpNode.Store,
+ n->Children[2]->Store,
+ NULL);
+
+ free_node_storage(emitInfo->vt, &tmpNode);
+
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_negation(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ /* Implement as MOV dst, -src; */
+ /* XXX we could look at the previous instruction and in some circumstances
+ * modify it to accomplish the negation.
+ */
+ struct prog_instruction *inst;
+
+ emit(emitInfo, n->Children[0]);
+
+ if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+ return NULL;
+
+ inst = emit_instruction(emitInfo,
+ OPCODE_MOV,
+ n->Store, /* dest */
+ n->Children[0]->Store,
+ NULL,
+ NULL);
+ inst->SrcReg[0].Negate = NEGATE_XYZW;
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
+{
+ assert(n->Label);
+#if 0
+ /* XXX this fails in loop tail code - investigate someday */
+ assert(_slang_label_get_location(n->Label) < 0);
+ _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+ emitInfo->prog);
+#else
+ if (_slang_label_get_location(n->Label) < 0)
+ _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+ emitInfo->prog);
+#endif
+ return NULL;
+}
+
+
+/**
+ * Emit code for a function call.
+ * Note that for each time a function is called, we emit the function's
+ * body code again because the set of available registers may be different.
+ */
+static struct prog_instruction *
+emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct gl_program *progSave;
+ struct prog_instruction *inst;
+ GLuint subroutineId;
+ GLuint maxInstSave;
+
+ assert(n->Opcode == IR_CALL);
+ assert(n->Label);
+
+ /* save/push cur program */
+ maxInstSave = emitInfo->MaxInstructions;
+ progSave = emitInfo->prog;
+
+ emitInfo->prog = new_subroutine(emitInfo, &subroutineId);
+ emitInfo->MaxInstructions = emitInfo->prog->NumInstructions;
+
+ _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+ emitInfo->prog);
+
+ if (emitInfo->EmitBeginEndSub) {
+ /* BGNSUB isn't a real instruction.
+ * We require a label (i.e. "foobar:") though, if we're going to
+ * print the program in the NV format. The BNGSUB instruction is
+ * really just a NOP to attach the label to.
+ */
+ inst = new_instruction(emitInfo, OPCODE_BGNSUB);
+ inst_comment(inst, n->Label->Name);
+ }
+
+ /* body of function: */
+ emit(emitInfo, n->Children[0]);
+ n->Store = n->Children[0]->Store;
+
+ /* add RET instruction now, if needed */
+ inst = prev_instruction(emitInfo);
+ if (inst && inst->Opcode != OPCODE_RET) {
+ inst = new_instruction(emitInfo, OPCODE_RET);
+ }
+
+ if (emitInfo->EmitBeginEndSub) {
+ inst = new_instruction(emitInfo, OPCODE_ENDSUB);
+ inst_comment(inst, n->Label->Name);
+ }
+
+ /* pop/restore cur program */
+ emitInfo->prog = progSave;
+ emitInfo->MaxInstructions = maxInstSave;
+
+ /* emit the function call */
+ inst = new_instruction(emitInfo, OPCODE_CAL);
+ /* The branch target is just the subroutine number (changed later) */
+ inst->BranchTarget = subroutineId;
+ inst_comment(inst, n->Label->Name);
+ assert(inst->BranchTarget >= 0);
+
+ return inst;
+}
+
+
+/**
+ * Emit code for a 'return' statement.
+ */
+static struct prog_instruction *
+emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+ assert(n);
+ assert(n->Opcode == IR_RETURN);
+ assert(n->Label);
+ inst = new_instruction(emitInfo, OPCODE_RET);
+ inst->DstReg.CondMask = COND_TR; /* always return */
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_kill(slang_emit_info *emitInfo)
+{
+ struct gl_fragment_program *fp;
+ struct prog_instruction *inst;
+ /* NV-KILL - discard fragment depending on condition code.
+ * Note that ARB-KILL depends on sign of vector operand.
+ */
+ inst = new_instruction(emitInfo, OPCODE_KIL_NV);
+ inst->DstReg.CondMask = COND_TR; /* always kill */
+
+ assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+ fp = (struct gl_fragment_program *) emitInfo->prog;
+ fp->UsesKill = GL_TRUE;
+
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+ gl_inst_opcode opcode;
+ GLboolean shadow = GL_FALSE;
+
+ switch (n->Opcode) {
+ case IR_TEX:
+ opcode = OPCODE_TEX;
+ break;
+ case IR_TEX_SH:
+ opcode = OPCODE_TEX;
+ shadow = GL_TRUE;
+ break;
+ case IR_TEXB:
+ opcode = OPCODE_TXB;
+ break;
+ case IR_TEXB_SH:
+ opcode = OPCODE_TXB;
+ shadow = GL_TRUE;
+ break;
+ case IR_TEXP:
+ opcode = OPCODE_TXP;
+ break;
+ case IR_TEXP_SH:
+ opcode = OPCODE_TXP;
+ shadow = GL_TRUE;
+ break;
+ default:
+ _mesa_problem(NULL, "Bad IR TEX code");
+ return NULL;
+ }
+
+ if (n->Children[0]->Opcode == IR_ELEMENT) {
+ /* array is the sampler (a uniform which'll indicate the texture unit) */
+ assert(n->Children[0]->Children[0]->Store);
+ assert(n->Children[0]->Children[0]->Store->File == PROGRAM_SAMPLER);
+
+ emit(emitInfo, n->Children[0]);
+
+ n->Children[0]->Var = n->Children[0]->Children[0]->Var;
+ } else {
+ /* this is the sampler (a uniform which'll indicate the texture unit) */
+ assert(n->Children[0]->Store);
+ assert(n->Children[0]->Store->File == PROGRAM_SAMPLER);
+ }
+
+ /* emit code for the texcoord operand */
+ (void) emit(emitInfo, n->Children[1]);
+
+ /* alloc storage for result of texture fetch */
+ if (!alloc_node_storage(emitInfo, n, 4))
+ return NULL;
+
+ /* emit TEX instruction; Child[1] is the texcoord */
+ inst = emit_instruction(emitInfo,
+ opcode,
+ n->Store,
+ n->Children[1]->Store,
+ NULL,
+ NULL);
+
+ inst->TexShadow = shadow;
+
+ /* Store->Index is the uniform/sampler index */
+ assert(n->Children[0]->Store->Index >= 0);
+ inst->TexSrcUnit = n->Children[0]->Store->Index;
+ inst->TexSrcTarget = n->Children[0]->Store->TexTarget;
+
+ /* mark the sampler as being used */
+ _mesa_use_uniform(emitInfo->prog->Parameters,
+ (char *) n->Children[0]->Var->a_name);
+
+ return inst;
+}
+
+
+/**
+ * Assignment/copy
+ */
+static struct prog_instruction *
+emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+
+ assert(n->Opcode == IR_COPY);
+
+ /* lhs */
+ emit(emitInfo, n->Children[0]);
+ if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
+ /* an error should have been already recorded */
+ return NULL;
+ }
+
+ /* rhs */
+ assert(n->Children[1]);
+ inst = emit(emitInfo, n->Children[1]);
+
+ if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
+ if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) {
+ /* XXX this error should have been caught in slang_codegen.c */
+ slang_info_log_error(emitInfo->log, "invalid assignment");
+ }
+ return NULL;
+ }
+
+ assert(n->Children[1]->Store->Index >= 0);
+
+ /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
+
+ n->Store = n->Children[0]->Store;
+
+ if (n->Store->File == PROGRAM_SAMPLER) {
+ /* no code generated for sampler assignments,
+ * just copy the sampler index/target at compile time.
+ */
+ n->Store->Index = n->Children[1]->Store->Index;
+ n->Store->TexTarget = n->Children[1]->Store->TexTarget;
+ return NULL;
+ }
+
+#if PEEPHOLE_OPTIMIZATIONS
+ if (inst &&
+ (n->Children[1]->Opcode != IR_SWIZZLE) &&
+ _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
+ (inst->DstReg.File == n->Children[1]->Store->File) &&
+ (inst->DstReg.Index == n->Children[1]->Store->Index) &&
+ !n->Children[0]->Store->IsIndirect &&
+ n->Children[0]->Store->Size <= 4) {
+ /* Peephole optimization:
+ * The Right-Hand-Side has its results in a temporary place.
+ * Modify the RHS (and the prev instruction) to store its results
+ * in the destination specified by n->Children[0].
+ * Then, this MOVE is a no-op.
+ * Ex:
+ * MUL tmp, x, y;
+ * MOV a, tmp;
+ * becomes:
+ * MUL a, x, y;
+ */
+
+ /* fixup the previous instruction (which stored the RHS result) */
+ assert(n->Children[0]->Store->Index >= 0);
+ storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store);
+ return inst;
+ }
+ else
+#endif
+ {
+ if (n->Children[0]->Store->Size > 4) {
+ /* move matrix/struct etc (block of registers) */
+ slang_ir_storage dstStore = *n->Children[0]->Store;
+ slang_ir_storage srcStore = *n->Children[1]->Store;
+ GLint size = srcStore.Size;
+ ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);
+ dstStore.Size = 4;
+ srcStore.Size = 4;
+ while (size >= 4) {
+ inst = emit_instruction(emitInfo, OPCODE_MOV,
+ &dstStore,
+ &srcStore,
+ NULL,
+ NULL);
+ inst_comment(inst, "IR_COPY block");
+ srcStore.Index++;
+ dstStore.Index++;
+ size -= 4;
+ }
+ }
+ else {
+ /* single register move */
+ char *srcAnnot, *dstAnnot;
+ assert(n->Children[0]->Store->Index >= 0);
+ inst = emit_instruction(emitInfo, OPCODE_MOV,
+ n->Children[0]->Store, /* dest */
+ n->Children[1]->Store,
+ NULL,
+ NULL);
+ dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);
+ srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);
+ inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,
+ srcAnnot, NULL, NULL);
+ }
+ free_node_storage(emitInfo->vt, n->Children[1]);
+ return inst;
+ }
+}
+
+
+/**
+ * An IR_COND node wraps a boolean expression which is used by an
+ * IF or WHILE test. This is where we'll set condition codes, if needed.
+ */
+static struct prog_instruction *
+emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+
+ assert(n->Opcode == IR_COND);
+
+ if (!n->Children[0])
+ return NULL;
+
+ /* emit code for the expression */
+ inst = emit(emitInfo, n->Children[0]);
+
+ if (!n->Children[0]->Store) {
+ /* error recovery */
+ return NULL;
+ }
+
+ assert(n->Children[0]->Store);
+ /*assert(n->Children[0]->Store->Size == 1);*/
+
+ if (emitInfo->EmitCondCodes) {
+ if (inst &&
+ n->Children[0]->Store &&
+ inst->DstReg.File == n->Children[0]->Store->File &&
+ inst->DstReg.Index == n->Children[0]->Store->Index) {
+ /* The previous instruction wrote to the register who's value
+ * we're testing. Just fix that instruction so that the
+ * condition codes are computed.
+ */
+ inst->CondUpdate = GL_TRUE;
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+ else {
+ /* This'll happen for things like "if (i) ..." where no code
+ * is normally generated for the expression "i".
+ * Generate a move instruction just to set condition codes.
+ */
+ if (!alloc_node_storage(emitInfo, n, 1))
+ return NULL;
+ inst = emit_instruction(emitInfo, OPCODE_MOV,
+ n->Store, /* dest */
+ n->Children[0]->Store,
+ NULL,
+ NULL);
+ inst->CondUpdate = GL_TRUE;
+ inst_comment(inst, "COND expr");
+ _slang_free_temp(emitInfo->vt, n->Store);
+ return inst;
+ }
+ }
+ else {
+ /* No-op: the boolean result of the expression is in a regular reg */
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+}
+
+
+/**
+ * Logical-NOT
+ */
+static struct prog_instruction *
+emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ static const struct {
+ gl_inst_opcode op, opNot;
+ } operators[] = {
+ { OPCODE_SLT, OPCODE_SGE },
+ { OPCODE_SLE, OPCODE_SGT },
+ { OPCODE_SGT, OPCODE_SLE },
+ { OPCODE_SGE, OPCODE_SLT },
+ { OPCODE_SEQ, OPCODE_SNE },
+ { OPCODE_SNE, OPCODE_SEQ },
+ { 0, 0 }
+ };
+ struct prog_instruction *inst;
+ slang_ir_storage zero;
+ GLuint i;
+
+ /* child expr */
+ inst = emit(emitInfo, n->Children[0]);
+
+#if PEEPHOLE_OPTIMIZATIONS
+ if (inst) {
+ /* if the prev instruction was a comparison instruction, invert it */
+ for (i = 0; operators[i].op; i++) {
+ if (inst->Opcode == operators[i].op) {
+ inst->Opcode = operators[i].opNot;
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+ }
+ }
+#endif
+
+ /* else, invert using SEQ (v = v == 0) */
+ if (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))
+ return NULL;
+
+ constant_to_storage(emitInfo, 0.0, &zero);
+ inst = emit_instruction(emitInfo,
+ OPCODE_SEQ,
+ n->Store,
+ n->Children[0]->Store,
+ &zero,
+ NULL);
+ inst_comment(inst, "NOT");
+
+ free_node_storage(emitInfo->vt, n->Children[0]);
+
+ return inst;
+}
+
+
+static struct prog_instruction *
+emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct gl_program *prog = emitInfo->prog;
+ GLuint ifInstLoc, elseInstLoc = 0;
+ GLuint condWritemask = 0;
+
+ /* emit condition expression code */
+ {
+ struct prog_instruction *inst;
+ inst = emit(emitInfo, n->Children[0]);
+ if (emitInfo->EmitCondCodes) {
+ if (!inst) {
+ /* error recovery */
+ return NULL;
+ }
+ condWritemask = inst->DstReg.WriteMask;
+ }
+ }
+
+ if (!n->Children[0]->Store)
+ return NULL;
+
+#if 0
+ assert(n->Children[0]->Store->Size == 1); /* a bool! */
+#endif
+
+ ifInstLoc = prog->NumInstructions;
+ if (emitInfo->EmitHighLevelInstructions) {
+ if (emitInfo->EmitCondCodes) {
+ /* IF condcode THEN ... */
+ struct prog_instruction *ifInst;
+ ifInst = new_instruction(emitInfo, OPCODE_IF);
+ ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ /* only test the cond code (1 of 4) that was updated by the
+ * previous instruction.
+ */
+ ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+ }
+ else {
+ /* IF src[0] THEN ... */
+ emit_instruction(emitInfo, OPCODE_IF,
+ NULL, /* dst */
+ n->Children[0]->Store, /* op0 */
+ NULL,
+ NULL);
+ }
+ }
+ else {
+ /* conditional jump to else, or endif */
+ struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);
+ ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */
+ inst_comment(ifInst, "if zero");
+ ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+ }
+
+ /* if body */
+ emit(emitInfo, n->Children[1]);
+
+ if (n->Children[2]) {
+ /* have else body */
+ elseInstLoc = prog->NumInstructions;
+ if (emitInfo->EmitHighLevelInstructions) {
+ (void) new_instruction(emitInfo, OPCODE_ELSE);
+ }
+ else {
+ /* jump to endif instruction */
+ struct prog_instruction *inst;
+ inst = new_instruction(emitInfo, OPCODE_BRA);
+ inst_comment(inst, "else");
+ inst->DstReg.CondMask = COND_TR; /* always branch */
+ }
+ prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
+ emit(emitInfo, n->Children[2]);
+ }
+ else {
+ /* no else body */
+ prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;
+ }
+
+ if (emitInfo->EmitHighLevelInstructions) {
+ (void) new_instruction(emitInfo, OPCODE_ENDIF);
+ }
+
+ if (n->Children[2]) {
+ prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;
+ }
+ return NULL;
+}
+
+
+static struct prog_instruction *
+emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct gl_program *prog = emitInfo->prog;
+ struct prog_instruction *endInst;
+ GLuint beginInstLoc, tailInstLoc, endInstLoc;
+ slang_ir_node *ir;
+
+ /* emit OPCODE_BGNLOOP */
+ beginInstLoc = prog->NumInstructions;
+ if (emitInfo->EmitHighLevelInstructions) {
+ (void) new_instruction(emitInfo, OPCODE_BGNLOOP);
+ }
+
+ /* body */
+ emit(emitInfo, n->Children[0]);
+
+ /* tail */
+ tailInstLoc = prog->NumInstructions;
+ if (n->Children[1]) {
+ if (emitInfo->EmitComments)
+ emit_comment(emitInfo, "Loop tail code:");
+ emit(emitInfo, n->Children[1]);
+ }
+
+ endInstLoc = prog->NumInstructions;
+ if (emitInfo->EmitHighLevelInstructions) {
+ /* emit OPCODE_ENDLOOP */
+ endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);
+ }
+ else {
+ /* emit unconditional BRA-nch */
+ endInst = new_instruction(emitInfo, OPCODE_BRA);
+ endInst->DstReg.CondMask = COND_TR; /* always true */
+ }
+ /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
+ endInst->BranchTarget = beginInstLoc;
+
+ if (emitInfo->EmitHighLevelInstructions) {
+ /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+ prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;
+ }
+
+ /* Done emitting loop code. Now walk over the loop's linked list of
+ * BREAK and CONT nodes, filling in their BranchTarget fields (which
+ * will point to the ENDLOOP+1 or BGNLOOP instructions, respectively).
+ */
+ for (ir = n->List; ir; ir = ir->List) {
+ struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
+ assert(inst->BranchTarget < 0);
+ if (ir->Opcode == IR_BREAK ||
+ ir->Opcode == IR_BREAK_IF_TRUE) {
+ assert(inst->Opcode == OPCODE_BRK ||
+ inst->Opcode == OPCODE_BRA);
+ /* go to instruction after end of loop */
+ inst->BranchTarget = endInstLoc + 1;
+ }
+ else {
+ assert(ir->Opcode == IR_CONT ||
+ ir->Opcode == IR_CONT_IF_TRUE);
+ assert(inst->Opcode == OPCODE_CONT ||
+ inst->Opcode == OPCODE_BRA);
+ /* go to instruction at tail of loop */
+ inst->BranchTarget = endInstLoc;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Unconditional "continue" or "break" statement.
+ * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
+ */
+static struct prog_instruction *
+emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ gl_inst_opcode opcode;
+ struct prog_instruction *inst;
+
+ if (n->Opcode == IR_CONT) {
+ /* we need to execute the loop's tail code before doing CONT */
+ assert(n->Parent);
+ assert(n->Parent->Opcode == IR_LOOP);
+ if (n->Parent->Children[1]) {
+ /* emit tail code */
+ if (emitInfo->EmitComments) {
+ emit_comment(emitInfo, "continue - tail code:");
+ }
+ emit(emitInfo, n->Parent->Children[1]);
+ }
+ }
+
+ /* opcode selection */
+ if (emitInfo->EmitHighLevelInstructions) {
+ opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+ }
+ else {
+ opcode = OPCODE_BRA;
+ }
+ n->InstLocation = emitInfo->prog->NumInstructions;
+ inst = new_instruction(emitInfo, opcode);
+ inst->DstReg.CondMask = COND_TR; /* always true */
+ return inst;
+}
+
+
+/**
+ * Conditional "continue" or "break" statement.
+ * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
+ */
+static struct prog_instruction *
+emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+
+ assert(n->Opcode == IR_CONT_IF_TRUE ||
+ n->Opcode == IR_BREAK_IF_TRUE);
+
+ /* evaluate condition expr, setting cond codes */
+ inst = emit(emitInfo, n->Children[0]);
+ if (emitInfo->EmitCondCodes) {
+ assert(inst);
+ inst->CondUpdate = GL_TRUE;
+ }
+
+ n->InstLocation = emitInfo->prog->NumInstructions;
+
+ /* opcode selection */
+ if (emitInfo->EmitHighLevelInstructions) {
+ const gl_inst_opcode opcode
+ = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
+ if (emitInfo->EmitCondCodes) {
+ /* Get the writemask from the previous instruction which set
+ * the condcodes. Use that writemask as the CondSwizzle.
+ */
+ const GLuint condWritemask = inst->DstReg.WriteMask;
+ inst = new_instruction(emitInfo, opcode);
+ inst->DstReg.CondMask = COND_NE;
+ inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+ return inst;
+ }
+ else {
+ /* IF reg
+ * BRK/CONT;
+ * ENDIF
+ */
+ GLint ifInstLoc;
+ ifInstLoc = emitInfo->prog->NumInstructions;
+ inst = emit_instruction(emitInfo, OPCODE_IF,
+ NULL, /* dest */
+ n->Children[0]->Store,
+ NULL,
+ NULL);
+ n->InstLocation = emitInfo->prog->NumInstructions;
+
+ inst = new_instruction(emitInfo, opcode);
+ inst = new_instruction(emitInfo, OPCODE_ENDIF);
+
+ emitInfo->prog->Instructions[ifInstLoc].BranchTarget
+ = emitInfo->prog->NumInstructions;
+ return inst;
+ }
+ }
+ else {
+ const GLuint condWritemask = inst->DstReg.WriteMask;
+ assert(emitInfo->EmitCondCodes);
+ inst = new_instruction(emitInfo, OPCODE_BRA);
+ inst->DstReg.CondMask = COND_NE;
+ inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
+ return inst;
+ }
+}
+
+
+/**
+ * Return the size of a swizzle mask given that some swizzle components
+ * may be NIL/undefined. For example:
+ * swizzle_size(".zzxx") = 4
+ * swizzle_size(".xy??") = 2
+ * swizzle_size(".w???") = 1
+ */
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+ GLuint i;
+ for (i = 0; i < 4; i++) {
+ if (GET_SWZ(swizzle, i) == SWIZZLE_NIL)
+ return i;
+ }
+ return 4;
+}
+
+
+static struct prog_instruction *
+emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+
+ inst = emit(emitInfo, n->Children[0]);
+
+ if (!n->Store->Parent) {
+ /* this covers a case such as "(b ? p : q).x" */
+ n->Store->Parent = n->Children[0]->Store;
+ assert(n->Store->Parent);
+ }
+
+ {
+ const GLuint swizzle = n->Store->Swizzle;
+ /* new storage is parent storage with updated Swizzle + Size fields */
+ _slang_copy_ir_storage(n->Store, n->Store->Parent);
+ /* Apply this node's swizzle to parent's storage */
+ n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle);
+ /* Update size */
+ n->Store->Size = swizzle_size(n->Store->Swizzle);
+ }
+
+ assert(!n->Store->Parent);
+ assert(n->Store->Index >= 0);
+
+ return inst;
+}
+
+
+/**
+ * Dereference array element: element == array[index]
+ * This basically involves emitting code for computing the array index
+ * and updating the node/element's storage info.
+ */
+static struct prog_instruction *
+emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ slang_ir_storage *arrayStore, *indexStore;
+ const int elemSize = n->Store->Size; /* number of floats */
+ const GLint elemSizeVec = (elemSize + 3) / 4; /* number of vec4 */
+ struct prog_instruction *inst;
+
+ assert(n->Opcode == IR_ELEMENT);
+ assert(elemSize > 0);
+
+ /* special case for built-in state variables, like light state */
+ {
+ slang_ir_storage *root = n->Store;
+ assert(!root->Parent);
+ while (root->Parent)
+ root = root->Parent;
+
+ if (root->File == PROGRAM_STATE_VAR) {
+ GLboolean direct;
+ GLint index =
+ _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+ if (index < 0) {
+ /* error */
+ return NULL;
+ }
+ if (direct) {
+ n->Store->Index = index;
+ return NULL; /* all done */
+ }
+ }
+ }
+
+ /* do codegen for array itself */
+ emit(emitInfo, n->Children[0]);
+ arrayStore = n->Children[0]->Store;
+
+ /* The initial array element storage is the array's storage,
+ * then modified below.
+ */
+ _slang_copy_ir_storage(n->Store, arrayStore);
+
+
+ if (n->Children[1]->Opcode == IR_FLOAT) {
+ /* Constant array index */
+ const GLint element = (GLint) n->Children[1]->Value[0];
+
+ /* this element's storage is the array's storage, plus constant offset */
+ n->Store->Index += elemSizeVec * element;
+ }
+ else {
+ /* Variable array index */
+
+ /* do codegen for array index expression */
+ emit(emitInfo, n->Children[1]);
+ indexStore = n->Children[1]->Store;
+
+ if (indexStore->IsIndirect) {
+ /* need to put the array index into a temporary since we can't
+ * directly support a[b[i]] constructs.
+ */
+
+
+ /*indexStore = tempstore();*/
+ }
+
+
+ if (elemSize > 4) {
+ /* need to multiply array index by array element size */
+ struct prog_instruction *inst;
+ slang_ir_storage *indexTemp;
+ slang_ir_storage elemSizeStore;
+
+ /* allocate 1 float indexTemp */
+ indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+ _slang_alloc_temp(emitInfo->vt, indexTemp);
+
+ /* allocate a constant containing the element size */
+ constant_to_storage(emitInfo, (float) elemSizeVec, &elemSizeStore);
+
+ /* multiply array index by element size */
+ inst = emit_instruction(emitInfo,
+ OPCODE_MUL,
+ indexTemp, /* dest */
+ indexStore, /* the index */
+ &elemSizeStore,
+ NULL);
+
+ indexStore = indexTemp;
+ }
+
+ if (arrayStore->IsIndirect) {
+ /* ex: in a[i][j], a[i] (the arrayStore) is indirect */
+ /* Need to add indexStore to arrayStore->Indirect store */
+ slang_ir_storage indirectArray;
+ slang_ir_storage *indexTemp;
+
+ _slang_init_ir_storage(&indirectArray,
+ arrayStore->IndirectFile,
+ arrayStore->IndirectIndex,
+ 1,
+ arrayStore->IndirectSwizzle);
+
+ /* allocate 1 float indexTemp */
+ indexTemp = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, 1);
+ _slang_alloc_temp(emitInfo->vt, indexTemp);
+
+ inst = emit_instruction(emitInfo,
+ OPCODE_ADD,
+ indexTemp, /* dest */
+ indexStore, /* the index */
+ &indirectArray, /* indirect array base */
+ NULL);
+
+ indexStore = indexTemp;
+ }
+
+ /* update the array element storage info */
+ n->Store->IsIndirect = GL_TRUE;
+ n->Store->IndirectFile = indexStore->File;
+ n->Store->IndirectIndex = indexStore->Index;
+ n->Store->IndirectSwizzle = indexStore->Swizzle;
+ }
+
+ n->Store->Size = elemSize;
+ n->Store->Swizzle = _slang_var_swizzle(elemSize, 0);
+
+ return NULL; /* no instruction */
+}
+
+
+/**
+ * Resolve storage for accessing a structure field.
+ */
+static struct prog_instruction *
+emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ slang_ir_storage *root = n->Store;
+ GLint fieldOffset, fieldSize;
+
+ assert(n->Opcode == IR_FIELD);
+
+ assert(!root->Parent);
+ while (root->Parent)
+ root = root->Parent;
+
+ /* If this is the field of a state var, allocate constant/uniform
+ * storage for it now if we haven't already.
+ * Note that we allocate storage (uniform/constant slots) for state
+ * variables here rather than at declaration time so we only allocate
+ * space for the ones that we actually use!
+ */
+ if (root->File == PROGRAM_STATE_VAR) {
+ GLboolean direct;
+ GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+ if (index < 0) {
+ slang_info_log_error(emitInfo->log, "Error parsing state variable");
+ return NULL;
+ }
+ if (direct) {
+ root->Index = index;
+ return NULL; /* all done */
+ }
+ }
+
+ /* do codegen for struct */
+ emit(emitInfo, n->Children[0]);
+ assert(n->Children[0]->Store->Index >= 0);
+
+
+ fieldOffset = n->Store->Index;
+ fieldSize = n->Store->Size;
+
+ _slang_copy_ir_storage(n->Store, n->Children[0]->Store);
+
+ n->Store->Index = n->Children[0]->Store->Index + fieldOffset / 4;
+ n->Store->Size = fieldSize;
+
+ switch (fieldSize) {
+ case 1:
+ {
+ GLint swz = fieldOffset % 4;
+ n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
+ }
+ break;
+ case 2:
+ n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_NIL, SWIZZLE_NIL);
+ break;
+ case 3:
+ n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_Z, SWIZZLE_NIL);
+ break;
+ default:
+ n->Store->Swizzle = SWIZZLE_XYZW;
+ }
+
+ assert(n->Store->Index >= 0);
+
+ return NULL; /* no instruction */
+}
+
+
+/**
+ * Emit code for a variable declaration.
+ * This usually doesn't result in any code generation, but just
+ * memory allocation.
+ */
+static struct prog_instruction *
+emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ assert(n->Store);
+ assert(n->Store->File != PROGRAM_UNDEFINED);
+ assert(n->Store->Size > 0);
+ /*assert(n->Store->Index < 0);*/
+
+ if (!n->Var || n->Var->isTemp) {
+ /* a nameless/temporary variable, will be freed after first use */
+ /*NEW*/
+ if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
+ slang_info_log_error(emitInfo->log,
+ "Ran out of registers, too many temporaries");
+ return NULL;
+ }
+ }
+ else {
+ /* a regular variable */
+ _slang_add_variable(emitInfo->vt, n->Var);
+ if (!_slang_alloc_var(emitInfo->vt, n->Store)) {
+ slang_info_log_error(emitInfo->log,
+ "Ran out of registers, too many variables");
+ return NULL;
+ }
+ /*
+ printf("IR_VAR_DECL %s %d store %p\n",
+ (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);
+ */
+ assert(n->Var->store == n->Store);
+ }
+ if (emitInfo->EmitComments) {
+ /* emit NOP with comment describing the variable's storage location */
+ char s[1000];
+ sprintf(s, "TEMP[%d]%s = variable %s (size %d)",
+ n->Store->Index,
+ _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
+ (n->Var ? (char *) n->Var->a_name : "anonymous"),
+ n->Store->Size);
+ emit_comment(emitInfo, s);
+ }
+ return NULL;
+}
+
+
+/**
+ * Emit code for a reference to a variable.
+ * Actually, no code is generated but we may do some memory allocation.
+ * In particular, state vars (uniforms) are allocated on an as-needed basis.
+ */
+static struct prog_instruction *
+emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ assert(n->Store);
+ assert(n->Store->File != PROGRAM_UNDEFINED);
+
+ if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {
+ GLboolean direct;
+ GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters, &direct);
+ if (index < 0) {
+ /* error */
+ char s[100];
+ /* XXX isn't this really an out of memory/resources error? */
+ _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",
+ (char *) n->Var->a_name);
+ slang_info_log_error(emitInfo->log, s);
+ return NULL;
+ }
+
+ n->Store->Index = index;
+ }
+ else if (n->Store->File == PROGRAM_UNIFORM ||
+ n->Store->File == PROGRAM_SAMPLER) {
+ /* mark var as used */
+ _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);
+ }
+ else if (n->Store->File == PROGRAM_INPUT) {
+ assert(n->Store->Index >= 0);
+ emitInfo->prog->InputsRead |= (1 << n->Store->Index);
+ }
+
+ if (n->Store->Index < 0) {
+ /* probably ran out of registers */
+ return NULL;
+ }
+ assert(n->Store->Size > 0);
+
+ return NULL;
+}
+
+
+static struct prog_instruction *
+emit(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+ if (!n)
+ return NULL;
+
+ if (emitInfo->log->error_flag) {
+ return NULL;
+ }
+
+ if (n->Comment) {
+ inst = new_instruction(emitInfo, OPCODE_NOP);
+ inst->Comment = _mesa_strdup(n->Comment);
+ inst = NULL;
+ }
+
+ switch (n->Opcode) {
+ case IR_SEQ:
+ /* sequence of two sub-trees */
+ assert(n->Children[0]);
+ assert(n->Children[1]);
+ emit(emitInfo, n->Children[0]);
+ if (emitInfo->log->error_flag)
+ return NULL;
+ inst = emit(emitInfo, n->Children[1]);
+#if 0
+ assert(!n->Store);
+#endif
+ n->Store = n->Children[1]->Store;
+ return inst;
+
+ case IR_SCOPE:
+ /* new variable scope */
+ _slang_push_var_table(emitInfo->vt);
+ inst = emit(emitInfo, n->Children[0]);
+ _slang_pop_var_table(emitInfo->vt);
+ return inst;
+
+ case IR_VAR_DECL:
+ /* Variable declaration - allocate a register for it */
+ inst = emit_var_decl(emitInfo, n);
+ return inst;
+
+ case IR_VAR:
+ /* Reference to a variable
+ * Storage should have already been resolved/allocated.
+ */
+ return emit_var_ref(emitInfo, n);
+
+ case IR_ELEMENT:
+ return emit_array_element(emitInfo, n);
+ case IR_FIELD:
+ return emit_struct_field(emitInfo, n);
+ case IR_SWIZZLE:
+ return emit_swizzle(emitInfo, n);
+
+ /* Simple arithmetic */
+ /* unary */
+ case IR_MOVE:
+ case IR_RSQ:
+ case IR_RCP:
+ case IR_FLOOR:
+ case IR_FRAC:
+ case IR_F_TO_I:
+ case IR_I_TO_F:
+ case IR_ABS:
+ case IR_SIN:
+ case IR_COS:
+ case IR_DDX:
+ case IR_DDY:
+ case IR_EXP:
+ case IR_EXP2:
+ case IR_LOG2:
+ case IR_NOISE1:
+ case IR_NOISE2:
+ case IR_NOISE3:
+ case IR_NOISE4:
+ case IR_NRM4:
+ case IR_NRM3:
+ /* binary */
+ case IR_ADD:
+ case IR_SUB:
+ case IR_MUL:
+ case IR_DOT4:
+ case IR_DOT3:
+ case IR_DOT2:
+ case IR_CROSS:
+ case IR_MIN:
+ case IR_MAX:
+ case IR_SEQUAL:
+ case IR_SNEQUAL:
+ case IR_SGE:
+ case IR_SGT:
+ case IR_SLE:
+ case IR_SLT:
+ case IR_POW:
+ /* trinary operators */
+ case IR_LRP:
+ return emit_arith(emitInfo, n);
+
+ case IR_EQUAL:
+ case IR_NOTEQUAL:
+ return emit_compare(emitInfo, n);
+
+ case IR_CLAMP:
+ return emit_clamp(emitInfo, n);
+ case IR_TEX:
+ case IR_TEXB:
+ case IR_TEXP:
+ case IR_TEX_SH:
+ case IR_TEXB_SH:
+ case IR_TEXP_SH:
+ return emit_tex(emitInfo, n);
+ case IR_NEG:
+ return emit_negation(emitInfo, n);
+ case IR_FLOAT:
+ /* find storage location for this float constant */
+ n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
+ n->Value,
+ n->Store->Size,
+ &n->Store->Swizzle);
+ if (n->Store->Index < 0) {
+ slang_info_log_error(emitInfo->log, "Ran out of space for constants");
+ return NULL;
+ }
+ return NULL;
+
+ case IR_COPY:
+ return emit_copy(emitInfo, n);
+
+ case IR_COND:
+ return emit_cond(emitInfo, n);
+
+ case IR_NOT:
+ return emit_not(emitInfo, n);
+
+ case IR_LABEL:
+ return emit_label(emitInfo, n);
+
+ case IR_KILL:
+ return emit_kill(emitInfo);
+
+ case IR_CALL:
+ /* new variable scope for subroutines/function calls */
+ _slang_push_var_table(emitInfo->vt);
+ inst = emit_fcall(emitInfo, n);
+ _slang_pop_var_table(emitInfo->vt);
+ return inst;
+
+ case IR_IF:
+ return emit_if(emitInfo, n);
+
+ case IR_LOOP:
+ return emit_loop(emitInfo, n);
+ case IR_BREAK_IF_TRUE:
+ case IR_CONT_IF_TRUE:
+ return emit_cont_break_if_true(emitInfo, n);
+ case IR_BREAK:
+ /* fall-through */
+ case IR_CONT:
+ return emit_cont_break(emitInfo, n);
+
+ case IR_BEGIN_SUB:
+ return new_instruction(emitInfo, OPCODE_BGNSUB);
+ case IR_END_SUB:
+ return new_instruction(emitInfo, OPCODE_ENDSUB);
+ case IR_RETURN:
+ return emit_return(emitInfo, n);
+
+ case IR_NOP:
+ return NULL;
+
+ default:
+ _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
+ }
+ return NULL;
+}
+
+
+/**
+ * After code generation, any subroutines will be in separate program
+ * objects. This function appends all the subroutines onto the main
+ * program and resolves the linking of all the branch/call instructions.
+ * XXX this logic should really be part of the linking process...
+ */
+static void
+_slang_resolve_subroutines(slang_emit_info *emitInfo)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_program *mainP = emitInfo->prog;
+ GLuint *subroutineLoc, i, total;
+
+ subroutineLoc
+ = (GLuint *) _mesa_malloc(emitInfo->NumSubroutines * sizeof(GLuint));
+
+ /* total number of instructions */
+ total = mainP->NumInstructions;
+ for (i = 0; i < emitInfo->NumSubroutines; i++) {
+ subroutineLoc[i] = total;
+ total += emitInfo->Subroutines[i]->NumInstructions;
+ }
+
+ /* adjust BranchTargets within the functions */
+ for (i = 0; i < emitInfo->NumSubroutines; i++) {
+ struct gl_program *sub = emitInfo->Subroutines[i];
+ GLuint j;
+ for (j = 0; j < sub->NumInstructions; j++) {
+ struct prog_instruction *inst = sub->Instructions + j;
+ if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {
+ inst->BranchTarget += subroutineLoc[i];
+ }
+ }
+ }
+
+ /* append subroutines' instructions after main's instructions */
+ mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
+ mainP->NumInstructions,
+ total);
+ mainP->NumInstructions = total;
+ for (i = 0; i < emitInfo->NumSubroutines; i++) {
+ struct gl_program *sub = emitInfo->Subroutines[i];
+ _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
+ sub->Instructions,
+ sub->NumInstructions);
+ /* delete subroutine code */
+ sub->Parameters = NULL; /* prevent double-free */
+ _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);
+ }
+
+ /* free subroutine list */
+ if (emitInfo->Subroutines) {
+ _mesa_free(emitInfo->Subroutines);
+ emitInfo->Subroutines = NULL;
+ }
+ emitInfo->NumSubroutines = 0;
+
+ /* Examine CAL instructions.
+ * At this point, the BranchTarget field of the CAL instruction is
+ * the number/id of the subroutine to call (an index into the
+ * emitInfo->Subroutines list).
+ * Translate that into an actual instruction location now.
+ */
+ for (i = 0; i < mainP->NumInstructions; i++) {
+ struct prog_instruction *inst = mainP->Instructions + i;
+ if (inst->Opcode == OPCODE_CAL) {
+ const GLuint f = inst->BranchTarget;
+ inst->BranchTarget = subroutineLoc[f];
+ }
+ }
+
+ _mesa_free(subroutineLoc);
+}
+
+
+
+/**
+ * Convert the IR tree into GPU instructions.
+ * \param n root of IR tree
+ * \param vt variable table
+ * \param prog program to put GPU instructions into
+ * \param pragmas controls codegen options
+ * \param withEnd if true, emit END opcode at end
+ * \param log log for emitting errors/warnings/info
+ */
+GLboolean
+_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
+ struct gl_program *prog,
+ const struct gl_sl_pragmas *pragmas,
+ GLboolean withEnd,
+ slang_info_log *log)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLboolean success;
+ slang_emit_info emitInfo;
+ GLuint maxUniforms;
+
+ emitInfo.log = log;
+ emitInfo.vt = vt;
+ emitInfo.prog = prog;
+ emitInfo.Subroutines = NULL;
+ emitInfo.NumSubroutines = 0;
+ emitInfo.MaxInstructions = prog->NumInstructions;
+
+ emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
+ emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
+ emitInfo.EmitComments = ctx->Shader.EmitComments || pragmas->Debug;
+ emitInfo.EmitBeginEndSub = GL_TRUE;
+
+ if (!emitInfo.EmitCondCodes) {
+ emitInfo.EmitHighLevelInstructions = GL_TRUE;
+ }
+
+ /* Check uniform/constant limits */
+ if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;
+ }
+ else {
+ assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;
+ }
+ if (prog->Parameters->NumParameters > maxUniforms) {
+ slang_info_log_error(log, "Constant/uniform register limit exceeded "
+ "(max=%u vec4)", maxUniforms);
+
+ return GL_FALSE;
+ }
+
+ (void) emit(&emitInfo, n);
+
+ /* finish up by adding the END opcode to program */
+ if (withEnd) {
+ struct prog_instruction *inst;
+ inst = new_instruction(&emitInfo, OPCODE_END);
+ }
+
+ _slang_resolve_subroutines(&emitInfo);
+
+ success = GL_TRUE;
+
+#if 0
+ printf("*********** End emit code (%u inst):\n", prog->NumInstructions);
+ _mesa_print_program(prog);
+ _mesa_print_program_parameters(ctx,prog);
+#endif
+
+ return success;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_emit.h b/mesalib/src/mesa/shader/slang/slang_emit.h
new file mode 100644
index 000000000..ab4c202d6
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_emit.h
@@ -0,0 +1,51 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2005-2008 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 SLANG_EMIT_H
+#define SLANG_EMIT_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+#include "main/mtypes.h"
+
+
+extern GLuint
+_slang_swizzle_swizzle(GLuint swz1, GLuint swz2);
+
+
+extern GLuint
+_slang_var_swizzle(GLint size, GLint comp);
+
+
+extern GLboolean
+_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
+ struct gl_program *prog,
+ const struct gl_sl_pragmas *pragmas,
+ GLboolean withEnd,
+ slang_info_log *log);
+
+
+#endif /* SLANG_EMIT_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_ir.c b/mesalib/src/mesa/shader/slang/slang_ir.c
new file mode 100644
index 000000000..1c7f7474e
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_ir.c
@@ -0,0 +1,497 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "main/imports.h"
+#include "main/context.h"
+#include "slang_ir.h"
+#include "slang_mem.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_print.h"
+
+
+static const slang_ir_info IrInfo[] = {
+ /* binary ops */
+ { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
+ { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
+ { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
+ { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
+ { IR_DOT4, "IR_DOT4", OPCODE_DP4, 1, 2 },
+ { IR_DOT3, "IR_DOT3", OPCODE_DP3, 1, 2 },
+ { IR_DOT2, "IR_DOT2", OPCODE_DP2, 1, 2 },
+ { IR_NRM4, "IR_NRM4", OPCODE_NRM4, 1, 1 },
+ { IR_NRM3, "IR_NRM3", OPCODE_NRM3, 1, 1 },
+ { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
+ { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 },
+ { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
+ { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+ { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */
+ { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
+ { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
+ { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
+ { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
+ { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 },
+ { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 },
+ { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+ { IR_EQUAL, "IR_EQUAL", OPCODE_NOP, 1, 2 },
+ { IR_NOTEQUAL, "IR_NOTEQUAL", OPCODE_NOP, 1, 2 },
+
+ /* unary ops */
+ { IR_MOVE, "IR_MOVE", OPCODE_MOV, 4, 1 },
+ { IR_I_TO_F, "IR_I_TO_F", OPCODE_MOV, 4, 1 }, /* int[4] to float[4] */
+ { IR_F_TO_I, "IR_F_TO_I", OPCODE_TRUNC, 4, 1 },
+ { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
+ { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
+ { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
+ { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
+ { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
+ { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
+ { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
+ { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+ { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */
+ { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 },
+ { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 },
+ { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
+ { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
+ { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 },
+ { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 },
+ { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 },
+ { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 },
+
+ /* other */
+ { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 },
+ { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 },
+ { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 },
+ { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
+ { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
+ { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
+ { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
+ { IR_COPY, "IR_COPY", OPCODE_NOP, 0, 1 },
+ { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 },
+ { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 },
+ { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 },
+ { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 },
+ { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 },
+ { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 },
+ { IR_TEX_SH, "IR_TEX_SH", OPCODE_TEX, 4, 1 },
+ { IR_TEXB_SH, "IR_TEXB_SH", OPCODE_TXB, 4, 1 },
+ { IR_TEXP_SH, "IR_TEXP_SH", OPCODE_TXP, 4, 1 },
+ { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */
+ { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 },
+ { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 },
+ { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 },
+ { IR_NOP, "IR_NOP", OPCODE_NOP, 0, 0 },
+ { 0, NULL, 0, 0, 0 }
+};
+
+
+const slang_ir_info *
+_slang_ir_info(slang_ir_opcode opcode)
+{
+ GLuint i;
+ for (i = 0; IrInfo[i].IrName; i++) {
+ if (IrInfo[i].IrOpcode == opcode) {
+ return IrInfo + i;
+ }
+ }
+ return NULL;
+}
+
+
+void
+_slang_init_ir_storage(slang_ir_storage *st,
+ gl_register_file file, GLint index, GLint size,
+ GLuint swizzle)
+{
+ st->File = file;
+ st->Index = index;
+ st->Size = size;
+ st->Swizzle = swizzle;
+ st->Parent = NULL;
+ st->IsIndirect = GL_FALSE;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size)
+{
+ slang_ir_storage *st;
+ st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+ if (st) {
+ st->File = file;
+ st->Index = index;
+ st->Size = size;
+ st->Swizzle = SWIZZLE_NOOP;
+ st->Parent = NULL;
+ st->IsIndirect = GL_FALSE;
+ }
+ return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
+ GLuint swizzle)
+{
+ slang_ir_storage *st;
+ st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+ if (st) {
+ st->File = file;
+ st->Index = index;
+ st->Size = size;
+ st->Swizzle = swizzle;
+ st->Parent = NULL;
+ st->IsIndirect = GL_FALSE;
+ }
+ return st;
+}
+
+
+/**
+ * Return a new slang_ir_storage object.
+ */
+slang_ir_storage *
+_slang_new_ir_storage_relative(GLint index, GLint size,
+ slang_ir_storage *parent)
+{
+ slang_ir_storage *st;
+ st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+ if (st) {
+ st->File = PROGRAM_UNDEFINED;
+ st->Index = index;
+ st->Size = size;
+ st->Swizzle = SWIZZLE_NOOP;
+ st->Parent = parent;
+ st->IsIndirect = GL_FALSE;
+ }
+ return st;
+}
+
+
+slang_ir_storage *
+_slang_new_ir_storage_indirect(gl_register_file file,
+ GLint index,
+ GLint size,
+ gl_register_file indirectFile,
+ GLint indirectIndex,
+ GLuint indirectSwizzle)
+{
+ slang_ir_storage *st;
+ st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
+ if (st) {
+ st->File = file;
+ st->Index = index;
+ st->Size = size;
+ st->Swizzle = SWIZZLE_NOOP;
+ st->IsIndirect = GL_TRUE;
+ st->IndirectFile = indirectFile;
+ st->IndirectIndex = indirectIndex;
+ st->IndirectSwizzle = indirectSwizzle;
+ }
+ return st;
+}
+
+
+/**
+ * Allocate IR storage for a texture sampler.
+ * \param sampNum the sampler number/index
+ * \param texTarget one of TEXTURE_x_INDEX values
+ * \param size number of samplers (in case of sampler array)
+ */
+slang_ir_storage *
+_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size)
+{
+ slang_ir_storage *st;
+ assert(texTarget < NUM_TEXTURE_TARGETS);
+ st = _slang_new_ir_storage(PROGRAM_SAMPLER, sampNum, size);
+ if (st) {
+ st->TexTarget = texTarget;
+ }
+ return st;
+}
+
+
+
+/* XXX temporary function */
+void
+_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src)
+{
+ *dst = *src;
+ dst->Parent = NULL;
+}
+
+
+
+static const char *
+_slang_ir_name(slang_ir_opcode opcode)
+{
+ return _slang_ir_info(opcode)->IrName;
+}
+
+
+
+#if 0 /* no longer needed with mempool */
+/**
+ * Since many IR nodes might point to the same IR storage info, we need
+ * to be careful when deleting things.
+ * Before deleting an IR tree, traverse it and do refcounting on the
+ * IR storage nodes. Use the refcount info during delete to free things
+ * properly.
+ */
+static void
+_slang_refcount_storage(slang_ir_node *n)
+{
+ GLuint i;
+ if (!n)
+ return;
+ if (n->Store)
+ n->Store->RefCount++;
+ for (i = 0; i < 3; i++)
+ _slang_refcount_storage(n->Children[i]);
+}
+#endif
+
+
+static void
+_slang_free_ir(slang_ir_node *n)
+{
+ GLuint i;
+ if (!n)
+ return;
+
+#if 0
+ if (n->Store) {
+ n->Store->RefCount--;
+ if (n->Store->RefCount == 0) {
+ _slang_free(n->Store);
+ n->Store = NULL;
+ }
+ }
+#endif
+
+ for (i = 0; i < 3; i++)
+ _slang_free_ir(n->Children[i]);
+ /* Do not free n->List since it's a child elsewhere */
+ _slang_free(n);
+}
+
+
+/**
+ * Recursively free an IR tree.
+ */
+void
+_slang_free_ir_tree(slang_ir_node *n)
+{
+#if 0
+ _slang_refcount_storage(n);
+#endif
+ _slang_free_ir(n);
+}
+
+
+static const char *
+storage_string(const slang_ir_storage *st)
+{
+ static const char *files[] = {
+ "TEMP",
+ "LOCAL_PARAM",
+ "ENV_PARAM",
+ "STATE",
+ "INPUT",
+ "OUTPUT",
+ "NAMED_PARAM",
+ "CONSTANT",
+ "UNIFORM",
+ "VARYING",
+ "WRITE_ONLY",
+ "ADDRESS",
+ "SAMPLER",
+ "UNDEFINED"
+ };
+ static char s[100];
+ assert(Elements(files) == PROGRAM_FILE_MAX);
+#if 0
+ if (st->Size == 1)
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
+ else
+ sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
+ st->Index + st->Size - 1);
+#endif
+ assert(st->File < (GLint) (sizeof(files) / sizeof(files[0])));
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
+ return s;
+}
+
+
+static void
+spaces(int n)
+{
+ while (n-- > 0) {
+ printf(" ");
+ }
+}
+
+
+void
+_slang_print_ir_tree(const slang_ir_node *n, int indent)
+{
+#define IND 0
+
+ if (!n)
+ return;
+#if !IND
+ if (n->Opcode != IR_SEQ)
+#else
+ printf("%3d:", indent);
+#endif
+ spaces(indent);
+
+ switch (n->Opcode) {
+ case IR_SEQ:
+#if IND
+ printf("SEQ at %p\n", (void*) n);
+#endif
+ assert(n->Children[0]);
+ assert(n->Children[1]);
+ _slang_print_ir_tree(n->Children[0], indent + IND);
+ _slang_print_ir_tree(n->Children[1], indent + IND);
+ break;
+ case IR_SCOPE:
+ printf("NEW SCOPE\n");
+ assert(!n->Children[1]);
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+ case IR_COPY:
+ printf("COPY\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ break;
+ case IR_LABEL:
+ printf("LABEL: %s\n", n->Label->Name);
+ break;
+ case IR_COND:
+ printf("COND\n");
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+
+ case IR_IF:
+ printf("IF \n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ spaces(indent);
+ printf("THEN\n");
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ if (n->Children[2]) {
+ spaces(indent);
+ printf("ELSE\n");
+ _slang_print_ir_tree(n->Children[2], indent+3);
+ }
+ spaces(indent);
+ printf("ENDIF\n");
+ break;
+
+ case IR_BEGIN_SUB:
+ printf("BEGIN_SUB\n");
+ break;
+ case IR_END_SUB:
+ printf("END_SUB\n");
+ break;
+ case IR_RETURN:
+ printf("RETURN\n");
+ break;
+ case IR_CALL:
+ printf("CALL %s\n", n->Label->Name);
+ break;
+
+ case IR_LOOP:
+ printf("LOOP\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ if (n->Children[1]) {
+ spaces(indent);
+ printf("TAIL:\n");
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ }
+ spaces(indent);
+ printf("ENDLOOP\n");
+ break;
+ case IR_CONT:
+ printf("CONT\n");
+ break;
+ case IR_BREAK:
+ printf("BREAK\n");
+ break;
+ case IR_BREAK_IF_TRUE:
+ printf("BREAK_IF_TRUE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_CONT_IF_TRUE:
+ printf("CONT_IF_TRUE\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+
+ case IR_VAR:
+ printf("VAR %s%s at %s store %p\n",
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
+ storage_string(n->Store), (void*) n->Store);
+ break;
+ case IR_VAR_DECL:
+ printf("VAR_DECL %s (%p) at %s store %p\n",
+ (n->Var ? (char *) n->Var->a_name : "TEMP"),
+ (void*) n->Var, storage_string(n->Store),
+ (void*) n->Store);
+ break;
+ case IR_FIELD:
+ printf("FIELD %s of\n", n->Field);
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_FLOAT:
+ printf("FLOAT %g %g %g %g\n",
+ n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
+ break;
+ case IR_I_TO_F:
+ printf("INT_TO_FLOAT\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_F_TO_I:
+ printf("FLOAT_TO_INT\n");
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ break;
+ case IR_SWIZZLE:
+ printf("SWIZZLE %s of (store %p) \n",
+ _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
+ _slang_print_ir_tree(n->Children[0], indent + 3);
+ break;
+ default:
+ printf("%s (%p, %p) (store %p)\n", _slang_ir_name(n->Opcode),
+ (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
+ _slang_print_ir_tree(n->Children[0], indent+3);
+ _slang_print_ir_tree(n->Children[1], indent+3);
+ }
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_ir.h b/mesalib/src/mesa/shader/slang/slang_ir.h
new file mode 100644
index 000000000..e796693ed
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_ir.h
@@ -0,0 +1,279 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_ir.h
+ * Mesa GLSL Intermediate Representation tree types and constants.
+ * \author Brian Paul
+ */
+
+
+#ifndef SLANG_IR_H
+#define SLANG_IR_H
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_label.h"
+#include "main/mtypes.h"
+
+
+/**
+ * Intermediate Representation opcodes
+ */
+typedef enum
+{
+ IR_NOP = 0,
+ IR_SEQ, /* sequence (eval left, then right) */
+ IR_SCOPE, /* new variable scope (one child) */
+
+ IR_LABEL, /* target of a jump or cjump */
+
+ IR_COND, /* conditional expression/predicate */
+
+ IR_IF, /* high-level IF/then/else */
+ /* Children[0] = conditional expression */
+ /* Children[1] = if-true part */
+ /* Children[2] = if-else part, or NULL */
+
+ IR_BEGIN_SUB, /* begin subroutine */
+ IR_END_SUB, /* end subroutine */
+ IR_RETURN, /* return from subroutine */
+ IR_CALL, /* call subroutine */
+
+ IR_LOOP, /* high-level loop-begin / loop-end */
+ /* Children[0] = loop body */
+ /* Children[1] = loop tail code, or NULL */
+
+ IR_CONT, /* continue loop */
+ /* n->Parent = ptr to parent IR_LOOP Node */
+ IR_BREAK, /* break loop */
+
+ IR_BREAK_IF_TRUE, /**< Children[0] = the condition expression */
+ IR_CONT_IF_TRUE,
+
+ IR_COPY, /**< assignment/copy */
+ IR_MOVE, /**< assembly MOV instruction */
+
+ /* vector ops: */
+ IR_ADD, /**< assembly ADD instruction */
+ IR_SUB,
+ IR_MUL,
+ IR_DIV,
+ IR_DOT4,
+ IR_DOT3,
+ IR_DOT2,
+ IR_NRM4,
+ IR_NRM3,
+ IR_CROSS, /* vec3 cross product */
+ IR_LRP,
+ IR_CLAMP,
+ IR_MIN,
+ IR_MAX,
+ IR_SEQUAL, /* Set if args are equal (vector) */
+ IR_SNEQUAL, /* Set if args are not equal (vector) */
+ IR_SGE, /* Set if greater or equal (vector) */
+ IR_SGT, /* Set if greater than (vector) */
+ IR_SLE, /* Set if less or equal (vector) */
+ IR_SLT, /* Set if less than (vector) */
+ IR_POW, /* x^y */
+ IR_EXP, /* e^x */
+ IR_EXP2, /* 2^x */
+ IR_LOG2, /* log base 2 */
+ IR_RSQ, /* 1/sqrt() */
+ IR_RCP, /* reciprocol */
+ IR_FLOOR,
+ IR_FRAC,
+ IR_ABS, /* absolute value */
+ IR_NEG, /* negate */
+ IR_DDX, /* derivative w.r.t. X */
+ IR_DDY, /* derivative w.r.t. Y */
+ IR_SIN, /* sine */
+ IR_COS, /* cosine */
+ IR_NOISE1, /* noise(x) */
+ IR_NOISE2, /* noise(x, y) */
+ IR_NOISE3, /* noise(x, y, z) */
+ IR_NOISE4, /* noise(x, y, z, w) */
+
+ IR_EQUAL, /* boolean equality */
+ IR_NOTEQUAL,/* boolean inequality */
+ IR_NOT, /* boolean not */
+
+ IR_VAR, /* variable reference */
+ IR_VAR_DECL,/* var declaration */
+
+ IR_ELEMENT, /* array element */
+ IR_FIELD, /* struct field */
+ IR_SWIZZLE, /* swizzled storage access */
+
+ IR_TEX, /* texture lookup */
+ IR_TEXB, /* texture lookup with LOD bias */
+ IR_TEXP, /* texture lookup with projection */
+
+ IR_TEX_SH, /* texture lookup, shadow compare */
+ IR_TEXB_SH, /* texture lookup with LOD bias, shadow compare */
+ IR_TEXP_SH, /* texture lookup with projection, shadow compare */
+
+ IR_FLOAT,
+ IR_I_TO_F, /* int[4] to float[4] conversion */
+ IR_F_TO_I, /* float[4] to int[4] conversion */
+
+ IR_KILL /* fragment kill/discard */
+} slang_ir_opcode;
+
+
+/**
+ * Describes where data/variables are stored in the various register files.
+ *
+ * In the simple case, the File, Index and Size fields indicate where
+ * a variable is stored. For example, a vec3 variable may be stored
+ * as (File=PROGRAM_TEMPORARY, Index=6, Size=3). Or, File[Index].
+ * Or, a program input like color may be stored as
+ * (File=PROGRAM_INPUT,Index=3,Size=4);
+ *
+ * For single-float values, the Swizzle field indicates which component
+ * of the vector contains the float.
+ *
+ * If IsIndirect is set, the storage is accessed through an indirect
+ * register lookup. The value in question will be located at:
+ * File[Index + IndirectFile[IndirectIndex]]
+ *
+ * This is primary used for indexing arrays. For example, consider this
+ * GLSL code:
+ * uniform int i;
+ * float a[10];
+ * float x = a[i];
+ *
+ * here, storage for a[i] would be described by (File=PROGRAM_TEMPORAY,
+ * Index=aPos, IndirectFile=PROGRAM_UNIFORM, IndirectIndex=iPos), which
+ * would mean TEMP[aPos + UNIFORM[iPos]]
+ */
+struct slang_ir_storage_
+{
+ gl_register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
+ GLint Index; /**< -1 means unallocated */
+ GLint Size; /**< number of floats or ints */
+ GLuint Swizzle; /**< Swizzle AND writemask info */
+ GLint RefCount; /**< Used during IR tree delete */
+
+ GLboolean RelAddr; /* we'll remove this eventually */
+
+ GLboolean IsIndirect;
+ gl_register_file IndirectFile;
+ GLint IndirectIndex;
+ GLuint IndirectSwizzle;
+ GLuint TexTarget; /**< If File==PROGRAM_SAMPLER, one of TEXTURE_x_INDEX */
+
+ /** If Parent is non-null, Index is relative to parent.
+ * The other fields are ignored.
+ */
+ struct slang_ir_storage_ *Parent;
+};
+
+typedef struct slang_ir_storage_ slang_ir_storage;
+
+
+/**
+ * Intermediate Representation (IR) tree node
+ * Basically a binary tree, but IR_LRP and IR_CLAMP have three children.
+ */
+typedef struct slang_ir_node_
+{
+ slang_ir_opcode Opcode;
+ struct slang_ir_node_ *Children[3];
+ slang_ir_storage *Store; /**< location of result of this operation */
+ GLint InstLocation; /**< Location of instruction emitted for this node */
+
+ /** special fields depending on Opcode: */
+ const char *Field; /**< If Opcode == IR_FIELD */
+ GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
+ slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
+ struct slang_ir_node_ *List; /**< For various linked lists */
+ struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */
+ slang_label *Label; /**< Used for branches */
+ const char *Comment; /**< If Opcode == IR_COMMENT */
+} slang_ir_node;
+
+
+
+/**
+ * Assembly and IR info
+ */
+typedef struct
+{
+ slang_ir_opcode IrOpcode;
+ const char *IrName;
+ gl_inst_opcode InstOpcode;
+ GLuint ResultSize, NumParams;
+} slang_ir_info;
+
+
+
+extern const slang_ir_info *
+_slang_ir_info(slang_ir_opcode opcode);
+
+
+extern void
+_slang_init_ir_storage(slang_ir_storage *st,
+ gl_register_file file, GLint index, GLint size,
+ GLuint swizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage(gl_register_file file, GLint index, GLint size);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage_swz(gl_register_file file, GLint index, GLint size,
+ GLuint swizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage_relative(GLint index, GLint size,
+ slang_ir_storage *parent);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage_indirect(gl_register_file file,
+ GLint index,
+ GLint size,
+ gl_register_file indirectFile,
+ GLint indirectIndex,
+ GLuint indirectSwizzle);
+
+extern slang_ir_storage *
+_slang_new_ir_storage_sampler(GLint sampNum, GLuint texTarget, GLint size);
+
+
+extern void
+_slang_copy_ir_storage(slang_ir_storage *dst, const slang_ir_storage *src);
+
+
+extern void
+_slang_free_ir_tree(slang_ir_node *n);
+
+
+extern void
+_slang_print_ir_tree(const slang_ir_node *n, int indent);
+
+
+#endif /* SLANG_IR_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_label.c b/mesalib/src/mesa/shader/slang/slang_label.c
new file mode 100644
index 000000000..1ca1ef0c7
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_label.c
@@ -0,0 +1,104 @@
+
+
+/**
+ * Functions for managing instruction labels.
+ * Basically, this is used to manage the problem of forward branches where
+ * we have a branch instruciton but don't know the target address yet.
+ */
+
+
+#include "slang_label.h"
+#include "slang_mem.h"
+
+
+
+slang_label *
+_slang_label_new(const char *name)
+{
+ slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
+ if (l) {
+ l->Name = _slang_strdup(name);
+ l->Location = -1;
+ }
+ return l;
+}
+
+/**
+ * As above, but suffix the name with a unique number.
+ */
+slang_label *
+_slang_label_new_unique(const char *name)
+{
+ static int id = 1;
+ slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label));
+ if (l) {
+ l->Name = (char *) _slang_alloc(_mesa_strlen(name) + 10);
+ if (!l->Name) {
+ _mesa_free(l);
+ return NULL;
+ }
+ _mesa_sprintf(l->Name, "%s_%d", name, id);
+ id++;
+ l->Location = -1;
+ }
+ return l;
+}
+
+void
+_slang_label_delete(slang_label *l)
+{
+ if (l->Name) {
+ _slang_free(l->Name);
+ l->Name = NULL;
+ }
+ if (l->References) {
+ _slang_free(l->References);
+ l->References = NULL;
+ }
+ _slang_free(l);
+}
+
+
+void
+_slang_label_add_reference(slang_label *l, GLuint inst)
+{
+ const GLuint oldSize = l->NumReferences * sizeof(GLuint);
+ assert(l->Location < 0);
+ l->References = _slang_realloc(l->References,
+ oldSize, oldSize + sizeof(GLuint));
+ if (l->References) {
+ l->References[l->NumReferences] = inst;
+ l->NumReferences++;
+ }
+}
+
+
+GLint
+_slang_label_get_location(const slang_label *l)
+{
+ return l->Location;
+}
+
+
+void
+_slang_label_set_location(slang_label *l, GLint location,
+ struct gl_program *prog)
+{
+ GLuint i;
+
+ assert(l->Location < 0);
+ assert(location >= 0);
+
+ l->Location = location;
+
+ /* for the instructions that were waiting to learn the label's location: */
+ for (i = 0; i < l->NumReferences; i++) {
+ const GLuint j = l->References[i];
+ prog->Instructions[j].BranchTarget = location;
+ }
+
+ if (l->References) {
+ _slang_free(l->References);
+ l->References = NULL;
+ }
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_label.h b/mesalib/src/mesa/shader/slang/slang_label.h
new file mode 100644
index 000000000..87068ae7a
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_label.h
@@ -0,0 +1,45 @@
+#ifndef SLANG_LABEL_H
+#define SLANG_LABEL_H 1
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "shader/prog_instruction.h"
+
+
+struct slang_label_
+{
+ char *Name;
+ GLint Location;
+ /**
+ * List of instruction references (numbered starting at zero) which need
+ * their BranchTarget field filled in with the location eventually
+ * assigned to the label.
+ */
+ GLuint NumReferences;
+ GLuint *References; /** Array [NumReferences] */
+};
+
+typedef struct slang_label_ slang_label;
+
+
+extern slang_label *
+_slang_label_new(const char *name);
+
+extern slang_label *
+_slang_label_new_unique(const char *name);
+
+extern void
+_slang_label_delete(slang_label *l);
+
+extern void
+_slang_label_add_reference(slang_label *l, GLuint inst);
+
+extern GLint
+_slang_label_get_location(const slang_label *l);
+
+extern void
+_slang_label_set_location(slang_label *l, GLint location,
+ struct gl_program *prog);
+
+
+#endif /* SLANG_LABEL_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_link.c b/mesalib/src/mesa/shader/slang/slang_link.c
new file mode 100644
index 000000000..8f2b40d5d
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_link.c
@@ -0,0 +1,898 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_link.c
+ * GLSL linker
+ * \author Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/hash.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+#include "shader/prog_uniform.h"
+#include "shader/shader_api.h"
+#include "slang_builtin.h"
+#include "slang_link.h"
+
+
+/** cast wrapper */
+static struct gl_vertex_program *
+vertex_program(struct gl_program *prog)
+{
+ assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
+ return (struct gl_vertex_program *) prog;
+}
+
+
+/** cast wrapper */
+static struct gl_fragment_program *
+fragment_program(struct gl_program *prog)
+{
+ assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+ return (struct gl_fragment_program *) prog;
+}
+
+
+/**
+ * Record a linking error.
+ */
+static void
+link_error(struct gl_shader_program *shProg, const char *msg)
+{
+ if (shProg->InfoLog) {
+ _mesa_free(shProg->InfoLog);
+ }
+ shProg->InfoLog = _mesa_strdup(msg);
+ shProg->LinkStatus = GL_FALSE;
+}
+
+
+
+/**
+ * Check if the given bit is either set or clear in both bitfields.
+ */
+static GLboolean
+bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
+{
+ return (flags1 & bit) == (flags2 & bit);
+}
+
+
+/**
+ * Linking varying vars involves rearranging varying vars so that the
+ * vertex program's output varyings matches the order of the fragment
+ * program's input varyings.
+ * We'll then rewrite instructions to replace PROGRAM_VARYING with either
+ * PROGRAM_INPUT or PROGRAM_OUTPUT depending on whether it's a vertex or
+ * fragment shader.
+ * This is also where we set program Input/OutputFlags to indicate
+ * which inputs are centroid-sampled, invariant, etc.
+ */
+static GLboolean
+link_varying_vars(GLcontext *ctx,
+ struct gl_shader_program *shProg, struct gl_program *prog)
+{
+ GLuint *map, i, firstVarying, newFile;
+ GLbitfield *inOutFlags;
+
+ map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
+ if (!map)
+ return GL_FALSE;
+
+ /* Varying variables are treated like other vertex program outputs
+ * (and like other fragment program inputs). The position of the
+ * first varying differs for vertex/fragment programs...
+ * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
+ */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ firstVarying = VERT_RESULT_VAR0;
+ newFile = PROGRAM_OUTPUT;
+ inOutFlags = prog->OutputFlags;
+ }
+ else {
+ assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
+ firstVarying = FRAG_ATTRIB_VAR0;
+ newFile = PROGRAM_INPUT;
+ inOutFlags = prog->InputFlags;
+ }
+
+ for (i = 0; i < prog->Varying->NumParameters; i++) {
+ /* see if this varying is in the linked varying list */
+ const struct gl_program_parameter *var = prog->Varying->Parameters + i;
+ GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
+ if (j >= 0) {
+ /* varying is already in list, do some error checking */
+ const struct gl_program_parameter *v =
+ &shProg->Varying->Parameters[j];
+ if (var->Size != v->Size) {
+ link_error(shProg, "mismatched varying variable types");
+ return GL_FALSE;
+ }
+ if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
+ char msg[100];
+ _mesa_snprintf(msg, sizeof(msg),
+ "centroid modifier mismatch for '%s'", var->Name);
+ link_error(shProg, msg);
+ return GL_FALSE;
+ }
+ if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
+ char msg[100];
+ _mesa_snprintf(msg, sizeof(msg),
+ "invariant modifier mismatch for '%s'", var->Name);
+ link_error(shProg, msg);
+ return GL_FALSE;
+ }
+ }
+ else {
+ /* not already in linked list */
+ j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
+ var->Flags);
+ }
+
+ if (shProg->Varying->NumParameters > ctx->Const.MaxVarying) {
+ link_error(shProg, "Too many varying variables");
+ return GL_FALSE;
+ }
+
+ /* Map varying[i] to varying[j].
+ * Note: the loop here takes care of arrays or large (sz>4) vars.
+ */
+ {
+ GLint sz = var->Size;
+ while (sz > 0) {
+ inOutFlags[firstVarying + j] = var->Flags;
+ /*printf("Link varying from %d to %d\n", i, j);*/
+ map[i++] = j++;
+ sz -= 4;
+ }
+ i--; /* go back one */
+ }
+ }
+
+
+ /* OK, now scan the program/shader instructions looking for varying vars,
+ * replacing the old index with the new index.
+ */
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ GLuint j;
+
+ if (inst->DstReg.File == PROGRAM_VARYING) {
+ inst->DstReg.File = newFile;
+ inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
+ }
+
+ for (j = 0; j < 3; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_VARYING) {
+ inst->SrcReg[j].File = newFile;
+ inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
+ }
+ }
+ }
+
+ free(map);
+
+ /* these will get recomputed before linking is completed */
+ prog->InputsRead = 0x0;
+ prog->OutputsWritten = 0x0;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Build the shProg->Uniforms list.
+ * This is basically a list/index of all uniforms found in either/both of
+ * the vertex and fragment shaders.
+ *
+ * About uniforms:
+ * Each uniform has two indexes, one that points into the vertex
+ * program's parameter array and another that points into the fragment
+ * program's parameter array. When the user changes a uniform's value
+ * we have to change the value in the vertex and/or fragment program's
+ * parameter array.
+ *
+ * This function will be called twice to set up the two uniform->parameter
+ * mappings.
+ *
+ * If a uniform is only present in the vertex program OR fragment program
+ * then the fragment/vertex parameter index, respectively, will be -1.
+ */
+static GLboolean
+link_uniform_vars(GLcontext *ctx,
+ struct gl_shader_program *shProg,
+ struct gl_program *prog,
+ GLuint *numSamplers)
+{
+ GLuint samplerMap[200]; /* max number of samplers declared, not used */
+ GLuint i;
+
+ for (i = 0; i < prog->Parameters->NumParameters; i++) {
+ const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
+
+ /*
+ * XXX FIX NEEDED HERE
+ * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
+ * For example, modelview matrix, light pos, etc.
+ * Also, we need to update the state-var name-generator code to
+ * generate GLSL-style names, like "gl_LightSource[0].position".
+ * Furthermore, we'll need to fix the state-var's size/datatype info.
+ */
+
+ if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
+ && p->Used) {
+ /* add this uniform, indexing into the target's Parameters list */
+ struct gl_uniform *uniform =
+ _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
+ if (uniform)
+ uniform->Initialized = p->Initialized;
+ }
+
+ /* The samplerMap[] table we build here is used to remap/re-index
+ * sampler references by TEX instructions.
+ */
+ if (p->Type == PROGRAM_SAMPLER && p->Used) {
+ /* Allocate a new sampler index */
+ GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
+ GLuint newSampNum = *numSamplers;
+ if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
+ char s[100];
+ _mesa_sprintf(s, "Too many texture samplers (%u, max is %u)",
+ newSampNum, ctx->Const.MaxTextureImageUnits);
+ link_error(shProg, s);
+ return GL_FALSE;
+ }
+ /* save old->new mapping in the table */
+ if (oldSampNum < Elements(samplerMap))
+ samplerMap[oldSampNum] = newSampNum;
+ /* update parameter's sampler index */
+ prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
+ (*numSamplers)++;
+ }
+ }
+
+ /* OK, now scan the program/shader instructions looking for texture
+ * instructions using sampler vars. Replace old sampler indexes with
+ * new ones.
+ */
+ prog->SamplersUsed = 0x0;
+ for (i = 0; i < prog->NumInstructions; i++) {
+ struct prog_instruction *inst = prog->Instructions + i;
+ if (_mesa_is_tex_instruction(inst->Opcode)) {
+ /* here, inst->TexSrcUnit is really the sampler unit */
+ const GLint oldSampNum = inst->TexSrcUnit;
+
+#if 0
+ printf("====== remap sampler from %d to %d\n",
+ inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
+#endif
+
+ if (oldSampNum < Elements(samplerMap)) {
+ const GLuint newSampNum = samplerMap[oldSampNum];
+ inst->TexSrcUnit = newSampNum;
+ prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
+ prog->SamplersUsed |= (1 << newSampNum);
+ if (inst->TexShadow) {
+ prog->ShadowSamplers |= (1 << newSampNum);
+ }
+ }
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Resolve binding of generic vertex attributes.
+ * For example, if the vertex shader declared "attribute vec4 foobar" we'll
+ * allocate a generic vertex attribute for "foobar" and plug that value into
+ * the vertex program instructions.
+ * But if the user called glBindAttributeLocation(), those bindings will
+ * have priority.
+ */
+static GLboolean
+_slang_resolve_attributes(struct gl_shader_program *shProg,
+ const struct gl_program *origProg,
+ struct gl_program *linkedProg)
+{
+ GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS];
+ GLuint i, j;
+ GLbitfield usedAttributes; /* generics only, not legacy attributes */
+ GLbitfield inputsRead = 0x0;
+
+ assert(origProg != linkedProg);
+ assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
+ assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
+
+ if (!shProg->Attributes)
+ shProg->Attributes = _mesa_new_parameter_list();
+
+ if (linkedProg->Attributes) {
+ _mesa_free_parameter_list(linkedProg->Attributes);
+ }
+ linkedProg->Attributes = _mesa_new_parameter_list();
+
+
+ /* Build a bitmask indicating which attribute indexes have been
+ * explicitly bound by the user with glBindAttributeLocation().
+ */
+ usedAttributes = 0x0;
+ for (i = 0; i < shProg->Attributes->NumParameters; i++) {
+ GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
+ usedAttributes |= (1 << attr);
+ }
+
+ /* If gl_Vertex is used, that actually counts against the limit
+ * on generic vertex attributes. This avoids the ambiguity of
+ * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
+ * or generic attribute[0]. If gl_Vertex is used, we want the former.
+ */
+ if (origProg->InputsRead & VERT_BIT_POS) {
+ usedAttributes |= 0x1;
+ }
+
+ /* initialize the generic attribute map entries to -1 */
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
+ attribMap[i] = -1;
+ }
+
+ /*
+ * Scan program for generic attribute references
+ */
+ for (i = 0; i < linkedProg->NumInstructions; i++) {
+ struct prog_instruction *inst = linkedProg->Instructions + i;
+ for (j = 0; j < 3; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+ inputsRead |= (1 << inst->SrcReg[j].Index);
+ }
+
+ if (inst->SrcReg[j].File == PROGRAM_INPUT &&
+ inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
+ /*
+ * OK, we've found a generic vertex attribute reference.
+ */
+ const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
+
+ GLint attr = attribMap[k];
+
+ if (attr < 0) {
+ /* Need to figure out attribute mapping now.
+ */
+ const char *name = origProg->Attributes->Parameters[k].Name;
+ const GLint size = origProg->Attributes->Parameters[k].Size;
+ const GLenum type =origProg->Attributes->Parameters[k].DataType;
+ GLint index;
+
+ /* See if there's a user-defined attribute binding for
+ * this name.
+ */
+ index = _mesa_lookup_parameter_index(shProg->Attributes,
+ -1, name);
+ if (index >= 0) {
+ /* Found a user-defined binding */
+ attr = shProg->Attributes->Parameters[index].StateIndexes[0];
+ }
+ else {
+ /* No user-defined binding, choose our own attribute number.
+ * Start at 1 since generic attribute 0 always aliases
+ * glVertex/position.
+ */
+ for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) {
+ if (((1 << attr) & usedAttributes) == 0)
+ break;
+ }
+ if (attr == MAX_VERTEX_GENERIC_ATTRIBS) {
+ link_error(shProg, "Too many vertex attributes");
+ return GL_FALSE;
+ }
+
+ /* mark this attribute as used */
+ usedAttributes |= (1 << attr);
+ }
+
+ attribMap[k] = attr;
+
+ /* Save the final name->attrib binding so it can be queried
+ * with glGetAttributeLocation().
+ */
+ _mesa_add_attribute(linkedProg->Attributes, name,
+ size, type, attr);
+ }
+
+ assert(attr >= 0);
+
+ /* update the instruction's src reg */
+ inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
+ }
+ }
+ }
+
+ /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc).
+ * When the user queries the active attributes we need to include both
+ * the user-defined attributes and the built-in ones.
+ */
+ for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) {
+ if (inputsRead & (1 << i)) {
+ _mesa_add_attribute(linkedProg->Attributes,
+ _slang_vert_attrib_name(i),
+ 4, /* size in floats */
+ _slang_vert_attrib_type(i),
+ -1 /* attrib/input */);
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Scan program instructions to update the program's NumTemporaries field.
+ * Note: this implemenation relies on the code generator allocating
+ * temps in increasing order (0, 1, 2, ... ).
+ */
+static void
+_slang_count_temporaries(struct gl_program *prog)
+{
+ GLuint i, j;
+ GLint maxIndex = -1;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
+ if (maxIndex < inst->SrcReg[j].Index)
+ maxIndex = inst->SrcReg[j].Index;
+ }
+ if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ if (maxIndex < (GLint) inst->DstReg.Index)
+ maxIndex = inst->DstReg.Index;
+ }
+ }
+ }
+
+ prog->NumTemporaries = (GLuint) (maxIndex + 1);
+}
+
+
+/**
+ * Scan program instructions to update the program's InputsRead and
+ * OutputsWritten fields.
+ */
+static void
+_slang_update_inputs_outputs(struct gl_program *prog)
+{
+ GLuint i, j;
+ GLuint maxAddrReg = 0;
+
+ prog->InputsRead = 0x0;
+ prog->OutputsWritten = 0x0;
+
+ for (i = 0; i < prog->NumInstructions; i++) {
+ const struct prog_instruction *inst = prog->Instructions + i;
+ const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
+ for (j = 0; j < numSrc; j++) {
+ if (inst->SrcReg[j].File == PROGRAM_INPUT) {
+ prog->InputsRead |= 1 << inst->SrcReg[j].Index;
+ }
+ else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
+ maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
+ }
+ }
+
+ if (inst->DstReg.File == PROGRAM_OUTPUT) {
+ prog->OutputsWritten |= 1 << inst->DstReg.Index;
+ if (inst->DstReg.RelAddr) {
+ /* If the output attribute is indexed with relative addressing
+ * we know that it must be a varying or texcoord such as
+ * gl_TexCoord[i] = v; In this case, mark all the texcoords
+ * or varying outputs as being written. It's not an error if
+ * a vertex shader writes varying vars that aren't used by the
+ * fragment shader. But it is an error for a fragment shader
+ * to use varyings that are not written by the vertex shader.
+ */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ if (inst->DstReg.Index == VERT_RESULT_TEX0) {
+ /* mark all texcoord outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_TEXTURE_COORD_UNITS) - 1) << VERT_RESULT_TEX0;
+ prog->OutputsWritten |= mask;
+ }
+ else if (inst->DstReg.Index == VERT_RESULT_VAR0) {
+ /* mark all generic varying outputs as written */
+ const GLbitfield mask =
+ ((1 << MAX_VARYING) - 1) << VERT_RESULT_VAR0;
+ prog->OutputsWritten |= mask;
+ }
+ }
+ }
+ }
+ else if (inst->DstReg.File == PROGRAM_ADDRESS) {
+ maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
+ }
+ }
+ prog->NumAddressRegs = maxAddrReg;
+}
+
+
+
+/**
+ * Remove extra #version directives from the concatenated source string.
+ * Disable the extra ones by converting first two chars to //, a comment.
+ * This is a bit of hack to work around a preprocessor bug that only
+ * allows one #version directive per source.
+ */
+static void
+remove_extra_version_directives(GLchar *source)
+{
+ GLuint verCount = 0;
+ while (1) {
+ char *ver = _mesa_strstr(source, "#version");
+ if (ver) {
+ verCount++;
+ if (verCount > 1) {
+ ver[0] = '/';
+ ver[1] = '/';
+ }
+ source += 8;
+ }
+ else {
+ break;
+ }
+ }
+}
+
+
+
+/**
+ * Return a new shader whose source code is the concatenation of
+ * all the shader sources of the given type.
+ */
+static struct gl_shader *
+concat_shaders(struct gl_shader_program *shProg, GLenum shaderType)
+{
+ struct gl_shader *newShader;
+ const struct gl_shader *firstShader = NULL;
+ GLuint shaderLengths[100];
+ GLchar *source;
+ GLuint totalLen = 0, len = 0;
+ GLuint i;
+
+ /* compute total size of new shader source code */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ const struct gl_shader *shader = shProg->Shaders[i];
+ if (shader->Type == shaderType) {
+ shaderLengths[i] = _mesa_strlen(shader->Source);
+ totalLen += shaderLengths[i];
+ if (!firstShader)
+ firstShader = shader;
+ }
+ }
+
+ if (totalLen == 0)
+ return NULL;
+
+ source = (GLchar *) _mesa_malloc(totalLen + 1);
+ if (!source)
+ return NULL;
+
+ /* concatenate shaders */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ const struct gl_shader *shader = shProg->Shaders[i];
+ if (shader->Type == shaderType) {
+ _mesa_memcpy(source + len, shader->Source, shaderLengths[i]);
+ len += shaderLengths[i];
+ }
+ }
+ source[len] = '\0';
+ /*
+ _mesa_printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source);
+ */
+
+ remove_extra_version_directives(source);
+
+ newShader = CALLOC_STRUCT(gl_shader);
+ newShader->Type = shaderType;
+ newShader->Source = source;
+ newShader->Pragmas = firstShader->Pragmas;
+
+ return newShader;
+}
+
+
+/**
+ * Search the shader program's list of shaders to find the one that
+ * defines main().
+ * This will involve shader concatenation and recompilation if needed.
+ */
+static struct gl_shader *
+get_main_shader(GLcontext *ctx,
+ struct gl_shader_program *shProg, GLenum type)
+{
+ struct gl_shader *shader = NULL;
+ GLuint i;
+
+ /*
+ * Look for a shader that defines main() and has no unresolved references.
+ */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ shader = shProg->Shaders[i];
+ if (shader->Type == type &&
+ shader->Main &&
+ !shader->UnresolvedRefs) {
+ /* All set! */
+ return shader;
+ }
+ }
+
+ /*
+ * There must have been unresolved references during the original
+ * compilation. Try concatenating all the shaders of the given type
+ * and recompile that.
+ */
+ shader = concat_shaders(shProg, type);
+
+ if (shader) {
+ _slang_compile(ctx, shader);
+
+ /* Finally, check if recompiling failed */
+ if (!shader->CompileStatus ||
+ !shader->Main ||
+ shader->UnresolvedRefs) {
+ link_error(shProg, "Unresolved symbols");
+ return NULL;
+ }
+ }
+
+ return shader;
+}
+
+
+/**
+ * Shader linker. Currently:
+ *
+ * 1. The last attached vertex shader and fragment shader are linked.
+ * 2. Varying vars in the two shaders are combined so their locations
+ * agree between the vertex and fragment stages. They're treated as
+ * vertex program output attribs and as fragment program input attribs.
+ * 3. The vertex and fragment programs are cloned and modified to update
+ * src/dst register references so they use the new, linked varying
+ * storage locations.
+ */
+void
+_slang_link(GLcontext *ctx,
+ GLhandleARB programObj,
+ struct gl_shader_program *shProg)
+{
+ const struct gl_vertex_program *vertProg = NULL;
+ const struct gl_fragment_program *fragProg = NULL;
+ GLuint numSamplers = 0;
+ GLuint i;
+
+ _mesa_clear_shader_program_data(ctx, shProg);
+
+ /* Initialize LinkStatus to "success". Will be cleared if error. */
+ shProg->LinkStatus = GL_TRUE;
+
+ /* check that all programs compiled successfully */
+ for (i = 0; i < shProg->NumShaders; i++) {
+ if (!shProg->Shaders[i]->CompileStatus) {
+ link_error(shProg, "linking with uncompiled shader\n");
+ return;
+ }
+ }
+
+ shProg->Uniforms = _mesa_new_uniform_list();
+ shProg->Varying = _mesa_new_parameter_list();
+
+ /*
+ * Find the vertex and fragment shaders which define main()
+ */
+ {
+ struct gl_shader *vertShader, *fragShader;
+ vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER);
+ fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER);
+ if (vertShader)
+ vertProg = vertex_program(vertShader->Program);
+ if (fragShader)
+ fragProg = fragment_program(fragShader->Program);
+ if (!shProg->LinkStatus)
+ return;
+ }
+
+#if FEATURE_es2_glsl
+ /* must have both a vertex and fragment program for ES2 */
+ if (!vertProg) {
+ link_error(shProg, "missing vertex shader\n");
+ return;
+ }
+ if (!fragProg) {
+ link_error(shProg, "missing fragment shader\n");
+ return;
+ }
+#endif
+
+ /*
+ * Make copies of the vertex/fragment programs now since we'll be
+ * changing src/dst registers after merging the uniforms and varying vars.
+ */
+ _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
+ if (vertProg) {
+ struct gl_vertex_program *linked_vprog =
+ vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
+ shProg->VertexProgram = linked_vprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->VertexProgram->Base.Id = shProg->Name;
+ ASSERT(shProg->VertexProgram->Base.RefCount == 1);
+ }
+
+ _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
+ if (fragProg) {
+ struct gl_fragment_program *linked_fprog =
+ fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
+ shProg->FragmentProgram = linked_fprog; /* refcount OK */
+ /* vertex program ID not significant; just set Id for debugging purposes */
+ shProg->FragmentProgram->Base.Id = shProg->Name;
+ ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
+ }
+
+ /* link varying vars */
+ if (shProg->VertexProgram) {
+ if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base))
+ return;
+ }
+ if (shProg->FragmentProgram) {
+ if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base))
+ return;
+ }
+
+ /* link uniform vars */
+ if (shProg->VertexProgram) {
+ if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
+ &numSamplers)) {
+ return;
+ }
+ }
+ if (shProg->FragmentProgram) {
+ if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
+ &numSamplers)) {
+ return;
+ }
+ }
+
+ /*_mesa_print_uniforms(shProg->Uniforms);*/
+
+ if (shProg->VertexProgram) {
+ if (!_slang_resolve_attributes(shProg, &vertProg->Base,
+ &shProg->VertexProgram->Base)) {
+ return;
+ }
+ }
+
+ if (shProg->VertexProgram) {
+ _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
+ _slang_count_temporaries(&shProg->VertexProgram->Base);
+ if (!(shProg->VertexProgram->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {
+ /* the vertex program did not compute a vertex position */
+ link_error(shProg,
+ "gl_Position was not written by vertex shader\n");
+ return;
+ }
+ }
+ if (shProg->FragmentProgram) {
+ _slang_count_temporaries(&shProg->FragmentProgram->Base);
+ _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
+ }
+
+ /* Check that all the varying vars needed by the fragment shader are
+ * actually produced by the vertex shader.
+ */
+ if (shProg->FragmentProgram) {
+ const GLbitfield varyingRead
+ = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
+ const GLbitfield varyingWritten = shProg->VertexProgram ?
+ shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
+ if ((varyingRead & varyingWritten) != varyingRead) {
+ link_error(shProg,
+ "Fragment program using varying vars not written by vertex shader\n");
+ return;
+ }
+ }
+
+ /* check that gl_FragColor and gl_FragData are not both written to */
+ if (shProg->FragmentProgram) {
+ GLbitfield outputsWritten = shProg->FragmentProgram->Base.OutputsWritten;
+ if ((outputsWritten & ((1 << FRAG_RESULT_COLOR))) &&
+ (outputsWritten >= (1 << FRAG_RESULT_DATA0))) {
+ link_error(shProg, "Fragment program cannot write both gl_FragColor"
+ " and gl_FragData[].\n");
+ return;
+ }
+ }
+
+
+ if (fragProg && shProg->FragmentProgram) {
+ /* Compute initial program's TexturesUsed info */
+ _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
+
+ /* notify driver that a new fragment program has been compiled/linked */
+ ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ &shProg->FragmentProgram->Base);
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Mesa pre-link fragment program:\n");
+ _mesa_print_program(&fragProg->Base);
+ _mesa_print_program_parameters(ctx, &fragProg->Base);
+
+ _mesa_printf("Mesa post-link fragment program:\n");
+ _mesa_print_program(&shProg->FragmentProgram->Base);
+ _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
+ }
+ }
+
+ if (vertProg && shProg->VertexProgram) {
+ /* Compute initial program's TexturesUsed info */
+ _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
+
+ /* notify driver that a new vertex program has been compiled/linked */
+ ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
+ &shProg->VertexProgram->Base);
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Mesa pre-link vertex program:\n");
+ _mesa_print_program(&vertProg->Base);
+ _mesa_print_program_parameters(ctx, &vertProg->Base);
+
+ _mesa_printf("Mesa post-link vertex program:\n");
+ _mesa_print_program(&shProg->VertexProgram->Base);
+ _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
+ }
+ }
+
+ /* Debug: */
+ if (0) {
+ if (shProg->VertexProgram)
+ _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base);
+ if (shProg->FragmentProgram)
+ _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base);
+ }
+
+ if (ctx->Shader.Flags & GLSL_DUMP) {
+ _mesa_printf("Varying vars:\n");
+ _mesa_print_parameter_list(shProg->Varying);
+ if (shProg->InfoLog) {
+ _mesa_printf("Info Log: %s\n", shProg->InfoLog);
+ }
+ }
+
+ shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_link.h b/mesalib/src/mesa/shader/slang/slang_link.h
new file mode 100644
index 000000000..2b44d2078
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_link.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 2008 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 SLANG_LINK_H
+#define SLANG_LINK_H 1
+
+#include "slang_compile.h"
+
+
+extern void
+_slang_link(GLcontext *ctx, GLhandleARB h,
+ struct gl_shader_program *shProg);
+
+
+#endif
+
diff --git a/mesalib/src/mesa/shader/slang/slang_log.c b/mesalib/src/mesa/shader/slang/slang_log.c
new file mode 100644
index 000000000..d7d2b4fbf
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_log.c
@@ -0,0 +1,134 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "main/imports.h"
+#include "main/context.h"
+#include "slang_log.h"
+#include "slang_utility.h"
+
+
+
+static char *out_of_memory = "Error: Out of memory.\n";
+
+void
+slang_info_log_construct(slang_info_log * log)
+{
+ log->text = NULL;
+ log->dont_free_text = GL_FALSE;
+ log->error_flag = GL_FALSE;
+}
+
+void
+slang_info_log_destruct(slang_info_log * log)
+{
+ if (!log->dont_free_text)
+ _mesa_free(log->text);
+}
+
+static int
+slang_info_log_message(slang_info_log * log, const char *prefix,
+ const char *msg)
+{
+ GLuint size;
+
+ if (log->dont_free_text)
+ return 0;
+ size = slang_string_length(msg) + 2;
+ if (prefix != NULL)
+ size += slang_string_length(prefix) + 2;
+ if (log->text != NULL) {
+ GLuint old_len = slang_string_length(log->text);
+ log->text = (char *)
+ _mesa_realloc(log->text, old_len + 1, old_len + size);
+ }
+ else {
+ log->text = (char *) (_mesa_malloc(size));
+ if (log->text != NULL)
+ log->text[0] = '\0';
+ }
+ if (log->text == NULL)
+ return 0;
+ if (prefix != NULL) {
+ slang_string_concat(log->text, prefix);
+ slang_string_concat(log->text, ": ");
+ }
+ slang_string_concat(log->text, msg);
+ slang_string_concat(log->text, "\n");
+
+ return 1;
+}
+
+int
+slang_info_log_print(slang_info_log * log, const char *msg, ...)
+{
+ va_list va;
+ char buf[1024];
+
+ va_start(va, msg);
+ _mesa_vsprintf(buf, msg, va);
+ va_end(va);
+ return slang_info_log_message(log, NULL, buf);
+}
+
+int
+slang_info_log_error(slang_info_log * log, const char *msg, ...)
+{
+ va_list va;
+ char buf[1024];
+
+ va_start(va, msg);
+ _mesa_vsprintf(buf, msg, va);
+ va_end(va);
+ log->error_flag = GL_TRUE;
+ if (slang_info_log_message(log, "Error", buf))
+ return 1;
+ slang_info_log_memory(log);
+ return 0;
+}
+
+int
+slang_info_log_warning(slang_info_log * log, const char *msg, ...)
+{
+ va_list va;
+ char buf[1024];
+
+ va_start(va, msg);
+ _mesa_vsprintf(buf, msg, va);
+ va_end(va);
+ if (slang_info_log_message(log, "Warning", buf))
+ return 1;
+ slang_info_log_memory(log);
+ return 0;
+}
+
+void
+slang_info_log_memory(slang_info_log * log)
+{
+ if (!slang_info_log_message(log, "Error", "Out of memory.")) {
+ log->dont_free_text = GL_TRUE;
+ log->error_flag = GL_TRUE;
+ log->text = out_of_memory;
+ }
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_log.h b/mesalib/src/mesa/shader/slang/slang_log.h
new file mode 100644
index 000000000..dcaba0285
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_log.h
@@ -0,0 +1,57 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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 SLANG_LOG_H
+#define SLANG_LOG_H
+
+
+typedef struct slang_info_log_
+{
+ char *text;
+ GLboolean dont_free_text;
+ GLboolean error_flag;
+} slang_info_log;
+
+
+extern void
+slang_info_log_construct(slang_info_log *);
+
+extern void
+slang_info_log_destruct(slang_info_log *);
+
+extern int
+slang_info_log_print(slang_info_log *, const char *, ...);
+
+extern int
+slang_info_log_error(slang_info_log *, const char *, ...);
+
+extern int
+slang_info_log_warning(slang_info_log *, const char *, ...);
+
+extern void
+slang_info_log_memory(slang_info_log *);
+
+
+#endif /* SLANG_LOG_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_mem.c b/mesalib/src/mesa/shader/slang/slang_mem.c
new file mode 100644
index 000000000..9224578ed
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_mem.c
@@ -0,0 +1,243 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_mem.c
+ *
+ * Memory manager for GLSL compiler. The general idea is to do all
+ * allocations out of a large pool then just free the pool when done
+ * compiling to avoid intricate malloc/free tracking and memory leaks.
+ *
+ * \author Brian Paul
+ */
+
+#include "main/context.h"
+#include "main/macros.h"
+#include "slang_mem.h"
+
+
+#define GRANULARITY 8
+#define ROUND_UP(B) ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) )
+
+
+/** If 1, use conventional malloc/free. Helpful for debugging */
+#define USE_MALLOC_FREE 0
+
+
+struct slang_mempool_
+{
+ GLuint Size, Used, Count, Largest;
+ char *Data;
+ struct slang_mempool_ *Next;
+};
+
+
+slang_mempool *
+_slang_new_mempool(GLuint initialSize)
+{
+ slang_mempool *pool = (slang_mempool *) _mesa_calloc(sizeof(slang_mempool));
+ if (pool) {
+ pool->Data = (char *) _mesa_calloc(initialSize);
+ /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/
+ if (!pool->Data) {
+ _mesa_free(pool);
+ return NULL;
+ }
+ pool->Size = initialSize;
+ pool->Used = 0;
+ }
+ return pool;
+}
+
+
+void
+_slang_delete_mempool(slang_mempool *pool)
+{
+ GLuint total = 0;
+ while (pool) {
+ slang_mempool *next = pool->Next;
+ /*
+ printf("DELETE MEMPOOL %u / %u count=%u largest=%u\n",
+ pool->Used, pool->Size, pool->Count, pool->Largest);
+ */
+ total += pool->Used;
+ _mesa_free(pool->Data);
+ _mesa_free(pool);
+ pool = next;
+ }
+ /*printf("TOTAL ALLOCATED: %u\n", total);*/
+}
+
+
+#ifdef DEBUG
+static void
+check_zero(const char *addr, GLuint n)
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ assert(addr[i]==0);
+ }
+}
+#endif
+
+
+#ifdef DEBUG
+static GLboolean
+is_valid_address(const slang_mempool *pool, void *addr)
+{
+ while (pool) {
+ if ((char *) addr >= pool->Data &&
+ (char *) addr < pool->Data + pool->Used)
+ return GL_TRUE;
+
+ pool = pool->Next;
+ }
+ return GL_FALSE;
+}
+#endif
+
+
+/**
+ * Alloc 'bytes' from shader mempool.
+ */
+void *
+_slang_alloc(GLuint bytes)
+{
+#if USE_MALLOC_FREE
+ return _mesa_calloc(bytes);
+#else
+ slang_mempool *pool;
+ GET_CURRENT_CONTEXT(ctx);
+ pool = (slang_mempool *) ctx->Shader.MemPool;
+
+ if (bytes == 0)
+ bytes = 1;
+
+ while (pool) {
+ if (pool->Used + bytes <= pool->Size) {
+ /* found room */
+ void *addr = (void *) (pool->Data + pool->Used);
+#ifdef DEBUG
+ check_zero((char*) addr, bytes);
+#endif
+ pool->Used += ROUND_UP(bytes);
+ pool->Largest = MAX2(pool->Largest, bytes);
+ pool->Count++;
+ /*printf("alloc %u Used %u\n", bytes, pool->Used);*/
+ return addr;
+ }
+ else if (pool->Next) {
+ /* try next block */
+ pool = pool->Next;
+ }
+ else {
+ /* alloc new pool */
+ const GLuint sz = MAX2(bytes, pool->Size);
+ pool->Next = _slang_new_mempool(sz);
+ if (!pool->Next) {
+ /* we're _really_ out of memory */
+ return NULL;
+ }
+ else {
+ pool = pool->Next;
+ pool->Largest = bytes;
+ pool->Count++;
+ pool->Used = ROUND_UP(bytes);
+#ifdef DEBUG
+ check_zero((char*) pool->Data, bytes);
+#endif
+ return (void *) pool->Data;
+ }
+ }
+ }
+ return NULL;
+#endif
+}
+
+
+void *
+_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize)
+{
+#if USE_MALLOC_FREE
+ return _mesa_realloc(oldBuffer, oldSize, newSize);
+#else
+ GET_CURRENT_CONTEXT(ctx);
+ slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
+ (void) pool;
+
+ if (newSize < oldSize) {
+ return oldBuffer;
+ }
+ else {
+ const GLuint copySize = (oldSize < newSize) ? oldSize : newSize;
+ void *newBuffer = _slang_alloc(newSize);
+
+ if (oldBuffer)
+ ASSERT(is_valid_address(pool, oldBuffer));
+
+ if (newBuffer && oldBuffer && copySize > 0)
+ _mesa_memcpy(newBuffer, oldBuffer, copySize);
+
+ return newBuffer;
+ }
+#endif
+}
+
+
+/**
+ * Clone string, storing in current mempool.
+ */
+char *
+_slang_strdup(const char *s)
+{
+ if (s) {
+ size_t l = _mesa_strlen(s);
+ char *s2 = (char *) _slang_alloc(l + 1);
+ if (s2)
+ _mesa_strcpy(s2, s);
+ return s2;
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+/**
+ * Don't actually free memory, but mark it (for debugging).
+ */
+void
+_slang_free(void *addr)
+{
+#if USE_MALLOC_FREE
+ _mesa_free(addr);
+#else
+ if (addr) {
+ GET_CURRENT_CONTEXT(ctx);
+ slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool;
+ (void) pool;
+ ASSERT(is_valid_address(pool, addr));
+ }
+#endif
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_mem.h b/mesalib/src/mesa/shader/slang/slang_mem.h
new file mode 100644
index 000000000..b5bfae247
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_mem.h
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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 SLANG_MEM_H
+#define SLANG_MEM_H
+
+
+#include "main/imports.h"
+
+
+typedef struct slang_mempool_ slang_mempool;
+
+
+extern slang_mempool *
+_slang_new_mempool(GLuint initialSize);
+
+extern void
+_slang_delete_mempool(slang_mempool *pool);
+
+extern void *
+_slang_alloc(GLuint bytes);
+
+extern void *
+_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize);
+
+extern char *
+_slang_strdup(const char *s);
+
+extern void
+_slang_free(void *addr);
+
+
+#endif
diff --git a/mesalib/src/mesa/shader/slang/slang_preprocess.c b/mesalib/src/mesa/shader/slang/slang_preprocess.c
new file mode 100644
index 000000000..e9a24cc00
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_preprocess.c
@@ -0,0 +1,1406 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/**
+ * \file slang_preprocess.c
+ * slang preprocessor
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "shader/grammar/grammar_mesa.h"
+#include "slang_preprocess.h"
+
+LONGSTRING static const char *slang_pp_directives_syn =
+#include "library/slang_pp_directives_syn.h"
+;
+
+LONGSTRING static const char *slang_pp_expression_syn =
+#include "library/slang_pp_expression_syn.h"
+;
+
+LONGSTRING static const char *slang_pp_version_syn =
+#include "library/slang_pp_version_syn.h"
+;
+
+static GLvoid
+grammar_error_to_log (slang_info_log *log)
+{
+ char buf[1024];
+ GLint pos;
+
+ grammar_get_last_error ((byte *) (buf), sizeof (buf), &pos);
+ if (buf[0] == 0) {
+ _mesa_snprintf(buf, sizeof(buf), "Preprocessor error");
+ }
+ slang_info_log_error (log, buf);
+}
+
+GLboolean
+_slang_preprocess_version (const char *text, GLuint *version, GLuint *eaten, slang_info_log *log)
+{
+ grammar id;
+ byte *prod, *I;
+ unsigned int size;
+
+ id = grammar_load_from_text ((const byte *) (slang_pp_version_syn));
+ if (id == 0) {
+ grammar_error_to_log (log);
+ return GL_FALSE;
+ }
+
+ if (!grammar_fast_check (id, (const byte *) (text), &prod, &size, 8)) {
+ grammar_error_to_log (log);
+ grammar_destroy (id);
+ return GL_FALSE;
+ }
+
+ /* there can be multiple #version directives - grab the last one */
+ I = &prod[size - 6];
+ *version = (GLuint) (I[0]) + (GLuint) (I[1]) * 100;
+ *eaten = (GLuint) (I[2]) + ((GLuint) (I[3]) << 8) + ((GLuint) (I[4]) << 16) + ((GLuint) (I[5]) << 24);
+
+ grammar_destroy (id);
+ grammar_alloc_free (prod);
+ return GL_TRUE;
+}
+
+/*
+ * The preprocessor does the following work.
+ * 1. Remove comments. Each comment block is replaced with a single space and if the
+ * block contains new-lines, they are preserved. This ensures that line numbers
+ * stay the same and if a comment block delimits two tokens, the are delitmited
+ * by the space after comment removal.
+ * 2. Remove preprocessor directives from the source string, checking their syntax and
+ * executing them if appropriate. Again, new-lines are preserved.
+ * 3. Expand macros.
+ * 4. Tokenize the source string by ensuring there is at least one space between every
+ * two adjacent tokens.
+ */
+
+#define PP_ANNOTATE 0
+
+static GLvoid
+pp_annotate (slang_string *output, const char *fmt, ...)
+{
+#if PP_ANNOTATE
+ va_list va;
+ char buffer[1024];
+
+ va_start (va, fmt);
+ _mesa_vsprintf (buffer, fmt, va);
+ va_end (va);
+ slang_string_pushs (output, buffer, _mesa_strlen (buffer));
+#else
+ (GLvoid) (output);
+ (GLvoid) (fmt);
+#endif
+}
+
+ /*
+ * The expression is executed on a fixed-sized stack. The PUSH macro makes a runtime
+ * check if the stack is not overflown by too complex expressions. In that situation the
+ * GLSL preprocessor should report internal compiler error.
+ * The BINARYDIV makes a runtime check if the divider is not 0. If it is, it reports
+ * compilation error.
+ */
+
+#define EXECUTION_STACK_SIZE 1024
+
+#define PUSH(x)\
+ do {\
+ if (sp == 0) {\
+ slang_info_log_error (elog, "internal compiler error: preprocessor execution stack overflow.");\
+ return GL_FALSE;\
+ }\
+ stack[--sp] = x;\
+ } while (GL_FALSE)
+
+#define POP(x)\
+ do {\
+ assert (sp < EXECUTION_STACK_SIZE);\
+ x = stack[sp++];\
+ } while (GL_FALSE)
+
+#define BINARY(op)\
+ do {\
+ GLint a, b;\
+ POP(b);\
+ POP(a);\
+ PUSH(a op b);\
+ } while (GL_FALSE)
+
+#define BINARYDIV(op)\
+ do {\
+ GLint a, b;\
+ POP(b);\
+ POP(a);\
+ if (b == 0) {\
+ slang_info_log_error (elog, "division by zero in preprocessor expression.");\
+ return GL_FALSE;\
+ }\
+ PUSH(a op b);\
+ } while (GL_FALSE)
+
+#define UNARY(op)\
+ do {\
+ GLint a;\
+ POP(a);\
+ PUSH(op a);\
+ } while (GL_FALSE)
+
+#define OP_END 0
+#define OP_PUSHINT 1
+#define OP_LOGICALOR 2
+#define OP_LOGICALAND 3
+#define OP_OR 4
+#define OP_XOR 5
+#define OP_AND 6
+#define OP_EQUAL 7
+#define OP_NOTEQUAL 8
+#define OP_LESSEQUAL 9
+#define OP_GREATEREQUAL 10
+#define OP_LESS 11
+#define OP_GREATER 12
+#define OP_LEFTSHIFT 13
+#define OP_RIGHTSHIFT 14
+#define OP_ADD 15
+#define OP_SUBTRACT 16
+#define OP_MULTIPLY 17
+#define OP_DIVIDE 18
+#define OP_MODULUS 19
+#define OP_PLUS 20
+#define OP_MINUS 21
+#define OP_NEGATE 22
+#define OP_COMPLEMENT 23
+
+static GLboolean
+execute_expression (slang_string *output, const byte *code, GLuint *pi, GLint *result,
+ slang_info_log *elog)
+{
+ GLuint i = *pi;
+ GLint stack[EXECUTION_STACK_SIZE];
+ GLuint sp = EXECUTION_STACK_SIZE;
+
+ while (code[i] != OP_END) {
+ switch (code[i++]) {
+ case OP_PUSHINT:
+ i++;
+ PUSH(_mesa_atoi ((const char *) (&code[i])));
+ i += _mesa_strlen ((const char *) (&code[i])) + 1;
+ break;
+ case OP_LOGICALOR:
+ BINARY(||);
+ break;
+ case OP_LOGICALAND:
+ BINARY(&&);
+ break;
+ case OP_OR:
+ BINARY(|);
+ break;
+ case OP_XOR:
+ BINARY(^);
+ break;
+ case OP_AND:
+ BINARY(&);
+ break;
+ case OP_EQUAL:
+ BINARY(==);
+ break;
+ case OP_NOTEQUAL:
+ BINARY(!=);
+ break;
+ case OP_LESSEQUAL:
+ BINARY(<=);
+ break;
+ case OP_GREATEREQUAL:
+ BINARY(>=);
+ break;
+ case OP_LESS:
+ BINARY(<);
+ break;
+ case OP_GREATER:
+ BINARY(>);
+ break;
+ case OP_LEFTSHIFT:
+ BINARY(<<);
+ break;
+ case OP_RIGHTSHIFT:
+ BINARY(>>);
+ break;
+ case OP_ADD:
+ BINARY(+);
+ break;
+ case OP_SUBTRACT:
+ BINARY(-);
+ break;
+ case OP_MULTIPLY:
+ BINARY(*);
+ break;
+ case OP_DIVIDE:
+ BINARYDIV(/);
+ break;
+ case OP_MODULUS:
+ BINARYDIV(%);
+ break;
+ case OP_PLUS:
+ UNARY(+);
+ break;
+ case OP_MINUS:
+ UNARY(-);
+ break;
+ case OP_NEGATE:
+ UNARY(!);
+ break;
+ case OP_COMPLEMENT:
+ UNARY(~);
+ break;
+ default:
+ assert (0);
+ }
+ }
+
+ /* Write-back the index skipping the OP_END. */
+ *pi = i + 1;
+
+ /* There should be exactly one value left on the stack. This is our result. */
+ POP(*result);
+ pp_annotate (output, "%d ", *result);
+ assert (sp == EXECUTION_STACK_SIZE);
+ return GL_TRUE;
+}
+
+/*
+ * Function execute_expressions() executes up to 2 expressions. The second expression is there
+ * for the #line directive which takes 1 or 2 expressions that indicate line and file numbers.
+ * If it fails, it returns 0. If it succeeds, it returns the number of executed expressions.
+ */
+
+#define EXP_END 0
+#define EXP_EXPRESSION 1
+
+static GLuint
+execute_expressions (slang_string *output, grammar eid, const byte *expr, GLint results[2],
+ slang_info_log *elog)
+{
+ GLint success;
+ byte *code;
+ GLuint size, count = 0;
+
+ success = grammar_fast_check (eid, expr, &code, &size, 64);
+ if (success) {
+ GLuint i = 0;
+
+ while (code[i++] == EXP_EXPRESSION) {
+ assert (count < 2);
+
+ if (!execute_expression (output, code, &i, &results[count], elog)) {
+ count = 0;
+ break;
+ }
+ count++;
+ }
+ grammar_alloc_free (code);
+ }
+ else {
+ slang_info_log_error (elog, "syntax error in preprocessor expression.");\
+ }
+ return count;
+}
+
+/*
+ * The pp_symbol structure is used to hold macro definitions and macro formal parameters. The
+ * pp_symbols strcture is a collection of pp_symbol. It is used both for storing macro formal
+ * parameters and all global macro definitions. Making this unification wastes some memory,
+ * becuse macro formal parameters don't need further lists of symbols. We lose 8 bytes per
+ * formal parameter here, but making this we can use the same code to substitute macro parameters
+ * as well as macros in the source string.
+ */
+
+typedef struct
+{
+ struct pp_symbol_ *symbols;
+ GLuint count;
+} pp_symbols;
+
+static GLvoid
+pp_symbols_init (pp_symbols *self)
+{
+ self->symbols = NULL;
+ self->count = 0;
+}
+
+static GLvoid
+pp_symbols_free (pp_symbols *);
+
+typedef struct pp_symbol_
+{
+ slang_string name;
+ slang_string replacement;
+ pp_symbols parameters;
+} pp_symbol;
+
+static GLvoid
+pp_symbol_init (pp_symbol *self)
+{
+ slang_string_init (&self->name);
+ slang_string_init (&self->replacement);
+ pp_symbols_init (&self->parameters);
+}
+
+static GLvoid
+pp_symbol_free (pp_symbol *self)
+{
+ slang_string_free (&self->name);
+ slang_string_free (&self->replacement);
+ pp_symbols_free (&self->parameters);
+}
+
+static GLvoid
+pp_symbol_reset (pp_symbol *self)
+{
+ /* Leave symbol name intact. */
+ slang_string_reset (&self->replacement);
+ pp_symbols_free (&self->parameters);
+ pp_symbols_init (&self->parameters);
+}
+
+static GLvoid
+pp_symbols_free (pp_symbols *self)
+{
+ GLuint i;
+
+ for (i = 0; i < self->count; i++)
+ pp_symbol_free (&self->symbols[i]);
+ _mesa_free (self->symbols);
+}
+
+static pp_symbol *
+pp_symbols_push (pp_symbols *self)
+{
+ self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, self->count * sizeof (pp_symbol),
+ (self->count + 1) * sizeof (pp_symbol)));
+ if (self->symbols == NULL)
+ return NULL;
+ pp_symbol_init (&self->symbols[self->count]);
+ return &self->symbols[self->count++];
+}
+
+static GLboolean
+pp_symbols_erase (pp_symbols *self, pp_symbol *symbol)
+{
+ assert (symbol >= self->symbols && symbol < self->symbols + self->count);
+
+ self->count--;
+ pp_symbol_free (symbol);
+ if (symbol < self->symbols + self->count)
+ _mesa_memcpy (symbol, symbol + 1, sizeof (pp_symbol) * (self->symbols + self->count - symbol));
+ self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, (self->count + 1) * sizeof (pp_symbol),
+ self->count * sizeof (pp_symbol)));
+ return self->symbols != NULL;
+}
+
+static pp_symbol *
+pp_symbols_find (pp_symbols *self, const char *name)
+{
+ GLuint i;
+
+ for (i = 0; i < self->count; i++)
+ if (_mesa_strcmp (name, slang_string_cstr (&self->symbols[i].name)) == 0)
+ return &self->symbols[i];
+ return NULL;
+}
+
+/*
+ * The condition context of a single #if/#else/#endif level. Those can be nested, so there
+ * is a stack of condition contexts.
+ * There is a special global context on the bottom of the stack. It is there to simplify
+ * context handling.
+ */
+
+typedef struct
+{
+ GLboolean current; /* The condition value of this level. */
+ GLboolean effective; /* The effective product of current condition, outer level conditions
+ * and position within #if-#else-#endif sections. */
+ GLboolean else_allowed; /* TRUE if in #if-#else section, FALSE if in #else-#endif section
+ * and for global context. */
+ GLboolean endif_required; /* FALSE for global context only. */
+} pp_cond_ctx;
+
+/* Should be enuff. */
+#define CONDITION_STACK_SIZE 64
+
+typedef struct
+{
+ pp_cond_ctx stack[CONDITION_STACK_SIZE];
+ pp_cond_ctx *top;
+} pp_cond_stack;
+
+static GLboolean
+pp_cond_stack_push (pp_cond_stack *self, slang_info_log *elog)
+{
+ if (self->top == self->stack) {
+ slang_info_log_error (elog, "internal compiler error: preprocessor condition stack overflow.");
+ return GL_FALSE;
+ }
+ self->top--;
+ return GL_TRUE;
+}
+
+static GLvoid
+pp_cond_stack_reevaluate (pp_cond_stack *self)
+{
+ /* There must be at least 2 conditions on the stack - one global and one being evaluated. */
+ assert (self->top <= &self->stack[CONDITION_STACK_SIZE - 2]);
+
+ self->top->effective = self->top->current && self->top[1].effective;
+}
+
+
+/**
+ * Extension enables through #extension directive.
+ * NOTE: Currently, only enable/disable state is stored.
+ */
+typedef struct
+{
+ GLboolean ARB_draw_buffers;
+ GLboolean ARB_texture_rectangle;
+} pp_ext;
+
+
+/**
+ * Disable all extensions. Called at startup and on #extension all: disable.
+ */
+static GLvoid
+pp_ext_disable_all(pp_ext *self)
+{
+ _mesa_memset(self, 0, sizeof(self));
+}
+
+
+/**
+ * Called during preprocessor initialization to set the initial enable/disable
+ * state of extensions.
+ */
+static GLvoid
+pp_ext_init(pp_ext *self, const struct gl_extensions *extensions)
+{
+ pp_ext_disable_all (self);
+ self->ARB_draw_buffers = GL_TRUE;
+ if (extensions->NV_texture_rectangle)
+ self->ARB_texture_rectangle = GL_TRUE;
+}
+
+/**
+ * Called in response to #extension directives to enable/disable
+ * the named extension.
+ */
+static GLboolean
+pp_ext_set(pp_ext *self, const char *name, GLboolean enable)
+{
+ if (_mesa_strcmp (name, "GL_ARB_draw_buffers") == 0)
+ self->ARB_draw_buffers = enable;
+ else if (_mesa_strcmp (name, "GL_ARB_texture_rectangle") == 0)
+ self->ARB_texture_rectangle = enable;
+ else
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+
+/**
+ * Called in response to #pragma. For example, "#pragma debug(on)" would
+ * call this function as pp_pragma("debug", "on").
+ * \return GL_TRUE if pragma is valid, GL_FALSE if invalid
+ */
+static GLboolean
+pp_pragma(struct gl_sl_pragmas *pragmas, const char *pragma, const char *param)
+{
+#if 0
+ printf("#pragma %s %s\n", pragma, param);
+#endif
+ if (_mesa_strcmp(pragma, "optimize") == 0) {
+ if (!param)
+ return GL_FALSE; /* missing required param */
+ if (_mesa_strcmp(param, "on") == 0) {
+ if (!pragmas->IgnoreOptimize)
+ pragmas->Optimize = GL_TRUE;
+ }
+ else if (_mesa_strcmp(param, "off") == 0) {
+ if (!pragmas->IgnoreOptimize)
+ pragmas->Optimize = GL_FALSE;
+ }
+ else {
+ return GL_FALSE; /* invalid param */
+ }
+ }
+ else if (_mesa_strcmp(pragma, "debug") == 0) {
+ if (!param)
+ return GL_FALSE; /* missing required param */
+ if (_mesa_strcmp(param, "on") == 0) {
+ if (!pragmas->IgnoreDebug)
+ pragmas->Debug = GL_TRUE;
+ }
+ else if (_mesa_strcmp(param, "off") == 0) {
+ if (!pragmas->IgnoreDebug)
+ pragmas->Debug = GL_FALSE;
+ }
+ else {
+ return GL_FALSE; /* invalid param */
+ }
+ }
+ /* all other pragmas are silently ignored */
+ return GL_TRUE;
+}
+
+
+/**
+ * The state of preprocessor: current line, file and version number, list
+ * of all defined macros and the #if/#endif context.
+ */
+typedef struct
+{
+ GLint line;
+ GLint file;
+ GLint version;
+ pp_symbols symbols;
+ pp_ext ext;
+ slang_info_log *elog;
+ pp_cond_stack cond;
+} pp_state;
+
+static GLvoid
+pp_state_init (pp_state *self, slang_info_log *elog,
+ const struct gl_extensions *extensions)
+{
+ self->line = 0;
+ self->file = 1;
+#if FEATURE_es2_glsl
+ self->version = 100;
+#else
+ self->version = 110;
+#endif
+ pp_symbols_init (&self->symbols);
+ pp_ext_init (&self->ext, extensions);
+ self->elog = elog;
+
+ /* Initialize condition stack and create the global context. */
+ self->cond.top = &self->cond.stack[CONDITION_STACK_SIZE - 1];
+ self->cond.top->current = GL_TRUE;
+ self->cond.top->effective = GL_TRUE;
+ self->cond.top->else_allowed = GL_FALSE;
+ self->cond.top->endif_required = GL_FALSE;
+}
+
+static GLvoid
+pp_state_free (pp_state *self)
+{
+ pp_symbols_free (&self->symbols);
+}
+
+#define IS_FIRST_ID_CHAR(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')
+#define IS_NEXT_ID_CHAR(x) (IS_FIRST_ID_CHAR(x) || ((x) >= '0' && (x) <= '9'))
+#define IS_WHITE(x) ((x) == ' ' || (x) == '\n')
+#define IS_NULL(x) ((x) == '\0')
+
+#define SKIP_WHITE(x) do { while (IS_WHITE(*(x))) (x)++; } while (GL_FALSE)
+
+typedef struct
+{
+ slang_string *output;
+ const char *input;
+ pp_state *state;
+} expand_state;
+
+static GLboolean
+expand_defined (expand_state *e, slang_string *buffer)
+{
+ GLboolean in_paren = GL_FALSE;
+ const char *id;
+
+ /* Parse the optional opening parenthesis. */
+ SKIP_WHITE(e->input);
+ if (*e->input == '(') {
+ e->input++;
+ in_paren = GL_TRUE;
+ SKIP_WHITE(e->input);
+ }
+
+ /* Parse operand. */
+ if (!IS_FIRST_ID_CHAR(*e->input)) {
+ slang_info_log_error (e->state->elog,
+ "preprocess error: identifier expected after operator 'defined'.");
+ return GL_FALSE;
+ }
+ slang_string_reset (buffer);
+ slang_string_pushc (buffer, *e->input++);
+ while (IS_NEXT_ID_CHAR(*e->input))
+ slang_string_pushc (buffer, *e->input++);
+ id = slang_string_cstr (buffer);
+
+ /* Check if the operand is defined. Output 1 if it is defined, output 0 if not. */
+ if (pp_symbols_find (&e->state->symbols, id) == NULL)
+ slang_string_pushs (e->output, " 0 ", 3);
+ else
+ slang_string_pushs (e->output, " 1 ", 3);
+
+ /* Parse the closing parentehesis if the opening one was there. */
+ if (in_paren) {
+ SKIP_WHITE(e->input);
+ if (*e->input != ')') {
+ slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
+ return GL_FALSE;
+ }
+ e->input++;
+ SKIP_WHITE(e->input);
+ }
+ return GL_TRUE;
+}
+
+static GLboolean
+expand (expand_state *, pp_symbols *);
+
+static GLboolean
+expand_symbol (expand_state *e, pp_symbol *symbol)
+{
+ expand_state es;
+
+ /* If the macro has some parameters, we need to parse them. */
+ if (symbol->parameters.count != 0) {
+ GLuint i;
+
+ /* Parse the opening parenthesis. */
+ SKIP_WHITE(e->input);
+ if (*e->input != '(') {
+ slang_info_log_error (e->state->elog, "preprocess error: '(' expected.");
+ return GL_FALSE;
+ }
+ e->input++;
+ SKIP_WHITE(e->input);
+
+ /* Parse macro actual parameters. This can be anything, separated by a colon.
+ */
+ for (i = 0; i < symbol->parameters.count; i++) {
+ GLuint nested_paren_count = 0; /* track number of nested parentheses */
+
+ if (*e->input == ')') {
+ slang_info_log_error (e->state->elog, "preprocess error: unexpected ')'.");
+ return GL_FALSE;
+ }
+
+ /* Eat all characters up to the comma or closing parentheses. */
+ pp_symbol_reset (&symbol->parameters.symbols[i]);
+ while (!IS_NULL(*e->input)) {
+ /* Exit loop only when all nested parens have been eaten. */
+ if (nested_paren_count == 0 && (*e->input == ',' || *e->input == ')'))
+ break;
+
+ /* Actually count nested parens here. */
+ if (*e->input == '(')
+ nested_paren_count++;
+ else if (*e->input == ')')
+ nested_paren_count--;
+
+ slang_string_pushc (&symbol->parameters.symbols[i].replacement, *e->input++);
+ }
+
+ /* If it was not the last paremeter, skip the comma. Otherwise, skip the
+ * closing parentheses. */
+ if (i + 1 == symbol->parameters.count) {
+ /* This is the last paremeter - skip the closing parentheses. */
+ if (*e->input != ')') {
+ slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");
+ return GL_FALSE;
+ }
+ e->input++;
+ SKIP_WHITE(e->input);
+ }
+ else {
+ /* Skip the separating comma. */
+ if (*e->input != ',') {
+ slang_info_log_error (e->state->elog, "preprocess error: ',' expected.");
+ return GL_FALSE;
+ }
+ e->input++;
+ SKIP_WHITE(e->input);
+ }
+ }
+ }
+
+ /* Expand the macro. Use its parameters as a priority symbol list to expand
+ * macro parameters correctly. */
+ es.output = e->output;
+ es.input = slang_string_cstr (&symbol->replacement);
+ es.state = e->state;
+ slang_string_pushc (e->output, ' ');
+ if (!expand (&es, &symbol->parameters))
+ return GL_FALSE;
+ slang_string_pushc (e->output, ' ');
+ return GL_TRUE;
+}
+
+/*
+ * Function expand() expands source text from <input> to <output>. The expansion is made using
+ * the list passed in <symbols> parameter. It allows us to expand macro formal parameters with
+ * actual parameters. The global list of symbols from pp state is used when doing a recursive
+ * call of expand().
+ */
+
+static GLboolean
+expand (expand_state *e, pp_symbols *symbols)
+{
+ while (!IS_NULL(*e->input)) {
+ if (IS_FIRST_ID_CHAR(*e->input)) {
+ slang_string buffer;
+ const char *id;
+
+ /* Parse the identifier. */
+ slang_string_init (&buffer);
+ slang_string_pushc (&buffer, *e->input++);
+ while (IS_NEXT_ID_CHAR(*e->input))
+ slang_string_pushc (&buffer, *e->input++);
+ id = slang_string_cstr (&buffer);
+
+ /* Now check if the identifier is special in some way. The "defined" identifier is
+ * actually an operator that we must handle here and expand it either to " 0 " or " 1 ".
+ * The other identifiers start with "__" and we expand it to appropriate values
+ * taken from the preprocessor state. */
+ if (_mesa_strcmp (id, "defined") == 0) {
+ if (!expand_defined (e, &buffer))
+ return GL_FALSE;
+ }
+ else if (_mesa_strcmp (id, "__LINE__") == 0) {
+ slang_string_pushc (e->output, ' ');
+ slang_string_pushi (e->output, e->state->line);
+ slang_string_pushc (e->output, ' ');
+ }
+ else if (_mesa_strcmp (id, "__FILE__") == 0) {
+ slang_string_pushc (e->output, ' ');
+ slang_string_pushi (e->output, e->state->file);
+ slang_string_pushc (e->output, ' ');
+ }
+ else if (_mesa_strcmp (id, "__VERSION__") == 0) {
+ slang_string_pushc (e->output, ' ');
+ slang_string_pushi (e->output, e->state->version);
+ slang_string_pushc (e->output, ' ');
+ }
+#if FEATURE_es2_glsl
+ else if (_mesa_strcmp (id, "GL_ES") == 0 ||
+ _mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) {
+ slang_string_pushc (e->output, ' ');
+ slang_string_pushi (e->output, '1');
+ slang_string_pushc (e->output, ' ');
+ }
+#endif
+ else {
+ pp_symbol *symbol;
+
+ /* The list of symbols from <symbols> take precedence over the list from <state>.
+ * Note that in some cases this is the same list so avoid double look-up. */
+ symbol = pp_symbols_find (symbols, id);
+ if (symbol == NULL && symbols != &e->state->symbols)
+ symbol = pp_symbols_find (&e->state->symbols, id);
+
+ /* If the symbol was found, recursively expand its definition. */
+ if (symbol != NULL) {
+ if (!expand_symbol (e, symbol)) {
+ slang_string_free (&buffer);
+ return GL_FALSE;
+ }
+ }
+ else {
+ slang_string_push (e->output, &buffer);
+ }
+ }
+ slang_string_free (&buffer);
+ }
+ else if (IS_WHITE(*e->input)) {
+ slang_string_pushc (e->output, *e->input++);
+ }
+ else {
+ while (!IS_WHITE(*e->input) && !IS_NULL(*e->input) && !IS_FIRST_ID_CHAR(*e->input))
+ slang_string_pushc (e->output, *e->input++);
+ }
+ }
+ return GL_TRUE;
+}
+
+static GLboolean
+parse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state,
+ grammar eid)
+{
+ const char *text;
+ GLuint len;
+
+ text = (const char *) (&prod[*pi]);
+ len = _mesa_strlen (text);
+
+ if (state->cond.top->effective) {
+ slang_string expr;
+ GLuint count;
+ GLint results[2];
+ expand_state es;
+
+ /* Expand the expression. */
+ slang_string_init (&expr);
+ es.output = &expr;
+ es.input = text;
+ es.state = state;
+ if (!expand (&es, &state->symbols))
+ return GL_FALSE;
+
+ /* Execute the expression. */
+ count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)),
+ results, state->elog);
+ slang_string_free (&expr);
+ if (count != 1)
+ return GL_FALSE;
+ *result = results[0];
+ }
+ else {
+ /* The directive is dead. */
+ *result = 0;
+ }
+
+ *pi += len + 1;
+ return GL_TRUE;
+}
+
+#define ESCAPE_TOKEN 0
+
+#define TOKEN_END 0
+#define TOKEN_DEFINE 1
+#define TOKEN_UNDEF 2
+#define TOKEN_IF 3
+#define TOKEN_ELSE 4
+#define TOKEN_ELIF 5
+#define TOKEN_ENDIF 6
+#define TOKEN_ERROR 7
+#define TOKEN_PRAGMA 8
+#define TOKEN_EXTENSION 9
+#define TOKEN_LINE 10
+
+#define PARAM_END 0
+#define PARAM_PARAMETER 1
+
+#define BEHAVIOR_REQUIRE 1
+#define BEHAVIOR_ENABLE 2
+#define BEHAVIOR_WARN 3
+#define BEHAVIOR_DISABLE 4
+
+#define PRAGMA_NO_PARAM 0
+#define PRAGMA_PARAM 1
+
+
+static GLboolean
+preprocess_source (slang_string *output, const char *source,
+ grammar pid, grammar eid,
+ slang_info_log *elog,
+ const struct gl_extensions *extensions,
+ struct gl_sl_pragmas *pragmas)
+{
+ static const char *predefined[] = {
+ "__FILE__",
+ "__LINE__",
+ "__VERSION__",
+#if FEATURE_es2_glsl
+ "GL_ES",
+ "GL_FRAGMENT_PRECISION_HIGH",
+#endif
+ NULL
+ };
+ byte *prod;
+ GLuint size, i;
+ pp_state state;
+
+ if (!grammar_fast_check (pid, (const byte *) (source), &prod, &size, 65536)) {
+ grammar_error_to_log (elog);
+ return GL_FALSE;
+ }
+
+ pp_state_init (&state, elog, extensions);
+
+ /* add the predefined symbols to the symbol table */
+ for (i = 0; predefined[i]; i++) {
+ pp_symbol *symbol = NULL;
+ symbol = pp_symbols_push(&state.symbols);
+ assert(symbol);
+ slang_string_pushs(&symbol->name,
+ predefined[i], _mesa_strlen(predefined[i]));
+ }
+
+ i = 0;
+ while (i < size) {
+ if (prod[i] != ESCAPE_TOKEN) {
+ if (state.cond.top->effective) {
+ slang_string input;
+ expand_state es;
+
+ /* Eat only one line of source code to expand it.
+ * FIXME: This approach has one drawback. If a macro with parameters spans across
+ * multiple lines, the preprocessor will raise an error. */
+ slang_string_init (&input);
+ while (prod[i] != '\0' && prod[i] != '\n')
+ slang_string_pushc (&input, prod[i++]);
+ if (prod[i] != '\0')
+ slang_string_pushc (&input, prod[i++]);
+
+ /* Increment line number. */
+ state.line++;
+
+ es.output = output;
+ es.input = slang_string_cstr (&input);
+ es.state = &state;
+ if (!expand (&es, &state.symbols))
+ goto error;
+
+ slang_string_free (&input);
+ }
+ else {
+ /* Condition stack is disabled - keep track on line numbers and output only newlines. */
+ if (prod[i] == '\n') {
+ state.line++;
+ /*pp_annotate (output, "%c", prod[i]);*/
+ }
+ else {
+ /*pp_annotate (output, "%c", prod[i]);*/
+ }
+ i++;
+ }
+ }
+ else {
+ const char *id;
+ GLuint idlen;
+ GLubyte token;
+
+ i++;
+ token = prod[i++];
+ switch (token) {
+
+ case TOKEN_END:
+ /* End of source string.
+ * Check if all #ifs have been terminated by matching #endifs.
+ * On condition stack there should be only the global condition context. */
+ if (state.cond.top->endif_required) {
+ slang_info_log_error (elog, "end of source without matching #endif.");
+ return GL_FALSE;
+ }
+ break;
+
+ case TOKEN_DEFINE:
+ {
+ pp_symbol *symbol = NULL;
+
+ /* Parse macro name. */
+ id = (const char *) (&prod[i]);
+ idlen = _mesa_strlen (id);
+ if (state.cond.top->effective) {
+ pp_annotate (output, "// #define %s(", id);
+
+ /* If the symbol is already defined, override it. */
+ symbol = pp_symbols_find (&state.symbols, id);
+ if (symbol == NULL) {
+ symbol = pp_symbols_push (&state.symbols);
+ if (symbol == NULL)
+ goto error;
+ slang_string_pushs (&symbol->name, id, idlen);
+ }
+ else {
+ pp_symbol_reset (symbol);
+ }
+ }
+ i += idlen + 1;
+
+ /* Parse optional macro parameters. */
+ while (prod[i++] != PARAM_END) {
+ pp_symbol *param;
+
+ id = (const char *) (&prod[i]);
+ idlen = _mesa_strlen (id);
+ if (state.cond.top->effective) {
+ pp_annotate (output, "%s, ", id);
+ param = pp_symbols_push (&symbol->parameters);
+ if (param == NULL)
+ goto error;
+ slang_string_pushs (&param->name, id, idlen);
+ }
+ i += idlen + 1;
+ }
+
+ /* Parse macro replacement. */
+ id = (const char *) (&prod[i]);
+ idlen = _mesa_strlen (id);
+ if (state.cond.top->effective) {
+ slang_string replacement;
+ expand_state es;
+
+ pp_annotate (output, ") %s", id);
+
+ slang_string_init(&replacement);
+ slang_string_pushs(&replacement, id, idlen);
+
+ /* Expand macro replacement. */
+ es.output = &symbol->replacement;
+ es.input = slang_string_cstr(&replacement);
+ es.state = &state;
+ if (!expand(&es, &state.symbols)) {
+ slang_string_free(&replacement);
+ goto error;
+ }
+ slang_string_free(&replacement);
+ }
+ i += idlen + 1;
+ }
+ break;
+
+ case TOKEN_UNDEF:
+ id = (const char *) (&prod[i]);
+ i += _mesa_strlen (id) + 1;
+ if (state.cond.top->effective) {
+ pp_symbol *symbol;
+
+ pp_annotate (output, "// #undef %s", id);
+ /* Try to find symbol with given name and remove it. */
+ symbol = pp_symbols_find (&state.symbols, id);
+ if (symbol != NULL)
+ if (!pp_symbols_erase (&state.symbols, symbol))
+ goto error;
+ }
+ break;
+
+ case TOKEN_IF:
+ {
+ GLint result;
+
+ /* Parse #if expression end execute it. */
+ pp_annotate (output, "// #if ");
+ if (!parse_if (output, prod, &i, &result, &state, eid))
+ goto error;
+
+ /* Push new condition on the stack. */
+ if (!pp_cond_stack_push (&state.cond, state.elog))
+ goto error;
+ state.cond.top->current = result ? GL_TRUE : GL_FALSE;
+ state.cond.top->else_allowed = GL_TRUE;
+ state.cond.top->endif_required = GL_TRUE;
+ pp_cond_stack_reevaluate (&state.cond);
+ }
+ break;
+
+ case TOKEN_ELSE:
+ /* Check if #else is alloved here. */
+ if (!state.cond.top->else_allowed) {
+ slang_info_log_error (elog, "#else without matching #if.");
+ goto error;
+ }
+
+ /* Negate current condition and reevaluate it. */
+ state.cond.top->current = !state.cond.top->current;
+ state.cond.top->else_allowed = GL_FALSE;
+ pp_cond_stack_reevaluate (&state.cond);
+ if (state.cond.top->effective)
+ pp_annotate (output, "// #else");
+ break;
+
+ case TOKEN_ELIF:
+ /* Check if #elif is alloved here. */
+ if (!state.cond.top->else_allowed) {
+ slang_info_log_error (elog, "#elif without matching #if.");
+ goto error;
+ }
+
+ /* Negate current condition and reevaluate it. */
+ state.cond.top->current = !state.cond.top->current;
+ pp_cond_stack_reevaluate (&state.cond);
+
+ if (state.cond.top->effective)
+ pp_annotate (output, "// #elif ");
+
+ {
+ GLint result;
+
+ /* Parse #elif expression end execute it. */
+ if (!parse_if (output, prod, &i, &result, &state, eid))
+ goto error;
+
+ /* Update current condition and reevaluate it. */
+ state.cond.top->current = result ? GL_TRUE : GL_FALSE;
+ pp_cond_stack_reevaluate (&state.cond);
+ }
+ break;
+
+ case TOKEN_ENDIF:
+ /* Check if #endif is alloved here. */
+ if (!state.cond.top->endif_required) {
+ slang_info_log_error (elog, "#endif without matching #if.");
+ goto error;
+ }
+
+ /* Pop the condition off the stack. */
+ state.cond.top++;
+ if (state.cond.top->effective)
+ pp_annotate (output, "// #endif");
+ break;
+
+ case TOKEN_EXTENSION:
+ /* Parse the extension name. */
+ id = (const char *) (&prod[i]);
+ i += _mesa_strlen (id) + 1;
+ if (state.cond.top->effective)
+ pp_annotate (output, "// #extension %s: ", id);
+
+ /* Parse and apply extension behavior. */
+ if (state.cond.top->effective) {
+ switch (prod[i++]) {
+
+ case BEHAVIOR_REQUIRE:
+ pp_annotate (output, "require");
+ if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
+ if (_mesa_strcmp (id, "all") == 0) {
+ slang_info_log_error (elog, "require: bad behavior for #extension all.");
+ goto error;
+ }
+ else {
+ slang_info_log_error (elog, "%s: required extension is not supported.", id);
+ goto error;
+ }
+ }
+ break;
+
+ case BEHAVIOR_ENABLE:
+ pp_annotate (output, "enable");
+ if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
+ if (_mesa_strcmp (id, "all") == 0) {
+ slang_info_log_error (elog, "enable: bad behavior for #extension all.");
+ goto error;
+ }
+ else {
+ slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
+ }
+ }
+ break;
+
+ case BEHAVIOR_WARN:
+ pp_annotate (output, "warn");
+ if (!pp_ext_set (&state.ext, id, GL_TRUE)) {
+ if (_mesa_strcmp (id, "all") != 0) {
+ slang_info_log_warning (elog, "%s: enabled extension is not supported.", id);
+ }
+ }
+ break;
+
+ case BEHAVIOR_DISABLE:
+ pp_annotate (output, "disable");
+ if (!pp_ext_set (&state.ext, id, GL_FALSE)) {
+ if (_mesa_strcmp (id, "all") == 0) {
+ pp_ext_disable_all (&state.ext);
+ }
+ else {
+ slang_info_log_warning (elog, "%s: disabled extension is not supported.", id);
+ }
+ }
+ break;
+
+ default:
+ assert (0);
+ }
+ }
+ break;
+
+ case TOKEN_PRAGMA:
+ {
+ GLint have_param;
+ const char *pragma, *param;
+
+ pragma = (const char *) (&prod[i]);
+ i += _mesa_strlen(pragma) + 1;
+ have_param = (prod[i++] == PRAGMA_PARAM);
+ if (have_param) {
+ param = (const char *) (&prod[i]);
+ i += _mesa_strlen(param) + 1;
+ }
+ else {
+ param = NULL;
+ }
+ pp_pragma(pragmas, pragma, param);
+ }
+ break;
+
+ case TOKEN_LINE:
+ id = (const char *) (&prod[i]);
+ i += _mesa_strlen (id) + 1;
+
+ if (state.cond.top->effective) {
+ slang_string buffer;
+ GLuint count;
+ GLint results[2];
+ expand_state es;
+
+ slang_string_init (&buffer);
+ state.line++;
+ es.output = &buffer;
+ es.input = id;
+ es.state = &state;
+ if (!expand (&es, &state.symbols))
+ goto error;
+
+ pp_annotate (output, "// #line ");
+ count = execute_expressions (output, eid,
+ (const byte *) (slang_string_cstr (&buffer)),
+ results, state.elog);
+ slang_string_free (&buffer);
+ if (count == 0)
+ goto error;
+
+ state.line = results[0] - 1;
+ if (count == 2)
+ state.file = results[1];
+ }
+ break;
+ }
+ }
+ }
+
+ /* Check for missing #endifs. */
+ if (state.cond.top->endif_required) {
+ slang_info_log_error (elog, "#endif expected but end of source found.");
+ goto error;
+ }
+
+ grammar_alloc_free(prod);
+ pp_state_free (&state);
+ return GL_TRUE;
+
+error:
+ grammar_alloc_free(prod);
+ pp_state_free (&state);
+ return GL_FALSE;
+}
+
+
+/**
+ * Remove the continuation characters from the input string.
+ * This is the very first step in preprocessing and is effective
+ * even inside comment blocks.
+ * If there is a whitespace between a backslash and a newline,
+ * this is not considered as a line continuation.
+ * \return GL_TRUE for success, GL_FALSE otherwise.
+ */
+static GLboolean
+_slang_preprocess_backslashes(slang_string *output,
+ const char *input)
+{
+ while (*input) {
+ if (input[0] == '\\') {
+ /* If a newline follows, eat the backslash and the newline. */
+ if (input[1] == '\r') {
+ if (input[2] == '\n') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else if (input[1] == '\n') {
+ if (input[2] == '\r') {
+ input += 3;
+ } else {
+ input += 2;
+ }
+ } else {
+ /* Leave the backslash alone. */
+ slang_string_pushc(output, *input++);
+ }
+ } else {
+ slang_string_pushc(output, *input++);
+ }
+ }
+ return GL_TRUE;
+}
+
+
+/**
+ * Run preprocessor on source code.
+ * \param extensions indicates which GL extensions are enabled
+ * \param output the post-process results
+ * \param input the input text
+ * \param elog log to record warnings, errors
+ * \param extensions out extension settings
+ * \param pragmas in/out #pragma settings
+ * \return GL_TRUE for success, GL_FALSE for error
+ */
+GLboolean
+_slang_preprocess_directives(slang_string *output,
+ const char *input,
+ slang_info_log *elog,
+ const struct gl_extensions *extensions,
+ struct gl_sl_pragmas *pragmas)
+{
+ grammar pid, eid;
+ GLboolean success;
+ slang_string without_backslashes;
+
+ pid = grammar_load_from_text ((const byte *) (slang_pp_directives_syn));
+ if (pid == 0) {
+ grammar_error_to_log (elog);
+ return GL_FALSE;
+ }
+ eid = grammar_load_from_text ((const byte *) (slang_pp_expression_syn));
+ if (eid == 0) {
+ grammar_error_to_log (elog);
+ grammar_destroy (pid);
+ return GL_FALSE;
+ }
+
+ slang_string_init(&without_backslashes);
+ success = _slang_preprocess_backslashes(&without_backslashes, input);
+
+ if (0) {
+ _mesa_printf("Pre-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(&without_backslashes));
+ _mesa_printf("----------------------\n");
+ }
+
+ if (success) {
+ success = preprocess_source(output,
+ slang_string_cstr(&without_backslashes),
+ pid,
+ eid,
+ elog,
+ extensions,
+ pragmas);
+ }
+
+ slang_string_free(&without_backslashes);
+ grammar_destroy (eid);
+ grammar_destroy (pid);
+
+ if (0) {
+ _mesa_printf("Post-processed shader:\n");
+ _mesa_printf("%s", slang_string_cstr(output));
+ _mesa_printf("----------------------\n");
+ }
+
+ return success;
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_preprocess.h b/mesalib/src/mesa/shader/slang/slang_preprocess.h
new file mode 100644
index 000000000..f344820da
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_preprocess.h
@@ -0,0 +1,41 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 SLANG_PREPROCESS_H
+#define SLANG_PREPROCESS_H
+
+#include "slang_compile.h"
+#include "slang_log.h"
+
+
+extern GLboolean
+_slang_preprocess_version (const char *, GLuint *, GLuint *, slang_info_log *);
+
+extern GLboolean
+_slang_preprocess_directives(slang_string *output, const char *input,
+ slang_info_log *,
+ const struct gl_extensions *extensions,
+ struct gl_sl_pragmas *pragmas);
+
+#endif /* SLANG_PREPROCESS_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_print.c b/mesalib/src/mesa/shader/slang/slang_print.c
new file mode 100644
index 000000000..98c787753
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_print.c
@@ -0,0 +1,883 @@
+
+/**
+ * Dump/print a slang_operation tree
+ */
+
+
+#include "main/imports.h"
+#include "slang_compile.h"
+#include "slang_print.h"
+
+
+static void
+spaces(int n)
+{
+ while (n--)
+ printf(" ");
+}
+
+
+static void
+print_type(const slang_fully_specified_type *t)
+{
+ switch (t->qualifier) {
+ case SLANG_QUAL_NONE:
+ /*printf("");*/
+ break;
+ case SLANG_QUAL_CONST:
+ printf("const ");
+ break;
+ case SLANG_QUAL_ATTRIBUTE:
+ printf("attrib ");
+ break;
+ case SLANG_QUAL_VARYING:
+ printf("varying ");
+ break;
+ case SLANG_QUAL_UNIFORM:
+ printf("uniform ");
+ break;
+ case SLANG_QUAL_OUT:
+ printf("output ");
+ break;
+ case SLANG_QUAL_INOUT:
+ printf("inout ");
+ break;
+ case SLANG_QUAL_FIXEDOUTPUT:
+ printf("fixedoutput");
+ break;
+ case SLANG_QUAL_FIXEDINPUT:
+ printf("fixedinput");
+ break;
+ default:
+ printf("unknown qualifer!");
+ }
+
+ switch (t->specifier.type) {
+ case SLANG_SPEC_VOID:
+ printf("void");
+ break;
+ case SLANG_SPEC_BOOL:
+ printf("bool");
+ break;
+ case SLANG_SPEC_BVEC2:
+ printf("bvec2");
+ break;
+ case SLANG_SPEC_BVEC3:
+ printf("bvec3");
+ break;
+ case SLANG_SPEC_BVEC4:
+ printf("bvec4");
+ break;
+ case SLANG_SPEC_INT:
+ printf("int");
+ break;
+ case SLANG_SPEC_IVEC2:
+ printf("ivec2");
+ break;
+ case SLANG_SPEC_IVEC3:
+ printf("ivec3");
+ break;
+ case SLANG_SPEC_IVEC4:
+ printf("ivec4");
+ break;
+ case SLANG_SPEC_FLOAT:
+ printf("float");
+ break;
+ case SLANG_SPEC_VEC2:
+ printf("vec2");
+ break;
+ case SLANG_SPEC_VEC3:
+ printf("vec3");
+ break;
+ case SLANG_SPEC_VEC4:
+ printf("vec4");
+ break;
+ case SLANG_SPEC_MAT2:
+ printf("mat2");
+ break;
+ case SLANG_SPEC_MAT3:
+ printf("mat3");
+ break;
+ case SLANG_SPEC_MAT4:
+ printf("mat4");
+ break;
+ case SLANG_SPEC_MAT23:
+ printf("mat2x3");
+ break;
+ case SLANG_SPEC_MAT32:
+ printf("mat3x2");
+ break;
+ case SLANG_SPEC_MAT24:
+ printf("mat2x4");
+ break;
+ case SLANG_SPEC_MAT42:
+ printf("mat4x2");
+ break;
+ case SLANG_SPEC_MAT34:
+ printf("mat3x4");
+ break;
+ case SLANG_SPEC_MAT43:
+ printf("mat4x3");
+ break;
+ case SLANG_SPEC_SAMPLER1D:
+ printf("sampler1D");
+ break;
+ case SLANG_SPEC_SAMPLER2D:
+ printf("sampler2D");
+ break;
+ case SLANG_SPEC_SAMPLER3D:
+ printf("sampler3D");
+ break;
+ case SLANG_SPEC_SAMPLERCUBE:
+ printf("samplerCube");
+ break;
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ printf("sampler1DShadow");
+ break;
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ printf("sampler2DShadow");
+ break;
+ case SLANG_SPEC_STRUCT:
+ printf("struct");
+ break;
+ case SLANG_SPEC_ARRAY:
+ printf("array");
+ break;
+ default:
+ printf("unknown type");
+ }
+ /*printf("\n");*/
+}
+
+
+static void
+print_variable(const slang_variable *v, int indent)
+{
+ spaces(indent);
+ printf("VAR ");
+ print_type(&v->type);
+ printf(" %s (at %p)", (char *) v->a_name, (void *) v);
+ if (v->initializer) {
+ printf(" :=\n");
+ slang_print_tree(v->initializer, indent + 3);
+ }
+ else {
+ printf(";\n");
+ }
+}
+
+
+static void
+print_binary(const slang_operation *op, const char *oper, int indent)
+{
+ assert(op->num_children == 2);
+#if 0
+ printf("binary at %p locals=%p outer=%p\n",
+ (void *) op,
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+#endif
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("%s at %p locals=%p outer=%p\n",
+ oper, (void *) op, (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ slang_print_tree(&op->children[1], indent + 3);
+}
+
+
+static void
+print_generic2(const slang_operation *op, const char *oper,
+ const char *s, int indent)
+{
+ GLuint i;
+ if (oper) {
+ spaces(indent);
+ printf("%s %s at %p locals=%p outer=%p\n",
+ oper, s, (void *) op, (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ }
+ for (i = 0; i < op->num_children; i++) {
+ spaces(indent);
+ printf("//child %u of %u:\n", i, op->num_children);
+ slang_print_tree(&op->children[i], indent);
+ }
+}
+
+static void
+print_generic(const slang_operation *op, const char *oper, int indent)
+{
+ print_generic2(op, oper, "", indent);
+}
+
+
+static const slang_variable_scope *
+find_scope(const slang_variable_scope *s, slang_atom name)
+{
+ GLuint i;
+ for (i = 0; i < s->num_variables; i++) {
+ if (s->variables[i]->a_name == name)
+ return s;
+ }
+ if (s->outer_scope)
+ return find_scope(s->outer_scope, name);
+ else
+ return NULL;
+}
+
+static const slang_variable *
+find_var(const slang_variable_scope *s, slang_atom name)
+{
+ GLuint i;
+ for (i = 0; i < s->num_variables; i++) {
+ if (s->variables[i]->a_name == name)
+ return s->variables[i];
+ }
+ if (s->outer_scope)
+ return find_var(s->outer_scope, name);
+ else
+ return NULL;
+}
+
+
+void
+slang_print_tree(const slang_operation *op, int indent)
+{
+ GLuint i;
+
+ switch (op->type) {
+
+ case SLANG_OPER_NONE:
+ spaces(indent);
+ printf("SLANG_OPER_NONE\n");
+ break;
+
+ case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+ spaces(indent);
+ printf("{ locals=%p outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope);
+ print_generic(op, NULL, indent+3);
+ spaces(indent);
+ printf("}\n");
+ break;
+
+ case SLANG_OPER_BLOCK_NEW_SCOPE:
+ case SLANG_OPER_NON_INLINED_CALL:
+ spaces(indent);
+ printf("{{ // new scope locals=%p outer=%p: ",
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ for (i = 0; i < op->locals->num_variables; i++) {
+ printf("%s ", (char *) op->locals->variables[i]->a_name);
+ }
+ printf("\n");
+ print_generic(op, NULL, indent+3);
+ spaces(indent);
+ printf("}}\n");
+ break;
+
+ case SLANG_OPER_VARIABLE_DECL:
+ assert(op->num_children == 0 || op->num_children == 1);
+ {
+ slang_variable *v;
+ v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
+ if (v) {
+ const slang_variable_scope *scope;
+ spaces(indent);
+ printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
+ print_type(&v->type);
+ printf(" %s (%p)", (char *) op->a_id,
+ (void *) find_var(op->locals, op->a_id));
+
+ scope = find_scope(op->locals, op->a_id);
+ printf(" (in scope %p) ", (void *) scope);
+ assert(scope);
+ if (op->num_children == 1) {
+ printf(" :=\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ }
+ else if (v->initializer) {
+ printf(" := INITIALIZER\n");
+ slang_print_tree(v->initializer, indent + 3);
+ }
+ else {
+ printf(";\n");
+ }
+ /*
+ spaces(indent);
+ printf("TYPE: ");
+ print_type(&v->type);
+ spaces(indent);
+ printf("ADDR: %d size: %d\n", v->address, v->size);
+ */
+ }
+ else {
+ spaces(indent);
+ printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
+ }
+ }
+ break;
+
+ case SLANG_OPER_ASM:
+ spaces(indent);
+ printf("ASM: %s at %p locals=%p outer=%p\n",
+ (char *) op->a_id,
+ (void *) op,
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ print_generic(op, "ASM", indent+3);
+ break;
+
+ case SLANG_OPER_BREAK:
+ spaces(indent);
+ printf("BREAK\n");
+ break;
+
+ case SLANG_OPER_CONTINUE:
+ spaces(indent);
+ printf("CONTINUE\n");
+ break;
+
+ case SLANG_OPER_DISCARD:
+ spaces(indent);
+ printf("DISCARD\n");
+ break;
+
+ case SLANG_OPER_RETURN:
+ spaces(indent);
+ printf("RETURN\n");
+ if (op->num_children > 0)
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
+ case SLANG_OPER_RETURN_INLINED:
+ spaces(indent);
+ printf("RETURN_INLINED\n");
+ if (op->num_children > 0)
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
+ case SLANG_OPER_LABEL:
+ spaces(indent);
+ printf("LABEL %s\n", (char *) op->a_id);
+ break;
+
+ case SLANG_OPER_EXPRESSION:
+ spaces(indent);
+ printf("EXPR: locals=%p outer=%p\n",
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
+ case SLANG_OPER_IF:
+ spaces(indent);
+ printf("IF\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("THEN\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ spaces(indent);
+ printf("ELSE\n");
+ slang_print_tree(&op->children[2], indent + 3);
+ spaces(indent);
+ printf("ENDIF\n");
+ break;
+
+ case SLANG_OPER_WHILE:
+ assert(op->num_children == 2);
+ spaces(indent);
+ printf("WHILE LOOP: locals = %p\n", (void *) op->locals);
+ indent += 3;
+ spaces(indent);
+ printf("WHILE cond:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("WHILE body:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ indent -= 3;
+ spaces(indent);
+ printf("END WHILE LOOP\n");
+ break;
+
+ case SLANG_OPER_DO:
+ spaces(indent);
+ printf("DO LOOP: locals = %p\n", (void *) op->locals);
+ indent += 3;
+ spaces(indent);
+ printf("DO body:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("DO cond:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ indent -= 3;
+ spaces(indent);
+ printf("END DO LOOP\n");
+ break;
+
+ case SLANG_OPER_FOR:
+ spaces(indent);
+ printf("FOR LOOP: locals = %p\n", (void *) op->locals);
+ indent += 3;
+ spaces(indent);
+ printf("FOR init:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("FOR condition:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ spaces(indent);
+ printf("FOR step:\n");
+ slang_print_tree(&op->children[2], indent + 3);
+ spaces(indent);
+ printf("FOR body:\n");
+ slang_print_tree(&op->children[3], indent + 3);
+ indent -= 3;
+ spaces(indent);
+ printf("ENDFOR\n");
+ /*
+ print_generic(op, "FOR", indent + 3);
+ */
+ break;
+
+ case SLANG_OPER_VOID:
+ spaces(indent);
+ printf("(oper-void)\n");
+ break;
+
+ case SLANG_OPER_LITERAL_BOOL:
+ spaces(indent);
+ printf("LITERAL (");
+ for (i = 0; i < op->literal_size; i++)
+ printf("%s ", op->literal[0] ? "TRUE" : "FALSE");
+ printf(")\n");
+
+ break;
+
+ case SLANG_OPER_LITERAL_INT:
+ spaces(indent);
+ printf("LITERAL (");
+ for (i = 0; i < op->literal_size; i++)
+ printf("%d ", (int) op->literal[i]);
+ printf(")\n");
+ break;
+
+ case SLANG_OPER_LITERAL_FLOAT:
+ spaces(indent);
+ printf("LITERAL (");
+ for (i = 0; i < op->literal_size; i++)
+ printf("%f ", op->literal[i]);
+ printf(")\n");
+ break;
+
+ case SLANG_OPER_IDENTIFIER:
+ {
+ const slang_variable_scope *scope;
+ spaces(indent);
+ if (op->var && op->var->a_name) {
+ scope = find_scope(op->locals, op->var->a_name);
+ printf("VAR %s (in scope %p)\n", (char *) op->var->a_name,
+ (void *) scope);
+ assert(scope);
+ }
+ else {
+ scope = find_scope(op->locals, op->a_id);
+ printf("VAR' %s (in scope %p) locals=%p outer=%p\n",
+ (char *) op->a_id,
+ (void *) scope,
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ /*assert(scope);*/
+ }
+ }
+ break;
+
+ case SLANG_OPER_SEQUENCE:
+ print_generic(op, "COMMA-SEQ", indent+3);
+ break;
+
+ case SLANG_OPER_ASSIGN:
+ spaces(indent);
+ printf("ASSIGNMENT locals=%p outer=%p\n",
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ print_binary(op, ":=", indent);
+ break;
+
+ case SLANG_OPER_ADDASSIGN:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "+=", indent);
+ break;
+
+ case SLANG_OPER_SUBASSIGN:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "-=", indent);
+ break;
+
+ case SLANG_OPER_MULASSIGN:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "*=", indent);
+ break;
+
+ case SLANG_OPER_DIVASSIGN:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "/=", indent);
+ break;
+
+ /*SLANG_OPER_MODASSIGN,*/
+ /*SLANG_OPER_LSHASSIGN,*/
+ /*SLANG_OPER_RSHASSIGN,*/
+ /*SLANG_OPER_ORASSIGN,*/
+ /*SLANG_OPER_XORASSIGN,*/
+ /*SLANG_OPER_ANDASSIGN,*/
+ case SLANG_OPER_SELECT:
+ spaces(indent);
+ printf("SLANG_OPER_SELECT n=%d\n", op->num_children);
+ assert(op->num_children == 3);
+ slang_print_tree(&op->children[0], indent+3);
+ spaces(indent);
+ printf("?\n");
+ slang_print_tree(&op->children[1], indent+3);
+ spaces(indent);
+ printf(":\n");
+ slang_print_tree(&op->children[2], indent+3);
+ break;
+
+ case SLANG_OPER_LOGICALOR:
+ print_binary(op, "||", indent);
+ break;
+
+ case SLANG_OPER_LOGICALXOR:
+ print_binary(op, "^^", indent);
+ break;
+
+ case SLANG_OPER_LOGICALAND:
+ print_binary(op, "&&", indent);
+ break;
+
+ /*SLANG_OPER_BITOR*/
+ /*SLANG_OPER_BITXOR*/
+ /*SLANG_OPER_BITAND*/
+ case SLANG_OPER_EQUAL:
+ print_binary(op, "==", indent);
+ break;
+
+ case SLANG_OPER_NOTEQUAL:
+ print_binary(op, "!=", indent);
+ break;
+
+ case SLANG_OPER_LESS:
+ print_binary(op, "<", indent);
+ break;
+
+ case SLANG_OPER_GREATER:
+ print_binary(op, ">", indent);
+ break;
+
+ case SLANG_OPER_LESSEQUAL:
+ print_binary(op, "<=", indent);
+ break;
+
+ case SLANG_OPER_GREATEREQUAL:
+ print_binary(op, ">=", indent);
+ break;
+
+ /*SLANG_OPER_LSHIFT*/
+ /*SLANG_OPER_RSHIFT*/
+ case SLANG_OPER_ADD:
+ print_binary(op, "+", indent);
+ break;
+
+ case SLANG_OPER_SUBTRACT:
+ print_binary(op, "-", indent);
+ break;
+
+ case SLANG_OPER_MULTIPLY:
+ print_binary(op, "*", indent);
+ break;
+
+ case SLANG_OPER_DIVIDE:
+ print_binary(op, "/", indent);
+ break;
+
+ /*SLANG_OPER_MODULUS*/
+ case SLANG_OPER_PREINCREMENT:
+ spaces(indent);
+ printf("PRE++\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case SLANG_OPER_PREDECREMENT:
+ spaces(indent);
+ printf("PRE--\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case SLANG_OPER_PLUS:
+ spaces(indent);
+ printf("SLANG_OPER_PLUS\n");
+ break;
+
+ case SLANG_OPER_MINUS:
+ spaces(indent);
+ printf("SLANG_OPER_MINUS\n");
+ break;
+
+ /*SLANG_OPER_COMPLEMENT*/
+ case SLANG_OPER_NOT:
+ spaces(indent);
+ printf("NOT\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case SLANG_OPER_SUBSCRIPT:
+ spaces(indent);
+ printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n",
+ (void *) op->locals,
+ (void *) op->locals->outer_scope);
+ print_generic(op, NULL, indent+3);
+ break;
+
+ case SLANG_OPER_CALL:
+#if 0
+ slang_function *fun
+ = _slang_function_locate(A->space.funcs, oper->a_id,
+ oper->children,
+ oper->num_children, &A->space, A->atoms);
+#endif
+ spaces(indent);
+ printf("CALL %s(\n", (char *) op->a_id);
+ for (i = 0; i < op->num_children; i++) {
+ slang_print_tree(&op->children[i], indent+3);
+ if (i + 1 < op->num_children) {
+ spaces(indent + 3);
+ printf(",\n");
+ }
+ }
+ spaces(indent);
+ printf(")\n");
+ break;
+
+ case SLANG_OPER_METHOD:
+ spaces(indent);
+ printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id);
+ break;
+
+ case SLANG_OPER_FIELD:
+ spaces(indent);
+ printf("FIELD %s of\n", (char*) op->a_id);
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case SLANG_OPER_POSTINCREMENT:
+ spaces(indent);
+ printf("POST++\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case SLANG_OPER_POSTDECREMENT:
+ spaces(indent);
+ printf("POST--\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ default:
+ printf("unknown op->type %d\n", (int) op->type);
+ }
+
+}
+
+
+
+void
+slang_print_function(const slang_function *f, GLboolean body)
+{
+ GLuint i;
+
+#if 0
+ if (_mesa_strcmp((char *) f->header.a_name, "main") != 0)
+ return;
+#endif
+
+ printf("FUNCTION %s ( scope=%p\n",
+ (char *) f->header.a_name, (void *) f->parameters);
+
+ for (i = 0; i < f->param_count; i++) {
+ print_variable(f->parameters->variables[i], 3);
+ }
+
+ printf(") param scope = %p\n", (void *) f->parameters);
+
+ if (body && f->body)
+ slang_print_tree(f->body, 0);
+}
+
+
+
+
+
+const char *
+slang_type_qual_string(slang_type_qualifier q)
+{
+ switch (q) {
+ case SLANG_QUAL_NONE:
+ return "none";
+ case SLANG_QUAL_CONST:
+ return "const";
+ case SLANG_QUAL_ATTRIBUTE:
+ return "attribute";
+ case SLANG_QUAL_VARYING:
+ return "varying";
+ case SLANG_QUAL_UNIFORM:
+ return "uniform";
+ case SLANG_QUAL_OUT:
+ return "out";
+ case SLANG_QUAL_INOUT:
+ return "inout";
+ case SLANG_QUAL_FIXEDOUTPUT:
+ return "fixedoutput";
+ case SLANG_QUAL_FIXEDINPUT:
+ return "fixedinputk";
+ default:
+ return "qual?";
+ }
+}
+
+
+static const char *
+slang_type_string(slang_type_specifier_type t)
+{
+ switch (t) {
+ case SLANG_SPEC_VOID:
+ return "void";
+ case SLANG_SPEC_BOOL:
+ return "bool";
+ case SLANG_SPEC_BVEC2:
+ return "bvec2";
+ case SLANG_SPEC_BVEC3:
+ return "bvec3";
+ case SLANG_SPEC_BVEC4:
+ return "bvec4";
+ case SLANG_SPEC_INT:
+ return "int";
+ case SLANG_SPEC_IVEC2:
+ return "ivec2";
+ case SLANG_SPEC_IVEC3:
+ return "ivec3";
+ case SLANG_SPEC_IVEC4:
+ return "ivec4";
+ case SLANG_SPEC_FLOAT:
+ return "float";
+ case SLANG_SPEC_VEC2:
+ return "vec2";
+ case SLANG_SPEC_VEC3:
+ return "vec3";
+ case SLANG_SPEC_VEC4:
+ return "vec4";
+ case SLANG_SPEC_MAT2:
+ return "mat2";
+ case SLANG_SPEC_MAT3:
+ return "mat3";
+ case SLANG_SPEC_MAT4:
+ return "mat4";
+ case SLANG_SPEC_SAMPLER1D:
+ return "sampler1D";
+ case SLANG_SPEC_SAMPLER2D:
+ return "sampler2D";
+ case SLANG_SPEC_SAMPLER3D:
+ return "sampler3D";
+ case SLANG_SPEC_SAMPLERCUBE:
+ return "samplerCube";
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ return "sampler1DShadow";
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ return "sampler2DShadow";
+ case SLANG_SPEC_SAMPLER2DRECT:
+ return "sampler2DRect";
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return "sampler2DRectShadow";
+ case SLANG_SPEC_STRUCT:
+ return "struct";
+ case SLANG_SPEC_ARRAY:
+ return "array";
+ default:
+ return "type?";
+ }
+}
+
+
+static const char *
+slang_fq_type_string(const slang_fully_specified_type *t)
+{
+ static char str[1000];
+ sprintf(str, "%s %s", slang_type_qual_string(t->qualifier),
+ slang_type_string(t->specifier.type));
+ return str;
+}
+
+
+void
+slang_print_type(const slang_fully_specified_type *t)
+{
+ printf("%s %s", slang_type_qual_string(t->qualifier),
+ slang_type_string(t->specifier.type));
+}
+
+
+#if 0
+static char *
+slang_var_string(const slang_variable *v)
+{
+ static char str[1000];
+ sprintf(str, "%s : %s",
+ (char *) v->a_name,
+ slang_fq_type_string(&v->type));
+ return str;
+}
+#endif
+
+
+void
+slang_print_variable(const slang_variable *v)
+{
+ printf("Name: %s\n", (char *) v->a_name);
+ printf("Type: %s\n", slang_fq_type_string(&v->type));
+}
+
+
+void
+_slang_print_var_scope(const slang_variable_scope *vars, int indent)
+{
+ GLuint i;
+
+ spaces(indent);
+ printf("Var scope %p %d vars:\n", (void *) vars, vars->num_variables);
+ for (i = 0; i < vars->num_variables; i++) {
+ spaces(indent + 3);
+ printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
+ }
+ spaces(indent + 3);
+ printf("outer_scope = %p\n", (void*) vars->outer_scope);
+
+ if (vars->outer_scope) {
+ /*spaces(indent + 3);*/
+ _slang_print_var_scope(vars->outer_scope, indent + 3);
+ }
+}
+
+
+
+int
+slang_checksum_tree(const slang_operation *op)
+{
+ int s = op->num_children;
+ GLuint i;
+
+ for (i = 0; i < op->num_children; i++) {
+ s += slang_checksum_tree(&op->children[i]);
+ }
+ return s;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_print.h b/mesalib/src/mesa/shader/slang/slang_print.h
new file mode 100644
index 000000000..46605c806
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_print.h
@@ -0,0 +1,29 @@
+
+
+#ifndef SLANG_PRINT
+#define SLANG_PRINT
+
+extern void
+slang_print_function(const slang_function *f, GLboolean body);
+
+extern void
+slang_print_tree(const slang_operation *op, int indent);
+
+extern const char *
+slang_type_qual_string(slang_type_qualifier q);
+
+extern void
+slang_print_type(const slang_fully_specified_type *t);
+
+extern void
+slang_print_variable(const slang_variable *v);
+
+extern void
+_slang_print_var_scope(const slang_variable_scope *s, int indent);
+
+
+extern int
+slang_checksum_tree(const slang_operation *op);
+
+#endif /* SLANG_PRINT */
+
diff --git a/mesalib/src/mesa/shader/slang/slang_simplify.c b/mesalib/src/mesa/shader/slang/slang_simplify.c
new file mode 100644
index 000000000..b8a21f642
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_simplify.c
@@ -0,0 +1,526 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2005-2008 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.
+ */
+
+/**
+ * Functions for constant folding, built-in constant lookup, and function
+ * call casting.
+ */
+
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/get.h"
+#include "slang_compile.h"
+#include "slang_codegen.h"
+#include "slang_simplify.h"
+#include "slang_print.h"
+
+
+#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#endif
+#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#endif
+#ifndef GL_MAX_VARYING_VECTORS
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#endif
+
+
+/**
+ * Lookup the value of named constant, such as gl_MaxLights.
+ * \return value of constant, or -1 if unknown
+ */
+GLint
+_slang_lookup_constant(const char *name)
+{
+ struct constant_info {
+ const char *Name;
+ const GLenum Token;
+ };
+ static const struct constant_info info[] = {
+ { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
+ { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
+ { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS },
+ { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
+ { "gl_MaxLights", GL_MAX_LIGHTS },
+ { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
+ { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
+ { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
+ { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
+ { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
+ { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
+ { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
+#if FEATURE_es2_glsl
+ { "gl_MaxVertexUniformVectors", GL_MAX_VERTEX_UNIFORM_VECTORS },
+ { "gl_MaxVaryingVectors", GL_MAX_VARYING_VECTORS },
+ { "gl_MaxFragmentUniformVectors", GL_MAX_FRAGMENT_UNIFORM_VECTORS },
+#endif
+ { NULL, 0 }
+ };
+ GLuint i;
+
+ for (i = 0; info[i].Name; i++) {
+ if (strcmp(info[i].Name, name) == 0) {
+ /* found */
+ GLint value = -1;
+ _mesa_GetIntegerv(info[i].Token, &value);
+ ASSERT(value >= 0); /* sanity check that glGetFloatv worked */
+ return value;
+ }
+ }
+ return -1;
+}
+
+
+static slang_operation_type
+literal_type(slang_operation_type t1, slang_operation_type t2)
+{
+ if (t1 == SLANG_OPER_LITERAL_FLOAT || t2 == SLANG_OPER_LITERAL_FLOAT)
+ return SLANG_OPER_LITERAL_FLOAT;
+ else
+ return SLANG_OPER_LITERAL_INT;
+}
+
+
+/**
+ * Recursively traverse an AST tree, applying simplifications wherever
+ * possible.
+ * At the least, we do constant folding. We need to do that much so that
+ * compile-time expressions can be evaluated for things like array
+ * declarations. I.e.: float foo[3 + 5];
+ */
+void
+_slang_simplify(slang_operation *oper,
+ const slang_name_space * space,
+ slang_atom_pool * atoms)
+{
+ GLboolean isFloat[4];
+ GLboolean isBool[4];
+ GLuint i, n;
+
+ if (oper->type == SLANG_OPER_IDENTIFIER) {
+ /* see if it's a named constant */
+ GLint value = _slang_lookup_constant((char *) oper->a_id);
+ /*printf("value[%s] = %d\n", (char*) oper->a_id, value);*/
+ if (value >= 0) {
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = (GLfloat) value;
+ oper->type = SLANG_OPER_LITERAL_INT;
+ return;
+ }
+ /* look for user-defined constant */
+ {
+ slang_variable *var;
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ if (var) {
+ if (var->type.qualifier == SLANG_QUAL_CONST &&
+ var->initializer &&
+ (var->initializer->type == SLANG_OPER_LITERAL_INT ||
+ var->initializer->type == SLANG_OPER_LITERAL_FLOAT)) {
+ oper->literal[0] = var->initializer->literal[0];
+ oper->literal[1] = var->initializer->literal[1];
+ oper->literal[2] = var->initializer->literal[2];
+ oper->literal[3] = var->initializer->literal[3];
+ oper->literal_size = var->initializer->literal_size;
+ oper->type = var->initializer->type;
+ /*
+ printf("value[%s] = %f\n",
+ (char*) oper->a_id, oper->literal[0]);
+ */
+ return;
+ }
+ }
+ }
+ }
+
+ /* first, simplify children */
+ for (i = 0; i < oper->num_children; i++) {
+ _slang_simplify(&oper->children[i], space, atoms);
+ }
+
+ /* examine children */
+ n = MIN2(oper->num_children, 4);
+ for (i = 0; i < n; i++) {
+ isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT ||
+ oper->children[i].type == SLANG_OPER_LITERAL_INT);
+ isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL);
+ }
+
+ if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
+ /* probably simple arithmetic */
+ switch (oper->type) {
+ case SLANG_OPER_ADD:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] + oper->children[1].literal[i];
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ oper->type = literal_type(oper->children[0].type,
+ oper->children[1].type);
+ slang_operation_destruct(oper); /* frees unused children */
+ return;
+ case SLANG_OPER_SUBTRACT:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] - oper->children[1].literal[i];
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ oper->type = literal_type(oper->children[0].type,
+ oper->children[1].type);
+ slang_operation_destruct(oper);
+ return;
+ case SLANG_OPER_MULTIPLY:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] * oper->children[1].literal[i];
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ oper->type = literal_type(oper->children[0].type,
+ oper->children[1].type);
+ slang_operation_destruct(oper);
+ return;
+ case SLANG_OPER_DIVIDE:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] / oper->children[1].literal[i];
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ oper->type = literal_type(oper->children[0].type,
+ oper->children[1].type);
+ slang_operation_destruct(oper);
+ return;
+ default:
+ ; /* nothing */
+ }
+ }
+
+ if (oper->num_children == 1 && isFloat[0]) {
+ switch (oper->type) {
+ case SLANG_OPER_MINUS:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i] = -oper->children[0].literal[i];
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ return;
+ case SLANG_OPER_PLUS:
+ COPY_4V(oper->literal, oper->children[0].literal);
+ oper->literal_size = oper->children[0].literal_size;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ return;
+ default:
+ ; /* nothing */
+ }
+ }
+
+ if (oper->num_children == 2 && isBool[0] && isBool[1]) {
+ /* simple boolean expression */
+ switch (oper->type) {
+ case SLANG_OPER_LOGICALAND:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a && b);
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_BOOL;
+ return;
+ case SLANG_OPER_LOGICALOR:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a || b);
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_BOOL;
+ return;
+ case SLANG_OPER_LOGICALXOR:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a ^ b);
+ }
+ oper->literal_size = oper->children[0].literal_size;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_BOOL;
+ return;
+ default:
+ ; /* nothing */
+ }
+ }
+
+ if (oper->num_children == 4
+ && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
+ /* vec4(flt, flt, flt, flt) constructor */
+ if (oper->type == SLANG_OPER_CALL) {
+ if (strcmp((char *) oper->a_id, "vec4") == 0) {
+ oper->literal[0] = oper->children[0].literal[0];
+ oper->literal[1] = oper->children[1].literal[0];
+ oper->literal[2] = oper->children[2].literal[0];
+ oper->literal[3] = oper->children[3].literal[0];
+ oper->literal_size = 4;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ return;
+ }
+ }
+ }
+
+ if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) {
+ /* vec3(flt, flt, flt) constructor */
+ if (oper->type == SLANG_OPER_CALL) {
+ if (strcmp((char *) oper->a_id, "vec3") == 0) {
+ oper->literal[0] = oper->children[0].literal[0];
+ oper->literal[1] = oper->children[1].literal[0];
+ oper->literal[2] = oper->children[2].literal[0];
+ oper->literal[3] = oper->literal[2];
+ oper->literal_size = 3;
+ slang_operation_destruct(oper);
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ return;
+ }
+ }
+ }
+
+ if (oper->num_children == 2 && isFloat[0] && isFloat[1]) {
+ /* vec2(flt, flt) constructor */
+ if (oper->type == SLANG_OPER_CALL) {
+ if (strcmp((char *) oper->a_id, "vec2") == 0) {
+ oper->literal[0] = oper->children[0].literal[0];
+ oper->literal[1] = oper->children[1].literal[0];
+ oper->literal[2] = oper->literal[1];
+ oper->literal[3] = oper->literal[1];
+ oper->literal_size = 2;
+ slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ assert(oper->num_children == 0);
+ return;
+ }
+ }
+ }
+
+ if (oper->num_children == 1 && isFloat[0]) {
+ /* vec2/3/4(flt, flt) constructor */
+ if (oper->type == SLANG_OPER_CALL) {
+ const char *func = (const char *) oper->a_id;
+ if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') {
+ oper->literal[0] =
+ oper->literal[1] =
+ oper->literal[2] =
+ oper->literal[3] = oper->children[0].literal[0];
+ oper->literal_size = func[3] - '0';
+ assert(oper->literal_size >= 2);
+ assert(oper->literal_size <= 4);
+ slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */
+ oper->type = SLANG_OPER_LITERAL_FLOAT;
+ assert(oper->num_children == 0);
+ return;
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Insert casts to try to adapt actual parameters to formal parameters for a
+ * function call when an exact match for the parameter types is not found.
+ * Example:
+ * void foo(int i, bool b) {}
+ * x = foo(3.15, 9);
+ * Gets translated into:
+ * x = foo(int(3.15), bool(9))
+ */
+GLboolean
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log)
+{
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ const int numParams = fun->param_count - haveRetValue;
+ int i;
+ int dbg = 0;
+
+ if (dbg)
+ printf("Adapt call of %d args to func %s (%d params)\n",
+ callOper->num_children, (char*) fun->header.a_name, numParams);
+
+ for (i = 0; i < numParams; i++) {
+ slang_typeinfo argType;
+ slang_variable *paramVar = fun->parameters->variables[i];
+
+ /* Get type of arg[i] */
+ if (!slang_typeinfo_construct(&argType))
+ return GL_FALSE;
+ if (!_slang_typeof_operation(&callOper->children[i], space,
+ &argType, atoms, log)) {
+ slang_typeinfo_destruct(&argType);
+ return GL_FALSE;
+ }
+
+ /* see if arg type matches parameter type */
+ if (!slang_type_specifier_equal(&argType.spec,
+ &paramVar->type.specifier)) {
+ /* need to adapt arg type to match param type */
+ const char *constructorName =
+ slang_type_specifier_type_to_string(paramVar->type.specifier.type);
+ slang_operation *child = slang_operation_new(1);
+
+ if (dbg)
+ printf("Need to adapt types of arg %d\n", i);
+
+ slang_operation_copy(child, &callOper->children[i]);
+ child->locals->outer_scope = callOper->children[i].locals;
+
+#if 0
+ if (_slang_sizeof_type_specifier(&argType.spec) >
+ _slang_sizeof_type_specifier(&paramVar->type.specifier)) {
+ }
+#endif
+
+ callOper->children[i].type = SLANG_OPER_CALL;
+ callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
+ callOper->children[i].num_children = 1;
+ callOper->children[i].children = child;
+ }
+
+ slang_typeinfo_destruct(&argType);
+ }
+
+ if (dbg) {
+ printf("===== New call to %s with cast arguments ===============\n",
+ (char*) fun->header.a_name);
+ slang_print_tree(callOper, 5);
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Adapt the arguments for a function call to match the parameters of
+ * the given function.
+ * This is for:
+ * 1. converting/casting argument types to match parameters
+ * 2. breaking up vector/matrix types into individual components to
+ * satisfy constructors.
+ */
+GLboolean
+_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log)
+{
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ const int numParams = fun->param_count - haveRetValue;
+ int i;
+ int dbg = 0;
+
+ if (dbg)
+ printf("Adapt %d args to %d parameters for %s\n",
+ callOper->num_children, numParams, (char *) fun->header.a_name);
+
+ /* Only try adapting for constructors */
+ if (fun->kind != SLANG_FUNC_CONSTRUCTOR)
+ return GL_FALSE;
+
+ if (callOper->num_children != numParams) {
+ /* number of arguments doesn't match number of parameters */
+
+ /* For constructor calls, we can try to unroll vector/matrix args
+ * into individual floats/ints and try to match the function params.
+ */
+ for (i = 0; i < numParams; i++) {
+ slang_typeinfo argType;
+ GLint argSz, j;
+
+ /* Get type of arg[i] */
+ if (!slang_typeinfo_construct(&argType))
+ return GL_FALSE;
+ if (!_slang_typeof_operation(&callOper->children[i], space,
+ &argType, atoms, log)) {
+ slang_typeinfo_destruct(&argType);
+ return GL_FALSE;
+ }
+
+ /*
+ paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
+ assert(paramSz == 1);
+ */
+ argSz = _slang_sizeof_type_specifier(&argType.spec);
+ if (argSz > 1) {
+ slang_operation origArg;
+ /* break up arg[i] into components */
+ if (dbg)
+ printf("Break up arg %d from 1 to %d elements\n", i, argSz);
+
+ slang_operation_construct(&origArg);
+ slang_operation_copy(&origArg, &callOper->children[i]);
+
+ /* insert argSz-1 new children/args */
+ for (j = 0; j < argSz - 1; j++) {
+ (void) slang_operation_insert(&callOper->num_children,
+ &callOper->children, i);
+ }
+
+ /* replace arg[i+j] with subscript/index oper */
+ for (j = 0; j < argSz; j++) {
+ callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
+ callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
+ callOper->children[i + j].num_children = 2;
+ callOper->children[i + j].children = slang_operation_new(2);
+ slang_operation_copy(&callOper->children[i + j].children[0],
+ &origArg);
+ callOper->children[i + j].children[1].type
+ = SLANG_OPER_LITERAL_INT;
+ callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
+ }
+ }
+ }
+ }
+
+ if (callOper->num_children < (GLuint) numParams) {
+ /* still not enough args for all params */
+ return GL_FALSE;
+ }
+ else if (callOper->num_children > (GLuint) numParams) {
+ /* now too many arguments */
+ /* just truncate */
+ callOper->num_children = (GLuint) numParams;
+ }
+
+ if (dbg) {
+ printf("===== New call to %s with adapted arguments ===============\n",
+ (char*) fun->header.a_name);
+ slang_print_tree(callOper, 5);
+ }
+
+ return GL_TRUE;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_simplify.h b/mesalib/src/mesa/shader/slang/slang_simplify.h
new file mode 100644
index 000000000..8689c23b1
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_simplify.h
@@ -0,0 +1,50 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2005-2008 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 SLANG_SIMPLIFY_H
+#define SLANG_SIMPLIFY_H
+
+
+extern GLint
+_slang_lookup_constant(const char *name);
+
+
+extern void
+_slang_simplify(slang_operation *oper,
+ const slang_name_space * space,
+ slang_atom_pool * atoms);
+
+
+extern GLboolean
+_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log);
+
+extern GLboolean
+_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
+ const slang_name_space * space,
+ slang_atom_pool * atoms, slang_info_log *log);
+
+
+#endif /* SLANG_SIMPLIFY_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_storage.c b/mesalib/src/mesa/shader/slang/slang_storage.c
new file mode 100644
index 000000000..e8b0fb774
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_storage.c
@@ -0,0 +1,316 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_storage.c
+ * slang variable storage
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_storage.h"
+#include "slang_mem.h"
+
+/* slang_storage_array */
+
+GLboolean
+slang_storage_array_construct(slang_storage_array * arr)
+{
+ arr->type = SLANG_STORE_AGGREGATE;
+ arr->aggregate = NULL;
+ arr->length = 0;
+ return GL_TRUE;
+}
+
+GLvoid
+slang_storage_array_destruct(slang_storage_array * arr)
+{
+ if (arr->aggregate != NULL) {
+ slang_storage_aggregate_destruct(arr->aggregate);
+ _slang_free(arr->aggregate);
+ }
+}
+
+/* slang_storage_aggregate */
+
+GLboolean
+slang_storage_aggregate_construct(slang_storage_aggregate * agg)
+{
+ agg->arrays = NULL;
+ agg->count = 0;
+ return GL_TRUE;
+}
+
+GLvoid
+slang_storage_aggregate_destruct(slang_storage_aggregate * agg)
+{
+ GLuint i;
+
+ for (i = 0; i < agg->count; i++)
+ slang_storage_array_destruct(agg->arrays + i);
+ _slang_free(agg->arrays);
+}
+
+static slang_storage_array *
+slang_storage_aggregate_push_new(slang_storage_aggregate * agg)
+{
+ slang_storage_array *arr = NULL;
+
+ agg->arrays = (slang_storage_array *)
+ _slang_realloc(agg->arrays,
+ agg->count * sizeof(slang_storage_array),
+ (agg->count + 1) * sizeof(slang_storage_array));
+ if (agg->arrays != NULL) {
+ arr = agg->arrays + agg->count;
+ if (!slang_storage_array_construct(arr))
+ return NULL;
+ agg->count++;
+ }
+ return arr;
+}
+
+/* _slang_aggregate_variable() */
+
+static GLboolean
+aggregate_vector(slang_storage_aggregate * agg, slang_storage_type basic_type,
+ GLuint row_count)
+{
+ slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
+ if (arr == NULL)
+ return GL_FALSE;
+ arr->type = basic_type;
+ arr->length = row_count;
+ return GL_TRUE;
+}
+
+static GLboolean
+aggregate_matrix(slang_storage_aggregate * agg, slang_storage_type basic_type,
+ GLuint columns, GLuint rows)
+{
+ slang_storage_array *arr = slang_storage_aggregate_push_new(agg);
+ if (arr == NULL)
+ return GL_FALSE;
+ arr->type = SLANG_STORE_AGGREGATE;
+ arr->length = columns;
+ arr->aggregate = (slang_storage_aggregate *)
+ _slang_alloc(sizeof(slang_storage_aggregate));
+ if (arr->aggregate == NULL)
+ return GL_FALSE;
+ if (!slang_storage_aggregate_construct(arr->aggregate)) {
+ _slang_free(arr->aggregate);
+ arr->aggregate = NULL;
+ return GL_FALSE;
+ }
+ if (!aggregate_vector(arr->aggregate, basic_type, rows))
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+
+static GLboolean
+aggregate_variables(slang_storage_aggregate * agg,
+ slang_variable_scope * vars, slang_function_scope * funcs,
+ slang_struct_scope * structs,
+ slang_variable_scope * globals,
+ slang_atom_pool * atoms)
+{
+ GLuint i;
+
+ for (i = 0; i < vars->num_variables; i++)
+ if (!_slang_aggregate_variable(agg, &vars->variables[i]->type.specifier,
+ vars->variables[i]->array_len, funcs,
+ structs, globals, atoms))
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+
+GLboolean
+_slang_aggregate_variable(slang_storage_aggregate * agg,
+ slang_type_specifier * spec, GLuint array_len,
+ slang_function_scope * funcs,
+ slang_struct_scope * structs,
+ slang_variable_scope * vars,
+ slang_atom_pool * atoms)
+{
+ switch (spec->type) {
+ case SLANG_SPEC_BOOL:
+ return aggregate_vector(agg, SLANG_STORE_BOOL, 1);
+ case SLANG_SPEC_BVEC2:
+ return aggregate_vector(agg, SLANG_STORE_BOOL, 2);
+ case SLANG_SPEC_BVEC3:
+ return aggregate_vector(agg, SLANG_STORE_BOOL, 3);
+ case SLANG_SPEC_BVEC4:
+ return aggregate_vector(agg, SLANG_STORE_BOOL, 4);
+ case SLANG_SPEC_INT:
+ return aggregate_vector(agg, SLANG_STORE_INT, 1);
+ case SLANG_SPEC_IVEC2:
+ return aggregate_vector(agg, SLANG_STORE_INT, 2);
+ case SLANG_SPEC_IVEC3:
+ return aggregate_vector(agg, SLANG_STORE_INT, 3);
+ case SLANG_SPEC_IVEC4:
+ return aggregate_vector(agg, SLANG_STORE_INT, 4);
+ case SLANG_SPEC_FLOAT:
+ return aggregate_vector(agg, SLANG_STORE_FLOAT, 1);
+ case SLANG_SPEC_VEC2:
+ return aggregate_vector(agg, SLANG_STORE_FLOAT, 2);
+ case SLANG_SPEC_VEC3:
+ return aggregate_vector(agg, SLANG_STORE_FLOAT, 3);
+ case SLANG_SPEC_VEC4:
+ return aggregate_vector(agg, SLANG_STORE_FLOAT, 4);
+ case SLANG_SPEC_MAT2:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 2);
+ case SLANG_SPEC_MAT3:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 3);
+ case SLANG_SPEC_MAT4:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 4);
+
+ case SLANG_SPEC_MAT23:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 3);
+ case SLANG_SPEC_MAT32:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 2);
+ case SLANG_SPEC_MAT24:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 2, 4);
+ case SLANG_SPEC_MAT42:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 2);
+ case SLANG_SPEC_MAT34:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 3, 4);
+ case SLANG_SPEC_MAT43:
+ return aggregate_matrix(agg, SLANG_STORE_FLOAT, 4, 3);
+
+ case SLANG_SPEC_SAMPLER1D:
+ case SLANG_SPEC_SAMPLER2D:
+ case SLANG_SPEC_SAMPLER3D:
+ case SLANG_SPEC_SAMPLERCUBE:
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ case SLANG_SPEC_SAMPLER2DRECT:
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return aggregate_vector(agg, SLANG_STORE_INT, 1);
+ case SLANG_SPEC_STRUCT:
+ return aggregate_variables(agg, spec->_struct->fields, funcs, structs,
+ vars, atoms);
+ case SLANG_SPEC_ARRAY:
+ {
+ slang_storage_array *arr;
+
+ arr = slang_storage_aggregate_push_new(agg);
+ if (arr == NULL)
+ return GL_FALSE;
+ arr->type = SLANG_STORE_AGGREGATE;
+ arr->aggregate = (slang_storage_aggregate *)
+ _slang_alloc(sizeof(slang_storage_aggregate));
+ if (arr->aggregate == NULL)
+ return GL_FALSE;
+ if (!slang_storage_aggregate_construct(arr->aggregate)) {
+ _slang_free(arr->aggregate);
+ arr->aggregate = NULL;
+ return GL_FALSE;
+ }
+ if (!_slang_aggregate_variable(arr->aggregate, spec->_array, 0,
+ funcs, structs, vars, atoms))
+ return GL_FALSE;
+ arr->length = array_len;
+ /* TODO: check if 0 < arr->length <= 65535 */
+ }
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+GLuint
+_slang_sizeof_type(slang_storage_type type)
+{
+ if (type == SLANG_STORE_AGGREGATE)
+ return 0;
+ if (type == SLANG_STORE_VEC4)
+ return 4 * sizeof(GLfloat);
+ return sizeof(GLfloat);
+}
+
+
+GLuint
+_slang_sizeof_aggregate(const slang_storage_aggregate * agg)
+{
+ GLuint i, size = 0;
+
+ for (i = 0; i < agg->count; i++) {
+ slang_storage_array *arr = &agg->arrays[i];
+ GLuint element_size;
+
+ if (arr->type == SLANG_STORE_AGGREGATE)
+ element_size = _slang_sizeof_aggregate(arr->aggregate);
+ else
+ element_size = _slang_sizeof_type(arr->type);
+ size += element_size * arr->length;
+ }
+ return size;
+}
+
+
+#if 0
+GLboolean
+_slang_flatten_aggregate(slang_storage_aggregate * flat,
+ const slang_storage_aggregate * agg)
+{
+ GLuint i;
+
+ for (i = 0; i < agg->count; i++) {
+ GLuint j;
+
+ for (j = 0; j < agg->arrays[i].length; j++) {
+ if (agg->arrays[i].type == SLANG_STORE_AGGREGATE) {
+ if (!_slang_flatten_aggregate(flat, agg->arrays[i].aggregate))
+ return GL_FALSE;
+ }
+ else {
+ GLuint k, count;
+ slang_storage_type type;
+
+ if (agg->arrays[i].type == SLANG_STORE_VEC4) {
+ count = 4;
+ type = SLANG_STORE_FLOAT;
+ }
+ else {
+ count = 1;
+ type = agg->arrays[i].type;
+ }
+
+ for (k = 0; k < count; k++) {
+ slang_storage_array *arr;
+
+ arr = slang_storage_aggregate_push_new(flat);
+ if (arr == NULL)
+ return GL_FALSE;
+ arr->type = type;
+ arr->length = 1;
+ }
+ }
+ }
+ }
+ return GL_TRUE;
+}
+#endif
diff --git a/mesalib/src/mesa/shader/slang/slang_storage.h b/mesalib/src/mesa/shader/slang/slang_storage.h
new file mode 100644
index 000000000..1876a36dd
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_storage.h
@@ -0,0 +1,139 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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 SLANG_STORAGE_H
+#define SLANG_STORAGE_H
+
+#include "slang_compile.h"
+
+
+/*
+ * Program variable data storage is kept completely transparent to the
+ * front-end compiler. It is up to the back-end how the data is
+ * actually allocated. The slang_storage_type enum provides the basic
+ * information about how the memory is interpreted. This abstract
+ * piece of memory is called a data slot. A data slot of a particular
+ * type has a fixed size.
+ *
+ * For now, only the three basic types are supported, that is bool,
+ * int and float. Other built-in types like vector or matrix can
+ * easily be decomposed into a series of basic types.
+ *
+ * If the vec4 module is enabled, 4-component vectors of floats are
+ * used when possible. 4x4 matrices are constructed of 4 vec4 slots.
+ */
+typedef enum slang_storage_type_
+{
+ /* core */
+ SLANG_STORE_AGGREGATE,
+ SLANG_STORE_BOOL,
+ SLANG_STORE_INT,
+ SLANG_STORE_FLOAT,
+ /* vec4 */
+ SLANG_STORE_VEC4
+} slang_storage_type;
+
+
+/**
+ * The slang_storage_array structure groups data slots of the same
+ * type into an array. This array has a fixed length. Arrays are
+ * required to have a size equal to the sum of sizes of its
+ * elements. They are also required to support indirect
+ * addressing. That is, if B references first data slot in the array,
+ * S is the size of the data slot and I is the integral index that is
+ * not known at compile time, B+I*S references I-th data slot.
+ *
+ * This structure is also used to break down built-in data types that
+ * are not supported directly. Vectors, like vec3, are constructed
+ * from arrays of their basic types. Matrices are formed of an array
+ * of column vectors, which are in turn processed as other vectors.
+ */
+typedef struct slang_storage_array_
+{
+ slang_storage_type type;
+ struct slang_storage_aggregate_ *aggregate;
+ GLuint length;
+} slang_storage_array;
+
+GLboolean slang_storage_array_construct (slang_storage_array *);
+GLvoid slang_storage_array_destruct (slang_storage_array *);
+
+
+/**
+ * The slang_storage_aggregate structure relaxes the indirect
+ * addressing requirement for slang_storage_array
+ * structure. Aggregates are always accessed statically - its member
+ * addresses are well-known at compile time. For example, user-defined
+ * types are implemented as aggregates. Aggregates can collect data of
+ * a different type.
+ */
+typedef struct slang_storage_aggregate_
+{
+ slang_storage_array *arrays;
+ GLuint count;
+} slang_storage_aggregate;
+
+GLboolean slang_storage_aggregate_construct (slang_storage_aggregate *);
+GLvoid slang_storage_aggregate_destruct (slang_storage_aggregate *);
+
+
+extern GLboolean
+_slang_aggregate_variable(slang_storage_aggregate *agg,
+ slang_type_specifier *spec,
+ GLuint array_len,
+ slang_function_scope *funcs,
+ slang_struct_scope *structs,
+ slang_variable_scope *vars,
+ slang_atom_pool *atoms);
+
+/*
+ * Returns the size (in machine units) of the given storage type.
+ * It is an error to pass-in SLANG_STORE_AGGREGATE.
+ * Returns 0 on error.
+ */
+extern GLuint
+_slang_sizeof_type (slang_storage_type);
+
+
+/**
+ * Returns total size (in machine units) of the given aggregate.
+ * Returns 0 on error.
+ */
+extern GLuint
+_slang_sizeof_aggregate (const slang_storage_aggregate *);
+
+
+#if 0
+/**
+ * Converts structured aggregate to a flat one, with arrays of generic
+ * type being one-element long. Returns GL_TRUE on success. Returns
+ * GL_FALSE otherwise.
+ */
+extern GLboolean
+_slang_flatten_aggregate (slang_storage_aggregate *,
+ const slang_storage_aggregate *);
+
+#endif
+
+#endif /* SLANG_STORAGE_H */
diff --git a/mesalib/src/mesa/shader/slang/slang_typeinfo.c b/mesalib/src/mesa/shader/slang/slang_typeinfo.c
new file mode 100644
index 000000000..4a48bc8b8
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_typeinfo.c
@@ -0,0 +1,1138 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_typeinfo.c
+ * slang type info
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "shader/prog_instruction.h"
+#include "slang_typeinfo.h"
+#include "slang_compile.h"
+#include "slang_log.h"
+#include "slang_mem.h"
+
+
+/**
+ * Checks if a field selector is a general swizzle (an r-value swizzle
+ * with replicated components or an l-value swizzle mask) for a
+ * vector. Returns GL_TRUE if this is the case, <swz> is filled with
+ * swizzle information. Returns GL_FALSE otherwise.
+ */
+GLboolean
+_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
+{
+ GLuint i;
+ GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
+
+ /* init to undefined.
+ * We rely on undefined/nil values to distinguish between
+ * regular swizzles and writemasks.
+ * For example, the swizzle ".xNNN" is the writemask ".x".
+ * That's different than the swizzle ".xxxx".
+ */
+ for (i = 0; i < 4; i++)
+ swz->swizzle[i] = SWIZZLE_NIL;
+
+ /* the swizzle can be at most 4-component long */
+ swz->num_components = slang_string_length(field);
+ if (swz->num_components > 4)
+ return GL_FALSE;
+
+ for (i = 0; i < swz->num_components; i++) {
+ /* mark which swizzle group is used */
+ switch (field[i]) {
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'w':
+ xyzw = GL_TRUE;
+ break;
+ case 'r':
+ case 'g':
+ case 'b':
+ case 'a':
+ rgba = GL_TRUE;
+ break;
+ case 's':
+ case 't':
+ case 'p':
+ case 'q':
+ stpq = GL_TRUE;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ /* collect swizzle component */
+ switch (field[i]) {
+ case 'x':
+ case 'r':
+ case 's':
+ swz->swizzle[i] = 0;
+ break;
+ case 'y':
+ case 'g':
+ case 't':
+ swz->swizzle[i] = 1;
+ break;
+ case 'z':
+ case 'b':
+ case 'p':
+ swz->swizzle[i] = 2;
+ break;
+ case 'w':
+ case 'a':
+ case 'q':
+ swz->swizzle[i] = 3;
+ break;
+ }
+
+ /* check if the component is valid for given vector's row count */
+ if (rows <= swz->swizzle[i])
+ return GL_FALSE;
+ }
+
+ /* only one swizzle group can be used */
+ if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Checks if a general swizzle is an l-value swizzle - these swizzles
+ * do not have duplicated fields. Returns GL_TRUE if this is a
+ * swizzle mask. Returns GL_FALSE otherwise
+ */
+static GLboolean
+_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
+{
+ GLuint i, c = 0;
+
+ /* the swizzle may not be longer than the vector dim */
+ if (swz->num_components > rows)
+ return GL_FALSE;
+
+ /* the swizzle components cannot be duplicated */
+ for (i = 0; i < swz->num_components; i++) {
+ if ((c & (1 << swz->swizzle[i])) != 0)
+ return GL_FALSE;
+ c |= 1 << swz->swizzle[i];
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Combines (multiplies) two swizzles to form single swizzle.
+ * Example: "vec.wzyx.yx" --> "vec.zw".
+ */
+static void
+_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
+ const slang_swizzle * right)
+{
+ GLuint i;
+
+ dst->num_components = right->num_components;
+ for (i = 0; i < right->num_components; i++)
+ dst->swizzle[i] = left->swizzle[right->swizzle[i]];
+}
+
+
+typedef struct
+{
+ const char *name;
+ slang_type_specifier_type type;
+} type_specifier_type_name;
+
+static const type_specifier_type_name type_specifier_type_names[] = {
+ {"void", SLANG_SPEC_VOID},
+ {"bool", SLANG_SPEC_BOOL},
+ {"bvec2", SLANG_SPEC_BVEC2},
+ {"bvec3", SLANG_SPEC_BVEC3},
+ {"bvec4", SLANG_SPEC_BVEC4},
+ {"int", SLANG_SPEC_INT},
+ {"ivec2", SLANG_SPEC_IVEC2},
+ {"ivec3", SLANG_SPEC_IVEC3},
+ {"ivec4", SLANG_SPEC_IVEC4},
+ {"float", SLANG_SPEC_FLOAT},
+ {"vec2", SLANG_SPEC_VEC2},
+ {"vec3", SLANG_SPEC_VEC3},
+ {"vec4", SLANG_SPEC_VEC4},
+ {"mat2", SLANG_SPEC_MAT2},
+ {"mat3", SLANG_SPEC_MAT3},
+ {"mat4", SLANG_SPEC_MAT4},
+ {"mat2x3", SLANG_SPEC_MAT23},
+ {"mat3x2", SLANG_SPEC_MAT32},
+ {"mat2x4", SLANG_SPEC_MAT24},
+ {"mat4x2", SLANG_SPEC_MAT42},
+ {"mat3x4", SLANG_SPEC_MAT34},
+ {"mat4x3", SLANG_SPEC_MAT43},
+ {"sampler1D", SLANG_SPEC_SAMPLER1D},
+ {"sampler2D", SLANG_SPEC_SAMPLER2D},
+ {"sampler3D", SLANG_SPEC_SAMPLER3D},
+ {"samplerCube", SLANG_SPEC_SAMPLERCUBE},
+ {"sampler1DShadow", SLANG_SPEC_SAMPLER1DSHADOW},
+ {"sampler2DShadow", SLANG_SPEC_SAMPLER2DSHADOW},
+ {"sampler2DRect", SLANG_SPEC_SAMPLER2DRECT},
+ {"sampler2DRectShadow", SLANG_SPEC_SAMPLER2DRECTSHADOW},
+ {NULL, SLANG_SPEC_VOID}
+};
+
+slang_type_specifier_type
+slang_type_specifier_type_from_string(const char *name)
+{
+ const type_specifier_type_name *p = type_specifier_type_names;
+ while (p->name != NULL) {
+ if (slang_string_compare(p->name, name) == 0)
+ break;
+ p++;
+ }
+ return p->type;
+}
+
+const char *
+slang_type_specifier_type_to_string(slang_type_specifier_type type)
+{
+ const type_specifier_type_name *p = type_specifier_type_names;
+ while (p->name != NULL) {
+ if (p->type == type)
+ break;
+ p++;
+ }
+ return p->name;
+}
+
+/* slang_fully_specified_type */
+
+int
+slang_fully_specified_type_construct(slang_fully_specified_type * type)
+{
+ type->qualifier = SLANG_QUAL_NONE;
+ slang_type_specifier_ctr(&type->specifier);
+ return 1;
+}
+
+void
+slang_fully_specified_type_destruct(slang_fully_specified_type * type)
+{
+ slang_type_specifier_dtr(&type->specifier);
+}
+
+int
+slang_fully_specified_type_copy(slang_fully_specified_type * x,
+ const slang_fully_specified_type * y)
+{
+ slang_fully_specified_type z;
+
+ if (!slang_fully_specified_type_construct(&z))
+ return 0;
+ z.qualifier = y->qualifier;
+ z.precision = y->precision;
+ z.variant = y->variant;
+ z.centroid = y->centroid;
+ z.array_len = y->array_len;
+ if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
+ slang_fully_specified_type_destruct(&z);
+ return 0;
+ }
+ slang_fully_specified_type_destruct(x);
+ *x = z;
+ return 1;
+}
+
+
+
+GLvoid
+slang_type_specifier_ctr(slang_type_specifier * self)
+{
+ self->type = SLANG_SPEC_VOID;
+ self->_struct = NULL;
+ self->_array = NULL;
+}
+
+GLvoid
+slang_type_specifier_dtr(slang_type_specifier * self)
+{
+ if (self->_struct != NULL) {
+ slang_struct_destruct(self->_struct);
+ _slang_free(self->_struct);
+ }
+ if (self->_array != NULL) {
+ slang_type_specifier_dtr(self->_array);
+ _slang_free(self->_array);
+ }
+}
+
+slang_type_specifier *
+slang_type_specifier_new(slang_type_specifier_type type,
+ struct slang_struct_ *_struct,
+ struct slang_type_specifier_ *_array)
+{
+ slang_type_specifier *spec =
+ (slang_type_specifier *) _slang_alloc(sizeof(slang_type_specifier));
+ if (spec) {
+ spec->type = type;
+ spec->_struct = _struct;
+ spec->_array = _array;
+ }
+ return spec;
+}
+
+GLboolean
+slang_type_specifier_copy(slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ slang_type_specifier z;
+
+ slang_type_specifier_ctr(&z);
+ z.type = y->type;
+ if (z.type == SLANG_SPEC_STRUCT) {
+ z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
+ if (z._struct == NULL) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ if (!slang_struct_construct(z._struct)) {
+ _slang_free(z._struct);
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ if (!slang_struct_copy(z._struct, y->_struct)) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ }
+ else if (z.type == SLANG_SPEC_ARRAY) {
+ z._array = (slang_type_specifier *)
+ _slang_alloc(sizeof(slang_type_specifier));
+ if (z._array == NULL) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ slang_type_specifier_ctr(z._array);
+ if (!slang_type_specifier_copy(z._array, y->_array)) {
+ slang_type_specifier_dtr(&z);
+ return GL_FALSE;
+ }
+ }
+ slang_type_specifier_dtr(x);
+ *x = z;
+ return GL_TRUE;
+}
+
+
+/**
+ * Test if two types are equal.
+ */
+GLboolean
+slang_type_specifier_equal(const slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ if (x->type != y->type)
+ return GL_FALSE;
+ if (x->type == SLANG_SPEC_STRUCT)
+ return slang_struct_equal(x->_struct, y->_struct);
+ if (x->type == SLANG_SPEC_ARRAY)
+ return slang_type_specifier_equal(x->_array, y->_array);
+ return GL_TRUE;
+}
+
+
+/**
+ * As above, but allow float/int casting.
+ */
+GLboolean
+slang_type_specifier_compatible(const slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ /* special case: float == int */
+ if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
+ return GL_TRUE;
+ }
+ /* XXX may need to add bool/int compatibility, etc */
+
+ if (x->type != y->type)
+ return GL_FALSE;
+ if (x->type == SLANG_SPEC_STRUCT)
+ return slang_struct_equal(x->_struct, y->_struct);
+ if (x->type == SLANG_SPEC_ARRAY)
+ return slang_type_specifier_compatible(x->_array, y->_array);
+ return GL_TRUE;
+}
+
+
+GLboolean
+slang_typeinfo_construct(slang_typeinfo * ti)
+{
+ _mesa_bzero(ti, sizeof(*ti));
+ slang_type_specifier_ctr(&ti->spec);
+ ti->array_len = 0;
+ return GL_TRUE;
+}
+
+GLvoid
+slang_typeinfo_destruct(slang_typeinfo * ti)
+{
+ slang_type_specifier_dtr(&ti->spec);
+}
+
+
+
+/**
+ * Determine the return type of a function.
+ * \param a_name the function name
+ * \param param function parameters (overloading)
+ * \param num_params number of parameters to function
+ * \param space namespace to search
+ * \param spec returns the type
+ * \param funFound returns pointer to the function, or NULL if not found.
+ * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
+ */
+static GLboolean
+_slang_typeof_function(slang_atom a_name,
+ slang_operation * params, GLuint num_params,
+ const slang_name_space * space,
+ slang_type_specifier * spec,
+ slang_function **funFound,
+ slang_atom_pool *atoms, slang_info_log *log)
+{
+ GLboolean error;
+
+ *funFound = _slang_function_locate(space->funcs, a_name, params,
+ num_params, space, atoms, log, &error);
+ if (error)
+ return GL_FALSE;
+
+ if (!*funFound)
+ return GL_TRUE; /* yes, not false */
+
+ return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
+}
+
+
+/**
+ * Determine the type of a math function.
+ * \param name name of the operator, one of +,-,*,/ or unary -
+ * \param params array of function parameters
+ * \param num_params number of parameters
+ * \param space namespace to use
+ * \param spec returns the function's type
+ * \param atoms atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+static GLboolean
+typeof_math_call(const char *name, slang_operation *call,
+ const slang_name_space * space,
+ slang_type_specifier * spec,
+ slang_atom_pool * atoms,
+ slang_info_log *log)
+{
+ if (call->fun) {
+ /* we've previously resolved this function call */
+ slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
+ return GL_TRUE;
+ }
+ else {
+ slang_atom atom;
+ slang_function *fun;
+
+ /* number of params: */
+ assert(call->num_children == 1 || call->num_children == 2);
+
+ atom = slang_atom_pool_atom(atoms, name);
+ if (!_slang_typeof_function(atom, call->children, call->num_children,
+ space, spec, &fun, atoms, log))
+ return GL_FALSE;
+
+ if (fun) {
+ /* Save pointer to save time in future */
+ call->fun = fun;
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Determine the return type of an operation.
+ * \param op the operation node
+ * \param space the namespace to use
+ * \param ti the returned type
+ * \param atoms atom pool
+ * \return GL_TRUE for success, GL_FALSE if failure
+ */
+GLboolean
+_slang_typeof_operation(slang_operation * op,
+ const slang_name_space * space,
+ slang_typeinfo * ti,
+ slang_atom_pool * atoms,
+ slang_info_log *log)
+{
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+
+ switch (op->type) {
+ case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+ case SLANG_OPER_BLOCK_NEW_SCOPE:
+ case SLANG_OPER_ASM:
+ case SLANG_OPER_BREAK:
+ case SLANG_OPER_CONTINUE:
+ case SLANG_OPER_DISCARD:
+ case SLANG_OPER_RETURN:
+ case SLANG_OPER_IF:
+ case SLANG_OPER_WHILE:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_VOID:
+ ti->spec.type = SLANG_SPEC_VOID;
+ break;
+ case SLANG_OPER_EXPRESSION:
+ case SLANG_OPER_ASSIGN:
+ case SLANG_OPER_ADDASSIGN:
+ case SLANG_OPER_SUBASSIGN:
+ case SLANG_OPER_MULASSIGN:
+ case SLANG_OPER_DIVASSIGN:
+ case SLANG_OPER_PREINCREMENT:
+ case SLANG_OPER_PREDECREMENT:
+ if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+ return GL_FALSE;
+ break;
+ case SLANG_OPER_LITERAL_BOOL:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_BOOL;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_BVEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_BVEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_BVEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected bool literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_BOOL;
+ }
+ break;
+ case SLANG_OPER_LOGICALOR:
+ case SLANG_OPER_LOGICALXOR:
+ case SLANG_OPER_LOGICALAND:
+ case SLANG_OPER_EQUAL:
+ case SLANG_OPER_NOTEQUAL:
+ case SLANG_OPER_LESS:
+ case SLANG_OPER_GREATER:
+ case SLANG_OPER_LESSEQUAL:
+ case SLANG_OPER_GREATEREQUAL:
+ case SLANG_OPER_NOT:
+ ti->spec.type = SLANG_SPEC_BOOL;
+ break;
+ case SLANG_OPER_LITERAL_INT:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_INT;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_IVEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_IVEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_IVEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected int literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_INT;
+ }
+ break;
+ case SLANG_OPER_LITERAL_FLOAT:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_FLOAT;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_VEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_VEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_VEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected float literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_FLOAT;
+ }
+ break;
+ case SLANG_OPER_IDENTIFIER:
+ case SLANG_OPER_VARIABLE_DECL:
+ {
+ slang_variable *var;
+ var = _slang_variable_locate(op->locals, op->a_id, GL_TRUE);
+ if (!var) {
+ slang_info_log_error(log, "undefined variable '%s'",
+ (char *) op->a_id);
+ return GL_FALSE;
+ }
+ if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
+ slang_info_log_memory(log);
+ return GL_FALSE;
+ }
+ ti->can_be_referenced = GL_TRUE;
+ if (var->type.specifier.type == SLANG_SPEC_ARRAY &&
+ var->type.array_len >= 1) {
+ /* the datatype is an array, ex: float[3] x; */
+ ti->array_len = var->type.array_len;
+ }
+ else {
+ /* the variable is an array, ex: float x[3]; */
+ ti->array_len = var->array_len;
+ }
+ }
+ break;
+ case SLANG_OPER_SEQUENCE:
+ /* TODO: check [0] and [1] if they match */
+ if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
+ return GL_FALSE;
+ }
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ /*case SLANG_OPER_MODASSIGN: */
+ /*case SLANG_OPER_LSHASSIGN: */
+ /*case SLANG_OPER_RSHASSIGN: */
+ /*case SLANG_OPER_ORASSIGN: */
+ /*case SLANG_OPER_XORASSIGN: */
+ /*case SLANG_OPER_ANDASSIGN: */
+ case SLANG_OPER_SELECT:
+ /* TODO: check [1] and [2] if they match */
+ if (!_slang_typeof_operation(&op->children[1], space, ti, atoms, log)) {
+ return GL_FALSE;
+ }
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ /*case SLANG_OPER_BITOR: */
+ /*case SLANG_OPER_BITXOR: */
+ /*case SLANG_OPER_BITAND: */
+ /*case SLANG_OPER_LSHIFT: */
+ /*case SLANG_OPER_RSHIFT: */
+ case SLANG_OPER_ADD:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
+ break;
+ case SLANG_OPER_SUBTRACT:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
+ break;
+ case SLANG_OPER_MULTIPLY:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
+ break;
+ case SLANG_OPER_DIVIDE:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
+ break;
+ /*case SLANG_OPER_MODULUS: */
+ case SLANG_OPER_PLUS:
+ if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+ return GL_FALSE;
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ case SLANG_OPER_MINUS:
+ assert(op->num_children == 1);
+ if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
+ break;
+ /*case SLANG_OPER_COMPLEMENT: */
+ case SLANG_OPER_SUBSCRIPT:
+ {
+ slang_typeinfo _ti;
+
+ if (!slang_typeinfo_construct(&_ti))
+ return GL_FALSE;
+ if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
+ }
+ ti->can_be_referenced = _ti.can_be_referenced;
+ if (_ti.spec.type == SLANG_SPEC_ARRAY) {
+ if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
+ }
+ }
+ else {
+ if (!_slang_type_is_vector(_ti.spec.type)
+ && !_slang_type_is_matrix(_ti.spec.type)) {
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "cannot index a non-array type");
+ return GL_FALSE;
+ }
+ ti->spec.type = _slang_type_base(_ti.spec.type);
+ }
+ slang_typeinfo_destruct(&_ti);
+ }
+ break;
+ case SLANG_OPER_CALL:
+ if (op->array_constructor) {
+ /* build array typeinfo */
+ ti->spec.type = SLANG_SPEC_ARRAY;
+ ti->spec._array = (slang_type_specifier *)
+ _slang_alloc(sizeof(slang_type_specifier));
+ slang_type_specifier_ctr(ti->spec._array);
+
+ ti->spec._array->type =
+ slang_type_specifier_type_from_string((char *) op->a_id);
+ ti->array_len = op->num_children;
+ }
+ else if (op->fun) {
+ /* we've resolved this call before */
+ slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
+ }
+ else {
+ slang_function *fun;
+ if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
+ space, &ti->spec, &fun, atoms, log))
+ return GL_FALSE;
+ if (fun) {
+ /* save result for future use */
+ op->fun = fun;
+ }
+ else {
+ slang_struct *s =
+ slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
+ if (s) {
+ /* struct initializer */
+ ti->spec.type = SLANG_SPEC_STRUCT;
+ ti->spec._struct =
+ (slang_struct *) _slang_alloc(sizeof(slang_struct));
+ if (ti->spec._struct == NULL)
+ return GL_FALSE;
+ if (!slang_struct_construct(ti->spec._struct)) {
+ _slang_free(ti->spec._struct);
+ ti->spec._struct = NULL;
+ return GL_FALSE;
+ }
+ if (!slang_struct_copy(ti->spec._struct, s))
+ return GL_FALSE;
+ }
+ else {
+ /* float, int, vec4, mat3, etc. constructor? */
+ const char *name;
+ slang_type_specifier_type type;
+
+ name = slang_atom_pool_id(atoms, op->a_id);
+ type = slang_type_specifier_type_from_string(name);
+ if (type == SLANG_SPEC_VOID) {
+ slang_info_log_error(log, "undefined function '%s'", name);
+ return GL_FALSE;
+ }
+ ti->spec.type = type;
+ }
+ }
+ }
+ break;
+ case SLANG_OPER_METHOD:
+ /* at this time, GLSL 1.20 only has one method: array.length()
+ * which returns an integer.
+ */
+ ti->spec.type = SLANG_SPEC_INT;
+ break;
+ case SLANG_OPER_FIELD:
+ {
+ slang_typeinfo _ti;
+
+ if (!slang_typeinfo_construct(&_ti))
+ return GL_FALSE;
+ if (!_slang_typeof_operation(op->children, space, &_ti, atoms, log)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
+ }
+ if (_ti.spec.type == SLANG_SPEC_STRUCT) {
+ slang_variable *field;
+
+ field = _slang_variable_locate(_ti.spec._struct->fields, op->a_id,
+ GL_FALSE);
+ if (field == NULL) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
+ }
+ if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
+ }
+ ti->can_be_referenced = _ti.can_be_referenced;
+ ti->array_len = field->array_len;
+ }
+ else {
+ GLuint rows;
+ const char *swizzle;
+ slang_type_specifier_type base;
+
+ /* determine the swizzle of the field expression */
+ if (!_slang_type_is_vector(_ti.spec.type)) {
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "Can't swizzle scalar expression");
+ return GL_FALSE;
+ }
+ rows = _slang_type_dim(_ti.spec.type);
+ swizzle = slang_atom_pool_id(atoms, op->a_id);
+ if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "bad swizzle '%s'", swizzle);
+ return GL_FALSE;
+ }
+ ti->is_swizzled = GL_TRUE;
+ ti->can_be_referenced = _ti.can_be_referenced
+ && _slang_is_swizzle_mask(&ti->swz, rows);
+ if (_ti.is_swizzled) {
+ slang_swizzle swz;
+
+ /* swizzle the swizzle */
+ _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
+ ti->swz = swz;
+ }
+ base = _slang_type_base(_ti.spec.type);
+ switch (ti->swz.num_components) {
+ case 1:
+ ti->spec.type = base;
+ break;
+ case 2:
+ switch (base) {
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC2;
+ break;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC2;
+ break;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ switch (base) {
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC3;
+ break;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC3;
+ break;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC3;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ switch (base) {
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC4;
+ break;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC4;
+ break;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC4;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ slang_typeinfo_destruct(&_ti);
+ }
+ break;
+ case SLANG_OPER_POSTINCREMENT:
+ case SLANG_OPER_POSTDECREMENT:
+ if (!_slang_typeof_operation(op->children, space, ti, atoms, log))
+ return GL_FALSE;
+ ti->can_be_referenced = GL_FALSE;
+ ti->is_swizzled = GL_FALSE;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Determine if a type is a matrix.
+ * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_matrix(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_MAT2:
+ case SLANG_SPEC_MAT3:
+ case SLANG_SPEC_MAT4:
+ case SLANG_SPEC_MAT23:
+ case SLANG_SPEC_MAT32:
+ case SLANG_SPEC_MAT24:
+ case SLANG_SPEC_MAT42:
+ case SLANG_SPEC_MAT34:
+ case SLANG_SPEC_MAT43:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Determine if a type is a vector.
+ * \return GL_TRUE if is a vector, GL_FALSE otherwise.
+ */
+GLboolean
+_slang_type_is_vector(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_VEC2:
+ case SLANG_SPEC_VEC3:
+ case SLANG_SPEC_VEC4:
+ case SLANG_SPEC_IVEC2:
+ case SLANG_SPEC_IVEC3:
+ case SLANG_SPEC_IVEC4:
+ case SLANG_SPEC_BVEC2:
+ case SLANG_SPEC_BVEC3:
+ case SLANG_SPEC_BVEC4:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Determine if a type is a float, float vector or float matrix.
+ * \return GL_TRUE if so, GL_FALSE otherwise
+ */
+GLboolean
+_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_FLOAT:
+ case SLANG_SPEC_VEC2:
+ case SLANG_SPEC_VEC3:
+ case SLANG_SPEC_VEC4:
+ case SLANG_SPEC_MAT2:
+ case SLANG_SPEC_MAT3:
+ case SLANG_SPEC_MAT4:
+ case SLANG_SPEC_MAT23:
+ case SLANG_SPEC_MAT32:
+ case SLANG_SPEC_MAT24:
+ case SLANG_SPEC_MAT42:
+ case SLANG_SPEC_MAT34:
+ case SLANG_SPEC_MAT43:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Given a vector type, return the type of the vector's elements.
+ * For a matrix, return the type of the columns.
+ */
+slang_type_specifier_type
+_slang_type_base(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_FLOAT:
+ case SLANG_SPEC_VEC2:
+ case SLANG_SPEC_VEC3:
+ case SLANG_SPEC_VEC4:
+ return SLANG_SPEC_FLOAT;
+ case SLANG_SPEC_INT:
+ case SLANG_SPEC_IVEC2:
+ case SLANG_SPEC_IVEC3:
+ case SLANG_SPEC_IVEC4:
+ return SLANG_SPEC_INT;
+ case SLANG_SPEC_BOOL:
+ case SLANG_SPEC_BVEC2:
+ case SLANG_SPEC_BVEC3:
+ case SLANG_SPEC_BVEC4:
+ return SLANG_SPEC_BOOL;
+ case SLANG_SPEC_MAT2:
+ return SLANG_SPEC_VEC2;
+ case SLANG_SPEC_MAT3:
+ return SLANG_SPEC_VEC3;
+ case SLANG_SPEC_MAT4:
+ return SLANG_SPEC_VEC4;
+ case SLANG_SPEC_MAT23:
+ return SLANG_SPEC_VEC3;
+ case SLANG_SPEC_MAT32:
+ return SLANG_SPEC_VEC2;
+ case SLANG_SPEC_MAT24:
+ return SLANG_SPEC_VEC4;
+ case SLANG_SPEC_MAT42:
+ return SLANG_SPEC_VEC2;
+ case SLANG_SPEC_MAT34:
+ return SLANG_SPEC_VEC4;
+ case SLANG_SPEC_MAT43:
+ return SLANG_SPEC_VEC3;
+ default:
+ return SLANG_SPEC_VOID;
+ }
+}
+
+
+/**
+ * Return the dimensionality of a vector, or for a matrix, return number
+ * of columns.
+ */
+GLuint
+_slang_type_dim(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_FLOAT:
+ case SLANG_SPEC_INT:
+ case SLANG_SPEC_BOOL:
+ return 1;
+ case SLANG_SPEC_VEC2:
+ case SLANG_SPEC_IVEC2:
+ case SLANG_SPEC_BVEC2:
+ case SLANG_SPEC_MAT2:
+ return 2;
+ case SLANG_SPEC_VEC3:
+ case SLANG_SPEC_IVEC3:
+ case SLANG_SPEC_BVEC3:
+ case SLANG_SPEC_MAT3:
+ return 3;
+ case SLANG_SPEC_VEC4:
+ case SLANG_SPEC_IVEC4:
+ case SLANG_SPEC_BVEC4:
+ case SLANG_SPEC_MAT4:
+ return 4;
+
+ case SLANG_SPEC_MAT23:
+ return 2;
+ case SLANG_SPEC_MAT32:
+ return 3;
+ case SLANG_SPEC_MAT24:
+ return 2;
+ case SLANG_SPEC_MAT42:
+ return 4;
+ case SLANG_SPEC_MAT34:
+ return 3;
+ case SLANG_SPEC_MAT43:
+ return 4;
+
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
+ */
+GLenum
+_slang_gltype_from_specifier(const slang_type_specifier *type)
+{
+ switch (type->type) {
+ case SLANG_SPEC_BOOL:
+ return GL_BOOL;
+ case SLANG_SPEC_BVEC2:
+ return GL_BOOL_VEC2;
+ case SLANG_SPEC_BVEC3:
+ return GL_BOOL_VEC3;
+ case SLANG_SPEC_BVEC4:
+ return GL_BOOL_VEC4;
+ case SLANG_SPEC_INT:
+ return GL_INT;
+ case SLANG_SPEC_IVEC2:
+ return GL_INT_VEC2;
+ case SLANG_SPEC_IVEC3:
+ return GL_INT_VEC3;
+ case SLANG_SPEC_IVEC4:
+ return GL_INT_VEC4;
+ case SLANG_SPEC_FLOAT:
+ return GL_FLOAT;
+ case SLANG_SPEC_VEC2:
+ return GL_FLOAT_VEC2;
+ case SLANG_SPEC_VEC3:
+ return GL_FLOAT_VEC3;
+ case SLANG_SPEC_VEC4:
+ return GL_FLOAT_VEC4;
+ case SLANG_SPEC_MAT2:
+ return GL_FLOAT_MAT2;
+ case SLANG_SPEC_MAT3:
+ return GL_FLOAT_MAT3;
+ case SLANG_SPEC_MAT4:
+ return GL_FLOAT_MAT4;
+ case SLANG_SPEC_MAT23:
+ return GL_FLOAT_MAT2x3;
+ case SLANG_SPEC_MAT32:
+ return GL_FLOAT_MAT3x2;
+ case SLANG_SPEC_MAT24:
+ return GL_FLOAT_MAT2x4;
+ case SLANG_SPEC_MAT42:
+ return GL_FLOAT_MAT4x2;
+ case SLANG_SPEC_MAT34:
+ return GL_FLOAT_MAT3x4;
+ case SLANG_SPEC_MAT43:
+ return GL_FLOAT_MAT4x3;
+ case SLANG_SPEC_SAMPLER1D:
+ return GL_SAMPLER_1D;
+ case SLANG_SPEC_SAMPLER2D:
+ return GL_SAMPLER_2D;
+ case SLANG_SPEC_SAMPLER3D:
+ return GL_SAMPLER_3D;
+ case SLANG_SPEC_SAMPLERCUBE:
+ return GL_SAMPLER_CUBE;
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ return GL_SAMPLER_1D_SHADOW;
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ return GL_SAMPLER_2D_SHADOW;
+ case SLANG_SPEC_SAMPLER2DRECT:
+ return GL_SAMPLER_2D_RECT_ARB;
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return GL_SAMPLER_2D_RECT_SHADOW_ARB;
+ case SLANG_SPEC_ARRAY:
+ return _slang_gltype_from_specifier(type->_array);
+ case SLANG_SPEC_STRUCT:
+ /* fall-through */
+ default:
+ return GL_NONE;
+ }
+}
+
diff --git a/mesalib/src/mesa/shader/slang/slang_typeinfo.h b/mesalib/src/mesa/shader/slang/slang_typeinfo.h
new file mode 100644
index 000000000..e6fecd350
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_typeinfo.h
@@ -0,0 +1,239 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 2005-2006 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 SLANG_TYPEINFO_H
+#define SLANG_TYPEINFO_H 1
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "slang_log.h"
+#include "slang_utility.h"
+#include "slang_vartable.h"
+
+
+struct slang_operation_;
+
+struct slang_name_space_;
+
+
+
+/**
+ * Holds complete information about vector swizzle - the <swizzle>
+ * array contains vector component source indices, where 0 is "x", 1
+ * is "y", 2 is "z" and 3 is "w".
+ * Example: "xwz" --> { 3, { 0, 3, 2, not used } }.
+ */
+typedef struct slang_swizzle_
+{
+ GLuint num_components;
+ GLuint swizzle[4];
+} slang_swizzle;
+
+extern GLboolean
+_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz);
+
+
+typedef enum slang_type_variant_
+{
+ SLANG_VARIANT, /* the default */
+ SLANG_INVARIANT /* indicates the "invariant" keyword */
+} slang_type_variant;
+
+
+typedef enum slang_type_centroid_
+{
+ SLANG_CENTER, /* the default */
+ SLANG_CENTROID /* indicates the "centroid" keyword */
+} slang_type_centroid;
+
+
+typedef enum slang_type_qualifier_
+{
+ SLANG_QUAL_NONE,
+ SLANG_QUAL_CONST,
+ SLANG_QUAL_ATTRIBUTE,
+ SLANG_QUAL_VARYING,
+ SLANG_QUAL_UNIFORM,
+ SLANG_QUAL_OUT,
+ SLANG_QUAL_INOUT,
+ SLANG_QUAL_FIXEDOUTPUT, /* internal */
+ SLANG_QUAL_FIXEDINPUT /* internal */
+} slang_type_qualifier;
+
+
+typedef enum slang_type_precision_
+{
+ SLANG_PREC_DEFAULT,
+ SLANG_PREC_LOW,
+ SLANG_PREC_MEDIUM,
+ SLANG_PREC_HIGH
+} slang_type_precision;
+
+
+/**
+ * The basic shading language types (float, vec4, mat3, etc)
+ */
+typedef enum slang_type_specifier_type_
+{
+ SLANG_SPEC_VOID,
+ SLANG_SPEC_BOOL,
+ SLANG_SPEC_BVEC2,
+ SLANG_SPEC_BVEC3,
+ SLANG_SPEC_BVEC4,
+ SLANG_SPEC_INT,
+ SLANG_SPEC_IVEC2,
+ SLANG_SPEC_IVEC3,
+ SLANG_SPEC_IVEC4,
+ SLANG_SPEC_FLOAT,
+ SLANG_SPEC_VEC2,
+ SLANG_SPEC_VEC3,
+ SLANG_SPEC_VEC4,
+ SLANG_SPEC_MAT2,
+ SLANG_SPEC_MAT3,
+ SLANG_SPEC_MAT4,
+ SLANG_SPEC_MAT23,
+ SLANG_SPEC_MAT32,
+ SLANG_SPEC_MAT24,
+ SLANG_SPEC_MAT42,
+ SLANG_SPEC_MAT34,
+ SLANG_SPEC_MAT43,
+ SLANG_SPEC_SAMPLER1D,
+ SLANG_SPEC_SAMPLER2D,
+ SLANG_SPEC_SAMPLER3D,
+ SLANG_SPEC_SAMPLERCUBE,
+ SLANG_SPEC_SAMPLER2DRECT,
+ SLANG_SPEC_SAMPLER1DSHADOW,
+ SLANG_SPEC_SAMPLER2DSHADOW,
+ SLANG_SPEC_SAMPLER2DRECTSHADOW,
+ SLANG_SPEC_STRUCT,
+ SLANG_SPEC_ARRAY
+} slang_type_specifier_type;
+
+
+extern slang_type_specifier_type
+slang_type_specifier_type_from_string(const char *);
+
+extern const char *
+slang_type_specifier_type_to_string(slang_type_specifier_type);
+
+
+/**
+ * Describes more sophisticated types, like structs and arrays.
+ */
+typedef struct slang_type_specifier_
+{
+ slang_type_specifier_type type;
+ struct slang_struct_ *_struct; /**< if type == SLANG_SPEC_STRUCT */
+ struct slang_type_specifier_ *_array; /**< if type == SLANG_SPEC_ARRAY */
+} slang_type_specifier;
+
+
+extern GLvoid
+slang_type_specifier_ctr(slang_type_specifier *);
+
+extern GLvoid
+slang_type_specifier_dtr(slang_type_specifier *);
+
+extern slang_type_specifier *
+slang_type_specifier_new(slang_type_specifier_type type,
+ struct slang_struct_ *_struct,
+ struct slang_type_specifier_ *_array);
+
+
+extern GLboolean
+slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *);
+
+extern GLboolean
+slang_type_specifier_equal(const slang_type_specifier *,
+ const slang_type_specifier *);
+
+
+extern GLboolean
+slang_type_specifier_compatible(const slang_type_specifier * x,
+ const slang_type_specifier * y);
+
+
+typedef struct slang_fully_specified_type_
+{
+ slang_type_qualifier qualifier;
+ slang_type_specifier specifier;
+ slang_type_precision precision;
+ slang_type_variant variant;
+ slang_type_centroid centroid;
+ GLint array_len; /**< -1 if not an array type */
+} slang_fully_specified_type;
+
+extern int
+slang_fully_specified_type_construct(slang_fully_specified_type *);
+
+extern void
+slang_fully_specified_type_destruct(slang_fully_specified_type *);
+
+extern int
+slang_fully_specified_type_copy(slang_fully_specified_type *,
+ const slang_fully_specified_type *);
+
+
+
+typedef struct slang_typeinfo_
+{
+ GLboolean can_be_referenced;
+ GLboolean is_swizzled;
+ slang_swizzle swz;
+ slang_type_specifier spec;
+ GLuint array_len;
+} slang_typeinfo;
+
+extern GLboolean
+slang_typeinfo_construct(slang_typeinfo *);
+
+extern GLvoid
+slang_typeinfo_destruct(slang_typeinfo *);
+
+
+extern GLboolean
+_slang_typeof_operation(struct slang_operation_ *,
+ const struct slang_name_space_ *,
+ slang_typeinfo *, slang_atom_pool *,
+ slang_info_log *log);
+
+extern GLboolean
+_slang_type_is_matrix(slang_type_specifier_type);
+
+extern GLboolean
+_slang_type_is_vector(slang_type_specifier_type);
+
+extern GLboolean
+_slang_type_is_float_vec_mat(slang_type_specifier_type);
+
+extern slang_type_specifier_type
+_slang_type_base(slang_type_specifier_type);
+
+extern GLuint
+_slang_type_dim(slang_type_specifier_type);
+
+extern GLenum
+_slang_gltype_from_specifier(const slang_type_specifier *type);
+
+#endif
diff --git a/mesalib/src/mesa/shader/slang/slang_utility.c b/mesalib/src/mesa/shader/slang/slang_utility.c
new file mode 100644
index 000000000..3631e32b3
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_utility.c
@@ -0,0 +1,228 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_utility.c
+ * slang utilities
+ * \author Michal Krol
+ */
+
+#include "main/imports.h"
+#include "slang_utility.h"
+#include "slang_mem.h"
+
+char *
+slang_string_concat (char *dst, const char *src)
+{
+ return _mesa_strcpy (dst + _mesa_strlen (dst), src);
+}
+
+
+/* slang_string */
+
+GLvoid
+slang_string_init (slang_string *self)
+{
+ self->data = NULL;
+ self->capacity = 0;
+ self->length = 0;
+ self->fail = GL_FALSE;
+}
+
+GLvoid
+slang_string_free (slang_string *self)
+{
+ if (self->data != NULL)
+ _mesa_free (self->data);
+}
+
+GLvoid
+slang_string_reset (slang_string *self)
+{
+ self->length = 0;
+ self->fail = GL_FALSE;
+}
+
+static GLboolean
+grow (slang_string *self, GLuint size)
+{
+ if (self->fail)
+ return GL_FALSE;
+ if (size > self->capacity) {
+ /* do not overflow 32-bit range */
+ assert (size < 0x80000000);
+
+ self->data = (char *) (_mesa_realloc (self->data, self->capacity, size * 2));
+ self->capacity = size * 2;
+ if (self->data == NULL) {
+ self->capacity = 0;
+ self->fail = GL_TRUE;
+ return GL_FALSE;
+ }
+ }
+ return GL_TRUE;
+}
+
+GLvoid
+slang_string_push (slang_string *self, const slang_string *str)
+{
+ if (str->fail) {
+ self->fail = GL_TRUE;
+ return;
+ }
+ if (grow (self, self->length + str->length)) {
+ _mesa_memcpy (&self->data[self->length], str->data, str->length);
+ self->length += str->length;
+ }
+}
+
+GLvoid
+slang_string_pushc (slang_string *self, const char c)
+{
+ if (grow (self, self->length + 1)) {
+ self->data[self->length] = c;
+ self->length++;
+ }
+}
+
+GLvoid
+slang_string_pushs (slang_string *self, const char *cstr, GLuint len)
+{
+ if (grow (self, self->length + len)) {
+ _mesa_memcpy (&self->data[self->length], cstr, len);
+ self->length += len;
+ }
+}
+
+GLvoid
+slang_string_pushi (slang_string *self, GLint i)
+{
+ char buffer[12];
+
+ _mesa_sprintf (buffer, "%d", i);
+ slang_string_pushs (self, buffer, strlen (buffer));
+}
+
+const char *
+slang_string_cstr (slang_string *self)
+{
+ if (grow (self, self->length + 1))
+ self->data[self->length] = '\0';
+ return self->data;
+}
+
+/* slang_atom_pool */
+
+void
+slang_atom_pool_construct(slang_atom_pool * pool)
+{
+ GLuint i;
+
+ for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++)
+ pool->entries[i] = NULL;
+}
+
+void
+slang_atom_pool_destruct (slang_atom_pool * pool)
+{
+ GLuint i;
+
+ for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) {
+ slang_atom_entry * entry;
+
+ entry = pool->entries[i];
+ while (entry != NULL) {
+ slang_atom_entry *next = entry->next;
+ _slang_free(entry->id);
+ _slang_free(entry);
+ entry = next;
+ }
+ }
+}
+
+/*
+ * Search the atom pool for an atom with a given name.
+ * If atom is not found, create and add it to the pool.
+ * Returns ATOM_NULL if the atom was not found and the function failed
+ * to create a new atom.
+ */
+slang_atom
+slang_atom_pool_atom(slang_atom_pool * pool, const char * id)
+{
+ GLuint hash;
+ const char * p = id;
+ slang_atom_entry ** entry;
+
+ /* Hash a given string to a number in the range [0, ATOM_POOL_SIZE). */
+ hash = 0;
+ while (*p != '\0') {
+ GLuint g;
+
+ hash = (hash << 4) + (GLuint) (*p++);
+ g = hash & 0xf0000000;
+ if (g != 0)
+ hash ^= g >> 24;
+ hash &= ~g;
+ }
+ hash %= SLANG_ATOM_POOL_SIZE;
+
+ /* Now the hash points to a linked list of atoms with names that
+ * have the same hash value. Search the linked list for a given
+ * name.
+ */
+ entry = &pool->entries[hash];
+ while (*entry != NULL) {
+ /* If the same, return the associated atom. */
+ if (slang_string_compare((**entry).id, id) == 0)
+ return (slang_atom) (**entry).id;
+ /* Grab the next atom in the linked list. */
+ entry = &(**entry).next;
+ }
+
+ /* Okay, we have not found an atom. Create a new entry for it.
+ * Note that the <entry> points to the last entry's <next> field.
+ */
+ *entry = (slang_atom_entry *) _slang_alloc(sizeof(slang_atom_entry));
+ if (*entry == NULL)
+ return SLANG_ATOM_NULL;
+
+ /* Initialize a new entry. Because we'll need the actual name of
+ * the atom, we use the pointer to this string as an actual atom's
+ * value.
+ */
+ (**entry).next = NULL;
+ (**entry).id = _slang_strdup(id);
+ if ((**entry).id == NULL)
+ return SLANG_ATOM_NULL;
+ return (slang_atom) (**entry).id;
+}
+
+/**
+ * Return the name of a given atom.
+ */
+const char *
+slang_atom_pool_id(slang_atom_pool * pool, slang_atom atom)
+{
+ return (const char *) (atom);
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_utility.h b/mesalib/src/mesa/shader/slang/slang_utility.h
new file mode 100644
index 000000000..032c56181
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_utility.h
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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 SLANG_UTILITY_H
+#define SLANG_UTILITY_H
+
+
+/* Compile-time assertions. If the expression is zero, try to declare an
+ * array of size [-1] to cause compilation error.
+ */
+#define static_assert(expr) do { int _array[(expr) ? 1 : -1]; (void) _array[0]; } while (0)
+
+
+#define slang_string_compare(str1, str2) _mesa_strcmp (str1, str2)
+#define slang_string_copy(dst, src) _mesa_strcpy (dst, src)
+#define slang_string_length(str) _mesa_strlen (str)
+
+char *slang_string_concat (char *, const char *);
+
+/* slang_string */
+
+typedef struct
+{
+ char *data;
+ GLuint length;
+ GLuint capacity;
+ GLboolean fail;
+} slang_string;
+
+GLvoid
+slang_string_init (slang_string *);
+
+GLvoid
+slang_string_free (slang_string *);
+
+GLvoid
+slang_string_reset (slang_string *);
+
+GLvoid
+slang_string_push (slang_string *, const slang_string *);
+
+GLvoid
+slang_string_pushc (slang_string *, const char);
+
+GLvoid
+slang_string_pushs (slang_string *, const char *, GLuint);
+
+GLvoid
+slang_string_pushi (slang_string *, GLint);
+
+const char *
+slang_string_cstr (slang_string *);
+
+/* slang_atom */
+
+typedef GLvoid *slang_atom;
+
+#define SLANG_ATOM_NULL ((slang_atom) 0)
+
+typedef struct slang_atom_entry_
+{
+ char *id;
+ struct slang_atom_entry_ *next;
+} slang_atom_entry;
+
+#define SLANG_ATOM_POOL_SIZE 1023
+
+typedef struct slang_atom_pool_
+{
+ slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE];
+} slang_atom_pool;
+
+GLvoid slang_atom_pool_construct (slang_atom_pool *);
+GLvoid slang_atom_pool_destruct (slang_atom_pool *);
+slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
+const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
+
+
+#endif
diff --git a/mesalib/src/mesa/shader/slang/slang_vartable.c b/mesalib/src/mesa/shader/slang/slang_vartable.c
new file mode 100644
index 000000000..a4ebacc09
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_vartable.c
@@ -0,0 +1,362 @@
+
+#include "main/imports.h"
+#include "shader/program.h"
+#include "shader/prog_print.h"
+#include "slang_compile.h"
+#include "slang_compile_variable.h"
+#include "slang_emit.h"
+#include "slang_mem.h"
+#include "slang_vartable.h"
+#include "slang_ir.h"
+
+
+static int dbg = 0;
+
+
+typedef enum {
+ FREE,
+ VAR,
+ TEMP
+} TempState;
+
+
+/**
+ * Variable/register info for one variable scope.
+ */
+struct table
+{
+ int Level;
+ int NumVars;
+ slang_variable **Vars; /* array [NumVars] */
+
+ TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
+ int ValSize[MAX_PROGRAM_TEMPS * 4]; /**< For debug only */
+
+ struct table *Parent; /** Parent scope table */
+};
+
+
+/**
+ * A variable table is a stack of tables, one per scope.
+ */
+struct slang_var_table_
+{
+ GLint CurLevel;
+ GLuint MaxRegisters;
+ struct table *Top; /**< Table at top of stack */
+};
+
+
+
+slang_var_table *
+_slang_new_var_table(GLuint maxRegisters)
+{
+ slang_var_table *vt
+ = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
+ if (vt) {
+ vt->MaxRegisters = maxRegisters;
+ }
+ return vt;
+}
+
+
+void
+_slang_delete_var_table(slang_var_table *vt)
+{
+ if (vt->Top) {
+ _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
+ return;
+ }
+ _slang_free(vt);
+}
+
+
+
+/**
+ * Create new table on top of vartable stack.
+ * Used when we enter a {} block.
+ */
+void
+_slang_push_var_table(slang_var_table *vt)
+{
+ struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
+ if (t) {
+ t->Level = vt->CurLevel++;
+ t->Parent = vt->Top;
+ if (t->Parent) {
+ /* copy the info indicating which temp regs are in use */
+ memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
+ memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
+ }
+ vt->Top = t;
+ if (dbg) printf("Pushing level %d\n", t->Level);
+ }
+}
+
+
+/**
+ * Pop top entry from variable table.
+ * Used when we leave a {} block.
+ */
+void
+_slang_pop_var_table(slang_var_table *vt)
+{
+ struct table *t = vt->Top;
+ int i;
+
+ if (dbg) printf("Popping level %d\n", t->Level);
+
+ /* free the storage allocated for each variable */
+ for (i = 0; i < t->NumVars; i++) {
+ slang_ir_storage *store = t->Vars[i]->store;
+ GLint j;
+ GLuint comp;
+ if (dbg) printf(" Free var %s, size %d at %d.%s\n",
+ (char*) t->Vars[i]->a_name, store->Size,
+ store->Index,
+ _mesa_swizzle_string(store->Swizzle, 0, 0));
+
+ if (store->File == PROGRAM_SAMPLER) {
+ /* samplers have no storage */
+ continue;
+ }
+
+ if (store->Size == 1)
+ comp = GET_SWZ(store->Swizzle, 0);
+ else
+ comp = 0;
+
+ /* store->Index may be -1 if we run out of registers */
+ if (store->Index >= 0) {
+ for (j = 0; j < store->Size; j++) {
+ assert(t->Temps[store->Index * 4 + j + comp] == VAR);
+ t->Temps[store->Index * 4 + j + comp] = FREE;
+ }
+ }
+ store->Index = -1;
+ }
+ if (t->Parent) {
+ /* just verify that any remaining allocations in this scope
+ * were for temps
+ */
+ for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
+ if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
+ if (dbg) printf(" Free reg %d\n", i/4);
+ assert(t->Temps[i] == TEMP);
+ }
+ }
+ }
+
+ if (t->Vars) {
+ _slang_free(t->Vars);
+ t->Vars = NULL;
+ }
+
+ vt->Top = t->Parent;
+ _slang_free(t);
+ vt->CurLevel--;
+}
+
+
+/**
+ * Add a new variable to the given var/symbol table.
+ */
+void
+_slang_add_variable(slang_var_table *vt, slang_variable *v)
+{
+ struct table *t;
+ assert(vt);
+ t = vt->Top;
+ assert(t);
+ if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
+ t->Vars = (slang_variable **)
+ _slang_realloc(t->Vars,
+ t->NumVars * sizeof(slang_variable *),
+ (t->NumVars + 1) * sizeof(slang_variable *));
+ t->Vars[t->NumVars] = v;
+ t->NumVars++;
+}
+
+
+/**
+ * Look for variable by name in given table.
+ * If not found, Parent table will be searched.
+ */
+slang_variable *
+_slang_find_variable(const slang_var_table *vt, slang_atom name)
+{
+ struct table *t = vt->Top;
+ while (1) {
+ int i;
+ for (i = 0; i < t->NumVars; i++) {
+ if (t->Vars[i]->a_name == name)
+ return t->Vars[i];
+ }
+ if (t->Parent)
+ t = t->Parent;
+ else
+ return NULL;
+ }
+}
+
+
+/**
+ * Allocation helper.
+ * \param size var size in floats
+ * \return position for var, measured in floats
+ */
+static GLint
+alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
+{
+ struct table *t = vt->Top;
+ /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
+ const GLuint step = (size == 1) ? 1 : 4;
+ GLuint i, j;
+ assert(size > 0); /* number of floats */
+
+ for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
+ GLuint found = 0;
+ for (j = 0; j < (GLuint) size; j++) {
+ assert(i + j < 4 * MAX_PROGRAM_TEMPS);
+ if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
+ found++;
+ }
+ else {
+ break;
+ }
+ }
+ if (found == size) {
+ /* found block of size free regs */
+ if (size > 1)
+ assert(i % 4 == 0);
+ for (j = 0; j < (GLuint) size; j++) {
+ assert(i + j < 4 * MAX_PROGRAM_TEMPS);
+ t->Temps[i + j] = isTemp ? TEMP : VAR;
+ }
+ assert(i < MAX_PROGRAM_TEMPS * 4);
+ t->ValSize[i] = size;
+ return i;
+ }
+ }
+
+ /* if we get here, we ran out of registers */
+ return -1;
+}
+
+
+/**
+ * Allocate temp register(s) for storing a variable.
+ * \param size size needed, in floats
+ * \param swizzle returns swizzle mask for accessing var in register
+ * \return register allocated, or -1
+ */
+GLboolean
+_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
+{
+ struct table *t = vt->Top;
+ int i;
+
+ if (store->File == PROGRAM_SAMPLER) {
+ /* don't really allocate storage */
+ store->Index = 0;
+ return GL_TRUE;
+ }
+
+ i = alloc_reg(vt, store->Size, GL_FALSE);
+ if (i < 0)
+ return GL_FALSE;
+
+ store->Index = i / 4;
+ store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+ if (dbg)
+ printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
+ store->Size, store->Index,
+ _mesa_swizzle_string(store->Swizzle, 0, 0),
+ t->Level,
+ (void*) store);
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Allocate temp register(s) for storing an unnamed intermediate value.
+ */
+GLboolean
+_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
+{
+ struct table *t = vt->Top;
+ const int i = alloc_reg(vt, store->Size, GL_TRUE);
+ if (i < 0)
+ return GL_FALSE;
+
+ assert(store->Index < 0);
+
+ store->Index = i / 4;
+ store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
+
+ if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
+ store->Size, store->Index,
+ _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
+ (void *) store);
+
+ return GL_TRUE;
+}
+
+
+void
+_slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
+{
+ struct table *t = vt->Top;
+ GLuint i;
+ GLuint r = store->Index;
+ assert(store->Size > 0);
+ assert(r >= 0);
+ assert(r + store->Size <= vt->MaxRegisters * 4);
+ if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
+ store->Size, r,
+ _mesa_swizzle_string(store->Swizzle, 0, 0),
+ t->Level, (void *) store);
+ if (store->Size == 1) {
+ const GLuint comp = GET_SWZ(store->Swizzle, 0);
+ /* we can actually fail some of these assertions because of the
+ * troublesome IR_SWIZZLE handling.
+ */
+#if 0
+ assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
+ assert(comp < 4);
+ assert(t->ValSize[r * 4 + comp] == 1);
+#endif
+ assert(t->Temps[r * 4 + comp] == TEMP);
+ t->Temps[r * 4 + comp] = FREE;
+ }
+ else {
+ /*assert(store->Swizzle == SWIZZLE_NOOP);*/
+ assert(t->ValSize[r*4] == store->Size);
+ for (i = 0; i < (GLuint) store->Size; i++) {
+ assert(t->Temps[r * 4 + i] == TEMP);
+ t->Temps[r * 4 + i] = FREE;
+ }
+ }
+}
+
+
+GLboolean
+_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
+{
+ struct table *t = vt->Top;
+ GLuint comp;
+ assert(store->Index >= 0);
+ assert(store->Index < (int) vt->MaxRegisters);
+ if (store->Swizzle == SWIZZLE_NOOP)
+ comp = 0;
+ else
+ comp = GET_SWZ(store->Swizzle, 0);
+
+ if (t->Temps[store->Index * 4 + comp] == TEMP)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
diff --git a/mesalib/src/mesa/shader/slang/slang_vartable.h b/mesalib/src/mesa/shader/slang/slang_vartable.h
new file mode 100644
index 000000000..94bcd63f4
--- /dev/null
+++ b/mesalib/src/mesa/shader/slang/slang_vartable.h
@@ -0,0 +1,42 @@
+
+#ifndef SLANG_VARTABLE_H
+#define SLANG_VARTABLE_H
+
+struct slang_ir_storage_;
+
+typedef struct slang_var_table_ slang_var_table;
+
+struct slang_variable_;
+
+extern slang_var_table *
+_slang_new_var_table(GLuint maxRegisters);
+
+extern void
+_slang_delete_var_table(slang_var_table *vt);
+
+extern void
+_slang_push_var_table(slang_var_table *parent);
+
+extern void
+_slang_pop_var_table(slang_var_table *t);
+
+extern void
+_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
+
+extern struct slang_variable_ *
+_slang_find_variable(const slang_var_table *t, slang_atom name);
+
+extern GLboolean
+_slang_alloc_var(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern GLboolean
+_slang_alloc_temp(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern void
+_slang_free_temp(slang_var_table *t, struct slang_ir_storage_ *store);
+
+extern GLboolean
+_slang_is_temp(const slang_var_table *t, const struct slang_ir_storage_ *store);
+
+
+#endif /* SLANG_VARTABLE_H */
diff --git a/mesalib/src/mesa/shader/symbol_table.c b/mesalib/src/mesa/shader/symbol_table.c
new file mode 100644
index 000000000..7a9aa7b8f
--- /dev/null
+++ b/mesalib/src/mesa/shader/symbol_table.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "symbol_table.h"
+#include "hash_table.h"
+
+struct symbol {
+ /**
+ * Link to the next symbol in the table with the same name
+ *
+ * The linked list of symbols with the same name is ordered by scope
+ * from inner-most to outer-most.
+ */
+ struct symbol *next_with_same_name;
+
+
+ /**
+ * Link to the next symbol in the table with the same scope
+ *
+ * The linked list of symbols with the same scope is unordered. Symbols
+ * in this list my have unique names.
+ */
+ struct symbol *next_with_same_scope;
+
+
+ /**
+ * Header information for the list of symbols with the same name.
+ */
+ struct symbol_header *hdr;
+
+
+ /**
+ * Name space of the symbol
+ *
+ * Name space are arbitrary user assigned integers. No two symbols can
+ * exist in the same name space at the same scope level.
+ */
+ int name_space;
+
+
+ /**
+ * Arbitrary user supplied data.
+ */
+ void *data;
+};
+
+
+/**
+ */
+struct symbol_header {
+ /** Symbol name. */
+ const char *name;
+
+ /** Linked list of symbols with the same name. */
+ struct symbol *symbols;
+};
+
+
+/**
+ * Element of the scope stack.
+ */
+struct scope_level {
+ /** Link to next (inner) scope level. */
+ struct scope_level *next;
+
+ /** Linked list of symbols with the same scope. */
+ struct symbol *symbols;
+};
+
+
+/**
+ *
+ */
+struct _mesa_symbol_table {
+ /** Hash table containing all symbols in the symbol table. */
+ struct hash_table *ht;
+
+ /** Top of scope stack. */
+ struct scope_level *current_scope;
+};
+
+
+struct _mesa_symbol_table_iterator {
+ /**
+ * Name space of symbols returned by this iterator.
+ */
+ int name_space;
+
+
+ /**
+ * Currently iterated symbol
+ *
+ * The next call to \c _mesa_symbol_table_iterator_get will return this
+ * value. It will also update this value to the value that should be
+ * returned by the next call.
+ */
+ struct symbol *curr;
+};
+
+
+static void
+check_symbol_table(struct _mesa_symbol_table *table)
+{
+#if 1
+ struct scope_level *scope;
+
+ for (scope = table->current_scope; scope != NULL; scope = scope->next) {
+ struct symbol *sym;
+
+ for (sym = scope->symbols
+ ; sym != NULL
+ ; sym = sym->next_with_same_name) {
+ const struct symbol_header *const hdr = sym->hdr;
+ struct symbol *sym2;
+
+ for (sym2 = hdr->symbols
+ ; sym2 != NULL
+ ; sym2 = sym2->next_with_same_name) {
+ assert(sym2->hdr == hdr);
+ }
+ }
+ }
+#endif
+}
+
+void
+_mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = table->current_scope;
+ struct symbol *sym = scope->symbols;
+
+ table->current_scope = scope->next;
+
+ free(scope);
+
+ while (sym != NULL) {
+ struct symbol *const next = sym->next_with_same_scope;
+ struct symbol_header *const hdr = sym->hdr;
+
+ assert(hdr->symbols == sym);
+
+ hdr->symbols = sym->next_with_same_name;
+
+ free(sym);
+
+ sym = next;
+ }
+
+ check_symbol_table(table);
+}
+
+
+void
+_mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
+{
+ struct scope_level *const scope = calloc(1, sizeof(*scope));
+
+ scope->next = table->current_scope;
+ table->current_scope = scope;
+}
+
+
+static struct symbol_header *
+find_symbol(struct _mesa_symbol_table *table, const char *name)
+{
+ return (struct symbol_header *) hash_table_find(table->ht, name);
+}
+
+
+struct _mesa_symbol_table_iterator *
+_mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter));
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ iter->name_space = name_space;
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+ for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+ assert(sym->hdr == hdr);
+
+ if ((name_space == -1) || (sym->name_space == name_space)) {
+ iter->curr = sym;
+ break;
+ }
+ }
+ }
+
+ return iter;
+}
+
+
+void
+_mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter)
+{
+ free(iter);
+}
+
+
+void *
+_mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter)
+{
+ return (iter->curr == NULL) ? NULL : iter->curr->data;
+}
+
+
+int
+_mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
+{
+ struct symbol_header *hdr;
+
+ if (iter->curr == NULL) {
+ return 0;
+ }
+
+ hdr = iter->curr->hdr;
+ iter->curr = iter->curr->next_with_same_name;
+
+ while (iter->curr != NULL) {
+ assert(iter->curr->hdr == hdr);
+
+ if ((iter->name_space == -1)
+ || (iter->curr->name_space == iter->name_space)) {
+ return 1;
+ }
+
+ iter->curr = iter->curr->next_with_same_name;
+ }
+
+ return 0;
+}
+
+
+void *
+_mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name)
+{
+ struct symbol_header *const hdr = find_symbol(table, name);
+
+ if (hdr != NULL) {
+ struct symbol *sym;
+
+
+ for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
+ assert(sym->hdr == hdr);
+
+ if ((name_space == -1) || (sym->name_space == name_space)) {
+ return sym->data;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int
+_mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name,
+ void *declaration)
+{
+ struct symbol_header *hdr;
+ struct symbol *sym;
+
+ check_symbol_table(table);
+
+ hdr = find_symbol(table, name);
+
+ check_symbol_table(table);
+
+ if (hdr == NULL) {
+ hdr = calloc(1, sizeof(*hdr));
+ hdr->name = name;
+
+ hash_table_insert(table->ht, hdr, name);
+ }
+
+ check_symbol_table(table);
+
+ sym = calloc(1, sizeof(*sym));
+ sym->next_with_same_name = hdr->symbols;
+ sym->next_with_same_scope = table->current_scope->symbols;
+ sym->hdr = hdr;
+ sym->name_space = name_space;
+ sym->data = declaration;
+
+ assert(sym->hdr == hdr);
+
+ hdr->symbols = sym;
+ table->current_scope->symbols = sym;
+
+ check_symbol_table(table);
+ return 0;
+}
+
+
+struct _mesa_symbol_table *
+_mesa_symbol_table_ctor(void)
+{
+ struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
+
+ if (table != NULL) {
+ table->ht = hash_table_ctor(32, hash_table_string_hash,
+ hash_table_string_compare);
+
+ _mesa_symbol_table_push_scope(table);
+ }
+
+ return table;
+}
+
+
+void
+_mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
+{
+ while (table->current_scope != NULL) {
+ _mesa_symbol_table_pop_scope(table);
+ }
+
+ hash_table_dtor(table->ht);
+ free(table);
+}
diff --git a/mesalib/src/mesa/shader/symbol_table.h b/mesalib/src/mesa/shader/symbol_table.h
new file mode 100644
index 000000000..0c054ef13
--- /dev/null
+++ b/mesalib/src/mesa/shader/symbol_table.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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 MESA_SYMBOL_TABLE_H
+#define MESA_SYMBOL_TABLE_H
+
+struct _mesa_symbol_table;
+struct _mesa_symbol_table_iterator;
+
+extern void _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table);
+
+extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
+
+extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
+ int name_space, const char *name, void *declaration);
+
+extern void *_mesa_symbol_table_find_symbol(
+ struct _mesa_symbol_table *symtab, int name_space, const char *name);
+
+extern struct _mesa_symbol_table *_mesa_symbol_table_ctor(void);
+
+extern void _mesa_symbol_table_dtor(struct _mesa_symbol_table *);
+
+extern struct _mesa_symbol_table_iterator *_mesa_symbol_table_iterator_ctor(
+ struct _mesa_symbol_table *table, int name_space, const char *name);
+
+extern void _mesa_symbol_table_iterator_dtor(
+ struct _mesa_symbol_table_iterator *);
+
+extern void *_mesa_symbol_table_iterator_get(
+ struct _mesa_symbol_table_iterator *iter);
+
+extern int _mesa_symbol_table_iterator_next(
+ struct _mesa_symbol_table_iterator *iter);
+
+#endif /* MESA_SYMBOL_TABLE_H */
diff --git a/mesalib/src/mesa/sources.mak b/mesalib/src/mesa/sources.mak
new file mode 100644
index 000000000..fa2a6307a
--- /dev/null
+++ b/mesalib/src/mesa/sources.mak
@@ -0,0 +1,375 @@
+### Lists of source files, included by Makefiles
+
+MAIN_SOURCES = \
+ main/api_arrayelt.c \
+ main/api_exec.c \
+ main/api_loopback.c \
+ main/api_noop.c \
+ main/api_validate.c \
+ main/accum.c \
+ main/attrib.c \
+ main/arrayobj.c \
+ main/blend.c \
+ main/bufferobj.c \
+ main/buffers.c \
+ main/clear.c \
+ main/clip.c \
+ main/colortab.c \
+ main/context.c \
+ main/convolve.c \
+ main/cpuinfo.c \
+ main/debug.c \
+ main/depth.c \
+ main/depthstencil.c \
+ main/dlist.c \
+ main/dlopen.c \
+ main/drawpix.c \
+ main/enable.c \
+ main/enums.c \
+ main/eval.c \
+ main/execmem.c \
+ main/extensions.c \
+ main/fbobject.c \
+ main/feedback.c \
+ main/ffvertex_prog.c \
+ main/fog.c \
+ main/framebuffer.c \
+ main/get.c \
+ main/getstring.c \
+ main/hash.c \
+ main/hint.c \
+ main/histogram.c \
+ main/image.c \
+ main/imports.c \
+ main/light.c \
+ main/lines.c \
+ main/matrix.c \
+ main/mipmap.c \
+ main/mm.c \
+ main/multisample.c \
+ main/pixel.c \
+ main/pixelstore.c \
+ main/points.c \
+ main/polygon.c \
+ main/queryobj.c \
+ main/rastpos.c \
+ main/rbadaptors.c \
+ main/readpix.c \
+ main/renderbuffer.c \
+ main/scissor.c \
+ main/shaders.c \
+ main/shared.c \
+ main/state.c \
+ main/stencil.c \
+ main/syncobj.c \
+ main/texcompress.c \
+ main/texcompress_s3tc.c \
+ main/texcompress_fxt1.c \
+ main/texenv.c \
+ main/texenvprogram.c \
+ main/texformat.c \
+ main/texgen.c \
+ main/texgetimage.c \
+ main/teximage.c \
+ main/texobj.c \
+ main/texparam.c \
+ main/texrender.c \
+ main/texstate.c \
+ main/texstore.c \
+ main/varray.c \
+ main/viewport.c \
+ main/vtxfmt.c
+
+GLAPI_SOURCES = \
+ main/dispatch.c \
+ glapi/glapi.c \
+ glapi/glapi_getproc.c \
+ glapi/glthread.c
+
+MATH_SOURCES = \
+ math/m_debug_clip.c \
+ math/m_debug_norm.c \
+ math/m_debug_xform.c \
+ math/m_eval.c \
+ math/m_matrix.c \
+ math/m_translate.c \
+ math/m_vector.c
+
+MATH_XFORM_SOURCES = \
+ math/m_xform.c
+
+SWRAST_SOURCES = \
+ swrast/s_aaline.c \
+ swrast/s_aatriangle.c \
+ swrast/s_accum.c \
+ swrast/s_alpha.c \
+ swrast/s_atifragshader.c \
+ swrast/s_bitmap.c \
+ swrast/s_blend.c \
+ swrast/s_blit.c \
+ swrast/s_clear.c \
+ swrast/s_copypix.c \
+ swrast/s_context.c \
+ swrast/s_depth.c \
+ swrast/s_drawpix.c \
+ swrast/s_feedback.c \
+ swrast/s_fog.c \
+ swrast/s_fragprog.c \
+ swrast/s_imaging.c \
+ swrast/s_lines.c \
+ swrast/s_logic.c \
+ swrast/s_masking.c \
+ swrast/s_points.c \
+ swrast/s_readpix.c \
+ swrast/s_span.c \
+ swrast/s_stencil.c \
+ swrast/s_texcombine.c \
+ swrast/s_texfilter.c \
+ swrast/s_texstore.c \
+ swrast/s_triangle.c \
+ swrast/s_zoom.c
+
+SWRAST_SETUP_SOURCES = \
+ swrast_setup/ss_context.c \
+ swrast_setup/ss_triangle.c
+
+TNL_SOURCES = \
+ tnl/t_context.c \
+ tnl/t_pipeline.c \
+ tnl/t_draw.c \
+ tnl/t_rasterpos.c \
+ tnl/t_vb_program.c \
+ tnl/t_vb_render.c \
+ tnl/t_vb_texgen.c \
+ tnl/t_vb_texmat.c \
+ tnl/t_vb_vertex.c \
+ tnl/t_vb_cull.c \
+ tnl/t_vb_fog.c \
+ tnl/t_vb_light.c \
+ tnl/t_vb_normals.c \
+ tnl/t_vb_points.c \
+ tnl/t_vp_build.c \
+ tnl/t_vertex.c \
+ tnl/t_vertex_sse.c \
+ tnl/t_vertex_generic.c
+
+VBO_SOURCES = \
+ vbo/vbo_context.c \
+ vbo/vbo_exec.c \
+ vbo/vbo_exec_api.c \
+ vbo/vbo_exec_array.c \
+ vbo/vbo_exec_draw.c \
+ vbo/vbo_exec_eval.c \
+ vbo/vbo_rebase.c \
+ vbo/vbo_split.c \
+ vbo/vbo_split_copy.c \
+ vbo/vbo_split_inplace.c \
+ vbo/vbo_save.c \
+ vbo/vbo_save_api.c \
+ vbo/vbo_save_draw.c \
+ vbo/vbo_save_loopback.c
+
+STATETRACKER_SOURCES = \
+ state_tracker/st_atom.c \
+ state_tracker/st_atom_blend.c \
+ state_tracker/st_atom_clip.c \
+ state_tracker/st_atom_constbuf.c \
+ state_tracker/st_atom_depth.c \
+ state_tracker/st_atom_framebuffer.c \
+ state_tracker/st_atom_pixeltransfer.c \
+ state_tracker/st_atom_sampler.c \
+ state_tracker/st_atom_scissor.c \
+ state_tracker/st_atom_shader.c \
+ state_tracker/st_atom_rasterizer.c \
+ state_tracker/st_atom_stipple.c \
+ state_tracker/st_atom_texture.c \
+ state_tracker/st_atom_viewport.c \
+ state_tracker/st_cb_accum.c \
+ state_tracker/st_cb_bitmap.c \
+ state_tracker/st_cb_blit.c \
+ state_tracker/st_cb_bufferobjects.c \
+ state_tracker/st_cb_clear.c \
+ state_tracker/st_cb_flush.c \
+ state_tracker/st_cb_get.c \
+ state_tracker/st_cb_drawpixels.c \
+ state_tracker/st_cb_fbo.c \
+ state_tracker/st_cb_feedback.c \
+ state_tracker/st_cb_program.c \
+ state_tracker/st_cb_queryobj.c \
+ state_tracker/st_cb_rasterpos.c \
+ state_tracker/st_cb_readpixels.c \
+ state_tracker/st_cb_strings.c \
+ state_tracker/st_cb_texture.c \
+ state_tracker/st_cb_viewport.c \
+ state_tracker/st_api.c \
+ state_tracker/st_context.c \
+ state_tracker/st_debug.c \
+ state_tracker/st_draw.c \
+ state_tracker/st_draw_feedback.c \
+ state_tracker/st_extensions.c \
+ state_tracker/st_format.c \
+ state_tracker/st_framebuffer.c \
+ state_tracker/st_gen_mipmap.c \
+ state_tracker/st_mesa_to_tgsi.c \
+ state_tracker/st_program.c \
+ state_tracker/st_texture.c
+
+SHADER_SOURCES = \
+ shader/arbprogparse.c \
+ shader/arbprogram.c \
+ shader/atifragshader.c \
+ shader/grammar/grammar_mesa.c \
+ shader/hash_table.c \
+ shader/lex.yy.c \
+ shader/nvfragparse.c \
+ shader/nvprogram.c \
+ shader/nvvertparse.c \
+ shader/program.c \
+ shader/program_parse.tab.c \
+ shader/program_parse_extra.c \
+ shader/prog_cache.c \
+ shader/prog_execute.c \
+ shader/prog_instruction.c \
+ shader/prog_noise.c \
+ shader/prog_optimize.c \
+ shader/prog_parameter.c \
+ shader/prog_parameter_layout.c \
+ shader/prog_print.c \
+ shader/prog_statevars.c \
+ shader/prog_uniform.c \
+ shader/programopt.c \
+ shader/symbol_table.c \
+ shader/shader_api.c
+
+SLANG_SOURCES = \
+ shader/slang/slang_builtin.c \
+ shader/slang/slang_codegen.c \
+ shader/slang/slang_compile.c \
+ shader/slang/slang_compile_function.c \
+ shader/slang/slang_compile_operation.c \
+ shader/slang/slang_compile_struct.c \
+ shader/slang/slang_compile_variable.c \
+ shader/slang/slang_emit.c \
+ shader/slang/slang_ir.c \
+ shader/slang/slang_label.c \
+ shader/slang/slang_link.c \
+ shader/slang/slang_log.c \
+ shader/slang/slang_mem.c \
+ shader/slang/slang_preprocess.c \
+ shader/slang/slang_print.c \
+ shader/slang/slang_simplify.c \
+ shader/slang/slang_storage.c \
+ shader/slang/slang_typeinfo.c \
+ shader/slang/slang_vartable.c \
+ shader/slang/slang_utility.c
+
+ASM_C_SOURCES = \
+ x86/common_x86.c \
+ x86/x86_xform.c \
+ x86/3dnow.c \
+ x86/sse.c \
+ x86/rtasm/x86sse.c \
+ sparc/sparc.c \
+ ppc/common_ppc.c \
+ x86-64/x86-64.c
+
+X86_SOURCES = \
+ x86/common_x86_asm.S \
+ x86/x86_xform2.S \
+ x86/x86_xform3.S \
+ x86/x86_xform4.S \
+ x86/x86_cliptest.S \
+ x86/mmx_blend.S \
+ x86/3dnow_xform1.S \
+ x86/3dnow_xform2.S \
+ x86/3dnow_xform3.S \
+ x86/3dnow_xform4.S \
+ x86/3dnow_normal.S \
+ x86/sse_xform1.S \
+ x86/sse_xform2.S \
+ x86/sse_xform3.S \
+ x86/sse_xform4.S \
+ x86/sse_normal.S \
+ x86/read_rgba_span_x86.S
+
+X86_API = \
+ x86/glapi_x86.S
+
+X86-64_SOURCES = \
+ x86-64/xform4.S
+
+X86-64_API = \
+ x86-64/glapi_x86-64.S
+
+SPARC_SOURCES = \
+ sparc/clip.S \
+ sparc/norm.S \
+ sparc/xform.S
+
+SPARC_API = \
+ sparc/glapi_sparc.S
+
+COMMON_DRIVER_SOURCES = \
+ drivers/common/driverfuncs.c \
+ drivers/common/meta.c
+
+
+# Sources for building non-Gallium drivers
+MESA_SOURCES = \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(MATH_XFORM_SOURCES) \
+ $(VBO_SOURCES) \
+ $(TNL_SOURCES) \
+ $(SHADER_SOURCES) \
+ $(SWRAST_SOURCES) \
+ $(SWRAST_SETUP_SOURCES) \
+ $(COMMON_DRIVER_SOURCES)\
+ $(ASM_C_SOURCES) \
+ $(SLANG_SOURCES)
+
+# Sources for building Gallium drivers
+MESA_GALLIUM_SOURCES = \
+ $(MAIN_SOURCES) \
+ $(MATH_SOURCES) \
+ $(VBO_SOURCES) \
+ $(STATETRACKER_SOURCES) \
+ $(SHADER_SOURCES) \
+ ppc/common_ppc.c \
+ x86/common_x86.c \
+ $(SLANG_SOURCES)
+
+# All the core C sources, for dependency checking
+ALL_SOURCES = \
+ $(MESA_SOURCES) \
+ $(GLAPI_SOURCES) \
+ $(MESA_ASM_SOURCES) \
+ $(STATETRACKER_SOURCES)
+
+
+### Object files
+
+MESA_OBJECTS = \
+ $(MESA_SOURCES:.c=.o) \
+ $(MESA_ASM_SOURCES:.S=.o)
+
+MESA_GALLIUM_OBJECTS = \
+ $(MESA_GALLIUM_SOURCES:.c=.o) \
+ $(MESA_ASM_SOURCES:.S=.o)
+
+GLAPI_OBJECTS = \
+ $(GLAPI_SOURCES:.c=.o) \
+ $(GLAPI_ASM_SOURCES:.S=.o)
+
+
+COMMON_DRIVER_OBJECTS = $(COMMON_DRIVER_SOURCES:.c=.o)
+
+
+
+### Include directories
+
+INCLUDE_DIRS = \
+ -I$(TOP)/include \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/gallium/include \
+ -I$(TOP)/src/gallium/auxiliary
diff --git a/mesalib/src/mesa/swrast/descrip.mms b/mesalib/src/mesa/swrast/descrip.mms
new file mode 100644
index 000000000..0b23deb3c
--- /dev/null
+++ b/mesalib/src/mesa/swrast/descrip.mms
@@ -0,0 +1,82 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define swrast [-.swrast]
+ define array_cache [-.array_cache]
+ define glapi [-.glapi]
+ define main [-.main]
+ define shader [-.shader]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = s_aaline.c s_aatriangle.c s_accum.c s_alpha.c \
+ s_bitmap.c s_blend.c s_blit.c s_buffers.c s_context.c \
+ s_copypix.c s_depth.c s_fragprog.c \
+ s_drawpix.c s_feedback.c s_fog.c s_imaging.c s_lines.c s_logic.c \
+ s_masking.c s_points.c s_readpix.c \
+ s_span.c s_stencil.c s_texstore.c s_texcombine.c s_texfilter.c \
+ s_triangle.c s_zoom.c s_atifragshader.c
+
+OBJECTS = s_aaline.obj,s_aatriangle.obj,s_accum.obj,s_alpha.obj,\
+ s_bitmap.obj,s_blend.obj,s_blit.obj,s_fragprog.obj,\
+ s_buffers.obj,s_context.obj,s_atifragshader.obj,\
+ s_copypix.obj,s_depth.obj,s_drawpix.obj,s_feedback.obj,s_fog.obj,\
+ s_imaging.obj,s_lines.obj,s_logic.obj,s_masking.obj,\
+ s_points.obj,s_readpix.obj,s_span.obj,s_stencil.obj,\
+ s_texstore.obj,s_texcombine.obj,s_texfilter.obj,s_triangle.obj,\
+ s_zoom.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+s_atifragshader.obj : s_atifragshader.c
+s_aaline.obj : s_aaline.c
+s_aatriangle.obj : s_aatriangle.c
+s_accum.obj : s_accum.c
+s_alpha.obj : s_alpha.c
+s_bitmap.obj : s_bitmap.c
+s_blend.obj : s_blend.c
+s_blit.obj : s_blit.c
+s_buffers.obj : s_buffers.c
+s_context.obj : s_context.c
+s_copypix.obj : s_copypix.c
+s_depth.obj : s_depth.c
+s_drawpix.obj : s_drawpix.c
+s_feedback.obj : s_feedback.c
+s_fog.obj : s_fog.c
+s_imaging.obj : s_imaging.c
+s_lines.obj : s_lines.c
+s_logic.obj : s_logic.c
+s_masking.obj : s_masking.c
+s_points.obj : s_points.c
+s_readpix.obj : s_readpix.c
+s_span.obj : s_span.c
+s_stencil.obj : s_stencil.c
+s_texstore.obj : s_texstore.c
+s_texcombine.obj : s_texcombine.c
+s_texfilter.obj : s_texfilter.c
+s_triangle.obj : s_triangle.c
+s_zoom.obj : s_zoom.c
+s_fragprog.obj : s_fragprog.c
diff --git a/mesalib/src/mesa/swrast/s_aaline.c b/mesalib/src/mesa/swrast/s_aaline.c
new file mode 100644
index 000000000..9bfa8f2e6
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aaline.c
@@ -0,0 +1,524 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "swrast/s_aaline.h"
+#include "swrast/s_context.h"
+#include "swrast/s_span.h"
+#include "swrast/swrast.h"
+
+
+#define SUB_PIXEL 4
+
+
+/*
+ * Info about the AA line we're rendering
+ */
+struct LineInfo
+{
+ GLfloat x0, y0; /* start */
+ GLfloat x1, y1; /* end */
+ GLfloat dx, dy; /* direction vector */
+ GLfloat len; /* length */
+ GLfloat halfWidth; /* half of line width */
+ GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */
+ /* for coverage computation */
+ GLfloat qx0, qy0; /* quad vertices */
+ GLfloat qx1, qy1;
+ GLfloat qx2, qy2;
+ GLfloat qx3, qy3;
+ GLfloat ex0, ey0; /* quad edge vectors */
+ GLfloat ex1, ey1;
+ GLfloat ex2, ey2;
+ GLfloat ex3, ey3;
+
+ /* DO_Z */
+ GLfloat zPlane[4];
+ /* DO_RGBA */
+ GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
+ /* DO_INDEX */
+ GLfloat iPlane[4];
+ /* DO_ATTRIBS */
+ GLfloat wPlane[4];
+ GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4];
+ GLfloat lambda[FRAG_ATTRIB_MAX];
+ GLfloat texWidth[FRAG_ATTRIB_MAX];
+ GLfloat texHeight[FRAG_ATTRIB_MAX];
+
+ SWspan span;
+};
+
+
+
+/*
+ * Compute the equation of a plane used to interpolate line fragment data
+ * such as color, Z, texture coords, etc.
+ * Input: (x0, y0) and (x1,y1) are the endpoints of the line.
+ * z0, and z1 are the end point values to interpolate.
+ * Output: plane - the plane equation.
+ *
+ * Note: we don't really have enough parameters to specify a plane.
+ * We take the endpoints of the line and compute a plane such that
+ * the cross product of the line vector and the plane normal is
+ * parallel to the projection plane.
+ */
+static void
+compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
+ GLfloat z0, GLfloat z1, GLfloat plane[4])
+{
+#if 0
+ /* original */
+ const GLfloat px = x1 - x0;
+ const GLfloat py = y1 - y0;
+ const GLfloat pz = z1 - z0;
+ const GLfloat qx = -py;
+ const GLfloat qy = px;
+ const GLfloat qz = 0;
+ const GLfloat a = py * qz - pz * qy;
+ const GLfloat b = pz * qx - px * qz;
+ const GLfloat c = px * qy - py * qx;
+ const GLfloat d = -(a * x0 + b * y0 + c * z0);
+ plane[0] = a;
+ plane[1] = b;
+ plane[2] = c;
+ plane[3] = d;
+#else
+ /* simplified */
+ const GLfloat px = x1 - x0;
+ const GLfloat py = y1 - y0;
+ const GLfloat pz = z0 - z1;
+ const GLfloat a = pz * px;
+ const GLfloat b = pz * py;
+ const GLfloat c = px * px + py * py;
+ const GLfloat d = -(a * x0 + b * y0 + c * z0);
+ if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) {
+ plane[0] = 0.0;
+ plane[1] = 0.0;
+ plane[2] = 1.0;
+ plane[3] = 0.0;
+ }
+ else {
+ plane[0] = a;
+ plane[1] = b;
+ plane[2] = c;
+ plane[3] = d;
+ }
+#endif
+}
+
+
+static INLINE void
+constant_plane(GLfloat value, GLfloat plane[4])
+{
+ plane[0] = 0.0;
+ plane[1] = 0.0;
+ plane[2] = -1.0;
+ plane[3] = value;
+}
+
+
+static INLINE GLfloat
+solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
+ return z;
+}
+
+#define SOLVE_PLANE(X, Y, PLANE) \
+ ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
+
+
+/*
+ * Return 1 / solve_plane().
+ */
+static INLINE GLfloat
+solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
+ if (denom == 0.0)
+ return 0.0;
+ else
+ return -plane[2] / denom;
+}
+
+
+/*
+ * Solve plane and return clamped GLchan value.
+ */
+static INLINE GLchan
+solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
+#if CHAN_TYPE == GL_FLOAT
+ return CLAMP(z, 0.0F, CHAN_MAXF);
+#else
+ if (z < 0)
+ return 0;
+ else if (z > CHAN_MAX)
+ return CHAN_MAX;
+ return (GLchan) IROUND_POS(z);
+#endif
+}
+
+
+/*
+ * Compute mipmap level of detail.
+ */
+static INLINE GLfloat
+compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
+ GLfloat invQ, GLfloat width, GLfloat height)
+{
+ GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
+ GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
+ GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
+ GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
+ GLfloat r1 = dudx * dudx + dudy * dudy;
+ GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
+ GLfloat rho2 = r1 + r2;
+ /* return log base 2 of rho */
+ if (rho2 == 0.0F)
+ return 0.0;
+ else
+ return (GLfloat) (LOGF(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */
+}
+
+
+
+
+/*
+ * Fill in the samples[] array with the (x,y) subpixel positions of
+ * xSamples * ySamples sample positions.
+ * Note that the four corner samples are put into the first four
+ * positions of the array. This allows us to optimize for the common
+ * case of all samples being inside the polygon.
+ */
+static void
+make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2])
+{
+ const GLfloat dx = 1.0F / (GLfloat) xSamples;
+ const GLfloat dy = 1.0F / (GLfloat) ySamples;
+ GLint x, y;
+ GLint i;
+
+ i = 4;
+ for (x = 0; x < xSamples; x++) {
+ for (y = 0; y < ySamples; y++) {
+ GLint j;
+ if (x == 0 && y == 0) {
+ /* lower left */
+ j = 0;
+ }
+ else if (x == xSamples - 1 && y == 0) {
+ /* lower right */
+ j = 1;
+ }
+ else if (x == 0 && y == ySamples - 1) {
+ /* upper left */
+ j = 2;
+ }
+ else if (x == xSamples - 1 && y == ySamples - 1) {
+ /* upper right */
+ j = 3;
+ }
+ else {
+ j = i++;
+ }
+ samples[j][0] = x * dx + 0.5F * dx;
+ samples[j][1] = y * dy + 0.5F * dy;
+ }
+ }
+}
+
+
+
+/*
+ * Compute how much of the given pixel's area is inside the rectangle
+ * defined by vertices v0, v1, v2, v3.
+ * Vertices MUST be specified in counter-clockwise order.
+ * Return: coverage in [0, 1].
+ */
+static GLfloat
+compute_coveragef(const struct LineInfo *info,
+ GLint winx, GLint winy)
+{
+ static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2];
+ static GLboolean haveSamples = GL_FALSE;
+ const GLfloat x = (GLfloat) winx;
+ const GLfloat y = (GLfloat) winy;
+ GLint stop = 4, i;
+ GLfloat insideCount = SUB_PIXEL * SUB_PIXEL;
+
+ if (!haveSamples) {
+ make_sample_table(SUB_PIXEL, SUB_PIXEL, samples);
+ haveSamples = GL_TRUE;
+ }
+
+#if 0 /*DEBUG*/
+ {
+ const GLfloat area = dx0 * dy1 - dx1 * dy0;
+ assert(area >= 0.0);
+ }
+#endif
+
+ for (i = 0; i < stop; i++) {
+ const GLfloat sx = x + samples[i][0];
+ const GLfloat sy = y + samples[i][1];
+ const GLfloat fx0 = sx - info->qx0;
+ const GLfloat fy0 = sy - info->qy0;
+ const GLfloat fx1 = sx - info->qx1;
+ const GLfloat fy1 = sy - info->qy1;
+ const GLfloat fx2 = sx - info->qx2;
+ const GLfloat fy2 = sy - info->qy2;
+ const GLfloat fx3 = sx - info->qx3;
+ const GLfloat fy3 = sy - info->qy3;
+ /* cross product determines if sample is inside or outside each edge */
+ GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0);
+ GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1);
+ GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2);
+ GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3);
+ /* Check if the sample is exactly on an edge. If so, let cross be a
+ * positive or negative value depending on the direction of the edge.
+ */
+ if (cross0 == 0.0F)
+ cross0 = info->ex0 + info->ey0;
+ if (cross1 == 0.0F)
+ cross1 = info->ex1 + info->ey1;
+ if (cross2 == 0.0F)
+ cross2 = info->ex2 + info->ey2;
+ if (cross3 == 0.0F)
+ cross3 = info->ex3 + info->ey3;
+ if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) {
+ /* point is outside quadrilateral */
+ insideCount -= 1.0F;
+ stop = SUB_PIXEL * SUB_PIXEL;
+ }
+ }
+ if (stop == 4)
+ return 1.0F;
+ else
+ return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL));
+}
+
+
+/**
+ * Compute coverage value for color index mode.
+ * XXX this may not be quite correct.
+ * \return coverage in [0,15].
+ */
+static GLfloat
+compute_coveragei(const struct LineInfo *info,
+ GLint winx, GLint winy)
+{
+ return compute_coveragef(info, winx, winy) * 15.0F;
+}
+
+
+
+typedef void (*plot_func)(GLcontext *ctx, struct LineInfo *line,
+ int ix, int iy);
+
+
+
+/*
+ * Draw an AA line segment (called many times per line when stippling)
+ */
+static void
+segment(GLcontext *ctx,
+ struct LineInfo *line,
+ plot_func plot,
+ GLfloat t0, GLfloat t1)
+{
+ const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
+ const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy;
+ /* compute the actual segment's endpoints */
+ const GLfloat x0 = line->x0 + t0 * line->dx;
+ const GLfloat y0 = line->y0 + t0 * line->dy;
+ const GLfloat x1 = line->x0 + t1 * line->dx;
+ const GLfloat y1 = line->y0 + t1 * line->dy;
+
+ /* compute vertices of the line-aligned quadrilateral */
+ line->qx0 = x0 - line->yAdj;
+ line->qy0 = y0 + line->xAdj;
+ line->qx1 = x0 + line->yAdj;
+ line->qy1 = y0 - line->xAdj;
+ line->qx2 = x1 + line->yAdj;
+ line->qy2 = y1 - line->xAdj;
+ line->qx3 = x1 - line->yAdj;
+ line->qy3 = y1 + line->xAdj;
+ /* compute the quad's edge vectors (for coverage calc) */
+ line->ex0 = line->qx1 - line->qx0;
+ line->ey0 = line->qy1 - line->qy0;
+ line->ex1 = line->qx2 - line->qx1;
+ line->ey1 = line->qy2 - line->qy1;
+ line->ex2 = line->qx3 - line->qx2;
+ line->ey2 = line->qy3 - line->qy2;
+ line->ex3 = line->qx0 - line->qx3;
+ line->ey3 = line->qy0 - line->qy3;
+
+ if (absDx > absDy) {
+ /* X-major line */
+ GLfloat dydx = line->dy / line->dx;
+ GLfloat xLeft, xRight, yBot, yTop;
+ GLint ix, ixRight;
+ if (x0 < x1) {
+ xLeft = x0 - line->halfWidth;
+ xRight = x1 + line->halfWidth;
+ if (line->dy >= 0.0) {
+ yBot = y0 - 3.0F * line->halfWidth;
+ yTop = y0 + line->halfWidth;
+ }
+ else {
+ yBot = y0 - line->halfWidth;
+ yTop = y0 + 3.0F * line->halfWidth;
+ }
+ }
+ else {
+ xLeft = x1 - line->halfWidth;
+ xRight = x0 + line->halfWidth;
+ if (line->dy <= 0.0) {
+ yBot = y1 - 3.0F * line->halfWidth;
+ yTop = y1 + line->halfWidth;
+ }
+ else {
+ yBot = y1 - line->halfWidth;
+ yTop = y1 + 3.0F * line->halfWidth;
+ }
+ }
+
+ /* scan along the line, left-to-right */
+ ixRight = (GLint) (xRight + 1.0F);
+
+ /*printf("avg span height: %g\n", yTop - yBot);*/
+ for (ix = (GLint) xLeft; ix < ixRight; ix++) {
+ const GLint iyBot = (GLint) yBot;
+ const GLint iyTop = (GLint) (yTop + 1.0F);
+ GLint iy;
+ /* scan across the line, bottom-to-top */
+ for (iy = iyBot; iy < iyTop; iy++) {
+ (*plot)(ctx, line, ix, iy);
+ }
+ yBot += dydx;
+ yTop += dydx;
+ }
+ }
+ else {
+ /* Y-major line */
+ GLfloat dxdy = line->dx / line->dy;
+ GLfloat yBot, yTop, xLeft, xRight;
+ GLint iy, iyTop;
+ if (y0 < y1) {
+ yBot = y0 - line->halfWidth;
+ yTop = y1 + line->halfWidth;
+ if (line->dx >= 0.0) {
+ xLeft = x0 - 3.0F * line->halfWidth;
+ xRight = x0 + line->halfWidth;
+ }
+ else {
+ xLeft = x0 - line->halfWidth;
+ xRight = x0 + 3.0F * line->halfWidth;
+ }
+ }
+ else {
+ yBot = y1 - line->halfWidth;
+ yTop = y0 + line->halfWidth;
+ if (line->dx <= 0.0) {
+ xLeft = x1 - 3.0F * line->halfWidth;
+ xRight = x1 + line->halfWidth;
+ }
+ else {
+ xLeft = x1 - line->halfWidth;
+ xRight = x1 + 3.0F * line->halfWidth;
+ }
+ }
+
+ /* scan along the line, bottom-to-top */
+ iyTop = (GLint) (yTop + 1.0F);
+
+ /*printf("avg span width: %g\n", xRight - xLeft);*/
+ for (iy = (GLint) yBot; iy < iyTop; iy++) {
+ const GLint ixLeft = (GLint) xLeft;
+ const GLint ixRight = (GLint) (xRight + 1.0F);
+ GLint ix;
+ /* scan across the line, left-to-right */
+ for (ix = ixLeft; ix < ixRight; ix++) {
+ (*plot)(ctx, line, ix, iy);
+ }
+ xLeft += dxdy;
+ xRight += dxdy;
+ }
+ }
+}
+
+
+#define NAME(x) aa_ci_##x
+#define DO_Z
+#define DO_ATTRIBS /* for fog */
+#define DO_INDEX
+#include "s_aalinetemp.h"
+
+
+#define NAME(x) aa_rgba_##x
+#define DO_Z
+#define DO_RGBA
+#include "s_aalinetemp.h"
+
+
+#define NAME(x) aa_general_rgba_##x
+#define DO_Z
+#define DO_RGBA
+#define DO_ATTRIBS
+#include "s_aalinetemp.h"
+
+
+
+void
+_swrast_choose_aa_line_function(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ ASSERT(ctx->Line.SmoothFlag);
+
+ if (ctx->Visual.rgbMode) {
+ /* RGBA */
+ if (ctx->Texture._EnabledCoordUnits != 0
+ || ctx->FragmentProgram._Current
+ || (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
+ || ctx->Fog.ColorSumEnabled
+ || swrast->_FogEnabled) {
+ swrast->Line = aa_general_rgba_line;
+ }
+ else {
+ swrast->Line = aa_rgba_line;
+ }
+ }
+ else {
+ /* Color Index */
+ swrast->Line = aa_ci_line;
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_aaline.h b/mesalib/src/mesa/swrast/s_aaline.h
new file mode 100644
index 000000000..f1d708ec8
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aaline.h
@@ -0,0 +1,38 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_AALINE_H
+#define S_AALINE_H
+
+
+#include "swrast.h"
+
+
+extern void
+_swrast_choose_aa_line_function(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_aalinetemp.h b/mesalib/src/mesa/swrast/s_aalinetemp.h
new file mode 100644
index 000000000..42ffe9f20
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aalinetemp.h
@@ -0,0 +1,274 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * Antialiased line template.
+ */
+
+
+/*
+ * Function to render each fragment in the AA line.
+ * \param ix - integer fragment window X coordiante
+ * \param iy - integer fragment window Y coordiante
+ */
+static void
+NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLfloat fx = (GLfloat) ix;
+ const GLfloat fy = (GLfloat) iy;
+#ifdef DO_INDEX
+ const GLfloat coverage = compute_coveragei(line, ix, iy);
+#else
+ const GLfloat coverage = compute_coveragef(line, ix, iy);
+#endif
+ const GLuint i = line->span.end;
+
+ (void) swrast;
+
+ if (coverage == 0.0)
+ return;
+
+ line->span.end++;
+ line->span.array->coverage[i] = coverage;
+ line->span.array->x[i] = ix;
+ line->span.array->y[i] = iy;
+
+ /*
+ * Compute Z, color, texture coords, fog for the fragment by
+ * solving the plane equations at (ix,iy).
+ */
+#ifdef DO_Z
+ line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane);
+#endif
+#ifdef DO_RGBA
+ line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane);
+ line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane);
+ line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane);
+ line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane);
+#endif
+#ifdef DO_INDEX
+ line->span.array->index[i] = (GLint) solve_plane(fx, fy, line->iPlane);
+#endif
+#if defined(DO_ATTRIBS)
+ ATTRIB_LOOP_BEGIN
+ GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
+ if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0
+ && !ctx->FragmentProgram._Current) {
+ /* texcoord w/ divide by Q */
+ const GLuint unit = attr - FRAG_ATTRIB_TEX0;
+ const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]);
+ GLuint c;
+ for (c = 0; c < 3; c++) {
+ attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ;
+ }
+ line->span.array->lambda[unit][i]
+ = compute_lambda(line->attrPlane[attr][0],
+ line->attrPlane[attr][1], invQ,
+ line->texWidth[attr], line->texHeight[attr]);
+ }
+ else {
+ /* non-texture attrib */
+ const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane);
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW;
+ }
+ }
+ ATTRIB_LOOP_END
+#endif
+
+ if (line->span.end == MAX_WIDTH) {
+#if defined(DO_RGBA)
+ _swrast_write_rgba_span(ctx, &(line->span));
+#else
+ _swrast_write_index_span(ctx, &(line->span));
+#endif
+ line->span.end = 0; /* reset counter */
+ }
+}
+
+
+
+/*
+ * Line setup
+ */
+static void
+NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat tStart, tEnd; /* segment start, end along line length */
+ GLboolean inSegment;
+ GLint iLen, i;
+
+ /* Init the LineInfo struct */
+ struct LineInfo line;
+ line.x0 = v0->attrib[FRAG_ATTRIB_WPOS][0];
+ line.y0 = v0->attrib[FRAG_ATTRIB_WPOS][1];
+ line.x1 = v1->attrib[FRAG_ATTRIB_WPOS][0];
+ line.y1 = v1->attrib[FRAG_ATTRIB_WPOS][1];
+ line.dx = line.x1 - line.x0;
+ line.dy = line.y1 - line.y0;
+ line.len = SQRTF(line.dx * line.dx + line.dy * line.dy);
+ line.halfWidth = 0.5F * CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidthAA,
+ ctx->Const.MaxLineWidthAA);
+
+ if (line.len == 0.0 || IS_INF_OR_NAN(line.len))
+ return;
+
+ INIT_SPAN(line.span, GL_LINE);
+ line.span.arrayMask = SPAN_XY | SPAN_COVERAGE;
+ line.span.facing = swrast->PointLineFacing;
+ line.xAdj = line.dx / line.len * line.halfWidth;
+ line.yAdj = line.dy / line.len * line.halfWidth;
+
+#ifdef DO_Z
+ line.span.arrayMask |= SPAN_Z;
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->attrib[FRAG_ATTRIB_WPOS][2], v1->attrib[FRAG_ATTRIB_WPOS][2], line.zPlane);
+#endif
+#ifdef DO_RGBA
+ line.span.arrayMask |= SPAN_RGBA;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
+ }
+ else {
+ constant_plane(v1->color[RCOMP], line.rPlane);
+ constant_plane(v1->color[GCOMP], line.gPlane);
+ constant_plane(v1->color[BCOMP], line.bPlane);
+ constant_plane(v1->color[ACOMP], line.aPlane);
+ }
+#endif
+#ifdef DO_INDEX
+ line.span.arrayMask |= SPAN_INDEX;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ compute_plane(line.x0, line.y0, line.x1, line.y1,
+ v0->attrib[FRAG_ATTRIB_CI][0],
+ v1->attrib[FRAG_ATTRIB_CI][0], line.iPlane);
+ }
+ else {
+ constant_plane(v1->attrib[FRAG_ATTRIB_CI][0], line.iPlane);
+ }
+#endif
+#if defined(DO_ATTRIBS)
+ {
+ const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3];
+ line.span.arrayMask |= SPAN_LAMBDA;
+ compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane);
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ if (swrast->_InterpMode[attr] == GL_FLAT) {
+ for (c = 0; c < 4; c++) {
+ constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]);
+ }
+ }
+ else {
+ for (c = 0; c < 4; c++) {
+ const GLfloat a0 = v0->attrib[attr][c] * invW0;
+ const GLfloat a1 = v1->attrib[attr][c] * invW1;
+ compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1,
+ line.attrPlane[attr][c]);
+ }
+ }
+ line.span.arrayAttribs |= (1 << attr);
+ if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) {
+ const GLuint u = attr - FRAG_ATTRIB_TEX0;
+ const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
+ const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
+ line.texWidth[attr] = (GLfloat) texImage->Width;
+ line.texHeight[attr] = (GLfloat) texImage->Height;
+ }
+ ATTRIB_LOOP_END
+ }
+#endif
+
+ tStart = tEnd = 0.0;
+ inSegment = GL_FALSE;
+ iLen = (GLint) line.len;
+
+ if (ctx->Line.StippleFlag) {
+ for (i = 0; i < iLen; i++) {
+ const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
+ if ((1 << bit) & ctx->Line.StipplePattern) {
+ /* stipple bit is on */
+ const GLfloat t = (GLfloat) i / (GLfloat) line.len;
+ if (!inSegment) {
+ /* start new segment */
+ inSegment = GL_TRUE;
+ tStart = t;
+ }
+ else {
+ /* still in the segment, extend it */
+ tEnd = t;
+ }
+ }
+ else {
+ /* stipple bit is off */
+ if (inSegment && (tEnd > tStart)) {
+ /* draw the segment */
+ segment(ctx, &line, NAME(plot), tStart, tEnd);
+ inSegment = GL_FALSE;
+ }
+ else {
+ /* still between segments, do nothing */
+ }
+ }
+ swrast->StippleCounter++;
+ }
+
+ if (inSegment) {
+ /* draw the final segment of the line */
+ segment(ctx, &line, NAME(plot), tStart, 1.0F);
+ }
+ }
+ else {
+ /* non-stippled */
+ segment(ctx, &line, NAME(plot), 0.0, 1.0);
+ }
+
+#if defined(DO_RGBA)
+ _swrast_write_rgba_span(ctx, &(line.span));
+#else
+ _swrast_write_index_span(ctx, &(line.span));
+#endif
+}
+
+
+
+
+#undef DO_Z
+#undef DO_RGBA
+#undef DO_INDEX
+#undef DO_ATTRIBS
+#undef NAME
diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c
new file mode 100644
index 000000000..078f16aea
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aatriangle.c
@@ -0,0 +1,417 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * Antialiased Triangle rasterizers
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "s_aatriangle.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+/*
+ * Compute coefficients of a plane using the X,Y coords of the v0, v1, v2
+ * vertices and the given Z values.
+ * A point (x,y,z) lies on plane iff a*x+b*y+c*z+d = 0.
+ */
+static INLINE void
+compute_plane(const GLfloat v0[], const GLfloat v1[], const GLfloat v2[],
+ GLfloat z0, GLfloat z1, GLfloat z2, GLfloat plane[4])
+{
+ const GLfloat px = v1[0] - v0[0];
+ const GLfloat py = v1[1] - v0[1];
+ const GLfloat pz = z1 - z0;
+
+ const GLfloat qx = v2[0] - v0[0];
+ const GLfloat qy = v2[1] - v0[1];
+ const GLfloat qz = z2 - z0;
+
+ /* Crossproduct "(a,b,c):= dv1 x dv2" is orthogonal to plane. */
+ const GLfloat a = py * qz - pz * qy;
+ const GLfloat b = pz * qx - px * qz;
+ const GLfloat c = px * qy - py * qx;
+ /* Point on the plane = "r*(a,b,c) + w", with fixed "r" depending
+ on the distance of plane from origin and arbitrary "w" parallel
+ to the plane. */
+ /* The scalar product "(r*(a,b,c)+w)*(a,b,c)" is "r*(a^2+b^2+c^2)",
+ which is equal to "-d" below. */
+ const GLfloat d = -(a * v0[0] + b * v0[1] + c * z0);
+
+ plane[0] = a;
+ plane[1] = b;
+ plane[2] = c;
+ plane[3] = d;
+}
+
+
+/*
+ * Compute coefficients of a plane with a constant Z value.
+ */
+static INLINE void
+constant_plane(GLfloat value, GLfloat plane[4])
+{
+ plane[0] = 0.0;
+ plane[1] = 0.0;
+ plane[2] = -1.0;
+ plane[3] = value;
+}
+
+#define CONSTANT_PLANE(VALUE, PLANE) \
+do { \
+ PLANE[0] = 0.0F; \
+ PLANE[1] = 0.0F; \
+ PLANE[2] = -1.0F; \
+ PLANE[3] = VALUE; \
+} while (0)
+
+
+
+/*
+ * Solve plane equation for Z at (X,Y).
+ */
+static INLINE GLfloat
+solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ ASSERT(plane[2] != 0.0F);
+ return (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
+}
+
+
+#define SOLVE_PLANE(X, Y, PLANE) \
+ ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
+
+
+/*
+ * Return 1 / solve_plane().
+ */
+static INLINE GLfloat
+solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
+ if (denom == 0.0F)
+ return 0.0F;
+ else
+ return -plane[2] / denom;
+}
+
+
+/*
+ * Solve plane and return clamped GLchan value.
+ */
+static INLINE GLchan
+solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
+{
+ const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
+#if CHAN_TYPE == GL_FLOAT
+ return CLAMP(z, 0.0F, CHAN_MAXF);
+#else
+ if (z < 0)
+ return 0;
+ else if (z > CHAN_MAX)
+ return CHAN_MAX;
+ return (GLchan) IROUND_POS(z);
+#endif
+}
+
+
+static INLINE GLfloat
+plane_dx(const GLfloat plane[4])
+{
+ return -plane[0] / plane[2];
+}
+
+static INLINE GLfloat
+plane_dy(const GLfloat plane[4])
+{
+ return -plane[1] / plane[2];
+}
+
+
+
+/*
+ * Compute how much (area) of the given pixel is inside the triangle.
+ * Vertices MUST be specified in counter-clockwise order.
+ * Return: coverage in [0, 1].
+ */
+static GLfloat
+compute_coveragef(const GLfloat v0[3], const GLfloat v1[3],
+ const GLfloat v2[3], GLint winx, GLint winy)
+{
+ /* Given a position [0,3]x[0,3] return the sub-pixel sample position.
+ * Contributed by Ray Tice.
+ *
+ * Jitter sample positions -
+ * - average should be .5 in x & y for each column
+ * - each of the 16 rows and columns should be used once
+ * - the rectangle formed by the first four points
+ * should contain the other points
+ * - the distrubition should be fairly even in any given direction
+ *
+ * The pattern drawn below isn't optimal, but it's better than a regular
+ * grid. In the drawing, the center of each subpixel is surrounded by
+ * four dots. The "x" marks the jittered position relative to the
+ * subpixel center.
+ */
+#define POS(a, b) (0.5+a*4+b)/16
+ static const GLfloat samples[16][2] = {
+ /* start with the four corners */
+ { POS(0, 2), POS(0, 0) },
+ { POS(3, 3), POS(0, 2) },
+ { POS(0, 0), POS(3, 1) },
+ { POS(3, 1), POS(3, 3) },
+ /* continue with interior samples */
+ { POS(1, 1), POS(0, 1) },
+ { POS(2, 0), POS(0, 3) },
+ { POS(0, 3), POS(1, 3) },
+ { POS(1, 2), POS(1, 0) },
+ { POS(2, 3), POS(1, 2) },
+ { POS(3, 2), POS(1, 1) },
+ { POS(0, 1), POS(2, 2) },
+ { POS(1, 0), POS(2, 1) },
+ { POS(2, 1), POS(2, 3) },
+ { POS(3, 0), POS(2, 0) },
+ { POS(1, 3), POS(3, 0) },
+ { POS(2, 2), POS(3, 2) }
+ };
+
+ const GLfloat x = (GLfloat) winx;
+ const GLfloat y = (GLfloat) winy;
+ const GLfloat dx0 = v1[0] - v0[0];
+ const GLfloat dy0 = v1[1] - v0[1];
+ const GLfloat dx1 = v2[0] - v1[0];
+ const GLfloat dy1 = v2[1] - v1[1];
+ const GLfloat dx2 = v0[0] - v2[0];
+ const GLfloat dy2 = v0[1] - v2[1];
+ GLint stop = 4, i;
+ GLfloat insideCount = 16.0F;
+
+#ifdef DEBUG
+ {
+ const GLfloat area = dx0 * dy1 - dx1 * dy0;
+ ASSERT(area >= 0.0);
+ }
+#endif
+
+ for (i = 0; i < stop; i++) {
+ const GLfloat sx = x + samples[i][0];
+ const GLfloat sy = y + samples[i][1];
+ /* cross product determines if sample is inside or outside each edge */
+ GLfloat cross = (dx0 * (sy - v0[1]) - dy0 * (sx - v0[0]));
+ /* Check if the sample is exactly on an edge. If so, let cross be a
+ * positive or negative value depending on the direction of the edge.
+ */
+ if (cross == 0.0F)
+ cross = dx0 + dy0;
+ if (cross < 0.0F) {
+ /* sample point is outside first edge */
+ insideCount -= 1.0F;
+ stop = 16;
+ }
+ else {
+ /* sample point is inside first edge */
+ cross = (dx1 * (sy - v1[1]) - dy1 * (sx - v1[0]));
+ if (cross == 0.0F)
+ cross = dx1 + dy1;
+ if (cross < 0.0F) {
+ /* sample point is outside second edge */
+ insideCount -= 1.0F;
+ stop = 16;
+ }
+ else {
+ /* sample point is inside first and second edges */
+ cross = (dx2 * (sy - v2[1]) - dy2 * (sx - v2[0]));
+ if (cross == 0.0F)
+ cross = dx2 + dy2;
+ if (cross < 0.0F) {
+ /* sample point is outside third edge */
+ insideCount -= 1.0F;
+ stop = 16;
+ }
+ }
+ }
+ }
+ if (stop == 4)
+ return 1.0F;
+ else
+ return insideCount * (1.0F / 16.0F);
+}
+
+
+
+/*
+ * Compute how much (area) of the given pixel is inside the triangle.
+ * Vertices MUST be specified in counter-clockwise order.
+ * Return: coverage in [0, 15].
+ */
+static GLint
+compute_coveragei(const GLfloat v0[3], const GLfloat v1[3],
+ const GLfloat v2[3], GLint winx, GLint winy)
+{
+ /* NOTE: 15 samples instead of 16. */
+ static const GLfloat samples[15][2] = {
+ /* start with the four corners */
+ { POS(0, 2), POS(0, 0) },
+ { POS(3, 3), POS(0, 2) },
+ { POS(0, 0), POS(3, 1) },
+ { POS(3, 1), POS(3, 3) },
+ /* continue with interior samples */
+ { POS(1, 1), POS(0, 1) },
+ { POS(2, 0), POS(0, 3) },
+ { POS(0, 3), POS(1, 3) },
+ { POS(1, 2), POS(1, 0) },
+ { POS(2, 3), POS(1, 2) },
+ { POS(3, 2), POS(1, 1) },
+ { POS(0, 1), POS(2, 2) },
+ { POS(1, 0), POS(2, 1) },
+ { POS(2, 1), POS(2, 3) },
+ { POS(3, 0), POS(2, 0) },
+ { POS(1, 3), POS(3, 0) }
+ };
+ const GLfloat x = (GLfloat) winx;
+ const GLfloat y = (GLfloat) winy;
+ const GLfloat dx0 = v1[0] - v0[0];
+ const GLfloat dy0 = v1[1] - v0[1];
+ const GLfloat dx1 = v2[0] - v1[0];
+ const GLfloat dy1 = v2[1] - v1[1];
+ const GLfloat dx2 = v0[0] - v2[0];
+ const GLfloat dy2 = v0[1] - v2[1];
+ GLint stop = 4, i;
+ GLint insideCount = 15;
+
+#ifdef DEBUG
+ {
+ const GLfloat area = dx0 * dy1 - dx1 * dy0;
+ ASSERT(area >= 0.0);
+ }
+#endif
+
+ for (i = 0; i < stop; i++) {
+ const GLfloat sx = x + samples[i][0];
+ const GLfloat sy = y + samples[i][1];
+ const GLfloat fx0 = sx - v0[0];
+ const GLfloat fy0 = sy - v0[1];
+ const GLfloat fx1 = sx - v1[0];
+ const GLfloat fy1 = sy - v1[1];
+ const GLfloat fx2 = sx - v2[0];
+ const GLfloat fy2 = sy - v2[1];
+ /* cross product determines if sample is inside or outside each edge */
+ GLfloat cross0 = (dx0 * fy0 - dy0 * fx0);
+ GLfloat cross1 = (dx1 * fy1 - dy1 * fx1);
+ GLfloat cross2 = (dx2 * fy2 - dy2 * fx2);
+ /* Check if the sample is exactly on an edge. If so, let cross be a
+ * positive or negative value depending on the direction of the edge.
+ */
+ if (cross0 == 0.0F)
+ cross0 = dx0 + dy0;
+ if (cross1 == 0.0F)
+ cross1 = dx1 + dy1;
+ if (cross2 == 0.0F)
+ cross2 = dx2 + dy2;
+ if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F) {
+ /* point is outside triangle */
+ insideCount--;
+ stop = 15;
+ }
+ }
+ if (stop == 4)
+ return 15;
+ else
+ return insideCount;
+}
+
+
+static void
+rgba_aa_tri(GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+#define DO_Z
+#define DO_RGBA
+#include "s_aatritemp.h"
+}
+
+
+static void
+index_aa_tri(GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+#define DO_Z
+#define DO_ATTRIBS
+#define DO_INDEX
+#include "s_aatritemp.h"
+}
+
+
+static void
+general_aa_tri(GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+#define DO_Z
+#define DO_RGBA
+#define DO_ATTRIBS
+#include "s_aatritemp.h"
+}
+
+
+
+/*
+ * Examine GL state and set swrast->Triangle to an
+ * appropriate antialiased triangle rasterizer function.
+ */
+void
+_swrast_set_aa_triangle_function(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ ASSERT(ctx->Polygon.SmoothFlag);
+
+ if (ctx->Texture._EnabledCoordUnits != 0
+ || ctx->FragmentProgram._Current
+ || swrast->_FogEnabled
+ || NEED_SECONDARY_COLOR(ctx)) {
+ SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri;
+ }
+ else if (ctx->Visual.rgbMode) {
+ SWRAST_CONTEXT(ctx)->Triangle = rgba_aa_tri;
+ }
+ else {
+ SWRAST_CONTEXT(ctx)->Triangle = index_aa_tri;
+ }
+
+ ASSERT(SWRAST_CONTEXT(ctx)->Triangle);
+}
diff --git a/mesalib/src/mesa/swrast/s_aatriangle.h b/mesalib/src/mesa/swrast/s_aatriangle.h
new file mode 100644
index 000000000..4b57fa73a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aatriangle.h
@@ -0,0 +1,38 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_AATRIANGLE_H
+#define S_AATRIANGLE_H
+
+
+#include "swrast.h"
+
+
+extern void
+_swrast_set_aa_triangle_function(GLcontext *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_aatritemp.h b/mesalib/src/mesa/swrast/s_aatritemp.h
new file mode 100644
index 000000000..0827b3db9
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_aatritemp.h
@@ -0,0 +1,383 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * Antialiased Triangle Rasterizer Template
+ *
+ * This file is #include'd to generate custom AA triangle rasterizers.
+ * NOTE: this code hasn't been optimized yet. That'll come after it
+ * works correctly.
+ *
+ * The following macros may be defined to indicate what auxillary information
+ * must be copmuted across the triangle:
+ * DO_Z - if defined, compute Z values
+ * DO_RGBA - if defined, compute RGBA values
+ * DO_INDEX - if defined, compute color index values
+ * DO_ATTRIBS - if defined, compute texcoords, varying, etc.
+ */
+
+/*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLfloat *p0 = v0->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *p1 = v1->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *p2 = v2->attrib[FRAG_ATTRIB_WPOS];
+ const SWvertex *vMin, *vMid, *vMax;
+ GLint iyMin, iyMax;
+ GLfloat yMin, yMax;
+ GLboolean ltor;
+ GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */
+
+ SWspan span;
+
+#ifdef DO_Z
+ GLfloat zPlane[4];
+#endif
+#ifdef DO_RGBA
+ GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
+#endif
+#ifdef DO_INDEX
+ GLfloat iPlane[4];
+#endif
+#if defined(DO_ATTRIBS)
+ GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4];
+ GLfloat wPlane[4]; /* win[3] */
+#endif
+ GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceCullSign;
+
+ (void) swrast;
+
+ INIT_SPAN(span, GL_POLYGON);
+ span.arrayMask = SPAN_COVERAGE;
+
+ /* determine bottom to top order of vertices */
+ {
+ GLfloat y0 = v0->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat y1 = v1->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat y2 = v2->attrib[FRAG_ATTRIB_WPOS][1];
+ if (y0 <= y1) {
+ if (y1 <= y2) {
+ vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
+ }
+ else if (y2 <= y0) {
+ vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
+ }
+ else {
+ vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */
+ }
+ }
+ else {
+ if (y0 <= y2) {
+ vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */
+ }
+ else if (y2 <= y1) {
+ vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */
+ }
+ else {
+ vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
+ }
+ }
+ }
+
+ majDx = vMax->attrib[FRAG_ATTRIB_WPOS][0] - vMin->attrib[FRAG_ATTRIB_WPOS][0];
+ majDy = vMax->attrib[FRAG_ATTRIB_WPOS][1] - vMin->attrib[FRAG_ATTRIB_WPOS][1];
+
+ /* front/back-face determination and cullling */
+ {
+ const GLfloat botDx = vMid->attrib[FRAG_ATTRIB_WPOS][0] - vMin->attrib[FRAG_ATTRIB_WPOS][0];
+ const GLfloat botDy = vMid->attrib[FRAG_ATTRIB_WPOS][1] - vMin->attrib[FRAG_ATTRIB_WPOS][1];
+ const GLfloat area = majDx * botDy - botDx * majDy;
+ /* Do backface culling */
+ if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
+ return;
+ ltor = (GLboolean) (area < 0.0F);
+
+ span.facing = area * swrast->_BackfaceSign > 0.0F;
+ }
+
+ /* Plane equation setup:
+ * We evaluate plane equations at window (x,y) coordinates in order
+ * to compute color, Z, fog, texcoords, etc. This isn't terribly
+ * efficient but it's easy and reliable.
+ */
+#ifdef DO_Z
+ compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
+ span.arrayMask |= SPAN_Z;
+#endif
+#ifdef DO_RGBA
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
+ compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
+ compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
+ compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
+ }
+ else {
+ constant_plane(v2->color[RCOMP], rPlane);
+ constant_plane(v2->color[GCOMP], gPlane);
+ constant_plane(v2->color[BCOMP], bPlane);
+ constant_plane(v2->color[ACOMP], aPlane);
+ }
+ span.arrayMask |= SPAN_RGBA;
+#endif
+#ifdef DO_INDEX
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ compute_plane(p0, p1, p2, (GLfloat) v0->attrib[FRAG_ATTRIB_CI][0],
+ v1->attrib[FRAG_ATTRIB_CI][0], v2->attrib[FRAG_ATTRIB_CI][0], iPlane);
+ }
+ else {
+ constant_plane(v2->attrib[FRAG_ATTRIB_CI][0], iPlane);
+ }
+ span.arrayMask |= SPAN_INDEX;
+#endif
+#if defined(DO_ATTRIBS)
+ {
+ const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat invW2 = v2->attrib[FRAG_ATTRIB_WPOS][3];
+ compute_plane(p0, p1, p2, invW0, invW1, invW2, wPlane);
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = plane_dx(wPlane);
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = plane_dy(wPlane);
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ if (swrast->_InterpMode[attr] == GL_FLAT) {
+ for (c = 0; c < 4; c++) {
+ constant_plane(v2->attrib[attr][c] * invW2, attrPlane[attr][c]);
+ }
+ }
+ else {
+ for (c = 0; c < 4; c++) {
+ const GLfloat a0 = v0->attrib[attr][c] * invW0;
+ const GLfloat a1 = v1->attrib[attr][c] * invW1;
+ const GLfloat a2 = v2->attrib[attr][c] * invW2;
+ compute_plane(p0, p1, p2, a0, a1, a2, attrPlane[attr][c]);
+ }
+ }
+ for (c = 0; c < 4; c++) {
+ span.attrStepX[attr][c] = plane_dx(attrPlane[attr][c]);
+ span.attrStepY[attr][c] = plane_dy(attrPlane[attr][c]);
+ }
+ ATTRIB_LOOP_END
+ }
+#endif
+
+ /* Begin bottom-to-top scan over the triangle.
+ * The long edge will either be on the left or right side of the
+ * triangle. We always scan from the long edge toward the shorter
+ * edges, stopping when we find that coverage = 0. If the long edge
+ * is on the left we scan left-to-right. Else, we scan right-to-left.
+ */
+ yMin = vMin->attrib[FRAG_ATTRIB_WPOS][1];
+ yMax = vMax->attrib[FRAG_ATTRIB_WPOS][1];
+ iyMin = (GLint) yMin;
+ iyMax = (GLint) yMax + 1;
+
+ if (ltor) {
+ /* scan left to right */
+ const GLfloat *pMin = vMin->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *pMid = vMid->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *pMax = vMax->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat dxdy = majDx / majDy;
+ const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
+ GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
+ GLint iy;
+ for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
+ GLint ix, startX = (GLint) (x - xAdj);
+ GLuint count;
+ GLfloat coverage = 0.0F;
+
+ /* skip over fragments with zero coverage */
+ while (startX < MAX_WIDTH) {
+ coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
+ if (coverage > 0.0F)
+ break;
+ startX++;
+ }
+
+ /* enter interior of triangle */
+ ix = startX;
+
+#if defined(DO_ATTRIBS)
+ /* compute attributes at left-most fragment */
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = solve_plane(ix + 0.5, iy + 0.5, wPlane);
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ span.attrStart[attr][c] = solve_plane(ix + 0.5, iy + 0.5, attrPlane[attr][c]);
+ }
+ ATTRIB_LOOP_END
+#endif
+
+ count = 0;
+ while (coverage > 0.0F) {
+ /* (cx,cy) = center of fragment */
+ const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
+ SWspanarrays *array = span.array;
+#ifdef DO_INDEX
+ array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy);
+#else
+ array->coverage[count] = coverage;
+#endif
+#ifdef DO_Z
+ array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
+#endif
+#ifdef DO_RGBA
+ array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
+ array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
+ array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
+ array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
+#endif
+#ifdef DO_INDEX
+ array->index[count] = (GLint) solve_plane(cx, cy, iPlane);
+#endif
+ ix++;
+ count++;
+ coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
+ }
+
+ if (ix <= startX)
+ continue;
+
+ span.x = startX;
+ span.y = iy;
+ span.end = (GLuint) ix - (GLuint) startX;
+#if defined(DO_RGBA)
+ _swrast_write_rgba_span(ctx, &span);
+#else
+ _swrast_write_index_span(ctx, &span);
+#endif
+ }
+ }
+ else {
+ /* scan right to left */
+ const GLfloat *pMin = vMin->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *pMid = vMid->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat *pMax = vMax->attrib[FRAG_ATTRIB_WPOS];
+ const GLfloat dxdy = majDx / majDy;
+ const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
+ GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
+ GLint iy;
+ for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
+ GLint ix, left, startX = (GLint) (x + xAdj);
+ GLuint count, n;
+ GLfloat coverage = 0.0F;
+
+ /* make sure we're not past the window edge */
+ if (startX >= ctx->DrawBuffer->_Xmax) {
+ startX = ctx->DrawBuffer->_Xmax - 1;
+ }
+
+ /* skip fragments with zero coverage */
+ while (startX > 0) {
+ coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
+ if (coverage > 0.0F)
+ break;
+ startX--;
+ }
+
+ /* enter interior of triangle */
+ ix = startX;
+ count = 0;
+ while (coverage > 0.0F) {
+ /* (cx,cy) = center of fragment */
+ const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
+ SWspanarrays *array = span.array;
+ ASSERT(ix >= 0);
+#ifdef DO_INDEX
+ array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy);
+#else
+ array->coverage[ix] = coverage;
+#endif
+#ifdef DO_Z
+ array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
+#endif
+#ifdef DO_RGBA
+ array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
+ array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
+ array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
+ array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
+#endif
+#ifdef DO_INDEX
+ array->index[ix] = (GLint) solve_plane(cx, cy, iPlane);
+#endif
+ ix--;
+ count++;
+ coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
+ }
+
+#if defined(DO_ATTRIBS)
+ /* compute attributes at left-most fragment */
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = solve_plane(ix + 1.5, iy + 0.5, wPlane);
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ span.attrStart[attr][c] = solve_plane(ix + 1.5, iy + 0.5, attrPlane[attr][c]);
+ }
+ ATTRIB_LOOP_END
+#endif
+
+ if (startX <= ix)
+ continue;
+
+ n = (GLuint) startX - (GLuint) ix;
+
+ left = ix + 1;
+
+ /* shift all values to the left */
+ /* XXX this is temporary */
+ {
+ SWspanarrays *array = span.array;
+ GLint j;
+ for (j = 0; j < (GLint) n; j++) {
+ array->coverage[j] = array->coverage[j + left];
+#ifdef DO_RGBA
+ COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
+#endif
+#ifdef DO_INDEX
+ array->index[j] = array->index[j + left];
+#endif
+#ifdef DO_Z
+ array->z[j] = array->z[j + left];
+#endif
+ }
+ }
+
+ span.x = left;
+ span.y = iy;
+ span.end = n;
+#if defined(DO_RGBA)
+ _swrast_write_rgba_span(ctx, &span);
+#else
+ _swrast_write_index_span(ctx, &span);
+#endif
+ }
+ }
+}
+
+
+#undef DO_Z
+#undef DO_RGBA
+#undef DO_INDEX
+#undef DO_ATTRIBS
+#undef DO_OCCLUSION_TEST
diff --git a/mesalib/src/mesa/swrast/s_accum.c b/mesalib/src/mesa/swrast/s_accum.c
new file mode 100644
index 000000000..c6c7dbf5c
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_accum.c
@@ -0,0 +1,599 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/fbobject.h"
+
+#include "s_accum.h"
+#include "s_context.h"
+#include "s_masking.h"
+#include "s_span.h"
+
+
+/* XXX this would have to change for accum buffers with more or less
+ * than 16 bits per color channel.
+ */
+#define ACCUM_SCALE16 32767.0
+
+
+/*
+ * Accumulation buffer notes
+ *
+ * Normally, accumulation buffer values are GLshorts with values in
+ * [-32767, 32767] which represent floating point colors in [-1, 1],
+ * as defined 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 (n=1/w).
+ * This lets us avoid _many_ int->float->int conversions.
+ */
+
+
+#if CHAN_BITS == 8
+/* enable the optimization */
+#define USE_OPTIMIZED_ACCUM 1
+#else
+#define USE_OPTIMIZED_ACCUM 0
+#endif
+
+
+/**
+ * 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 )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
+ const GLfloat s = swrast->_IntegerAccumScaler * (32767.0F / CHAN_MAXF);
+
+ assert(rb);
+ assert(rb->_BaseFormat == GL_RGBA);
+ /* add other types in future? */
+ assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
+ assert(swrast->_IntegerAccumMode);
+
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* directly-addressable memory */
+ GLuint y;
+ for (y = 0; y < rb->Height; y++) {
+ GLuint i;
+ GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, 0, y);
+ for (i = 0; i < 4 * rb->Width; i++) {
+ acc[i] = (GLshort) (acc[i] * s);
+ }
+ }
+ }
+ else {
+ /* use get/put row funcs */
+ GLuint y;
+ for (y = 0; y < rb->Height; y++) {
+ GLshort accRow[MAX_WIDTH * 4];
+ GLuint i;
+ rb->GetRow(ctx, rb, rb->Width, 0, y, accRow);
+ for (i = 0; i < 4 * rb->Width; i++) {
+ accRow[i] = (GLshort) (accRow[i] * s);
+ }
+ rb->PutRow(ctx, rb, rb->Width, 0, y, accRow, NULL);
+ }
+ }
+
+ swrast->_IntegerAccumMode = GL_FALSE;
+}
+
+
+
+/**
+ * Clear the accumulation Buffer.
+ */
+void
+_swrast_clear_accum_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint x, y, width, height;
+
+ if (ctx->Visual.accumRedBits == 0) {
+ /* No accumulation buffer! Not an error. */
+ return;
+ }
+
+ if (!rb || !rb->Data)
+ return;
+
+ assert(rb->_BaseFormat == GL_RGBA);
+ /* add other types in future? */
+ assert(rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT);
+
+ /* bounds, with scissor */
+ x = ctx->DrawBuffer->_Xmin;
+ y = ctx->DrawBuffer->_Ymin;
+ width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+
+ if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLfloat accScale = 32767.0;
+ GLshort clearVal[4];
+ GLuint i;
+
+ clearVal[0] = (GLshort) (ctx->Accum.ClearColor[0] * accScale);
+ clearVal[1] = (GLshort) (ctx->Accum.ClearColor[1] * accScale);
+ clearVal[2] = (GLshort) (ctx->Accum.ClearColor[2] * accScale);
+ clearVal[3] = (GLshort) (ctx->Accum.ClearColor[3] * accScale);
+
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
+ }
+ }
+ else {
+ /* someday support other sizes */
+ }
+
+ /* 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) {
+#if USE_OPTIMIZED_ACCUM
+ swrast->_IntegerAccumMode = GL_TRUE;
+#else
+ swrast->_IntegerAccumMode = GL_FALSE;
+#endif
+ swrast->_IntegerAccumScaler = 0.0; /* denotes empty accum buffer */
+ }
+ else {
+ swrast->_IntegerAccumMode = GL_FALSE;
+ }
+}
+
+
+static void
+accum_add(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
+
+ assert(rb);
+
+ /* Leave optimized accum buffer mode */
+ if (swrast->_IntegerAccumMode)
+ rescale_accum(ctx);
+
+ if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLshort incr = (GLshort) (value * ACCUM_SCALE16);
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
+ for (j = 0; j < 4 * width; j++) {
+ acc[j] += incr;
+ }
+ }
+ }
+ else {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLshort accRow[4 * MAX_WIDTH];
+ rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
+ for (j = 0; j < 4 * width; j++) {
+ accRow[j] += incr;
+ }
+ rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
+ }
+ }
+ }
+ else {
+ /* other types someday */
+ }
+}
+
+
+static void
+accum_mult(GLcontext *ctx, GLfloat mult,
+ GLint xpos, GLint ypos, GLint width, GLint height )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
+
+ assert(rb);
+
+ /* Leave optimized accum buffer mode */
+ if (swrast->_IntegerAccumMode)
+ rescale_accum(ctx);
+
+ if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLshort *acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
+ for (j = 0; j < 4 * width; j++) {
+ acc[j] = (GLshort) (acc[j] * mult);
+ }
+ }
+ }
+ else {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLshort accRow[4 * MAX_WIDTH];
+ rb->GetRow(ctx, rb, width, xpos, ypos + i, accRow);
+ for (j = 0; j < 4 * width; j++) {
+ accRow[j] = (GLshort) (accRow[j] * mult);
+ }
+ rb->PutRow(ctx, rb, width, xpos, ypos + i, accRow, NULL);
+ }
+ }
+ }
+ else {
+ /* other types someday */
+ }
+}
+
+
+
+static void
+accum_accum(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
+ const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
+
+ assert(rb);
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no read buffer - OK */
+ return;
+ }
+
+ /* May have to leave optimized accum buffer mode */
+ if (swrast->_IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
+ swrast->_IntegerAccumScaler = value;
+ if (swrast->_IntegerAccumMode && value != swrast->_IntegerAccumScaler)
+ rescale_accum(ctx);
+
+ if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
+ GLshort accumRow[4 * MAX_WIDTH];
+ GLchan rgba[MAX_WIDTH][4];
+ GLint i;
+
+ for (i = 0; i < height; i++) {
+ GLshort *acc;
+ if (directAccess) {
+ acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
+ }
+ else {
+ rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
+ acc = accumRow;
+ }
+
+ /* read colors from color buffer */
+ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
+ xpos, ypos + i, CHAN_TYPE, rgba);
+
+ /* do accumulation */
+ if (swrast->_IntegerAccumMode) {
+ /* simply add integer color values into accum buffer */
+ GLint j;
+ for (j = 0; j < width; j++) {
+ acc[j * 4 + 0] += rgba[j][RCOMP];
+ acc[j * 4 + 1] += rgba[j][GCOMP];
+ acc[j * 4 + 2] += rgba[j][BCOMP];
+ acc[j * 4 + 3] += rgba[j][ACOMP];
+ }
+ }
+ else {
+ /* scaled integer (or float) accum buffer */
+ GLint j;
+ for (j = 0; j < width; j++) {
+ acc[j * 4 + 0] += (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
+ acc[j * 4 + 1] += (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
+ acc[j * 4 + 2] += (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
+ acc[j * 4 + 3] += (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
+ }
+ }
+
+ if (!directAccess) {
+ rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
+ }
+ }
+ }
+ else {
+ /* other types someday */
+ }
+}
+
+
+
+static void
+accum_load(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_renderbuffer *rb
+ = ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer;
+ const GLboolean directAccess = (rb->GetPointer(ctx, rb, 0, 0) != NULL);
+
+ assert(rb);
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no read buffer - OK */
+ return;
+ }
+
+ /* This is a change to go into optimized accum buffer mode */
+ if (value > 0.0 && value <= 1.0) {
+#if USE_OPTIMIZED_ACCUM
+ swrast->_IntegerAccumMode = GL_TRUE;
+#else
+ swrast->_IntegerAccumMode = GL_FALSE;
+#endif
+ swrast->_IntegerAccumScaler = value;
+ }
+ else {
+ swrast->_IntegerAccumMode = GL_FALSE;
+ swrast->_IntegerAccumScaler = 0.0;
+ }
+
+ if (rb->DataType == GL_SHORT || rb->DataType == GL_UNSIGNED_SHORT) {
+ const GLfloat scale = value * ACCUM_SCALE16 / CHAN_MAXF;
+ GLshort accumRow[4 * MAX_WIDTH];
+ GLchan rgba[MAX_WIDTH][4];
+ GLint i;
+
+ for (i = 0; i < height; i++) {
+ GLshort *acc;
+ if (directAccess) {
+ acc = (GLshort *) rb->GetPointer(ctx, rb, xpos, ypos + i);
+ }
+ else {
+ rb->GetRow(ctx, rb, width, xpos, ypos + i, accumRow);
+ acc = accumRow;
+ }
+
+ /* read colors from color buffer */
+ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
+ xpos, ypos + i, CHAN_TYPE, rgba);
+
+ /* do load */
+ if (swrast->_IntegerAccumMode) {
+ /* just copy values in */
+ GLint j;
+ assert(swrast->_IntegerAccumScaler > 0.0);
+ assert(swrast->_IntegerAccumScaler <= 1.0);
+ for (j = 0; j < width; j++) {
+ acc[j * 4 + 0] = rgba[j][RCOMP];
+ acc[j * 4 + 1] = rgba[j][GCOMP];
+ acc[j * 4 + 2] = rgba[j][BCOMP];
+ acc[j * 4 + 3] = rgba[j][ACOMP];
+ }
+ }
+ else {
+ /* scaled integer (or float) accum buffer */
+ GLint j;
+ for (j = 0; j < width; j++) {
+ acc[j * 4 + 0] = (GLshort) ((GLfloat) rgba[j][RCOMP] * scale);
+ acc[j * 4 + 1] = (GLshort) ((GLfloat) rgba[j][GCOMP] * scale);
+ acc[j * 4 + 2] = (GLshort) ((GLfloat) rgba[j][BCOMP] * scale);
+ acc[j * 4 + 3] = (GLshort) ((GLfloat) rgba[j][ACOMP] * scale);
+ }
+ }
+
+ if (!directAccess) {
+ rb->PutRow(ctx, rb, width, xpos, ypos + i, accumRow, NULL);
+ }
+ }
+ }
+}
+
+
+static void
+accum_return(GLcontext *ctx, GLfloat value,
+ GLint xpos, GLint ypos, GLint width, GLint height )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *accumRb = fb->Attachment[BUFFER_ACCUM].Renderbuffer;
+ const GLboolean directAccess
+ = (accumRb->GetPointer(ctx, accumRb, 0, 0) != NULL);
+ const GLboolean masking = (!ctx->Color.ColorMask[RCOMP] ||
+ !ctx->Color.ColorMask[GCOMP] ||
+ !ctx->Color.ColorMask[BCOMP] ||
+ !ctx->Color.ColorMask[ACOMP]);
+
+ static GLchan multTable[32768];
+ static GLfloat prevMult = 0.0;
+ const GLfloat mult = swrast->_IntegerAccumScaler;
+ const GLint max = MIN2((GLint) (256 / mult), 32767);
+
+ /* May have to leave optimized accum buffer mode */
+ if (swrast->_IntegerAccumMode && value != 1.0)
+ rescale_accum(ctx);
+
+ if (swrast->_IntegerAccumMode && swrast->_IntegerAccumScaler > 0) {
+ /* build lookup table to avoid many floating point multiplies */
+ GLint j;
+ assert(swrast->_IntegerAccumScaler <= 1.0);
+ if (mult != prevMult) {
+ for (j = 0; j < max; j++)
+ multTable[j] = IROUND((GLfloat) j * mult);
+ prevMult = mult;
+ }
+ }
+
+ if (accumRb->DataType == GL_SHORT ||
+ accumRb->DataType == GL_UNSIGNED_SHORT) {
+ const GLfloat scale = value * CHAN_MAXF / ACCUM_SCALE16;
+ GLuint buffer;
+ GLint i;
+
+ /* XXX maybe transpose the 'i' and 'buffer' loops??? */
+ for (i = 0; i < height; i++) {
+ GLshort accumRow[4 * MAX_WIDTH];
+ GLshort *acc;
+ SWspan span;
+
+ /* init color span */
+ INIT_SPAN(span, GL_BITMAP);
+ span.end = width;
+ span.arrayMask = SPAN_RGBA;
+ span.x = xpos;
+ span.y = ypos + i;
+
+ if (directAccess) {
+ acc = (GLshort *) accumRb->GetPointer(ctx, accumRb, xpos, ypos +i);
+ }
+ else {
+ accumRb->GetRow(ctx, accumRb, width, xpos, ypos + i, accumRow);
+ acc = accumRow;
+ }
+
+ /* get the colors to return */
+ if (swrast->_IntegerAccumMode) {
+ GLint j;
+ for (j = 0; j < width; j++) {
+ ASSERT(acc[j * 4 + 0] < max);
+ ASSERT(acc[j * 4 + 1] < max);
+ ASSERT(acc[j * 4 + 2] < max);
+ ASSERT(acc[j * 4 + 3] < max);
+ span.array->rgba[j][RCOMP] = multTable[acc[j * 4 + 0]];
+ span.array->rgba[j][GCOMP] = multTable[acc[j * 4 + 1]];
+ span.array->rgba[j][BCOMP] = multTable[acc[j * 4 + 2]];
+ span.array->rgba[j][ACOMP] = multTable[acc[j * 4 + 3]];
+ }
+ }
+ else {
+ /* scaled integer (or float) accum buffer */
+ GLint j;
+ for (j = 0; j < width; j++) {
+#if CHAN_BITS==32
+ GLchan r = acc[j * 4 + 0] * scale;
+ GLchan g = acc[j * 4 + 1] * scale;
+ GLchan b = acc[j * 4 + 2] * scale;
+ GLchan a = acc[j * 4 + 3] * scale;
+#else
+ GLint r = IROUND( (GLfloat) (acc[j * 4 + 0]) * scale );
+ GLint g = IROUND( (GLfloat) (acc[j * 4 + 1]) * scale );
+ GLint b = IROUND( (GLfloat) (acc[j * 4 + 2]) * scale );
+ GLint a = IROUND( (GLfloat) (acc[j * 4 + 3]) * scale );
+#endif
+ span.array->rgba[j][RCOMP] = CLAMP( r, 0, CHAN_MAX );
+ span.array->rgba[j][GCOMP] = CLAMP( g, 0, CHAN_MAX );
+ span.array->rgba[j][BCOMP] = CLAMP( b, 0, CHAN_MAX );
+ span.array->rgba[j][ACOMP] = CLAMP( a, 0, CHAN_MAX );
+ }
+ }
+
+ /* store colors */
+ for (buffer = 0; buffer < fb->_NumColorDrawBuffers; buffer++) {
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buffer];
+ if (masking) {
+ _swrast_mask_rgba_span(ctx, rb, &span);
+ }
+ rb->PutRow(ctx, rb, width, xpos, ypos + i, span.array->rgba, NULL);
+ }
+ }
+ }
+ else {
+ /* other types someday */
+ }
+}
+
+
+
+/**
+ * Software fallback for glAccum.
+ */
+void
+_swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLint xpos, ypos, width, height;
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ if (!ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer) {
+ _mesa_warning(ctx, "Calling glAccum() without an accumulation buffer");
+ return;
+ }
+
+ swrast_render_start(ctx);
+
+ /* Compute region after calling swrast_render_start() so that we know the
+ * drawbuffer's size/bounds are up to date.
+ */
+ xpos = ctx->DrawBuffer->_Xmin;
+ ypos = ctx->DrawBuffer->_Ymin;
+ width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+
+ switch (op) {
+ case GL_ADD:
+ if (value != 0.0F) {
+ accum_add(ctx, value, xpos, ypos, width, height);
+ }
+ break;
+ case GL_MULT:
+ if (value != 1.0F) {
+ accum_mult(ctx, value, xpos, ypos, width, height);
+ }
+ break;
+ case GL_ACCUM:
+ if (value != 0.0F) {
+ accum_accum(ctx, value, xpos, ypos, width, height);
+ }
+ break;
+ case GL_LOAD:
+ accum_load(ctx, value, xpos, ypos, width, height);
+ break;
+ case GL_RETURN:
+ accum_return(ctx, value, xpos, ypos, width, height);
+ break;
+ default:
+ _mesa_problem(ctx, "invalid mode in _swrast_Accum()");
+ break;
+ }
+
+ swrast_render_finish(ctx);
+}
diff --git a/mesalib/src/mesa/swrast/s_accum.h b/mesalib/src/mesa/swrast/s_accum.h
new file mode 100644
index 000000000..42e38cf02
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_accum.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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 S_ACCUM_H
+#define S_ACCUM_H
+
+
+#include "main/mtypes.h"
+
+
+extern void
+_swrast_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_alpha.c b/mesalib/src/mesa/swrast/s_alpha.c
new file mode 100644
index 000000000..5761bb00b
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_alpha.c
@@ -0,0 +1,160 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file swrast/s_alpha.c
+ * \brief Functions to apply alpha test.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+
+#include "s_alpha.h"
+#include "s_context.h"
+
+
+#define ALPHA_TEST(ALPHA, LOOP_CODE) \
+do { \
+ switch (ctx->Color.AlphaFunc) { \
+ case GL_LESS: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA < ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_LEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA <= ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_GEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA >= ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_GREATER: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA > ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_NOTEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA != ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_EQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA == ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ default: \
+ _mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
+ return 0; \
+ } \
+} while (0)
+
+
+
+/**
+ * Perform the alpha test for an array of pixels.
+ * For pixels that fail the test, mask[i] will be set to 0.
+ * \return 0 if all pixels in the span failed the alpha test,
+ * 1 if one or more pixels passed the alpha test.
+ */
+GLint
+_swrast_alpha_test(const GLcontext *ctx, SWspan *span)
+{
+ const GLuint n = span->end;
+ GLubyte *mask = span->array->mask;
+ GLuint i;
+
+ if (ctx->Color.AlphaFunc == GL_ALWAYS) {
+ /* do nothing */
+ return 1;
+ }
+ else if (ctx->Color.AlphaFunc == GL_NEVER) {
+ /* All pixels failed - caller should check for this return value and
+ * act accordingly.
+ */
+ span->writeAll = GL_FALSE;
+ return 0;
+ }
+
+ if (span->arrayMask & SPAN_RGBA) {
+ /* Use array's alpha values */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ GLubyte ref;
+ CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(rgba[i][ACOMP], ;);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ GLushort ref;
+ CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(rgba[i][ACOMP], ;);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ const GLfloat ref = ctx->Color.AlphaRef;
+ ALPHA_TEST(rgba[i][ACOMP], ;);
+ }
+ }
+ else {
+ /* Interpolate alpha values */
+ ASSERT(span->interpMask & SPAN_RGBA);
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLfixed alphaStep = span->alphaStep;
+ GLfixed alpha = span->alpha;
+ GLubyte ref;
+ CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLfixed alphaStep = span->alphaStep;
+ GLfixed alpha = span->alpha;
+ GLushort ref;
+ CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
+ }
+ else {
+ const GLfloat alphaStep = span->alphaStep;
+ GLfloat alpha = span->alpha;
+ const GLfloat ref = ctx->Color.AlphaRef;
+ ALPHA_TEST(alpha, alpha += alphaStep);
+ }
+ }
+
+ span->writeAll = GL_FALSE;
+
+ /* XXX examine mask[] values? */
+ return 1;
+}
diff --git a/mesalib/src/mesa/swrast/s_alpha.h b/mesalib/src/mesa/swrast/s_alpha.h
new file mode 100644
index 000000000..7a5b72e65
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_alpha.h
@@ -0,0 +1,38 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_ALPHA_H
+#define S_ALPHA_H
+
+
+#include "s_context.h"
+
+
+extern GLint
+_swrast_alpha_test( const GLcontext *ctx, SWspan *span );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_atifragshader.c b/mesalib/src/mesa/swrast/s_atifragshader.c
new file mode 100644
index 000000000..5fefae6c4
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_atifragshader.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2004 David Airlie 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
+ * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/atifragshader.h"
+#include "swrast/s_atifragshader.h"
+
+
+/**
+ * State for executing ATI fragment shader.
+ */
+struct atifs_machine
+{
+ GLfloat Registers[6][4]; /** six temporary registers */
+ GLfloat PrevPassRegisters[6][4];
+ GLfloat Inputs[2][4]; /** Primary, secondary input colors */
+};
+
+
+
+/**
+ * Fetch a texel.
+ */
+static void
+fetch_texel(GLcontext * ctx, const GLfloat texcoord[4], GLfloat lambda,
+ GLuint unit, GLfloat color[4])
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ /* XXX use a float-valued TextureSample routine here!!! */
+ swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
+ 1, (const GLfloat(*)[4]) texcoord,
+ &lambda, (GLfloat (*)[4]) color);
+}
+
+static void
+apply_swizzle(GLfloat values[4], GLuint swizzle)
+{
+ GLfloat s, t, r, q;
+
+ s = values[0];
+ t = values[1];
+ r = values[2];
+ q = values[3];
+
+ switch (swizzle) {
+ case GL_SWIZZLE_STR_ATI:
+ values[0] = s;
+ values[1] = t;
+ values[2] = r;
+ break;
+ case GL_SWIZZLE_STQ_ATI:
+ values[0] = s;
+ values[1] = t;
+ values[2] = q;
+ break;
+ case GL_SWIZZLE_STR_DR_ATI:
+ values[0] = s / r;
+ values[1] = t / r;
+ values[2] = 1 / r;
+ break;
+ case GL_SWIZZLE_STQ_DQ_ATI:
+/* make sure q is not 0 to avoid problems later with infinite values (texture lookup)? */
+ if (q == 0.0F) q = 0.000000001;
+ values[0] = s / q;
+ values[1] = t / q;
+ values[2] = 1 / q;
+ break;
+ }
+ values[3] = 0.0;
+}
+
+static void
+apply_src_rep(GLint optype, GLuint rep, GLfloat * val)
+{
+ GLint i;
+ GLint start, end;
+ if (!rep)
+ return;
+
+ start = optype ? 3 : 0;
+ end = 4;
+
+ for (i = start; i < end; i++) {
+ switch (rep) {
+ case GL_RED:
+ val[i] = val[0];
+ break;
+ case GL_GREEN:
+ val[i] = val[1];
+ break;
+ case GL_BLUE:
+ val[i] = val[2];
+ break;
+ case GL_ALPHA:
+ val[i] = val[3];
+ break;
+ }
+ }
+}
+
+static void
+apply_src_mod(GLint optype, GLuint mod, GLfloat * val)
+{
+ GLint i;
+ GLint start, end;
+
+ if (!mod)
+ return;
+
+ start = optype ? 3 : 0;
+ end = 4;
+
+ for (i = start; i < end; i++) {
+ if (mod & GL_COMP_BIT_ATI)
+ val[i] = 1 - val[i];
+
+ if (mod & GL_BIAS_BIT_ATI)
+ val[i] = val[i] - 0.5;
+
+ if (mod & GL_2X_BIT_ATI)
+ val[i] = 2 * val[i];
+
+ if (mod & GL_NEGATE_BIT_ATI)
+ val[i] = -val[i];
+ }
+}
+
+static void
+apply_dst_mod(GLuint optype, GLuint mod, GLfloat * val)
+{
+ GLint i;
+ GLint has_sat = mod & GL_SATURATE_BIT_ATI;
+ GLint start, end;
+
+ mod &= ~GL_SATURATE_BIT_ATI;
+
+ start = optype ? 3 : 0;
+ end = optype ? 4 : 3;
+
+ for (i = start; i < end; i++) {
+ switch (mod) {
+ case GL_2X_BIT_ATI:
+ val[i] = 2 * val[i];
+ break;
+ case GL_4X_BIT_ATI:
+ val[i] = 4 * val[i];
+ break;
+ case GL_8X_BIT_ATI:
+ val[i] = 8 * val[i];
+ break;
+ case GL_HALF_BIT_ATI:
+ val[i] = val[i] * 0.5;
+ break;
+ case GL_QUARTER_BIT_ATI:
+ val[i] = val[i] * 0.25;
+ break;
+ case GL_EIGHTH_BIT_ATI:
+ val[i] = val[i] * 0.125;
+ break;
+ }
+
+ if (has_sat) {
+ if (val[i] < 0.0)
+ val[i] = 0;
+ else if (val[i] > 1.0)
+ val[i] = 1.0;
+ }
+ else {
+ if (val[i] < -8.0)
+ val[i] = -8.0;
+ else if (val[i] > 8.0)
+ val[i] = 8.0;
+ }
+ }
+}
+
+
+static void
+write_dst_addr(GLuint optype, GLuint mod, GLuint mask, GLfloat * src,
+ GLfloat * dst)
+{
+ GLint i;
+ apply_dst_mod(optype, mod, src);
+
+ if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) {
+ if (mask) {
+ if (mask & GL_RED_BIT_ATI)
+ dst[0] = src[0];
+
+ if (mask & GL_GREEN_BIT_ATI)
+ dst[1] = src[1];
+
+ if (mask & GL_BLUE_BIT_ATI)
+ dst[2] = src[2];
+ }
+ else {
+ for (i = 0; i < 3; i++)
+ dst[i] = src[i];
+ }
+ }
+ else
+ dst[3] = src[3];
+}
+
+static void
+finish_pass(struct atifs_machine *machine)
+{
+ GLint i;
+
+ for (i = 0; i < 6; i++) {
+ COPY_4V(machine->PrevPassRegisters[i], machine->Registers[i]);
+ }
+}
+
+struct ati_fs_opcode_st ati_fs_opcodes[] = {
+ {GL_ADD_ATI, 2},
+ {GL_SUB_ATI, 2},
+ {GL_MUL_ATI, 2},
+ {GL_MAD_ATI, 3},
+ {GL_LERP_ATI, 3},
+ {GL_MOV_ATI, 1},
+ {GL_CND_ATI, 3},
+ {GL_CND0_ATI, 3},
+ {GL_DOT2_ADD_ATI, 3},
+ {GL_DOT3_ATI, 2},
+ {GL_DOT4_ATI, 2}
+};
+
+
+
+static void
+handle_pass_op(struct atifs_machine *machine, struct atifs_setupinst *texinst,
+ const SWspan *span, GLuint column, GLuint idx)
+{
+ GLuint swizzle = texinst->swizzle;
+ GLuint pass_tex = texinst->src;
+
+ if (pass_tex >= GL_TEXTURE0_ARB && pass_tex <= GL_TEXTURE7_ARB) {
+ pass_tex -= GL_TEXTURE0_ARB;
+ COPY_4V(machine->Registers[idx],
+ span->array->attribs[FRAG_ATTRIB_TEX0 + pass_tex][column]);
+ }
+ else if (pass_tex >= GL_REG_0_ATI && pass_tex <= GL_REG_5_ATI) {
+ pass_tex -= GL_REG_0_ATI;
+ COPY_4V(machine->Registers[idx], machine->PrevPassRegisters[pass_tex]);
+ }
+ apply_swizzle(machine->Registers[idx], swizzle);
+
+}
+
+static void
+handle_sample_op(GLcontext * ctx, struct atifs_machine *machine,
+ struct atifs_setupinst *texinst, const SWspan *span,
+ GLuint column, GLuint idx)
+{
+/* sample from unit idx using texinst->src as coords */
+ GLuint swizzle = texinst->swizzle;
+ GLuint coord_source = texinst->src;
+ GLfloat tex_coords[4];
+
+ if (coord_source >= GL_TEXTURE0_ARB && coord_source <= GL_TEXTURE7_ARB) {
+ coord_source -= GL_TEXTURE0_ARB;
+ COPY_4V(tex_coords,
+ span->array->attribs[FRAG_ATTRIB_TEX0 + coord_source][column]);
+ }
+ else if (coord_source >= GL_REG_0_ATI && coord_source <= GL_REG_5_ATI) {
+ coord_source -= GL_REG_0_ATI;
+ COPY_4V(tex_coords, machine->PrevPassRegisters[coord_source]);
+ }
+ apply_swizzle(tex_coords, swizzle);
+ fetch_texel(ctx, tex_coords, 0.0F, idx, machine->Registers[idx]);
+}
+
+#define SETUP_SRC_REG(optype, i, x) \
+do { \
+ COPY_4V(src[optype][i], x); \
+} while (0)
+
+
+
+/**
+ * Execute the given fragment shader.
+ * NOTE: we do everything in single-precision floating point
+ * \param ctx - rendering context
+ * \param shader - the shader to execute
+ * \param machine - virtual machine state
+ * \param span - the SWspan we're operating on
+ * \param column - which pixel [i] we're operating on in the span
+ */
+static void
+execute_shader(GLcontext *ctx, const struct ati_fragment_shader *shader,
+ struct atifs_machine *machine, const SWspan *span,
+ GLuint column)
+{
+ GLuint pc;
+ struct atifs_instruction *inst;
+ struct atifs_setupinst *texinst;
+ GLint optype;
+ GLuint i;
+ GLint j, pass;
+ GLint dstreg;
+ GLfloat src[2][3][4];
+ GLfloat zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
+ GLfloat ones[4] = { 1.0, 1.0, 1.0, 1.0 };
+ GLfloat dst[2][4], *dstp;
+
+ for (pass = 0; pass < shader->NumPasses; pass++) {
+ if (pass > 0)
+ finish_pass(machine);
+ for (j = 0; j < MAX_NUM_FRAGMENT_REGISTERS_ATI; j++) {
+ texinst = &shader->SetupInst[pass][j];
+ if (texinst->Opcode == ATI_FRAGMENT_SHADER_PASS_OP)
+ handle_pass_op(machine, texinst, span, column, j);
+ else if (texinst->Opcode == ATI_FRAGMENT_SHADER_SAMPLE_OP)
+ handle_sample_op(ctx, machine, texinst, span, column, j);
+ }
+
+ for (pc = 0; pc < shader->numArithInstr[pass]; pc++) {
+ inst = &shader->Instructions[pass][pc];
+
+ /* setup the source registers for color and alpha ops */
+ for (optype = 0; optype < 2; optype++) {
+ for (i = 0; i < inst->ArgCount[optype]; i++) {
+ GLint index = inst->SrcReg[optype][i].Index;
+
+ if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI)
+ SETUP_SRC_REG(optype, i,
+ machine->Registers[index - GL_REG_0_ATI]);
+ else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) {
+ if (shader->LocalConstDef & (1 << (index - GL_CON_0_ATI))) {
+ SETUP_SRC_REG(optype, i,
+ shader->Constants[index - GL_CON_0_ATI]);
+ } else {
+ SETUP_SRC_REG(optype, i,
+ ctx->ATIFragmentShader.GlobalConstants[index - GL_CON_0_ATI]);
+ }
+ }
+ else if (index == GL_ONE)
+ SETUP_SRC_REG(optype, i, ones);
+ else if (index == GL_ZERO)
+ SETUP_SRC_REG(optype, i, zeros);
+ else if (index == GL_PRIMARY_COLOR_EXT)
+ SETUP_SRC_REG(optype, i,
+ machine->Inputs[ATI_FS_INPUT_PRIMARY]);
+ else if (index == GL_SECONDARY_INTERPOLATOR_ATI)
+ SETUP_SRC_REG(optype, i,
+ machine->Inputs[ATI_FS_INPUT_SECONDARY]);
+
+ apply_src_rep(optype, inst->SrcReg[optype][i].argRep,
+ src[optype][i]);
+ apply_src_mod(optype, inst->SrcReg[optype][i].argMod,
+ src[optype][i]);
+ }
+ }
+
+ /* Execute the operations - color then alpha */
+ for (optype = 0; optype < 2; optype++) {
+ if (inst->Opcode[optype]) {
+ switch (inst->Opcode[optype]) {
+ case GL_ADD_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ src[optype][0][i] + src[optype][1][i];
+ }
+ else
+ dst[optype][3] = src[optype][0][3] + src[optype][1][3];
+ break;
+ case GL_SUB_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ src[optype][0][i] - src[optype][1][i];
+ }
+ else
+ dst[optype][3] = src[optype][0][3] - src[optype][1][3];
+ break;
+ case GL_MUL_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ src[optype][0][i] * src[optype][1][i];
+ }
+ else
+ dst[optype][3] = src[optype][0][3] * src[optype][1][3];
+ break;
+ case GL_MAD_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ src[optype][0][i] * src[optype][1][i] +
+ src[optype][2][i];
+ }
+ else
+ dst[optype][3] =
+ src[optype][0][3] * src[optype][1][3] +
+ src[optype][2][3];
+ break;
+ case GL_LERP_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ src[optype][0][i] * src[optype][1][i] + (1 -
+ src
+ [optype]
+ [0][i]) *
+ src[optype][2][i];
+ }
+ else
+ dst[optype][3] =
+ src[optype][0][3] * src[optype][1][3] + (1 -
+ src[optype]
+ [0][3]) *
+ src[optype][2][3];
+ break;
+
+ case GL_MOV_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] = src[optype][0][i];
+ }
+ else
+ dst[optype][3] = src[optype][0][3];
+ break;
+ case GL_CND_ATI:
+ if (!optype) {
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ (src[optype][2][i] >
+ 0.5) ? src[optype][0][i] : src[optype][1][i];
+ }
+ }
+ else {
+ dst[optype][3] =
+ (src[optype][2][3] >
+ 0.5) ? src[optype][0][3] : src[optype][1][3];
+ }
+ break;
+
+ case GL_CND0_ATI:
+ if (!optype)
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] =
+ (src[optype][2][i] >=
+ 0) ? src[optype][0][i] : src[optype][1][i];
+ }
+ else {
+ dst[optype][3] =
+ (src[optype][2][3] >=
+ 0) ? src[optype][0][3] : src[optype][1][3];
+ }
+ break;
+ case GL_DOT2_ADD_ATI:
+ {
+ GLfloat result;
+
+ /* DOT 2 always uses the source from the color op */
+ /* could save recalculation of dot products for alpha inst */
+ result = src[0][0][0] * src[0][1][0] +
+ src[0][0][1] * src[0][1][1] + src[0][2][2];
+ if (!optype) {
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] = result;
+ }
+ }
+ else
+ dst[optype][3] = result;
+ }
+ break;
+ case GL_DOT3_ATI:
+ {
+ GLfloat result;
+
+ /* DOT 3 always uses the source from the color op */
+ result = src[0][0][0] * src[0][1][0] +
+ src[0][0][1] * src[0][1][1] +
+ src[0][0][2] * src[0][1][2];
+
+ if (!optype) {
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] = result;
+ }
+ }
+ else
+ dst[optype][3] = result;
+ }
+ break;
+ case GL_DOT4_ATI:
+ {
+ GLfloat result;
+
+ /* DOT 4 always uses the source from the color op */
+ result = src[0][0][0] * src[0][1][0] +
+ src[0][0][1] * src[0][1][1] +
+ src[0][0][2] * src[0][1][2] +
+ src[0][0][3] * src[0][1][3];
+ if (!optype) {
+ for (i = 0; i < 3; i++) {
+ dst[optype][i] = result;
+ }
+ }
+ else
+ dst[optype][3] = result;
+ }
+ break;
+
+ }
+ }
+ }
+
+ /* write out the destination registers */
+ for (optype = 0; optype < 2; optype++) {
+ if (inst->Opcode[optype]) {
+ dstreg = inst->DstReg[optype].Index;
+ dstp = machine->Registers[dstreg - GL_REG_0_ATI];
+
+ if ((optype == 0) || ((inst->Opcode[1] != GL_DOT2_ADD_ATI) &&
+ (inst->Opcode[1] != GL_DOT3_ATI) && (inst->Opcode[1] != GL_DOT4_ATI)))
+ write_dst_addr(optype, inst->DstReg[optype].dstMod,
+ inst->DstReg[optype].dstMask, dst[optype],
+ dstp);
+ else
+ write_dst_addr(1, inst->DstReg[0].dstMod, 0, dst[1], dstp);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Init fragment shader virtual machine state.
+ */
+static void
+init_machine(GLcontext * ctx, struct atifs_machine *machine,
+ const struct ati_fragment_shader *shader,
+ const SWspan *span, GLuint col)
+{
+ GLfloat (*inputs)[4] = machine->Inputs;
+ GLint i, j;
+
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 4; j++)
+ machine->Registers[i][j] = 0.0;
+ }
+
+ COPY_4V(inputs[ATI_FS_INPUT_PRIMARY], span->array->attribs[FRAG_ATTRIB_COL0][col]);
+ COPY_4V(inputs[ATI_FS_INPUT_SECONDARY], span->array->attribs[FRAG_ATTRIB_COL1][col]);
+}
+
+
+
+/**
+ * Execute the current ATI shader program, operating on the given span.
+ */
+void
+_swrast_exec_fragment_shader(GLcontext * ctx, SWspan *span)
+{
+ const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current;
+ struct atifs_machine machine;
+ GLuint i;
+
+ /* incoming colors should be floats */
+ ASSERT(span->array->ChanType == GL_FLOAT);
+
+ for (i = 0; i < span->end; i++) {
+ if (span->array->mask[i]) {
+ init_machine(ctx, &machine, shader, span, i);
+
+ execute_shader(ctx, shader, &machine, span, i);
+
+ /* store result color */
+ {
+ const GLfloat *colOut = machine.Registers[0];
+ /*fprintf(stderr,"outputs %f %f %f %f\n",
+ colOut[0], colOut[1], colOut[2], colOut[3]); */
+ COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], colOut);
+ }
+ }
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_atifragshader.h b/mesalib/src/mesa/swrast/s_atifragshader.h
new file mode 100644
index 000000000..871a0c045
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_atifragshader.h
@@ -0,0 +1,37 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2003 David Airlie 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
+ * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION 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 S_ATIFRAGSHADER_H
+#define S_ATIFRAGSHADER_H
+
+
+#include "s_context.h"
+
+
+extern void
+_swrast_exec_fragment_shader( GLcontext *ctx, SWspan *span );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_bitmap.c b/mesalib/src/mesa/swrast/s_bitmap.c
new file mode 100644
index 000000000..3dbdf2a61
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_bitmap.c
@@ -0,0 +1,228 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/**
+ * \file swrast/s_bitmap.c
+ * \brief glBitmap rendering.
+ * \author Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/pixel.h"
+
+#include "s_context.h"
+#include "s_span.h"
+
+
+
+/**
+ * Render a bitmap.
+ * Called via ctx->Driver.Bitmap()
+ * All parameter error checking will have been done before this is called.
+ */
+void
+_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ GLint row, col;
+ GLuint count = 0;
+ SWspan span;
+
+ ASSERT(ctx->RenderMode == GL_RENDER);
+
+ bitmap = (const GLubyte *) _mesa_map_pbo_source(ctx, unpack, bitmap);
+ if (!bitmap)
+ return;
+
+ swrast_render_start(ctx);
+
+ if (SWRAST_CONTEXT(ctx)->NewState)
+ _swrast_validate_derived( ctx );
+
+ INIT_SPAN(span, GL_BITMAP);
+ span.end = width;
+ span.arrayMask = SPAN_XY;
+ _swrast_span_default_attribs(ctx, &span);
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
+ bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ span.array->x[count] = px + col;
+ span.array->y[count] = py + row;
+ count++;
+ }
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ span.array->x[count] = px + col;
+ span.array->y[count] = py + row;
+ count++;
+ }
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+
+ if (count + width >= MAX_WIDTH || row + 1 == height) {
+ /* flush the span */
+ span.end = count;
+ if (ctx->Visual.rgbMode)
+ _swrast_write_rgba_span(ctx, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+ span.end = 0;
+ count = 0;
+ }
+ }
+
+ swrast_render_finish(ctx);
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+}
+
+
+#if 0
+/*
+ * XXX this is another way to implement Bitmap. Use horizontal runs of
+ * fragments, initializing the mask array to indicate which fragments to
+ * draw or skip.
+ */
+void
+_swrast_Bitmap( GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLint row, col;
+ SWspan span;
+
+ ASSERT(ctx->RenderMode == GL_RENDER);
+ ASSERT(bitmap);
+
+ swrast_render_start(ctx);
+
+ if (SWRAST_CONTEXT(ctx)->NewState)
+ _swrast_validate_derived( ctx );
+
+ INIT_SPAN(span, GL_BITMAP);
+ span.end = width;
+ span.arrayMask = SPAN_MASK;
+ _swrast_span_default_attribs(ctx, &span);
+
+ /*span.arrayMask |= SPAN_MASK;*/ /* we'll init span.mask[] */
+ span.x = px;
+ span.y = py;
+ /*span.end = width;*/
+
+ for (row=0; row<height; row++, span.y++) {
+ const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
+ bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
+
+ if (unpack->LsbFirst) {
+ /* Lsb first */
+ GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
+ for (col=0; col<width; col++) {
+ span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+
+ if (ctx->Visual.rgbMode)
+ _swrast_write_rgba_span(ctx, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+
+ /* get ready for next row */
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* Msb first */
+ GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+ for (col=0; col<width; col++) {
+ span.array->mask[col] = (*src & mask) ? GL_TRUE : GL_FALSE;
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+
+ if (ctx->Visual.rgbMode)
+ _swrast_write_rgba_span(ctx, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+
+ /* get ready for next row */
+ if (mask != 128)
+ src++;
+ }
+ }
+
+ swrast_render_finish(ctx);
+}
+#endif
diff --git a/mesalib/src/mesa/swrast/s_blend.c b/mesalib/src/mesa/swrast/s_blend.c
new file mode 100644
index 000000000..95c83432a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_blend.c
@@ -0,0 +1,1002 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+
+/**
+ * \file swrast/s_blend.c
+ * \brief software blending.
+ * \author Brian Paul
+ *
+ * Only a few blend modes have been optimized (min, max, transparency, add)
+ * more optimized cases can easily be added if needed.
+ * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
+ */
+
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+
+#include "s_blend.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+#if defined(USE_MMX_ASM)
+#include "x86/mmx.h"
+#include "x86/common_x86_asm.h"
+#define _BLENDAPI _ASMAPI
+#else
+#define _BLENDAPI
+#endif
+
+
+/**
+ * Integer divide by 255
+ * Declare "int divtemp" before using.
+ * This satisfies Glean and should be reasonably fast.
+ * Contributed by Nathan Hand.
+ */
+#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
+
+
+
+/**
+ * Special case for glBlendFunc(GL_ZERO, GL_ONE).
+ * No-op means the framebuffer values remain unchanged.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_noop(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLint bytes;
+
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ZERO);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE);
+ (void) ctx;
+
+ /* just memcpy */
+ if (chanType == GL_UNSIGNED_BYTE)
+ bytes = 4 * n * sizeof(GLubyte);
+ else if (chanType == GL_UNSIGNED_SHORT)
+ bytes = 4 * n * sizeof(GLushort);
+ else
+ bytes = 4 * n * sizeof(GLfloat);
+
+ _mesa_memcpy(src, dst, bytes);
+}
+
+
+/**
+ * Special case for glBlendFunc(GL_ONE, GL_ZERO)
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_replace(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ZERO);
+ (void) ctx;
+ (void) n;
+ (void) mask;
+ (void) src;
+ (void) dst;
+}
+
+
+/**
+ * Common transparency blending mode:
+ * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
+ */
+static void _BLENDAPI
+blend_transparency_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ GLuint i;
+
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendSrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_UNSIGNED_BYTE);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */
+ if (t == 0) {
+ /* 0% alpha */
+ COPY_4UBV(rgba[i], dest[i]);
+ }
+ else if (t != 255) {
+ GLint divtemp;
+ const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
+ const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
+ const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
+ const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
+ ASSERT(r <= 255);
+ ASSERT(g <= 255);
+ ASSERT(b <= 255);
+ ASSERT(a <= 255);
+ rgba[i][RCOMP] = (GLubyte) r;
+ rgba[i][GCOMP] = (GLubyte) g;
+ rgba[i][BCOMP] = (GLubyte) b;
+ rgba[i][ACOMP] = (GLubyte) a;
+ }
+ }
+ }
+}
+
+
+static void _BLENDAPI
+blend_transparency_ushort(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ GLuint i;
+
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendSrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_UNSIGNED_SHORT);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLint t = rgba[i][ACOMP];
+ if (t == 0) {
+ /* 0% alpha */
+ COPY_4V(rgba[i], dest[i]);
+ }
+ else if (t != 65535) {
+ const GLfloat tt = (GLfloat) t / 65535.0F;
+ GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
+ GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
+ GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
+ GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
+ ASSIGN_4V(rgba[i], r, g, b, a);
+ }
+ }
+ }
+}
+
+
+static void _BLENDAPI
+blend_transparency_float(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ GLuint i;
+
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendSrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_FLOAT);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */
+ if (t == 0.0F) {
+ /* 0% alpha */
+ COPY_4V(rgba[i], dest[i]);
+ }
+ else if (t != 1.0F) {
+ GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
+ GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
+ GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
+ GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
+ ASSIGN_4V(rgba[i], r, g, b, a);
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_add(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ 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] = (GLubyte) MIN2( r, 255 );
+ rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
+ rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
+ rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ 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] = (GLshort) MIN2( r, 255 );
+ rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
+ rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
+ rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ /* don't RGB clamp to max */
+ rgba[i][RCOMP] += dest[i][RCOMP];
+ rgba[i][GCOMP] += dest[i][GCOMP];
+ rgba[i][BCOMP] += dest[i][BCOMP];
+ rgba[i][ACOMP] += dest[i][ACOMP];
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Blend min function.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_min(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquationRGB == GL_MIN);
+ ASSERT(ctx->Color.BlendEquationA == GL_MIN);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ 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.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_max(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquationRGB == GL_MAX);
+ ASSERT(ctx->Color.BlendEquationA == GL_MAX);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ 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
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_modulate(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint divtemp;
+ rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
+ rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
+ rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
+ rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
+ rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
+ rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
+ rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
+ rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
+ rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
+ rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
+ }
+ }
+ }
+}
+
+
+/**
+ * Do any blending operation, using floating point.
+ * \param n number of pixels
+ * \param mask fragment writemask array
+ * \param rgba array of incoming (and modified) pixels
+ * \param dest array of pixels from the dest color buffer
+ */
+static void
+blend_general_float(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLfloat rgba[][4], GLfloat dest[][4],
+ GLenum chanType)
+{
+ GLuint i;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ /* Incoming/source Color */
+ const GLfloat Rs = rgba[i][RCOMP];
+ const GLfloat Gs = rgba[i][GCOMP];
+ const GLfloat Bs = rgba[i][BCOMP];
+ const GLfloat As = rgba[i][ACOMP];
+
+ /* Frame buffer/dest color */
+ const GLfloat Rd = dest[i][RCOMP];
+ const GLfloat Gd = dest[i][GCOMP];
+ const GLfloat Bd = dest[i][BCOMP];
+ const GLfloat Ad = dest[i][ACOMP];
+
+ GLfloat sR, sG, sB, sA; /* Source factor */
+ GLfloat dR, dG, dB, dA; /* Dest factor */
+ GLfloat r, g, b, a; /* result color */
+
+ /* XXX for the case of constant blend terms we could init
+ * the sX and dX variables just once before the loop.
+ */
+
+ /* 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 = Rd;
+ sG = Gd;
+ sB = Bd;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sR = 1.0F - Rd;
+ sG = 1.0F - Gd;
+ sB = 1.0F - Bd;
+ break;
+ case GL_SRC_ALPHA:
+ sR = sG = sB = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sR = sG = sB = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ sR = sG = sB = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sR = sG = sB = 1.0F - Ad;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ if (As < 1.0F - Ad) {
+ sR = sG = sB = As;
+ }
+ else {
+ sR = sG = sB = 1.0F - Ad;
+ }
+ 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;
+ case GL_SRC_COLOR:
+ sR = Rs;
+ sG = Gs;
+ sB = Bs;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ sR = 1.0F - Rs;
+ sG = 1.0F - Gs;
+ sB = 1.0F - Bs;
+ break;
+ default:
+ /* this should never happen */
+ _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
+ 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 = Ad;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sA = 1.0F - Ad;
+ break;
+ case GL_SRC_ALPHA:
+ sA = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sA = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ sA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sA = 1.0F - Ad;
+ 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;
+ case GL_SRC_COLOR:
+ sA = As;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ sA = 1.0F - As;
+ break;
+ default:
+ /* this should never happen */
+ sA = 0.0F;
+ _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
+ return;
+ }
+
+ /* 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 = Rs;
+ dG = Gs;
+ dB = Bs;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dR = 1.0F - Rs;
+ dG = 1.0F - Gs;
+ dB = 1.0F - Bs;
+ break;
+ case GL_SRC_ALPHA:
+ dR = dG = dB = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dR = dG = dB = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ dR = dG = dB = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dR = dG = dB = 1.0F - Ad;
+ 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];
+ break;
+ case GL_DST_COLOR:
+ dR = Rd;
+ dG = Gd;
+ dB = Bd;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ dR = 1.0F - Rd;
+ dG = 1.0F - Gd;
+ dB = 1.0F - Bd;
+ break;
+ default:
+ /* this should never happen */
+ dR = dG = dB = 0.0F;
+ _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
+ return;
+ }
+
+ /* 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 = As;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dA = 1.0F - As;
+ break;
+ case GL_SRC_ALPHA:
+ dA = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dA = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ dA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dA = 1.0F - Ad;
+ 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];
+ break;
+ case GL_DST_COLOR:
+ dA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ dA = 1.0F - Ad;
+ break;
+ default:
+ /* this should never happen */
+ dA = 0.0F;
+ _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
+ return;
+ }
+
+ /* compute the blended RGB */
+ switch (ctx->Color.BlendEquationRGB) {
+ case GL_FUNC_ADD:
+ r = Rs * sR + Rd * dR;
+ g = Gs * sG + Gd * dG;
+ b = Bs * sB + Bd * dB;
+ a = As * sA + Ad * dA;
+ break;
+ case GL_FUNC_SUBTRACT:
+ r = Rs * sR - Rd * dR;
+ g = Gs * sG - Gd * dG;
+ b = Bs * sB - Bd * dB;
+ a = As * sA - Ad * dA;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ r = Rd * dR - Rs * sR;
+ g = Gd * dG - Gs * sG;
+ b = Bd * dB - Bs * sB;
+ a = Ad * dA - As * sA;
+ break;
+ case GL_MIN:
+ r = MIN2( Rd, Rs );
+ g = MIN2( Gd, Gs );
+ b = MIN2( Bd, Bs );
+ break;
+ case GL_MAX:
+ r = MAX2( Rd, Rs );
+ g = MAX2( Gd, Gs );
+ b = MAX2( Bd, Bs );
+ break;
+ default:
+ /* should never get here */
+ r = g = b = 0.0F; /* silence uninitialized var warning */
+ _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
+ }
+
+ /* compute the blended alpha */
+ switch (ctx->Color.BlendEquationA) {
+ case GL_FUNC_ADD:
+ a = As * sA + Ad * dA;
+ break;
+ case GL_FUNC_SUBTRACT:
+ a = As * sA - Ad * dA;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ a = Ad * dA - As * sA;
+ break;
+ case GL_MIN:
+ a = MIN2( Ad, As );
+ break;
+ case GL_MAX:
+ a = MAX2( Ad, As );
+ break;
+ default:
+ /* should never get here */
+ a = 0.0F; /* silence uninitialized var warning */
+ _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
+ }
+
+ /* final clamping */
+#if 0
+ rgba[i][RCOMP] = MAX2( r, 0.0F );
+ rgba[i][GCOMP] = MAX2( g, 0.0F );
+ rgba[i][BCOMP] = MAX2( b, 0.0F );
+ rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
+#else
+ ASSIGN_4V(rgba[i], r, g, b, a);
+#endif
+ }
+ }
+}
+
+
+/**
+ * Do any blending operation, any chanType.
+ */
+static void
+blend_general(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ void *src, const void *dst, GLenum chanType)
+{
+ GLfloat rgbaF[MAX_WIDTH][4], destF[MAX_WIDTH][4];
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ GLuint i;
+ /* convert ubytes to floats */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
+ rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
+ rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
+ rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
+ destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
+ destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
+ destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
+ destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
+ }
+ }
+ /* do blend */
+ blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+ /* convert back to ubytes */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ GLuint i;
+ /* convert ushorts to floats */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
+ rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
+ rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
+ rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
+ destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
+ destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
+ destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
+ destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
+ }
+ }
+ /* do blend */
+ blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+ /* convert back to ushorts */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+ }
+ }
+ }
+ else {
+ blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src,
+ (GLfloat (*)[4]) dst, chanType);
+ }
+}
+
+
+
+/**
+ * Analyze current blending parameters to pick fastest blending function.
+ * Result: the ctx->Color.BlendFunc pointer is updated.
+ */
+void
+_swrast_choose_blend_func(GLcontext *ctx, GLenum chanType)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLenum eq = ctx->Color.BlendEquationRGB;
+ 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 (ctx->Color.BlendEquationRGB != ctx->Color.BlendEquationA) {
+ swrast->BlendFunc = blend_general;
+ }
+ else if (eq == GL_MIN) {
+ /* Note: GL_MIN ignores the blending weight factors */
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_min;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_min;
+ }
+ else if (eq == GL_MAX) {
+ /* Note: GL_MAX ignores the blending weight factors */
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_max;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_max;
+ }
+ else if (srcRGB != srcA || dstRGB != dstA) {
+ swrast->BlendFunc = blend_general;
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
+ && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_transparency;
+ }
+ else
+#endif
+ {
+ if (chanType == GL_UNSIGNED_BYTE)
+ swrast->BlendFunc = blend_transparency_ubyte;
+ else if (chanType == GL_UNSIGNED_SHORT)
+ swrast->BlendFunc = blend_transparency_ushort;
+ else
+ swrast->BlendFunc = blend_transparency_float;
+ }
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_add;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_add;
+ }
+ else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
+ && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
+ ||
+ ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
+ && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_modulate;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_modulate;
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
+ swrast->BlendFunc = blend_noop;
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
+ swrast->BlendFunc = blend_replace;
+ }
+ else {
+ swrast->BlendFunc = blend_general;
+ }
+}
+
+
+
+/**
+ * Apply the blending operator to a span of pixels.
+ * We can handle horizontal runs of pixels (spans) or arrays of x/y
+ * pixel coordinates.
+ */
+void
+_swrast_blend_span(GLcontext *ctx, struct gl_renderbuffer *rb, SWspan *span)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ void *rbPixels;
+
+ ASSERT(span->end <= MAX_WIDTH);
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(rb->DataType == span->array->ChanType);
+ ASSERT(!ctx->Color._LogicOpEnabled);
+
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+ swrast->BlendFunc(ctx, span->end, span->array->mask,
+ span->array->rgba, rbPixels, span->array->ChanType);
+}
diff --git a/mesalib/src/mesa/swrast/s_blend.h b/mesalib/src/mesa/swrast/s_blend.h
new file mode 100644
index 000000000..8d5a81635
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_blend.h
@@ -0,0 +1,41 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 S_BLEND_H
+#define S_BLEND_H
+
+
+#include "s_context.h"
+
+
+extern void
+_swrast_blend_span(GLcontext *ctx, struct gl_renderbuffer *rb, SWspan *span);
+
+
+extern void
+_swrast_choose_blend_func(GLcontext *ctx, GLenum chanType);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c
new file mode 100644
index 000000000..8303e4deb
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_blit.c
@@ -0,0 +1,615 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "s_context.h"
+
+
+#define ABS(X) ((X) < 0 ? -(X) : (X))
+
+
+/**
+ * Generate a row resampler function for GL_NEAREST mode.
+ */
+#define RESAMPLE(NAME, PIXELTYPE, SIZE) \
+static void \
+NAME(GLint srcWidth, GLint dstWidth, \
+ const GLvoid *srcBuffer, GLvoid *dstBuffer, \
+ GLboolean flip) \
+{ \
+ const PIXELTYPE *src = (const PIXELTYPE *) srcBuffer;\
+ PIXELTYPE *dst = (PIXELTYPE *) dstBuffer; \
+ GLint dstCol; \
+ \
+ if (flip) { \
+ for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
+ GLint srcCol = (dstCol * srcWidth) / dstWidth; \
+ ASSERT(srcCol >= 0); \
+ ASSERT(srcCol < srcWidth); \
+ srcCol = srcWidth - 1 - srcCol; /* flip */ \
+ if (SIZE == 1) { \
+ dst[dstCol] = src[srcCol]; \
+ } \
+ else if (SIZE == 2) { \
+ dst[dstCol*2+0] = src[srcCol*2+0]; \
+ dst[dstCol*2+1] = src[srcCol*2+1]; \
+ } \
+ else if (SIZE == 4) { \
+ dst[dstCol*4+0] = src[srcCol*4+0]; \
+ dst[dstCol*4+1] = src[srcCol*4+1]; \
+ dst[dstCol*4+2] = src[srcCol*4+2]; \
+ dst[dstCol*4+3] = src[srcCol*4+3]; \
+ } \
+ } \
+ } \
+ else { \
+ for (dstCol = 0; dstCol < dstWidth; dstCol++) { \
+ GLint srcCol = (dstCol * srcWidth) / dstWidth; \
+ ASSERT(srcCol >= 0); \
+ ASSERT(srcCol < srcWidth); \
+ if (SIZE == 1) { \
+ dst[dstCol] = src[srcCol]; \
+ } \
+ else if (SIZE == 2) { \
+ dst[dstCol*2+0] = src[srcCol*2+0]; \
+ dst[dstCol*2+1] = src[srcCol*2+1]; \
+ } \
+ else if (SIZE == 4) { \
+ dst[dstCol*4+0] = src[srcCol*4+0]; \
+ dst[dstCol*4+1] = src[srcCol*4+1]; \
+ dst[dstCol*4+2] = src[srcCol*4+2]; \
+ dst[dstCol*4+3] = src[srcCol*4+3]; \
+ } \
+ } \
+ } \
+}
+
+/**
+ * Resamplers for 1, 2, 4, 8 and 16-byte pixels.
+ */
+RESAMPLE(resample_row_1, GLubyte, 1)
+RESAMPLE(resample_row_2, GLushort, 1)
+RESAMPLE(resample_row_4, GLuint, 1)
+RESAMPLE(resample_row_8, GLuint, 2)
+RESAMPLE(resample_row_16, GLuint, 4)
+
+
+/**
+ * Blit color, depth or stencil with GL_NEAREST filtering.
+ */
+static void
+blit_nearest(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield buffer)
+{
+ struct gl_renderbuffer *readRb, *drawRb;
+
+ const GLint srcWidth = ABS(srcX1 - srcX0);
+ const GLint dstWidth = ABS(dstX1 - dstX0);
+ const GLint srcHeight = ABS(srcY1 - srcY0);
+ const GLint dstHeight = ABS(dstY1 - dstY0);
+
+ const GLint srcXpos = MIN2(srcX0, srcX1);
+ const GLint srcYpos = MIN2(srcY0, srcY1);
+ const GLint dstXpos = MIN2(dstX0, dstX1);
+ const GLint dstYpos = MIN2(dstY0, dstY1);
+
+ const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
+ const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
+
+ GLint dstRow;
+
+ GLint comps, pixelSize;
+ GLvoid *srcBuffer, *dstBuffer;
+ GLint prevY = -1;
+
+ typedef void (*resample_func)(GLint srcWidth, GLint dstWidth,
+ const GLvoid *srcBuffer, GLvoid *dstBuffer,
+ GLboolean flip);
+ resample_func resampleRow;
+
+ switch (buffer) {
+ case GL_COLOR_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_ColorReadBuffer;
+ drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ comps = 4;
+ break;
+ case GL_DEPTH_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_DepthBuffer;
+ drawRb = ctx->DrawBuffer->_DepthBuffer;
+ comps = 1;
+ break;
+ case GL_STENCIL_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_StencilBuffer;
+ drawRb = ctx->DrawBuffer->_StencilBuffer;
+ comps = 1;
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected buffer in blit_nearest()");
+ return;
+ }
+
+ switch (readRb->DataType) {
+ case GL_UNSIGNED_BYTE:
+ pixelSize = comps * sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ pixelSize = comps * sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_INT:
+ pixelSize = comps * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ pixelSize = comps * sizeof(GLfloat);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
+ readRb->DataType);
+ return;
+ }
+
+ /* choose row resampler */
+ switch (pixelSize) {
+ case 1:
+ resampleRow = resample_row_1;
+ break;
+ case 2:
+ resampleRow = resample_row_2;
+ break;
+ case 4:
+ resampleRow = resample_row_4;
+ break;
+ case 8:
+ resampleRow = resample_row_8;
+ break;
+ case 16:
+ resampleRow = resample_row_16;
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
+ pixelSize);
+ return;
+ }
+
+ /* allocate the src/dst row buffers */
+ srcBuffer = _mesa_malloc(pixelSize * srcWidth);
+ if (!srcBuffer) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+ dstBuffer = _mesa_malloc(pixelSize * dstWidth);
+ if (!dstBuffer) {
+ _mesa_free(srcBuffer);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+
+ for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+ const GLint dstY = dstYpos + dstRow;
+ GLint srcRow = (dstRow * srcHeight) / dstHeight;
+ GLint srcY;
+
+ ASSERT(srcRow >= 0);
+ ASSERT(srcRow < srcHeight);
+
+ if (invertY) {
+ srcRow = srcHeight - 1 - srcRow;
+ }
+
+ srcY = srcYpos + srcRow;
+
+ /* get pixel row from source and resample to match dest width */
+ if (prevY != srcY) {
+ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY, srcBuffer);
+ (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
+ prevY = srcY;
+ }
+
+ /* store pixel row in destination */
+ drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
+ }
+
+ _mesa_free(srcBuffer);
+ _mesa_free(dstBuffer);
+}
+
+
+
+#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
+
+static INLINE GLfloat
+lerp_2d(GLfloat a, GLfloat b,
+ GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
+{
+ const GLfloat temp0 = LERP(a, v00, v10);
+ const GLfloat temp1 = LERP(a, v01, v11);
+ return LERP(b, temp0, temp1);
+}
+
+
+/**
+ * Bilinear interpolation of two source rows.
+ * GLubyte pixels.
+ */
+static void
+resample_linear_row_ub(GLint srcWidth, GLint dstWidth,
+ const GLvoid *srcBuffer0, const GLvoid *srcBuffer1,
+ GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight)
+{
+ const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0;
+ const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1;
+ GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer;
+ const GLfloat dstWidthF = (GLfloat) dstWidth;
+ GLint dstCol;
+
+ for (dstCol = 0; dstCol < dstWidth; dstCol++) {
+ const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF;
+ GLint srcCol0 = IFLOOR(srcCol);
+ GLint srcCol1 = srcCol0 + 1;
+ GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */
+ GLfloat red, green, blue, alpha;
+
+ ASSERT(srcCol0 >= 0);
+ ASSERT(srcCol0 < srcWidth);
+ ASSERT(srcCol1 <= srcWidth);
+
+ if (srcCol1 == srcWidth) {
+ /* last column fudge */
+ srcCol1--;
+ colWeight = 0.0;
+ }
+
+ if (flip) {
+ srcCol0 = srcWidth - 1 - srcCol0;
+ srcCol1 = srcWidth - 1 - srcCol1;
+ }
+
+ red = lerp_2d(colWeight, rowWeight,
+ srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP],
+ srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]);
+ green = lerp_2d(colWeight, rowWeight,
+ srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP],
+ srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]);
+ blue = lerp_2d(colWeight, rowWeight,
+ srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP],
+ srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]);
+ alpha = lerp_2d(colWeight, rowWeight,
+ srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP],
+ srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]);
+
+ dstColor[dstCol][RCOMP] = IFLOOR(red);
+ dstColor[dstCol][GCOMP] = IFLOOR(green);
+ dstColor[dstCol][BCOMP] = IFLOOR(blue);
+ dstColor[dstCol][ACOMP] = IFLOOR(alpha);
+ }
+}
+
+
+
+/**
+ * Bilinear filtered blit (color only).
+ */
+static void
+blit_linear(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
+{
+ struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
+ struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+
+ const GLint srcWidth = ABS(srcX1 - srcX0);
+ const GLint dstWidth = ABS(dstX1 - dstX0);
+ const GLint srcHeight = ABS(srcY1 - srcY0);
+ const GLint dstHeight = ABS(dstY1 - dstY0);
+ const GLfloat dstHeightF = (GLfloat) dstHeight;
+
+ const GLint srcXpos = MIN2(srcX0, srcX1);
+ const GLint srcYpos = MIN2(srcY0, srcY1);
+ const GLint dstXpos = MIN2(dstX0, dstX1);
+ const GLint dstYpos = MIN2(dstY0, dstY1);
+
+ const GLboolean invertX = (srcX1 < srcX0) ^ (dstX1 < dstX0);
+ const GLboolean invertY = (srcY1 < srcY0) ^ (dstY1 < dstY0);
+
+ GLint dstRow;
+
+ GLint pixelSize;
+ GLvoid *srcBuffer0, *srcBuffer1;
+ GLint srcBufferY0 = -1, srcBufferY1 = -1;
+ GLvoid *dstBuffer;
+
+ switch (readRb->DataType) {
+ case GL_UNSIGNED_BYTE:
+ pixelSize = 4 * sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ pixelSize = 4 * sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_INT:
+ pixelSize = 4 * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ pixelSize = 4 * sizeof(GLfloat);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected buffer type (0x%x) in blit_nearest",
+ readRb->DataType);
+ return;
+ }
+
+ /* Allocate the src/dst row buffers.
+ * Keep two adjacent src rows around for bilinear sampling.
+ */
+ srcBuffer0 = _mesa_malloc(pixelSize * srcWidth);
+ if (!srcBuffer0) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+ srcBuffer1 = _mesa_malloc(pixelSize * srcWidth);
+ if (!srcBuffer1) {
+ _mesa_free(srcBuffer0);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+ dstBuffer = _mesa_malloc(pixelSize * dstWidth);
+ if (!dstBuffer) {
+ _mesa_free(srcBuffer0);
+ _mesa_free(srcBuffer1);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+
+ for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+ const GLint dstY = dstYpos + dstRow;
+ const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
+ GLint srcRow0 = IFLOOR(srcRow);
+ GLint srcRow1 = srcRow0 + 1;
+ GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
+
+ ASSERT(srcRow >= 0);
+ ASSERT(srcRow < srcHeight);
+
+ if (srcRow1 == srcHeight) {
+ /* last row fudge */
+ srcRow1 = srcRow0;
+ rowWeight = 0.0;
+ }
+
+ if (invertY) {
+ srcRow0 = srcHeight - 1 - srcRow0;
+ srcRow1 = srcHeight - 1 - srcRow1;
+ }
+
+ srcY0 = srcYpos + srcRow0;
+ srcY1 = srcYpos + srcRow1;
+
+ /* get the two source rows */
+ if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
+ /* use same source row buffers again */
+ }
+ else if (srcY0 == srcBufferY1) {
+ /* move buffer1 into buffer0 by swapping pointers */
+ GLvoid *tmp = srcBuffer0;
+ srcBuffer0 = srcBuffer1;
+ srcBuffer1 = tmp;
+ /* get y1 row */
+ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
+ srcBufferY0 = srcY0;
+ srcBufferY1 = srcY1;
+ }
+ else {
+ /* get both new rows */
+ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY0, srcBuffer0);
+ readRb->GetRow(ctx, readRb, srcWidth, srcXpos, srcY1, srcBuffer1);
+ srcBufferY0 = srcY0;
+ srcBufferY1 = srcY1;
+ }
+
+ if (readRb->DataType == GL_UNSIGNED_BYTE) {
+ resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+ dstBuffer, invertX, rowWeight);
+ }
+ else {
+ _mesa_problem(ctx, "Unsupported color channel type in sw blit");
+ break;
+ }
+
+ /* store pixel row in destination */
+ drawRb->PutRow(ctx, drawRb, dstWidth, dstXpos, dstY, dstBuffer, NULL);
+ }
+
+ _mesa_free(srcBuffer0);
+ _mesa_free(srcBuffer1);
+ _mesa_free(dstBuffer);
+}
+
+
+/**
+ * Simple case: Blit color, depth or stencil with no scaling or flipping.
+ * XXX we could easily support vertical flipping here.
+ */
+static void
+simple_blit(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield buffer)
+{
+ struct gl_renderbuffer *readRb, *drawRb;
+ const GLint width = srcX1 - srcX0;
+ const GLint height = srcY1 - srcY0;
+ GLint row, srcY, dstY, yStep;
+ GLint comps, bytesPerRow;
+ void *rowBuffer;
+
+ /* only one buffer */
+ ASSERT(_mesa_bitcount(buffer) == 1);
+ /* no flipping checks */
+ ASSERT(srcX0 < srcX1);
+ ASSERT(srcY0 < srcY1);
+ ASSERT(dstX0 < dstX1);
+ ASSERT(dstY0 < dstY1);
+ /* size checks */
+ ASSERT(srcX1 - srcX0 == dstX1 - dstX0);
+ ASSERT(srcY1 - srcY0 == dstY1 - dstY0);
+
+ /* determine if copy should be bottom-to-top or top-to-bottom */
+ if (srcY0 > dstY0) {
+ /* src above dst: copy bottom-to-top */
+ yStep = 1;
+ srcY = srcY0;
+ dstY = dstY0;
+ }
+ else {
+ /* src below dst: copy top-to-bottom */
+ yStep = -1;
+ srcY = srcY1 - 1;
+ dstY = dstY1 - 1;
+ }
+
+ switch (buffer) {
+ case GL_COLOR_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_ColorReadBuffer;
+ drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ comps = 4;
+ break;
+ case GL_DEPTH_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_DepthBuffer;
+ drawRb = ctx->DrawBuffer->_DepthBuffer;
+ comps = 1;
+ break;
+ case GL_STENCIL_BUFFER_BIT:
+ readRb = ctx->ReadBuffer->_StencilBuffer;
+ drawRb = ctx->DrawBuffer->_StencilBuffer;
+ comps = 1;
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected buffer in simple_blit()");
+ return;
+ }
+
+ ASSERT(readRb->DataType == drawRb->DataType);
+
+ /* compute bytes per row */
+ switch (readRb->DataType) {
+ case GL_UNSIGNED_BYTE:
+ bytesPerRow = comps * width * sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ bytesPerRow = comps * width * sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_INT:
+ bytesPerRow = comps * width * sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ bytesPerRow = comps * width * sizeof(GLfloat);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected buffer type in simple_blit");
+ return;
+ }
+
+ /* allocate the row buffer */
+ rowBuffer = _mesa_malloc(bytesPerRow);
+ if (!rowBuffer) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT");
+ return;
+ }
+
+ for (row = 0; row < height; row++) {
+ readRb->GetRow(ctx, readRb, width, srcX0, srcY, rowBuffer);
+ drawRb->PutRow(ctx, drawRb, width, dstX0, dstY, rowBuffer, NULL);
+ srcY += yStep;
+ dstY += yStep;
+ }
+
+ _mesa_free(rowBuffer);
+}
+
+
+/**
+ * Software fallback for glBlitFramebufferEXT().
+ */
+void
+_swrast_BlitFramebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ static const GLbitfield buffers[3] = {
+ GL_COLOR_BUFFER_BIT,
+ GL_DEPTH_BUFFER_BIT,
+ GL_STENCIL_BUFFER_BIT
+ };
+ GLint i;
+
+ if (!ctx->DrawBuffer->_NumColorDrawBuffers)
+ return;
+
+ if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
+ &dstX0, &dstY0, &dstX1, &dstY1)) {
+ return;
+ }
+
+ swrast_render_start(ctx);
+
+ if (srcX1 - srcX0 == dstX1 - dstX0 &&
+ srcY1 - srcY0 == dstY1 - dstY0 &&
+ srcX0 < srcX1 &&
+ srcY0 < srcY1 &&
+ dstX0 < dstX1 &&
+ dstY0 < dstY1) {
+ /* no stretching or flipping.
+ * filter doesn't matter.
+ */
+ for (i = 0; i < 3; i++) {
+ if (mask & buffers[i]) {
+ simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, buffers[i]);
+ }
+ }
+ }
+ else {
+ if (filter == GL_NEAREST) {
+ for (i = 0; i < 3; i++) {
+ if (mask & buffers[i]) {
+ blit_nearest(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, buffers[i]);
+ }
+ }
+ }
+ else {
+ ASSERT(filter == GL_LINEAR);
+ if (mask & GL_COLOR_BUFFER_BIT) { /* depth/stencil not allowed */
+ blit_linear(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1);
+ }
+ }
+ }
+
+ swrast_render_finish(ctx);
+}
diff --git a/mesalib/src/mesa/swrast/s_clear.c b/mesalib/src/mesa/swrast/s_clear.c
new file mode 100644
index 000000000..35080fd39
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_clear.c
@@ -0,0 +1,344 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "s_accum.h"
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_masking.h"
+#include "s_stencil.h"
+
+
+/**
+ * Clear the color buffer when glColorMask is in effect.
+ */
+static void
+clear_rgba_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ SWspan span;
+ GLint i;
+
+ ASSERT(ctx->Visual.rgbMode);
+ ASSERT(rb->PutRow);
+
+ /* Initialize color span with clear color */
+ /* XXX optimize for clearcolor == black/zero (bzero) */
+ INIT_SPAN(span, GL_BITMAP);
+ span.end = width;
+ span.arrayMask = SPAN_RGBA;
+ span.array->ChanType = rb->DataType;
+ if (span.array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte clearColor[4];
+ UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]);
+ for (i = 0; i < width; i++) {
+ COPY_4UBV(span.array->rgba[i], clearColor);
+ }
+ }
+ else if (span.array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort clearColor[4];
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]);
+ for (i = 0; i < width; i++) {
+ COPY_4V(span.array->rgba[i], clearColor);
+ }
+ }
+ else {
+ ASSERT(span.array->ChanType == GL_FLOAT);
+ for (i = 0; i < width; i++) {
+ CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]);
+ }
+ }
+
+ /* Note that masking will change the color values, but only the
+ * channels for which the write mask is GL_FALSE. The channels
+ * which which are write-enabled won't get modified.
+ */
+ for (i = 0; i < height; i++) {
+ span.x = x;
+ span.y = y + i;
+ _swrast_mask_rgba_span(ctx, rb, &span);
+ /* write masked row */
+ rb->PutRow(ctx, rb, width, x, y + i, span.array->rgba, NULL);
+ }
+}
+
+
+/**
+ * Clear color index buffer with masking.
+ */
+static void
+clear_ci_buffer_with_masking(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ SWspan span;
+ GLint i;
+
+ ASSERT(!ctx->Visual.rgbMode);
+ ASSERT(rb->PutRow);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+
+ /* Initialize index span with clear index */
+ INIT_SPAN(span, GL_BITMAP);
+ span.end = width;
+ span.arrayMask = SPAN_INDEX;
+ for (i = 0; i < width;i++) {
+ span.array->index[i] = ctx->Color.ClearIndex;
+ }
+
+ /* Note that masking will change the color indexes, but only the
+ * bits for which the write mask is GL_FALSE. The bits
+ * which are write-enabled won't get modified.
+ */
+ for (i = 0; i < height;i++) {
+ span.x = x;
+ span.y = y + i;
+ _swrast_mask_ci_span(ctx, rb, &span);
+ /* write masked row */
+ rb->PutRow(ctx, rb, width, x, y + i, span.array->index, NULL);
+ }
+}
+
+
+/**
+ * Clear an rgba color buffer without channel masking.
+ */
+static void
+clear_rgba_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ GLubyte clear8[4];
+ GLushort clear16[4];
+ GLvoid *clearVal;
+ GLint i;
+
+ ASSERT(ctx->Visual.rgbMode);
+
+ ASSERT(ctx->Color.ColorMask[0] &&
+ ctx->Color.ColorMask[1] &&
+ ctx->Color.ColorMask[2] &&
+ ctx->Color.ColorMask[3]);
+
+ ASSERT(rb->PutMonoRow);
+
+ switch (rb->DataType) {
+ case GL_UNSIGNED_BYTE:
+ UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]);
+ clearVal = clear8;
+ break;
+ case GL_UNSIGNED_SHORT:
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]);
+ clearVal = clear16;
+ break;
+ case GL_FLOAT:
+ clearVal = ctx->Color.ClearColor;
+ break;
+ default:
+ _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer");
+ return;
+ }
+
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
+ }
+}
+
+
+/**
+ * Clear color index buffer without masking.
+ */
+static void
+clear_ci_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
+{
+ const GLint x = ctx->DrawBuffer->_Xmin;
+ const GLint y = ctx->DrawBuffer->_Ymin;
+ const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ GLubyte clear8;
+ GLushort clear16;
+ GLuint clear32;
+ GLvoid *clearVal;
+ GLint i;
+
+ ASSERT(!ctx->Visual.rgbMode);
+
+ ASSERT((ctx->Color.IndexMask & ((1 << rb->IndexBits) - 1))
+ == (GLuint) ((1 << rb->IndexBits) - 1));
+
+ ASSERT(rb->PutMonoRow);
+
+ /* setup clear value */
+ switch (rb->DataType) {
+ case GL_UNSIGNED_BYTE:
+ clear8 = (GLubyte) ctx->Color.ClearIndex;
+ clearVal = &clear8;
+ break;
+ case GL_UNSIGNED_SHORT:
+ clear16 = (GLushort) ctx->Color.ClearIndex;
+ clearVal = &clear16;
+ break;
+ case GL_UNSIGNED_INT:
+ clear32 = ctx->Color.ClearIndex;
+ clearVal = &clear32;
+ break;
+ default:
+ _mesa_problem(ctx, "Bad rb DataType in clear_color_buffer");
+ return;
+ }
+
+ for (i = 0; i < height; i++)
+ rb->PutMonoRow(ctx, rb, width, x, y + i, clearVal, NULL);
+}
+
+
+/**
+ * Clear the front/back/left/right/aux color buffers.
+ * This function is usually only called if the device driver can't
+ * clear its own color buffers for some reason (such as with masking).
+ */
+static void
+clear_color_buffers(GLcontext *ctx)
+{
+ GLboolean masking;
+ GLuint buf;
+
+ if (ctx->Visual.rgbMode) {
+ if (ctx->Color.ColorMask[0] &&
+ ctx->Color.ColorMask[1] &&
+ ctx->Color.ColorMask[2] &&
+ ctx->Color.ColorMask[3]) {
+ masking = GL_FALSE;
+ }
+ else {
+ masking = GL_TRUE;
+ }
+ }
+ else {
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ const GLuint indexBits = (1 << rb->IndexBits) - 1;
+ if ((ctx->Color.IndexMask & indexBits) == indexBits) {
+ masking = GL_FALSE;
+ }
+ else {
+ masking = GL_TRUE;
+ }
+ }
+
+ for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf];
+ if (ctx->Visual.rgbMode) {
+ if (masking) {
+ clear_rgba_buffer_with_masking(ctx, rb);
+ }
+ else {
+ clear_rgba_buffer(ctx, rb);
+ }
+ }
+ else {
+ if (masking) {
+ clear_ci_buffer_with_masking(ctx, rb);
+ }
+ else {
+ clear_ci_buffer(ctx, rb);
+ }
+ }
+ }
+}
+
+
+/**
+ * Called via the device driver's ctx->Driver.Clear() function if the
+ * device driver can't clear one or more of the buffers itself.
+ * \param buffers bitfield of BUFFER_BIT_* values indicating which
+ * renderbuffers are to be cleared.
+ * \param all if GL_TRUE, clear whole buffer, else clear specified region.
+ */
+void
+_swrast_Clear(GLcontext *ctx, GLbitfield buffers)
+{
+#ifdef DEBUG_FOO
+ {
+ const GLbitfield legalBits =
+ BUFFER_BIT_FRONT_LEFT |
+ BUFFER_BIT_FRONT_RIGHT |
+ BUFFER_BIT_BACK_LEFT |
+ BUFFER_BIT_BACK_RIGHT |
+ BUFFER_BIT_DEPTH |
+ BUFFER_BIT_STENCIL |
+ BUFFER_BIT_ACCUM |
+ BUFFER_BIT_AUX0;
+ assert((buffers & (~legalBits)) == 0);
+ }
+#endif
+
+ swrast_render_start(ctx);
+
+ /* do software clearing here */
+ if (buffers) {
+ if ((buffers & BUFFER_BITS_COLOR)
+ && (ctx->DrawBuffer->_NumColorDrawBuffers > 0)) {
+ clear_color_buffers(ctx);
+ }
+ if (buffers & BUFFER_BIT_DEPTH) {
+ _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer);
+ }
+ if (buffers & BUFFER_BIT_ACCUM) {
+ _swrast_clear_accum_buffer(ctx,
+ ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
+ }
+ if (buffers & BUFFER_BIT_STENCIL) {
+ _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer);
+ }
+ }
+
+ swrast_render_finish(ctx);
+}
diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c
new file mode 100644
index 000000000..abf000856
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_context.c
@@ -0,0 +1,957 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/mtypes.h"
+#include "main/teximage.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_statevars.h"
+#include "swrast.h"
+#include "s_blend.h"
+#include "s_context.h"
+#include "s_lines.h"
+#include "s_points.h"
+#include "s_span.h"
+#include "s_triangle.h"
+#include "s_texfilter.h"
+
+
+/**
+ * Recompute the value of swrast->_RasterMask, etc. according to
+ * the current context. The _RasterMask field can be easily tested by
+ * drivers to determine certain basic GL state (does the primitive need
+ * stenciling, logic-op, fog, etc?).
+ */
+static void
+_swrast_update_rasterflags( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLbitfield rasterMask = 0;
+
+ if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT;
+ if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT;
+ if (ctx->Depth.Test) rasterMask |= DEPTH_BIT;
+ if (swrast->_FogEnabled) rasterMask |= FOG_BIT;
+ if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT;
+ if (ctx->Stencil._Enabled) rasterMask |= STENCIL_BIT;
+ if (ctx->Visual.rgbMode) {
+ const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
+ if (colorMask != 0xffffffff) rasterMask |= MASKING_BIT;
+ if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
+ if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT;
+ }
+ else {
+ if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT;
+ if (ctx->Color.IndexLogicOpEnabled) rasterMask |= LOGIC_OP_BIT;
+ }
+
+ if ( ctx->Viewport.X < 0
+ || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width
+ || ctx->Viewport.Y < 0
+ || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) {
+ rasterMask |= CLIP_BIT;
+ }
+
+ if (ctx->Query.CurrentOcclusionObject)
+ rasterMask |= OCCLUSION_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.
+ */
+ if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
+ /* more than one color buffer designated for writing (or zero buffers) */
+ rasterMask |= MULTI_DRAW_BIT;
+ }
+ else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) {
+ rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */
+ }
+ else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) {
+ rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
+ }
+
+ if (ctx->FragmentProgram._Current) {
+ rasterMask |= FRAGPROG_BIT;
+ }
+
+ if (ctx->ATIFragmentShader._Enabled) {
+ rasterMask |= ATIFRAGSHADER_BIT;
+ }
+
+#if CHAN_TYPE == GL_FLOAT
+ if (ctx->Color.ClampFragmentColor == GL_TRUE) {
+ rasterMask |= CLAMPING_BIT;
+ }
+#endif
+
+ SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask;
+}
+
+
+/**
+ * Examine polygon cull state to compute the _BackfaceCullSign field.
+ * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces,
+ * and 1 if culling front-faces. The Polygon FrontFace state also
+ * factors in.
+ */
+static void
+_swrast_update_polygon( GLcontext *ctx )
+{
+ GLfloat backface_sign;
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ backface_sign = -1.0;
+ break;
+ case GL_FRONT:
+ backface_sign = 1.0;
+ break;
+ case GL_FRONT_AND_BACK:
+ /* fallthrough */
+ default:
+ backface_sign = 0.0;
+ }
+ }
+ else {
+ backface_sign = 0.0;
+ }
+
+ SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign;
+
+ /* This is for front/back-face determination, but not for culling */
+ SWRAST_CONTEXT(ctx)->_BackfaceSign
+ = (ctx->Polygon.FrontFace == GL_CW) ? -1.0 : 1.0;
+}
+
+
+
+/**
+ * Update the _PreferPixelFog field to indicate if we need to compute
+ * fog blend factors (from the fog coords) per-fragment.
+ */
+static void
+_swrast_update_fog_hint( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
+ ctx->FragmentProgram._Current ||
+ (ctx->Hint.Fog == GL_NICEST &&
+ swrast->AllowPixelFog));
+}
+
+
+
+/**
+ * Update the swrast->_TextureCombinePrimary flag.
+ */
+static void
+_swrast_update_texture_env( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint i;
+
+ swrast->_TextureCombinePrimary = GL_FALSE;
+
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ const struct gl_tex_env_combine_state *combine =
+ ctx->Texture.Unit[i]._CurrentCombine;
+ GLuint term;
+ for (term = 0; term < combine->_NumArgsRGB; term++) {
+ if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
+ if (combine->SourceA[term] == GL_PRIMARY_COLOR) {
+ swrast->_TextureCombinePrimary = GL_TRUE;
+ return;
+ }
+ }
+ }
+}
+
+
+/**
+ * Determine if we can defer texturing/shading until after Z/stencil
+ * testing. This potentially allows us to skip texturing/shading for
+ * lots of fragments.
+ */
+static void
+_swrast_update_deferred_texture(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (ctx->Color.AlphaEnabled) {
+ /* alpha test depends on post-texture/shader colors */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else {
+ const struct gl_fragment_program *fprog
+ = ctx->FragmentProgram._Current;
+ if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
+ /* Z comes from fragment program/shader */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else if (fprog && fprog->UsesKill) {
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else if (ctx->Query.CurrentOcclusionObject) {
+ /* occlusion query depends on shader discard/kill results */
+ swrast->_DeferredTexture = GL_FALSE;
+ }
+ else {
+ swrast->_DeferredTexture = GL_TRUE;
+ }
+ }
+}
+
+
+/**
+ * Update swrast->_FogColor and swrast->_FogEnable values.
+ */
+static void
+_swrast_update_fog_state( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+
+ /* determine if fog is needed, and if so, which fog mode */
+ swrast->_FogEnabled = GL_FALSE;
+ if (fp && fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
+ if (fp->FogOption != GL_NONE) {
+ swrast->_FogEnabled = GL_TRUE;
+ swrast->_FogMode = fp->FogOption;
+ }
+ }
+ else if (ctx->Fog.Enabled) {
+ swrast->_FogEnabled = GL_TRUE;
+ swrast->_FogMode = ctx->Fog.Mode;
+ }
+}
+
+
+/**
+ * Update state for running fragment programs. Basically, load the
+ * program parameters with current state values.
+ */
+static void
+_swrast_update_fragment_program(GLcontext *ctx, GLbitfield newState)
+{
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+ if (fp) {
+ _mesa_load_state_parameters(ctx, fp->Base.Parameters);
+ }
+}
+
+
+/**
+ * See if we can do early diffuse+specular (primary+secondary) color
+ * add per vertex instead of per-fragment.
+ */
+static void
+_swrast_update_specular_vertex_add(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLboolean separateSpecular = ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR);
+
+ swrast->SpecularVertexAdd = (separateSpecular
+ && ctx->Texture._EnabledUnits == 0x0
+ && !ctx->FragmentProgram._Current
+ && !ctx->ATIFragmentShader._Enabled);
+}
+
+
+#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
+ _NEW_PROGRAM_CONSTANTS | \
+ _NEW_TEXTURE | \
+ _NEW_HINT | \
+ _NEW_POLYGON )
+
+/* State referenced by _swrast_choose_triangle, _swrast_choose_line.
+ */
+#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \
+ _NEW_RENDERMODE| \
+ _NEW_POLYGON| \
+ _NEW_DEPTH| \
+ _NEW_STENCIL| \
+ _NEW_COLOR| \
+ _NEW_TEXTURE| \
+ _SWRAST_NEW_RASTERMASK| \
+ _NEW_LIGHT| \
+ _NEW_FOG | \
+ _DD_NEW_SEPARATE_SPECULAR)
+
+#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \
+ _NEW_RENDERMODE| \
+ _NEW_LINE| \
+ _NEW_TEXTURE| \
+ _NEW_LIGHT| \
+ _NEW_FOG| \
+ _NEW_DEPTH | \
+ _DD_NEW_SEPARATE_SPECULAR)
+
+#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \
+ _NEW_RENDERMODE | \
+ _NEW_POINT | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_FOG | \
+ _DD_NEW_SEPARATE_SPECULAR)
+
+#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
+
+#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
+
+#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
+
+
+
+/**
+ * Stub for swrast->Triangle to select a true triangle function
+ * after a state change.
+ */
+static void
+_swrast_validate_triangle( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2 )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ _swrast_validate_derived( ctx );
+ swrast->choose_triangle( ctx );
+ ASSERT(swrast->Triangle);
+
+ if (swrast->SpecularVertexAdd) {
+ /* separate specular color, but no texture */
+ swrast->SpecTriangle = swrast->Triangle;
+ swrast->Triangle = _swrast_add_spec_terms_triangle;
+ }
+
+ swrast->Triangle( ctx, v0, v1, v2 );
+}
+
+/**
+ * Called via swrast->Line. Examine current GL state and choose a software
+ * line routine. Then call it.
+ */
+static void
+_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ _swrast_validate_derived( ctx );
+ swrast->choose_line( ctx );
+ ASSERT(swrast->Line);
+
+ if (swrast->SpecularVertexAdd) {
+ swrast->SpecLine = swrast->Line;
+ swrast->Line = _swrast_add_spec_terms_line;
+ }
+
+ swrast->Line( ctx, v0, v1 );
+}
+
+/**
+ * Called via swrast->Point. Examine current GL state and choose a software
+ * point routine. Then call it.
+ */
+static void
+_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ _swrast_validate_derived( ctx );
+ swrast->choose_point( ctx );
+
+ if (swrast->SpecularVertexAdd) {
+ swrast->SpecPoint = swrast->Point;
+ swrast->Point = _swrast_add_spec_terms_point;
+ }
+
+ swrast->Point( ctx, v0 );
+}
+
+
+/**
+ * Called via swrast->BlendFunc. Examine GL state to choose a blending
+ * function, then call it.
+ */
+static void _ASMAPI
+_swrast_validate_blend_func(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst,
+ GLenum chanType )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ _swrast_validate_derived( ctx ); /* why is this needed? */
+ _swrast_choose_blend_func( ctx, chanType );
+
+ swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
+}
+
+
+/**
+ * Make sure we have texture image data for all the textures we may need
+ * for subsequent rendering.
+ */
+static void
+_swrast_validate_texture_images(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint u;
+
+ if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) {
+ /* no textures enabled, or no way to validate images! */
+ return;
+ }
+
+ for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
+ if (ctx->Texture.Unit[u]._ReallyEnabled) {
+ struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
+ ASSERT(texObj);
+ if (texObj) {
+ GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ GLuint face;
+ for (face = 0; face < numFaces; face++) {
+ GLint lvl;
+ for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
+ struct gl_texture_image *texImg = texObj->Image[face][lvl];
+ if (texImg && !texImg->Data) {
+ swrast->ValidateTextureImage(ctx, texObj, face, lvl);
+ ASSERT(texObj->Image[face][lvl]->Data);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Free the texture image data attached to all currently enabled
+ * textures. Meant to be called by device drivers when transitioning
+ * from software to hardware rendering.
+ */
+void
+_swrast_eject_texture_images(GLcontext *ctx)
+{
+ GLuint u;
+
+ if (!ctx->Texture._EnabledUnits) {
+ /* no textures enabled */
+ return;
+ }
+
+ for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
+ if (ctx->Texture.Unit[u]._ReallyEnabled) {
+ struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current;
+ ASSERT(texObj);
+ if (texObj) {
+ GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ GLuint face;
+ for (face = 0; face < numFaces; face++) {
+ GLint lvl;
+ for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) {
+ struct gl_texture_image *texImg = texObj->Image[face][lvl];
+ if (texImg && texImg->Data) {
+ _mesa_free_texmemory(texImg->Data);
+ texImg->Data = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+static void
+_swrast_sleep( GLcontext *ctx, GLbitfield new_state )
+{
+ (void) ctx; (void) new_state;
+}
+
+
+static void
+_swrast_invalidate_state( GLcontext *ctx, GLbitfield new_state )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint i;
+
+ swrast->NewState |= new_state;
+
+ /* After 10 statechanges without any swrast functions being called,
+ * put the module to sleep.
+ */
+ if (++swrast->StateChanges > 10) {
+ swrast->InvalidateState = _swrast_sleep;
+ swrast->NewState = ~0;
+ new_state = ~0;
+ }
+
+ if (new_state & swrast->InvalidateTriangleMask)
+ swrast->Triangle = _swrast_validate_triangle;
+
+ if (new_state & swrast->InvalidateLineMask)
+ swrast->Line = _swrast_validate_line;
+
+ if (new_state & swrast->InvalidatePointMask)
+ swrast->Point = _swrast_validate_point;
+
+ if (new_state & _SWRAST_NEW_BLEND_FUNC)
+ swrast->BlendFunc = _swrast_validate_blend_func;
+
+ if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC)
+ for (i = 0 ; i < ctx->Const.MaxTextureImageUnits ; i++)
+ swrast->TextureSample[i] = NULL;
+}
+
+
+void
+_swrast_update_texture_samplers(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint u;
+
+ if (!swrast)
+ return; /* pipe hack */
+
+ for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) {
+ const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
+ /* Note: If tObj is NULL, the sample function will be a simple
+ * function that just returns opaque black (0,0,0,1).
+ */
+ swrast->TextureSample[u] = _swrast_choose_texture_sample_func(ctx, tObj);
+ }
+}
+
+
+/**
+ * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs,
+ * swrast->_ActiveAtttribMask.
+ */
+static void
+_swrast_update_active_attribs(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint attribsMask;
+
+ /*
+ * Compute _ActiveAttribsMask = which fragment attributes are needed.
+ */
+ if (ctx->FragmentProgram._Current) {
+ /* fragment program/shader */
+ attribsMask = ctx->FragmentProgram._Current->Base.InputsRead;
+ attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */
+ }
+ else if (ctx->ATIFragmentShader._Enabled) {
+ attribsMask = ~0; /* XXX fix me */
+ }
+ else {
+ /* fixed function */
+ attribsMask = 0x0;
+
+#if CHAN_TYPE == GL_FLOAT
+ attribsMask |= FRAG_BIT_COL0;
+#endif
+
+ if (ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+ attribsMask |= FRAG_BIT_COL1;
+ }
+
+ if (swrast->_FogEnabled)
+ attribsMask |= FRAG_BIT_FOGC;
+
+ attribsMask |= (ctx->Texture._EnabledUnits << FRAG_ATTRIB_TEX0);
+ }
+
+ swrast->_ActiveAttribMask = attribsMask;
+
+ /* Update _ActiveAttribs[] list */
+ {
+ GLuint i, num = 0;
+ for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ if (attribsMask & (1 << i)) {
+ swrast->_ActiveAttribs[num++] = i;
+ /* how should this attribute be interpolated? */
+ if (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1)
+ swrast->_InterpMode[i] = ctx->Light.ShadeModel;
+ else
+ swrast->_InterpMode[i] = GL_SMOOTH;
+ }
+ }
+ swrast->_NumActiveAttribs = num;
+ }
+}
+
+
+void
+_swrast_validate_derived( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (swrast->NewState) {
+ if (swrast->NewState & _NEW_POLYGON)
+ _swrast_update_polygon( ctx );
+
+ if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM))
+ _swrast_update_fog_hint( ctx );
+
+ if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE)
+ _swrast_update_texture_env( ctx );
+
+ if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
+ _swrast_update_fog_state( ctx );
+
+ if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM))
+ _swrast_update_fragment_program( ctx, swrast->NewState );
+
+ if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) {
+ _swrast_update_texture_samplers( ctx );
+ _swrast_validate_texture_images(ctx);
+ }
+
+ if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM))
+ _swrast_update_deferred_texture(ctx);
+
+ if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
+ _swrast_update_rasterflags( ctx );
+
+ if (swrast->NewState & (_NEW_DEPTH |
+ _NEW_FOG |
+ _NEW_LIGHT |
+ _NEW_PROGRAM |
+ _NEW_TEXTURE))
+ _swrast_update_active_attribs(ctx);
+
+ if (swrast->NewState & (_NEW_FOG |
+ _NEW_PROGRAM |
+ _NEW_LIGHT |
+ _NEW_TEXTURE))
+ _swrast_update_specular_vertex_add(ctx);
+
+ swrast->NewState = 0;
+ swrast->StateChanges = 0;
+ swrast->InvalidateState = _swrast_invalidate_state;
+ }
+}
+
+#define SWRAST_DEBUG 0
+
+/* Public entrypoints: See also s_accum.c, s_bitmap.c, etc.
+ */
+void
+_swrast_Quad( GLcontext *ctx,
+ const SWvertex *v0, const SWvertex *v1,
+ const SWvertex *v2, const SWvertex *v3 )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_Quad\n");
+ _swrast_print_vertex( ctx, v0 );
+ _swrast_print_vertex( ctx, v1 );
+ _swrast_print_vertex( ctx, v2 );
+ _swrast_print_vertex( ctx, v3 );
+ }
+ SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 );
+ SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 );
+}
+
+void
+_swrast_Triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_Triangle\n");
+ _swrast_print_vertex( ctx, v0 );
+ _swrast_print_vertex( ctx, v1 );
+ _swrast_print_vertex( ctx, v2 );
+ }
+ SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 );
+}
+
+void
+_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_Line\n");
+ _swrast_print_vertex( ctx, v0 );
+ _swrast_print_vertex( ctx, v1 );
+ }
+ SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 );
+}
+
+void
+_swrast_Point( GLcontext *ctx, const SWvertex *v0 )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_Point\n");
+ _swrast_print_vertex( ctx, v0 );
+ }
+ SWRAST_CONTEXT(ctx)->Point( ctx, v0 );
+}
+
+void
+_swrast_InvalidateState( GLcontext *ctx, GLbitfield new_state )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_InvalidateState\n");
+ }
+ SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state );
+}
+
+void
+_swrast_ResetLineStipple( GLcontext *ctx )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_ResetLineStipple\n");
+ }
+ SWRAST_CONTEXT(ctx)->StippleCounter = 0;
+}
+
+void
+_swrast_SetFacing(GLcontext *ctx, GLuint facing)
+{
+ SWRAST_CONTEXT(ctx)->PointLineFacing = facing;
+}
+
+void
+_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value);
+ }
+ SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
+ SWRAST_CONTEXT(ctx)->AllowVertexFog = value;
+}
+
+void
+_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value )
+{
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value);
+ }
+ SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT );
+ SWRAST_CONTEXT(ctx)->AllowPixelFog = value;
+}
+
+
+GLboolean
+_swrast_CreateContext( GLcontext *ctx )
+{
+ GLuint i;
+ SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext));
+
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_CreateContext\n");
+ }
+
+ if (!swrast)
+ return GL_FALSE;
+
+ swrast->NewState = ~0;
+
+ swrast->choose_point = _swrast_choose_point;
+ swrast->choose_line = _swrast_choose_line;
+ swrast->choose_triangle = _swrast_choose_triangle;
+
+ swrast->InvalidatePointMask = _SWRAST_NEW_POINT;
+ swrast->InvalidateLineMask = _SWRAST_NEW_LINE;
+ swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE;
+
+ swrast->Point = _swrast_validate_point;
+ swrast->Line = _swrast_validate_line;
+ swrast->Triangle = _swrast_validate_triangle;
+ swrast->InvalidateState = _swrast_sleep;
+ swrast->BlendFunc = _swrast_validate_blend_func;
+
+ swrast->AllowVertexFog = GL_TRUE;
+ swrast->AllowPixelFog = GL_TRUE;
+
+ /* Optimized Accum buffer */
+ swrast->_IntegerAccumMode = GL_FALSE;
+ swrast->_IntegerAccumScaler = 0.0;
+
+ for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+ swrast->TextureSample[i] = NULL;
+
+ swrast->SpanArrays = MALLOC_STRUCT(sw_span_arrays);
+ if (!swrast->SpanArrays) {
+ FREE(swrast);
+ return GL_FALSE;
+ }
+ swrast->SpanArrays->ChanType = CHAN_TYPE;
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ swrast->SpanArrays->rgba = swrast->SpanArrays->rgba8;
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+ swrast->SpanArrays->rgba = swrast->SpanArrays->rgba16;
+#else
+ swrast->SpanArrays->rgba = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
+#endif
+
+ /* init point span buffer */
+ swrast->PointSpan.primitive = GL_POINT;
+ swrast->PointSpan.end = 0;
+ swrast->PointSpan.facing = 0;
+ swrast->PointSpan.array = swrast->SpanArrays;
+
+ swrast->TexelBuffer = (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits *
+ MAX_WIDTH * 4 * sizeof(GLfloat));
+ if (!swrast->TexelBuffer) {
+ FREE(swrast->SpanArrays);
+ FREE(swrast);
+ return GL_FALSE;
+ }
+
+ ctx->swrast_context = swrast;
+
+ return GL_TRUE;
+}
+
+void
+_swrast_DestroyContext( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (SWRAST_DEBUG) {
+ _mesa_debug(ctx, "_swrast_DestroyContext\n");
+ }
+
+ FREE( swrast->SpanArrays );
+ if (swrast->ZoomedArrays)
+ FREE( swrast->ZoomedArrays );
+ FREE( swrast->TexelBuffer );
+ FREE( swrast );
+
+ ctx->swrast_context = 0;
+}
+
+
+struct swrast_device_driver *
+_swrast_GetDeviceDriverReference( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ return &swrast->Driver;
+}
+
+void
+_swrast_flush( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ /* flush any pending fragments from rendering points */
+ if (swrast->PointSpan.end > 0) {
+ if (ctx->Visual.rgbMode) {
+ _swrast_write_rgba_span(ctx, &(swrast->PointSpan));
+ }
+ else {
+ _swrast_write_index_span(ctx, &(swrast->PointSpan));
+ }
+ swrast->PointSpan.end = 0;
+ }
+}
+
+void
+_swrast_render_primitive( GLcontext *ctx, GLenum prim )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
+ _swrast_flush(ctx);
+ }
+ swrast->Primitive = prim;
+}
+
+
+void
+_swrast_render_start( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderStart)
+ swrast->Driver.SpanRenderStart( ctx );
+ swrast->PointSpan.end = 0;
+}
+
+void
+_swrast_render_finish( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderFinish)
+ swrast->Driver.SpanRenderFinish( ctx );
+
+ _swrast_flush(ctx);
+}
+
+
+#define SWRAST_DEBUG_VERTICES 0
+
+void
+_swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
+{
+ GLuint i;
+
+ if (SWRAST_DEBUG_VERTICES) {
+ _mesa_debug(ctx, "win %f %f %f %f\n",
+ v->attrib[FRAG_ATTRIB_WPOS][0],
+ v->attrib[FRAG_ATTRIB_WPOS][1],
+ v->attrib[FRAG_ATTRIB_WPOS][2],
+ v->attrib[FRAG_ATTRIB_WPOS][3]);
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
+ v->attrib[FRAG_ATTRIB_TEX0 + i][0],
+ v->attrib[FRAG_ATTRIB_TEX0 + i][1],
+ v->attrib[FRAG_ATTRIB_TEX0 + i][2],
+ v->attrib[FRAG_ATTRIB_TEX0 + i][3]);
+
+#if CHAN_TYPE == GL_FLOAT
+ _mesa_debug(ctx, "color %f %f %f %f\n",
+ v->color[0], v->color[1], v->color[2], v->color[3]);
+#else
+ _mesa_debug(ctx, "color %d %d %d %d\n",
+ v->color[0], v->color[1], v->color[2], v->color[3]);
+#endif
+ _mesa_debug(ctx, "spec %g %g %g %g\n",
+ v->attrib[FRAG_ATTRIB_COL1][0],
+ v->attrib[FRAG_ATTRIB_COL1][1],
+ v->attrib[FRAG_ATTRIB_COL1][2],
+ v->attrib[FRAG_ATTRIB_COL1][3]);
+ _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]);
+ _mesa_debug(ctx, "index %d\n", v->attrib[FRAG_ATTRIB_CI][0]);
+ _mesa_debug(ctx, "pointsize %f\n", v->pointSize);
+ _mesa_debug(ctx, "\n");
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_context.h b/mesalib/src/mesa/swrast/s_context.h
new file mode 100644
index 000000000..9059f9b5e
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_context.h
@@ -0,0 +1,348 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/**
+ * \file swrast/s_context.h
+ * \brief Software rasterization context and private types.
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/**
+ * \mainpage swrast module
+ *
+ * This module, software rasterization, contains the software fallback
+ * routines for drawing points, lines, triangles, bitmaps and images.
+ * All rendering boils down to writing spans (arrays) of pixels with
+ * particular colors. The span-writing routines must be implemented
+ * by the device driver.
+ */
+
+
+#ifndef S_CONTEXT_H
+#define S_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "shader/prog_execute.h"
+#include "swrast.h"
+#include "s_span.h"
+
+
+typedef void (*texture_sample_func)(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4]);
+
+typedef void (_ASMAPIP blend_func)( GLcontext *ctx, GLuint n,
+ const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst,
+ GLenum chanType);
+
+typedef void (*swrast_point_func)( GLcontext *ctx, const SWvertex *);
+
+typedef void (*swrast_line_func)( GLcontext *ctx,
+ const SWvertex *, const SWvertex *);
+
+typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *,
+ const SWvertex *, const SWvertex *);
+
+
+typedef void (*validate_texture_image_func)(GLcontext *ctx,
+ struct gl_texture_object *texObj,
+ GLuint face, GLuint level);
+
+
+/**
+ * \defgroup Bitmasks
+ * Bitmasks to indicate which rasterization options are enabled
+ * (RasterMask)
+ */
+/*@{*/
+#define ALPHATEST_BIT 0x001 /**< Alpha-test pixels */
+#define BLEND_BIT 0x002 /**< Blend pixels */
+#define DEPTH_BIT 0x004 /**< Depth-test pixels */
+#define FOG_BIT 0x008 /**< Fog pixels */
+#define LOGIC_OP_BIT 0x010 /**< Apply logic op in software */
+#define CLIP_BIT 0x020 /**< Scissor or window clip pixels */
+#define STENCIL_BIT 0x040 /**< Stencil pixels */
+#define MASKING_BIT 0x080 /**< Do glColorMask or glIndexMask */
+#define MULTI_DRAW_BIT 0x400 /**< Write to more than one color- */
+ /**< buffer or no buffers. */
+#define OCCLUSION_BIT 0x800 /**< GL_HP_occlusion_test enabled */
+#define TEXTURE_BIT 0x1000 /**< Texturing really enabled */
+#define FRAGPROG_BIT 0x2000 /**< Fragment program enabled */
+#define ATIFRAGSHADER_BIT 0x4000 /**< ATI Fragment shader enabled */
+#define CLAMPING_BIT 0x8000 /**< Clamp colors to [0,1] */
+/*@}*/
+
+#define _SWRAST_NEW_RASTERMASK (_NEW_BUFFERS| \
+ _NEW_SCISSOR| \
+ _NEW_COLOR| \
+ _NEW_DEPTH| \
+ _NEW_FOG| \
+ _NEW_PROGRAM| \
+ _NEW_STENCIL| \
+ _NEW_TEXTURE| \
+ _NEW_VIEWPORT| \
+ _NEW_DEPTH)
+
+
+/**
+ * \struct SWcontext
+ * \brief Per-context state that's private to the software rasterizer module.
+ */
+typedef struct
+{
+ /** Driver interface:
+ */
+ struct swrast_device_driver Driver;
+
+ /** Configuration mechanisms to make software rasterizer match
+ * characteristics of the hardware rasterizer (if present):
+ */
+ GLboolean AllowVertexFog;
+ GLboolean AllowPixelFog;
+
+ /** Derived values, invalidated on statechanges, updated from
+ * _swrast_validate_derived():
+ */
+ GLbitfield _RasterMask;
+ GLfloat _BackfaceSign; /** +1 or -1 */
+ GLfloat _BackfaceCullSign; /** +1, 0, or -1 */
+ GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */
+ GLboolean _TextureCombinePrimary;
+ GLboolean _FogEnabled;
+ GLboolean _DeferredTexture;
+ GLenum _FogMode; /* either GL_FOG_MODE or fragment program's fog mode */
+
+ /** List/array of the fragment attributes to interpolate */
+ GLuint _ActiveAttribs[FRAG_ATTRIB_MAX];
+ /** Same info, but as a bitmask */
+ GLbitfield _ActiveAttribMask;
+ /** Number of fragment attributes to interpolate */
+ GLuint _NumActiveAttribs;
+ /** Indicates how each attrib is to be interpolated (lines/tris) */
+ GLenum _InterpMode[FRAG_ATTRIB_MAX]; /* GL_FLAT or GL_SMOOTH (for now) */
+
+ /* Accum buffer temporaries.
+ */
+ GLboolean _IntegerAccumMode; /**< Storing unscaled integers? */
+ GLfloat _IntegerAccumScaler; /**< Implicit scale factor */
+
+ /* Working values:
+ */
+ GLuint StippleCounter; /**< Line stipple counter */
+ GLuint PointLineFacing;
+ GLbitfield NewState;
+ GLuint StateChanges;
+ GLenum Primitive; /* current primitive being drawn (ala glBegin) */
+ GLboolean SpecularVertexAdd; /**< Add specular/secondary color per vertex */
+
+ void (*InvalidateState)( GLcontext *ctx, GLbitfield new_state );
+
+ /**
+ * When the NewState mask intersects these masks, we invalidate the
+ * Point/Line/Triangle function pointers below.
+ */
+ /*@{*/
+ GLbitfield InvalidatePointMask;
+ GLbitfield InvalidateLineMask;
+ GLbitfield InvalidateTriangleMask;
+ /*@}*/
+
+ /**
+ * Device drivers plug in functions for these callbacks.
+ * Will be called when the GL state change mask intersects the above masks.
+ */
+ /*@{*/
+ void (*choose_point)( GLcontext * );
+ void (*choose_line)( GLcontext * );
+ void (*choose_triangle)( GLcontext * );
+ /*@}*/
+
+ /**
+ * Current point, line and triangle drawing functions.
+ */
+ /*@{*/
+ swrast_point_func Point;
+ swrast_line_func Line;
+ swrast_tri_func Triangle;
+ /*@}*/
+
+ /**
+ * Placeholders for when separate specular (or secondary color) is
+ * enabled but texturing is not.
+ */
+ /*@{*/
+ swrast_point_func SpecPoint;
+ swrast_line_func SpecLine;
+ swrast_tri_func SpecTriangle;
+ /*@}*/
+
+ /**
+ * Typically, we'll allocate a sw_span structure as a local variable
+ * and set its 'array' pointer to point to this object. The reason is
+ * this object is big and causes problems when allocated on the stack
+ * on some systems.
+ */
+ SWspanarrays *SpanArrays;
+ SWspanarrays *ZoomedArrays; /**< For pixel zooming */
+
+ /**
+ * Used to buffer N GL_POINTS, instead of rendering one by one.
+ */
+ SWspan PointSpan;
+
+ /** Internal hooks, kept up to date by the same mechanism as above.
+ */
+ blend_func BlendFunc;
+ texture_sample_func TextureSample[MAX_TEXTURE_IMAGE_UNITS];
+
+ /** Buffer for saving the sampled texture colors.
+ * Needed for GL_ARB_texture_env_crossbar implementation.
+ */
+ GLfloat *TexelBuffer;
+
+ validate_texture_image_func ValidateTextureImage;
+
+ /** State used during execution of fragment programs */
+ struct gl_program_machine FragProgMachine;
+
+} SWcontext;
+
+
+extern void
+_swrast_validate_derived( GLcontext *ctx );
+
+extern void
+_swrast_update_texture_samplers(GLcontext *ctx);
+
+
+/** Return SWcontext for the given GLcontext */
+static INLINE SWcontext *
+SWRAST_CONTEXT(GLcontext *ctx)
+{
+ return (SWcontext *) ctx->swrast_context;
+}
+
+/** const version of above */
+static INLINE const SWcontext *
+CONST_SWRAST_CONTEXT(const GLcontext *ctx)
+{
+ return (const SWcontext *) ctx->swrast_context;
+}
+
+
+/**
+ * Called prior to framebuffer reading/writing.
+ * For drivers that rely on swrast for fallback rendering, this is the
+ * driver's opportunity to map renderbuffers and textures.
+ */
+static INLINE void
+swrast_render_start(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderStart)
+ swrast->Driver.SpanRenderStart(ctx);
+}
+
+
+/** Called after framebuffer reading/writing */
+static INLINE void
+swrast_render_finish(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.SpanRenderFinish)
+ swrast->Driver.SpanRenderFinish(ctx);
+}
+
+
+
+/**
+ * Size of an RGBA pixel, in bytes, for given datatype.
+ */
+#define RGBA_PIXEL_SIZE(TYPE) \
+ ((TYPE == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : \
+ ((TYPE == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) \
+ : 4 * sizeof(GLfloat)))
+
+
+
+/*
+ * Fixed point arithmetic macros
+ */
+#ifndef FIXED_FRAC_BITS
+#define FIXED_FRAC_BITS 11
+#endif
+
+#define FIXED_SHIFT FIXED_FRAC_BITS
+#define FIXED_ONE (1 << FIXED_SHIFT)
+#define FIXED_HALF (1 << (FIXED_SHIFT-1))
+#define FIXED_FRAC_MASK (FIXED_ONE - 1)
+#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
+#define FIXED_EPSILON 1
+#define FIXED_SCALE ((float) FIXED_ONE)
+#define FIXED_DBL_SCALE ((double) FIXED_ONE)
+#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE))
+#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE))
+#define IntToFixed(I) ((I) << FIXED_SHIFT)
+#define FixedToInt(X) ((X) >> FIXED_SHIFT)
+#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT)
+#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
+#define FixedFloor(X) ((X) & FIXED_INT_MASK)
+#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE))
+#define PosFloatToFixed(X) FloatToFixed(X)
+#define SignedFloatToFixed(X) FloatToFixed(X)
+
+
+
+/*
+ * XXX these macros are just bandages for now in order to make
+ * CHAN_BITS==32 compile cleanly.
+ * These should probably go elsewhere at some point.
+ */
+#if CHAN_TYPE == GL_FLOAT
+#define ChanToFixed(X) (X)
+#define FixedToChan(X) (X)
+#else
+#define ChanToFixed(X) IntToFixed(X)
+#define FixedToChan(X) FixedToInt(X)
+#endif
+
+
+/**
+ * For looping over fragment attributes in the pointe, line
+ * triangle rasterizers.
+ */
+#define ATTRIB_LOOP_BEGIN \
+ { \
+ GLuint a; \
+ for (a = 0; a < swrast->_NumActiveAttribs; a++) { \
+ const GLuint attr = swrast->_ActiveAttribs[a];
+
+#define ATTRIB_LOOP_END } }
+
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c
new file mode 100644
index 000000000..5ecfb1e90
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_copypix.c
@@ -0,0 +1,932 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/convolve.h"
+#include "main/histogram.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/pixel.h"
+
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_span.h"
+#include "s_stencil.h"
+#include "s_zoom.h"
+
+
+
+/**
+ * Determine if there's overlap in an image copy.
+ * This test also compensates for the fact that copies are done from
+ * bottom to top and overlaps can sometimes be handled correctly
+ * without making a temporary image copy.
+ * \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
+ */
+static GLboolean
+regions_overlap(GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty,
+ GLint width, GLint height,
+ GLfloat zoomX, GLfloat zoomY)
+{
+ if (zoomX == 1.0 && zoomY == 1.0) {
+ /* no zoom */
+ if (srcx >= dstx + width || (srcx + width <= dstx)) {
+ return GL_FALSE;
+ }
+ else if (srcy < dsty) { /* this is OK */
+ return GL_FALSE;
+ }
+ else if (srcy > dsty + height) {
+ return GL_FALSE;
+ }
+ else {
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* add one pixel of slop when zooming, just to be safe */
+ if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
+ /* src is completely right of dest */
+ return GL_FALSE;
+ }
+ else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
+ /* src is completely left of dest */
+ return GL_FALSE;
+ }
+ else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
+ /* src is completely below dest */
+ return GL_FALSE;
+ }
+ else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
+ /* src is completely above dest */
+ return GL_FALSE;
+ }
+ else {
+ return GL_TRUE;
+ }
+ }
+}
+
+
+/**
+ * RGBA copypixels with convolution.
+ */
+static void
+copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLint width, GLint height, GLint destx, GLint desty)
+{
+ GLint row;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ const GLbitfield transferOps = ctx->_ImageTransferState;
+ const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
+ || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
+ GLfloat *dest, *tmpImage, *convImage;
+ SWspan span;
+
+ INIT_SPAN(span, GL_BITMAP);
+ _swrast_span_default_attribs(ctx, &span);
+ span.arrayMask = SPAN_RGBA;
+ span.arrayAttribs = FRAG_BIT_COL0;
+
+ /* allocate space for GLfloat image */
+ tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!tmpImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
+ return;
+ }
+ convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!convImage) {
+ _mesa_free(tmpImage);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
+ return;
+ }
+
+ /* read source image as float/RGBA */
+ dest = tmpImage;
+ for (row = 0; row < height; row++) {
+ _swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, srcx, srcy + row, GL_FLOAT, dest);
+ dest += 4 * width;
+ }
+
+ /* do the image transfer ops which preceed convolution */
+ for (row = 0; row < height; row++) {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4);
+ _mesa_apply_rgba_transfer_ops(ctx,
+ transferOps & IMAGE_PRE_CONVOLUTION_BITS,
+ width, rgba);
+ }
+
+ /* do convolution */
+ if (ctx->Pixel.Convolution2DEnabled) {
+ _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ else {
+ ASSERT(ctx->Pixel.Separable2DEnabled);
+ _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ _mesa_free(tmpImage);
+
+ /* do remaining post-convolution image transfer ops */
+ for (row = 0; row < height; row++) {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4);
+ _mesa_apply_rgba_transfer_ops(ctx,
+ transferOps & IMAGE_POST_CONVOLUTION_BITS,
+ width, rgba);
+ }
+
+ if (!sink) {
+ /* write the new image */
+ for (row = 0; row < height; row++) {
+ const GLfloat *src = convImage + row * width * 4;
+ GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
+
+ /* copy convolved colors into span array */
+ _mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat));
+
+ /* write span */
+ span.x = destx;
+ span.y = desty + row;
+ span.end = width;
+ span.array->ChanType = GL_FLOAT;
+ if (zoom) {
+ _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
+ }
+ else {
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ }
+ /* restore this */
+ span.array->ChanType = CHAN_TYPE;
+ }
+
+ _mesa_free(convImage);
+}
+
+
+/**
+ * RGBA copypixels
+ */
+static void
+copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
+ GLint width, GLint height, GLint destx, GLint desty)
+{
+ GLfloat *tmpImage, *p;
+ GLint sy, dy, stepy, row;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ GLint overlapping;
+ GLuint transferOps = ctx->_ImageTransferState;
+ SWspan span;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
+ copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
+ return;
+ }
+ else if (ctx->Pixel.Convolution1DEnabled) {
+ /* make sure we don't apply 1D convolution */
+ transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+ IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+ }
+
+ if (ctx->DrawBuffer == ctx->ReadBuffer) {
+ overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+ ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+ }
+ else {
+ overlapping = GL_FALSE;
+ }
+
+ /* Determine if copy should be done bottom-to-top or top-to-bottom */
+ if (!overlapping && srcy < desty) {
+ /* top-down max-to-min */
+ sy = srcy + height - 1;
+ dy = desty + height - 1;
+ stepy = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ sy = srcy;
+ dy = desty;
+ stepy = 1;
+ }
+
+ INIT_SPAN(span, GL_BITMAP);
+ _swrast_span_default_attribs(ctx, &span);
+ span.arrayMask = SPAN_RGBA;
+ span.arrayAttribs = FRAG_BIT_COL0; /* we'll fill in COL0 attrib values */
+
+ if (overlapping) {
+ tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4);
+ if (!tmpImage) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
+ return;
+ }
+ /* read the source image as RGBA/float */
+ p = tmpImage;
+ for (row = 0; row < height; row++) {
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, srcx, sy + row, GL_FLOAT, p );
+ p += width * 4;
+ }
+ p = tmpImage;
+ }
+ else {
+ tmpImage = NULL; /* silence compiler warnings */
+ p = NULL;
+ }
+
+ ASSERT(width < MAX_WIDTH);
+
+ for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
+ GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
+
+ /* Get row/span of source pixels */
+ if (overlapping) {
+ /* get from buffered image */
+ _mesa_memcpy(rgba, p, width * sizeof(GLfloat) * 4);
+ p += width * 4;
+ }
+ else {
+ /* get from framebuffer */
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, srcx, sy, GL_FLOAT, rgba );
+ }
+
+ if (transferOps) {
+ _mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
+ (GLfloat (*)[4]) rgba);
+ }
+
+ /* Write color span */
+ span.x = destx;
+ span.y = dy;
+ span.end = width;
+ span.array->ChanType = GL_FLOAT;
+ if (zoom) {
+ _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
+ }
+ else {
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ }
+
+ span.array->ChanType = CHAN_TYPE; /* restore */
+
+ if (overlapping)
+ _mesa_free(tmpImage);
+}
+
+
+static void
+copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
+ GLint width, GLint height,
+ GLint destx, GLint desty )
+{
+ GLuint *tmpImage,*p;
+ GLint sy, dy, stepy;
+ GLint j;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ GLint overlapping;
+ SWspan span;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ INIT_SPAN(span, GL_BITMAP);
+ _swrast_span_default_attribs(ctx, &span);
+ span.arrayMask = SPAN_INDEX;
+
+ if (ctx->DrawBuffer == ctx->ReadBuffer) {
+ overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+ ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+ }
+ else {
+ overlapping = GL_FALSE;
+ }
+
+ /* Determine if copy should be bottom-to-top or top-to-bottom */
+ if (!overlapping && srcy < desty) {
+ /* top-down max-to-min */
+ sy = srcy + height - 1;
+ dy = desty + height - 1;
+ stepy = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ sy = srcy;
+ dy = desty;
+ stepy = 1;
+ }
+
+ if (overlapping) {
+ GLint ssy = sy;
+ tmpImage = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
+ if (!tmpImage) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
+ return;
+ }
+ /* read the image */
+ p = tmpImage;
+ for (j = 0; j < height; j++, ssy += stepy) {
+ _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, srcx, ssy, p );
+ p += width;
+ }
+ p = tmpImage;
+ }
+ else {
+ tmpImage = NULL; /* silence compiler warning */
+ p = NULL;
+ }
+
+ for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
+ /* Get color indexes */
+ if (overlapping) {
+ _mesa_memcpy(span.array->index, p, width * sizeof(GLuint));
+ p += width;
+ }
+ else {
+ _swrast_read_index_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, srcx, sy, span.array->index );
+ }
+
+ if (ctx->_ImageTransferState)
+ _mesa_apply_ci_transfer_ops(ctx, ctx->_ImageTransferState,
+ width, span.array->index);
+
+ /* write color indexes */
+ span.x = destx;
+ span.y = dy;
+ span.end = width;
+ if (zoom)
+ _swrast_write_zoomed_index_span(ctx, destx, desty, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+ }
+
+ if (overlapping)
+ _mesa_free(tmpImage);
+}
+
+
+/**
+ * Convert floating point Z values to integer Z values with pixel transfer's
+ * Z scale and bias.
+ */
+static void
+scale_and_bias_z(GLcontext *ctx, GLuint width,
+ const GLfloat depth[], GLuint z[])
+{
+ const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
+ GLuint i;
+
+ if (depthMax <= 0xffffff &&
+ ctx->Pixel.DepthScale == 1.0 &&
+ ctx->Pixel.DepthBias == 0.0) {
+ /* no scale or bias and no clamping and no worry of overflow */
+ const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
+ for (i = 0; i < width; i++) {
+ z[i] = (GLuint) (depth[i] * depthMaxF);
+ }
+ }
+ else {
+ /* need to be careful with overflow */
+ const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
+ for (i = 0; i < width; i++) {
+ GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
+ d = CLAMP(d, 0.0, 1.0) * depthMaxF;
+ if (d >= depthMaxF)
+ z[i] = depthMax;
+ else
+ z[i] = (GLuint) d;
+ }
+ }
+}
+
+
+
+/*
+ * TODO: Optimize!!!!
+ */
+static void
+copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
+ GLint width, GLint height,
+ GLint destx, GLint desty )
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct gl_renderbuffer *readRb = fb->_DepthBuffer;
+ GLfloat *p, *tmpImage;
+ GLint sy, dy, stepy;
+ GLint j;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ GLint overlapping;
+ SWspan span;
+
+ if (!readRb) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ INIT_SPAN(span, GL_BITMAP);
+ _swrast_span_default_attribs(ctx, &span);
+ span.arrayMask = SPAN_Z;
+
+ if (ctx->DrawBuffer == ctx->ReadBuffer) {
+ overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+ ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+ }
+ else {
+ overlapping = GL_FALSE;
+ }
+
+ /* Determine if copy should be bottom-to-top or top-to-bottom */
+ if (!overlapping && srcy < desty) {
+ /* top-down max-to-min */
+ sy = srcy + height - 1;
+ dy = desty + height - 1;
+ stepy = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ sy = srcy;
+ dy = desty;
+ stepy = 1;
+ }
+
+ if (overlapping) {
+ GLint ssy = sy;
+ tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
+ if (!tmpImage) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
+ return;
+ }
+ p = tmpImage;
+ for (j = 0; j < height; j++, ssy += stepy) {
+ _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
+ p += width;
+ }
+ p = tmpImage;
+ }
+ else {
+ tmpImage = NULL; /* silence compiler warning */
+ p = NULL;
+ }
+
+ for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
+ GLfloat depth[MAX_WIDTH];
+ /* get depth values */
+ if (overlapping) {
+ _mesa_memcpy(depth, p, width * sizeof(GLfloat));
+ p += width;
+ }
+ else {
+ _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
+ }
+
+ /* apply scale and bias */
+ scale_and_bias_z(ctx, width, depth, span.array->z);
+
+ /* write depth values */
+ span.x = destx;
+ span.y = dy;
+ span.end = width;
+ if (fb->Visual.rgbMode) {
+ if (zoom)
+ _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
+ else
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ else {
+ if (zoom)
+ _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+ }
+ }
+
+ if (overlapping)
+ _mesa_free(tmpImage);
+}
+
+
+
+static void
+copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
+ GLint width, GLint height,
+ GLint destx, GLint desty )
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ GLint sy, dy, stepy;
+ GLint j;
+ GLstencil *p, *tmpImage;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ GLint overlapping;
+
+ if (!rb) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ if (ctx->DrawBuffer == ctx->ReadBuffer) {
+ overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+ ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+ }
+ else {
+ overlapping = GL_FALSE;
+ }
+
+ /* Determine if copy should be bottom-to-top or top-to-bottom */
+ if (!overlapping && srcy < desty) {
+ /* top-down max-to-min */
+ sy = srcy + height - 1;
+ dy = desty + height - 1;
+ stepy = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ sy = srcy;
+ dy = desty;
+ stepy = 1;
+ }
+
+ if (overlapping) {
+ GLint ssy = sy;
+ tmpImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
+ if (!tmpImage) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
+ return;
+ }
+ p = tmpImage;
+ for (j = 0; j < height; j++, ssy += stepy) {
+ _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
+ p += width;
+ }
+ p = tmpImage;
+ }
+ else {
+ tmpImage = NULL; /* silence compiler warning */
+ p = NULL;
+ }
+
+ for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
+ GLstencil stencil[MAX_WIDTH];
+
+ /* Get stencil values */
+ if (overlapping) {
+ _mesa_memcpy(stencil, p, width * sizeof(GLstencil));
+ p += width;
+ }
+ else {
+ _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
+ }
+
+ _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
+
+ /* Write stencil values */
+ if (zoom) {
+ _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
+ destx, dy, stencil);
+ }
+ else {
+ _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
+ }
+ }
+
+ if (overlapping)
+ _mesa_free(tmpImage);
+}
+
+
+/**
+ * This isn't terribly efficient. If a driver really has combined
+ * depth/stencil buffers the driver should implement an optimized
+ * CopyPixels function.
+ */
+static void
+copy_depth_stencil_pixels(GLcontext *ctx,
+ const GLint srcX, const GLint srcY,
+ const GLint width, const GLint height,
+ const GLint destX, const GLint destY)
+{
+ struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb;
+ GLint sy, dy, stepy;
+ GLint j;
+ GLstencil *tempStencilImage = NULL, *stencilPtr = NULL;
+ GLfloat *tempDepthImage = NULL, *depthPtr = NULL;
+ const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
+ const GLuint stencilMask = ctx->Stencil.WriteMask[0];
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+ const GLboolean scaleOrBias
+ = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
+ GLint overlapping;
+
+ depthDrawRb = ctx->DrawBuffer->_DepthBuffer;
+ depthReadRb = ctx->ReadBuffer->_DepthBuffer;
+ stencilReadRb = ctx->ReadBuffer->_StencilBuffer;
+
+ ASSERT(depthDrawRb);
+ ASSERT(depthReadRb);
+ ASSERT(stencilReadRb);
+
+ if (ctx->DrawBuffer == ctx->ReadBuffer) {
+ overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
+ ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+ }
+ else {
+ overlapping = GL_FALSE;
+ }
+
+ /* Determine if copy should be bottom-to-top or top-to-bottom */
+ if (!overlapping && srcY < destY) {
+ /* top-down max-to-min */
+ sy = srcY + height - 1;
+ dy = destY + height - 1;
+ stepy = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ sy = srcY;
+ dy = destY;
+ stepy = 1;
+ }
+
+ if (overlapping) {
+ GLint ssy = sy;
+
+ if (stencilMask != 0x0) {
+ tempStencilImage
+ = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
+ if (!tempStencilImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
+ return;
+ }
+
+ /* get copy of stencil pixels */
+ stencilPtr = tempStencilImage;
+ for (j = 0; j < height; j++, ssy += stepy) {
+ _swrast_read_stencil_span(ctx, stencilReadRb,
+ width, srcX, ssy, stencilPtr);
+ stencilPtr += width;
+ }
+ stencilPtr = tempStencilImage;
+ }
+
+ if (ctx->Depth.Mask) {
+ tempDepthImage
+ = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
+ if (!tempDepthImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
+ _mesa_free(tempStencilImage);
+ return;
+ }
+
+ /* get copy of depth pixels */
+ depthPtr = tempDepthImage;
+ for (j = 0; j < height; j++, ssy += stepy) {
+ _swrast_read_depth_span_float(ctx, depthReadRb,
+ width, srcX, ssy, depthPtr);
+ depthPtr += width;
+ }
+ depthPtr = tempDepthImage;
+ }
+ }
+
+ for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
+ if (stencilMask != 0x0) {
+ GLstencil stencil[MAX_WIDTH];
+
+ /* Get stencil values */
+ if (overlapping) {
+ _mesa_memcpy(stencil, stencilPtr, width * sizeof(GLstencil));
+ stencilPtr += width;
+ }
+ else {
+ _swrast_read_stencil_span(ctx, stencilReadRb,
+ width, srcX, sy, stencil);
+ }
+
+ _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
+
+ /* Write values */
+ if (zoom) {
+ _swrast_write_zoomed_stencil_span(ctx, destX, destY, width,
+ destX, dy, stencil);
+ }
+ else {
+ _swrast_write_stencil_span( ctx, width, destX, dy, stencil );
+ }
+ }
+
+ if (ctx->Depth.Mask) {
+ GLfloat depth[MAX_WIDTH];
+ GLuint zVals32[MAX_WIDTH];
+ GLushort zVals16[MAX_WIDTH];
+ GLvoid *zVals;
+ GLuint zBytes;
+
+ /* get depth values */
+ if (overlapping) {
+ _mesa_memcpy(depth, depthPtr, width * sizeof(GLfloat));
+ depthPtr += width;
+ }
+ else {
+ _swrast_read_depth_span_float(ctx, depthReadRb,
+ width, srcX, sy, depth);
+ }
+
+ /* scale & bias */
+ if (scaleOrBias) {
+ _mesa_scale_and_bias_depth(ctx, width, depth);
+ }
+ /* convert to integer Z values */
+ if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) {
+ GLint k;
+ for (k = 0; k < width; k++)
+ zVals16[k] = (GLushort) (depth[k] * depthScale);
+ zVals = zVals16;
+ zBytes = 2;
+ }
+ else {
+ GLint k;
+ for (k = 0; k < width; k++)
+ zVals32[k] = (GLuint) (depth[k] * depthScale);
+ zVals = zVals32;
+ zBytes = 4;
+ }
+
+ /* Write values */
+ if (zoom) {
+ _swrast_write_zoomed_z_span(ctx, destX, destY, width,
+ destX, dy, zVals);
+ }
+ else {
+ _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes);
+ }
+ }
+ }
+
+ if (tempStencilImage)
+ _mesa_free(tempStencilImage);
+
+ if (tempDepthImage)
+ _mesa_free(tempDepthImage);
+}
+
+
+
+/**
+ * Try to do a fast copy pixels.
+ */
+static GLboolean
+fast_copy_pixels(GLcontext *ctx,
+ GLint srcX, GLint srcY, GLsizei width, GLsizei height,
+ GLint dstX, GLint dstY, GLenum type)
+{
+ struct gl_framebuffer *srcFb = ctx->ReadBuffer;
+ struct gl_framebuffer *dstFb = ctx->DrawBuffer;
+ struct gl_renderbuffer *srcRb, *dstRb;
+ GLint row, yStep;
+
+ if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
+ ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F ||
+ ctx->_ImageTransferState) {
+ /* can't handle these */
+ return GL_FALSE;
+ }
+
+ if (type == GL_COLOR) {
+ if (dstFb->_NumColorDrawBuffers != 1)
+ return GL_FALSE;
+ srcRb = srcFb->_ColorReadBuffer;
+ dstRb = dstFb->_ColorDrawBuffers[0];
+ }
+ else if (type == GL_STENCIL) {
+ srcRb = srcFb->_StencilBuffer;
+ dstRb = dstFb->_StencilBuffer;
+ }
+ else if (type == GL_DEPTH) {
+ srcRb = srcFb->_DepthBuffer;
+ dstRb = dstFb->_DepthBuffer;
+ }
+ else {
+ ASSERT(type == GL_DEPTH_STENCIL_EXT);
+ /* XXX correct? */
+ srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
+ dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
+ }
+
+ /* src and dst renderbuffers must be same format and type */
+ if (!srcRb || !dstRb ||
+ srcRb->DataType != dstRb->DataType ||
+ srcRb->_BaseFormat != dstRb->_BaseFormat) {
+ return GL_FALSE;
+ }
+
+ /* clipping not supported */
+ if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
+ srcY < 0 || srcY + height > (GLint) srcFb->Height ||
+ dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
+ dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
+ return GL_FALSE;
+ }
+
+ /* overlapping src/dst doesn't matter, just determine Y direction */
+ if (srcY < dstY) {
+ /* top-down max-to-min */
+ srcY = srcY + height - 1;
+ dstY = dstY + height - 1;
+ yStep = -1;
+ }
+ else {
+ /* bottom-up min-to-max */
+ yStep = 1;
+ }
+
+ for (row = 0; row < height; row++) {
+ GLuint temp[MAX_WIDTH][4];
+ srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp);
+ dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL);
+ srcY += yStep;
+ dstY += yStep;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Do software-based glCopyPixels.
+ * By time we get here, all parameters will have been error-checked.
+ */
+void
+_swrast_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLint destx, GLint desty, GLenum type )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ swrast_render_start(ctx);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
+ switch (type) {
+ case GL_COLOR:
+ if (ctx->Visual.rgbMode) {
+ copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
+ }
+ else {
+ copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
+ }
+ break;
+ case GL_DEPTH:
+ copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
+ break;
+ case GL_STENCIL:
+ copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
+ }
+ }
+
+ swrast_render_finish(ctx);
+}
diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c
new file mode 100644
index 000000000..26e23f02d
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_depth.c
@@ -0,0 +1,1429 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2.1
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/fbobject.h"
+
+#include "s_depth.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+/**
+ * Do depth test for a horizontal span of fragments.
+ * Input: zbuffer - array of z values in the zbuffer
+ * z - array of fragment z values
+ * Return: number of fragments which pass the test.
+ */
+static GLuint
+depth_test_span16( GLcontext *ctx, GLuint n,
+ GLushort zbuffer[], const GLuint z[], GLubyte mask[] )
+{
+ 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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] < zbuffer[i]) {
+ /* pass */
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] < zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] <= zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] <= zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] >= zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] >= zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] > zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] > zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] != zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] != zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] == zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] == zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ passed = n;
+ }
+ break;
+ case GL_NEVER:
+ _mesa_bzero(mask, n * sizeof(GLubyte));
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth func in depth_test_span16");
+ }
+
+ return passed;
+}
+
+
+static GLuint
+depth_test_span32( GLcontext *ctx, GLuint n,
+ GLuint zbuffer[], const GLuint z[], GLubyte mask[] )
+{
+ 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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] < zbuffer[i]) {
+ /* pass */
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] < zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] <= zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] <= zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] >= zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] >= zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] > zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] > zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] != zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] != zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] == zbuffer[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ if (z[i] == zbuffer[i]) {
+ /* pass */
+ passed++;
+ }
+ else {
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ zbuffer[i] = z[i];
+ passed++;
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ passed = n;
+ }
+ break;
+ case GL_NEVER:
+ _mesa_bzero(mask, n * sizeof(GLubyte));
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth func in depth_test_span32");
+ }
+
+ return passed;
+}
+
+
+
+/*
+ * Apply depth test to span of fragments.
+ */
+static GLuint
+depth_test_span( GLcontext *ctx, SWspan *span)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ const GLint x = span->x;
+ const GLint y = span->y;
+ const GLuint count = span->end;
+ const GLuint *zValues = span->array->z;
+ GLubyte *mask = span->array->mask;
+ GLuint passed;
+
+ ASSERT((span->arrayMask & SPAN_XY) == 0);
+ ASSERT(span->arrayMask & SPAN_Z);
+
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Directly access buffer */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zbuffer = (GLushort *) rb->GetPointer(ctx, rb, x, y);
+ passed = depth_test_span16(ctx, count, zbuffer, zValues, mask);
+ }
+ else {
+ GLuint *zbuffer = (GLuint *) rb->GetPointer(ctx, rb, x, y);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ passed = depth_test_span32(ctx, count, zbuffer, zValues, mask);
+ }
+ }
+ else {
+ /* read depth values from buffer, test, write back */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort zbuffer[MAX_WIDTH];
+ rb->GetRow(ctx, rb, count, x, y, zbuffer);
+ passed = depth_test_span16(ctx, count, zbuffer, zValues, mask);
+ rb->PutRow(ctx, rb, count, x, y, zbuffer, mask);
+ }
+ else {
+ GLuint zbuffer[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ rb->GetRow(ctx, rb, count, x, y, zbuffer);
+ passed = depth_test_span32(ctx, count, zbuffer, zValues, mask);
+ rb->PutRow(ctx, rb, count, x, y, zbuffer, mask);
+ }
+ }
+
+ if (passed < count) {
+ span->writeAll = GL_FALSE;
+ }
+ return passed;
+}
+
+
+
+#define Z_ADDRESS(X, Y) (zStart + (Y) * stride + (X))
+
+
+/*
+ * Do depth testing for an array of fragments at assorted locations.
+ */
+static void
+direct_depth_test_pixels16(GLcontext *ctx, GLushort *zStart, GLuint stride,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint z[], GLubyte mask[] )
+{
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] <= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] >= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] > *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] != *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] == *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
+ *zptr = z[i];
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ }
+ break;
+ case GL_NEVER:
+ /* depth test never passes */
+ _mesa_bzero(mask, n * sizeof(GLubyte));
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth func in direct_depth_test_pixels");
+ }
+}
+
+
+
+/*
+ * Do depth testing for an array of fragments with direct access to zbuffer.
+ */
+static void
+direct_depth_test_pixels32(GLcontext *ctx, GLuint *zStart, GLuint stride,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint z[], GLubyte mask[] )
+{
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] <= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] >= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] > *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] != *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ if (z[i] == *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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 */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
+ *zptr = z[i];
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ }
+ break;
+ case GL_NEVER:
+ /* depth test never passes */
+ _mesa_bzero(mask, n * sizeof(GLubyte));
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth func in direct_depth_test_pixels");
+ }
+}
+
+
+
+
+static GLuint
+depth_test_pixels( GLcontext *ctx, SWspan *span )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ const GLuint count = span->end;
+ const GLint *x = span->array->x;
+ const GLint *y = span->array->y;
+ const GLuint *z = span->array->z;
+ GLubyte *mask = span->array->mask;
+
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Directly access values */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zStart = (GLushort *) rb->Data;
+ GLuint stride = rb->Width;
+ direct_depth_test_pixels16(ctx, zStart, stride, count, x, y, z, mask);
+ }
+ else {
+ GLuint *zStart = (GLuint *) rb->Data;
+ GLuint stride = rb->Width;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ direct_depth_test_pixels32(ctx, zStart, stride, count, x, y, z, mask);
+ }
+ }
+ else {
+ /* read depth values from buffer, test, write back */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort zbuffer[MAX_WIDTH];
+ _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLushort));
+ depth_test_span16(ctx, count, zbuffer, z, mask);
+ rb->PutValues(ctx, rb, count, x, y, zbuffer, mask);
+ }
+ else {
+ GLuint zbuffer[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLuint));
+ depth_test_span32(ctx, count, zbuffer, z, mask);
+ rb->PutValues(ctx, rb, count, x, y, zbuffer, mask);
+ }
+ }
+
+ return count; /* not really correct, but OK */
+}
+
+
+/**
+ * Apply depth (Z) buffer testing to the span.
+ * \return approx number of pixels that passed (only zero is reliable)
+ */
+GLuint
+_swrast_depth_test_span( GLcontext *ctx, SWspan *span)
+{
+ if (span->arrayMask & SPAN_XY)
+ return depth_test_pixels(ctx, span);
+ else
+ return depth_test_span(ctx, span);
+}
+
+
+/**
+ * GL_EXT_depth_bounds_test extension.
+ * Discard fragments depending on whether the corresponding Z-buffer
+ * values are outside the depth bounds test range.
+ * Note: we test the Z buffer values, not the fragment Z values!
+ * \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass
+ */
+GLboolean
+_swrast_depth_bounds_test( GLcontext *ctx, SWspan *span )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ GLuint zMin = (GLuint) (ctx->Depth.BoundsMin * fb->_DepthMaxF + 0.5F);
+ GLuint zMax = (GLuint) (ctx->Depth.BoundsMax * fb->_DepthMaxF + 0.5F);
+ GLubyte *mask = span->array->mask;
+ const GLuint count = span->end;
+ GLuint i;
+ GLboolean anyPass = GL_FALSE;
+
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ /* get 16-bit values */
+ GLushort zbuffer16[MAX_WIDTH], *zbuffer;
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+ zbuffer16, sizeof(GLushort));
+ zbuffer = zbuffer16;
+ }
+ else {
+ zbuffer = (GLushort*) rb->GetPointer(ctx, rb, span->x, span->y);
+ if (!zbuffer) {
+ rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer16);
+ zbuffer = zbuffer16;
+ }
+ }
+ assert(zbuffer);
+
+ /* Now do the tests */
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ if (zbuffer[i] < zMin || zbuffer[i] > zMax)
+ mask[i] = GL_FALSE;
+ else
+ anyPass = GL_TRUE;
+ }
+ }
+ }
+ else {
+ /* get 32-bit values */
+ GLuint zbuffer32[MAX_WIDTH], *zbuffer;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+ zbuffer32, sizeof(GLuint));
+ zbuffer = zbuffer32;
+ }
+ else {
+ zbuffer = (GLuint*) rb->GetPointer(ctx, rb, span->x, span->y);
+ if (!zbuffer) {
+ rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer32);
+ zbuffer = zbuffer32;
+ }
+ }
+ assert(zbuffer);
+
+ /* Now do the tests */
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ if (zbuffer[i] < zMin || zbuffer[i] > zMax)
+ mask[i] = GL_FALSE;
+ else
+ anyPass = GL_TRUE;
+ }
+ }
+ }
+
+ return anyPass;
+}
+
+
+
+/**********************************************************************/
+/***** Read Depth Buffer *****/
+/**********************************************************************/
+
+
+/**
+ * Read a span of depth values from the given depth renderbuffer, returning
+ * the values as GLfloats.
+ * This function does clipping to prevent reading outside the depth buffer's
+ * bounds. Though the clipping is redundant when we're called from
+ * _swrast_ReadPixels.
+ */
+void
+_swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLfloat depth[] )
+{
+ const GLfloat scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+
+ if (!rb) {
+ /* really only doing this to prevent FP exceptions later */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ }
+
+ ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
+ /* span is completely outside framebuffer */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ return;
+ }
+
+ if (x < 0) {
+ GLint dx = -x;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[i] = 0.0;
+ x = 0;
+ n -= dx;
+ depth += dx;
+ }
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - (GLint) rb->Width;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[n - i - 1] = 0.0;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ if (rb->DataType == GL_UNSIGNED_INT) {
+ GLuint temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ for (i = 0; i < n; i++) {
+ depth[i] = temp[i] * scale;
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ for (i = 0; i < n; i++) {
+ depth[i] = temp[i] * scale;
+ }
+ }
+ else {
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
+ }
+}
+
+
+/**
+ * As above, but return 32-bit GLuint values.
+ */
+void
+_swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLuint depth[] )
+{
+ if (!rb) {
+ /* really only doing this to prevent FP exceptions later */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ }
+
+ ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
+ /* span is completely outside framebuffer */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ return;
+ }
+
+ if (x < 0) {
+ GLint dx = -x;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[i] = 0;
+ x = 0;
+ n -= dx;
+ depth += dx;
+ }
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - (GLint) rb->Width;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[n - i - 1] = 0;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ if (rb->DataType == GL_UNSIGNED_INT) {
+ rb->GetRow(ctx, rb, n, x, y, depth);
+ if (rb->DepthBits < 32) {
+ GLuint shift = 32 - rb->DepthBits;
+ GLint i;
+ for (i = 0; i < n; i++) {
+ GLuint z = depth[i];
+ depth[i] = z << shift; /* XXX lsb bits? */
+ }
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ if (rb->DepthBits == 16) {
+ for (i = 0; i < n; i++) {
+ GLuint z = temp[i];
+ depth[i] = (z << 16) | z;
+ }
+ }
+ else {
+ GLuint shift = 16 - rb->DepthBits;
+ for (i = 0; i < n; i++) {
+ GLuint z = temp[i];
+ depth[i] = (z << (shift + 16)) | (z << shift); /* XXX lsb bits? */
+ }
+ }
+ }
+ else {
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
+ }
+}
+
+
+
+/**
+ * Clear the given z/depth renderbuffer.
+ */
+void
+_swrast_clear_depth_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
+{
+ GLuint clearValue;
+ GLint x, y, width, height;
+
+ if (!rb || !ctx->Depth.Mask) {
+ /* no depth buffer, or writing to it is disabled */
+ return;
+ }
+
+ /* compute integer clearing value */
+ if (ctx->Depth.Clear == 1.0) {
+ clearValue = ctx->DrawBuffer->_DepthMax;
+ }
+ else {
+ clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF);
+ }
+
+ assert(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ /* compute region to clear */
+ x = ctx->DrawBuffer->_Xmin;
+ y = ctx->DrawBuffer->_Ymin;
+ width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Direct buffer access is possible. Either this is just malloc'd
+ * memory, or perhaps the driver mmap'd the zbuffer memory.
+ */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ if ((clearValue & 0xff) == ((clearValue >> 8) & 0xff) &&
+ ((GLushort *) rb->GetPointer(ctx, rb, 0, 0) + width ==
+ (GLushort *) rb->GetPointer(ctx, rb, 0, 1))) {
+ /* optimized case */
+ GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y);
+ GLuint len = width * height * sizeof(GLushort);
+ _mesa_memset(dst, (clearValue & 0xff), len);
+ }
+ else {
+ /* general case */
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ dst[j] = clearValue;
+ }
+ }
+ }
+ }
+ else {
+ GLint i, j;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (i = 0; i < height; i++) {
+ GLuint *dst = (GLuint *) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ dst[j] = clearValue;
+ }
+ }
+ }
+ }
+ else {
+ /* Direct access not possible. Use PutRow to write new values. */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort clearVal16 = (GLushort) (clearValue & 0xffff);
+ GLint i;
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, &clearVal16, NULL);
+ }
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ GLint i;
+ ASSERT(sizeof(clearValue) == sizeof(GLuint));
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, &clearValue, NULL);
+ }
+ }
+ else {
+ _mesa_problem(ctx, "bad depth renderbuffer DataType");
+ }
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_depth.h b/mesalib/src/mesa/swrast/s_depth.h
new file mode 100644
index 000000000..368862568
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_depth.h
@@ -0,0 +1,55 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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 S_DEPTH_H
+#define S_DEPTH_H
+
+
+#include "s_context.h"
+
+
+extern GLuint
+_swrast_depth_test_span( GLcontext *ctx, SWspan *span);
+
+
+extern GLboolean
+_swrast_depth_bounds_test( GLcontext *ctx, SWspan *span );
+
+
+extern void
+_swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLfloat depth[] );
+
+
+extern void
+_swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLuint depth[] );
+
+
+extern void
+_swrast_clear_depth_buffer( GLcontext *ctx, struct gl_renderbuffer *rb );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c
new file mode 100644
index 000000000..6970b2e9c
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_drawpix.c
@@ -0,0 +1,898 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/convolve.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/pixel.h"
+#include "main/state.h"
+
+#include "s_context.h"
+#include "s_span.h"
+#include "s_stencil.h"
+#include "s_zoom.h"
+
+
+
+/**
+ * Try to do a fast and simple RGB(a) glDrawPixels.
+ * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
+ */
+static GLboolean
+fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *userUnpack,
+ const GLvoid *pixels)
+{
+ const GLint imgX = x, imgY = y;
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ GLenum rbType;
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ SWspan span;
+ GLboolean simpleZoom;
+ GLint yStep; /* +1 or -1 */
+ struct gl_pixelstore_attrib unpack;
+ GLint destX, destY, drawWidth, drawHeight; /* post clipping */
+
+ if (!rb)
+ return GL_TRUE; /* no-op */
+
+ rbType = rb->DataType;
+
+ if ((swrast->_RasterMask & ~CLIP_BIT) ||
+ ctx->Texture._EnabledCoordUnits ||
+ userUnpack->SwapBytes ||
+ ctx->_ImageTransferState) {
+ /* can't handle any of those conditions */
+ return GL_FALSE;
+ }
+
+ INIT_SPAN(span, GL_BITMAP);
+ span.arrayMask = SPAN_RGBA;
+ span.arrayAttribs = FRAG_BIT_COL0;
+ _swrast_span_default_attribs(ctx, &span);
+
+ /* copy input params since clipping may change them */
+ unpack = *userUnpack;
+ destX = x;
+ destY = y;
+ drawWidth = width;
+ drawHeight = height;
+
+ /* check for simple zooming and clipping */
+ if (ctx->Pixel.ZoomX == 1.0F &&
+ (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) {
+ if (!_mesa_clip_drawpixels(ctx, &destX, &destY,
+ &drawWidth, &drawHeight, &unpack)) {
+ /* image was completely clipped: no-op, all done */
+ return GL_TRUE;
+ }
+ simpleZoom = GL_TRUE;
+ yStep = (GLint) ctx->Pixel.ZoomY;
+ ASSERT(yStep == 1 || yStep == -1);
+ }
+ else {
+ /* non-simple zooming */
+ simpleZoom = GL_FALSE;
+ yStep = 1;
+ if (unpack.RowLength == 0)
+ unpack.RowLength = width;
+ }
+
+ /*
+ * Ready to draw!
+ */
+
+ if (format == GL_RGBA && type == rbType) {
+ const GLubyte *src
+ = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
+ height, format, type, 0, 0);
+ const GLint srcStride = _mesa_image_row_stride(&unpack, width,
+ format, type);
+ if (simpleZoom) {
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
+ src += srcStride;
+ destY += yStep;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ span.x = destX;
+ span.y = destY + row;
+ span.end = drawWidth;
+ span.array->ChanType = rbType;
+ _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
+ src += srcStride;
+ }
+ span.array->ChanType = CHAN_TYPE;
+ }
+ return GL_TRUE;
+ }
+
+ if (format == GL_RGB && type == rbType) {
+ const GLubyte *src
+ = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
+ height, format, type, 0, 0);
+ const GLint srcStride = _mesa_image_row_stride(&unpack, width,
+ format, type);
+ if (simpleZoom) {
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
+ src += srcStride;
+ destY += yStep;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ span.x = destX;
+ span.y = destY;
+ span.end = drawWidth;
+ span.array->ChanType = rbType;
+ _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
+ src += srcStride;
+ destY++;
+ }
+ span.array->ChanType = CHAN_TYPE;
+ }
+ return GL_TRUE;
+ }
+
+ /* Remaining cases haven't been tested with alignment != 1 */
+ if (userUnpack->Alignment != 1)
+ return GL_FALSE;
+
+ if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
+ const GLchan *src = (const GLchan *) pixels
+ + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
+ if (simpleZoom) {
+ /* no zooming */
+ GLint row;
+ ASSERT(drawWidth <= MAX_WIDTH);
+ for (row = 0; row < drawHeight; row++) {
+ GLchan rgb[MAX_WIDTH][3];
+ GLint i;
+ for (i = 0;i<drawWidth;i++) {
+ rgb[i][0] = src[i];
+ rgb[i][1] = src[i];
+ rgb[i][2] = src[i];
+ }
+ rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL);
+ src += unpack.RowLength;
+ destY += yStep;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ ASSERT(drawWidth <= MAX_WIDTH);
+ for (row = 0; row < drawHeight; row++) {
+ GLchan rgb[MAX_WIDTH][3];
+ GLint i;
+ for (i = 0;i<drawWidth;i++) {
+ rgb[i][0] = src[i];
+ rgb[i][1] = src[i];
+ rgb[i][2] = src[i];
+ }
+ span.x = destX;
+ span.y = destY;
+ span.end = drawWidth;
+ _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb);
+ src += unpack.RowLength;
+ destY++;
+ }
+ }
+ return GL_TRUE;
+ }
+
+ if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
+ const GLchan *src = (const GLchan *) pixels
+ + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2;
+ if (simpleZoom) {
+ GLint row;
+ ASSERT(drawWidth <= MAX_WIDTH);
+ for (row = 0; row < drawHeight; row++) {
+ GLint i;
+ const GLchan *ptr = src;
+ for (i = 0;i<drawWidth;i++) {
+ span.array->rgba[i][0] = *ptr;
+ span.array->rgba[i][1] = *ptr;
+ span.array->rgba[i][2] = *ptr++;
+ span.array->rgba[i][3] = *ptr++;
+ }
+ rb->PutRow(ctx, rb, drawWidth, destX, destY,
+ span.array->rgba, NULL);
+ src += unpack.RowLength*2;
+ destY += yStep;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ ASSERT(drawWidth <= MAX_WIDTH);
+ for (row = 0; row < drawHeight; row++) {
+ const GLchan *ptr = src;
+ GLint i;
+ for (i = 0;i<drawWidth;i++) {
+ span.array->rgba[i][0] = *ptr;
+ span.array->rgba[i][1] = *ptr;
+ span.array->rgba[i][2] = *ptr++;
+ span.array->rgba[i][3] = *ptr++;
+ }
+ span.x = destX;
+ span.y = destY;
+ span.end = drawWidth;
+ _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
+ span.array->rgba);
+ src += unpack.RowLength*2;
+ destY++;
+ }
+ }
+ return GL_TRUE;
+ }
+
+ if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) {
+ const GLubyte *src = (const GLubyte *) pixels
+ + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels;
+ if (ctx->Visual.rgbMode && rbType == GL_UNSIGNED_BYTE) {
+ /* convert ubyte/CI data to ubyte/RGBA */
+ if (simpleZoom) {
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ ASSERT(drawWidth <= MAX_WIDTH);
+ _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
+ span.array->rgba8);
+ rb->PutRow(ctx, rb, drawWidth, destX, destY,
+ span.array->rgba8, NULL);
+ src += unpack.RowLength;
+ destY += yStep;
+ }
+ }
+ else {
+ /* ubyte/CI to ubyte/RGBA with zooming */
+ GLint row;
+ for (row = 0; row < drawHeight; row++) {
+ ASSERT(drawWidth <= MAX_WIDTH);
+ _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
+ span.array->rgba8);
+ span.x = destX;
+ span.y = destY;
+ span.end = drawWidth;
+ _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
+ span.array->rgba8);
+ src += unpack.RowLength;
+ destY++;
+ }
+ }
+ return GL_TRUE;
+ }
+ else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) {
+ /* write CI data to CI frame buffer */
+ GLint row;
+ if (simpleZoom) {
+ for (row = 0; row < drawHeight; row++) {
+ GLuint index32[MAX_WIDTH];
+ GLint col;
+ for (col = 0; col < drawWidth; col++)
+ index32[col] = src[col];
+ rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL);
+ src += unpack.RowLength;
+ destY += yStep;
+ }
+ return GL_TRUE;
+ }
+ }
+ }
+
+ /* can't handle this pixel format and/or data type */
+ return GL_FALSE;
+}
+
+
+
+/*
+ * Draw color index image.
+ */
+static void
+draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const GLint imgX = x, imgY = y;
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+ GLint row, skipPixels;
+ SWspan span;
+
+ INIT_SPAN(span, GL_BITMAP);
+ span.arrayMask = SPAN_INDEX;
+ _swrast_span_default_attribs(ctx, &span);
+
+ /*
+ * General solution
+ */
+ skipPixels = 0;
+ while (skipPixels < width) {
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ ASSERT(spanWidth <= MAX_WIDTH);
+ for (row = 0; row < height; row++) {
+ const GLvoid *source = _mesa_image_address2d(unpack, pixels,
+ width, height,
+ GL_COLOR_INDEX, type,
+ row, skipPixels);
+ _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT,
+ span.array->index, type, source, unpack,
+ ctx->_ImageTransferState);
+
+ /* These may get changed during writing/clipping */
+ span.x = x + skipPixels;
+ span.y = y + row;
+ span.end = spanWidth;
+
+ if (zoom)
+ _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span);
+ else
+ _swrast_write_index_span(ctx, &span);
+ }
+ skipPixels += spanWidth;
+ }
+}
+
+
+
+/*
+ * Draw stencil image.
+ */
+static void
+draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+ GLint skipPixels;
+
+ /* if width > MAX_WIDTH, have to process image in chunks */
+ skipPixels = 0;
+ while (skipPixels < width) {
+ const GLint spanX = x + skipPixels;
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ GLint row;
+ for (row = 0; row < height; row++) {
+ const GLint spanY = y + row;
+ GLstencil values[MAX_WIDTH];
+ GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
+ ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
+ const GLvoid *source = _mesa_image_address2d(unpack, pixels,
+ width, height,
+ GL_COLOR_INDEX, type,
+ row, skipPixels);
+ _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
+ type, source, unpack,
+ ctx->_ImageTransferState);
+ if (zoom) {
+ _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
+ spanX, spanY, values);
+ }
+ else {
+ _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
+ }
+ }
+ skipPixels += spanWidth;
+ }
+}
+
+
+/*
+ * Draw depth image.
+ */
+static void
+draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const GLboolean scaleOrBias
+ = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+ SWspan span;
+
+ INIT_SPAN(span, GL_BITMAP);
+ span.arrayMask = SPAN_Z;
+ _swrast_span_default_attribs(ctx, &span);
+
+ if (type == GL_UNSIGNED_SHORT
+ && ctx->DrawBuffer->Visual.depthBits == 16
+ && !scaleOrBias
+ && !zoom
+ && ctx->Visual.rgbMode
+ && width <= MAX_WIDTH
+ && !unpack->SwapBytes) {
+ /* Special case: directly write 16-bit depth values */
+ GLint row;
+ for (row = 0; row < height; row++) {
+ const GLushort *zSrc = (const GLushort *)
+ _mesa_image_address2d(unpack, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, row, 0);
+ GLint i;
+ for (i = 0; i < width; i++)
+ span.array->z[i] = zSrc[i];
+ span.x = x;
+ span.y = y + row;
+ span.end = width;
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ }
+ else if (type == GL_UNSIGNED_INT
+ && !scaleOrBias
+ && !zoom
+ && ctx->Visual.rgbMode
+ && width <= MAX_WIDTH
+ && !unpack->SwapBytes) {
+ /* Special case: shift 32-bit values down to Visual.depthBits */
+ const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
+ GLint row;
+ for (row = 0; row < height; row++) {
+ const GLuint *zSrc = (const GLuint *)
+ _mesa_image_address2d(unpack, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, row, 0);
+ if (shift == 0) {
+ _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint));
+ }
+ else {
+ GLint col;
+ for (col = 0; col < width; col++)
+ span.array->z[col] = zSrc[col] >> shift;
+ }
+ span.x = x;
+ span.y = y + row;
+ span.end = width;
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ }
+ else {
+ /* General case */
+ const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
+ GLint skipPixels = 0;
+
+ /* in case width > MAX_WIDTH do the copy in chunks */
+ while (skipPixels < width) {
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ GLint row;
+ ASSERT(span.end <= MAX_WIDTH);
+ for (row = 0; row < height; row++) {
+ const GLvoid *zSrc = _mesa_image_address2d(unpack,
+ pixels, width, height,
+ GL_DEPTH_COMPONENT, type,
+ row, skipPixels);
+
+ /* Set these for each row since the _swrast_write_* function may
+ * change them while clipping.
+ */
+ span.x = x + skipPixels;
+ span.y = y + row;
+ span.end = spanWidth;
+
+ _mesa_unpack_depth_span(ctx, spanWidth,
+ GL_UNSIGNED_INT, span.array->z, depthMax,
+ type, zSrc, unpack);
+ if (zoom) {
+ _swrast_write_zoomed_depth_span(ctx, x, y, &span);
+ }
+ else if (ctx->Visual.rgbMode) {
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ else {
+ _swrast_write_index_span(ctx, &span);
+ }
+ }
+ skipPixels += spanWidth;
+ }
+ }
+}
+
+
+
+/**
+ * Draw RGBA image.
+ */
+static void
+draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const GLint imgX = x, imgY = y;
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+ GLfloat *convImage = NULL;
+ GLbitfield transferOps = ctx->_ImageTransferState;
+ SWspan span;
+
+ /* Try an optimized glDrawPixels first */
+ if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
+ unpack, pixels)) {
+ return;
+ }
+
+ INIT_SPAN(span, GL_BITMAP);
+ _swrast_span_default_attribs(ctx, &span);
+ span.arrayMask = SPAN_RGBA;
+ span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */
+
+ if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
+ /* Convolution has to be handled specially. We'll create an
+ * intermediate image, applying all pixel transfer operations
+ * up to convolution. Then we'll convolve the image. Then
+ * we'll proceed with the rest of the transfer operations and
+ * rasterize the image.
+ */
+ GLint row;
+ GLfloat *dest, *tmpImage;
+
+ tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!tmpImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+ convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!convImage) {
+ _mesa_free(tmpImage);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+ return;
+ }
+
+ /* Unpack the image and apply transfer ops up to convolution */
+ dest = tmpImage;
+ for (row = 0; row < height; row++) {
+ const GLvoid *source = _mesa_image_address2d(unpack,
+ pixels, width, height, format, type, row, 0);
+ _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest,
+ format, type, source, unpack,
+ transferOps & IMAGE_PRE_CONVOLUTION_BITS);
+ dest += width * 4;
+ }
+
+ /* do convolution */
+ if (ctx->Pixel.Convolution2DEnabled) {
+ _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ else {
+ ASSERT(ctx->Pixel.Separable2DEnabled);
+ _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ _mesa_free(tmpImage);
+
+ /* continue transfer ops and draw the convolved image */
+ unpack = &ctx->DefaultPacking;
+ pixels = convImage;
+ format = GL_RGBA;
+ type = GL_FLOAT;
+ transferOps &= IMAGE_POST_CONVOLUTION_BITS;
+ }
+ else if (ctx->Pixel.Convolution1DEnabled) {
+ /* we only want to apply 1D convolution to glTexImage1D */
+ transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+ IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+ }
+
+ if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 &&
+ ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT &&
+ ctx->Color.ClampFragmentColor != GL_FALSE) {
+ /* need to clamp colors before applying fragment ops */
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+
+ /*
+ * General solution
+ */
+ {
+ const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
+ || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
+ const GLbitfield interpMask = span.interpMask;
+ const GLbitfield arrayMask = span.arrayMask;
+ const GLint srcStride
+ = _mesa_image_row_stride(unpack, width, format, type);
+ GLint skipPixels = 0;
+ /* use span array for temp color storage */
+ GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
+
+ /* if the span is wider than MAX_WIDTH we have to do it in chunks */
+ while (skipPixels < width) {
+ const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+ const GLubyte *source
+ = (const GLubyte *) _mesa_image_address2d(unpack, pixels,
+ width, height, format,
+ type, 0, skipPixels);
+ GLint row;
+
+ for (row = 0; row < height; row++) {
+ /* get image row as float/RGBA */
+ _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
+ format, type, source, unpack,
+ transferOps);
+ /* draw the span */
+ if (!sink) {
+ /* Set these for each row since the _swrast_write_* functions
+ * may change them while clipping/rendering.
+ */
+ span.array->ChanType = GL_FLOAT;
+ span.x = x + skipPixels;
+ span.y = y + row;
+ span.end = spanWidth;
+ span.arrayMask = arrayMask;
+ span.interpMask = interpMask;
+ if (zoom) {
+ _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
+ }
+ else {
+ _swrast_write_rgba_span(ctx, &span);
+ }
+ }
+
+ source += srcStride;
+ } /* for row */
+
+ skipPixels += spanWidth;
+ } /* while skipPixels < width */
+
+ /* XXX this is ugly/temporary, to undo above change */
+ span.array->ChanType = CHAN_TYPE;
+ }
+
+ if (convImage) {
+ _mesa_free(convImage);
+ }
+}
+
+
+/**
+ * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
+ * The only per-pixel operations that apply are depth scale/bias,
+ * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
+ * and pixel zoom.
+ * Also, only the depth buffer and stencil buffers are touched, not the
+ * color buffer(s).
+ */
+static void
+draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ const GLint imgX = x, imgY = y;
+ const GLboolean scaleOrBias
+ = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
+ const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
+ const GLuint stencilMask = ctx->Stencil.WriteMask[0];
+ const GLuint stencilType = (STENCIL_BITS == 8) ?
+ GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
+ const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+ struct gl_renderbuffer *depthRb, *stencilRb;
+ struct gl_pixelstore_attrib clippedUnpack = *unpack;
+
+ if (!zoom) {
+ if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
+ &clippedUnpack)) {
+ /* totally clipped */
+ return;
+ }
+ }
+
+ depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ ASSERT(depthRb);
+ ASSERT(stencilRb);
+
+ if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
+ stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
+ depthRb == stencilRb &&
+ !scaleOrBias &&
+ !zoom &&
+ ctx->Depth.Mask &&
+ (stencilMask & 0xff) == 0xff) {
+ /* This is the ideal case.
+ * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
+ * Plus, no pixel transfer ops, zooming, or masking needed.
+ */
+ GLint i;
+ for (i = 0; i < height; i++) {
+ const GLuint *src = (const GLuint *)
+ _mesa_image_address2d(&clippedUnpack, pixels, width, height,
+ GL_DEPTH_STENCIL_EXT, type, i, 0);
+ depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL);
+ }
+ }
+ else {
+ /* sub-optimal cases:
+ * Separate depth/stencil buffers, or pixel transfer ops required.
+ */
+ /* XXX need to handle very wide images (skippixels) */
+ GLint i;
+
+ depthRb = ctx->DrawBuffer->_DepthBuffer;
+ stencilRb = ctx->DrawBuffer->_StencilBuffer;
+
+ for (i = 0; i < height; i++) {
+ const GLuint *depthStencilSrc = (const GLuint *)
+ _mesa_image_address2d(&clippedUnpack, pixels, width, height,
+ GL_DEPTH_STENCIL_EXT, type, i, 0);
+
+ if (ctx->Depth.Mask) {
+ if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) {
+ /* fast path 24-bit zbuffer */
+ GLuint zValues[MAX_WIDTH];
+ GLint j;
+ ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
+ for (j = 0; j < width; j++) {
+ zValues[j] = depthStencilSrc[j] >> 8;
+ }
+ if (zoom)
+ _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
+ x, y + i, zValues);
+ else
+ depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
+ }
+ else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) {
+ /* fast path 16-bit zbuffer */
+ GLushort zValues[MAX_WIDTH];
+ GLint j;
+ ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
+ for (j = 0; j < width; j++) {
+ zValues[j] = depthStencilSrc[j] >> 16;
+ }
+ if (zoom)
+ _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
+ x, y + i, zValues);
+ else
+ depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
+ }
+ else {
+ /* general case */
+ GLuint zValues[MAX_WIDTH]; /* 16 or 32-bit Z value storage */
+ _mesa_unpack_depth_span(ctx, width,
+ depthRb->DataType, zValues, depthMax,
+ type, depthStencilSrc, &clippedUnpack);
+ if (zoom) {
+ _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
+ y + i, zValues);
+ }
+ else {
+ depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
+ }
+ }
+ }
+
+ if (stencilMask != 0x0) {
+ GLstencil stencilValues[MAX_WIDTH];
+ /* get stencil values, with shift/offset/mapping */
+ _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
+ type, depthStencilSrc, &clippedUnpack,
+ ctx->_ImageTransferState);
+ if (zoom)
+ _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
+ x, y + i, stencilValues);
+ else
+ _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
+ }
+ }
+ }
+}
+
+
+/**
+ * Execute software-based glDrawPixels.
+ * By time we get here, all error checking will have been done.
+ */
+void
+_swrast_DrawPixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLboolean save_vp_override = ctx->VertexProgram._Overriden;
+
+ /* We are creating fragments directly, without going through vertex
+ * programs.
+ *
+ * This override flag tells the fragment processing code that its input
+ * comes from a non-standard source, and it may therefore not rely on
+ * optimizations that assume e.g. constant color if there is no color
+ * vertex array.
+ */
+ _mesa_set_vp_override(ctx, GL_TRUE);
+
+ swrast_render_start(ctx);
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
+ if (!pixels) {
+ swrast_render_finish(ctx);
+ _mesa_set_vp_override(ctx, save_vp_override);
+ return;
+ }
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
+ break;
+ case GL_DEPTH_COMPONENT:
+ draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
+ break;
+ case GL_COLOR_INDEX:
+ if (ctx->Visual.rgbMode)
+ draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels);
+ else
+ draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels);
+ break;
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ draw_depth_stencil_pixels(ctx, x, y, width, height,
+ type, unpack, pixels);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels");
+ /* don't return yet, clean-up */
+ }
+
+ swrast_render_finish(ctx);
+ _mesa_set_vp_override(ctx, save_vp_override);
+
+ _mesa_unmap_pbo_source(ctx, unpack);
+}
diff --git a/mesalib/src/mesa/swrast/s_feedback.c b/mesalib/src/mesa/swrast/s_feedback.c
new file mode 100644
index 000000000..47ed25ee1
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_feedback.c
@@ -0,0 +1,140 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/feedback.h"
+#include "main/macros.h"
+
+#include "s_context.h"
+#include "s_feedback.h"
+#include "s_triangle.h"
+
+
+
+static void
+feedback_vertex(GLcontext * ctx, const SWvertex * v, const SWvertex * pv)
+{
+ GLfloat win[4];
+ const GLfloat *vtc = v->attrib[FRAG_ATTRIB_TEX0];
+ const GLfloat *color = v->attrib[FRAG_ATTRIB_COL0];
+
+ win[0] = v->attrib[FRAG_ATTRIB_WPOS][0];
+ win[1] = v->attrib[FRAG_ATTRIB_WPOS][1];
+ win[2] = v->attrib[FRAG_ATTRIB_WPOS][2] / ctx->DrawBuffer->_DepthMaxF;
+ win[3] = 1.0F / v->attrib[FRAG_ATTRIB_WPOS][3];
+
+ _mesa_feedback_vertex(ctx, win, color, v->attrib[FRAG_ATTRIB_CI][0], vtc);
+}
+
+
+/*
+ * Put triangle in feedback buffer.
+ */
+void
+_swrast_feedback_triangle(GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2)
+{
+ if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POLYGON_TOKEN);
+ _mesa_feedback_token(ctx, (GLfloat) 3); /* three vertices */
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ feedback_vertex(ctx, v0, v0);
+ feedback_vertex(ctx, v1, v1);
+ feedback_vertex(ctx, v2, v2);
+ }
+ else {
+ feedback_vertex(ctx, v0, v2);
+ feedback_vertex(ctx, v1, v2);
+ feedback_vertex(ctx, v2, v2);
+ }
+ }
+}
+
+
+void
+_swrast_feedback_line(GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1)
+{
+ GLenum token = GL_LINE_TOKEN;
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (swrast->StippleCounter == 0)
+ token = GL_LINE_RESET_TOKEN;
+
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) token);
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ feedback_vertex(ctx, v0, v0);
+ feedback_vertex(ctx, v1, v1);
+ }
+ else {
+ feedback_vertex(ctx, v0, v1);
+ feedback_vertex(ctx, v1, v1);
+ }
+
+ swrast->StippleCounter++;
+}
+
+
+void
+_swrast_feedback_point(GLcontext *ctx, const SWvertex *v)
+{
+ _mesa_feedback_token(ctx, (GLfloat) (GLint) GL_POINT_TOKEN);
+ feedback_vertex(ctx, v, v);
+}
+
+
+void
+_swrast_select_triangle(GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2)
+{
+ if (!_swrast_culltriangle(ctx, v0, v1, v2)) {
+ const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+
+ _mesa_update_hitflag( ctx, v0->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+ _mesa_update_hitflag( ctx, v1->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+ _mesa_update_hitflag( ctx, v2->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+ }
+}
+
+
+void
+_swrast_select_line(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1)
+{
+ const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ _mesa_update_hitflag( ctx, v0->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+ _mesa_update_hitflag( ctx, v1->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+}
+
+
+void
+_swrast_select_point(GLcontext *ctx, const SWvertex *v)
+{
+ const GLfloat zs = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+ _mesa_update_hitflag( ctx, v->attrib[FRAG_ATTRIB_WPOS][2] * zs );
+}
diff --git a/mesalib/src/mesa/swrast/s_feedback.h b/mesalib/src/mesa/swrast/s_feedback.h
new file mode 100644
index 000000000..9feab75db
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_feedback.h
@@ -0,0 +1,50 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_FEEDBACK_H
+#define S_FEEDBACK_H
+
+
+#include "swrast.h"
+
+
+extern void _swrast_feedback_point( GLcontext *ctx, const SWvertex *v );
+
+extern void _swrast_feedback_line( GLcontext *ctx,
+ const SWvertex *v1, const SWvertex *v2 );
+
+extern void _swrast_feedback_triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 );
+
+extern void _swrast_select_point( GLcontext *ctx, const SWvertex *v );
+
+extern void _swrast_select_line( GLcontext *ctx,
+ const SWvertex *v1, const SWvertex *v2 );
+
+extern void _swrast_select_triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 );
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_fog.c b/mesalib/src/mesa/swrast/s_fog.c
new file mode 100644
index 000000000..77ed0cfef
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_fog.c
@@ -0,0 +1,330 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+
+#include "s_context.h"
+#include "s_fog.h"
+
+
+/**
+ * Used to convert current raster distance to a fog factor in [0,1].
+ */
+GLfloat
+_swrast_z_to_fogfactor(GLcontext *ctx, GLfloat z)
+{
+ GLfloat d, f;
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ if (ctx->Fog.Start == ctx->Fog.End)
+ d = 1.0F;
+ else
+ d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ f = (ctx->Fog.End - z) * d;
+ return CLAMP(f, 0.0F, 1.0F);
+ case GL_EXP:
+ d = ctx->Fog.Density;
+ f = EXPF(-d * z);
+ f = CLAMP(f, 0.0F, 1.0F);
+ return f;
+ case GL_EXP2:
+ d = ctx->Fog.Density;
+ f = EXPF(-(d * d * z * z));
+ f = CLAMP(f, 0.0F, 1.0F);
+ return f;
+ default:
+ _mesa_problem(ctx, "Bad fog mode in _swrast_z_to_fogfactor");
+ return 0.0;
+ }
+}
+
+
+#define LINEAR_FOG(f, coord) f = (fogEnd - coord) * fogScale
+
+#define EXP_FOG(f, coord) f = EXPF(density * coord)
+
+#define EXP2_FOG(f, coord) \
+do { \
+ GLfloat tmp = negDensitySquared * coord * coord; \
+ if (tmp < FLT_MIN_10_EXP) \
+ tmp = FLT_MIN_10_EXP; \
+ f = EXPF(tmp); \
+ } while(0)
+
+
+#define BLEND_FOG(f, coord) f = coord
+
+
+
+/**
+ * Template code for computing fog blend factor and applying it to colors.
+ * \param TYPE either GLubyte, GLushort or GLfloat.
+ * \param COMPUTE_F code to compute the fog blend factor, f.
+ */
+#define FOG_LOOP(TYPE, FOG_FUNC) \
+if (span->arrayAttribs & FRAG_BIT_FOGC) { \
+ GLuint i; \
+ for (i = 0; i < span->end; i++) { \
+ const GLfloat fogCoord = span->array->attribs[FRAG_ATTRIB_FOGC][i][0]; \
+ const GLfloat c = FABSF(fogCoord); \
+ GLfloat f, oneMinusF; \
+ FOG_FUNC(f, c); \
+ f = CLAMP(f, 0.0F, 1.0F); \
+ oneMinusF = 1.0F - f; \
+ rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
+ rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
+ rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
+ } \
+} \
+else { \
+ const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0]; \
+ GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0]; \
+ const GLfloat wStep = span->attrStepX[FRAG_ATTRIB_WPOS][3]; \
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; \
+ GLuint i; \
+ for (i = 0; i < span->end; i++) { \
+ const GLfloat c = FABSF(fogCoord) / w; \
+ GLfloat f, oneMinusF; \
+ FOG_FUNC(f, c); \
+ f = CLAMP(f, 0.0F, 1.0F); \
+ oneMinusF = 1.0F - f; \
+ rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
+ rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
+ rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
+ fogCoord += fogStep; \
+ w += wStep; \
+ } \
+}
+
+/* As above, but CI mode (XXX try to merge someday) */
+#define FOG_LOOP_CI(FOG_FUNC) \
+if (span->arrayAttribs & FRAG_BIT_FOGC) { \
+ GLuint i; \
+ for (i = 0; i < span->end; i++) { \
+ const GLfloat fogCoord = span->array->attribs[FRAG_ATTRIB_FOGC][i][0]; \
+ const GLfloat c = FABSF(fogCoord); \
+ GLfloat f; \
+ FOG_FUNC(f, c); \
+ f = CLAMP(f, 0.0F, 1.0F); \
+ index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); \
+ } \
+} \
+else { \
+ const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0]; \
+ GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0]; \
+ const GLfloat wStep = span->attrStepX[FRAG_ATTRIB_WPOS][3]; \
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; \
+ GLuint i; \
+ for (i = 0; i < span->end; i++) { \
+ const GLfloat c = FABSF(fogCoord) / w; \
+ GLfloat f; \
+ FOG_FUNC(f, c); \
+ f = CLAMP(f, 0.0F, 1.0F); \
+ index[i] = (GLuint) ((GLfloat) index[i] + (1.0F - f) * fogIndex); \
+ fogCoord += fogStep; \
+ w += wStep; \
+ } \
+}
+
+
+
+/**
+ * Apply fog to a span of RGBA pixels.
+ * The fog value are either in the span->array->fog array or interpolated from
+ * the fog/fogStep values.
+ * They fog values are either fog coordinates (Z) or fog blend factors.
+ * _PreferPixelFog should be in sync with that state!
+ */
+void
+_swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span )
+{
+ const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
+ GLfloat rFog, gFog, bFog;
+
+ ASSERT(swrast->_FogEnabled);
+ ASSERT(span->arrayMask & SPAN_RGBA);
+
+ /* compute (scaled) fog color */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ rFog = ctx->Fog.Color[RCOMP] * 255.0;
+ gFog = ctx->Fog.Color[GCOMP] * 255.0;
+ bFog = ctx->Fog.Color[BCOMP] * 255.0;
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ rFog = ctx->Fog.Color[RCOMP] * 65535.0;
+ gFog = ctx->Fog.Color[GCOMP] * 65535.0;
+ bFog = ctx->Fog.Color[BCOMP] * 65535.0;
+ }
+ else {
+ rFog = ctx->Fog.Color[RCOMP];
+ gFog = ctx->Fog.Color[GCOMP];
+ bFog = ctx->Fog.Color[BCOMP];
+ }
+
+ if (swrast->_PreferPixelFog) {
+ /* The span's fog values are fog coordinates, now compute blend factors
+ * and blend the fragment colors with the fog color.
+ */
+ switch (swrast->_FogMode) {
+ case GL_LINEAR:
+ {
+ const GLfloat fogEnd = ctx->Fog.End;
+ const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
+ ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ FOG_LOOP(GLubyte, LINEAR_FOG);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ FOG_LOOP(GLushort, LINEAR_FOG);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, LINEAR_FOG);
+ }
+ }
+ break;
+
+ case GL_EXP:
+ {
+ const GLfloat density = -ctx->Fog.Density;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ FOG_LOOP(GLubyte, EXP_FOG);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ FOG_LOOP(GLushort, EXP_FOG);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, EXP_FOG);
+ }
+ }
+ break;
+
+ case GL_EXP2:
+ {
+ const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ FOG_LOOP(GLubyte, EXP2_FOG);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ FOG_LOOP(GLushort, EXP2_FOG);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, EXP2_FOG);
+ }
+ }
+ break;
+
+ default:
+ _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
+ return;
+ }
+ }
+ else {
+ /* The span's fog start/step/array values are blend factors in [0,1].
+ * They were previously computed per-vertex.
+ */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ FOG_LOOP(GLubyte, BLEND_FOG);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ FOG_LOOP(GLushort, BLEND_FOG);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, BLEND_FOG);
+ }
+ }
+}
+
+
+/**
+ * As above, but color index mode.
+ */
+void
+_swrast_fog_ci_span( const GLcontext *ctx, SWspan *span )
+{
+ const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx);
+ const GLuint fogIndex = (GLuint) ctx->Fog.Index;
+ GLuint *index = span->array->index;
+
+ ASSERT(swrast->_FogEnabled);
+ ASSERT(span->arrayMask & SPAN_INDEX);
+
+ /* we need to compute fog blend factors */
+ if (swrast->_PreferPixelFog) {
+ /* The span's fog values are fog coordinates, now compute blend factors
+ * and blend the fragment colors with the fog color.
+ */
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ {
+ const GLfloat fogEnd = ctx->Fog.End;
+ const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
+ ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ FOG_LOOP_CI(LINEAR_FOG);
+ }
+ break;
+ case GL_EXP:
+ {
+ const GLfloat density = -ctx->Fog.Density;
+ FOG_LOOP_CI(EXP_FOG);
+ }
+ break;
+ case GL_EXP2:
+ {
+ const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+ FOG_LOOP_CI(EXP2_FOG);
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad fog mode in _swrast_fog_ci_span");
+ return;
+ }
+ }
+ else {
+ /* The span's fog start/step/array values are blend factors in [0,1].
+ * They were previously computed per-vertex.
+ */
+ FOG_LOOP_CI(BLEND_FOG);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_fog.h b/mesalib/src/mesa/swrast/s_fog.h
new file mode 100644
index 000000000..50760d88a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_fog.h
@@ -0,0 +1,44 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_FOG_H
+#define S_FOG_H
+
+
+#include "swrast.h"
+
+
+extern GLfloat
+_swrast_z_to_fogfactor(GLcontext *ctx, GLfloat z);
+
+extern void
+_swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span );
+
+extern void
+_swrast_fog_ci_span( const GLcontext *ctx, SWspan *span );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c
new file mode 100644
index 000000000..77a77f0bc
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_fragprog.c
@@ -0,0 +1,269 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/texstate.h"
+#include "shader/prog_instruction.h"
+
+#include "s_fragprog.h"
+#include "s_span.h"
+
+
+/**
+ * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
+ * and return results in 'colorOut'.
+ */
+static INLINE void
+swizzle_texel(const GLfloat texel[4], GLfloat colorOut[4], GLuint swizzle)
+{
+ if (swizzle == SWIZZLE_NOOP) {
+ COPY_4V(colorOut, texel);
+ }
+ else {
+ GLfloat vector[6];
+ vector[SWIZZLE_X] = texel[0];
+ vector[SWIZZLE_Y] = texel[1];
+ vector[SWIZZLE_Z] = texel[2];
+ vector[SWIZZLE_W] = texel[3];
+ vector[SWIZZLE_ZERO] = 0.0F;
+ vector[SWIZZLE_ONE] = 1.0F;
+ colorOut[0] = vector[GET_SWZ(swizzle, 0)];
+ colorOut[1] = vector[GET_SWZ(swizzle, 1)];
+ colorOut[2] = vector[GET_SWZ(swizzle, 2)];
+ colorOut[3] = vector[GET_SWZ(swizzle, 3)];
+ }
+}
+
+
+/**
+ * Fetch a texel with given lod.
+ * Called via machine->FetchTexelLod()
+ */
+static void
+fetch_texel_lod( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
+ GLuint unit, GLfloat color[4] )
+{
+ const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+
+ if (texObj) {
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat rgba[4];
+
+ lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
+
+ swrast->TextureSample[unit](ctx, texObj, 1,
+ (const GLfloat (*)[4]) texcoord,
+ &lambda, &rgba);
+ swizzle_texel(rgba, color, texObj->_Swizzle);
+ }
+ else {
+ ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
+ }
+}
+
+
+/**
+ * Fetch a texel with the given partial derivatives to compute a level
+ * of detail in the mipmap.
+ * Called via machine->FetchTexelDeriv()
+ * \param lodBias the lod bias which may be specified by a TXB instruction,
+ * otherwise zero.
+ */
+static void
+fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4],
+ const GLfloat texdx[4], const GLfloat texdy[4],
+ GLfloat lodBias, GLuint unit, GLfloat color[4] )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *texObj = texUnit->_Current;
+
+ if (texObj) {
+ const struct gl_texture_image *texImg =
+ texObj->Image[0][texObj->BaseLevel];
+ const GLfloat texW = (GLfloat) texImg->WidthScale;
+ const GLfloat texH = (GLfloat) texImg->HeightScale;
+ GLfloat lambda;
+ GLfloat rgba[4];
+
+ lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
+ texdx[1], texdy[1], /* dt/dx, dt/dy */
+ texdx[3], texdy[3], /* dq/dx, dq/dy */
+ texW, texH,
+ texcoord[0], texcoord[1], texcoord[3],
+ 1.0F / texcoord[3]);
+
+ lambda += lodBias + texUnit->LodBias + texObj->LodBias;
+
+ lambda = CLAMP(lambda, texObj->MinLod, texObj->MaxLod);
+
+ swrast->TextureSample[unit](ctx, texObj, 1,
+ (const GLfloat (*)[4]) texcoord,
+ &lambda, &rgba);
+ swizzle_texel(rgba, color, texObj->_Swizzle);
+ }
+ else {
+ ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
+ }
+}
+
+
+/**
+ * Initialize the virtual fragment program machine state prior to running
+ * fragment program on a fragment. This involves initializing the input
+ * registers, condition codes, etc.
+ * \param machine the virtual machine state to init
+ * \param program the fragment program we're about to run
+ * \param span the span of pixels we'll operate on
+ * \param col which element (column) of the span we'll operate on
+ */
+static void
+init_machine(GLcontext *ctx, struct gl_program_machine *machine,
+ const struct gl_fragment_program *program,
+ const SWspan *span, GLuint col)
+{
+ if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
+ /* Clear temporary registers (undefined for ARB_f_p) */
+ _mesa_bzero(machine->Temporaries,
+ MAX_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
+ }
+
+ /* Setup pointer to input attributes */
+ machine->Attribs = span->array->attribs;
+
+ machine->DerivX = (GLfloat (*)[4]) span->attrStepX;
+ machine->DerivY = (GLfloat (*)[4]) span->attrStepY;
+ machine->NumDeriv = FRAG_ATTRIB_MAX;
+
+ machine->Samplers = program->Base.SamplerUnits;
+
+ /* if running a GLSL program (not ARB_fragment_program) */
+ if (ctx->Shader.CurrentProgram) {
+ /* Store front/back facing value */
+ machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0 - span->facing;
+ }
+
+ machine->CurElement = col;
+
+ /* init condition codes */
+ machine->CondCodes[0] = COND_EQ;
+ machine->CondCodes[1] = COND_EQ;
+ machine->CondCodes[2] = COND_EQ;
+ machine->CondCodes[3] = COND_EQ;
+
+ /* init call stack */
+ machine->StackDepth = 0;
+
+ machine->FetchTexelLod = fetch_texel_lod;
+ machine->FetchTexelDeriv = fetch_texel_deriv;
+}
+
+
+/**
+ * Run fragment program on the pixels in span from 'start' to 'end' - 1.
+ */
+static void
+run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
+ const GLbitfield outputsWritten = program->Base.OutputsWritten;
+ struct gl_program_machine *machine = &swrast->FragProgMachine;
+ GLuint i;
+
+ for (i = start; i < end; i++) {
+ if (span->array->mask[i]) {
+ init_machine(ctx, machine, program, span, i);
+
+ if (_mesa_execute_program(ctx, &program->Base, machine)) {
+
+ /* Store result color */
+ if (outputsWritten & (1 << FRAG_RESULT_COLOR)) {
+ COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i],
+ machine->Outputs[FRAG_RESULT_COLOR]);
+ }
+ else {
+ /* Multiple drawbuffers / render targets
+ * Note that colors beyond 0 and 1 will overwrite other
+ * attributes, such as FOGC, TEX0, TEX1, etc. That's OK.
+ */
+ GLuint buf;
+ for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) {
+ if (outputsWritten & (1 << (FRAG_RESULT_DATA0 + buf))) {
+ COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0 + buf][i],
+ machine->Outputs[FRAG_RESULT_DATA0 + buf]);
+ }
+ }
+ }
+
+ /* Store result depth/z */
+ if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) {
+ const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2];
+ if (depth <= 0.0)
+ span->array->z[i] = 0;
+ else if (depth >= 1.0)
+ span->array->z[i] = ctx->DrawBuffer->_DepthMax;
+ else
+ span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF);
+ }
+ }
+ else {
+ /* killed fragment */
+ span->array->mask[i] = GL_FALSE;
+ span->writeAll = GL_FALSE;
+ }
+ }
+ }
+}
+
+
+/**
+ * Execute the current fragment program for all the fragments
+ * in the given span.
+ */
+void
+_swrast_exec_fragment_program( GLcontext *ctx, SWspan *span )
+{
+ const struct gl_fragment_program *program = ctx->FragmentProgram._Current;
+
+ /* incoming colors should be floats */
+ if (program->Base.InputsRead & FRAG_BIT_COL0) {
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ }
+
+ run_program(ctx, span, 0, span->end);
+
+ if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
+ span->interpMask &= ~SPAN_RGBA;
+ span->arrayMask |= SPAN_RGBA;
+ }
+
+ if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH)) {
+ span->interpMask &= ~SPAN_Z;
+ span->arrayMask |= SPAN_Z;
+ }
+}
+
diff --git a/mesalib/src/mesa/swrast/s_fragprog.h b/mesalib/src/mesa/swrast/s_fragprog.h
new file mode 100644
index 000000000..e1b7e6791
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_fragprog.h
@@ -0,0 +1,38 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2006 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 S_FRAGPROG_H
+#define S_FRAGPROG_H
+
+
+#include "s_context.h"
+
+
+extern void
+_swrast_exec_fragment_program(GLcontext *ctx, SWspan *span);
+
+
+#endif /* S_FRAGPROG_H */
+
diff --git a/mesalib/src/mesa/swrast/s_imaging.c b/mesalib/src/mesa/swrast/s_imaging.c
new file mode 100644
index 000000000..3578b713f
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_imaging.c
@@ -0,0 +1,196 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+/* KW: Moved these here to remove knowledge of swrast from core mesa.
+ * Should probably pull the entire software implementation of these
+ * extensions into either swrast or a sister module.
+ */
+
+#include "main/glheader.h"
+#include "main/colortab.h"
+#include "main/convolve.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+void
+_swrast_CopyColorTable( GLcontext *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width)
+{
+ GLchan data[MAX_WIDTH][4];
+ struct gl_buffer_object *bufferSave;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ if (width > MAX_WIDTH)
+ width = MAX_WIDTH;
+
+ swrast_render_start(ctx);
+
+ /* read the data from framebuffer */
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, x, y, CHAN_TYPE, data );
+
+ swrast_render_finish(ctx);
+
+ /* save PBO binding */
+ bufferSave = ctx->Unpack.BufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
+
+ _mesa_ColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data);
+
+ /* restore PBO binding */
+ ctx->Unpack.BufferObj = bufferSave;
+}
+
+
+void
+_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width)
+{
+ GLchan data[MAX_WIDTH][4];
+ struct gl_buffer_object *bufferSave;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ if (width > MAX_WIDTH)
+ width = MAX_WIDTH;
+
+ swrast_render_start(ctx);
+
+ /* read the data from framebuffer */
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, x, y, CHAN_TYPE, data );
+
+ swrast_render_finish(ctx);
+
+ /* save PBO binding */
+ bufferSave = ctx->Unpack.BufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
+
+ _mesa_ColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data);
+
+ /* restore PBO binding */
+ ctx->Unpack.BufferObj = bufferSave;
+}
+
+
+void
+_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width)
+{
+ GLchan rgba[MAX_CONVOLUTION_WIDTH][4];
+ struct gl_buffer_object *bufferSave;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ swrast_render_start(ctx);
+
+ /* read the data from framebuffer */
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, x, y, CHAN_TYPE, rgba );
+
+ swrast_render_finish(ctx);
+
+ /* save PBO binding */
+ bufferSave = ctx->Unpack.BufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
+
+ /* store as convolution filter */
+ _mesa_ConvolutionFilter1D(target, internalFormat, width,
+ GL_RGBA, CHAN_TYPE, rgba);
+
+ /* restore PBO binding */
+ ctx->Unpack.BufferObj = bufferSave;
+}
+
+
+void
+_swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ struct gl_pixelstore_attrib packSave;
+ GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4];
+ GLint i;
+ struct gl_buffer_object *bufferSave;
+
+ if (!ctx->ReadBuffer->_ColorReadBuffer) {
+ /* no readbuffer - OK */
+ return;
+ }
+
+ swrast_render_start(ctx);
+
+ /* read pixels from framebuffer */
+ for (i = 0; i < height; i++) {
+ _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
+ width, x, y + i, CHAN_TYPE, rgba[i] );
+ }
+
+ swrast_render_finish(ctx);
+
+ /*
+ * HACK: save & restore context state so we can store this as a
+ * convolution filter via the GL api. Doesn't call any callbacks
+ * hanging off ctx->Unpack statechanges.
+ */
+
+ packSave = ctx->Unpack; /* save pixel packing params */
+
+ ctx->Unpack.Alignment = 1;
+ ctx->Unpack.RowLength = MAX_CONVOLUTION_WIDTH;
+ ctx->Unpack.SkipPixels = 0;
+ ctx->Unpack.SkipRows = 0;
+ ctx->Unpack.ImageHeight = 0;
+ ctx->Unpack.SkipImages = 0;
+ ctx->Unpack.SwapBytes = GL_FALSE;
+ ctx->Unpack.LsbFirst = GL_FALSE;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
+ ctx->NewState |= _NEW_PACKUNPACK;
+
+ /* save PBO binding */
+ bufferSave = ctx->Unpack.BufferObj;
+ ctx->Unpack.BufferObj = ctx->Shared->NullBufferObj;
+
+ _mesa_ConvolutionFilter2D(target, internalFormat, width, height,
+ GL_RGBA, CHAN_TYPE, rgba);
+
+ /* restore PBO binding */
+ ctx->Unpack.BufferObj = bufferSave;
+
+ ctx->Unpack = packSave; /* restore pixel packing params */
+ ctx->NewState |= _NEW_PACKUNPACK;
+}
diff --git a/mesalib/src/mesa/swrast/s_lines.c b/mesalib/src/mesa/swrast/s_lines.c
new file mode 100644
index 000000000..23cb9b57e
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_lines.c
@@ -0,0 +1,307 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "s_aaline.h"
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_feedback.h"
+#include "s_lines.h"
+#include "s_span.h"
+
+
+/*
+ * Init the mask[] array to implement a line stipple.
+ */
+static void
+compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0; i < len; i++) {
+ GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
+ if ((1 << bit) & ctx->Line.StipplePattern) {
+ mask[i] = GL_TRUE;
+ }
+ else {
+ mask[i] = GL_FALSE;
+ }
+ swrast->StippleCounter++;
+ }
+}
+
+
+/*
+ * To draw a wide line we can simply redraw the span N times, side by side.
+ */
+static void
+draw_wide_line( GLcontext *ctx, SWspan *span, GLboolean xMajor )
+{
+ const GLint width = (GLint) CLAMP(ctx->Line.Width,
+ ctx->Const.MinLineWidth,
+ ctx->Const.MaxLineWidth);
+ GLint start;
+
+ ASSERT(span->end < MAX_WIDTH);
+
+ if (width & 1)
+ start = width / 2;
+ else
+ start = width / 2 - 1;
+
+ if (xMajor) {
+ GLint *y = span->array->y;
+ GLuint i;
+ GLint w;
+ for (w = 0; w < width; w++) {
+ if (w == 0) {
+ for (i = 0; i < span->end; i++)
+ y[i] -= start;
+ }
+ else {
+ for (i = 0; i < span->end; i++)
+ y[i]++;
+ }
+ if (ctx->Visual.rgbMode)
+ _swrast_write_rgba_span(ctx, span);
+ else
+ _swrast_write_index_span(ctx, span);
+ }
+ }
+ else {
+ GLint *x = span->array->x;
+ GLuint i;
+ GLint w;
+ for (w = 0; w < width; w++) {
+ if (w == 0) {
+ for (i = 0; i < span->end; i++)
+ x[i] -= start;
+ }
+ else {
+ for (i = 0; i < span->end; i++)
+ x[i]++;
+ }
+ if (ctx->Visual.rgbMode)
+ _swrast_write_rgba_span(ctx, span);
+ else
+ _swrast_write_index_span(ctx, span);
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Rasterization *****/
+/**********************************************************************/
+
+/* Simple color index line (no stipple, width=1, no Z, no fog, no tex)*/
+#define NAME simple_no_z_ci_line
+#define INTERP_INDEX
+#define RENDER_SPAN(span) _swrast_write_index_span(ctx, &span)
+#include "s_linetemp.h"
+
+/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
+#define NAME simple_no_z_rgba_line
+#define INTERP_RGBA
+#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
+#include "s_linetemp.h"
+
+
+/* Z, fog, wide, stipple color index line */
+#define NAME ci_line
+#define INTERP_INDEX
+#define INTERP_Z
+#define INTERP_ATTRIBS /* for fog */
+#define RENDER_SPAN(span) \
+ if (ctx->Line.StippleFlag) { \
+ span.arrayMask |= SPAN_MASK; \
+ compute_stipple_mask(ctx, span.end, span.array->mask); \
+ } \
+ if (ctx->Line.Width > 1.0) { \
+ draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
+ } \
+ else { \
+ _swrast_write_index_span(ctx, &span); \
+ }
+#include "s_linetemp.h"
+
+
+/* Z, fog, wide, stipple RGBA line */
+#define NAME rgba_line
+#define INTERP_RGBA
+#define INTERP_Z
+#define RENDER_SPAN(span) \
+ if (ctx->Line.StippleFlag) { \
+ span.arrayMask |= SPAN_MASK; \
+ compute_stipple_mask(ctx, span.end, span.array->mask); \
+ } \
+ if (ctx->Line.Width > 1.0) { \
+ draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
+ } \
+ else { \
+ _swrast_write_rgba_span(ctx, &span); \
+ }
+#include "s_linetemp.h"
+
+
+/* General-purpose line (any/all features). */
+#define NAME general_line
+#define INTERP_RGBA
+#define INTERP_Z
+#define INTERP_ATTRIBS
+#define RENDER_SPAN(span) \
+ if (ctx->Line.StippleFlag) { \
+ span.arrayMask |= SPAN_MASK; \
+ compute_stipple_mask(ctx, span.end, span.array->mask); \
+ } \
+ if (ctx->Line.Width > 1.0) { \
+ draw_wide_line(ctx, &span, (GLboolean)(dx > dy)); \
+ } \
+ else { \
+ _swrast_write_rgba_span(ctx, &span); \
+ }
+#include "s_linetemp.h"
+
+
+
+void
+_swrast_add_spec_terms_line(GLcontext *ctx,
+ const SWvertex *v0, const SWvertex *v1)
+{
+ SWvertex *ncv0 = (SWvertex *)v0;
+ SWvertex *ncv1 = (SWvertex *)v1;
+ GLfloat rSum, gSum, bSum;
+ GLchan cSave[2][4];
+
+ /* save original colors */
+ COPY_CHAN4(cSave[0], ncv0->color);
+ COPY_CHAN4(cSave[1], ncv1->color);
+ /* sum v0 */
+ rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
+ /* sum v1 */
+ rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
+ /* draw */
+ SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
+ /* restore original colors */
+ COPY_CHAN4( ncv0->attrib[FRAG_ATTRIB_COL0], cSave[0] );
+ COPY_CHAN4( ncv1->attrib[FRAG_ATTRIB_COL0], cSave[1] );
+}
+
+
+
+#ifdef DEBUG
+
+/* record the current line function name */
+static const char *lineFuncName = NULL;
+
+#define USE(lineFunc) \
+do { \
+ lineFuncName = #lineFunc; \
+ /*_mesa_printf("%s\n", lineFuncName);*/ \
+ swrast->Line = lineFunc; \
+} while (0)
+
+#else
+
+#define USE(lineFunc) swrast->Line = lineFunc
+
+#endif
+
+
+
+/**
+ * Determine which line drawing function to use given the current
+ * rendering context.
+ *
+ * Please update the summary flag _SWRAST_NEW_LINE if you add or remove
+ * tests to this code.
+ */
+void
+_swrast_choose_line( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLboolean rgbmode = ctx->Visual.rgbMode;
+ GLboolean specular = (ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
+
+ if (ctx->RenderMode == GL_RENDER) {
+ if (ctx->Line.SmoothFlag) {
+ /* antialiased lines */
+ _swrast_choose_aa_line_function(ctx);
+ ASSERT(swrast->Line);
+ }
+ else if (ctx->Texture._EnabledCoordUnits
+ || ctx->FragmentProgram._Current
+ || swrast->_FogEnabled
+ || specular) {
+ USE(general_line);
+ }
+ else if (ctx->Depth.Test
+ || ctx->Line.Width != 1.0
+ || ctx->Line.StippleFlag) {
+ /* no texture, but Z, fog, width>1, stipple, etc. */
+ if (rgbmode)
+#if CHAN_BITS == 32
+ USE(general_line);
+#else
+ USE(rgba_line);
+#endif
+ else
+ USE(ci_line);
+ }
+ else {
+ ASSERT(!ctx->Depth.Test);
+ ASSERT(ctx->Line.Width == 1.0);
+ /* simple lines */
+ if (rgbmode)
+ USE(simple_no_z_rgba_line);
+ else
+ USE(simple_no_z_ci_line);
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ USE(_swrast_feedback_line);
+ }
+ else {
+ ASSERT(ctx->RenderMode == GL_SELECT);
+ USE(_swrast_select_line);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_lines.h b/mesalib/src/mesa/swrast/s_lines.h
new file mode 100644
index 000000000..22979a02b
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_lines.h
@@ -0,0 +1,41 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_LINES_H
+#define S_LINES_H
+
+#include "swrast.h"
+
+void
+_swrast_choose_line( GLcontext *ctx );
+
+void
+_swrast_add_spec_terms_line( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1 );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_linetemp.h b/mesalib/src/mesa/swrast/s_linetemp.h
new file mode 100644
index 000000000..1abf8d6c7
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_linetemp.h
@@ -0,0 +1,421 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * Line Rasterizer Template
+ *
+ * This file is #include'd to generate custom line rasterizers.
+ *
+ * The following macros may be defined to indicate what auxillary information
+ * must be interplated along the line:
+ * INTERP_Z - if defined, interpolate Z values
+ * INTERP_RGBA - if defined, interpolate RGBA values
+ * INTERP_INDEX - if defined, interpolate color index values
+ * INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc)
+ *
+ * When one can directly address pixels in the color buffer the following
+ * macros can be defined and used to directly compute pixel addresses during
+ * rasterization (see pixelPtr):
+ * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
+ * BYTES_PER_ROW - number of bytes per row in the color buffer
+ * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
+ * Y==0 at bottom of screen and increases upward.
+ *
+ * Similarly, for direct depth buffer access, this type is used for depth
+ * buffer addressing:
+ * DEPTH_TYPE - either GLushort or GLuint
+ *
+ * Optionally, one may provide one-time setup code
+ * SETUP_CODE - code which is to be executed once per line
+ *
+ * To actually "plot" each pixel the PLOT macro must be defined...
+ * PLOT(X,Y) - code to plot a pixel. Example:
+ * if (Z < *zPtr) {
+ * *zPtr = Z;
+ * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
+ * FixedToInt(b0) );
+ * put_pixel( X, Y, color );
+ * }
+ *
+ * This code was designed for the origin to be in the lower-left corner.
+ *
+ */
+
+
+static void
+NAME( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ SWspan span;
+ GLuint interpFlags = 0;
+ GLint x0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0];
+ GLint x1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
+ GLint y0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1];
+ GLint y1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1];
+ GLint dx, dy;
+ GLint numPixels;
+ GLint xstep, ystep;
+#if defined(DEPTH_TYPE)
+ const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
+ const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
+ struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+#define FixedToDepth(F) ((F) >> fixedToDepthShift)
+ GLint zPtrXstep, zPtrYstep;
+ DEPTH_TYPE *zPtr;
+#elif defined(INTERP_Z)
+ const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
+/*ctx->Visual.depthBits;*/
+#endif
+#ifdef PIXEL_ADDRESS
+ PIXEL_TYPE *pixelPtr;
+ GLint pixelXstep, pixelYstep;
+#endif
+
+#ifdef SETUP_CODE
+ SETUP_CODE
+#endif
+
+ (void) swrast;
+
+ /* Cull primitives with malformed coordinates.
+ */
+ {
+ GLfloat tmp = vert0->attrib[FRAG_ATTRIB_WPOS][0] + vert0->attrib[FRAG_ATTRIB_WPOS][1]
+ + vert1->attrib[FRAG_ATTRIB_WPOS][0] + vert1->attrib[FRAG_ATTRIB_WPOS][1];
+ if (IS_INF_OR_NAN(tmp))
+ return;
+ }
+
+ /*
+ printf("%s():\n", __FUNCTION__);
+ printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
+ vert0->attrib[FRAG_ATTRIB_WPOS][0],
+ vert0->attrib[FRAG_ATTRIB_WPOS][1],
+ vert0->attrib[FRAG_ATTRIB_WPOS][2],
+ vert1->attrib[FRAG_ATTRIB_WPOS][0],
+ vert1->attrib[FRAG_ATTRIB_WPOS][1],
+ vert1->attrib[FRAG_ATTRIB_WPOS][2]);
+ printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
+ vert0->color[0], vert0->color[1], vert0->color[2],
+ vert1->color[0], vert1->color[1], vert1->color[2]);
+ printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
+ vert0->specular[0], vert0->specular[1], vert0->specular[2],
+ vert1->specular[0], vert1->specular[1], vert1->specular[2]);
+ */
+
+/*
+ * Despite being clipped to the view volume, the line's window coordinates
+ * may just lie outside the window bounds. That is, if the legal window
+ * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
+ * This quick and dirty code nudges the endpoints inside the window if
+ * necessary.
+ */
+#ifdef CLIP_HACK
+ {
+ GLint w = ctx->DrawBuffer->Width;
+ GLint h = ctx->DrawBuffer->Height;
+ if ((x0==w) | (x1==w)) {
+ if ((x0==w) & (x1==w))
+ return;
+ x0 -= x0==w;
+ x1 -= x1==w;
+ }
+ if ((y0==h) | (y1==h)) {
+ if ((y0==h) & (y1==h))
+ return;
+ y0 -= y0==h;
+ y1 -= y1==h;
+ }
+ }
+#endif
+
+ dx = x1 - x0;
+ dy = y1 - y0;
+ if (dx == 0 && dy == 0)
+ return;
+
+ /*
+ printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy,
+ vert0->attrib[FRAG_ATTRIB_COL1][0],
+ vert0->attrib[FRAG_ATTRIB_COL1][1],
+ vert0->attrib[FRAG_ATTRIB_COL1][2],
+ vert0->attrib[FRAG_ATTRIB_COL1][3],
+ vert1->attrib[FRAG_ATTRIB_COL1][0],
+ vert1->attrib[FRAG_ATTRIB_COL1][1],
+ vert1->attrib[FRAG_ATTRIB_COL1][2],
+ vert1->attrib[FRAG_ATTRIB_COL1][3]);
+ */
+
+#ifdef DEPTH_TYPE
+ zPtr = (DEPTH_TYPE *) zrb->GetPointer(ctx, zrb, x0, y0);
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
+#endif
+
+ if (dx<0) {
+ dx = -dx; /* make positive */
+ xstep = -1;
+#ifdef DEPTH_TYPE
+ zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
+#endif
+ }
+ else {
+ xstep = 1;
+#ifdef DEPTH_TYPE
+ zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
+#endif
+ }
+
+ if (dy<0) {
+ dy = -dy; /* make positive */
+ ystep = -1;
+#ifdef DEPTH_TYPE
+ zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelYstep = BYTES_PER_ROW;
+#endif
+ }
+ else {
+ ystep = 1;
+#ifdef DEPTH_TYPE
+ zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelYstep = -(BYTES_PER_ROW);
+#endif
+ }
+
+ ASSERT(dx >= 0);
+ ASSERT(dy >= 0);
+
+ numPixels = MAX2(dx, dy);
+
+ /*
+ * Span setup: compute start and step values for all interpolated values.
+ */
+#ifdef INTERP_RGBA
+ interpFlags |= SPAN_RGBA;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ span.red = ChanToFixed(vert0->color[0]);
+ span.green = ChanToFixed(vert0->color[1]);
+ span.blue = ChanToFixed(vert0->color[2]);
+ span.alpha = ChanToFixed(vert0->color[3]);
+ span.redStep = (ChanToFixed(vert1->color[0]) - span.red ) / numPixels;
+ span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
+ span.blueStep = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
+ span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
+ }
+ else {
+ span.red = ChanToFixed(vert1->color[0]);
+ span.green = ChanToFixed(vert1->color[1]);
+ span.blue = ChanToFixed(vert1->color[2]);
+ span.alpha = ChanToFixed(vert1->color[3]);
+ span.redStep = 0;
+ span.greenStep = 0;
+ span.blueStep = 0;
+ span.alphaStep = 0;
+ }
+#endif
+#ifdef INTERP_INDEX
+ interpFlags |= SPAN_INDEX;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ span.index = FloatToFixed(vert0->attrib[FRAG_ATTRIB_CI][0]);
+ span.indexStep = FloatToFixed( vert1->attrib[FRAG_ATTRIB_CI][0]
+ - vert0->attrib[FRAG_ATTRIB_CI][0]) / numPixels;
+ }
+ else {
+ span.index = FloatToFixed(vert1->attrib[FRAG_ATTRIB_CI][0]);
+ span.indexStep = 0;
+ }
+#endif
+#if defined(INTERP_Z) || defined(DEPTH_TYPE)
+ interpFlags |= SPAN_Z;
+ {
+ if (depthBits <= 16) {
+ span.z = FloatToFixed(vert0->attrib[FRAG_ATTRIB_WPOS][2]) + FIXED_HALF;
+ span.zStep = FloatToFixed( vert1->attrib[FRAG_ATTRIB_WPOS][2]
+ - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels;
+ }
+ else {
+ /* don't use fixed point */
+ span.z = (GLuint) vert0->attrib[FRAG_ATTRIB_WPOS][2];
+ span.zStep = (GLint) (( vert1->attrib[FRAG_ATTRIB_WPOS][2]
+ - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels);
+ }
+ }
+#endif
+#if defined(INTERP_ATTRIBS)
+ {
+ const GLfloat invLen = 1.0F / numPixels;
+ const GLfloat invw0 = vert0->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat invw1 = vert1->attrib[FRAG_ATTRIB_WPOS][3];
+
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = invw0;
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = (invw1 - invw0) * invLen;
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
+
+ ATTRIB_LOOP_BEGIN
+ if (swrast->_InterpMode[attr] == GL_FLAT) {
+ COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
+ ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
+ }
+ else {
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ float da;
+ span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
+ da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
+ span.attrStepX[attr][c] = da * invLen;
+ }
+ }
+ ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
+ ATTRIB_LOOP_END
+ }
+#endif
+
+ INIT_SPAN(span, GL_LINE);
+ span.end = numPixels;
+ span.interpMask = interpFlags;
+ span.arrayMask = SPAN_XY;
+
+ span.facing = swrast->PointLineFacing;
+
+
+ /*
+ * Draw
+ */
+
+ if (dx > dy) {
+ /*** X-major line ***/
+ GLint i;
+ GLint errorInc = dy+dy;
+ GLint error = errorInc-dx;
+ GLint errorDec = error-dx;
+
+ for (i = 0; i < dx; i++) {
+#ifdef DEPTH_TYPE
+ GLuint Z = FixedToDepth(span.z);
+#endif
+#ifdef PLOT
+ PLOT( x0, y0 );
+#else
+ span.array->x[i] = x0;
+ span.array->y[i] = y0;
+#endif
+ x0 += xstep;
+#ifdef DEPTH_TYPE
+ zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
+ span.z += span.zStep;
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
+#endif
+ if (error < 0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ y0 += ystep;
+#ifdef DEPTH_TYPE
+ zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
+#endif
+ }
+ }
+ }
+ else {
+ /*** Y-major line ***/
+ GLint i;
+ GLint errorInc = dx+dx;
+ GLint error = errorInc-dy;
+ GLint errorDec = error-dy;
+
+ for (i=0;i<dy;i++) {
+#ifdef DEPTH_TYPE
+ GLuint Z = FixedToDepth(span.z);
+#endif
+#ifdef PLOT
+ PLOT( x0, y0 );
+#else
+ span.array->x[i] = x0;
+ span.array->y[i] = y0;
+#endif
+ y0 += ystep;
+#ifdef DEPTH_TYPE
+ zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
+ span.z += span.zStep;
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
+#endif
+ if (error<0) {
+ error += errorInc;
+ }
+ else {
+ error += errorDec;
+ x0 += xstep;
+#ifdef DEPTH_TYPE
+ zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
+#endif
+#ifdef PIXEL_ADDRESS
+ pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
+#endif
+ }
+ }
+ }
+
+#ifdef RENDER_SPAN
+ RENDER_SPAN( span );
+#endif
+
+ (void)span;
+
+}
+
+
+#undef NAME
+#undef INTERP_Z
+#undef INTERP_RGBA
+#undef INTERP_ATTRIBS
+#undef INTERP_INDEX
+#undef PIXEL_ADDRESS
+#undef PIXEL_TYPE
+#undef DEPTH_TYPE
+#undef BYTES_PER_ROW
+#undef SETUP_CODE
+#undef PLOT
+#undef CLIP_HACK
+#undef FixedToDepth
+#undef RENDER_SPAN
diff --git a/mesalib/src/mesa/swrast/s_logic.c b/mesalib/src/mesa/swrast/s_logic.c
new file mode 100644
index 000000000..f0274b4c0
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_logic.c
@@ -0,0 +1,246 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/macros.h"
+
+#include "s_context.h"
+#include "s_logic.h"
+#include "s_span.h"
+
+
+/**
+ * We do all logic ops on 4-byte GLuints.
+ * Depending on bytes per pixel, the mask array elements correspond to
+ * 1, 2 or 4 GLuints.
+ */
+#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \
+do { \
+ GLuint i; \
+ switch (MODE) { \
+ case GL_CLEAR: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = 0; \
+ } \
+ } \
+ break; \
+ case GL_SET: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~0; \
+ } \
+ } \
+ break; \
+ case GL_COPY: \
+ /* do nothing */ \
+ break; \
+ case GL_COPY_INVERTED: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~src[i]; \
+ } \
+ } \
+ break; \
+ case GL_NOOP: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_INVERT: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_AND: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] &= dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_NAND: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~(src[i] & dest[i]); \
+ } \
+ } \
+ break; \
+ case GL_OR: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] |= dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_NOR: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~(src[i] | dest[i]); \
+ } \
+ } \
+ break; \
+ case GL_XOR: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] ^= dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_EQUIV: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~(src[i] ^ dest[i]); \
+ } \
+ } \
+ break; \
+ case GL_AND_REVERSE: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = src[i] & ~dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_AND_INVERTED: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~src[i] & dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_OR_REVERSE: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = src[i] | ~dest[i]; \
+ } \
+ } \
+ break; \
+ case GL_OR_INVERTED: \
+ for (i = 0; i < n; i++) { \
+ if (mask[i / MASKSTRIDE]) { \
+ src[i] = ~src[i] | dest[i]; \
+ } \
+ } \
+ break; \
+ default: \
+ _mesa_problem(ctx, "bad logicop mode");\
+ } \
+} while (0)
+
+
+
+static INLINE void
+logicop_uint1(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+ const GLubyte mask[])
+{
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
+}
+
+
+static INLINE void
+logicop_uint2(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+ const GLubyte mask[])
+{
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
+}
+
+
+static INLINE void
+logicop_uint4(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+ const GLubyte mask[])
+{
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
+}
+
+
+
+/*
+ * Apply the current logic operator to a span of CI pixels. This is only
+ * used if the device driver can't do logic ops.
+ */
+void
+_swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span)
+{
+ GLuint dest[MAX_WIDTH];
+ GLuint *index = span->array->index;
+
+ ASSERT(span->end < MAX_WIDTH);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+
+ /* Read dest values from frame buffer */
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+ dest, sizeof(GLuint));
+ }
+ else {
+ rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
+ }
+
+ logicop_uint1(ctx, span->end, index, dest, span->array->mask);
+}
+
+
+/**
+ * Apply the current logic operator to a span of RGBA pixels.
+ * We can handle horizontal runs of pixels (spans) or arrays of x/y
+ * pixel coordinates.
+ */
+void
+_swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span)
+{
+ void *rbPixels;
+
+ ASSERT(span->end < MAX_WIDTH);
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(rb->DataType == span->array->ChanType);
+
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ /* treat 4*GLubyte as GLuint */
+ logicop_uint1(ctx, span->end,
+ (GLuint *) span->array->rgba8,
+ (const GLuint *) rbPixels, span->array->mask);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ /* treat 2*GLushort as GLuint */
+ logicop_uint2(ctx, 2 * span->end,
+ (GLuint *) span->array->rgba16,
+ (const GLuint *) rbPixels, span->array->mask);
+ }
+ else {
+ logicop_uint4(ctx, 4 * span->end,
+ (GLuint *) span->array->attribs[FRAG_ATTRIB_COL0],
+ (const GLuint *) rbPixels, span->array->mask);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_logic.h b/mesalib/src/mesa/swrast/s_logic.h
new file mode 100644
index 000000000..ba20cd7b3
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_logic.h
@@ -0,0 +1,43 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 S_LOGIC_H
+#define S_LOGIC_H
+
+
+#include "swrast.h"
+
+
+extern void
+_swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span);
+
+
+extern void
+_swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_masking.c b/mesalib/src/mesa/swrast/s_masking.c
new file mode 100644
index 000000000..df779b073
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_masking.c
@@ -0,0 +1,134 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * Implement the effect of glColorMask and glIndexMask in software.
+ */
+
+
+#include "main/glheader.h"
+#include "main/macros.h"
+
+#include "s_context.h"
+#include "s_masking.h"
+#include "s_span.h"
+
+
+/**
+ * Apply the color mask to a span of rgba values.
+ */
+void
+_swrast_mask_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span)
+{
+ const GLuint n = span->end;
+ void *rbPixels;
+
+ ASSERT(n < MAX_WIDTH);
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(rb->DataType == span->array->ChanType);
+
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+ /*
+ * Do component masking.
+ * Note that we're not using span->array->mask[] here. We could...
+ */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ /* treat 4xGLubyte as 1xGLuint */
+ const GLuint srcMask = *((GLuint *) ctx->Color.ColorMask);
+ const GLuint dstMask = ~srcMask;
+ const GLuint *dst = (const GLuint *) rbPixels;
+ GLuint *src = (GLuint *) span->array->rgba8;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
+ }
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ /* 2-byte components */
+ /* XXX try to use 64-bit arithmetic someday */
+ const GLushort rMask = ctx->Color.ColorMask[RCOMP] ? 0xffff : 0x0;
+ const GLushort gMask = ctx->Color.ColorMask[GCOMP] ? 0xffff : 0x0;
+ const GLushort bMask = ctx->Color.ColorMask[BCOMP] ? 0xffff : 0x0;
+ const GLushort aMask = ctx->Color.ColorMask[ACOMP] ? 0xffff : 0x0;
+ const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
+ GLushort (*src)[4] = span->array->rgba16;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+ src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+ src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+ src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+ }
+ }
+ else {
+ /* 4-byte components */
+ const GLuint rMask = ctx->Color.ColorMask[RCOMP] ? ~0x0 : 0x0;
+ const GLuint gMask = ctx->Color.ColorMask[GCOMP] ? ~0x0 : 0x0;
+ const GLuint bMask = ctx->Color.ColorMask[BCOMP] ? ~0x0 : 0x0;
+ const GLuint aMask = ctx->Color.ColorMask[ACOMP] ? ~0x0 : 0x0;
+ const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
+ GLuint (*src)[4] = (GLuint (*)[4]) span->array->attribs[FRAG_ATTRIB_COL0];
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+ src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+ src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+ src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+ }
+ }
+}
+
+
+/**
+ * Apply the index mask to a span of color index values.
+ */
+void
+_swrast_mask_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span)
+{
+ const GLuint srcMask = ctx->Color.IndexMask;
+ const GLuint dstMask = ~srcMask;
+ GLuint *index = span->array->index;
+ GLuint dest[MAX_WIDTH];
+ GLuint i;
+
+ ASSERT(span->arrayMask & SPAN_INDEX);
+ ASSERT(span->end <= MAX_WIDTH);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+ dest, sizeof(GLuint));
+ }
+ else {
+ _swrast_read_index_span(ctx, rb, span->end, span->x, span->y, dest);
+ }
+
+ for (i = 0; i < span->end; i++) {
+ index[i] = (index[i] & srcMask) | (dest[i] & dstMask);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_masking.h b/mesalib/src/mesa/swrast/s_masking.h
new file mode 100644
index 000000000..3260ca34e
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_masking.h
@@ -0,0 +1,42 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 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 S_MASKING_H
+#define S_MASKING_H
+
+
+#include "swrast.h"
+
+
+extern void
+_swrast_mask_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span);
+
+
+extern void
+_swrast_mask_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span);
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_points.c b/mesalib/src/mesa/swrast/s_points.c
new file mode 100644
index 000000000..50ec2063a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_points.c
@@ -0,0 +1,598 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/texstate.h"
+#include "s_context.h"
+#include "s_feedback.h"
+#include "s_points.h"
+#include "s_span.h"
+
+
+/**
+ * Used to cull points with invalid coords
+ */
+#define CULL_INVALID(V) \
+ do { \
+ float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0] \
+ + (V)->attrib[FRAG_ATTRIB_WPOS][1]; \
+ if (IS_INF_OR_NAN(tmp)) \
+ return; \
+ } while(0)
+
+
+
+/**
+ * Get/compute the point size.
+ * The size may come from a vertex shader, or computed with attentuation
+ * or just the glPointSize value.
+ * Must also clamp to user-defined range and implmentation limits.
+ */
+static INLINE GLfloat
+get_size(const GLcontext *ctx, const SWvertex *vert, GLboolean smoothed)
+{
+ GLfloat size;
+
+ if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
+ /* use vertex's point size */
+ size = vert->pointSize;
+ }
+ else {
+ /* use constant point size */
+ size = ctx->Point.Size;
+ }
+ /* always clamp to user-specified limits */
+ size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
+ /* clamp to implementation limits */
+ if (smoothed)
+ size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
+ else
+ size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
+
+ return size;
+}
+
+
+/**
+ * Draw a point sprite
+ */
+static void
+sprite_point(GLcontext *ctx, const SWvertex *vert)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ SWspan span;
+ GLfloat size;
+ GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
+ GLuint numTcoords = 0;
+ GLfloat t0, dtdy;
+
+ CULL_INVALID(vert);
+
+ /* z coord */
+ if (ctx->DrawBuffer->Visual.depthBits <= 16)
+ span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ else
+ span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ span.zStep = 0;
+
+ size = get_size(ctx, vert, GL_FALSE);
+
+ /* span init */
+ INIT_SPAN(span, GL_POINT);
+ span.interpMask = SPAN_Z | SPAN_RGBA;
+
+ span.facing = swrast->PointLineFacing;
+
+ span.red = ChanToFixed(vert->color[0]);
+ span.green = ChanToFixed(vert->color[1]);
+ span.blue = ChanToFixed(vert->color[2]);
+ span.alpha = ChanToFixed(vert->color[3]);
+ span.redStep = 0;
+ span.greenStep = 0;
+ span.blueStep = 0;
+ span.alphaStep = 0;
+
+ /* need these for fragment programs */
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
+
+ {
+ GLfloat s, r, dsdx;
+
+ /* texcoord / pointcoord interpolants */
+ s = 0.0;
+ dsdx = 1.0 / size;
+ if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
+ dtdy = 1.0 / size;
+ t0 = 0.5 * dtdy;
+ }
+ else {
+ /* GL_UPPER_LEFT */
+ dtdy = -1.0 / size;
+ t0 = 1.0 + 0.5 * dtdy;
+ }
+
+ ATTRIB_LOOP_BEGIN
+ if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
+ /* a texcoord attribute */
+ const GLuint u = attr - FRAG_ATTRIB_TEX0;
+ ASSERT(u < Elements(ctx->Point.CoordReplace));
+ if (ctx->Point.CoordReplace[u]) {
+ tCoords[numTcoords++] = attr;
+
+ if (ctx->Point.SpriteRMode == GL_ZERO)
+ r = 0.0F;
+ else if (ctx->Point.SpriteRMode == GL_S)
+ r = vert->attrib[attr][0];
+ else /* GL_R */
+ r = vert->attrib[attr][2];
+
+ span.attrStart[attr][0] = s;
+ span.attrStart[attr][1] = 0.0; /* overwritten below */
+ span.attrStart[attr][2] = r;
+ span.attrStart[attr][3] = 1.0;
+
+ span.attrStepX[attr][0] = dsdx;
+ span.attrStepX[attr][1] = 0.0;
+ span.attrStepX[attr][2] = 0.0;
+ span.attrStepX[attr][3] = 0.0;
+
+ span.attrStepY[attr][0] = 0.0;
+ span.attrStepY[attr][1] = dtdy;
+ span.attrStepY[attr][2] = 0.0;
+ span.attrStepY[attr][3] = 0.0;
+
+ continue;
+ }
+ }
+ else if (attr == FRAG_ATTRIB_PNTC) {
+ /* GLSL gl_PointCoord.xy (.zw undefined) */
+ span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
+ span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
+ span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
+ span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
+ span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
+ span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
+ tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
+ continue;
+ }
+ /* use vertex's texcoord/attrib */
+ COPY_4V(span.attrStart[attr], vert->attrib[attr]);
+ ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
+ ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
+ ATTRIB_LOOP_END;
+ }
+
+ /* compute pos, bounds and render */
+ {
+ const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
+ const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
+ GLint iSize = (GLint) (size + 0.5F);
+ GLint xmin, xmax, ymin, ymax, iy;
+ GLint iRadius;
+ GLfloat tcoord = t0;
+
+ iSize = MAX2(1, iSize);
+ iRadius = iSize / 2;
+
+ if (iSize & 1) {
+ /* odd size */
+ xmin = (GLint) (x - iRadius);
+ xmax = (GLint) (x + iRadius);
+ ymin = (GLint) (y - iRadius);
+ ymax = (GLint) (y + iRadius);
+ }
+ else {
+ /* even size */
+ /* 0.501 factor allows conformance to pass */
+ xmin = (GLint) (x + 0.501) - iRadius;
+ xmax = xmin + iSize - 1;
+ ymin = (GLint) (y + 0.501) - iRadius;
+ ymax = ymin + iSize - 1;
+ }
+
+ /* render spans */
+ for (iy = ymin; iy <= ymax; iy++) {
+ GLuint i;
+ /* setup texcoord T for this row */
+ for (i = 0; i < numTcoords; i++) {
+ span.attrStart[tCoords[i]][1] = tcoord;
+ }
+
+ /* these might get changed by span clipping */
+ span.x = xmin;
+ span.y = iy;
+ span.end = xmax - xmin + 1;
+
+ _swrast_write_rgba_span(ctx, &span);
+
+ tcoord += dtdy;
+ }
+ }
+}
+
+
+/**
+ * Draw smooth/antialiased point. RGB or CI mode.
+ */
+static void
+smooth_point(GLcontext *ctx, const SWvertex *vert)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLboolean ciMode = !ctx->Visual.rgbMode;
+ SWspan span;
+ GLfloat size, alphaAtten;
+
+ CULL_INVALID(vert);
+
+ /* z coord */
+ if (ctx->DrawBuffer->Visual.depthBits <= 16)
+ span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ else
+ span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ span.zStep = 0;
+
+ size = get_size(ctx, vert, GL_TRUE);
+
+ /* alpha attenuation / fade factor */
+ if (ctx->Multisample._Enabled) {
+ if (vert->pointSize >= ctx->Point.Threshold) {
+ alphaAtten = 1.0F;
+ }
+ else {
+ GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
+ alphaAtten = dsize * dsize;
+ }
+ }
+ else {
+ alphaAtten = 1.0;
+ }
+ (void) alphaAtten; /* not used */
+
+ /* span init */
+ INIT_SPAN(span, GL_POINT);
+ span.interpMask = SPAN_Z | SPAN_RGBA;
+ span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
+
+ span.facing = swrast->PointLineFacing;
+
+ span.red = ChanToFixed(vert->color[0]);
+ span.green = ChanToFixed(vert->color[1]);
+ span.blue = ChanToFixed(vert->color[2]);
+ span.alpha = ChanToFixed(vert->color[3]);
+ span.redStep = 0;
+ span.greenStep = 0;
+ span.blueStep = 0;
+ span.alphaStep = 0;
+
+ /* need these for fragment programs */
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
+
+ ATTRIB_LOOP_BEGIN
+ COPY_4V(span.attrStart[attr], vert->attrib[attr]);
+ ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
+ ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
+ ATTRIB_LOOP_END
+
+ /* compute pos, bounds and render */
+ {
+ const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
+ const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
+ const GLfloat radius = 0.5F * size;
+ const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ const GLfloat rmax = radius + 0.7071F;
+ const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
+ const GLfloat rmax2 = rmax * rmax;
+ const GLfloat cscale = 1.0F / (rmax2 - rmin2);
+ const GLint xmin = (GLint) (x - radius);
+ const GLint xmax = (GLint) (x + radius);
+ const GLint ymin = (GLint) (y - radius);
+ const GLint ymax = (GLint) (y + radius);
+ GLint ix, iy;
+
+ for (iy = ymin; iy <= ymax; iy++) {
+
+ /* these might get changed by span clipping */
+ span.x = xmin;
+ span.y = iy;
+ span.end = xmax - xmin + 1;
+
+ /* compute coverage for each pixel in span */
+ for (ix = xmin; ix <= xmax; ix++) {
+ const GLfloat dx = ix - x + 0.5F;
+ const GLfloat dy = iy - y + 0.5F;
+ const GLfloat dist2 = dx * dx + dy * dy;
+ GLfloat coverage;
+
+ if (dist2 < rmax2) {
+ if (dist2 >= rmin2) {
+ /* compute partial coverage */
+ coverage = 1.0F - (dist2 - rmin2) * cscale;
+ if (ciMode) {
+ /* coverage in [0,15] */
+ coverage *= 15.0;
+ }
+ }
+ else {
+ /* full coverage */
+ coverage = 1.0F;
+ }
+ span.array->mask[ix - xmin] = 1;
+ }
+ else {
+ /* zero coverage - fragment outside the radius */
+ coverage = 0.0;
+ span.array->mask[ix - xmin] = 0;
+ }
+ span.array->coverage[ix - xmin] = coverage;
+ }
+
+ /* render span */
+ _swrast_write_rgba_span(ctx, &span);
+
+ }
+ }
+}
+
+
+/**
+ * Draw large (size >= 1) non-AA point. RGB or CI mode.
+ */
+static void
+large_point(GLcontext *ctx, const SWvertex *vert)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLboolean ciMode = !ctx->Visual.rgbMode;
+ SWspan span;
+ GLfloat size;
+
+ CULL_INVALID(vert);
+
+ /* z coord */
+ if (ctx->DrawBuffer->Visual.depthBits <= 16)
+ span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ else
+ span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+ span.zStep = 0;
+
+ size = get_size(ctx, vert, GL_FALSE);
+
+ /* span init */
+ INIT_SPAN(span, GL_POINT);
+ span.arrayMask = SPAN_XY;
+ span.facing = swrast->PointLineFacing;
+
+ if (ciMode) {
+ span.interpMask = SPAN_Z | SPAN_INDEX;
+ span.index = FloatToFixed(vert->attrib[FRAG_ATTRIB_CI][0]);
+ span.indexStep = 0;
+ }
+ else {
+ span.interpMask = SPAN_Z | SPAN_RGBA;
+ span.red = ChanToFixed(vert->color[0]);
+ span.green = ChanToFixed(vert->color[1]);
+ span.blue = ChanToFixed(vert->color[2]);
+ span.alpha = ChanToFixed(vert->color[3]);
+ span.redStep = 0;
+ span.greenStep = 0;
+ span.blueStep = 0;
+ span.alphaStep = 0;
+ }
+
+ /* need these for fragment programs */
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
+
+ ATTRIB_LOOP_BEGIN
+ COPY_4V(span.attrStart[attr], vert->attrib[attr]);
+ ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
+ ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
+ ATTRIB_LOOP_END
+
+ /* compute pos, bounds and render */
+ {
+ const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
+ const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
+ GLint iSize = (GLint) (size + 0.5F);
+ GLint xmin, xmax, ymin, ymax, ix, iy;
+ GLint iRadius;
+
+ iSize = MAX2(1, iSize);
+ iRadius = iSize / 2;
+
+ if (iSize & 1) {
+ /* odd size */
+ xmin = (GLint) (x - iRadius);
+ xmax = (GLint) (x + iRadius);
+ ymin = (GLint) (y - iRadius);
+ ymax = (GLint) (y + iRadius);
+ }
+ else {
+ /* even size */
+ /* 0.501 factor allows conformance to pass */
+ xmin = (GLint) (x + 0.501) - iRadius;
+ xmax = xmin + iSize - 1;
+ ymin = (GLint) (y + 0.501) - iRadius;
+ ymax = ymin + iSize - 1;
+ }
+
+ /* generate fragments */
+ span.end = 0;
+ for (iy = ymin; iy <= ymax; iy++) {
+ for (ix = xmin; ix <= xmax; ix++) {
+ span.array->x[span.end] = ix;
+ span.array->y[span.end] = iy;
+ span.end++;
+ }
+ }
+ assert(span.end <= MAX_WIDTH);
+ _swrast_write_rgba_span(ctx, &span);
+ }
+}
+
+
+/**
+ * Draw size=1, single-pixel point
+ */
+static void
+pixel_point(GLcontext *ctx, const SWvertex *vert)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLboolean ciMode = !ctx->Visual.rgbMode;
+ /*
+ * Note that unlike the other functions, we put single-pixel points
+ * into a special span array in order to render as many points as
+ * possible with a single _swrast_write_rgba_span() call.
+ */
+ SWspan *span = &(swrast->PointSpan);
+ GLuint count;
+
+ CULL_INVALID(vert);
+
+ /* Span init */
+ span->interpMask = 0;
+ span->arrayMask = SPAN_XY | SPAN_Z;
+ if (ciMode)
+ span->arrayMask |= SPAN_INDEX;
+ else
+ span->arrayMask |= SPAN_RGBA;
+ /*span->arrayMask |= SPAN_LAMBDA;*/
+ span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
+
+ /* need these for fragment programs */
+ span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
+ span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
+ span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
+
+ /* check if we need to flush */
+ if (span->end >= MAX_WIDTH ||
+ (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
+ span->facing != swrast->PointLineFacing) {
+ if (span->end > 0) {
+ if (ciMode)
+ _swrast_write_index_span(ctx, span);
+ else
+ _swrast_write_rgba_span(ctx, span);
+ span->end = 0;
+ }
+ }
+
+ count = span->end;
+
+ span->facing = swrast->PointLineFacing;
+
+ /* fragment attributes */
+ if (ciMode) {
+ span->array->index[count] = (GLuint) vert->attrib[FRAG_ATTRIB_CI][0];
+ }
+ else {
+ span->array->rgba[count][RCOMP] = vert->color[0];
+ span->array->rgba[count][GCOMP] = vert->color[1];
+ span->array->rgba[count][BCOMP] = vert->color[2];
+ span->array->rgba[count][ACOMP] = vert->color[3];
+ }
+ ATTRIB_LOOP_BEGIN
+ COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
+ ATTRIB_LOOP_END
+
+ /* fragment position */
+ span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0];
+ span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1];
+ span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
+
+ span->end = count + 1;
+ ASSERT(span->end <= MAX_WIDTH);
+}
+
+
+/**
+ * Add specular color to primary color, draw point, restore original
+ * primary color.
+ */
+void
+_swrast_add_spec_terms_point(GLcontext *ctx, const SWvertex *v0)
+{
+ SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
+ GLfloat rSum, gSum, bSum;
+ GLchan cSave[4];
+
+ /* save */
+ COPY_CHAN4(cSave, ncv0->color);
+ /* sum */
+ rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
+ /* draw */
+ SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
+ /* restore */
+ COPY_CHAN4(ncv0->color, cSave);
+}
+
+
+/**
+ * Examine current state to determine which point drawing function to use.
+ */
+void
+_swrast_choose_point(GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLfloat size = CLAMP(ctx->Point.Size,
+ ctx->Point.MinSize,
+ ctx->Point.MaxSize);
+
+ if (ctx->RenderMode == GL_RENDER) {
+ if (ctx->Point.PointSprite) {
+ swrast->Point = sprite_point;
+ }
+ else if (ctx->Point.SmoothFlag) {
+ swrast->Point = smooth_point;
+ }
+ else if (size > 1.0 ||
+ ctx->Point._Attenuated ||
+ ctx->VertexProgram.PointSizeEnabled) {
+ swrast->Point = large_point;
+ }
+ else {
+ swrast->Point = pixel_point;
+ }
+ }
+ else if (ctx->RenderMode == GL_FEEDBACK) {
+ swrast->Point = _swrast_feedback_point;
+ }
+ else {
+ /* GL_SELECT mode */
+ swrast->Point = _swrast_select_point;
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_points.h b/mesalib/src/mesa/swrast/s_points.h
new file mode 100644
index 000000000..9e39c601e
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_points.h
@@ -0,0 +1,39 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_POINTS_H
+#define S_POINTS_H
+
+#include "swrast.h"
+
+extern void
+_swrast_choose_point( GLcontext *ctx );
+
+extern void
+_swrast_add_spec_terms_point( GLcontext *ctx,
+ const SWvertex *v0 );
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_readpix.c b/mesalib/src/mesa/swrast/s_readpix.c
new file mode 100644
index 000000000..48b9408d2
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_readpix.c
@@ -0,0 +1,620 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/colormac.h"
+#include "main/convolve.h"
+#include "main/context.h"
+#include "main/feedback.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/pixel.h"
+#include "main/state.h"
+
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_span.h"
+#include "s_stencil.h"
+
+
+/*
+ * Read a block of color index pixels.
+ */
+static void
+read_index_pixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type, GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+ GLint i;
+
+ if (!rb)
+ return;
+
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ /* process image row by row */
+ for (i = 0; i < height; i++) {
+ GLuint index[MAX_WIDTH];
+ GLvoid *dest;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ rb->GetRow(ctx, rb, width, x, y + i, index);
+
+ dest = _mesa_image_address2d(packing, pixels, width, height,
+ GL_COLOR_INDEX, type, i, 0);
+
+ _mesa_pack_index_span(ctx, width, type, dest, index,
+ &ctx->Pack, ctx->_ImageTransferState);
+ }
+}
+
+
+
+/**
+ * Read pixels for format=GL_DEPTH_COMPONENT.
+ */
+static void
+read_depth_pixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type, GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ const GLboolean biasOrScale
+ = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
+
+ if (!rb)
+ return;
+
+ /* clipping should have been done already */
+ ASSERT(x >= 0);
+ ASSERT(y >= 0);
+ ASSERT(x + width <= (GLint) rb->Width);
+ ASSERT(y + height <= (GLint) rb->Height);
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ if (type == GL_UNSIGNED_SHORT && fb->Visual.depthBits == 16
+ && !biasOrScale && !packing->SwapBytes) {
+ /* Special case: directly read 16-bit unsigned depth values. */
+ GLint j;
+ ASSERT(rb->InternalFormat == GL_DEPTH_COMPONENT16);
+ ASSERT(rb->DataType == GL_UNSIGNED_SHORT);
+ for (j = 0; j < height; j++, y++) {
+ void *dest =_mesa_image_address2d(packing, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, j, 0);
+ rb->GetRow(ctx, rb, width, x, y, dest);
+ }
+ }
+ else if (type == GL_UNSIGNED_INT && fb->Visual.depthBits == 24
+ && !biasOrScale && !packing->SwapBytes) {
+ /* Special case: directly read 24-bit unsigned depth values. */
+ GLint j;
+ ASSERT(rb->InternalFormat == GL_DEPTH_COMPONENT24);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (j = 0; j < height; j++, y++) {
+ GLuint *dest = (GLuint *)
+ _mesa_image_address2d(packing, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, j, 0);
+ GLint k;
+ rb->GetRow(ctx, rb, width, x, y, dest);
+ /* convert range from 24-bit to 32-bit */
+ for (k = 0; k < width; k++) {
+ /* Note: put MSByte of 24-bit value into LSByte */
+ dest[k] = (dest[k] << 8) | ((dest[k] >> 16) & 0xff);
+ }
+ }
+ }
+ else if (type == GL_UNSIGNED_INT && fb->Visual.depthBits == 32
+ && !biasOrScale && !packing->SwapBytes) {
+ /* Special case: directly read 32-bit unsigned depth values. */
+ GLint j;
+ ASSERT(rb->InternalFormat == GL_DEPTH_COMPONENT32);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (j = 0; j < height; j++, y++) {
+ void *dest = _mesa_image_address2d(packing, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, j, 0);
+ rb->GetRow(ctx, rb, width, x, y, dest);
+ }
+ }
+ else {
+ /* General case (slower) */
+ GLint j;
+ for (j = 0; j < height; j++, y++) {
+ GLfloat depthValues[MAX_WIDTH];
+ GLvoid *dest = _mesa_image_address2d(packing, pixels, width, height,
+ GL_DEPTH_COMPONENT, type, j, 0);
+ _swrast_read_depth_span_float(ctx, rb, width, x, y, depthValues);
+ _mesa_pack_depth_span(ctx, width, dest, type, depthValues, packing);
+ }
+ }
+}
+
+
+/**
+ * Read pixels for format=GL_STENCIL_INDEX.
+ */
+static void
+read_stencil_pixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type, GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ GLint j;
+
+ if (!rb)
+ return;
+
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ /* process image row by row */
+ for (j=0;j<height;j++,y++) {
+ GLvoid *dest;
+ GLstencil stencil[MAX_WIDTH];
+
+ _swrast_read_stencil_span(ctx, rb, width, x, y, stencil);
+
+ dest = _mesa_image_address2d(packing, pixels, width, height,
+ GL_STENCIL_INDEX, type, j, 0);
+
+ _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
+ }
+}
+
+
+
+/**
+ * Optimized glReadPixels for particular pixel formats when pixel
+ * scaling, biasing, mapping, etc. are disabled.
+ * \return GL_TRUE if success, GL_FALSE if unable to do the readpixels
+ */
+static GLboolean
+fast_read_rgba_pixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ GLbitfield transferOps)
+{
+ struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+
+ if (!rb)
+ return GL_FALSE;
+
+ ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
+
+ /* clipping should have already been done */
+ ASSERT(x + width <= (GLint) rb->Width);
+ ASSERT(y + height <= (GLint) rb->Height);
+
+ /* check for things we can't handle here */
+ if (transferOps ||
+ packing->SwapBytes ||
+ packing->LsbFirst) {
+ return GL_FALSE;
+ }
+
+ if (format == GL_RGBA && rb->DataType == type) {
+ const GLint dstStride = _mesa_image_row_stride(packing, width,
+ format, type);
+ GLubyte *dest
+ = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
+ format, type, 0, 0);
+ GLint row;
+ ASSERT(rb->GetRow);
+ for (row = 0; row < height; row++) {
+ rb->GetRow(ctx, rb, width, x, y + row, dest);
+ dest += dstStride;
+ }
+ return GL_TRUE;
+ }
+
+ if (format == GL_RGB &&
+ rb->DataType == GL_UNSIGNED_BYTE &&
+ type == GL_UNSIGNED_BYTE) {
+ const GLint dstStride = _mesa_image_row_stride(packing, width,
+ format, type);
+ GLubyte *dest
+ = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
+ format, type, 0, 0);
+ GLint row;
+ ASSERT(rb->GetRow);
+ for (row = 0; row < height; row++) {
+ GLubyte tempRow[MAX_WIDTH][4];
+ GLint col;
+ rb->GetRow(ctx, rb, width, x, y + row, tempRow);
+ /* convert RGBA to RGB */
+ for (col = 0; col < width; col++) {
+ dest[col * 3 + 0] = tempRow[col][0];
+ dest[col * 3 + 1] = tempRow[col][1];
+ dest[col * 3 + 2] = tempRow[col][2];
+ }
+ dest += dstStride;
+ }
+ return GL_TRUE;
+ }
+
+ /* not handled */
+ return GL_FALSE;
+}
+
+
+/**
+ * When we're using a low-precision color buffer (like 16-bit 5/6/5)
+ * we have to adjust our color values a bit to pass conformance.
+ * The problem is when a 5 or 6-bit color value is convert to an 8-bit
+ * value and then a floating point value, the floating point values don't
+ * increment uniformly as the 5 or 6-bit value is incremented.
+ *
+ * This function adjusts floating point values to compensate.
+ */
+static void
+adjust_colors(GLcontext *ctx, GLuint n, GLfloat rgba[][4])
+{
+ const GLuint rShift = 8 - ctx->Visual.redBits;
+ const GLuint gShift = 8 - ctx->Visual.greenBits;
+ const GLuint bShift = 8 - ctx->Visual.blueBits;
+ const GLfloat rScale = 1.0F / (GLfloat) ((1 << ctx->Visual.redBits ) - 1);
+ const GLfloat gScale = 1.0F / (GLfloat) ((1 << ctx->Visual.greenBits) - 1);
+ const GLfloat bScale = 1.0F / (GLfloat) ((1 << ctx->Visual.blueBits ) - 1);
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLint r, g, b;
+ /* convert float back to ubyte */
+ CLAMPED_FLOAT_TO_UBYTE(r, rgba[i][RCOMP]);
+ CLAMPED_FLOAT_TO_UBYTE(g, rgba[i][GCOMP]);
+ CLAMPED_FLOAT_TO_UBYTE(b, rgba[i][BCOMP]);
+ /* using only the N most significant bits of the ubyte value, convert to
+ * float in [0,1].
+ */
+ rgba[i][RCOMP] = (GLfloat) (r >> rShift) * rScale;
+ rgba[i][GCOMP] = (GLfloat) (g >> gShift) * gScale;
+ rgba[i][BCOMP] = (GLfloat) (b >> bShift) * bScale;
+ }
+}
+
+
+
+/*
+ * Read R, G, B, A, RGB, L, or LA pixels.
+ */
+static void
+read_rgba_pixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLbitfield transferOps = ctx->_ImageTransferState;
+ struct gl_framebuffer *fb = ctx->ReadBuffer;
+ struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
+
+ if (!rb)
+ return;
+
+ if (type == GL_FLOAT && ((ctx->Color.ClampReadColor == GL_TRUE) ||
+ (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
+ rb->DataType != GL_FLOAT)))
+ transferOps |= IMAGE_CLAMP_BIT;
+
+ /* Try optimized path first */
+ if (fast_read_rgba_pixels(ctx, x, y, width, height,
+ format, type, pixels, packing, transferOps)) {
+ return; /* done! */
+ }
+
+ /* width should never be > MAX_WIDTH since we did clipping earlier */
+ ASSERT(width <= MAX_WIDTH);
+
+ if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
+ GLfloat *dest, *src, *tmpImage, *convImage;
+ GLint row;
+
+ tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!tmpImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
+ return;
+ }
+ convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
+ if (!convImage) {
+ _mesa_free(tmpImage);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
+ return;
+ }
+
+ /* read full RGBA, FLOAT image */
+ dest = tmpImage;
+ for (row = 0; row < height; row++, y++) {
+ if (fb->Visual.rgbMode) {
+ _swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, dest);
+ }
+ else {
+ GLuint index[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ rb->GetRow(ctx, rb, width, x, y, index);
+ _mesa_apply_ci_transfer_ops(ctx,
+ transferOps & IMAGE_SHIFT_OFFSET_BIT,
+ width, index);
+ _mesa_map_ci_to_rgba(ctx, width, index, (GLfloat (*)[4]) dest);
+ }
+ _mesa_apply_rgba_transfer_ops(ctx,
+ transferOps & IMAGE_PRE_CONVOLUTION_BITS,
+ width, (GLfloat (*)[4]) dest);
+ dest += width * 4;
+ }
+
+ /* do convolution */
+ if (ctx->Pixel.Convolution2DEnabled) {
+ _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ else {
+ ASSERT(ctx->Pixel.Separable2DEnabled);
+ _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
+ }
+ _mesa_free(tmpImage);
+
+ /* finish transfer ops and pack the resulting image */
+ src = convImage;
+ for (row = 0; row < height; row++) {
+ GLvoid *dest;
+ dest = _mesa_image_address2d(packing, pixels, width, height,
+ format, type, row, 0);
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) src,
+ format, type, dest, packing,
+ transferOps & IMAGE_POST_CONVOLUTION_BITS);
+ src += width * 4;
+ }
+ _mesa_free(convImage);
+ }
+ else {
+ /* no convolution */
+ const GLint dstStride
+ = _mesa_image_row_stride(packing, width, format, type);
+ GLfloat (*rgba)[4] = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
+ GLint row;
+ GLubyte *dst
+ = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
+ format, type, 0, 0);
+
+ /* make sure we don't apply 1D convolution */
+ transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+ IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+
+ for (row = 0; row < height; row++, y++) {
+
+ /* Get float rgba pixels */
+ if (fb->Visual.rgbMode) {
+ _swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, rgba);
+ }
+ else {
+ /* read CI and convert to RGBA */
+ GLuint index[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ rb->GetRow(ctx, rb, width, x, y, index);
+ _mesa_apply_ci_transfer_ops(ctx,
+ transferOps & IMAGE_SHIFT_OFFSET_BIT,
+ width, index);
+ _mesa_map_ci_to_rgba(ctx, width, index, rgba);
+ }
+
+ /* apply fudge factor for shallow color buffers */
+ if (fb->Visual.redBits < 8 ||
+ fb->Visual.greenBits < 8 ||
+ fb->Visual.blueBits < 8) {
+ adjust_colors(ctx, width, rgba);
+ }
+
+ /* pack the row of RGBA pixels into user's buffer */
+ _mesa_pack_rgba_span_float(ctx, width, rgba, format, type, dst,
+ packing, transferOps);
+
+ dst += dstStride;
+ }
+ }
+}
+
+
+/**
+ * Read combined depth/stencil values.
+ * We'll have already done error checking to be sure the expected
+ * depth and stencil buffers really exist.
+ */
+static void
+read_depth_stencil_pixels(GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type, GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ const GLboolean scaleOrBias
+ = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
+ const GLboolean stencilTransfer = ctx->Pixel.IndexShift
+ || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
+ struct gl_renderbuffer *depthRb, *stencilRb;
+
+ depthRb = ctx->ReadBuffer->_DepthBuffer;
+ stencilRb = ctx->ReadBuffer->_StencilBuffer;
+
+ if (!depthRb || !stencilRb)
+ return;
+
+ depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+
+ if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
+ stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
+ depthRb == stencilRb &&
+ !scaleOrBias &&
+ !stencilTransfer) {
+ /* This is the ideal case.
+ * Reading GL_DEPTH_STENCIL pixels from combined depth/stencil buffer.
+ * Plus, no pixel transfer ops to worry about!
+ */
+ GLint i;
+ GLint dstStride = _mesa_image_row_stride(packing, width,
+ GL_DEPTH_STENCIL_EXT, type);
+ GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
+ width, height,
+ GL_DEPTH_STENCIL_EXT,
+ type, 0, 0);
+ for (i = 0; i < height; i++) {
+ depthRb->GetRow(ctx, depthRb, width, x, y + i, dst);
+ dst += dstStride;
+ }
+ }
+ else {
+ /* Reading GL_DEPTH_STENCIL pixels from separate depth/stencil buffers,
+ * or we need pixel transfer.
+ */
+ GLint i;
+ depthRb = ctx->ReadBuffer->_DepthBuffer;
+ stencilRb = ctx->ReadBuffer->_StencilBuffer;
+
+ for (i = 0; i < height; i++) {
+ GLstencil stencilVals[MAX_WIDTH];
+
+ GLuint *depthStencilDst = (GLuint *)
+ _mesa_image_address2d(packing, pixels, width, height,
+ GL_DEPTH_STENCIL_EXT, type, i, 0);
+
+ _swrast_read_stencil_span(ctx, stencilRb, width,
+ x, y + i, stencilVals);
+
+ if (!scaleOrBias && !stencilTransfer
+ && ctx->ReadBuffer->Visual.depthBits == 24) {
+ /* ideal case */
+ GLuint zVals[MAX_WIDTH]; /* 24-bit values! */
+ GLint j;
+ ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
+ /* note, we've already been clipped */
+ depthRb->GetRow(ctx, depthRb, width, x, y + i, zVals);
+ for (j = 0; j < width; j++) {
+ depthStencilDst[j] = (zVals[j] << 8) | (stencilVals[j] & 0xff);
+ }
+ }
+ else {
+ /* general case */
+ GLfloat depthVals[MAX_WIDTH];
+ _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i,
+ depthVals);
+ _mesa_pack_depth_stencil_span(ctx, width, depthStencilDst,
+ depthVals, stencilVals, packing);
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Software fallback routine for ctx->Driver.ReadPixels().
+ * By time we get here, all error checking will have been done.
+ */
+void
+_swrast_ReadPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *pixels )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ struct gl_pixelstore_attrib clippedPacking = *packing;
+
+ /* Need to do swrast_render_start() before clipping or anything else
+ * since this is where a driver may grab the hw lock and get an updated
+ * window size.
+ */
+ swrast_render_start(ctx);
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ /* Do all needed clipping here, so that we can forget about it later */
+ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
+ /* The ReadPixels region is totally outside the window bounds */
+ swrast_render_finish(ctx);
+ return;
+ }
+
+ pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
+ if (!pixels)
+ return;
+
+ switch (format) {
+ case GL_COLOR_INDEX:
+ read_index_pixels(ctx, x, y, width, height, type, pixels,
+ &clippedPacking);
+ break;
+ case GL_STENCIL_INDEX:
+ read_stencil_pixels(ctx, x, y, width, height, type, pixels,
+ &clippedPacking);
+ break;
+ case GL_DEPTH_COMPONENT:
+ read_depth_pixels(ctx, x, y, width, height, type, pixels,
+ &clippedPacking);
+ 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:
+ case GL_BGR:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ read_rgba_pixels(ctx, x, y, width, height,
+ format, type, pixels, &clippedPacking);
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ read_depth_stencil_pixels(ctx, x, y, width, height,
+ type, pixels, &clippedPacking);
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected format in _swrast_ReadPixels");
+ /* don't return yet, clean-up */
+ }
+
+ swrast_render_finish(ctx);
+
+ _mesa_unmap_pbo_dest(ctx, &clippedPacking);
+}
diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c
new file mode 100644
index 000000000..0e2793b47
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_span.c
@@ -0,0 +1,1795 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file swrast/s_span.c
+ * \brief Span processing functions used by all rasterization functions.
+ * This is where all the per-fragment tests are performed
+ * \author Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/image.h"
+
+#include "s_atifragshader.h"
+#include "s_alpha.h"
+#include "s_blend.h"
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_fog.h"
+#include "s_logic.h"
+#include "s_masking.h"
+#include "s_fragprog.h"
+#include "s_span.h"
+#include "s_stencil.h"
+#include "s_texcombine.h"
+
+
+/**
+ * Set default fragment attributes for the span using the
+ * current raster values. Used prior to glDraw/CopyPixels
+ * and glBitmap.
+ */
+void
+_swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
+{
+ /* Z*/
+ {
+ const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
+ if (ctx->DrawBuffer->Visual.depthBits <= 16)
+ span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
+ else {
+ GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
+ tmpf = MIN2(tmpf, depthMax);
+ span->z = (GLint)tmpf;
+ }
+ span->zStep = 0;
+ span->interpMask |= SPAN_Z;
+ }
+
+ /* W (for perspective correction) */
+ span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
+ span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
+ span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
+
+ /* primary color, or color index */
+ if (ctx->Visual.rgbMode) {
+ GLchan r, g, b, a;
+ UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
+#if CHAN_TYPE == GL_FLOAT
+ span->red = r;
+ span->green = g;
+ span->blue = b;
+ span->alpha = a;
+#else
+ span->red = IntToFixed(r);
+ span->green = IntToFixed(g);
+ span->blue = IntToFixed(b);
+ span->alpha = IntToFixed(a);
+#endif
+ span->redStep = 0;
+ span->greenStep = 0;
+ span->blueStep = 0;
+ span->alphaStep = 0;
+ span->interpMask |= SPAN_RGBA;
+
+ COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
+ ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
+ ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
+ }
+ else {
+ span->index = FloatToFixed(ctx->Current.RasterIndex);
+ span->indexStep = 0;
+ span->interpMask |= SPAN_INDEX;
+ }
+
+ /* Secondary color */
+ if (ctx->Visual.rgbMode && (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled))
+ {
+ COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
+ ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
+ ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
+ }
+
+ /* fog */
+ {
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat fogVal; /* a coord or a blend factor */
+ if (swrast->_PreferPixelFog) {
+ /* fog blend factors will be computed from fog coordinates per pixel */
+ fogVal = ctx->Current.RasterDistance;
+ }
+ else {
+ /* fog blend factor should be computed from fogcoord now */
+ fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
+ }
+ span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
+ span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
+ span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
+ }
+
+ /* texcoords */
+ {
+ GLuint i;
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ const GLuint attr = FRAG_ATTRIB_TEX0 + i;
+ const GLfloat *tc = ctx->Current.RasterTexCoords[i];
+ if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
+ COPY_4V(span->attrStart[attr], tc);
+ }
+ else if (tc[3] > 0.0F) {
+ /* use (s/q, t/q, r/q, 1) */
+ span->attrStart[attr][0] = tc[0] / tc[3];
+ span->attrStart[attr][1] = tc[1] / tc[3];
+ span->attrStart[attr][2] = tc[2] / tc[3];
+ span->attrStart[attr][3] = 1.0;
+ }
+ else {
+ ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
+ }
+ ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
+ ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ }
+}
+
+
+/**
+ * Interpolate the active attributes (and'd with attrMask) to
+ * fill in span->array->attribs[].
+ * Perspective correction will be done. The point/line/triangle function
+ * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
+ */
+static INLINE void
+interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ /*
+ * Don't overwrite existing array values, such as colors that may have
+ * been produced by glDraw/CopyPixels.
+ */
+ attrMask &= ~span->arrayAttribs;
+
+ ATTRIB_LOOP_BEGIN
+ if (attrMask & (1 << attr)) {
+ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
+ const GLfloat dv0dx = span->attrStepX[attr][0];
+ const GLfloat dv1dx = span->attrStepX[attr][1];
+ const GLfloat dv2dx = span->attrStepX[attr][2];
+ const GLfloat dv3dx = span->attrStepX[attr][3];
+ GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
+ GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
+ GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
+ GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
+ GLuint k;
+ for (k = 0; k < span->end; k++) {
+ const GLfloat invW = 1.0f / w;
+ span->array->attribs[attr][k][0] = v0 * invW;
+ span->array->attribs[attr][k][1] = v1 * invW;
+ span->array->attribs[attr][k][2] = v2 * invW;
+ span->array->attribs[attr][k][3] = v3 * invW;
+ v0 += dv0dx;
+ v1 += dv1dx;
+ v2 += dv2dx;
+ v3 += dv3dx;
+ w += dwdx;
+ }
+ ASSERT((span->arrayAttribs & (1 << attr)) == 0);
+ span->arrayAttribs |= (1 << attr);
+ }
+ ATTRIB_LOOP_END
+}
+
+
+/**
+ * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
+ * color array.
+ */
+static INLINE void
+interpolate_int_colors(GLcontext *ctx, SWspan *span)
+{
+ const GLuint n = span->end;
+ GLuint i;
+
+#if CHAN_BITS != 32
+ ASSERT(!(span->arrayMask & SPAN_RGBA));
+#endif
+
+ switch (span->array->ChanType) {
+#if CHAN_BITS != 32
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ if (span->interpMask & SPAN_FLAT) {
+ GLubyte color[4];
+ color[RCOMP] = FixedToInt(span->red);
+ color[GCOMP] = FixedToInt(span->green);
+ color[BCOMP] = FixedToInt(span->blue);
+ color[ACOMP] = FixedToInt(span->alpha);
+ for (i = 0; i < n; i++) {
+ COPY_4UBV(rgba[i], color);
+ }
+ }
+ else {
+ GLfixed r = span->red;
+ GLfixed g = span->green;
+ GLfixed b = span->blue;
+ GLfixed a = span->alpha;
+ GLint dr = span->redStep;
+ GLint dg = span->greenStep;
+ GLint db = span->blueStep;
+ GLint da = span->alphaStep;
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = FixedToChan(r);
+ rgba[i][GCOMP] = FixedToChan(g);
+ rgba[i][BCOMP] = FixedToChan(b);
+ rgba[i][ACOMP] = FixedToChan(a);
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ if (span->interpMask & SPAN_FLAT) {
+ GLushort color[4];
+ color[RCOMP] = FixedToInt(span->red);
+ color[GCOMP] = FixedToInt(span->green);
+ color[BCOMP] = FixedToInt(span->blue);
+ color[ACOMP] = FixedToInt(span->alpha);
+ for (i = 0; i < n; i++) {
+ COPY_4V(rgba[i], color);
+ }
+ }
+ else {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ GLfixed r, g, b, a;
+ GLint dr, dg, db, da;
+ r = span->red;
+ g = span->green;
+ b = span->blue;
+ a = span->alpha;
+ dr = span->redStep;
+ dg = span->greenStep;
+ db = span->blueStep;
+ da = span->alphaStep;
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = FixedToChan(r);
+ rgba[i][GCOMP] = FixedToChan(g);
+ rgba[i][BCOMP] = FixedToChan(b);
+ rgba[i][ACOMP] = FixedToChan(a);
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+ }
+ }
+ break;
+#endif
+ case GL_FLOAT:
+ interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ break;
+ default:
+ _mesa_problem(NULL, "bad datatype in interpolate_int_colors");
+ }
+ span->arrayMask |= SPAN_RGBA;
+}
+
+
+/**
+ * Populate the FRAG_ATTRIB_COL0 array.
+ */
+static INLINE void
+interpolate_float_colors(SWspan *span)
+{
+ GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ const GLuint n = span->end;
+ GLuint i;
+
+ assert(!(span->arrayAttribs & FRAG_BIT_COL0));
+
+ if (span->arrayMask & SPAN_RGBA) {
+ /* convert array of int colors */
+ for (i = 0; i < n; i++) {
+ col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]);
+ col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]);
+ col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]);
+ col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]);
+ }
+ }
+ else {
+ /* interpolate red/green/blue/alpha to get float colors */
+ ASSERT(span->interpMask & SPAN_RGBA);
+ if (span->interpMask & SPAN_FLAT) {
+ GLfloat r = FixedToFloat(span->red);
+ GLfloat g = FixedToFloat(span->green);
+ GLfloat b = FixedToFloat(span->blue);
+ GLfloat a = FixedToFloat(span->alpha);
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(col0[i], r, g, b, a);
+ }
+ }
+ else {
+ GLfloat r = FixedToFloat(span->red);
+ GLfloat g = FixedToFloat(span->green);
+ GLfloat b = FixedToFloat(span->blue);
+ GLfloat a = FixedToFloat(span->alpha);
+ GLfloat dr = FixedToFloat(span->redStep);
+ GLfloat dg = FixedToFloat(span->greenStep);
+ GLfloat db = FixedToFloat(span->blueStep);
+ GLfloat da = FixedToFloat(span->alphaStep);
+ for (i = 0; i < n; i++) {
+ col0[i][0] = r;
+ col0[i][1] = g;
+ col0[i][2] = b;
+ col0[i][3] = a;
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+ }
+ }
+
+ span->arrayAttribs |= FRAG_BIT_COL0;
+ span->array->ChanType = GL_FLOAT;
+}
+
+
+
+/* Fill in the span.color.index array from the interpolation values */
+static INLINE void
+interpolate_indexes(GLcontext *ctx, SWspan *span)
+{
+ GLfixed index = span->index;
+ const GLint indexStep = span->indexStep;
+ const GLuint n = span->end;
+ GLuint *indexes = span->array->index;
+ GLuint i;
+ (void) ctx;
+
+ ASSERT(!(span->arrayMask & SPAN_INDEX));
+
+ if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
+ /* constant color */
+ index = FixedToInt(index);
+ for (i = 0; i < n; i++) {
+ indexes[i] = index;
+ }
+ }
+ else {
+ /* interpolate */
+ for (i = 0; i < n; i++) {
+ indexes[i] = FixedToInt(index);
+ index += indexStep;
+ }
+ }
+ span->arrayMask |= SPAN_INDEX;
+ span->interpMask &= ~SPAN_INDEX;
+}
+
+
+/**
+ * Fill in the span.zArray array from the span->z, zStep values.
+ */
+void
+_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
+{
+ const GLuint n = span->end;
+ GLuint i;
+
+ ASSERT(!(span->arrayMask & SPAN_Z));
+
+ if (ctx->DrawBuffer->Visual.depthBits <= 16) {
+ GLfixed zval = span->z;
+ GLuint *z = span->array->z;
+ for (i = 0; i < n; i++) {
+ z[i] = FixedToInt(zval);
+ zval += span->zStep;
+ }
+ }
+ else {
+ /* Deep Z buffer, no fixed->int shift */
+ GLuint zval = span->z;
+ GLuint *z = span->array->z;
+ for (i = 0; i < n; i++) {
+ z[i] = zval;
+ zval += span->zStep;
+ }
+ }
+ span->interpMask &= ~SPAN_Z;
+ span->arrayMask |= SPAN_Z;
+}
+
+
+/**
+ * Compute mipmap LOD from partial derivatives.
+ * This the ideal solution, as given in the OpenGL spec.
+ */
+GLfloat
+_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+ GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+ GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
+{
+ GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
+ GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
+ GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
+ GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
+ GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
+ GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
+ GLfloat rho = MAX2(x, y);
+ GLfloat lambda = LOG2(rho);
+ return lambda;
+}
+
+
+/**
+ * Compute mipmap LOD from partial derivatives.
+ * This is a faster approximation than above function.
+ */
+#if 0
+GLfloat
+_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+ GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+ GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
+{
+ GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
+ GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
+ GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
+ GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
+ GLfloat maxU, maxV, rho, lambda;
+ dsdx2 = FABSF(dsdx2);
+ dsdy2 = FABSF(dsdy2);
+ dtdx2 = FABSF(dtdx2);
+ dtdy2 = FABSF(dtdy2);
+ maxU = MAX2(dsdx2, dsdy2) * texW;
+ maxV = MAX2(dtdx2, dtdy2) * texH;
+ rho = MAX2(maxU, maxV);
+ lambda = LOG2(rho);
+ return lambda;
+}
+#endif
+
+
+/**
+ * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
+ * using the attrStart/Step values.
+ *
+ * This function only used during fixed-function fragment processing.
+ *
+ * Note: in the places where we divide by Q (or mult by invQ) we're
+ * really doing two things: perspective correction and texcoord
+ * projection. Remember, for texcoord (s,t,r,q) we need to index
+ * texels with (s/q, t/q, r/q).
+ */
+static void
+interpolate_texcoords(GLcontext *ctx, SWspan *span)
+{
+ const GLuint maxUnit
+ = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
+ GLuint u;
+
+ /* XXX CoordUnits vs. ImageUnits */
+ for (u = 0; u < maxUnit; u++) {
+ if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
+ const GLuint attr = FRAG_ATTRIB_TEX0 + u;
+ const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
+ GLfloat texW, texH;
+ GLboolean needLambda;
+ GLfloat (*texcoord)[4] = span->array->attribs[attr];
+ GLfloat *lambda = span->array->lambda[u];
+ const GLfloat dsdx = span->attrStepX[attr][0];
+ const GLfloat dsdy = span->attrStepY[attr][0];
+ const GLfloat dtdx = span->attrStepX[attr][1];
+ const GLfloat dtdy = span->attrStepY[attr][1];
+ const GLfloat drdx = span->attrStepX[attr][2];
+ const GLfloat dqdx = span->attrStepX[attr][3];
+ const GLfloat dqdy = span->attrStepY[attr][3];
+ GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
+ GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
+ GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
+ GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
+
+ if (obj) {
+ const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
+ needLambda = (obj->MinFilter != obj->MagFilter)
+ || ctx->FragmentProgram._Current;
+ texW = img->WidthScale;
+ texH = img->HeightScale;
+ }
+ else {
+ /* using a fragment program */
+ texW = 1.0;
+ texH = 1.0;
+ needLambda = GL_FALSE;
+ }
+
+ if (needLambda) {
+ GLuint i;
+ if (ctx->FragmentProgram._Current
+ || ctx->ATIFragmentShader._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invW);
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+ }
+ else {
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+ texcoord[i][0] = s * invQ;
+ texcoord[i][1] = t * invQ;
+ texcoord[i][2] = r * invQ;
+ texcoord[i][3] = q;
+ lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+ dqdx, dqdy, texW, texH,
+ s, t, q, invQ);
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ }
+ }
+ span->arrayMask |= SPAN_LAMBDA;
+ }
+ else {
+ GLuint i;
+ if (ctx->FragmentProgram._Current ||
+ ctx->ATIFragmentShader._Enabled) {
+ /* do perspective correction but don't divide s, t, r by q */
+ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
+ GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invW = 1.0F / w;
+ texcoord[i][0] = s * invW;
+ texcoord[i][1] = t * invW;
+ texcoord[i][2] = r * invW;
+ texcoord[i][3] = q * invW;
+ lambda[i] = 0.0;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ w += dwdx;
+ }
+ }
+ else if (dqdx == 0.0F) {
+ /* Ortho projection or polygon's parallel to window X axis */
+ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+ for (i = 0; i < span->end; i++) {
+ texcoord[i][0] = s * invQ;
+ texcoord[i][1] = t * invQ;
+ texcoord[i][2] = r * invQ;
+ texcoord[i][3] = q;
+ lambda[i] = 0.0;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ }
+ }
+ else {
+ for (i = 0; i < span->end; i++) {
+ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+ texcoord[i][0] = s * invQ;
+ texcoord[i][1] = t * invQ;
+ texcoord[i][2] = r * invQ;
+ texcoord[i][3] = q;
+ lambda[i] = 0.0;
+ s += dsdx;
+ t += dtdx;
+ r += drdx;
+ q += dqdx;
+ }
+ }
+ } /* lambda */
+ } /* if */
+ } /* for */
+}
+
+
+/**
+ * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
+ */
+static INLINE void
+interpolate_wpos(GLcontext *ctx, SWspan *span)
+{
+ GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
+ GLuint i;
+ const GLfloat zScale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
+ GLfloat w, dw;
+
+ if (span->arrayMask & SPAN_XY) {
+ for (i = 0; i < span->end; i++) {
+ wpos[i][0] = (GLfloat) span->array->x[i];
+ wpos[i][1] = (GLfloat) span->array->y[i];
+ }
+ }
+ else {
+ for (i = 0; i < span->end; i++) {
+ wpos[i][0] = (GLfloat) span->x + i;
+ wpos[i][1] = (GLfloat) span->y;
+ }
+ }
+
+ dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
+ w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
+ for (i = 0; i < span->end; i++) {
+ wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
+ wpos[i][3] = w;
+ w += dw;
+ }
+}
+
+
+/**
+ * Apply the current polygon stipple pattern to a span of pixels.
+ */
+static INLINE void
+stipple_polygon_span(GLcontext *ctx, SWspan *span)
+{
+ GLubyte *mask = span->array->mask;
+
+ ASSERT(ctx->Polygon.StippleFlag);
+
+ if (span->arrayMask & SPAN_XY) {
+ /* arrays of x/y pixel coords */
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ const GLint col = span->array->x[i] % 32;
+ const GLint row = span->array->y[i] % 32;
+ const GLuint stipple = ctx->PolygonStipple[row];
+ if (((1 << col) & stipple) == 0) {
+ mask[i] = 0;
+ }
+ }
+ }
+ else {
+ /* horizontal span of pixels */
+ const GLuint highBit = 1 << 31;
+ const GLuint stipple = ctx->PolygonStipple[span->y % 32];
+ GLuint i, m = highBit >> (GLuint) (span->x % 32);
+ for (i = 0; i < span->end; i++) {
+ if ((m & stipple) == 0) {
+ mask[i] = 0;
+ }
+ m = m >> 1;
+ if (m == 0) {
+ m = highBit;
+ }
+ }
+ }
+ span->writeAll = GL_FALSE;
+}
+
+
+/**
+ * Clip a pixel span to the current buffer/window boundaries:
+ * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish
+ * window clipping and scissoring.
+ * Return: GL_TRUE some pixels still visible
+ * GL_FALSE nothing visible
+ */
+static INLINE GLuint
+clip_span( GLcontext *ctx, SWspan *span )
+{
+ const GLint xmin = ctx->DrawBuffer->_Xmin;
+ const GLint xmax = ctx->DrawBuffer->_Xmax;
+ const GLint ymin = ctx->DrawBuffer->_Ymin;
+ const GLint ymax = ctx->DrawBuffer->_Ymax;
+
+ span->leftClip = 0;
+
+ if (span->arrayMask & SPAN_XY) {
+ /* arrays of x/y pixel coords */
+ const GLint *x = span->array->x;
+ const GLint *y = span->array->y;
+ const GLint n = span->end;
+ GLubyte *mask = span->array->mask;
+ GLint i;
+ if (span->arrayMask & SPAN_MASK) {
+ /* note: using & intead of && to reduce branches */
+ for (i = 0; i < n; i++) {
+ mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
+ & (y[i] >= ymin) & (y[i] < ymax);
+ }
+ }
+ else {
+ /* note: using & intead of && to reduce branches */
+ for (i = 0; i < n; i++) {
+ mask[i] = (x[i] >= xmin) & (x[i] < xmax)
+ & (y[i] >= ymin) & (y[i] < ymax);
+ }
+ }
+ return GL_TRUE; /* some pixels visible */
+ }
+ else {
+ /* horizontal span of pixels */
+ const GLint x = span->x;
+ const GLint y = span->y;
+ GLint n = span->end;
+
+ /* Trivial rejection tests */
+ if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
+ span->end = 0;
+ return GL_FALSE; /* all pixels clipped */
+ }
+
+ /* Clip to right */
+ if (x + n > xmax) {
+ ASSERT(x < xmax);
+ n = span->end = xmax - x;
+ }
+
+ /* Clip to the left */
+ if (x < xmin) {
+ const GLint leftClip = xmin - x;
+ GLuint i;
+
+ ASSERT(leftClip > 0);
+ ASSERT(x + n > xmin);
+
+ /* Clip 'leftClip' pixels from the left side.
+ * The span->leftClip field will be applied when we interpolate
+ * fragment attributes.
+ * For arrays of values, shift them left.
+ */
+ for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
+ if (span->arrayAttribs & (1 << i)) {
+ /* shift array elements left by 'leftClip' */
+ _mesa_memcpy(span->array->attribs[i],
+ span->array->attribs[i] + leftClip,
+ (n - leftClip) * 4 * sizeof(GLfloat));
+ }
+ }
+
+ span->leftClip = leftClip;
+ span->x = xmin;
+ span->end -= leftClip;
+ span->writeAll = GL_FALSE;
+ }
+
+ ASSERT(span->x >= xmin);
+ ASSERT(span->x + span->end <= xmax);
+ ASSERT(span->y >= ymin);
+ ASSERT(span->y < ymax);
+
+ return GL_TRUE; /* some pixels visible */
+ }
+}
+
+
+/**
+ * Apply all the per-fragment opertions to a span of color index fragments
+ * and write them to the enabled color drawbuffers.
+ * The 'span' parameter can be considered to be const. Note that
+ * span->interpMask and span->arrayMask may be changed but will be restored
+ * to their original values before returning.
+ */
+void
+_swrast_write_index_span( GLcontext *ctx, SWspan *span)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLbitfield origInterpMask = span->interpMask;
+ const GLbitfield origArrayMask = span->arrayMask;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ ASSERT(span->end <= MAX_WIDTH);
+ ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
+ span->primitive == GL_POLYGON || span->primitive == GL_BITMAP);
+ ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
+ /*
+ ASSERT((span->interpMask & span->arrayMask) == 0);
+ */
+
+ if (span->arrayMask & SPAN_MASK) {
+ /* mask was initialized by caller, probably glBitmap */
+ span->writeAll = GL_FALSE;
+ }
+ else {
+ _mesa_memset(span->array->mask, 1, span->end);
+ span->writeAll = GL_TRUE;
+ }
+
+ /* Clipping */
+ if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
+ if (!clip_span(ctx, span)) {
+ return;
+ }
+ }
+
+ if (!(span->arrayMask & SPAN_MASK)) {
+ /* post-clip sanity check */
+ assert(span->x >= 0);
+ assert(span->y >= 0);
+ }
+
+ /* Depth bounds test */
+ if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
+ if (!_swrast_depth_bounds_test(ctx, span)) {
+ return;
+ }
+ }
+
+#ifdef DEBUG
+ /* Make sure all fragments are within window bounds */
+ if (span->arrayMask & SPAN_XY) {
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ if (span->array->mask[i]) {
+ assert(span->array->x[i] >= fb->_Xmin);
+ assert(span->array->x[i] < fb->_Xmax);
+ assert(span->array->y[i] >= fb->_Ymin);
+ assert(span->array->y[i] < fb->_Ymax);
+ }
+ }
+ }
+#endif
+
+ /* Polygon Stippling */
+ if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
+ stipple_polygon_span(ctx, span);
+ }
+
+ /* Stencil and Z testing */
+ if (ctx->Stencil._Enabled || ctx->Depth.Test) {
+ if (!(span->arrayMask & SPAN_Z))
+ _swrast_span_interpolate_z(ctx, span);
+
+ if (ctx->Stencil._Enabled) {
+ if (!_swrast_stencil_and_ztest_span(ctx, span)) {
+ span->arrayMask = origArrayMask;
+ return;
+ }
+ }
+ else {
+ ASSERT(ctx->Depth.Test);
+ if (!_swrast_depth_test_span(ctx, span)) {
+ span->interpMask = origInterpMask;
+ span->arrayMask = origArrayMask;
+ return;
+ }
+ }
+ }
+
+#if FEATURE_ARB_occlusion_query
+ if (ctx->Query.CurrentOcclusionObject) {
+ /* update count of 'passed' fragments */
+ struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
+ GLuint i;
+ for (i = 0; i < span->end; i++)
+ q->Result += span->array->mask[i];
+ }
+#endif
+
+ /* we have to wait until after occlusion to do this test */
+ if (ctx->Color.IndexMask == 0) {
+ /* write no pixels */
+ span->arrayMask = origArrayMask;
+ return;
+ }
+
+ /* Interpolate the color indexes if needed */
+ if (swrast->_FogEnabled ||
+ ctx->Color.IndexLogicOpEnabled ||
+ ctx->Color.IndexMask != 0xffffffff ||
+ (span->arrayMask & SPAN_COVERAGE)) {
+ if (!(span->arrayMask & SPAN_INDEX) /*span->interpMask & SPAN_INDEX*/) {
+ interpolate_indexes(ctx, span);
+ }
+ }
+
+ /* Fog */
+ if (swrast->_FogEnabled) {
+ _swrast_fog_ci_span(ctx, span);
+ }
+
+ /* Antialias coverage application */
+ if (span->arrayMask & SPAN_COVERAGE) {
+ const GLfloat *coverage = span->array->coverage;
+ GLuint *index = span->array->index;
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ ASSERT(coverage[i] < 16);
+ index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
+ }
+ }
+
+ /*
+ * Write to renderbuffers
+ */
+ {
+ const GLuint numBuffers = fb->_NumColorDrawBuffers;
+ GLuint buf;
+
+ for (buf = 0; buf < numBuffers; buf++) {
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
+ GLuint indexSave[MAX_WIDTH];
+
+ ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
+
+ if (numBuffers > 1) {
+ /* save indexes for second, third renderbuffer writes */
+ _mesa_memcpy(indexSave, span->array->index,
+ span->end * sizeof(indexSave[0]));
+ }
+
+ if (ctx->Color.IndexLogicOpEnabled) {
+ _swrast_logicop_ci_span(ctx, rb, span);
+ }
+
+ if (ctx->Color.IndexMask != 0xffffffff) {
+ _swrast_mask_ci_span(ctx, rb, span);
+ }
+
+ if (!(span->arrayMask & SPAN_INDEX) && span->indexStep == 0) {
+ /* all fragments have same color index */
+ GLubyte index8;
+ GLushort index16;
+ GLuint index32;
+ void *value;
+
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ index8 = FixedToInt(span->index);
+ value = &index8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ index16 = FixedToInt(span->index);
+ value = &index16;
+ }
+ else {
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ index32 = FixedToInt(span->index);
+ value = &index32;
+ }
+
+ if (span->arrayMask & SPAN_XY) {
+ rb->PutMonoValues(ctx, rb, span->end, span->array->x,
+ span->array->y, value, span->array->mask);
+ }
+ else {
+ rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
+ value, span->array->mask);
+ }
+ }
+ else {
+ /* each fragment is a different color */
+ GLubyte index8[MAX_WIDTH];
+ GLushort index16[MAX_WIDTH];
+ void *values;
+
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ GLuint k;
+ for (k = 0; k < span->end; k++) {
+ index8[k] = (GLubyte) span->array->index[k];
+ }
+ values = index8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLuint k;
+ for (k = 0; k < span->end; k++) {
+ index16[k] = (GLushort) span->array->index[k];
+ }
+ values = index16;
+ }
+ else {
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ values = span->array->index;
+ }
+
+ if (span->arrayMask & SPAN_XY) {
+ rb->PutValues(ctx, rb, span->end,
+ span->array->x, span->array->y,
+ values, span->array->mask);
+ }
+ else {
+ rb->PutRow(ctx, rb, span->end, span->x, span->y,
+ values, span->array->mask);
+ }
+ }
+
+ if (buf + 1 < numBuffers) {
+ /* restore original span values */
+ _mesa_memcpy(span->array->index, indexSave,
+ span->end * sizeof(indexSave[0]));
+ }
+ } /* for buf */
+ }
+
+ span->interpMask = origInterpMask;
+ span->arrayMask = origArrayMask;
+}
+
+
+/**
+ * Add specular colors to primary colors.
+ * Only called during fixed-function operation.
+ * Result is float color array (FRAG_ATTRIB_COL0).
+ */
+static INLINE void
+add_specular(GLcontext *ctx, SWspan *span)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLubyte *mask = span->array->mask;
+ GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
+ GLuint i;
+
+ ASSERT(!ctx->FragmentProgram._Current);
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
+ (void) swrast; /* silence warning */
+
+ if (span->array->ChanType == GL_FLOAT) {
+ if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ }
+ }
+ else {
+ /* need float colors */
+ if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ interpolate_float_colors(span);
+ }
+ }
+
+ if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
+ /* XXX could avoid this and interpolate COL1 in the loop below */
+ interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
+ }
+
+ ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
+ ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
+
+ for (i = 0; i < span->end; i++) {
+ if (mask[i]) {
+ col0[i][0] += col1[i][0];
+ col0[i][1] += col1[i][1];
+ col0[i][2] += col1[i][2];
+ }
+ }
+
+ span->array->ChanType = GL_FLOAT;
+}
+
+
+/**
+ * Apply antialiasing coverage value to alpha values.
+ */
+static INLINE void
+apply_aa_coverage(SWspan *span)
+{
+ const GLfloat *coverage = span->array->coverage;
+ GLuint i;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->rgba8;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat a = rgba[i][ACOMP] * coverage[i];
+ rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
+ ASSERT(coverage[i] >= 0.0);
+ ASSERT(coverage[i] <= 1.0);
+ }
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->rgba16;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat a = rgba[i][ACOMP] * coverage[i];
+ rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ for (i = 0; i < span->end; i++) {
+ rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
+ /* clamp later */
+ }
+ }
+}
+
+
+/**
+ * Clamp span's float colors to [0,1]
+ */
+static INLINE void
+clamp_colors(SWspan *span)
+{
+ GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+ GLuint i;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ for (i = 0; i < span->end; i++) {
+ rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
+ rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
+ rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
+ rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
+ }
+}
+
+
+/**
+ * Convert the span's color arrays to the given type.
+ * The only way 'output' can be greater than zero is when we have a fragment
+ * program that writes to gl_FragData[1] or higher.
+ * \param output which fragment program color output is being processed
+ */
+static INLINE void
+convert_color_type(SWspan *span, GLenum newType, GLuint output)
+{
+ GLvoid *src, *dst;
+
+ if (output > 0 || span->array->ChanType == GL_FLOAT) {
+ src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
+ span->array->ChanType = GL_FLOAT;
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ src = span->array->rgba8;
+ }
+ else {
+ ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
+ src = span->array->rgba16;
+ }
+
+ if (newType == GL_UNSIGNED_BYTE) {
+ dst = span->array->rgba8;
+ }
+ else if (newType == GL_UNSIGNED_SHORT) {
+ dst = span->array->rgba16;
+ }
+ else {
+ dst = span->array->attribs[FRAG_ATTRIB_COL0];
+ }
+
+ _mesa_convert_colors(span->array->ChanType, src,
+ newType, dst,
+ span->end, span->array->mask);
+
+ span->array->ChanType = newType;
+ span->array->rgba = dst;
+}
+
+
+
+/**
+ * Apply fragment shader, fragment program or normal texturing to span.
+ */
+static INLINE void
+shade_texture_span(GLcontext *ctx, SWspan *span)
+{
+ GLbitfield inputsRead;
+
+ /* Determine which fragment attributes are actually needed */
+ if (ctx->FragmentProgram._Current) {
+ inputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
+ }
+ else {
+ /* XXX we could be a bit smarter about this */
+ inputsRead = ~0;
+ }
+
+ if (ctx->FragmentProgram._Current ||
+ ctx->ATIFragmentShader._Enabled) {
+ /* programmable shading */
+ if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
+ convert_color_type(span, GL_FLOAT, 0);
+ }
+ if (span->primitive != GL_POINT ||
+ (span->interpMask & SPAN_RGBA) ||
+ ctx->Point.PointSprite) {
+ /* for single-pixel points, we populated the arrays already */
+ interpolate_active_attribs(ctx, span, ~0);
+ }
+ span->array->ChanType = GL_FLOAT;
+
+ if (!(span->arrayMask & SPAN_Z))
+ _swrast_span_interpolate_z (ctx, span);
+
+#if 0
+ if (inputsRead & FRAG_BIT_WPOS)
+#else
+ /* XXX always interpolate wpos so that DDX/DDY work */
+#endif
+ interpolate_wpos(ctx, span);
+
+ /* Run fragment program/shader now */
+ if (ctx->FragmentProgram._Current) {
+ _swrast_exec_fragment_program(ctx, span);
+ }
+ else {
+ ASSERT(ctx->ATIFragmentShader._Enabled);
+ _swrast_exec_fragment_shader(ctx, span);
+ }
+ }
+ else if (ctx->Texture._EnabledCoordUnits) {
+ /* conventional texturing */
+
+#if CHAN_BITS == 32
+ if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ interpolate_int_colors(ctx, span);
+ }
+#else
+ if (!(span->arrayMask & SPAN_RGBA))
+ interpolate_int_colors(ctx, span);
+#endif
+ if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
+ interpolate_texcoords(ctx, span);
+
+ _swrast_texture_span(ctx, span);
+ }
+}
+
+
+
+/**
+ * Apply all the per-fragment operations to a span.
+ * This now includes texturing (_swrast_write_texture_span() is history).
+ * This function may modify any of the array values in the span.
+ * span->interpMask and span->arrayMask may be changed but will be restored
+ * to their original values before returning.
+ */
+void
+_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
+ const GLbitfield origInterpMask = span->interpMask;
+ const GLbitfield origArrayMask = span->arrayMask;
+ const GLbitfield origArrayAttribs = span->arrayAttribs;
+ const GLenum origChanType = span->array->ChanType;
+ void * const origRgba = span->array->rgba;
+ const GLboolean shader = (ctx->FragmentProgram._Current
+ || ctx->ATIFragmentShader._Enabled);
+ const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ /*
+ printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
+ span->interpMask, span->arrayMask);
+ */
+
+ ASSERT(span->primitive == GL_POINT ||
+ span->primitive == GL_LINE ||
+ span->primitive == GL_POLYGON ||
+ span->primitive == GL_BITMAP);
+
+ /* Fragment write masks */
+ if (span->arrayMask & SPAN_MASK) {
+ /* mask was initialized by caller, probably glBitmap */
+ span->writeAll = GL_FALSE;
+ }
+ else {
+ _mesa_memset(span->array->mask, 1, span->end);
+ span->writeAll = GL_TRUE;
+ }
+
+ /* Clip to window/scissor box */
+ if (!clip_span(ctx, span)) {
+ return;
+ }
+
+ ASSERT(span->end <= MAX_WIDTH);
+
+#ifdef DEBUG
+ /* Make sure all fragments are within window bounds */
+ if (span->arrayMask & SPAN_XY) {
+ /* array of pixel locations */
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ if (span->array->mask[i]) {
+ assert(span->array->x[i] >= fb->_Xmin);
+ assert(span->array->x[i] < fb->_Xmax);
+ assert(span->array->y[i] >= fb->_Ymin);
+ assert(span->array->y[i] < fb->_Ymax);
+ }
+ }
+ }
+#endif
+
+ /* Polygon Stippling */
+ if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
+ stipple_polygon_span(ctx, span);
+ }
+
+ /* This is the normal place to compute the fragment color/Z
+ * from texturing or shading.
+ */
+ if (shaderOrTexture && !swrast->_DeferredTexture) {
+ shade_texture_span(ctx, span);
+ }
+
+ /* Do the alpha test */
+ if (ctx->Color.AlphaEnabled) {
+ if (!_swrast_alpha_test(ctx, span)) {
+ /* all fragments failed test */
+ goto end;
+ }
+ }
+
+ /* Stencil and Z testing */
+ if (ctx->Stencil._Enabled || ctx->Depth.Test) {
+ if (!(span->arrayMask & SPAN_Z))
+ _swrast_span_interpolate_z(ctx, span);
+ if (ctx->Stencil._Enabled) {
+ /* Combined Z/stencil tests */
+ if (!_swrast_stencil_and_ztest_span(ctx, span)) {
+ /* all fragments failed test */
+ goto end;
+ }
+ }
+ else if (fb->Visual.depthBits > 0) {
+ /* Just regular depth testing */
+ ASSERT(ctx->Depth.Test);
+ ASSERT(span->arrayMask & SPAN_Z);
+ if (!_swrast_depth_test_span(ctx, span)) {
+ /* all fragments failed test */
+ goto end;
+ }
+ }
+ }
+
+#if FEATURE_ARB_occlusion_query
+ if (ctx->Query.CurrentOcclusionObject) {
+ /* update count of 'passed' fragments */
+ struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
+ GLuint i;
+ for (i = 0; i < span->end; i++)
+ q->Result += span->array->mask[i];
+ }
+#endif
+
+ /* We had to wait until now to check for glColorMask(0,0,0,0) because of
+ * the occlusion test.
+ */
+ if (colorMask == 0x0) {
+ /* no colors to write */
+ goto end;
+ }
+
+ /* If we were able to defer fragment color computation to now, there's
+ * a good chance that many fragments will have already been killed by
+ * Z/stencil testing.
+ */
+ if (shaderOrTexture && swrast->_DeferredTexture) {
+ shade_texture_span(ctx, span);
+ }
+
+#if CHAN_BITS == 32
+ if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+ interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+ }
+#else
+ if ((span->arrayMask & SPAN_RGBA) == 0) {
+ interpolate_int_colors(ctx, span);
+ }
+#endif
+
+ ASSERT(span->arrayMask & SPAN_RGBA);
+
+ if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
+ /* Add primary and specular (diffuse + specular) colors */
+ if (!shader) {
+ if (ctx->Fog.ColorSumEnabled ||
+ (ctx->Light.Enabled &&
+ ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+ add_specular(ctx, span);
+ }
+ }
+ }
+
+ /* Fog */
+ if (swrast->_FogEnabled) {
+ _swrast_fog_rgba_span(ctx, span);
+ }
+
+ /* Antialias coverage application */
+ if (span->arrayMask & SPAN_COVERAGE) {
+ apply_aa_coverage(span);
+ }
+
+ /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
+ if (ctx->Color.ClampFragmentColor == GL_TRUE &&
+ span->array->ChanType == GL_FLOAT) {
+ clamp_colors(span);
+ }
+
+ /*
+ * Write to renderbuffers.
+ * Depending on glDrawBuffer() state and the which color outputs are
+ * written by the fragment shader, we may either replicate one color to
+ * all renderbuffers or write a different color to each renderbuffer.
+ * multiFragOutputs=TRUE for the later case.
+ */
+ {
+ const GLuint numBuffers = fb->_NumColorDrawBuffers;
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+ const GLboolean multiFragOutputs =
+ (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
+ GLuint buf;
+
+ for (buf = 0; buf < numBuffers; buf++) {
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
+
+ /* color[fragOutput] will be written to buffer[buf] */
+
+ if (rb) {
+ GLchan rgbaSave[MAX_WIDTH][4];
+ const GLuint fragOutput = multiFragOutputs ? buf : 0;
+
+ if (rb->DataType != span->array->ChanType || fragOutput > 0) {
+ convert_color_type(span, rb->DataType, fragOutput);
+ }
+
+ if (!multiFragOutputs && numBuffers > 1) {
+ /* save colors for second, third renderbuffer writes */
+ _mesa_memcpy(rgbaSave, span->array->rgba,
+ 4 * span->end * sizeof(GLchan));
+ }
+
+ ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
+
+ if (ctx->Color._LogicOpEnabled) {
+ _swrast_logicop_rgba_span(ctx, rb, span);
+ }
+ else if (ctx->Color.BlendEnabled) {
+ _swrast_blend_span(ctx, rb, span);
+ }
+
+ if (colorMask != 0xffffffff) {
+ _swrast_mask_rgba_span(ctx, rb, span);
+ }
+
+ if (span->arrayMask & SPAN_XY) {
+ /* array of pixel coords */
+ ASSERT(rb->PutValues);
+ rb->PutValues(ctx, rb, span->end,
+ span->array->x, span->array->y,
+ span->array->rgba, span->array->mask);
+ }
+ else {
+ /* horizontal run of pixels */
+ ASSERT(rb->PutRow);
+ rb->PutRow(ctx, rb, span->end, span->x, span->y,
+ span->array->rgba,
+ span->writeAll ? NULL: span->array->mask);
+ }
+
+ if (!multiFragOutputs && numBuffers > 1) {
+ /* restore original span values */
+ _mesa_memcpy(span->array->rgba, rgbaSave,
+ 4 * span->end * sizeof(GLchan));
+ }
+
+ } /* if rb */
+ } /* for buf */
+ }
+
+end:
+ /* restore these values before returning */
+ span->interpMask = origInterpMask;
+ span->arrayMask = origArrayMask;
+ span->arrayAttribs = origArrayAttribs;
+ span->array->ChanType = origChanType;
+ span->array->rgba = origRgba;
+}
+
+
+/**
+ * Read RGBA pixels from a renderbuffer. Clipping will be done to prevent
+ * reading ouside the buffer's boundaries.
+ * \param dstType datatype for returned colors
+ * \param rgba the returned colors
+ */
+void
+_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, GLenum dstType,
+ GLvoid *rgba)
+{
+ const GLint bufWidth = (GLint) rb->Width;
+ const GLint bufHeight = (GLint) rb->Height;
+
+ if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
+ /* completely above, below, or right */
+ /* XXX maybe leave rgba values undefined? */
+ _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
+ }
+ else {
+ GLint skip, length;
+ if (x < 0) {
+ /* left edge clipping */
+ skip = -x;
+ length = (GLint) n - skip;
+ if (length < 0) {
+ /* completely left of window */
+ return;
+ }
+ if (length > bufWidth) {
+ length = bufWidth;
+ }
+ }
+ else if ((GLint) (x + n) > bufWidth) {
+ /* right edge clipping */
+ skip = 0;
+ length = bufWidth - x;
+ if (length < 0) {
+ /* completely to right of window */
+ return;
+ }
+ }
+ else {
+ /* no clipping */
+ skip = 0;
+ length = (GLint) n;
+ }
+
+ ASSERT(rb);
+ ASSERT(rb->GetRow);
+ ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
+
+ if (rb->DataType == dstType) {
+ rb->GetRow(ctx, rb, length, x + skip, y,
+ (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
+ }
+ else {
+ GLuint temp[MAX_WIDTH * 4];
+ rb->GetRow(ctx, rb, length, x + skip, y, temp);
+ _mesa_convert_colors(rb->DataType, temp,
+ dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
+ length, NULL);
+ }
+ }
+}
+
+
+/**
+ * Read CI pixels from a renderbuffer. Clipping will be done to prevent
+ * reading ouside the buffer's boundaries.
+ */
+void
+_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ const GLint bufWidth = (GLint) rb->Width;
+ const GLint bufHeight = (GLint) rb->Height;
+
+ if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
+ /* completely above, below, or right */
+ _mesa_bzero(index, n * sizeof(GLuint));
+ }
+ else {
+ GLint skip, length;
+ if (x < 0) {
+ /* left edge clipping */
+ skip = -x;
+ length = (GLint) n - skip;
+ if (length < 0) {
+ /* completely left of window */
+ return;
+ }
+ if (length > bufWidth) {
+ length = bufWidth;
+ }
+ }
+ else if ((GLint) (x + n) > bufWidth) {
+ /* right edge clipping */
+ skip = 0;
+ length = bufWidth - x;
+ if (length < 0) {
+ /* completely to right of window */
+ return;
+ }
+ }
+ else {
+ /* no clipping */
+ skip = 0;
+ length = (GLint) n;
+ }
+
+ ASSERT(rb->GetRow);
+ ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
+
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ GLubyte index8[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, length, x + skip, y, index8);
+ for (i = 0; i < length; i++)
+ index[skip + i] = index8[i];
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort index16[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, length, x + skip, y, index16);
+ for (i = 0; i < length; i++)
+ index[skip + i] = index16[i];
+ }
+ else if (rb->DataType == GL_UNSIGNED_INT) {
+ rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
+ }
+ }
+}
+
+
+/**
+ * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
+ * reading values outside the buffer bounds.
+ * We can use this for reading any format/type of renderbuffer.
+ * \param valueSize is the size in bytes of each value (pixel) put into the
+ * values array.
+ */
+void
+_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ void *values, GLuint valueSize)
+{
+ GLuint i, inCount = 0, inStart = 0;
+
+ for (i = 0; i < count; i++) {
+ if (x[i] >= 0 && y[i] >= 0 &&
+ x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
+ /* inside */
+ if (inCount == 0)
+ inStart = i;
+ inCount++;
+ }
+ else {
+ if (inCount > 0) {
+ /* read [inStart, inStart + inCount) */
+ rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
+ (GLubyte *) values + inStart * valueSize);
+ inCount = 0;
+ }
+ }
+ }
+ if (inCount > 0) {
+ /* read last values */
+ rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
+ (GLubyte *) values + inStart * valueSize);
+ }
+}
+
+
+/**
+ * Wrapper for gl_renderbuffer::PutRow() which does clipping.
+ * \param valueSize size of each value (pixel) in bytes
+ */
+void
+_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const GLvoid *values, GLuint valueSize)
+{
+ GLint skip = 0;
+
+ if (y < 0 || y >= (GLint) rb->Height)
+ return; /* above or below */
+
+ if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
+ return; /* entirely left or right */
+
+ if ((GLint) (x + count) > (GLint) rb->Width) {
+ /* right clip */
+ GLint clip = x + count - rb->Width;
+ count -= clip;
+ }
+
+ if (x < 0) {
+ /* left clip */
+ skip = -x;
+ x = 0;
+ count -= skip;
+ }
+
+ rb->PutRow(ctx, rb, count, x, y,
+ (const GLubyte *) values + skip * valueSize, NULL);
+}
+
+
+/**
+ * Wrapper for gl_renderbuffer::GetRow() which does clipping.
+ * \param valueSize size of each value (pixel) in bytes
+ */
+void
+_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ GLvoid *values, GLuint valueSize)
+{
+ GLint skip = 0;
+
+ if (y < 0 || y >= (GLint) rb->Height)
+ return; /* above or below */
+
+ if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
+ return; /* entirely left or right */
+
+ if (x + count > rb->Width) {
+ /* right clip */
+ GLint clip = x + count - rb->Width;
+ count -= clip;
+ }
+
+ if (x < 0) {
+ /* left clip */
+ skip = -x;
+ x = 0;
+ count -= skip;
+ }
+
+ rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
+}
+
+
+/**
+ * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
+ * the span's specular color arrays. The specular color arrays should no
+ * longer be needed by time this function is called.
+ * Used by blending, logicop and masking functions.
+ * \return pointer to the colors we read.
+ */
+void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span)
+{
+ const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
+ void *rbPixels;
+
+ /*
+ * Point rbPixels to a temporary space (use specular color arrays).
+ */
+ rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
+
+ /* Get destination values from renderbuffer */
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+ rbPixels, pixelSize);
+ }
+ else {
+ _swrast_get_row(ctx, rb, span->end, span->x, span->y,
+ rbPixels, pixelSize);
+ }
+
+ return rbPixels;
+}
diff --git a/mesalib/src/mesa/swrast/s_span.h b/mesalib/src/mesa/swrast/s_span.h
new file mode 100644
index 000000000..0eabae20e
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_span.h
@@ -0,0 +1,226 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 S_SPAN_H
+#define S_SPAN_H
+
+
+#include "swrast.h"
+
+
+/**
+ * \defgroup SpanFlags
+ * Special bitflags to describe span data.
+ *
+ * In general, the point/line/triangle functions interpolate/emit the
+ * attributes specified by swrast->_ActiveAttribs (i.e. FRAT_BIT_* values).
+ * Some things don't fit into that, though, so we have these flags.
+ */
+/*@{*/
+#define SPAN_RGBA 0x01 /**< interpMask and arrayMask */
+#define SPAN_INDEX 0x02 /**< interpMask and arrayMask */
+#define SPAN_Z 0x04 /**< interpMask and arrayMask */
+#define SPAN_FLAT 0x08 /**< interpMask: flat shading? */
+#define SPAN_XY 0x10 /**< array.x[], y[] valid? */
+#define SPAN_MASK 0x20 /**< was array.mask[] filled in by caller? */
+#define SPAN_LAMBDA 0x40 /**< array.lambda[] valid? */
+#define SPAN_COVERAGE 0x80 /**< array.coverage[] valid? */
+/*@}*/
+
+
+/**
+ * \sw_span_arrays
+ * \brief Arrays of fragment values.
+ *
+ * These will either be computed from the span x/xStep values or
+ * filled in by glDraw/CopyPixels, etc.
+ * These arrays are separated out of sw_span to conserve memory.
+ */
+typedef struct sw_span_arrays
+{
+ /** Per-fragment attributes (indexed by FRAG_ATTRIB_* tokens) */
+ /* XXX someday look at transposing first two indexes for better memory
+ * access pattern.
+ */
+ GLfloat attribs[FRAG_ATTRIB_MAX][MAX_WIDTH][4];
+
+ /** This mask indicates which fragments are alive or culled */
+ GLubyte mask[MAX_WIDTH];
+
+ GLenum ChanType; /**< Color channel type, GL_UNSIGNED_BYTE, GL_FLOAT */
+
+ /** Attribute arrays that don't fit into attribs[] array above */
+ /*@{*/
+ GLubyte rgba8[MAX_WIDTH][4];
+ GLushort rgba16[MAX_WIDTH][4];
+ GLchan (*rgba)[4]; /** either == rgba8 or rgba16 */
+ GLint x[MAX_WIDTH]; /**< fragment X coords */
+ GLint y[MAX_WIDTH]; /**< fragment Y coords */
+ GLuint z[MAX_WIDTH]; /**< fragment Z coords */
+ GLuint index[MAX_WIDTH]; /**< Color indexes */
+ GLfloat lambda[MAX_TEXTURE_COORD_UNITS][MAX_WIDTH]; /**< Texture LOD */
+ GLfloat coverage[MAX_WIDTH]; /**< Fragment coverage for AA/smoothing */
+ /*@}*/
+} SWspanarrays;
+
+
+/**
+ * The SWspan structure describes the colors, Z, fogcoord, texcoords,
+ * etc for either a horizontal run or an array of independent pixels.
+ * We can either specify a base/step to indicate interpolated values, or
+ * fill in explicit arrays of values. The interpMask and arrayMask bitfields
+ * indicate which attributes are active interpolants or arrays, respectively.
+ *
+ * It would be interesting to experiment with multiprocessor rasterization
+ * with this structure. The triangle rasterizer could simply emit a
+ * stream of these structures which would be consumed by one or more
+ * span-processing threads which could run in parallel.
+ */
+typedef struct sw_span
+{
+ /** Coord of first fragment in horizontal span/run */
+ GLint x, y;
+
+ /** Number of fragments in the span */
+ GLuint end;
+
+ /** for clipping left edge of spans */
+ GLuint leftClip;
+
+ /** This flag indicates that mask[] array is effectively filled with ones */
+ GLboolean writeAll;
+
+ /** either GL_POLYGON, GL_LINE, GL_POLYGON, GL_BITMAP */
+ GLenum primitive;
+
+ /** 0 = front-facing span, 1 = back-facing span (for two-sided stencil) */
+ GLuint facing;
+
+ /**
+ * This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
+ * which of the attrStart/StepX/StepY variables are relevant.
+ */
+ GLbitfield interpMask;
+
+ /** Fragment attribute interpolants */
+ GLfloat attrStart[FRAG_ATTRIB_MAX][4]; /**< initial value */
+ GLfloat attrStepX[FRAG_ATTRIB_MAX][4]; /**< dvalue/dx */
+ GLfloat attrStepY[FRAG_ATTRIB_MAX][4]; /**< dvalue/dy */
+
+ /* XXX the rest of these will go away eventually... */
+
+ /* For horizontal spans, step is the partial derivative wrt X.
+ * For lines, step is the delta from one fragment to the next.
+ */
+ GLfixed red, redStep;
+ GLfixed green, greenStep;
+ GLfixed blue, blueStep;
+ GLfixed alpha, alphaStep;
+ GLfixed index, indexStep;
+ GLfixed z, zStep; /**< XXX z should probably be GLuint */
+ GLfixed intTex[2], intTexStep[2]; /**< (s,t) for unit[0] only */
+
+ /**
+ * This bitmask (of \link SpanFlags SPAN_* flags\endlink) indicates
+ * which of the fragment arrays in the span_arrays struct are relevant.
+ */
+ GLbitfield arrayMask;
+
+ GLbitfield arrayAttribs;
+
+ /**
+ * We store the arrays of fragment values in a separate struct so
+ * that we can allocate sw_span structs on the stack without using
+ * a lot of memory. The span_arrays struct is about 1.4MB while the
+ * sw_span struct is only about 512 bytes.
+ */
+ SWspanarrays *array;
+} SWspan;
+
+
+
+#define INIT_SPAN(S, PRIMITIVE) \
+do { \
+ (S).primitive = (PRIMITIVE); \
+ (S).interpMask = 0x0; \
+ (S).arrayMask = 0x0; \
+ (S).arrayAttribs = 0x0; \
+ (S).end = 0; \
+ (S).leftClip = 0; \
+ (S).facing = 0; \
+ (S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \
+} while (0)
+
+
+
+extern void
+_swrast_span_default_attribs(GLcontext *ctx, SWspan *span);
+
+extern void
+_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span );
+
+extern GLfloat
+_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
+ GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
+ GLfloat s, GLfloat t, GLfloat q, GLfloat invQ);
+
+extern void
+_swrast_write_index_span( GLcontext *ctx, SWspan *span);
+
+
+extern void
+_swrast_write_rgba_span( GLcontext *ctx, SWspan *span);
+
+
+extern void
+_swrast_read_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, GLenum type, GLvoid *rgba);
+
+extern void
+_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, GLuint indx[] );
+
+extern void
+_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ void *values, GLuint valueSize);
+
+extern void
+_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const GLvoid *values, GLuint valueSize);
+
+extern void
+_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ GLvoid *values, GLuint valueSize);
+
+
+extern void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+ SWspan *span);
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_spantemp.h b/mesalib/src/mesa/swrast/s_spantemp.h
new file mode 100644
index 000000000..bab2ca737
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_spantemp.h
@@ -0,0 +1,235 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+
+/*
+ * Templates for the span/pixel-array write/read functions called via
+ * the gl_renderbuffer's GetRow, GetValues, PutRow, PutMonoRow, PutValues
+ * and PutMonoValues functions.
+ *
+ * Define the following macros before including this file:
+ * NAME(BASE) to generate the function name (i.e. add prefix or suffix)
+ * RB_TYPE the renderbuffer DataType
+ * CI_MODE if set, color index mode, else RGBA
+ * SPAN_VARS to declare any local variables
+ * INIT_PIXEL_PTR(P, X, Y) to initialize a pointer to a pixel
+ * INC_PIXEL_PTR(P) to increment a pixel pointer by one pixel
+ * STORE_PIXEL(DST, X, Y, VALUE) to store pixel values in buffer
+ * FETCH_PIXEL(DST, SRC) to fetch pixel values from buffer
+ *
+ * Note that in the STORE_PIXEL macros, we also pass in the (X,Y) coordinates
+ * for the pixels to be stored. This is useful when dithering and probably
+ * ignored otherwise.
+ */
+
+#include "main/macros.h"
+
+
+#ifdef CI_MODE
+#define RB_COMPONENTS 1
+#elif !defined(RB_COMPONENTS)
+#define RB_COMPONENTS 4
+#endif
+
+
+static void
+NAME(get_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y, void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+#ifdef CI_MODE
+ RB_TYPE *dest = (RB_TYPE *) values;
+#else
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+#endif
+ GLuint i;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ FETCH_PIXEL(dest[i], pixel);
+ INC_PIXEL_PTR(pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(get_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[], void *values )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+#ifdef CI_MODE
+ RB_TYPE *dest = (RB_TYPE *) values;
+#else
+ RB_TYPE (*dest)[RB_COMPONENTS] = (RB_TYPE (*)[RB_COMPONENTS]) values;
+#endif
+ GLuint i;
+ for (i = 0; i < count; i++) {
+ INIT_PIXEL_PTR(pixel, x[i], y[i]);
+ FETCH_PIXEL(dest[i], pixel);
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ INIT_PIXEL_PTR(pixel, x, y);
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ }
+ INC_PIXEL_PTR(pixel);
+ }
+ }
+ else {
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+ INC_PIXEL_PTR(pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+#if !defined(CI_MODE)
+static void
+NAME(put_row_rgb)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[3] = (const RB_TYPE (*)[3]) values;
+ GLuint i;
+ INIT_PIXEL_PTR(pixel, x, y);
+ for (i = 0; i < count; i++) {
+ if (!mask || mask[i]) {
+#ifdef STORE_PIXEL_RGB
+ STORE_PIXEL_RGB(pixel, x + i, y, src[i]);
+#else
+ STORE_PIXEL(pixel, x + i, y, src[i]);
+#endif
+ }
+ INC_PIXEL_PTR(pixel);
+ }
+ (void) rb;
+}
+#endif
+
+
+static void
+NAME(put_mono_row)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, GLint x, GLint y,
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ INIT_PIXEL_PTR(pixel, x, y);
+ if (mask) {
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ STORE_PIXEL(pixel, x + i, y, src);
+ }
+ INC_PIXEL_PTR(pixel);
+ }
+ }
+ else {
+ for (i = 0; i < count; i++) {
+ STORE_PIXEL(pixel, x + i, y, src);
+ INC_PIXEL_PTR(pixel);
+ }
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *values, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE (*src)[RB_COMPONENTS] = (const RB_TYPE (*)[RB_COMPONENTS]) values;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ INIT_PIXEL_PTR(pixel, x[i], y[i]);
+ STORE_PIXEL(pixel, x[i], y[i], src[i]);
+ }
+ }
+ (void) rb;
+}
+
+
+static void
+NAME(put_mono_values)( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint count, const GLint x[], const GLint y[],
+ const void *value, const GLubyte mask[] )
+{
+#ifdef SPAN_VARS
+ SPAN_VARS
+#endif
+ const RB_TYPE *src = (const RB_TYPE *) value;
+ GLuint i;
+ ASSERT(mask);
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ INIT_PIXEL_PTR(pixel, x[i], y[i]);
+ STORE_PIXEL(pixel, x[i], y[i], src);
+ }
+ }
+ (void) rb;
+}
+
+
+#undef NAME
+#undef RB_TYPE
+#undef RB_COMPONENTS
+#undef CI_MODE
+#undef SPAN_VARS
+#undef INIT_PIXEL_PTR
+#undef INC_PIXEL_PTR
+#undef STORE_PIXEL
+#undef STORE_PIXEL_RGB
+#undef FETCH_PIXEL
diff --git a/mesalib/src/mesa/swrast/s_stencil.c b/mesalib/src/mesa/swrast/s_stencil.c
new file mode 100644
index 000000000..e9e9d3a4f
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_stencil.c
@@ -0,0 +1,1245 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_stencil.h"
+#include "s_span.h"
+
+
+
+/* Stencil Logic:
+
+IF stencil test fails THEN
+ Apply fail-op to stencil value
+ Don't write the pixel (RGBA,Z)
+ELSE
+ IF doing depth test && depth test fails THEN
+ Apply zfail-op to stencil value
+ Write RGBA and Z to appropriate buffers
+ ELSE
+ Apply zpass-op to stencil value
+ENDIF
+
+*/
+
+
+/**
+ * Apply the given stencil operator to the array of stencil values.
+ * Don't touch stencil[i] if mask[i] is zero.
+ * Input: n - size of stencil array
+ * oper - the stencil buffer operator
+ * face - 0 or 1 for front or back face operation
+ * stencil - array of stencil values
+ * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
+ * Output: stencil - modified values
+ */
+static void
+apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
+ GLuint n, GLstencil stencil[], const GLubyte mask[] )
+{
+ const GLstencil ref = ctx->Stencil.Ref[face];
+ const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
+ const GLstencil invmask = (GLstencil) (~wrtmask);
+ const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
+ 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] = (GLstencil) (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] = (GLstencil) ((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 < stencilMax) {
+ stencil[i] = (GLstencil) (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 < stencilMax) {
+ stencil[i] = (GLstencil) ((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] = (GLstencil) (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] = (GLstencil) ((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] = (GLstencil) ((invmask & s) | (wrtmask & (s+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] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
+ }
+ }
+ }
+ break;
+ case GL_INVERT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (GLstencil) ~s;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
+ }
+}
+
+
+
+
+/**
+ * Apply stencil test to an array of stencil values (before depth buffering).
+ * Input: face - 0 or 1 for front or back-face polygons
+ * n - number of pixels in the array
+ * stencil - array of [n] stencil values
+ * 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.
+ * stencil - updated stencil values (where the test passed)
+ * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
+ */
+static GLboolean
+do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
+ GLubyte mask[] )
+{
+ GLubyte fail[MAX_WIDTH];
+ GLboolean allfail = GL_FALSE;
+ GLuint i;
+ const GLuint valueMask = ctx->Stencil.ValueMask[face];
+ const GLstencil r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ GLstencil s;
+
+ ASSERT(n <= MAX_WIDTH);
+
+ /*
+ * 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[face]) {
+ case GL_NEVER:
+ /* never pass; always fail */
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ mask[i] = 0;
+ fail[i] = 1;
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ allfail = GL_TRUE;
+ break;
+ case GL_LESS:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & valueMask);
+ if (r < s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & valueMask);
+ if (r <= s) {
+ /* pass */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GREATER:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & valueMask);
+ if (r > s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & valueMask);
+ if (r >= s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_EQUAL:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & valueMask);
+ if (r == s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = (GLstencil) (stencil[i] & 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:
+ _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
+ return 0;
+ }
+
+ if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
+ apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
+ }
+
+ return !allfail;
+}
+
+
+/**
+ * Compute the zpass/zfail masks by comparing the pre- and post-depth test
+ * masks.
+ */
+static INLINE void
+compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
+ const GLubyte newMask[],
+ GLubyte passMask[], GLubyte failMask[])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ ASSERT(newMask[i] == 0 || newMask[i] == 1);
+ passMask[i] = origMask[i] & newMask[i];
+ failMask[i] = origMask[i] & (newMask[i] ^ 1);
+ }
+}
+
+
+/**
+ * Apply stencil and depth testing to the span of pixels.
+ * Both software and hardware stencil buffers are acceptable.
+ * Input: n - number of pixels in the span
+ * x, y - location of leftmost pixel in span
+ * z - array [n] of z values
+ * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
+ * Output: mask - array [n] of flags (1=stencil and depth test passed)
+ * Return: GL_FALSE - all fragments failed the testing
+ * GL_TRUE - one or more fragments passed the testing
+ *
+ */
+static GLboolean
+stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ GLstencil stencilRow[MAX_WIDTH];
+ GLstencil *stencil;
+ const GLuint n = span->end;
+ const GLint x = span->x;
+ const GLint y = span->y;
+ GLubyte *mask = span->array->mask;
+
+ ASSERT((span->arrayMask & SPAN_XY) == 0);
+ ASSERT(ctx->Stencil.Enabled);
+ ASSERT(n <= MAX_WIDTH);
+#ifdef DEBUG
+ if (ctx->Depth.Test) {
+ ASSERT(span->arrayMask & SPAN_Z);
+ }
+#endif
+
+ stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
+ if (!stencil) {
+ rb->GetRow(ctx, rb, n, x, y, stencilRow);
+ stencil = stencilRow;
+ }
+
+ /*
+ * Apply the stencil test to the fragments.
+ * failMask[i] is 1 if the stencil test failed.
+ */
+ if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
+ /* all fragments failed the stencil test, we're done. */
+ span->writeAll = GL_FALSE;
+ if (!rb->GetPointer(ctx, rb, 0, 0)) {
+ /* put updated stencil values into buffer */
+ rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
+ }
+ return GL_FALSE;
+ }
+
+ /*
+ * Some fragments passed the stencil test, apply depth test to them
+ * and apply Zpass and Zfail stencil ops.
+ */
+ if (ctx->Depth.Test == GL_FALSE) {
+ /*
+ * No depth buffer, just apply zpass stencil function to active pixels.
+ */
+ apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
+ }
+ else {
+ /*
+ * Perform depth buffering, then apply zpass or zfail stencil function.
+ */
+ GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
+
+ /* save the current mask bits */
+ _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
+
+ /* apply the depth test */
+ _swrast_depth_test_span(ctx, span);
+
+ compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
+
+ /* apply the pass and fail operations */
+ if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
+ apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
+ n, stencil, failMask );
+ }
+ if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
+ apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
+ n, stencil, passMask );
+ }
+ }
+
+ /*
+ * Write updated stencil values back into hardware stencil buffer.
+ */
+ if (!rb->GetPointer(ctx, rb, 0, 0)) {
+ rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
+ }
+
+ span->writeAll = GL_FALSE;
+
+ return GL_TRUE; /* one or more fragments passed both tests */
+}
+
+
+
+/*
+ * Return the address of a stencil buffer value given the window coords:
+ */
+#define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
+
+
+
+/**
+ * Apply the given stencil operator for each pixel in the array whose
+ * mask flag is set.
+ * \note This is for software stencil buffers only.
+ * 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, GLuint face, const GLubyte mask[] )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
+ const GLstencil ref = ctx->Stencil.Ref[face];
+ const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
+ const GLstencil invmask = (GLstencil) (~wrtmask);
+ GLuint i;
+ GLstencil *stencilStart = (GLubyte *) rb->Data;
+ const GLuint stride = rb->Width;
+
+ ASSERT(rb->GetPointer(ctx, rb, 0, 0));
+ ASSERT(sizeof(GLstencil) == 1);
+
+ 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 = (GLstencil) (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 = (GLstencil) ((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 < stencilMax) {
+ *sptr = (GLstencil) (*sptr + 1);
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr < stencilMax) {
+ *sptr = (GLstencil) ((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 = (GLstencil) (*sptr - 1);
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr>0) {
+ *sptr = (GLstencil) ((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 = (GLstencil) (*sptr + 1);
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (GLstencil) ((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 = (GLstencil) (*sptr - 1);
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (GLstencil) ((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 = (GLstencil) (~*sptr);
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
+ }
+}
+
+
+
+/**
+ * Apply stencil test to an array of pixels before depth buffering.
+ *
+ * \note Used for software stencil buffer only.
+ * 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 GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
+ */
+static GLboolean
+stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
+ const GLint x[], const GLint y[], GLubyte mask[] )
+{
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ GLubyte fail[MAX_WIDTH];
+ GLstencil r, s;
+ GLuint i;
+ GLboolean allfail = GL_FALSE;
+ const GLuint valueMask = ctx->Stencil.ValueMask[face];
+ const GLstencil *stencilStart = (GLstencil *) rb->Data;
+ const GLuint stride = rb->Width;
+
+ ASSERT(rb->GetPointer(ctx, rb, 0, 0));
+ ASSERT(sizeof(GLstencil) == 1);
+
+ /*
+ * 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[face]) {
+ 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 = GL_TRUE;
+ break;
+ case GL_LESS:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & valueMask);
+ if (r < s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & valueMask);
+ if (r <= s) {
+ /* pass */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GREATER:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & valueMask);
+ if (r > s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & valueMask);
+ if (r >= s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_EQUAL:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & valueMask);
+ if (r == s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = (GLstencil) (*sptr & 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:
+ _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
+ return 0;
+ }
+
+ if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
+ apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
+ face, fail );
+ }
+
+ return !allfail;
+}
+
+
+
+
+/**
+ * Apply stencil and depth testing to an array of pixels.
+ * This is used both for software and hardware stencil buffers.
+ *
+ * The comments in this function are a bit sparse but the code is
+ * almost identical to stencil_and_ztest_span(), which is well
+ * commented.
+ *
+ * Input: n - number of pixels in the array
+ * x, y - array of [n] pixel positions
+ * z - array [n] of z values
+ * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
+ * Output: mask - array [n] of flags (1=stencil and depth test passed)
+ * Return: GL_FALSE - all fragments failed the testing
+ * GL_TRUE - one or more fragments passed the testing
+ */
+static GLboolean
+stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
+{
+ GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ const GLuint n = span->end;
+ const GLint *x = span->array->x;
+ const GLint *y = span->array->y;
+ GLubyte *mask = span->array->mask;
+
+ ASSERT(span->arrayMask & SPAN_XY);
+ ASSERT(ctx->Stencil.Enabled);
+ ASSERT(n <= MAX_WIDTH);
+
+ if (!rb->GetPointer(ctx, rb, 0, 0)) {
+ /* No direct access */
+ GLstencil stencil[MAX_WIDTH];
+
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
+ _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
+
+ _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
+
+ (void) do_stencil_test(ctx, face, n, stencil, mask);
+
+ if (ctx->Depth.Test == GL_FALSE) {
+ apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
+ n, stencil, mask);
+ }
+ else {
+ GLubyte tmpMask[MAX_WIDTH];
+ _mesa_memcpy(tmpMask, mask, n * sizeof(GLubyte));
+
+ _swrast_depth_test_span(ctx, span);
+
+ compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
+
+ if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
+ apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
+ n, stencil, failMask);
+ }
+ if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
+ apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
+ n, stencil, passMask);
+ }
+ }
+
+ /* Write updated stencil values into hardware stencil buffer */
+ rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
+
+ return GL_TRUE;
+ }
+ else {
+ /* Direct access to stencil buffer */
+
+ if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
+ /* all fragments failed the stencil test, we're done. */
+ return GL_FALSE;
+ }
+
+ if (ctx->Depth.Test==GL_FALSE) {
+ apply_stencil_op_to_pixels(ctx, n, x, y,
+ ctx->Stencil.ZPassFunc[face], face, mask);
+ }
+ else {
+ _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
+
+ _swrast_depth_test_span(ctx, span);
+
+ compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
+
+ if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
+ apply_stencil_op_to_pixels(ctx, n, x, y,
+ ctx->Stencil.ZFailFunc[face],
+ face, failMask);
+ }
+ if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
+ apply_stencil_op_to_pixels(ctx, n, x, y,
+ ctx->Stencil.ZPassFunc[face],
+ face, passMask);
+ }
+ }
+
+ return GL_TRUE; /* one or more fragments passed both tests */
+ }
+}
+
+
+/**
+ * /return GL_TRUE = one or more fragments passed,
+ * GL_FALSE = all fragments failed.
+ */
+GLboolean
+_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
+{
+ const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
+
+ if (span->arrayMask & SPAN_XY)
+ return stencil_and_ztest_pixels(ctx, span, face);
+ else
+ return stencil_and_ztest_span(ctx, span, face);
+}
+
+
+#if 0
+GLuint
+clip_span(GLuint bufferWidth, GLuint bufferHeight,
+ GLint x, GLint y, GLuint *count)
+{
+ GLuint n = *count;
+ GLuint skipPixels = 0;
+
+ if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
+ /* totally out of bounds */
+ n = 0;
+ }
+ else {
+ /* left clip */
+ if (x < 0) {
+ skipPixels = -x;
+ x = 0;
+ n -= skipPixels;
+ }
+ /* right clip */
+ if (x + n > bufferWidth) {
+ GLint dx = x + n - bufferWidth;
+ n -= dx;
+ }
+ }
+
+ *count = n;
+
+ return skipPixels;
+}
+#endif
+
+
+/**
+ * Return a span of stencil values from the stencil buffer.
+ * Used for glRead/CopyPixels
+ * Input: n - how many pixels
+ * x,y - location of first pixel
+ * Output: stencil - the array of stencil values
+ */
+void
+_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLstencil stencil[])
+{
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
+ /* span is completely outside framebuffer */
+ return; /* undefined values OK */
+ }
+
+ if (x < 0) {
+ GLint dx = -x;
+ x = 0;
+ n -= dx;
+ stencil += dx;
+ }
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - rb->Width;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ rb->GetRow(ctx, rb, n, x, y, stencil);
+}
+
+
+
+/**
+ * Write a span of stencil values to the stencil buffer. This function
+ * applies the stencil write mask when needed.
+ * Used for glDraw/CopyPixels
+ * Input: n - how many pixels
+ * x, y - location of first pixel
+ * stencil - the array of stencil values
+ */
+void
+_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
+ const GLstencil stencil[] )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_StencilBuffer;
+ const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
+ const GLuint stencilMask = ctx->Stencil.WriteMask[0];
+
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
+ /* span is completely outside framebuffer */
+ return; /* undefined values OK */
+ }
+ if (x < 0) {
+ GLint dx = -x;
+ x = 0;
+ n -= dx;
+ stencil += dx;
+ }
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - rb->Width;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ if ((stencilMask & stencilMax) != stencilMax) {
+ /* need to apply writemask */
+ GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, destVals);
+ for (i = 0; i < n; i++) {
+ newVals[i]
+ = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
+ }
+ rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
+ }
+ else {
+ rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
+ }
+}
+
+
+
+/**
+ * Clear the stencil buffer.
+ */
+void
+_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
+{
+ const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
+ const GLuint mask = ctx->Stencil.WriteMask[0];
+ const GLuint invMask = ~mask;
+ const GLuint clearVal = (ctx->Stencil.Clear & mask);
+ const GLuint stencilMax = (1 << stencilBits) - 1;
+ GLint x, y, width, height;
+
+ if (!rb || mask == 0)
+ return;
+
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
+ rb->DataType == GL_UNSIGNED_SHORT);
+
+ ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
+
+ /* compute region to clear */
+ x = ctx->DrawBuffer->_Xmin;
+ y = ctx->DrawBuffer->_Ymin;
+ width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Direct buffer access */
+ if ((mask & stencilMax) != stencilMax) {
+ /* need to mask the clear */
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ stencil[j] = (stencil[j] & invMask) | clearVal;
+ }
+ }
+ }
+ else {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ stencil[j] = (stencil[j] & invMask) | clearVal;
+ }
+ }
+ }
+ }
+ else {
+ /* no bit masking */
+ if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
+ /* optimized case */
+ /* Note: bottom-to-top raster assumed! */
+ GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
+ GLuint len = width * height * sizeof(GLubyte);
+ _mesa_memset(stencil, clearVal, len);
+ }
+ else {
+ /* general case */
+ GLint i;
+ for (i = 0; i < height; i++) {
+ GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ _mesa_memset(stencil, clearVal, width);
+ }
+ else {
+ _mesa_memset16((short unsigned int*) stencil, clearVal, width);
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* no direct access */
+ if ((mask & stencilMax) != stencilMax) {
+ /* need to mask the clear */
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLubyte stencil[MAX_WIDTH];
+ rb->GetRow(ctx, rb, width, x, y + i, stencil);
+ for (j = 0; j < width; j++) {
+ stencil[j] = (stencil[j] & invMask) | clearVal;
+ }
+ rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
+ }
+ }
+ else {
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLushort stencil[MAX_WIDTH];
+ rb->GetRow(ctx, rb, width, x, y + i, stencil);
+ for (j = 0; j < width; j++) {
+ stencil[j] = (stencil[j] & invMask) | clearVal;
+ }
+ rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
+ }
+ }
+ }
+ else {
+ /* no bit masking */
+ const GLubyte clear8 = (GLubyte) clearVal;
+ const GLushort clear16 = (GLushort) clearVal;
+ const void *clear;
+ GLint i;
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ clear = &clear8;
+ }
+ else {
+ clear = &clear16;
+ }
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
+ }
+ }
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_stencil.h b/mesalib/src/mesa/swrast/s_stencil.h
new file mode 100644
index 000000000..cd6cbc57b
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_stencil.h
@@ -0,0 +1,52 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 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 S_STENCIL_H
+#define S_STENCIL_H
+
+
+#include "swrast.h"
+
+
+
+extern GLboolean
+_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span);
+
+
+extern void
+_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLstencil stencil[]);
+
+
+extern void
+_swrast_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
+ const GLstencil stencil[] );
+
+
+extern void
+_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c
new file mode 100644
index 000000000..889164b98
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_texcombine.c
@@ -0,0 +1,710 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.5
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/image.h"
+#include "main/imports.h"
+#include "main/pixel.h"
+#include "shader/prog_instruction.h"
+
+#include "s_context.h"
+#include "s_texcombine.h"
+
+
+/**
+ * Pointer to array of float[4]
+ * This type makes the code below more concise and avoids a lot of casting.
+ */
+typedef float (*float4_array)[4];
+
+
+/**
+ * Return array of texels for given unit.
+ */
+static INLINE float4_array
+get_texel_array(SWcontext *swrast, GLuint unit)
+{
+ return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4);
+}
+
+
+
+/**
+ * Do texture application for:
+ * GL_EXT_texture_env_combine
+ * GL_ARB_texture_env_combine
+ * GL_EXT_texture_env_dot3
+ * GL_ARB_texture_env_dot3
+ * GL_ATI_texture_env_combine3
+ * GL_NV_texture_env_combine4
+ * conventional GL texture env modes
+ *
+ * \param ctx rendering context
+ * \param unit the texture combiner unit
+ * \param n number of fragments to process (span width)
+ * \param primary_rgba incoming fragment color array
+ * \param texelBuffer pointer to texel colors for all texture units
+ *
+ * \param rgba incoming/result fragment colors
+ */
+static void
+texture_combine( GLcontext *ctx, GLuint unit, GLuint n,
+ const float4_array primary_rgba,
+ const GLfloat *texelBuffer,
+ GLchan (*rgbaChan)[4] )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
+ const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
+ float4_array argRGB[MAX_COMBINER_TERMS];
+ float4_array argA[MAX_COMBINER_TERMS];
+ const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
+ const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
+ const GLuint numArgsRGB = combine->_NumArgsRGB;
+ const GLuint numArgsA = combine->_NumArgsA;
+ GLfloat ccolor[MAX_COMBINER_TERMS][MAX_WIDTH][4]; /* temp color buffers */
+ GLfloat rgba[MAX_WIDTH][4];
+ GLuint i, term;
+
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
+ rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
+ rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
+ rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
+ }
+
+ /*
+ printf("modeRGB 0x%x modeA 0x%x srcRGB1 0x%x srcA1 0x%x srcRGB2 0x%x srcA2 0x%x\n",
+ combine->ModeRGB,
+ combine->ModeA,
+ combine->SourceRGB[0],
+ combine->SourceA[0],
+ combine->SourceRGB[1],
+ combine->SourceA[1]);
+ */
+
+ /*
+ * Do operand setup for up to 4 operands. Loop over the terms.
+ */
+ for (term = 0; term < numArgsRGB; term++) {
+ const GLenum srcRGB = combine->SourceRGB[term];
+ const GLenum operandRGB = combine->OperandRGB[term];
+
+ switch (srcRGB) {
+ case GL_TEXTURE:
+ argRGB[term] = get_texel_array(swrast, unit);
+ break;
+ case GL_PRIMARY_COLOR:
+ argRGB[term] = primary_rgba;
+ break;
+ case GL_PREVIOUS:
+ argRGB[term] = rgba;
+ break;
+ case GL_CONSTANT:
+ {
+ float4_array c = ccolor[term];
+ GLfloat red = textureUnit->EnvColor[0];
+ GLfloat green = textureUnit->EnvColor[1];
+ GLfloat blue = textureUnit->EnvColor[2];
+ GLfloat alpha = textureUnit->EnvColor[3];
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(c[i], red, green, blue, alpha);
+ }
+ argRGB[term] = ccolor[term];
+ }
+ break;
+ /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
+ */
+ case GL_ZERO:
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ argRGB[term] = ccolor[term];
+ }
+ break;
+ case GL_ONE:
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++) {
+ ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
+ }
+ argRGB[term] = ccolor[term];
+ }
+ break;
+ default:
+ /* ARB_texture_env_crossbar source */
+ {
+ const GLuint srcUnit = srcRGB - GL_TEXTURE0;
+ ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
+ if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
+ return;
+ argRGB[term] = get_texel_array(swrast, srcUnit);
+ }
+ }
+
+ if (operandRGB != GL_SRC_COLOR) {
+ float4_array src = argRGB[term];
+ float4_array dst = ccolor[term];
+
+ /* point to new arg[term] storage */
+ argRGB[term] = ccolor[term];
+
+ switch (operandRGB) {
+ case GL_ONE_MINUS_SRC_COLOR:
+ for (i = 0; i < n; i++) {
+ dst[i][RCOMP] = 1.0F - src[i][RCOMP];
+ dst[i][GCOMP] = 1.0F - src[i][GCOMP];
+ dst[i][BCOMP] = 1.0F - src[i][BCOMP];
+ }
+ break;
+ case GL_SRC_ALPHA:
+ for (i = 0; i < n; i++) {
+ dst[i][RCOMP] =
+ dst[i][GCOMP] =
+ dst[i][BCOMP] = src[i][ACOMP];
+ }
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ for (i = 0; i < n; i++) {
+ dst[i][RCOMP] =
+ dst[i][GCOMP] =
+ dst[i][BCOMP] = 1.0F - src[i][ACOMP];
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad operandRGB");
+ }
+ }
+ }
+
+ /*
+ * Set up the argA[term] pointers
+ */
+ for (term = 0; term < numArgsA; term++) {
+ const GLenum srcA = combine->SourceA[term];
+ const GLenum operandA = combine->OperandA[term];
+
+ switch (srcA) {
+ case GL_TEXTURE:
+ argA[term] = get_texel_array(swrast, unit);
+ break;
+ case GL_PRIMARY_COLOR:
+ argA[term] = primary_rgba;
+ break;
+ case GL_PREVIOUS:
+ argA[term] = rgba;
+ break;
+ case GL_CONSTANT:
+ {
+ float4_array c = ccolor[term];
+ GLfloat alpha = textureUnit->EnvColor[3];
+ for (i = 0; i < n; i++)
+ c[i][ACOMP] = alpha;
+ argA[term] = ccolor[term];
+ }
+ break;
+ /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
+ */
+ case GL_ZERO:
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++)
+ c[i][ACOMP] = 0.0F;
+ argA[term] = ccolor[term];
+ }
+ break;
+ case GL_ONE:
+ {
+ float4_array c = ccolor[term];
+ for (i = 0; i < n; i++)
+ c[i][ACOMP] = 1.0F;
+ argA[term] = ccolor[term];
+ }
+ break;
+ default:
+ /* ARB_texture_env_crossbar source */
+ {
+ const GLuint srcUnit = srcA - GL_TEXTURE0;
+ ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
+ if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
+ return;
+ argA[term] = get_texel_array(swrast, srcUnit);
+ }
+ }
+
+ if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
+ float4_array src = argA[term];
+ float4_array dst = ccolor[term];
+ argA[term] = ccolor[term];
+ for (i = 0; i < n; i++) {
+ dst[i][ACOMP] = 1.0F - src[i][ACOMP];
+ }
+ }
+ }
+
+ /* RGB channel combine */
+ {
+ float4_array arg0 = argRGB[0];
+ float4_array arg1 = argRGB[1];
+ float4_array arg2 = argRGB[2];
+ float4_array arg3 = argRGB[3];
+
+ switch (combine->ModeRGB) {
+ case GL_REPLACE:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
+ rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
+ rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
+ }
+ break;
+ case GL_MODULATE:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
+ rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
+ rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
+ }
+ break;
+ case GL_ADD:
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) */
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
+ arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
+ arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
+ arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
+ }
+ }
+ else {
+ /* 2-term addition */
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
+ }
+ }
+ break;
+ case GL_ADD_SIGNED:
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) - 0.5 */
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
+ arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
+ arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
+ arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5) * scaleRGB;
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * scaleRGB;
+ }
+ }
+ break;
+ case GL_INTERPOLATE:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
+ arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
+ arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
+ arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
+ }
+ break;
+ case GL_SUBTRACT:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
+ }
+ break;
+ case GL_DOT3_RGB_EXT:
+ case GL_DOT3_RGBA_EXT:
+ /* Do not scale the result by 1 2 or 4 */
+ for (i = 0; i < n; i++) {
+ GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
+ (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
+ (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
+ * 4.0F;
+ dot = CLAMP(dot, 0.0F, 1.0F);
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
+ }
+ break;
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
+ /* DO scale the result by 1 2 or 4 */
+ for (i = 0; i < n; i++) {
+ GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
+ (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
+ (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
+ * 4.0F * scaleRGB;
+ dot = CLAMP(dot, 0.0, 1.0F);
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
+ }
+ break;
+ case GL_MODULATE_ADD_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
+ arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
+ arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
+ arg1[i][BCOMP]) * scaleRGB;
+ }
+ break;
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
+ arg1[i][RCOMP] - 0.5) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
+ arg1[i][GCOMP] - 0.5) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
+ arg1[i][BCOMP] - 0.5) * scaleRGB;
+ }
+ break;
+ case GL_MODULATE_SUBTRACT_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
+ arg1[i][RCOMP]) * scaleRGB;
+ rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
+ arg1[i][GCOMP]) * scaleRGB;
+ rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
+ arg1[i][BCOMP]) * scaleRGB;
+ }
+ break;
+ case GL_BUMP_ENVMAP_ATI:
+ /* this produces a fixed rgba color, and the coord calc is done elsewhere */
+ for (i = 0; i < n; i++) {
+ /* rgba result is 0,0,0,1 */
+ rgba[i][RCOMP] = 0.0;
+ rgba[i][GCOMP] = 0.0;
+ rgba[i][BCOMP] = 0.0;
+ rgba[i][ACOMP] = 1.0;
+ }
+ return; /* no alpha processing */
+ default:
+ _mesa_problem(ctx, "invalid combine mode");
+ }
+ }
+
+ /* Alpha channel combine */
+ {
+ float4_array arg0 = argA[0];
+ float4_array arg1 = argA[1];
+ float4_array arg2 = argA[2];
+ float4_array arg3 = argA[3];
+
+ switch (combine->ModeA) {
+ case GL_REPLACE:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
+ }
+ break;
+ case GL_MODULATE:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
+ }
+ break;
+ case GL_ADD:
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
+ arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
+ }
+ }
+ else {
+ /* two-term add */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
+ }
+ }
+ break;
+ case GL_ADD_SIGNED:
+ if (textureUnit->EnvMode == GL_COMBINE4_NV) {
+ /* (a * b) + (c * d) - 0.5 */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
+ arg2[i][ACOMP] * arg3[i][ACOMP] -
+ 0.5) * scaleA;
+ }
+ }
+ else {
+ /* a + b - 0.5 */
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
+ }
+ }
+ break;
+ case GL_INTERPOLATE:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
+ arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
+ * scaleA;
+ }
+ break;
+ case GL_SUBTRACT:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
+ }
+ break;
+ case GL_MODULATE_ADD_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
+ + arg1[i][ACOMP]) * scaleA;
+ }
+ break;
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
+ arg1[i][ACOMP] - 0.5F) * scaleA;
+ }
+ break;
+ case GL_MODULATE_SUBTRACT_ATI:
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
+ - arg1[i][ACOMP]) * scaleA;
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "invalid combine mode");
+ }
+ }
+
+ /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
+ * This is kind of a kludge. It would have been better if the spec
+ * were written such that the GL_COMBINE_ALPHA value could be set to
+ * GL_DOT3.
+ */
+ if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
+ combine->ModeRGB == GL_DOT3_RGBA) {
+ for (i = 0; i < n; i++) {
+ rgba[i][ACOMP] = rgba[i][RCOMP];
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
+ }
+}
+
+
+/**
+ * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
+ * See GL_EXT_texture_swizzle.
+ */
+static void
+swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
+{
+ const GLuint swzR = GET_SWZ(swizzle, 0);
+ const GLuint swzG = GET_SWZ(swizzle, 1);
+ const GLuint swzB = GET_SWZ(swizzle, 2);
+ const GLuint swzA = GET_SWZ(swizzle, 3);
+ GLfloat vector[6];
+ GLuint i;
+
+ vector[SWIZZLE_ZERO] = 0;
+ vector[SWIZZLE_ONE] = 1.0F;
+
+ for (i = 0; i < count; i++) {
+ vector[SWIZZLE_X] = texels[i][0];
+ vector[SWIZZLE_Y] = texels[i][1];
+ vector[SWIZZLE_Z] = texels[i][2];
+ vector[SWIZZLE_W] = texels[i][3];
+ texels[i][RCOMP] = vector[swzR];
+ texels[i][GCOMP] = vector[swzG];
+ texels[i][BCOMP] = vector[swzB];
+ texels[i][ACOMP] = vector[swzA];
+ }
+}
+
+
+/**
+ * Apply texture mapping to a span of fragments.
+ */
+void
+_swrast_texture_span( GLcontext *ctx, SWspan *span )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat primary_rgba[MAX_WIDTH][4];
+ GLuint unit;
+
+ ASSERT(span->end <= MAX_WIDTH);
+
+ /*
+ * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
+ */
+ if (swrast->_TextureCombinePrimary) {
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
+ primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
+ primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
+ primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
+ }
+ }
+
+ /* First must sample all bump maps */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ if (texUnit->_ReallyEnabled &&
+ texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
+ const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
+ span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
+ float4_array targetcoords =
+ span->array->attribs[FRAG_ATTRIB_TEX0 +
+ ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
+
+ const struct gl_texture_object *curObj = texUnit->_Current;
+ GLfloat *lambda = span->array->lambda[unit];
+ float4_array texels = get_texel_array(swrast, unit);
+ GLuint i;
+ GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
+ GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
+ GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
+ GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
+
+ /* adjust texture lod (lambda) */
+ if (span->arrayMask & SPAN_LAMBDA) {
+ if (texUnit->LodBias + curObj->LodBias != 0.0F) {
+ /* apply LOD bias, but don't clamp yet */
+ const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
+ -ctx->Const.MaxTextureLodBias,
+ ctx->Const.MaxTextureLodBias);
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ lambda[i] += bias;
+ }
+ }
+
+ if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
+ /* apply LOD clamping to lambda */
+ const GLfloat min = curObj->MinLod;
+ const GLfloat max = curObj->MaxLod;
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ GLfloat l = lambda[i];
+ lambda[i] = CLAMP(l, min, max);
+ }
+ }
+ }
+
+ /* Sample the texture (span->end = number of fragments) */
+ swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
+ texcoords, lambda, texels );
+
+ /* manipulate the span values of the bump target
+ not sure this can work correctly even ignoring
+ the problem that channel is unsigned */
+ for (i = 0; i < span->end; i++) {
+ targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
+ rotMatrix01) / targetcoords[i][3];
+ targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
+ rotMatrix11) / targetcoords[i][3];
+ }
+ }
+ }
+
+ /*
+ * Must do all texture sampling before combining in order to
+ * accomodate GL_ARB_texture_env_crossbar.
+ */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ if (texUnit->_ReallyEnabled &&
+ texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
+ const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
+ span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
+ const struct gl_texture_object *curObj = texUnit->_Current;
+ GLfloat *lambda = span->array->lambda[unit];
+ float4_array texels = get_texel_array(swrast, unit);
+
+ /* adjust texture lod (lambda) */
+ if (span->arrayMask & SPAN_LAMBDA) {
+ if (texUnit->LodBias + curObj->LodBias != 0.0F) {
+ /* apply LOD bias, but don't clamp yet */
+ const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
+ -ctx->Const.MaxTextureLodBias,
+ ctx->Const.MaxTextureLodBias);
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ lambda[i] += bias;
+ }
+ }
+
+ if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
+ /* apply LOD clamping to lambda */
+ const GLfloat min = curObj->MinLod;
+ const GLfloat max = curObj->MaxLod;
+ GLuint i;
+ for (i = 0; i < span->end; i++) {
+ GLfloat l = lambda[i];
+ lambda[i] = CLAMP(l, min, max);
+ }
+ }
+ }
+
+ /* Sample the texture (span->end = number of fragments) */
+ swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
+ texcoords, lambda, texels );
+
+ /* GL_SGI_texture_color_table */
+ if (texUnit->ColorTableEnabled) {
+ _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
+ }
+
+ /* GL_EXT_texture_swizzle */
+ if (curObj->_Swizzle != SWIZZLE_NOOP) {
+ swizzle_texels(curObj->_Swizzle, span->end, texels);
+ }
+ }
+ }
+
+ /*
+ * OK, now apply the texture (aka texture combine/blend).
+ * We modify the span->color.rgba values.
+ */
+ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
+ if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+ texture_combine( ctx, unit, span->end,
+ primary_rgba,
+ swrast->TexelBuffer,
+ span->array->rgba );
+ }
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_texcombine.h b/mesalib/src/mesa/swrast/s_texcombine.h
new file mode 100644
index 000000000..9ed96efb8
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_texcombine.h
@@ -0,0 +1,35 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 S_TEXCOMBINE_H
+#define S_TEXCOMBINE_H
+
+
+#include "swrast.h"
+
+extern void
+_swrast_texture_span( GLcontext *ctx, SWspan *span );
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c
new file mode 100644
index 000000000..efe6f2347
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_texfilter.c
@@ -0,0 +1,3266 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/imports.h"
+#include "main/texformat.h"
+
+#include "s_context.h"
+#include "s_texfilter.h"
+
+
+/*
+ * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
+ * see 1-pixel bands of improperly weighted linear-filtered textures.
+ * The tests/texwrap.c demo is a good test.
+ * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
+ * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
+ */
+#define FRAC(f) ((f) - IFLOOR(f))
+
+
+
+/**
+ * Linear interpolation macro
+ */
+#define LERP(T, A, B) ( (A) + (T) * ((B) - (A)) )
+
+
+/**
+ * Do 2D/biliner interpolation of float values.
+ * v00, v10, v01 and v11 are typically four texture samples in a square/box.
+ * a and b are the horizontal and vertical interpolants.
+ * It's important that this function is inlined when compiled with
+ * optimization! If we find that's not true on some systems, convert
+ * to a macro.
+ */
+static INLINE GLfloat
+lerp_2d(GLfloat a, GLfloat b,
+ GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
+{
+ const GLfloat temp0 = LERP(a, v00, v10);
+ const GLfloat temp1 = LERP(a, v01, v11);
+ return LERP(b, temp0, temp1);
+}
+
+
+/**
+ * Do 3D/trilinear interpolation of float values.
+ * \sa lerp_2d
+ */
+static INLINE GLfloat
+lerp_3d(GLfloat a, GLfloat b, GLfloat c,
+ GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110,
+ GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111)
+{
+ const GLfloat temp00 = LERP(a, v000, v100);
+ const GLfloat temp10 = LERP(a, v010, v110);
+ const GLfloat temp01 = LERP(a, v001, v101);
+ const GLfloat temp11 = LERP(a, v011, v111);
+ const GLfloat temp0 = LERP(b, temp00, temp10);
+ const GLfloat temp1 = LERP(b, temp01, temp11);
+ return LERP(c, temp0, temp1);
+}
+
+
+/**
+ * Do linear interpolation of colors.
+ */
+static INLINE void
+lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4])
+{
+ result[0] = LERP(t, a[0], b[0]);
+ result[1] = LERP(t, a[1], b[1]);
+ result[2] = LERP(t, a[2], b[2]);
+ result[3] = LERP(t, a[3], b[3]);
+}
+
+
+/**
+ * Do bilinear interpolation of colors.
+ */
+static INLINE void
+lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b,
+ const GLfloat t00[4], const GLfloat t10[4],
+ const GLfloat t01[4], const GLfloat t11[4])
+{
+ result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
+ result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
+ result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
+ result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
+}
+
+
+/**
+ * Do trilinear interpolation of colors.
+ */
+static INLINE void
+lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
+ const GLfloat t000[4], const GLfloat t100[4],
+ const GLfloat t010[4], const GLfloat t110[4],
+ const GLfloat t001[4], const GLfloat t101[4],
+ const GLfloat t011[4], const GLfloat t111[4])
+{
+ GLuint k;
+ /* compiler should unroll these short loops */
+ for (k = 0; k < 4; k++) {
+ result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],
+ t001[k], t101[k], t011[k], t111[k]);
+ }
+}
+
+
+/**
+ * If A is a signed integer, A % B doesn't give the right value for A < 0
+ * (in terms of texture repeat). Just casting to unsigned fixes that.
+ */
+#define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
+
+
+/**
+ * Used to compute texel locations for linear sampling.
+ * Input:
+ * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
+ * s = texcoord in [0,1]
+ * size = width (or height or depth) of texture
+ * Output:
+ * i0, i1 = returns two nearest texel indexes
+ * weight = returns blend factor between texels
+ */
+static INLINE void
+linear_texel_locations(GLenum wrapMode,
+ const struct gl_texture_image *img,
+ GLint size, GLfloat s,
+ GLint *i0, GLint *i1, GLfloat *weight)
+{
+ GLfloat u;
+ switch (wrapMode) {
+ case GL_REPEAT:
+ u = s * size - 0.5F;
+ if (img->_IsPowerOfTwo) {
+ *i0 = IFLOOR(u) & (size - 1);
+ *i1 = (*i0 + 1) & (size - 1);
+ }
+ else {
+ *i0 = REMAINDER(IFLOOR(u), size);
+ *i1 = REMAINDER(*i0 + 1, size);
+ }
+ break;
+ case GL_CLAMP_TO_EDGE:
+ if (s <= 0.0F)
+ u = 0.0F;
+ else if (s >= 1.0F)
+ u = (GLfloat) size;
+ else
+ u = s * size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ if (*i0 < 0)
+ *i0 = 0;
+ if (*i1 >= (GLint) size)
+ *i1 = size - 1;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ {
+ const GLfloat min = -1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ if (s <= min)
+ u = min * size;
+ else if (s >= max)
+ u = max * size;
+ else
+ u = s * size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ }
+ break;
+ case GL_MIRRORED_REPEAT:
+ {
+ const GLint flr = IFLOOR(s);
+ if (flr & 1)
+ u = 1.0F - (s - (GLfloat) flr);
+ else
+ u = s - (GLfloat) flr;
+ u = (u * size) - 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ if (*i0 < 0)
+ *i0 = 0;
+ if (*i1 >= (GLint) size)
+ *i1 = size - 1;
+ }
+ break;
+ case GL_MIRROR_CLAMP_EXT:
+ u = FABSF(s);
+ if (u >= 1.0F)
+ u = (GLfloat) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ break;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+ u = FABSF(s);
+ if (u >= 1.0F)
+ u = (GLfloat) size;
+ else
+ u *= size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ if (*i0 < 0)
+ *i0 = 0;
+ if (*i1 >= (GLint) size)
+ *i1 = size - 1;
+ break;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+ {
+ const GLfloat min = -1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ u = FABSF(s);
+ if (u <= min)
+ u = min * size;
+ else if (u >= max)
+ u = max * size;
+ else
+ u *= size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ }
+ break;
+ case GL_CLAMP:
+ if (s <= 0.0F)
+ u = 0.0F;
+ else if (s >= 1.0F)
+ u = (GLfloat) size;
+ else
+ u = s * size;
+ u -= 0.5F;
+ *i0 = IFLOOR(u);
+ *i1 = *i0 + 1;
+ break;
+ default:
+ _mesa_problem(NULL, "Bad wrap mode");
+ u = 0.0F;
+ }
+ *weight = FRAC(u);
+}
+
+
+/**
+ * Used to compute texel location for nearest sampling.
+ */
+static INLINE GLint
+nearest_texel_location(GLenum wrapMode,
+ const struct gl_texture_image *img,
+ GLint size, GLfloat s)
+{
+ GLint i;
+
+ switch (wrapMode) {
+ case GL_REPEAT:
+ /* s limited to [0,1) */
+ /* i limited to [0,size-1] */
+ i = IFLOOR(s * size);
+ if (img->_IsPowerOfTwo)
+ i &= (size - 1);
+ else
+ i = REMAINDER(i, size);
+ return i;
+ case GL_CLAMP_TO_EDGE:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const GLfloat min = 1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ if (s < min)
+ i = 0;
+ else if (s > max)
+ i = size - 1;
+ else
+ i = IFLOOR(s * size);
+ }
+ return i;
+ case GL_CLAMP_TO_BORDER:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [-1, size] */
+ const GLfloat min = -1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ if (s <= min)
+ i = -1;
+ else if (s >= max)
+ i = size;
+ else
+ i = IFLOOR(s * size);
+ }
+ return i;
+ case GL_MIRRORED_REPEAT:
+ {
+ const GLfloat min = 1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ const GLint flr = IFLOOR(s);
+ GLfloat u;
+ if (flr & 1)
+ u = 1.0F - (s - (GLfloat) flr);
+ else
+ u = s - (GLfloat) flr;
+ if (u < min)
+ i = 0;
+ else if (u > max)
+ i = size - 1;
+ else
+ i = IFLOOR(u * size);
+ }
+ return i;
+ case GL_MIRROR_CLAMP_EXT:
+ {
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ const GLfloat u = FABSF(s);
+ if (u <= 0.0F)
+ i = 0;
+ else if (u >= 1.0F)
+ i = size - 1;
+ else
+ i = IFLOOR(u * size);
+ }
+ return i;
+ case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const GLfloat min = 1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ const GLfloat u = FABSF(s);
+ if (u < min)
+ i = 0;
+ else if (u > max)
+ i = size - 1;
+ else
+ i = IFLOOR(u * size);
+ }
+ return i;
+ case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+ {
+ /* s limited to [min,max] */
+ /* i limited to [0, size-1] */
+ const GLfloat min = -1.0F / (2.0F * size);
+ const GLfloat max = 1.0F - min;
+ const GLfloat u = FABSF(s);
+ if (u < min)
+ i = -1;
+ else if (u > max)
+ i = size;
+ else
+ i = IFLOOR(u * size);
+ }
+ return i;
+ case GL_CLAMP:
+ /* s limited to [0,1] */
+ /* i limited to [0,size-1] */
+ if (s <= 0.0F)
+ i = 0;
+ else if (s >= 1.0F)
+ i = size - 1;
+ else
+ i = IFLOOR(s * size);
+ return i;
+ default:
+ _mesa_problem(NULL, "Bad wrap mode");
+ return 0;
+ }
+}
+
+
+/* Power of two image sizes only */
+static INLINE void
+linear_repeat_texel_location(GLuint size, GLfloat s,
+ GLint *i0, GLint *i1, GLfloat *weight)
+{
+ GLfloat u = s * size - 0.5F;
+ *i0 = IFLOOR(u) & (size - 1);
+ *i1 = (*i0 + 1) & (size - 1);
+ *weight = FRAC(u);
+}
+
+
+/**
+ * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
+ */
+static INLINE GLint
+clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
+{
+ switch (wrapMode) {
+ case GL_CLAMP:
+ return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
+ case GL_CLAMP_TO_EDGE:
+ return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
+ case GL_CLAMP_TO_BORDER:
+ return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
+ default:
+ _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
+ return 0;
+ }
+}
+
+
+/**
+ * As above, but GL_LINEAR filtering.
+ */
+static INLINE void
+clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
+ GLint *i0out, GLint *i1out, GLfloat *weight)
+{
+ GLfloat fcol;
+ GLint i0, i1;
+ switch (wrapMode) {
+ case GL_CLAMP:
+ /* Not exactly what the spec says, but it matches NVIDIA output */
+ fcol = CLAMP(coord - 0.5F, 0.0, max-1);
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ fcol = CLAMP(coord, 0.5F, max - 0.5F);
+ fcol -= 0.5F;
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ if (i1 > max - 1)
+ i1 = max - 1;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ fcol = CLAMP(coord, -0.5F, max + 0.5F);
+ fcol -= 0.5F;
+ i0 = IFLOOR(fcol);
+ i1 = i0 + 1;
+ break;
+ default:
+ _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
+ i0 = i1 = 0;
+ fcol = 0.0F;
+ }
+ *i0out = i0;
+ *i1out = i1;
+ *weight = FRAC(fcol);
+}
+
+
+/**
+ * Compute nearest integer texcoords for given texobj and coordinate.
+ */
+static INLINE void
+nearest_texcoord(const struct gl_texture_object *texObj,
+ const GLfloat texcoord[4],
+ GLint *i, GLint *j, GLint *k)
+{
+ const GLint baseLevel = texObj->BaseLevel;
+ const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ const GLint depth = img->Depth;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_RECTANGLE_ARB:
+ *i = clamp_rect_coord_nearest(texObj->WrapS, texcoord[0], width);
+ *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *k = 0;
+ break;
+ case GL_TEXTURE_1D:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = 0;
+ *k = 0;
+ break;
+ case GL_TEXTURE_2D:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
+ *k = 0;
+ break;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *k = 0;
+ break;
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
+ *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
+ *k = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+ break;
+ default:
+ *i = *j = *k = 0;
+ }
+}
+
+
+/**
+ * Compute linear integer texcoords for given texobj and coordinate.
+ */
+static INLINE void
+linear_texcoord(const struct gl_texture_object *texObj,
+ const GLfloat texcoord[4],
+ GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
+ GLfloat *wi, GLfloat *wj)
+{
+ const GLint baseLevel = texObj->BaseLevel;
+ const struct gl_texture_image *img = texObj->Image[0][baseLevel];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ const GLint depth = img->Depth;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_RECTANGLE_ARB:
+ clamp_rect_coord_linear(texObj->WrapS, texcoord[0],
+ width, i0, i1, wi);
+ clamp_rect_coord_linear(texObj->WrapT, texcoord[1],
+ height, j0, j1, wj);
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ linear_texel_locations(texObj->WrapT, img, height,
+ texcoord[1], j0, j1, wj);
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ *j0 = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
+ *j1 = *j0;
+ *slice = 0;
+ break;
+
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ linear_texel_locations(texObj->WrapS, img, width,
+ texcoord[0], i0, i1, wi);
+ linear_texel_locations(texObj->WrapT, img, height,
+ texcoord[1], j0, j1, wj);
+ *slice = clamp_rect_coord_nearest(texObj->WrapR, texcoord[2], depth);
+ break;
+
+ default:
+ *slice = 0;
+ }
+}
+
+
+
+/**
+ * For linear interpolation between mipmap levels N and N+1, this function
+ * computes N.
+ */
+static INLINE GLint
+linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
+{
+ if (lambda < 0.0F)
+ return tObj->BaseLevel;
+ else if (lambda > tObj->_MaxLambda)
+ return (GLint) (tObj->BaseLevel + tObj->_MaxLambda);
+ else
+ return (GLint) (tObj->BaseLevel + lambda);
+}
+
+
+/**
+ * Compute the nearest mipmap level to take texels from.
+ */
+static INLINE GLint
+nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
+{
+ GLfloat l;
+ GLint level;
+ if (lambda <= 0.5F)
+ l = 0.0F;
+ else if (lambda > tObj->_MaxLambda + 0.4999F)
+ l = tObj->_MaxLambda + 0.4999F;
+ else
+ l = lambda;
+ level = (GLint) (tObj->BaseLevel + l + 0.5F);
+ if (level > tObj->_MaxLevel)
+ level = tObj->_MaxLevel;
+ return level;
+}
+
+
+
+/*
+ * Bitflags for texture border color sampling.
+ */
+#define I0BIT 1
+#define I1BIT 2
+#define J0BIT 4
+#define J1BIT 8
+#define K0BIT 16
+#define K1BIT 32
+
+
+
+/**
+ * The lambda[] array values are always monotonic. Either the whole span
+ * will be minified, magnified, or split between the two. This function
+ * determines the subranges in [0, n-1] that are to be minified or magnified.
+ */
+static INLINE void
+compute_min_mag_ranges(const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat lambda[],
+ GLuint *minStart, GLuint *minEnd,
+ GLuint *magStart, GLuint *magEnd)
+{
+ GLfloat minMagThresh;
+
+ /* we shouldn't be here if minfilter == magfilter */
+ ASSERT(tObj->MinFilter != tObj->MagFilter);
+
+ /* This bit comes from the OpenGL spec: */
+ if (tObj->MagFilter == GL_LINEAR
+ && (tObj->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
+ tObj->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
+ minMagThresh = 0.5F;
+ }
+ else {
+ minMagThresh = 0.0F;
+ }
+
+#if 0
+ /* DEBUG CODE: Verify that lambda[] is monotonic.
+ * We can't really use this because the inaccuracy in the LOG2 function
+ * causes this test to fail, yet the resulting texturing is correct.
+ */
+ if (n > 1) {
+ GLuint i;
+ printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
+ if (lambda[0] >= lambda[n-1]) { /* decreasing */
+ for (i = 0; i < n - 1; i++) {
+ ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
+ }
+ }
+ else { /* increasing */
+ for (i = 0; i < n - 1; i++) {
+ ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
+ }
+ }
+ }
+#endif /* DEBUG */
+
+ if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) {
+ /* magnification for whole span */
+ *magStart = 0;
+ *magEnd = n;
+ *minStart = *minEnd = 0;
+ }
+ else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) {
+ /* minification for whole span */
+ *minStart = 0;
+ *minEnd = n;
+ *magStart = *magEnd = 0;
+ }
+ else {
+ /* a mix of minification and magnification */
+ GLuint i;
+ if (lambda[0] > minMagThresh) {
+ /* start with minification */
+ for (i = 1; i < n; i++) {
+ if (lambda[i] <= minMagThresh)
+ break;
+ }
+ *minStart = 0;
+ *minEnd = i;
+ *magStart = i;
+ *magEnd = n;
+ }
+ else {
+ /* start with magnification */
+ for (i = 1; i < n; i++) {
+ if (lambda[i] > minMagThresh)
+ break;
+ }
+ *magStart = 0;
+ *magEnd = i;
+ *minStart = i;
+ *minEnd = n;
+ }
+ }
+
+#if 0
+ /* Verify the min/mag Start/End values
+ * We don't use this either (see above)
+ */
+ {
+ GLint i;
+ for (i = 0; i < n; i++) {
+ if (lambda[i] > minMagThresh) {
+ /* minification */
+ ASSERT(i >= *minStart);
+ ASSERT(i < *minEnd);
+ }
+ else {
+ /* magnification */
+ ASSERT(i >= *magStart);
+ ASSERT(i < *magEnd);
+ }
+ }
+ }
+#endif
+}
+
+
+/**
+ * When we sample the border color, it must be interpreted according to
+ * the base texture format. Ex: if the texture base format it GL_ALPHA,
+ * we return (0,0,0,BorderAlpha).
+ */
+static INLINE void
+get_border_color(const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ GLfloat rgba[4])
+{
+ switch (img->TexFormat->BaseFormat) {
+ case GL_RGB:
+ rgba[0] = tObj->BorderColor[0];
+ rgba[1] = tObj->BorderColor[1];
+ rgba[2] = tObj->BorderColor[2];
+ rgba[3] = 1.0F;
+ break;
+ case GL_ALPHA:
+ rgba[0] = rgba[1] = rgba[2] = 0.0;
+ rgba[3] = tObj->BorderColor[3];
+ break;
+ case GL_LUMINANCE:
+ rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor[0];
+ rgba[3] = 1.0;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor[0];
+ rgba[3] = tObj->BorderColor[3];
+ break;
+ case GL_INTENSITY:
+ rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->BorderColor[0];
+ break;
+ default:
+ COPY_4V(rgba, tObj->BorderColor);
+ }
+}
+
+
+/**********************************************************************/
+/* 1-D Texture Sampling Functions */
+/**********************************************************************/
+
+/**
+ * Return the texture sample for coordinate (s) using GL_NEAREST filter.
+ */
+static INLINE void
+sample_1d_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4], GLfloat rgba[4])
+{
+ const GLint width = img->Width2; /* without border, power of two */
+ GLint i;
+ i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
+ /* skip over the border, if any */
+ i += img->Border;
+ if (i < 0 || i >= (GLint) img->Width) {
+ /* Need this test for GL_CLAMP_TO_BORDER mode */
+ get_border_color(tObj, img, rgba);
+ }
+ else {
+ img->FetchTexelf(img, i, 0, 0, rgba);
+ }
+}
+
+
+/**
+ * Return the texture sample for coordinate (s) using GL_LINEAR filter.
+ */
+static INLINE void
+sample_1d_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4], GLfloat rgba[4])
+{
+ const GLint width = img->Width2;
+ GLint i0, i1;
+ GLbitfield useBorderColor = 0x0;
+ GLfloat a;
+ GLfloat t0[4], t1[4]; /* texels */
+
+ linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
+
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ }
+ else {
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ }
+
+ /* fetch texel colors */
+ if (useBorderColor & I0BIT) {
+ get_border_color(tObj, img, t0);
+ }
+ else {
+ img->FetchTexelf(img, i0, 0, 0, t0);
+ }
+ if (useBorderColor & I1BIT) {
+ get_border_color(tObj, img, t1);
+ }
+ else {
+ img->FetchTexelf(img, i1, 0, 0, t1);
+ }
+
+ lerp_rgba(rgba, a, t0, t1);
+}
+
+
+static void
+sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_1d_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_1d_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4];
+ const GLfloat f = FRAC(lambda[i]);
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_1d_linear_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4];
+ const GLfloat f = FRAC(lambda[i]);
+ sample_1d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample 1D texture, nearest filtering for both min/magnification */
+static void
+sample_nearest_1d( GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4] )
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 1D texture, linear filtering for both min/magnification */
+static void
+sample_linear_1d( GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4] )
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 1D texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_1d( GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4] )
+{
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+ GLuint i;
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ const GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ for (i = minStart; i < minEnd; i++)
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = minStart; i < minEnd; i++)
+ sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
+ return;
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ for (i = magStart; i < magEnd; i++)
+ sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = magStart; i < magEnd; i++)
+ sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
+ return;
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* 2-D Texture Sampling Functions */
+/**********************************************************************/
+
+
+/**
+ * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
+ */
+static INLINE void
+sample_2d_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[])
+{
+ const GLint width = img->Width2; /* without border, power of two */
+ const GLint height = img->Height2; /* without border, power of two */
+ GLint i, j;
+ (void) ctx;
+
+ i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
+ j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
+
+ /* skip over the border, if any */
+ i += img->Border;
+ j += img->Border;
+
+ if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
+ /* Need this test for GL_CLAMP_TO_BORDER mode */
+ get_border_color(tObj, img, rgba);
+ }
+ else {
+ img->FetchTexelf(img, i, j, 0, rgba);
+ }
+}
+
+
+/**
+ * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
+ * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
+ */
+static INLINE void
+sample_2d_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[])
+{
+ const GLint width = img->Width2;
+ const GLint height = img->Height2;
+ GLint i0, j0, i1, j1;
+ GLbitfield useBorderColor = 0x0;
+ GLfloat a, b;
+ GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
+
+ linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
+ linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
+
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ j0 += img->Border;
+ j1 += img->Border;
+ }
+ else {
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
+ if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
+ }
+
+ /* fetch four texel colors */
+ if (useBorderColor & (I0BIT | J0BIT)) {
+ get_border_color(tObj, img, t00);
+ }
+ else {
+ img->FetchTexelf(img, i0, j0, 0, t00);
+ }
+ if (useBorderColor & (I1BIT | J0BIT)) {
+ get_border_color(tObj, img, t10);
+ }
+ else {
+ img->FetchTexelf(img, i1, j0, 0, t10);
+ }
+ if (useBorderColor & (I0BIT | J1BIT)) {
+ get_border_color(tObj, img, t01);
+ }
+ else {
+ img->FetchTexelf(img, i0, j1, 0, t01);
+ }
+ if (useBorderColor & (I1BIT | J1BIT)) {
+ get_border_color(tObj, img, t11);
+ }
+ else {
+ img->FetchTexelf(img, i1, j1, 0, t11);
+ }
+
+ lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
+}
+
+
+/**
+ * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
+ * We don't have to worry about the texture border.
+ */
+static INLINE void
+sample_2d_linear_repeat(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[])
+{
+ const GLint width = img->Width2;
+ const GLint height = img->Height2;
+ GLint i0, j0, i1, j1;
+ GLfloat wi, wj;
+ GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
+
+ (void) ctx;
+
+ ASSERT(tObj->WrapS == GL_REPEAT);
+ ASSERT(tObj->WrapT == GL_REPEAT);
+ ASSERT(img->Border == 0);
+ ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX);
+ ASSERT(img->_IsPowerOfTwo);
+
+ linear_repeat_texel_location(width, texcoord[0], &i0, &i1, &wi);
+ linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj);
+
+ img->FetchTexelf(img, i0, j0, 0, t00);
+ img->FetchTexelf(img, i1, j0, 0, t10);
+ img->FetchTexelf(img, i0, j1, 0, t01);
+ img->FetchTexelf(img, i1, j1, 0, t11);
+
+ lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11);
+}
+
+
+static void
+sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_2d_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_2d_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_2d_linear_mipmap_linear( GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4] )
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_2d_linear_mipmap_linear_repeat(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ ASSERT(tObj->WrapS == GL_REPEAT);
+ ASSERT(tObj->WrapT == GL_REPEAT);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level ],
+ texcoord[i], t0);
+ sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1],
+ texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample 2D texture, nearest filtering for both min/magnification */
+static void
+sample_nearest_2d(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 2D texture, linear filtering for both min/magnification */
+static void
+sample_linear_2d(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ if (tObj->WrapS == GL_REPEAT &&
+ tObj->WrapT == GL_REPEAT &&
+ image->_IsPowerOfTwo &&
+ image->Border == 0) {
+ for (i = 0; i < n; i++) {
+ sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+ }
+}
+
+
+/**
+ * Optimized 2-D texture sampling:
+ * S and T wrap mode == GL_REPEAT
+ * GL_NEAREST min/mag filter
+ * No border,
+ * RowStride == Width,
+ * Format = GL_RGB
+ */
+static void
+opt_sample_rgb_2d(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
+ const GLfloat width = (GLfloat) img->Width;
+ const GLfloat height = (GLfloat) img->Height;
+ const GLint colMask = img->Width - 1;
+ const GLint rowMask = img->Height - 1;
+ const GLint shift = img->WidthLog2;
+ GLuint k;
+ (void) ctx;
+ (void) lambda;
+ ASSERT(tObj->WrapS==GL_REPEAT);
+ ASSERT(tObj->WrapT==GL_REPEAT);
+ ASSERT(img->Border==0);
+ ASSERT(img->TexFormat->MesaFormat==MESA_FORMAT_RGB);
+ ASSERT(img->_IsPowerOfTwo);
+
+ for (k=0; k<n; k++) {
+ GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
+ GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
+ GLint pos = (j << shift) | i;
+ GLchan *texel = ((GLchan *) img->Data) + 3*pos;
+ rgba[k][RCOMP] = CHAN_TO_FLOAT(texel[0]);
+ rgba[k][GCOMP] = CHAN_TO_FLOAT(texel[1]);
+ rgba[k][BCOMP] = CHAN_TO_FLOAT(texel[2]);
+ }
+}
+
+
+/**
+ * Optimized 2-D texture sampling:
+ * S and T wrap mode == GL_REPEAT
+ * GL_NEAREST min/mag filter
+ * No border
+ * RowStride == Width,
+ * Format = GL_RGBA
+ */
+static void
+opt_sample_rgba_2d(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
+ const GLfloat width = (GLfloat) img->Width;
+ const GLfloat height = (GLfloat) img->Height;
+ const GLint colMask = img->Width - 1;
+ const GLint rowMask = img->Height - 1;
+ const GLint shift = img->WidthLog2;
+ GLuint i;
+ (void) ctx;
+ (void) lambda;
+ ASSERT(tObj->WrapS==GL_REPEAT);
+ ASSERT(tObj->WrapT==GL_REPEAT);
+ ASSERT(img->Border==0);
+ ASSERT(img->TexFormat->MesaFormat==MESA_FORMAT_RGBA);
+ ASSERT(img->_IsPowerOfTwo);
+
+ for (i = 0; i < n; i++) {
+ const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
+ const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
+ const GLint pos = (row << shift) | col;
+ const GLchan *texel = ((GLchan *) img->Data) + (pos << 2); /* pos*4 */
+ rgba[i][RCOMP] = CHAN_TO_FLOAT(texel[0]);
+ rgba[i][GCOMP] = CHAN_TO_FLOAT(texel[1]);
+ rgba[i][BCOMP] = CHAN_TO_FLOAT(texel[2]);
+ rgba[i][ACOMP] = CHAN_TO_FLOAT(texel[3]);
+ }
+}
+
+
+/** Sample 2D texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_2d(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+
+ const GLboolean repeatNoBorderPOT = (tObj->WrapS == GL_REPEAT)
+ && (tObj->WrapT == GL_REPEAT)
+ && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
+ && (tImg->TexFormat->BaseFormat != GL_COLOR_INDEX)
+ && tImg->_IsPowerOfTwo;
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ const GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ if (repeatNoBorderPOT) {
+ switch (tImg->TexFormat->MesaFormat) {
+ case MESA_FORMAT_RGB:
+ opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart,
+ NULL, rgba + minStart);
+ break;
+ case MESA_FORMAT_RGBA:
+ opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart,
+ NULL, rgba + minStart);
+ break;
+ default:
+ sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
+ NULL, rgba + minStart );
+ }
+ }
+ else {
+ sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
+ NULL, rgba + minStart);
+ }
+ break;
+ case GL_LINEAR:
+ sample_linear_2d(ctx, tObj, m, texcoords + minStart,
+ NULL, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_2d_nearest_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (repeatNoBorderPOT)
+ sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
+ texcoords + minStart, lambda + minStart, rgba + minStart);
+ else
+ sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
+ return;
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ const GLuint m = magEnd - magStart;
+
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ if (repeatNoBorderPOT) {
+ switch (tImg->TexFormat->MesaFormat) {
+ case MESA_FORMAT_RGB:
+ opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart,
+ NULL, rgba + magStart);
+ break;
+ case MESA_FORMAT_RGBA:
+ opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart,
+ NULL, rgba + magStart);
+ break;
+ default:
+ sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
+ NULL, rgba + magStart );
+ }
+ }
+ else {
+ sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
+ NULL, rgba + magStart);
+ }
+ break;
+ case GL_LINEAR:
+ sample_linear_2d(ctx, tObj, m, texcoords + magStart,
+ NULL, rgba + magStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/* 3-D Texture Sampling Functions */
+/**********************************************************************/
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
+ */
+static INLINE void
+sample_3d_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2; /* without border, power of two */
+ const GLint height = img->Height2; /* without border, power of two */
+ const GLint depth = img->Depth2; /* without border, power of two */
+ GLint i, j, k;
+ (void) ctx;
+
+ i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
+ j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
+ k = nearest_texel_location(tObj->WrapR, img, depth, texcoord[2]);
+
+ if (i < 0 || i >= (GLint) img->Width ||
+ j < 0 || j >= (GLint) img->Height ||
+ k < 0 || k >= (GLint) img->Depth) {
+ /* Need this test for GL_CLAMP_TO_BORDER mode */
+ get_border_color(tObj, img, rgba);
+ }
+ else {
+ img->FetchTexelf(img, i, j, k, rgba);
+ }
+}
+
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
+ */
+static void
+sample_3d_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2;
+ const GLint height = img->Height2;
+ const GLint depth = img->Depth2;
+ GLint i0, j0, k0, i1, j1, k1;
+ GLbitfield useBorderColor = 0x0;
+ GLfloat a, b, c;
+ GLfloat t000[4], t010[4], t001[4], t011[4];
+ GLfloat t100[4], t110[4], t101[4], t111[4];
+
+ linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
+ linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
+ linear_texel_locations(tObj->WrapR, img, depth, texcoord[2], &k0, &k1, &c);
+
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ j0 += img->Border;
+ j1 += img->Border;
+ k0 += img->Border;
+ k1 += img->Border;
+ }
+ else {
+ /* check if sampling texture border color */
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
+ if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
+ if (k0 < 0 || k0 >= depth) useBorderColor |= K0BIT;
+ if (k1 < 0 || k1 >= depth) useBorderColor |= K1BIT;
+ }
+
+ /* Fetch texels */
+ if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
+ get_border_color(tObj, img, t000);
+ }
+ else {
+ img->FetchTexelf(img, i0, j0, k0, t000);
+ }
+ if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
+ get_border_color(tObj, img, t100);
+ }
+ else {
+ img->FetchTexelf(img, i1, j0, k0, t100);
+ }
+ if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
+ get_border_color(tObj, img, t010);
+ }
+ else {
+ img->FetchTexelf(img, i0, j1, k0, t010);
+ }
+ if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
+ get_border_color(tObj, img, t110);
+ }
+ else {
+ img->FetchTexelf(img, i1, j1, k0, t110);
+ }
+
+ if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
+ get_border_color(tObj, img, t001);
+ }
+ else {
+ img->FetchTexelf(img, i0, j0, k1, t001);
+ }
+ if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
+ get_border_color(tObj, img, t101);
+ }
+ else {
+ img->FetchTexelf(img, i1, j0, k1, t101);
+ }
+ if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
+ get_border_color(tObj, img, t011);
+ }
+ else {
+ img->FetchTexelf(img, i0, j1, k1, t011);
+ }
+ if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
+ get_border_color(tObj, img, t111);
+ }
+ else {
+ img->FetchTexelf(img, i1, j1, k1, t111);
+ }
+
+ /* trilinear interpolation of samples */
+ lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111);
+}
+
+
+static void
+sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4] )
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_3d_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_3d_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_3d_linear_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_3d_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample 3D texture, nearest filtering for both min/magnification */
+static void
+sample_nearest_3d(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 3D texture, linear filtering for both min/magnification */
+static void
+sample_linear_3d(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 3D texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_3d(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+ GLuint i;
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ for (i = minStart; i < minEnd; i++)
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = minStart; i < minEnd; i++)
+ sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
+ return;
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ for (i = magStart; i < magEnd; i++)
+ sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = magStart; i < magEnd; i++)
+ sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
+ return;
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* Texture Cube Map Sampling Functions */
+/**********************************************************************/
+
+/**
+ * Choose one of six sides of a texture cube map given the texture
+ * coord (rx,ry,rz). Return pointer to corresponding array of texture
+ * images.
+ */
+static const struct gl_texture_image **
+choose_cube_face(const struct gl_texture_object *texObj,
+ const GLfloat texcoord[4], GLfloat newCoord[4])
+{
+ /*
+ major axis
+ direction target sc tc ma
+ ---------- ------------------------------- --- --- ---
+ +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
+ -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
+ -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+ +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
+ -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
+ */
+ const GLfloat rx = texcoord[0];
+ const GLfloat ry = texcoord[1];
+ const GLfloat rz = texcoord[2];
+ const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
+ GLuint face;
+ GLfloat sc, tc, ma;
+
+ if (arx >= ary && arx >= arz) {
+ if (rx >= 0.0F) {
+ face = FACE_POS_X;
+ sc = -rz;
+ tc = -ry;
+ ma = arx;
+ }
+ else {
+ face = FACE_NEG_X;
+ sc = rz;
+ tc = -ry;
+ ma = arx;
+ }
+ }
+ else if (ary >= arx && ary >= arz) {
+ if (ry >= 0.0F) {
+ face = FACE_POS_Y;
+ sc = rx;
+ tc = rz;
+ ma = ary;
+ }
+ else {
+ face = FACE_NEG_Y;
+ sc = rx;
+ tc = -rz;
+ ma = ary;
+ }
+ }
+ else {
+ if (rz > 0.0F) {
+ face = FACE_POS_Z;
+ sc = rx;
+ tc = -ry;
+ ma = arz;
+ }
+ else {
+ face = FACE_NEG_Z;
+ sc = -rx;
+ tc = -ry;
+ ma = arz;
+ }
+ }
+
+ newCoord[0] = ( sc / ma + 1.0F ) * 0.5F;
+ newCoord[1] = ( tc / ma + 1.0F ) * 0.5F;
+ return (const struct gl_texture_image **) texObj->Image[face];
+}
+
+
+static void
+sample_nearest_cube(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint i;
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ images = choose_cube_face(tObj, texcoords[i], newCoord);
+ sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
+ newCoord, rgba[i]);
+ }
+}
+
+
+static void
+sample_linear_cube(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ images = choose_cube_face(tObj, texcoords[i], newCoord);
+ sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
+ newCoord, rgba[i]);
+ }
+}
+
+
+static void
+sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ GLint level;
+ images = choose_cube_face(tObj, texcoord[i], newCoord);
+
+ /* XXX we actually need to recompute lambda here based on the newCoords.
+ * But we would need the texcoords of adjacent fragments to compute that
+ * properly, and we don't have those here.
+ * For now, do an approximation: subtracting 1 from the chosen mipmap
+ * level seems to work in some test cases.
+ * The same adjustment is done in the next few functions.
+ */
+ level = nearest_mipmap_level(tObj, lambda[i]);
+ level = MAX2(level - 1, 0);
+
+ sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
+ }
+}
+
+
+static void
+sample_cube_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ level = MAX2(level - 1, 0); /* see comment above */
+ images = choose_cube_face(tObj, texcoord[i], newCoord);
+ sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
+ }
+}
+
+
+static void
+sample_cube_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ level = MAX2(level - 1, 0); /* see comment above */
+ images = choose_cube_face(tObj, texcoord[i], newCoord);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
+ newCoord, rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_nearest(ctx, tObj, images[level ], newCoord, t0);
+ sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_cube_linear_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ const struct gl_texture_image **images;
+ GLfloat newCoord[4];
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ level = MAX2(level - 1, 0); /* see comment above */
+ images = choose_cube_face(tObj, texcoord[i], newCoord);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
+ newCoord, rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4];
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_linear(ctx, tObj, images[level ], newCoord, t0);
+ sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample cube texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_cube(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ const GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ sample_nearest_cube(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR:
+ sample_linear_cube(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_cube_nearest_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_cube_linear_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_cube_nearest_mipmap_linear(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ sample_cube_linear_mipmap_linear(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ const GLuint m = magEnd - magStart;
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ sample_nearest_cube(ctx, tObj, m, texcoords + magStart,
+ lambda + magStart, rgba + magStart);
+ break;
+ case GL_LINEAR:
+ sample_linear_cube(ctx, tObj, m, texcoords + magStart,
+ lambda + magStart, rgba + magStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* Texture Rectangle Sampling Functions */
+/**********************************************************************/
+
+
+static void
+sample_nearest_rect(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ const struct gl_texture_image *img = tObj->Image[0][0];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ GLuint i;
+
+ (void) ctx;
+ (void) lambda;
+
+ ASSERT(tObj->WrapS == GL_CLAMP ||
+ tObj->WrapS == GL_CLAMP_TO_EDGE ||
+ tObj->WrapS == GL_CLAMP_TO_BORDER);
+ ASSERT(tObj->WrapT == GL_CLAMP ||
+ tObj->WrapT == GL_CLAMP_TO_EDGE ||
+ tObj->WrapT == GL_CLAMP_TO_BORDER);
+ ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX);
+
+ for (i = 0; i < n; i++) {
+ GLint row, col;
+ col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
+ row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
+ if (col < 0 || col >= width || row < 0 || row >= height)
+ get_border_color(tObj, img, rgba[i]);
+ else
+ img->FetchTexelf(img, col, row, 0, rgba[i]);
+ }
+}
+
+
+static void
+sample_linear_rect(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ const struct gl_texture_image *img = tObj->Image[0][0];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ GLuint i;
+
+ (void) ctx;
+ (void) lambda;
+
+ ASSERT(tObj->WrapS == GL_CLAMP ||
+ tObj->WrapS == GL_CLAMP_TO_EDGE ||
+ tObj->WrapS == GL_CLAMP_TO_BORDER);
+ ASSERT(tObj->WrapT == GL_CLAMP ||
+ tObj->WrapT == GL_CLAMP_TO_EDGE ||
+ tObj->WrapT == GL_CLAMP_TO_BORDER);
+ ASSERT(img->TexFormat->BaseFormat != GL_COLOR_INDEX);
+
+ for (i = 0; i < n; i++) {
+ GLint i0, j0, i1, j1;
+ GLfloat t00[4], t01[4], t10[4], t11[4];
+ GLfloat a, b;
+ GLbitfield useBorderColor = 0x0;
+
+ clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0], width,
+ &i0, &i1, &a);
+ clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1], height,
+ &j0, &j1, &b);
+
+ /* compute integer rows/columns */
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
+ if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
+
+ /* get four texel samples */
+ if (useBorderColor & (I0BIT | J0BIT))
+ get_border_color(tObj, img, t00);
+ else
+ img->FetchTexelf(img, i0, j0, 0, t00);
+
+ if (useBorderColor & (I1BIT | J0BIT))
+ get_border_color(tObj, img, t10);
+ else
+ img->FetchTexelf(img, i1, j0, 0, t10);
+
+ if (useBorderColor & (I0BIT | J1BIT))
+ get_border_color(tObj, img, t01);
+ else
+ img->FetchTexelf(img, i0, j1, 0, t01);
+
+ if (useBorderColor & (I1BIT | J1BIT))
+ get_border_color(tObj, img, t11);
+ else
+ img->FetchTexelf(img, i1, j1, 0, t11);
+
+ lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11);
+ }
+}
+
+
+/** Sample Rect texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_rect(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint minStart, minEnd, magStart, magEnd;
+
+ /* We only need lambda to decide between minification and magnification.
+ * There is no mipmapping with rectangular textures.
+ */
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ if (tObj->MinFilter == GL_NEAREST) {
+ sample_nearest_rect(ctx, tObj, minEnd - minStart,
+ texcoords + minStart, NULL, rgba + minStart);
+ }
+ else {
+ sample_linear_rect(ctx, tObj, minEnd - minStart,
+ texcoords + minStart, NULL, rgba + minStart);
+ }
+ }
+ if (magStart < magEnd) {
+ if (tObj->MagFilter == GL_NEAREST) {
+ sample_nearest_rect(ctx, tObj, magEnd - magStart,
+ texcoords + magStart, NULL, rgba + magStart);
+ }
+ else {
+ sample_linear_rect(ctx, tObj, magEnd - magStart,
+ texcoords + magStart, NULL, rgba + magStart);
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/* 2D Texture Array Sampling Functions */
+/**********************************************************************/
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
+ */
+static void
+sample_2d_array_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2; /* without border, power of two */
+ const GLint height = img->Height2; /* without border, power of two */
+ const GLint depth = img->Depth;
+ GLint i, j;
+ GLint array;
+ (void) ctx;
+
+ i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
+ j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
+ array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth);
+
+ if (i < 0 || i >= (GLint) img->Width ||
+ j < 0 || j >= (GLint) img->Height ||
+ array < 0 || array >= (GLint) img->Depth) {
+ /* Need this test for GL_CLAMP_TO_BORDER mode */
+ get_border_color(tObj, img, rgba);
+ }
+ else {
+ img->FetchTexelf(img, i, j, array, rgba);
+ }
+}
+
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
+ */
+static void
+sample_2d_array_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2;
+ const GLint height = img->Height2;
+ const GLint depth = img->Depth;
+ GLint i0, j0, i1, j1;
+ GLint array;
+ GLbitfield useBorderColor = 0x0;
+ GLfloat a, b;
+ GLfloat t00[4], t01[4], t10[4], t11[4];
+
+ linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
+ linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
+ array = clamp_rect_coord_nearest(tObj->WrapR, texcoord[2], depth);
+
+ if (array < 0 || array >= depth) {
+ COPY_4V(rgba, tObj->BorderColor);
+ }
+ else {
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ j0 += img->Border;
+ j1 += img->Border;
+ }
+ else {
+ /* check if sampling texture border color */
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ if (j0 < 0 || j0 >= height) useBorderColor |= J0BIT;
+ if (j1 < 0 || j1 >= height) useBorderColor |= J1BIT;
+ }
+
+ /* Fetch texels */
+ if (useBorderColor & (I0BIT | J0BIT)) {
+ get_border_color(tObj, img, t00);
+ }
+ else {
+ img->FetchTexelf(img, i0, j0, array, t00);
+ }
+ if (useBorderColor & (I1BIT | J0BIT)) {
+ get_border_color(tObj, img, t10);
+ }
+ else {
+ img->FetchTexelf(img, i1, j0, array, t10);
+ }
+ if (useBorderColor & (I0BIT | J1BIT)) {
+ get_border_color(tObj, img, t01);
+ }
+ else {
+ img->FetchTexelf(img, i0, j1, array, t01);
+ }
+ if (useBorderColor & (I1BIT | J1BIT)) {
+ get_border_color(tObj, img, t11);
+ }
+ else {
+ img->FetchTexelf(img, i1, j1, array, t11);
+ }
+
+ /* trilinear interpolation of samples */
+ lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
+ }
+}
+
+
+static void
+sample_2d_array_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
+ rgba[i]);
+ }
+}
+
+
+static void
+sample_2d_array_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][level],
+ texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_2d_array_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level ],
+ texcoord[i], t0);
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1],
+ texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_2d_array_linear_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][level ],
+ texcoord[i], t0);
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1],
+ texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample 2D Array texture, nearest filtering for both min/magnification */
+static void
+sample_nearest_2d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+
+/** Sample 2D Array texture, linear filtering for both min/magnification */
+static void
+sample_linear_2d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 2D Array texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_2d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+ GLuint i;
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ for (i = minStart; i < minEnd; i++)
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = minStart; i < minEnd; i++)
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_2d_array_linear_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_2d_array_nearest_mipmap_linear(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ sample_2d_array_linear_mipmap_linear(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture");
+ return;
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ for (i = magStart; i < magEnd; i++)
+ sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = magStart; i < magEnd; i++)
+ sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture");
+ return;
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/* 1D Texture Array Sampling Functions */
+/**********************************************************************/
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
+ */
+static void
+sample_1d_array_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2; /* without border, power of two */
+ const GLint height = img->Height;
+ GLint i;
+ GLint array;
+ (void) ctx;
+
+ i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
+ array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height);
+
+ if (i < 0 || i >= (GLint) img->Width ||
+ array < 0 || array >= (GLint) img->Height) {
+ /* Need this test for GL_CLAMP_TO_BORDER mode */
+ get_border_color(tObj, img, rgba);
+ }
+ else {
+ img->FetchTexelf(img, i, array, 0, rgba);
+ }
+}
+
+
+/**
+ * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
+ */
+static void
+sample_1d_array_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ const struct gl_texture_image *img,
+ const GLfloat texcoord[4],
+ GLfloat rgba[4])
+{
+ const GLint width = img->Width2;
+ const GLint height = img->Height;
+ GLint i0, i1;
+ GLint array;
+ GLbitfield useBorderColor = 0x0;
+ GLfloat a;
+ GLfloat t0[4], t1[4];
+
+ linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
+ array = clamp_rect_coord_nearest(tObj->WrapT, texcoord[1], height);
+
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ }
+ else {
+ /* check if sampling texture border color */
+ if (i0 < 0 || i0 >= width) useBorderColor |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderColor |= I1BIT;
+ }
+
+ if (array < 0 || array >= height) useBorderColor |= K0BIT;
+
+ /* Fetch texels */
+ if (useBorderColor & (I0BIT | K0BIT)) {
+ get_border_color(tObj, img, t0);
+ }
+ else {
+ img->FetchTexelf(img, i0, array, 0, t0);
+ }
+ if (useBorderColor & (I1BIT | K0BIT)) {
+ get_border_color(tObj, img, t1);
+ }
+ else {
+ img->FetchTexelf(img, i1, array, 0, t1);
+ }
+
+ /* bilinear interpolation of samples */
+ lerp_rgba(rgba, a, t0, t1);
+}
+
+
+static void
+sample_1d_array_nearest_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
+ rgba[i]);
+ }
+}
+
+
+static void
+sample_1d_array_linear_mipmap_nearest(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = nearest_mipmap_level(tObj, lambda[i]);
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][level],
+ texcoord[i], rgba[i]);
+ }
+}
+
+
+static void
+sample_1d_array_nearest_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+static void
+sample_1d_array_linear_mipmap_linear(GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLuint n, const GLfloat texcoord[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ ASSERT(lambda != NULL);
+ for (i = 0; i < n; i++) {
+ GLint level = linear_mipmap_level(tObj, lambda[i]);
+ if (level >= tObj->_MaxLevel) {
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
+ texcoord[i], rgba[i]);
+ }
+ else {
+ GLfloat t0[4], t1[4]; /* texels */
+ const GLfloat f = FRAC(lambda[i]);
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][level ], texcoord[i], t0);
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
+ lerp_rgba(rgba[i], f, t0, t1);
+ }
+ }
+}
+
+
+/** Sample 1D Array texture, nearest filtering for both min/magnification */
+static void
+sample_nearest_1d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 1D Array texture, linear filtering for both min/magnification */
+static void
+sample_linear_1d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4],
+ const GLfloat lambda[], GLfloat rgba[][4])
+{
+ GLuint i;
+ struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
+ }
+}
+
+
+/** Sample 1D Array texture, using lambda to choose between min/magnification */
+static void
+sample_lambda_1d_array(GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint minStart, minEnd; /* texels with minification */
+ GLuint magStart, magEnd; /* texels with magnification */
+ GLuint i;
+
+ ASSERT(lambda != NULL);
+ compute_min_mag_ranges(tObj, n, lambda,
+ &minStart, &minEnd, &magStart, &magEnd);
+
+ if (minStart < minEnd) {
+ /* do the minified texels */
+ GLuint m = minEnd - minStart;
+ switch (tObj->MinFilter) {
+ case GL_NEAREST:
+ for (i = minStart; i < minEnd; i++)
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = minStart; i < minEnd; i++)
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ sample_1d_array_linear_mipmap_nearest(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
+ lambda + minStart, rgba + minStart);
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ sample_1d_array_linear_mipmap_linear(ctx, tObj, m,
+ texcoords + minStart,
+ lambda + minStart,
+ rgba + minStart);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture");
+ return;
+ }
+ }
+
+ if (magStart < magEnd) {
+ /* do the magnified texels */
+ switch (tObj->MagFilter) {
+ case GL_NEAREST:
+ for (i = magStart; i < magEnd; i++)
+ sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ case GL_LINEAR:
+ for (i = magStart; i < magEnd; i++)
+ sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
+ texcoords[i], rgba[i]);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture");
+ return;
+ }
+ }
+}
+
+
+/**
+ * Compare texcoord against depth sample. Return 1.0 or the ambient value.
+ */
+static INLINE GLfloat
+shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample,
+ GLfloat ambient)
+{
+ switch (function) {
+ case GL_LEQUAL:
+ return (coord <= depthSample) ? 1.0F : ambient;
+ case GL_GEQUAL:
+ return (coord >= depthSample) ? 1.0F : ambient;
+ case GL_LESS:
+ return (coord < depthSample) ? 1.0F : ambient;
+ case GL_GREATER:
+ return (coord > depthSample) ? 1.0F : ambient;
+ case GL_EQUAL:
+ return (coord == depthSample) ? 1.0F : ambient;
+ case GL_NOTEQUAL:
+ return (coord != depthSample) ? 1.0F : ambient;
+ case GL_ALWAYS:
+ return 1.0F;
+ case GL_NEVER:
+ return ambient;
+ case GL_NONE:
+ return depthSample;
+ default:
+ _mesa_problem(NULL, "Bad compare func in shadow_compare");
+ return ambient;
+ }
+}
+
+
+/**
+ * Compare texcoord against four depth samples.
+ */
+static INLINE GLfloat
+shadow_compare4(GLenum function, GLfloat coord,
+ GLfloat depth00, GLfloat depth01,
+ GLfloat depth10, GLfloat depth11,
+ GLfloat ambient, GLfloat wi, GLfloat wj)
+{
+ const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F;
+ GLfloat luminance = 1.0F;
+
+ switch (function) {
+ case GL_LEQUAL:
+ if (depth00 <= coord) luminance -= d;
+ if (depth01 <= coord) luminance -= d;
+ if (depth10 <= coord) luminance -= d;
+ if (depth11 <= coord) luminance -= d;
+ return luminance;
+ case GL_GEQUAL:
+ if (depth00 >= coord) luminance -= d;
+ if (depth01 >= coord) luminance -= d;
+ if (depth10 >= coord) luminance -= d;
+ if (depth11 >= coord) luminance -= d;
+ return luminance;
+ case GL_LESS:
+ if (depth00 < coord) luminance -= d;
+ if (depth01 < coord) luminance -= d;
+ if (depth10 < coord) luminance -= d;
+ if (depth11 < coord) luminance -= d;
+ return luminance;
+ case GL_GREATER:
+ if (depth00 > coord) luminance -= d;
+ if (depth01 > coord) luminance -= d;
+ if (depth10 > coord) luminance -= d;
+ if (depth11 > coord) luminance -= d;
+ return luminance;
+ case GL_EQUAL:
+ if (depth00 == coord) luminance -= d;
+ if (depth01 == coord) luminance -= d;
+ if (depth10 == coord) luminance -= d;
+ if (depth11 == coord) luminance -= d;
+ return luminance;
+ case GL_NOTEQUAL:
+ if (depth00 != coord) luminance -= d;
+ if (depth01 != coord) luminance -= d;
+ if (depth10 != coord) luminance -= d;
+ if (depth11 != coord) luminance -= d;
+ return luminance;
+ case GL_ALWAYS:
+ return 0.0;
+ case GL_NEVER:
+ return ambient;
+ case GL_NONE:
+ /* ordinary bilinear filtering */
+ return lerp_2d(wi, wj, depth00, depth10, depth01, depth11);
+ default:
+ _mesa_problem(NULL, "Bad compare func in sample_depth_texture");
+ return 0.0F;
+ }
+}
+
+
+/**
+ * Sample a shadow/depth texture.
+ */
+static void
+sample_depth_texture( GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat texel[][4] )
+{
+ const GLint baseLevel = tObj->BaseLevel;
+ const struct gl_texture_image *img = tObj->Image[0][baseLevel];
+ const GLint width = img->Width;
+ const GLint height = img->Height;
+ const GLint depth = img->Depth;
+ const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT)
+ ? 3 : 2;
+ GLfloat ambient;
+ GLenum function;
+ GLfloat result;
+
+ (void) lambda;
+
+ ASSERT(img->TexFormat->BaseFormat == GL_DEPTH_COMPONENT ||
+ img->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT);
+
+ ASSERT(tObj->Target == GL_TEXTURE_1D ||
+ tObj->Target == GL_TEXTURE_2D ||
+ tObj->Target == GL_TEXTURE_RECTANGLE_NV ||
+ tObj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
+ tObj->Target == GL_TEXTURE_2D_ARRAY_EXT);
+
+ ambient = tObj->CompareFailValue;
+
+ /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
+
+ function = (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
+ tObj->CompareFunc : GL_NONE;
+
+ if (tObj->MagFilter == GL_NEAREST) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLfloat depthSample;
+ GLint col, row, slice;
+
+ nearest_texcoord(tObj, texcoords[i], &col, &row, &slice);
+
+ if (col >= 0 && row >= 0 && col < width && row < height &&
+ slice >= 0 && slice < depth) {
+ img->FetchTexelf(img, col, row, slice, &depthSample);
+ }
+ else {
+ depthSample = tObj->BorderColor[0];
+ }
+
+ result = shadow_compare(function, texcoords[i][compare_coord],
+ depthSample, ambient);
+
+ switch (tObj->DepthMode) {
+ case GL_LUMINANCE:
+ ASSIGN_4V(texel[i], result, result, result, 1.0F);
+ break;
+ case GL_INTENSITY:
+ ASSIGN_4V(texel[i], result, result, result, result);
+ break;
+ case GL_ALPHA:
+ ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth texture mode");
+ }
+ }
+ }
+ else {
+ GLuint i;
+ ASSERT(tObj->MagFilter == GL_LINEAR);
+ for (i = 0; i < n; i++) {
+ GLfloat depth00, depth01, depth10, depth11;
+ GLint i0, i1, j0, j1;
+ GLint slice;
+ GLfloat wi, wj;
+ GLuint useBorderTexel;
+
+ linear_texcoord(tObj, texcoords[i], &i0, &i1, &j0, &j1, &slice,
+ &wi, &wj);
+
+ useBorderTexel = 0;
+ if (img->Border) {
+ i0 += img->Border;
+ i1 += img->Border;
+ if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
+ j0 += img->Border;
+ j1 += img->Border;
+ }
+ }
+ else {
+ if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT;
+ if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT;
+ if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT;
+ if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT;
+ }
+
+ if (slice < 0 || slice >= (GLint) depth) {
+ depth00 = tObj->BorderColor[0];
+ depth01 = tObj->BorderColor[0];
+ depth10 = tObj->BorderColor[0];
+ depth11 = tObj->BorderColor[0];
+ }
+ else {
+ /* get four depth samples from the texture */
+ if (useBorderTexel & (I0BIT | J0BIT)) {
+ depth00 = tObj->BorderColor[0];
+ }
+ else {
+ img->FetchTexelf(img, i0, j0, slice, &depth00);
+ }
+ if (useBorderTexel & (I1BIT | J0BIT)) {
+ depth10 = tObj->BorderColor[0];
+ }
+ else {
+ img->FetchTexelf(img, i1, j0, slice, &depth10);
+ }
+
+ if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
+ if (useBorderTexel & (I0BIT | J1BIT)) {
+ depth01 = tObj->BorderColor[0];
+ }
+ else {
+ img->FetchTexelf(img, i0, j1, slice, &depth01);
+ }
+ if (useBorderTexel & (I1BIT | J1BIT)) {
+ depth11 = tObj->BorderColor[0];
+ }
+ else {
+ img->FetchTexelf(img, i1, j1, slice, &depth11);
+ }
+ }
+ else {
+ depth01 = depth00;
+ depth11 = depth10;
+ }
+ }
+
+ result = shadow_compare4(function, texcoords[i][compare_coord],
+ depth00, depth01, depth10, depth11,
+ ambient, wi, wj);
+
+ switch (tObj->DepthMode) {
+ case GL_LUMINANCE:
+ ASSIGN_4V(texel[i], result, result, result, 1.0F);
+ break;
+ case GL_INTENSITY:
+ ASSIGN_4V(texel[i], result, result, result, result);
+ break;
+ case GL_ALPHA:
+ ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad depth texture mode");
+ }
+
+ } /* for */
+ } /* if filter */
+}
+
+
+/**
+ * We use this function when a texture object is in an "incomplete" state.
+ * When a fragment program attempts to sample an incomplete texture we
+ * return black (see issue 23 in GL_ARB_fragment_program spec).
+ * Note: fragment programs don't observe the texture enable/disable flags.
+ */
+static void
+null_sample_func( GLcontext *ctx,
+ const struct gl_texture_object *tObj, GLuint n,
+ const GLfloat texcoords[][4], const GLfloat lambda[],
+ GLfloat rgba[][4])
+{
+ GLuint i;
+ (void) ctx;
+ (void) tObj;
+ (void) texcoords;
+ (void) lambda;
+ for (i = 0; i < n; i++) {
+ rgba[i][RCOMP] = 0;
+ rgba[i][GCOMP] = 0;
+ rgba[i][BCOMP] = 0;
+ rgba[i][ACOMP] = CHAN_MAX;
+ }
+}
+
+
+/**
+ * Choose the texture sampling function for the given texture object.
+ */
+texture_sample_func
+_swrast_choose_texture_sample_func( GLcontext *ctx,
+ const struct gl_texture_object *t )
+{
+ if (!t || !t->_Complete) {
+ return &null_sample_func;
+ }
+ else {
+ const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
+ const GLenum format = t->Image[0][t->BaseLevel]->TexFormat->BaseFormat;
+
+ switch (t->Target) {
+ case GL_TEXTURE_1D:
+ if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
+ return &sample_depth_texture;
+ }
+ else if (needLambda) {
+ return &sample_lambda_1d;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_1d;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_1d;
+ }
+ case GL_TEXTURE_2D:
+ if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
+ return &sample_depth_texture;
+ }
+ else if (needLambda) {
+ return &sample_lambda_2d;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_2d;
+ }
+ else {
+ /* check for a few optimized cases */
+ const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
+ ASSERT(t->MinFilter == GL_NEAREST);
+ if (t->WrapS == GL_REPEAT &&
+ t->WrapT == GL_REPEAT &&
+ img->_IsPowerOfTwo &&
+ img->Border == 0 &&
+ img->TexFormat->MesaFormat == MESA_FORMAT_RGB) {
+ return &opt_sample_rgb_2d;
+ }
+ else if (t->WrapS == GL_REPEAT &&
+ t->WrapT == GL_REPEAT &&
+ img->_IsPowerOfTwo &&
+ img->Border == 0 &&
+ img->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
+ return &opt_sample_rgba_2d;
+ }
+ else {
+ return &sample_nearest_2d;
+ }
+ }
+ case GL_TEXTURE_3D:
+ if (needLambda) {
+ return &sample_lambda_3d;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_3d;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_3d;
+ }
+ case GL_TEXTURE_CUBE_MAP:
+ if (needLambda) {
+ return &sample_lambda_cube;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_cube;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_cube;
+ }
+ case GL_TEXTURE_RECTANGLE_NV:
+ if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
+ return &sample_depth_texture;
+ }
+ else if (needLambda) {
+ return &sample_lambda_rect;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_rect;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_rect;
+ }
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ if (needLambda) {
+ return &sample_lambda_1d_array;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_1d_array;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_1d_array;
+ }
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ if (needLambda) {
+ return &sample_lambda_2d_array;
+ }
+ else if (t->MinFilter == GL_LINEAR) {
+ return &sample_linear_2d_array;
+ }
+ else {
+ ASSERT(t->MinFilter == GL_NEAREST);
+ return &sample_nearest_2d_array;
+ }
+ default:
+ _mesa_problem(ctx,
+ "invalid target in _swrast_choose_texture_sample_func");
+ return &null_sample_func;
+ }
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_texfilter.h b/mesalib/src/mesa/swrast/s_texfilter.h
new file mode 100644
index 000000000..2e265d685
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_texfilter.h
@@ -0,0 +1,38 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 S_TEXFILTER_H
+#define S_TEXFILTER_H
+
+
+#include "swrast.h"
+
+
+extern texture_sample_func
+_swrast_choose_texture_sample_func( GLcontext *ctx,
+ const struct gl_texture_object *tObj );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_texstore.c b/mesalib/src/mesa/swrast/s_texstore.c
new file mode 100644
index 000000000..f9ff9ad6a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_texstore.c
@@ -0,0 +1,601 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Brian Paul
+ */
+
+
+/*
+ * The functions in this file are mostly related to software texture fallbacks.
+ * This includes texture image transfer/packing and texel fetching.
+ * Hardware drivers will likely override most of this.
+ */
+
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/convolve.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/mipmap.h"
+#include "main/texformat.h"
+#include "main/teximage.h"
+#include "main/texstore.h"
+
+#include "s_context.h"
+#include "s_depth.h"
+#include "s_span.h"
+
+
+/**
+ * Read an RGBA image from the frame buffer.
+ * This is used by glCopyTex[Sub]Image[12]D().
+ * \param x window source x
+ * \param y window source y
+ * \param width image width
+ * \param height image height
+ * \param type datatype for returned GL_RGBA image
+ * \return pointer to image
+ */
+static GLvoid *
+read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
+ GLsizei width, GLsizei height )
+{
+ struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+ const GLint pixelSize = _mesa_bytes_per_pixel(GL_RGBA, type);
+ const GLint stride = width * pixelSize;
+ GLint row;
+ GLubyte *image, *dst;
+
+ image = (GLubyte *) _mesa_malloc(width * height * pixelSize);
+ if (!image)
+ return NULL;
+
+ swrast_render_start(ctx);
+
+ dst = image;
+ for (row = 0; row < height; row++) {
+ _swrast_read_rgba_span(ctx, rb, width, x, y + row, type, dst);
+ dst += stride;
+ }
+
+ swrast_render_finish(ctx);
+
+ return image;
+}
+
+
+/**
+ * As above, but read data from depth buffer. Returned as GLuints.
+ * \sa read_color_image
+ */
+static GLuint *
+read_depth_image( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ struct gl_renderbuffer *rb = ctx->ReadBuffer->_DepthBuffer;
+ GLuint *image, *dst;
+ GLint i;
+
+ image = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
+ if (!image)
+ return NULL;
+
+ swrast_render_start(ctx);
+
+ dst = image;
+ for (i = 0; i < height; i++) {
+ _swrast_read_depth_span_uint(ctx, rb, width, x, y + i, dst);
+ dst += width;
+ }
+
+ swrast_render_finish(ctx);
+
+ return image;
+}
+
+
+/**
+ * As above, but read data from depth+stencil buffers.
+ */
+static GLuint *
+read_depth_stencil_image(GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ struct gl_renderbuffer *depthRb = ctx->ReadBuffer->_DepthBuffer;
+ struct gl_renderbuffer *stencilRb = ctx->ReadBuffer->_StencilBuffer;
+ GLuint *image, *dst;
+ GLint i;
+
+ ASSERT(depthRb);
+ ASSERT(stencilRb);
+
+ image = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
+ if (!image)
+ return NULL;
+
+ swrast_render_start(ctx);
+
+ /* read from depth buffer */
+ dst = image;
+ if (depthRb->DataType == GL_UNSIGNED_INT) {
+ for (i = 0; i < height; i++) {
+ _swrast_get_row(ctx, depthRb, width, x, y + i, dst, sizeof(GLuint));
+ dst += width;
+ }
+ }
+ else {
+ GLushort z16[MAX_WIDTH];
+ ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
+ for (i = 0; i < height; i++) {
+ GLint j;
+ _swrast_get_row(ctx, depthRb, width, x, y + i, z16, sizeof(GLushort));
+ /* convert GLushorts to GLuints */
+ for (j = 0; j < width; j++) {
+ dst[j] = z16[j];
+ }
+ dst += width;
+ }
+ }
+
+ /* put depth values into bits 0xffffff00 */
+ if (ctx->ReadBuffer->Visual.depthBits == 24) {
+ GLint j;
+ for (j = 0; j < width * height; j++) {
+ image[j] <<= 8;
+ }
+ }
+ else if (ctx->ReadBuffer->Visual.depthBits == 16) {
+ GLint j;
+ for (j = 0; j < width * height; j++) {
+ image[j] = (image[j] << 16) | (image[j] & 0xff00);
+ }
+ }
+ else {
+ /* this handles arbitrary depthBits >= 12 */
+ const GLint rShift = ctx->ReadBuffer->Visual.depthBits;
+ const GLint lShift = 32 - rShift;
+ GLint j;
+ for (j = 0; j < width * height; j++) {
+ GLuint z = (image[j] << lShift);
+ image[j] = z | (z >> rShift);
+ }
+ }
+
+ /* read stencil values and interleave into image array */
+ dst = image;
+ for (i = 0; i < height; i++) {
+ GLstencil stencil[MAX_WIDTH];
+ GLint j;
+ ASSERT(8 * sizeof(GLstencil) == stencilRb->StencilBits);
+ _swrast_get_row(ctx, stencilRb, width, x, y + i,
+ stencil, sizeof(GLstencil));
+ for (j = 0; j < width; j++) {
+ dst[j] = (dst[j] & 0xffffff00) | (stencil[j] & 0xff);
+ }
+ dst += width;
+ }
+
+ swrast_render_finish(ctx);
+
+ return image;
+}
+
+
+static GLboolean
+is_depth_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean
+is_depth_stencil_format(GLenum format)
+{
+ switch (format) {
+ case GL_DEPTH_STENCIL_EXT:
+ case GL_DEPTH24_STENCIL8_EXT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/*
+ * Fallback for Driver.CopyTexImage1D().
+ */
+void
+_swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLint border )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ ASSERT(texObj);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(texImage);
+
+ ASSERT(ctx->Driver.TexImage1D);
+
+ if (is_depth_format(internalFormat)) {
+ /* read depth image from framebuffer */
+ GLuint *image = read_depth_image(ctx, x, y, width, 1);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ return;
+ }
+ /* call glTexImage1D to redefine the texture */
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else if (is_depth_stencil_format(internalFormat)) {
+ /* read depth/stencil image from framebuffer */
+ GLuint *image = read_depth_stencil_image(ctx, x, y, width, 1);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ return;
+ }
+ /* call glTexImage1D to redefine the texture */
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border,
+ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
+ image, &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else {
+ /* read RGBA image from framebuffer */
+ const GLenum format = GL_RGBA;
+ const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
+ GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+ return;
+ }
+ /* call glTexImage1D to redefine the texture */
+ ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ width, border, format, type, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+/**
+ * Fallback for Driver.CopyTexImage2D().
+ *
+ * We implement CopyTexImage by reading the image from the framebuffer
+ * then passing it to the ctx->Driver.TexImage2D() function.
+ *
+ * Device drivers should try to implement direct framebuffer->texture copies.
+ */
+void
+_swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ ASSERT(texObj);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(texImage);
+
+ ASSERT(ctx->Driver.TexImage2D);
+
+ if (is_depth_format(internalFormat)) {
+ /* read depth image from framebuffer */
+ GLuint *image = read_depth_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+ return;
+ }
+ /* call glTexImage2D to redefine the texture */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else if (is_depth_stencil_format(internalFormat)) {
+ GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+ return;
+ }
+ /* call glTexImage2D to redefine the texture */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border,
+ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
+ image, &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else {
+ /* read RGBA image from framebuffer */
+ const GLenum format = GL_RGBA;
+ const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
+ GLvoid *image = read_color_image(ctx, x, y, type, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+ return;
+ }
+ /* call glTexImage2D to redefine the texture */
+ ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ width, height, border, format, type, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+/*
+ * Fallback for Driver.CopyTexSubImage1D().
+ */
+void
+_swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ ASSERT(texObj);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(texImage);
+
+ ASSERT(ctx->Driver.TexImage1D);
+
+ if (texImage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ /* read depth image from framebuffer */
+ GLuint *image = read_depth_image(ctx, x, y, width, 1);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
+ return;
+ }
+
+ /* call glTexSubImage1D to redefine the texture */
+ ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else if (texImage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* read depth/stencil image from framebuffer */
+ GLuint *image = read_depth_stencil_image(ctx, x, y, width, 1);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
+ return;
+ }
+ /* call glTexImage1D to redefine the texture */
+ ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
+ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
+ image, &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else {
+ /* read RGBA image from framebuffer */
+ const GLenum format = GL_RGBA;
+ const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
+ GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
+ if (!image) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
+ return;
+ }
+ /* now call glTexSubImage1D to do the real work */
+ ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
+ format, type, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+/**
+ * Fallback for Driver.CopyTexSubImage2D().
+ *
+ * Read the image from the framebuffer then hand it
+ * off to ctx->Driver.TexSubImage2D().
+ */
+void
+_swrast_copy_texsubimage2d( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ struct gl_texture_unit *texUnit;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ ASSERT(texObj);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(texImage);
+
+ ASSERT(ctx->Driver.TexImage2D);
+
+ if (texImage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ /* read depth image from framebuffer */
+ GLuint *image = read_depth_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
+ return;
+ }
+ /* call glTexImage2D to redefine the texture */
+ ctx->Driver.TexSubImage2D(ctx, target, level,
+ xoffset, yoffset, width, height,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else if (texImage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* read depth/stencil image from framebuffer */
+ GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
+ return;
+ }
+ /* call glTexImage2D to redefine the texture */
+ ctx->Driver.TexSubImage2D(ctx, target, level,
+ xoffset, yoffset, width, height,
+ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
+ image, &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else {
+ /* read RGBA image from framebuffer */
+ const GLenum format = GL_RGBA;
+ const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
+ GLvoid *image = read_color_image(ctx, x, y, type, width, height);
+ if (!image) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
+ return;
+ }
+ /* now call glTexSubImage2D to do the real work */
+ ctx->Driver.TexSubImage2D(ctx, target, level,
+ xoffset, yoffset, width, height,
+ format, type, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
+
+
+/*
+ * Fallback for Driver.CopyTexSubImage3D().
+ */
+void
+_swrast_copy_texsubimage3d( 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;
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ texObj = _mesa_select_tex_object(ctx, texUnit, target);
+ ASSERT(texObj);
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ ASSERT(texImage);
+
+ ASSERT(ctx->Driver.TexImage3D);
+
+ if (texImage->_BaseFormat == GL_DEPTH_COMPONENT) {
+ /* read depth image from framebuffer */
+ GLuint *image = read_depth_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
+ return;
+ }
+ /* call glTexImage3D to redefine the texture */
+ ctx->Driver.TexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset, width, height, 1,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else if (texImage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
+ /* read depth/stencil image from framebuffer */
+ GLuint *image = read_depth_stencil_image(ctx, x, y, width, height);
+ if (!image) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
+ return;
+ }
+ /* call glTexImage3D to redefine the texture */
+ ctx->Driver.TexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset, width, height, 1,
+ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT,
+ image, &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+ else {
+ /* read RGBA image from framebuffer */
+ const GLenum format = GL_RGBA;
+ const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
+ GLvoid *image = read_color_image(ctx, x, y, type, width, height);
+ if (!image) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
+ return;
+ }
+ /* now call glTexSubImage3D to do the real work */
+ ctx->Driver.TexSubImage3D(ctx, target, level,
+ xoffset, yoffset, zoffset, width, height, 1,
+ format, type, image,
+ &ctx->DefaultPacking, texObj, texImage);
+ _mesa_free(image);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ ctx->Driver.GenerateMipmap(ctx, target, texObj);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c
new file mode 100644
index 000000000..1ab0e19f9
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_triangle.c
@@ -0,0 +1,1150 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.3
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * When the device driver doesn't implement triangle rasterization it
+ * can hook in _swrast_Triangle, which eventually calls one of these
+ * functions to draw triangles.
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/texformat.h"
+#include "shader/prog_instruction.h"
+
+#include "s_aatriangle.h"
+#include "s_context.h"
+#include "s_feedback.h"
+#include "s_span.h"
+#include "s_triangle.h"
+
+
+/**
+ * Test if a triangle should be culled. Used for feedback and selection mode.
+ * \return GL_TRUE if the triangle is to be culled, GL_FALSE otherwise.
+ */
+GLboolean
+_swrast_culltriangle( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2 )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GLfloat ex = v1->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
+ GLfloat ey = v1->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat fx = v2->attrib[FRAG_ATTRIB_WPOS][0] - v0->attrib[FRAG_ATTRIB_WPOS][0];
+ GLfloat fy = v2->attrib[FRAG_ATTRIB_WPOS][1] - v0->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat c = ex*fy-ey*fx;
+
+ if (c * swrast->_BackfaceSign * swrast->_BackfaceCullSign <= 0.0F)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+
+/*
+ * Render a smooth or flat-shaded color index triangle.
+ */
+#define NAME ci_triangle
+#define INTERP_Z 1
+#define INTERP_ATTRIBS 1 /* just for fog */
+#define INTERP_INDEX 1
+#define RENDER_SPAN( span ) _swrast_write_index_span(ctx, &span);
+#include "s_tritemp.h"
+
+
+
+/*
+ * Render a flat-shaded RGBA triangle.
+ */
+#define NAME flat_rgba_triangle
+#define INTERP_Z 1
+#define SETUP_CODE \
+ ASSERT(ctx->Texture._EnabledCoordUnits == 0);\
+ ASSERT(ctx->Light.ShadeModel==GL_FLAT); \
+ span.interpMask |= SPAN_RGBA; \
+ span.red = ChanToFixed(v2->color[0]); \
+ span.green = ChanToFixed(v2->color[1]); \
+ span.blue = ChanToFixed(v2->color[2]); \
+ span.alpha = ChanToFixed(v2->color[3]); \
+ span.redStep = 0; \
+ span.greenStep = 0; \
+ span.blueStep = 0; \
+ span.alphaStep = 0;
+#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span);
+#include "s_tritemp.h"
+
+
+
+/*
+ * Render a smooth-shaded RGBA triangle.
+ */
+#define NAME smooth_rgba_triangle
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define SETUP_CODE \
+ { \
+ /* texturing must be off */ \
+ ASSERT(ctx->Texture._EnabledCoordUnits == 0); \
+ ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); \
+ }
+#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span);
+#include "s_tritemp.h"
+
+
+
+/*
+ * Render an RGB, GL_DECAL, textured triangle.
+ * Interpolate S,T only w/out mipmapping or perspective correction.
+ *
+ * No fog. No depth testing.
+ */
+#define NAME simple_textured_triangle
+#define INTERP_INT_TEX 1
+#define S_SCALE twidth
+#define T_SCALE theight
+
+#define SETUP_CODE \
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
+ const GLint b = obj->BaseLevel; \
+ const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
+ const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
+ const GLint twidth_log2 = obj->Image[0][b]->WidthLog2; \
+ const GLchan *texture = (const GLchan *) obj->Image[0][b]->Data; \
+ const GLint smask = obj->Image[0][b]->Width - 1; \
+ const GLint tmask = obj->Image[0][b]->Height - 1; \
+ if (!rb || !texture) { \
+ return; \
+ }
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLchan rgb[MAX_WIDTH][3]; \
+ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
+ span.intTex[1] -= FIXED_HALF; \
+ for (i = 0; i < span.end; i++) { \
+ GLint s = FixedToInt(span.intTex[0]) & smask; \
+ GLint t = FixedToInt(span.intTex[1]) & tmask; \
+ GLint pos = (t << twidth_log2) + s; \
+ pos = pos + pos + pos; /* multiply by 3 */ \
+ rgb[i][RCOMP] = texture[pos]; \
+ rgb[i][GCOMP] = texture[pos+1]; \
+ rgb[i][BCOMP] = texture[pos+2]; \
+ span.intTex[0] += span.intTexStep[0]; \
+ span.intTex[1] += span.intTexStep[1]; \
+ } \
+ rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, NULL);
+
+#include "s_tritemp.h"
+
+
+
+/*
+ * Render an RGB, GL_DECAL, textured triangle.
+ * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
+ * perspective correction.
+ * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE)
+ *
+ * No fog.
+ */
+#define NAME simple_z_textured_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_INT_TEX 1
+#define S_SCALE twidth
+#define T_SCALE theight
+
+#define SETUP_CODE \
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
+ const GLint b = obj->BaseLevel; \
+ const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
+ const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
+ const GLint twidth_log2 = obj->Image[0][b]->WidthLog2; \
+ const GLchan *texture = (const GLchan *) obj->Image[0][b]->Data; \
+ const GLint smask = obj->Image[0][b]->Width - 1; \
+ const GLint tmask = obj->Image[0][b]->Height - 1; \
+ if (!rb || !texture) { \
+ return; \
+ }
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLchan rgb[MAX_WIDTH][3]; \
+ span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
+ span.intTex[1] -= FIXED_HALF; \
+ for (i = 0; i < span.end; i++) { \
+ const GLuint z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ GLint s = FixedToInt(span.intTex[0]) & smask; \
+ GLint t = FixedToInt(span.intTex[1]) & tmask; \
+ GLint pos = (t << twidth_log2) + s; \
+ pos = pos + pos + pos; /* multiply by 3 */ \
+ rgb[i][RCOMP] = texture[pos]; \
+ rgb[i][GCOMP] = texture[pos+1]; \
+ rgb[i][BCOMP] = texture[pos+2]; \
+ zRow[i] = z; \
+ span.array->mask[i] = 1; \
+ } \
+ else { \
+ span.array->mask[i] = 0; \
+ } \
+ span.intTex[0] += span.intTexStep[0]; \
+ span.intTex[1] += span.intTexStep[1]; \
+ span.z += span.zStep; \
+ } \
+ rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, span.array->mask);
+
+#include "s_tritemp.h"
+
+
+#if CHAN_TYPE != GL_FLOAT
+
+struct affine_info
+{
+ GLenum filter;
+ GLenum format;
+ GLenum envmode;
+ GLint smask, tmask;
+ GLint twidth_log2;
+ const GLchan *texture;
+ GLfixed er, eg, eb, ea;
+ GLint tbytesline, tsize;
+};
+
+
+static INLINE GLint
+ilerp(GLint t, GLint a, GLint b)
+{
+ return a + ((t * (b - a)) >> FIXED_SHIFT);
+}
+
+static INLINE GLint
+ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11)
+{
+ const GLint temp0 = ilerp(ia, v00, v10);
+ const GLint temp1 = ilerp(ia, v01, v11);
+ return ilerp(ib, temp0, temp1);
+}
+
+
+/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
+ * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
+ * texture env modes.
+ */
+static INLINE void
+affine_span(GLcontext *ctx, SWspan *span,
+ struct affine_info *info)
+{
+ GLchan sample[4]; /* the filtered texture sample */
+ const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
+
+ /* Instead of defining a function for each mode, a test is done
+ * between the outer and inner loops. This is to reduce code size
+ * and complexity. Observe that an optimizing compiler kills
+ * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
+ */
+
+#define NEAREST_RGB \
+ sample[RCOMP] = tex00[RCOMP]; \
+ sample[GCOMP] = tex00[GCOMP]; \
+ sample[BCOMP] = tex00[BCOMP]; \
+ sample[ACOMP] = CHAN_MAX
+
+#define LINEAR_RGB \
+ sample[RCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\
+ sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
+ sample[BCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
+ sample[ACOMP] = CHAN_MAX;
+
+#define NEAREST_RGBA COPY_CHAN4(sample, tex00)
+
+#define LINEAR_RGBA \
+ sample[RCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\
+ sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
+ sample[BCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
+ sample[ACOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3])
+
+#define MODULATE \
+ dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
+ dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
+ dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
+ dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
+
+#define DECAL \
+ dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \
+ ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \
+ >> (FIXED_SHIFT + 8); \
+ dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \
+ ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \
+ >> (FIXED_SHIFT + 8); \
+ dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \
+ ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \
+ >> (FIXED_SHIFT + 8); \
+ dest[ACOMP] = FixedToInt(span->alpha)
+
+#define BLEND \
+ dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \
+ + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \
+ dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \
+ + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \
+ dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \
+ + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \
+ dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
+
+#define REPLACE COPY_CHAN4(dest, sample)
+
+#define ADD \
+ { \
+ GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \
+ GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \
+ GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \
+ dest[RCOMP] = MIN2(rSum, CHAN_MAX); \
+ dest[GCOMP] = MIN2(gSum, CHAN_MAX); \
+ dest[BCOMP] = MIN2(bSum, CHAN_MAX); \
+ dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
+ }
+
+/* shortcuts */
+
+#define NEAREST_RGB_REPLACE \
+ NEAREST_RGB; \
+ dest[0] = sample[0]; \
+ dest[1] = sample[1]; \
+ dest[2] = sample[2]; \
+ dest[3] = FixedToInt(span->alpha);
+
+#define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00)
+
+#define SPAN_NEAREST(DO_TEX, COMPS) \
+ for (i = 0; i < span->end; i++) { \
+ /* Isn't it necessary to use FixedFloor below?? */ \
+ GLint s = FixedToInt(span->intTex[0]) & info->smask; \
+ GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
+ GLint pos = (t << info->twidth_log2) + s; \
+ const GLchan *tex00 = info->texture + COMPS * pos; \
+ DO_TEX; \
+ span->red += span->redStep; \
+ span->green += span->greenStep; \
+ span->blue += span->blueStep; \
+ span->alpha += span->alphaStep; \
+ span->intTex[0] += span->intTexStep[0]; \
+ span->intTex[1] += span->intTexStep[1]; \
+ dest += 4; \
+ }
+
+#define SPAN_LINEAR(DO_TEX, COMPS) \
+ for (i = 0; i < span->end; i++) { \
+ /* Isn't it necessary to use FixedFloor below?? */ \
+ const GLint s = FixedToInt(span->intTex[0]) & info->smask; \
+ const GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
+ const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \
+ const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \
+ const GLint pos = (t << info->twidth_log2) + s; \
+ const GLchan *tex00 = info->texture + COMPS * pos; \
+ const GLchan *tex10 = tex00 + info->tbytesline; \
+ const GLchan *tex01 = tex00 + COMPS; \
+ const GLchan *tex11 = tex10 + COMPS; \
+ if (t == info->tmask) { \
+ tex10 -= info->tsize; \
+ tex11 -= info->tsize; \
+ } \
+ if (s == info->smask) { \
+ tex01 -= info->tbytesline; \
+ tex11 -= info->tbytesline; \
+ } \
+ DO_TEX; \
+ span->red += span->redStep; \
+ span->green += span->greenStep; \
+ span->blue += span->blueStep; \
+ span->alpha += span->alphaStep; \
+ span->intTex[0] += span->intTexStep[0]; \
+ span->intTex[1] += span->intTexStep[1]; \
+ dest += 4; \
+ }
+
+
+ GLuint i;
+ GLchan *dest = span->array->rgba[0];
+
+ /* Disable tex units so they're not re-applied in swrast_write_rgba_span */
+ ctx->Texture._EnabledCoordUnits = 0x0;
+
+ span->intTex[0] -= FIXED_HALF;
+ span->intTex[1] -= FIXED_HALF;
+ switch (info->filter) {
+ case GL_NEAREST:
+ switch (info->format) {
+ case GL_RGB:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
+ break;
+ case GL_DECAL:
+ case GL_REPLACE:
+ SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
+ break;
+ case GL_BLEND:
+ SPAN_NEAREST(NEAREST_RGB;BLEND,3);
+ break;
+ case GL_ADD:
+ SPAN_NEAREST(NEAREST_RGB;ADD,3);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR");
+ return;
+ }
+ break;
+ case GL_RGBA:
+ switch(info->envmode) {
+ case GL_MODULATE:
+ SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
+ break;
+ case GL_DECAL:
+ SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
+ break;
+ case GL_BLEND:
+ SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
+ break;
+ case GL_ADD:
+ SPAN_NEAREST(NEAREST_RGBA;ADD,4);
+ break;
+ case GL_REPLACE:
+ SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ }
+ break;
+
+ case GL_LINEAR:
+ span->intTex[0] -= FIXED_HALF;
+ span->intTex[1] -= FIXED_HALF;
+ switch (info->format) {
+ case GL_RGB:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
+ break;
+ case GL_DECAL:
+ case GL_REPLACE:
+ SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
+ break;
+ case GL_BLEND:
+ SPAN_LINEAR(LINEAR_RGB;BLEND,3);
+ break;
+ case GL_ADD:
+ SPAN_LINEAR(LINEAR_RGB;ADD,3);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ case GL_RGBA:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
+ break;
+ case GL_DECAL:
+ SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
+ break;
+ case GL_BLEND:
+ SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
+ break;
+ case GL_ADD:
+ SPAN_LINEAR(LINEAR_RGBA;ADD,4);
+ break;
+ case GL_REPLACE:
+ SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ }
+ break;
+ }
+ span->interpMask &= ~SPAN_RGBA;
+ ASSERT(span->arrayMask & SPAN_RGBA);
+
+ _swrast_write_rgba_span(ctx, span);
+
+ /* re-enable texture units */
+ ctx->Texture._EnabledCoordUnits = texEnableSave;
+
+#undef SPAN_NEAREST
+#undef SPAN_LINEAR
+}
+
+
+
+/*
+ * Render an RGB/RGBA textured triangle without perspective correction.
+ */
+#define NAME affine_textured_triangle
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_INT_TEX 1
+#define S_SCALE twidth
+#define T_SCALE theight
+
+#define SETUP_CODE \
+ struct affine_info info; \
+ struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
+ const GLint b = obj->BaseLevel; \
+ const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width; \
+ const GLfloat theight = (GLfloat) obj->Image[0][b]->Height; \
+ info.texture = (const GLchan *) obj->Image[0][b]->Data; \
+ info.twidth_log2 = obj->Image[0][b]->WidthLog2; \
+ info.smask = obj->Image[0][b]->Width - 1; \
+ info.tmask = obj->Image[0][b]->Height - 1; \
+ info.format = obj->Image[0][b]->_BaseFormat; \
+ info.filter = obj->MinFilter; \
+ info.envmode = unit->EnvMode; \
+ span.arrayMask |= SPAN_RGBA; \
+ \
+ if (info.envmode == GL_BLEND) { \
+ /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
+ info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \
+ info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \
+ info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \
+ info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \
+ } \
+ if (!info.texture) { \
+ /* this shouldn't happen */ \
+ return; \
+ } \
+ \
+ switch (info.format) { \
+ case GL_ALPHA: \
+ case GL_LUMINANCE: \
+ case GL_INTENSITY: \
+ info.tbytesline = obj->Image[0][b]->Width; \
+ break; \
+ case GL_LUMINANCE_ALPHA: \
+ info.tbytesline = obj->Image[0][b]->Width * 2; \
+ break; \
+ case GL_RGB: \
+ info.tbytesline = obj->Image[0][b]->Width * 3; \
+ break; \
+ case GL_RGBA: \
+ info.tbytesline = obj->Image[0][b]->Width * 4; \
+ break; \
+ default: \
+ _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
+ return; \
+ } \
+ info.tsize = obj->Image[0][b]->Height * info.tbytesline;
+
+#define RENDER_SPAN( span ) affine_span(ctx, &span, &info);
+
+#include "s_tritemp.h"
+
+
+
+struct persp_info
+{
+ GLenum filter;
+ GLenum format;
+ GLenum envmode;
+ GLint smask, tmask;
+ GLint twidth_log2;
+ const GLchan *texture;
+ GLfixed er, eg, eb, ea; /* texture env color */
+ GLint tbytesline, tsize;
+};
+
+
+static INLINE void
+fast_persp_span(GLcontext *ctx, SWspan *span,
+ struct persp_info *info)
+{
+ GLchan sample[4]; /* the filtered texture sample */
+
+ /* Instead of defining a function for each mode, a test is done
+ * between the outer and inner loops. This is to reduce code size
+ * and complexity. Observe that an optimizing compiler kills
+ * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
+ */
+#define SPAN_NEAREST(DO_TEX,COMP) \
+ for (i = 0; i < span->end; i++) { \
+ GLdouble invQ = tex_coord[2] ? \
+ (1.0 / tex_coord[2]) : 1.0; \
+ GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
+ GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
+ GLint s = IFLOOR(s_tmp) & info->smask; \
+ GLint t = IFLOOR(t_tmp) & info->tmask; \
+ GLint pos = (t << info->twidth_log2) + s; \
+ const GLchan *tex00 = info->texture + COMP * pos; \
+ DO_TEX; \
+ span->red += span->redStep; \
+ span->green += span->greenStep; \
+ span->blue += span->blueStep; \
+ span->alpha += span->alphaStep; \
+ tex_coord[0] += tex_step[0]; \
+ tex_coord[1] += tex_step[1]; \
+ tex_coord[2] += tex_step[2]; \
+ dest += 4; \
+ }
+
+#define SPAN_LINEAR(DO_TEX,COMP) \
+ for (i = 0; i < span->end; i++) { \
+ GLdouble invQ = tex_coord[2] ? \
+ (1.0 / tex_coord[2]) : 1.0; \
+ const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
+ const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
+ const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \
+ const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \
+ const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \
+ const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \
+ const GLfixed sf = s_fix & FIXED_FRAC_MASK; \
+ const GLfixed tf = t_fix & FIXED_FRAC_MASK; \
+ const GLint pos = (t << info->twidth_log2) + s; \
+ const GLchan *tex00 = info->texture + COMP * pos; \
+ const GLchan *tex10 = tex00 + info->tbytesline; \
+ const GLchan *tex01 = tex00 + COMP; \
+ const GLchan *tex11 = tex10 + COMP; \
+ if (t == info->tmask) { \
+ tex10 -= info->tsize; \
+ tex11 -= info->tsize; \
+ } \
+ if (s == info->smask) { \
+ tex01 -= info->tbytesline; \
+ tex11 -= info->tbytesline; \
+ } \
+ DO_TEX; \
+ span->red += span->redStep; \
+ span->green += span->greenStep; \
+ span->blue += span->blueStep; \
+ span->alpha += span->alphaStep; \
+ tex_coord[0] += tex_step[0]; \
+ tex_coord[1] += tex_step[1]; \
+ tex_coord[2] += tex_step[2]; \
+ dest += 4; \
+ }
+
+ GLuint i;
+ GLfloat tex_coord[3], tex_step[3];
+ GLchan *dest = span->array->rgba[0];
+
+ const GLuint texEnableSave = ctx->Texture._EnabledCoordUnits;
+ ctx->Texture._EnabledCoordUnits = 0;
+
+ tex_coord[0] = span->attrStart[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
+ tex_step[0] = span->attrStepX[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
+ tex_coord[1] = span->attrStart[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
+ tex_step[1] = span->attrStepX[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
+ /* span->attrStart[FRAG_ATTRIB_TEX0][2] only if 3D-texturing, here only 2D */
+ tex_coord[2] = span->attrStart[FRAG_ATTRIB_TEX0][3];
+ tex_step[2] = span->attrStepX[FRAG_ATTRIB_TEX0][3];
+
+ switch (info->filter) {
+ case GL_NEAREST:
+ switch (info->format) {
+ case GL_RGB:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
+ break;
+ case GL_DECAL:
+ case GL_REPLACE:
+ SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
+ break;
+ case GL_BLEND:
+ SPAN_NEAREST(NEAREST_RGB;BLEND,3);
+ break;
+ case GL_ADD:
+ SPAN_NEAREST(NEAREST_RGB;ADD,3);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ case GL_RGBA:
+ switch(info->envmode) {
+ case GL_MODULATE:
+ SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
+ break;
+ case GL_DECAL:
+ SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
+ break;
+ case GL_BLEND:
+ SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
+ break;
+ case GL_ADD:
+ SPAN_NEAREST(NEAREST_RGBA;ADD,4);
+ break;
+ case GL_REPLACE:
+ SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ }
+ break;
+
+ case GL_LINEAR:
+ switch (info->format) {
+ case GL_RGB:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
+ break;
+ case GL_DECAL:
+ case GL_REPLACE:
+ SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
+ break;
+ case GL_BLEND:
+ SPAN_LINEAR(LINEAR_RGB;BLEND,3);
+ break;
+ case GL_ADD:
+ SPAN_LINEAR(LINEAR_RGB;ADD,3);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ case GL_RGBA:
+ switch (info->envmode) {
+ case GL_MODULATE:
+ SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
+ break;
+ case GL_DECAL:
+ SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
+ break;
+ case GL_BLEND:
+ SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
+ break;
+ case GL_ADD:
+ SPAN_LINEAR(LINEAR_RGBA;ADD,4);
+ break;
+ case GL_REPLACE:
+ SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
+ break;
+ default:
+ _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR");
+ return;
+ }
+ break;
+ }
+ break;
+ }
+
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ _swrast_write_rgba_span(ctx, span);
+
+#undef SPAN_NEAREST
+#undef SPAN_LINEAR
+
+ /* restore state */
+ ctx->Texture._EnabledCoordUnits = texEnableSave;
+}
+
+
+/*
+ * Render an perspective corrected RGB/RGBA textured triangle.
+ * The Q (aka V in Mesa) coordinate must be zero such that the divide
+ * by interpolated Q/W comes out right.
+ *
+ */
+#define NAME persp_textured_triangle
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_ATTRIBS 1
+
+#define SETUP_CODE \
+ struct persp_info info; \
+ const struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
+ struct gl_texture_object *obj = \
+ ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; \
+ const GLint b = obj->BaseLevel; \
+ info.texture = (const GLchan *) obj->Image[0][b]->Data; \
+ info.twidth_log2 = obj->Image[0][b]->WidthLog2; \
+ info.smask = obj->Image[0][b]->Width - 1; \
+ info.tmask = obj->Image[0][b]->Height - 1; \
+ info.format = obj->Image[0][b]->_BaseFormat; \
+ info.filter = obj->MinFilter; \
+ info.envmode = unit->EnvMode; \
+ \
+ if (info.envmode == GL_BLEND) { \
+ /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
+ info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF); \
+ info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF); \
+ info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF); \
+ info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF); \
+ } \
+ if (!info.texture) { \
+ /* this shouldn't happen */ \
+ return; \
+ } \
+ \
+ switch (info.format) { \
+ case GL_ALPHA: \
+ case GL_LUMINANCE: \
+ case GL_INTENSITY: \
+ info.tbytesline = obj->Image[0][b]->Width; \
+ break; \
+ case GL_LUMINANCE_ALPHA: \
+ info.tbytesline = obj->Image[0][b]->Width * 2; \
+ break; \
+ case GL_RGB: \
+ info.tbytesline = obj->Image[0][b]->Width * 3; \
+ break; \
+ case GL_RGBA: \
+ info.tbytesline = obj->Image[0][b]->Width * 4; \
+ break; \
+ default: \
+ _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
+ return; \
+ } \
+ info.tsize = obj->Image[0][b]->Height * info.tbytesline;
+
+#define RENDER_SPAN( span ) \
+ span.interpMask &= ~SPAN_RGBA; \
+ span.arrayMask |= SPAN_RGBA; \
+ fast_persp_span(ctx, &span, &info);
+
+#include "s_tritemp.h"
+
+#endif /*CHAN_TYPE != GL_FLOAT*/
+
+
+
+/*
+ * Render an RGBA triangle with arbitrary attributes.
+ */
+#define NAME general_triangle
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_ATTRIBS 1
+#define RENDER_SPAN( span ) _swrast_write_rgba_span(ctx, &span);
+#include "s_tritemp.h"
+
+
+
+
+/*
+ * Special tri function for occlusion testing
+ */
+#define NAME occlusion_zless_triangle
+#define INTERP_Z 1
+#define SETUP_CODE \
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; \
+ struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; \
+ ASSERT(ctx->Depth.Test); \
+ ASSERT(!ctx->Depth.Mask); \
+ ASSERT(ctx->Depth.Func == GL_LESS); \
+ if (!q) { \
+ return; \
+ }
+#define RENDER_SPAN( span ) \
+ if (rb->DepthBits <= 16) { \
+ GLuint i; \
+ const GLushort *zRow = (const GLushort *) \
+ rb->GetPointer(ctx, rb, span.x, span.y); \
+ for (i = 0; i < span.end; i++) { \
+ GLuint z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ q->Result++; \
+ } \
+ span.z += span.zStep; \
+ } \
+ } \
+ else { \
+ GLuint i; \
+ const GLuint *zRow = (const GLuint *) \
+ rb->GetPointer(ctx, rb, span.x, span.y); \
+ for (i = 0; i < span.end; i++) { \
+ if ((GLuint)span.z < zRow[i]) { \
+ q->Result++; \
+ } \
+ span.z += span.zStep; \
+ } \
+ }
+#include "s_tritemp.h"
+
+
+
+static void
+nodraw_triangle( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2 )
+{
+ (void) (ctx && v0 && v1 && v2);
+}
+
+
+/*
+ * This is used when separate specular color is enabled, but not
+ * texturing. We add the specular color to the primary color,
+ * draw the triangle, then restore the original primary color.
+ * Inefficient, but seldom needed.
+ */
+void
+_swrast_add_spec_terms_triangle(GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2)
+{
+ SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
+ SWvertex *ncv1 = (SWvertex *)v1;
+ SWvertex *ncv2 = (SWvertex *)v2;
+ GLfloat rSum, gSum, bSum;
+ GLchan cSave[3][4];
+
+ /* save original colors */
+ COPY_CHAN4( cSave[0], ncv0->color );
+ COPY_CHAN4( cSave[1], ncv1->color );
+ COPY_CHAN4( cSave[2], ncv2->color );
+ /* sum v0 */
+ rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
+ /* sum v1 */
+ rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
+ /* sum v2 */
+ rSum = CHAN_TO_FLOAT(ncv2->color[0]) + ncv2->attrib[FRAG_ATTRIB_COL1][0];
+ gSum = CHAN_TO_FLOAT(ncv2->color[1]) + ncv2->attrib[FRAG_ATTRIB_COL1][1];
+ bSum = CHAN_TO_FLOAT(ncv2->color[2]) + ncv2->attrib[FRAG_ATTRIB_COL1][2];
+ UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[0], rSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[1], gSum);
+ UNCLAMPED_FLOAT_TO_CHAN(ncv2->color[2], bSum);
+ /* draw */
+ SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
+ /* restore original colors */
+ COPY_CHAN4( ncv0->color, cSave[0] );
+ COPY_CHAN4( ncv1->color, cSave[1] );
+ COPY_CHAN4( ncv2->color, cSave[2] );
+}
+
+
+
+#ifdef DEBUG
+
+/* record the current triangle function name */
+const char *_mesa_triFuncName = NULL;
+
+#define USE(triFunc) \
+do { \
+ _mesa_triFuncName = #triFunc; \
+ /*printf("%s\n", _mesa_triFuncName);*/ \
+ swrast->Triangle = triFunc; \
+} while (0)
+
+#else
+
+#define USE(triFunc) swrast->Triangle = triFunc;
+
+#endif
+
+
+
+
+/*
+ * Determine which triangle rendering function to use given the current
+ * rendering context.
+ *
+ * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
+ * remove tests to this code.
+ */
+void
+_swrast_choose_triangle( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLboolean rgbmode = ctx->Visual.rgbMode;
+
+ if (ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+ USE(nodraw_triangle);
+ return;
+ }
+
+ if (ctx->RenderMode==GL_RENDER) {
+
+ if (ctx->Polygon.SmoothFlag) {
+ _swrast_set_aa_triangle_function(ctx);
+ ASSERT(swrast->Triangle);
+ return;
+ }
+
+ /* special case for occlusion testing */
+ if (ctx->Query.CurrentOcclusionObject &&
+ ctx->Depth.Test &&
+ ctx->Depth.Mask == GL_FALSE &&
+ ctx->Depth.Func == GL_LESS &&
+ !ctx->Stencil._Enabled) {
+ if ((rgbmode &&
+ ctx->Color.ColorMask[0] == 0 &&
+ ctx->Color.ColorMask[1] == 0 &&
+ ctx->Color.ColorMask[2] == 0 &&
+ ctx->Color.ColorMask[3] == 0)
+ ||
+ (!rgbmode && ctx->Color.IndexMask == 0)) {
+ USE(occlusion_zless_triangle);
+ return;
+ }
+ }
+
+ if (!rgbmode) {
+ USE(ci_triangle);
+ return;
+ }
+
+ /*
+ * XXX should examine swrast->_ActiveAttribMask to determine what
+ * needs to be interpolated.
+ */
+ if (ctx->Texture._EnabledCoordUnits ||
+ ctx->FragmentProgram._Current ||
+ ctx->ATIFragmentShader._Enabled ||
+ NEED_SECONDARY_COLOR(ctx) ||
+ swrast->_FogEnabled) {
+ /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
+ const struct gl_texture_object *texObj2D;
+ const struct gl_texture_image *texImg;
+ GLenum minFilter, magFilter, envMode;
+ GLint format;
+ texObj2D = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX];
+
+ texImg = texObj2D ? texObj2D->Image[0][texObj2D->BaseLevel] : NULL;
+ format = texImg ? texImg->TexFormat->MesaFormat : -1;
+ minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
+ magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
+ envMode = ctx->Texture.Unit[0].EnvMode;
+
+ /* First see if we can use an optimized 2-D texture function */
+ if (ctx->Texture._EnabledCoordUnits == 0x1
+ && !ctx->FragmentProgram._Current
+ && !ctx->ATIFragmentShader._Enabled
+ && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
+ && texObj2D->WrapS == GL_REPEAT
+ && texObj2D->WrapT == GL_REPEAT
+ && texObj2D->_Swizzle == SWIZZLE_NOOP
+ && texImg->_IsPowerOfTwo
+ && texImg->Border == 0
+ && texImg->Width == texImg->RowStride
+ && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
+ && minFilter == magFilter
+ && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
+ && !swrast->_FogEnabled
+ && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT
+ && ctx->Texture.Unit[0].EnvMode != GL_COMBINE4_NV) {
+ if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
+ if (minFilter == GL_NEAREST
+ && format == MESA_FORMAT_RGB
+ && (envMode == GL_REPLACE || envMode == GL_DECAL)
+ && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
+ && ctx->Depth.Func == GL_LESS
+ && ctx->Depth.Mask == GL_TRUE)
+ || swrast->_RasterMask == TEXTURE_BIT)
+ && ctx->Polygon.StippleFlag == GL_FALSE
+ && ctx->DrawBuffer->Visual.depthBits <= 16) {
+ if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
+ USE(simple_z_textured_triangle);
+ }
+ else {
+ USE(simple_textured_triangle);
+ }
+ }
+ else {
+#if CHAN_BITS != 8
+ USE(general_triangle);
+#else
+ USE(affine_textured_triangle);
+#endif
+ }
+ }
+ else {
+#if CHAN_BITS != 8
+ USE(general_triangle);
+#else
+ USE(persp_textured_triangle);
+#endif
+ }
+ }
+ else {
+ /* general case textured triangles */
+ USE(general_triangle);
+ }
+ }
+ else {
+ ASSERT(!swrast->_FogEnabled);
+ ASSERT(!NEED_SECONDARY_COLOR(ctx));
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ /* smooth shaded, no texturing, stippled or some raster ops */
+#if CHAN_BITS != 8
+ USE(general_triangle);
+#else
+ USE(smooth_rgba_triangle);
+#endif
+ }
+ else {
+ /* flat shaded, no texturing, stippled or some raster ops */
+#if CHAN_BITS != 8
+ USE(general_triangle);
+#else
+ USE(flat_rgba_triangle);
+#endif
+ }
+ }
+ }
+ else if (ctx->RenderMode==GL_FEEDBACK) {
+ USE(_swrast_feedback_triangle);
+ }
+ else {
+ /* GL_SELECT mode */
+ USE(_swrast_select_triangle);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_triangle.h b/mesalib/src/mesa/swrast/s_triangle.h
new file mode 100644
index 000000000..b81932c73
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_triangle.h
@@ -0,0 +1,50 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_TRIANGLES_H
+#define S_TRIANGLES_H
+
+
+#include "swrast.h"
+
+
+extern GLboolean
+_swrast_culltriangle( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2);
+
+extern void
+_swrast_choose_triangle( GLcontext *ctx );
+
+extern void
+_swrast_add_spec_terms_triangle( GLcontext *ctx,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2 );
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/s_trispan.h b/mesalib/src/mesa/swrast/s_trispan.h
new file mode 100644
index 000000000..15207e863
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_trispan.h
@@ -0,0 +1,31 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_TRISPAN_H
+#define S_TRISPAN_H
+
+
+#endif /* S_TRISPAN_H */
diff --git a/mesalib/src/mesa/swrast/s_tritemp.h b/mesalib/src/mesa/swrast/s_tritemp.h
new file mode 100644
index 000000000..8e3c5b5ee
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_tritemp.h
@@ -0,0 +1,979 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+/*
+ * Triangle Rasterizer Template
+ *
+ * This file is #include'd to generate custom triangle rasterizers.
+ *
+ * The following macros may be defined to indicate what auxillary information
+ * must be interpolated across the triangle:
+ * INTERP_Z - if defined, interpolate integer Z values
+ * INTERP_RGB - if defined, interpolate integer RGB values
+ * INTERP_ALPHA - if defined, interpolate integer Alpha values
+ * INTERP_INDEX - if defined, interpolate color index values
+ * INTERP_INT_TEX - if defined, interpolate integer ST texcoords
+ * (fast, simple 2-D texture mapping, without
+ * perspective correction)
+ * INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords,
+ * varying vars, etc) This also causes W to be
+ * computed for perspective correction).
+ *
+ * When one can directly address pixels in the color buffer the following
+ * macros can be defined and used to compute pixel addresses during
+ * rasterization (see pRow):
+ * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
+ * BYTES_PER_ROW - number of bytes per row in the color buffer
+ * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
+ * Y==0 at bottom of screen and increases upward.
+ *
+ * Similarly, for direct depth buffer access, this type is used for depth
+ * buffer addressing (see zRow):
+ * DEPTH_TYPE - either GLushort or GLuint
+ *
+ * Optionally, one may provide one-time setup code per triangle:
+ * SETUP_CODE - code which is to be executed once per triangle
+ *
+ * The following macro MUST be defined:
+ * RENDER_SPAN(span) - code to write a span of pixels.
+ *
+ * This code was designed for the origin to be in the lower-left corner.
+ *
+ * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
+ *
+ *
+ * Some notes on rasterization accuracy:
+ *
+ * This code uses fixed point arithmetic (the GLfixed type) to iterate
+ * over the triangle edges and interpolate ancillary data (such as Z,
+ * color, secondary color, etc). The number of fractional bits in
+ * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
+ * accuracy of rasterization.
+ *
+ * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
+ * 1/16 of a pixel. If we're walking up a long, nearly vertical edge
+ * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
+ * GLfixed to walk the edge without error. If the maximum viewport
+ * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
+ *
+ * Historically, Mesa has used 11 fractional bits in GLfixed, snaps
+ * vertices to 1/16 pixel and allowed a maximum viewport height of 2K
+ * pixels. 11 fractional bits is actually insufficient for accurately
+ * rasterizing some triangles. More recently, the maximum viewport
+ * height was increased to 4K pixels. Thus, Mesa should be using 16
+ * fractional bits in GLfixed. Unfortunately, there may be some issues
+ * with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
+ * This will have to be examined in some detail...
+ *
+ * For now, if you find rasterization errors, particularly with tall,
+ * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
+ * SUB_PIXEL_BITS.
+ */
+
+
+/*
+ * Some code we unfortunately need to prevent negative interpolated colors.
+ */
+#ifndef CLAMP_INTERPOLANT
+#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \
+do { \
+ GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \
+ if (endVal < 0) { \
+ span.CHANNEL -= endVal; \
+ } \
+ if (span.CHANNEL < 0) { \
+ span.CHANNEL = 0; \
+ } \
+} while (0)
+#endif
+
+
+static void NAME(GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2 )
+{
+ typedef struct {
+ const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
+ GLfloat dx; /* X(v1) - X(v0) */
+ GLfloat dy; /* Y(v1) - Y(v0) */
+ GLfloat dxdy; /* dx/dy */
+ GLfixed fdxdy; /* dx/dy in fixed-point */
+ GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
+ GLfixed fsx; /* first sample point x coord */
+ GLfixed fsy;
+ GLfixed fx0; /* fixed pt X of lower endpoint */
+ GLint lines; /* number of lines to be sampled on this edge */
+ } EdgeT;
+
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+#ifdef INTERP_Z
+ const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
+ const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
+ const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
+#define FixedToDepth(F) ((F) >> fixedToDepthShift)
+#endif
+ EdgeT eMaj, eTop, eBot;
+ GLfloat oneOverArea;
+ const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
+ GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
+ const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
+ GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
+
+ SWspan span;
+
+ (void) swrast;
+
+ INIT_SPAN(span, GL_POLYGON);
+ span.y = 0; /* silence warnings */
+
+#ifdef INTERP_Z
+ (void) fixedToDepthShift;
+#endif
+
+ /*
+ printf("%s()\n", __FUNCTION__);
+ printf(" %g, %g, %g\n",
+ v0->attrib[FRAG_ATTRIB_WPOS][0],
+ v0->attrib[FRAG_ATTRIB_WPOS][1],
+ v0->attrib[FRAG_ATTRIB_WPOS][2]);
+ printf(" %g, %g, %g\n",
+ v1->attrib[FRAG_ATTRIB_WPOS][0],
+ v1->attrib[FRAG_ATTRIB_WPOS][1],
+ v1->attrib[FRAG_ATTRIB_WPOS][2]);
+ printf(" %g, %g, %g\n",
+ v2->attrib[FRAG_ATTRIB_WPOS][0],
+ v2->attrib[FRAG_ATTRIB_WPOS][1],
+ v2->attrib[FRAG_ATTRIB_WPOS][2]);
+ */
+
+ /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
+ * And find the order of the 3 vertices along the Y axis.
+ */
+ {
+ const GLfixed fy0 = FloatToFixed(v0->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
+ const GLfixed fy1 = FloatToFixed(v1->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
+ const GLfixed fy2 = FloatToFixed(v2->attrib[FRAG_ATTRIB_WPOS][1] - 0.5F) & snapMask;
+ if (fy0 <= fy1) {
+ if (fy1 <= fy2) {
+ /* y0 <= y1 <= y2 */
+ vMin = v0; vMid = v1; vMax = v2;
+ vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
+ }
+ else if (fy2 <= fy0) {
+ /* y2 <= y0 <= y1 */
+ vMin = v2; vMid = v0; vMax = v1;
+ vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
+ }
+ else {
+ /* y0 <= y2 <= y1 */
+ vMin = v0; vMid = v2; vMax = v1;
+ vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
+ bf = -bf;
+ }
+ }
+ else {
+ if (fy0 <= fy2) {
+ /* y1 <= y0 <= y2 */
+ vMin = v1; vMid = v0; vMax = v2;
+ vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
+ bf = -bf;
+ }
+ else if (fy2 <= fy1) {
+ /* y2 <= y1 <= y0 */
+ vMin = v2; vMid = v1; vMax = v0;
+ vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
+ bf = -bf;
+ }
+ else {
+ /* y1 <= y2 <= y0 */
+ vMin = v1; vMid = v2; vMax = v0;
+ vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
+ }
+ }
+
+ /* fixed point X coords */
+ vMin_fx = FloatToFixed(vMin->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
+ vMid_fx = FloatToFixed(vMid->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
+ vMax_fx = FloatToFixed(vMax->attrib[FRAG_ATTRIB_WPOS][0] + 0.5F) & snapMask;
+ }
+
+ /* vertex/edge relationship */
+ eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
+ eTop.v0 = vMid; eTop.v1 = vMax;
+ eBot.v0 = vMin; eBot.v1 = vMid;
+
+ /* compute deltas for each edge: vertex[upper] - vertex[lower] */
+ eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
+ eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
+ eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
+ eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
+ eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
+ eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
+
+ /* compute area, oneOverArea and perform backface culling */
+ {
+ const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
+
+ if (IS_INF_OR_NAN(area) || area == 0.0F)
+ return;
+
+ if (area * bf * swrast->_BackfaceCullSign < 0.0)
+ return;
+
+ oneOverArea = 1.0F / area;
+
+ /* 0 = front, 1 = back */
+ span.facing = oneOverArea * bf > 0.0F;
+ }
+
+ /* Edge setup. For a triangle strip these could be reused... */
+ {
+ eMaj.fsy = FixedCeil(vMin_fy);
+ eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
+ if (eMaj.lines > 0) {
+ eMaj.dxdy = eMaj.dx / eMaj.dy;
+ eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
+ eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
+ eMaj.fx0 = vMin_fx;
+ eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
+ }
+ else {
+ return; /*CULLED*/
+ }
+
+ eTop.fsy = FixedCeil(vMid_fy);
+ eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
+ if (eTop.lines > 0) {
+ eTop.dxdy = eTop.dx / eTop.dy;
+ eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
+ eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
+ eTop.fx0 = vMid_fx;
+ eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
+ }
+
+ eBot.fsy = FixedCeil(vMin_fy);
+ eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
+ if (eBot.lines > 0) {
+ eBot.dxdy = eBot.dx / eBot.dy;
+ eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
+ eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
+ eBot.fx0 = vMin_fx;
+ eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
+ }
+ }
+
+ /*
+ * Conceptually, we view a triangle as two subtriangles
+ * separated by a perfectly horizontal line. The edge that is
+ * intersected by this line is one with maximal absolute dy; we
+ * call it a ``major'' edge. The other two edges are the
+ * ``top'' edge (for the upper subtriangle) and the ``bottom''
+ * edge (for the lower subtriangle). If either of these two
+ * edges is horizontal or very close to horizontal, the
+ * corresponding subtriangle might cover zero sample points;
+ * we take care to handle such cases, for performance as well
+ * as correctness.
+ *
+ * By stepping rasterization parameters along the major edge,
+ * we can avoid recomputing them at the discontinuity where
+ * the top and bottom edges meet. However, this forces us to
+ * be able to scan both left-to-right and right-to-left.
+ * Also, we must determine whether the major edge is at the
+ * left or right side of the triangle. We do this by
+ * computing the magnitude of the cross-product of the major
+ * and top edges. Since this magnitude depends on the sine of
+ * the angle between the two edges, its sign tells us whether
+ * we turn to the left or to the right when travelling along
+ * the major edge to the top edge, and from this we infer
+ * whether the major edge is on the left or the right.
+ *
+ * Serendipitously, this cross-product magnitude is also a
+ * value we need to compute the iteration parameter
+ * derivatives for the triangle, and it can be used to perform
+ * backface culling because its sign tells us whether the
+ * triangle is clockwise or counterclockwise. In this code we
+ * refer to it as ``area'' because it's also proportional to
+ * the pixel area of the triangle.
+ */
+
+ {
+ GLint scan_from_left_to_right; /* true if scanning left-to-right */
+#ifdef INTERP_INDEX
+ GLfloat didx, didy;
+#endif
+
+ /*
+ * Execute user-supplied setup code
+ */
+#ifdef SETUP_CODE
+ SETUP_CODE
+#endif
+
+ scan_from_left_to_right = (oneOverArea < 0.0F);
+
+
+ /* compute d?/dx and d?/dy derivatives */
+#ifdef INTERP_Z
+ span.interpMask |= SPAN_Z;
+ {
+ GLfloat eMaj_dz = vMax->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2];
+ GLfloat eBot_dz = vMid->attrib[FRAG_ATTRIB_WPOS][2] - vMin->attrib[FRAG_ATTRIB_WPOS][2];
+ span.attrStepX[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
+ if (span.attrStepX[FRAG_ATTRIB_WPOS][2] > maxDepth ||
+ span.attrStepX[FRAG_ATTRIB_WPOS][2] < -maxDepth) {
+ /* probably a sliver triangle */
+ span.attrStepX[FRAG_ATTRIB_WPOS][2] = 0.0;
+ span.attrStepY[FRAG_ATTRIB_WPOS][2] = 0.0;
+ }
+ else {
+ span.attrStepY[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
+ }
+ if (depthBits <= 16)
+ span.zStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_WPOS][2]);
+ else
+ span.zStep = (GLint) span.attrStepX[FRAG_ATTRIB_WPOS][2];
+ }
+#endif
+#ifdef INTERP_RGB
+ span.interpMask |= SPAN_RGBA;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]);
+ GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]);
+ GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]);
+ GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]);
+ GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]);
+ GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]);
+# ifdef INTERP_ALPHA
+ GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]);
+ GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]);
+# endif
+ span.attrStepX[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
+ span.attrStepY[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
+ span.attrStepX[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
+ span.attrStepY[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
+ span.attrStepX[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
+ span.attrStepY[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
+ span.redStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][0]);
+ span.greenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][1]);
+ span.blueStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][2]);
+# ifdef INTERP_ALPHA
+ span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
+ span.attrStepY[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
+ span.alphaStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3]);
+# endif /* INTERP_ALPHA */
+ }
+ else {
+ ASSERT(ctx->Light.ShadeModel == GL_FLAT);
+ span.interpMask |= SPAN_FLAT;
+ span.attrStepX[FRAG_ATTRIB_COL0][0] = span.attrStepY[FRAG_ATTRIB_COL0][0] = 0.0F;
+ span.attrStepX[FRAG_ATTRIB_COL0][1] = span.attrStepY[FRAG_ATTRIB_COL0][1] = 0.0F;
+ span.attrStepX[FRAG_ATTRIB_COL0][2] = span.attrStepY[FRAG_ATTRIB_COL0][2] = 0.0F;
+ span.redStep = 0;
+ span.greenStep = 0;
+ span.blueStep = 0;
+# ifdef INTERP_ALPHA
+ span.attrStepX[FRAG_ATTRIB_COL0][3] = span.attrStepY[FRAG_ATTRIB_COL0][3] = 0.0F;
+ span.alphaStep = 0;
+# endif
+ }
+#endif /* INTERP_RGB */
+#ifdef INTERP_INDEX
+ span.interpMask |= SPAN_INDEX;
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ GLfloat eMaj_di = vMax->attrib[FRAG_ATTRIB_CI][0] - vMin->attrib[FRAG_ATTRIB_CI][0];
+ GLfloat eBot_di = vMid->attrib[FRAG_ATTRIB_CI][0] - vMin->attrib[FRAG_ATTRIB_CI][0];
+ didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
+ didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
+ span.indexStep = SignedFloatToFixed(didx);
+ }
+ else {
+ span.interpMask |= SPAN_FLAT;
+ didx = didy = 0.0F;
+ span.indexStep = 0;
+ }
+#endif
+#ifdef INTERP_INT_TEX
+ {
+ GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
+ GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
+ GLfloat eMaj_dt = (vMax->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
+ GLfloat eBot_dt = (vMid->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
+ span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
+ span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
+ span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
+ span.attrStepY[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
+ span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][0]);
+ span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][1]);
+ }
+#endif
+#ifdef INTERP_ATTRIBS
+ {
+ /* attrib[FRAG_ATTRIB_WPOS][3] is 1/W */
+ const GLfloat wMax = vMax->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat wMin = vMin->attrib[FRAG_ATTRIB_WPOS][3];
+ const GLfloat wMid = vMid->attrib[FRAG_ATTRIB_WPOS][3];
+ {
+ const GLfloat eMaj_dw = wMax - wMin;
+ const GLfloat eBot_dw = wMid - wMin;
+ span.attrStepX[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
+ span.attrStepY[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
+ }
+ ATTRIB_LOOP_BEGIN
+ if (swrast->_InterpMode[attr] == GL_FLAT) {
+ ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
+ ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
+ }
+ else {
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin;
+ GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin;
+ span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
+ span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
+ }
+ }
+ ATTRIB_LOOP_END
+ }
+#endif
+
+ /*
+ * We always sample at pixel centers. However, we avoid
+ * explicit half-pixel offsets in this code by incorporating
+ * the proper offset in each of x and y during the
+ * transformation to window coordinates.
+ *
+ * We also apply the usual rasterization rules to prevent
+ * cracks and overlaps. A pixel is considered inside a
+ * subtriangle if it meets all of four conditions: it is on or
+ * to the right of the left edge, strictly to the left of the
+ * right edge, on or below the top edge, and strictly above
+ * the bottom edge. (Some edges may be degenerate.)
+ *
+ * The following discussion assumes left-to-right scanning
+ * (that is, the major edge is on the left); the right-to-left
+ * case is a straightforward variation.
+ *
+ * We start by finding the half-integral y coordinate that is
+ * at or below the top of the triangle. This gives us the
+ * first scan line that could possibly contain pixels that are
+ * inside the triangle.
+ *
+ * Next we creep down the major edge until we reach that y,
+ * and compute the corresponding x coordinate on the edge.
+ * Then we find the half-integral x that lies on or just
+ * inside the edge. This is the first pixel that might lie in
+ * the interior of the triangle. (We won't know for sure
+ * until we check the other edges.)
+ *
+ * As we rasterize the triangle, we'll step down the major
+ * edge. For each step in y, we'll move an integer number
+ * of steps in x. There are two possible x step sizes, which
+ * we'll call the ``inner'' step (guaranteed to land on the
+ * edge or inside it) and the ``outer'' step (guaranteed to
+ * land on the edge or outside it). The inner and outer steps
+ * differ by one. During rasterization we maintain an error
+ * term that indicates our distance from the true edge, and
+ * select either the inner step or the outer step, whichever
+ * gets us to the first pixel that falls inside the triangle.
+ *
+ * All parameters (z, red, etc.) as well as the buffer
+ * addresses for color and z have inner and outer step values,
+ * so that we can increment them appropriately. This method
+ * eliminates the need to adjust parameters by creeping a
+ * sub-pixel amount into the triangle at each scanline.
+ */
+
+ {
+ GLint subTriangle;
+ GLfixed fxLeftEdge = 0, fxRightEdge = 0;
+ GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
+ GLfixed fError = 0, fdError = 0;
+#ifdef PIXEL_ADDRESS
+ PIXEL_TYPE *pRow = NULL;
+ GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */
+#endif
+#ifdef INTERP_Z
+# ifdef DEPTH_TYPE
+ struct gl_renderbuffer *zrb
+ = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ DEPTH_TYPE *zRow = NULL;
+ GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */
+# endif
+ GLuint zLeft = 0;
+ GLfixed fdzOuter = 0, fdzInner;
+#endif
+#ifdef INTERP_RGB
+ GLint rLeft = 0, fdrOuter = 0, fdrInner;
+ GLint gLeft = 0, fdgOuter = 0, fdgInner;
+ GLint bLeft = 0, fdbOuter = 0, fdbInner;
+#endif
+#ifdef INTERP_ALPHA
+ GLint aLeft = 0, fdaOuter = 0, fdaInner;
+#endif
+#ifdef INTERP_INDEX
+ GLfixed iLeft=0, diOuter=0, diInner;
+#endif
+#ifdef INTERP_INT_TEX
+ GLfixed sLeft=0, dsOuter=0, dsInner;
+ GLfixed tLeft=0, dtOuter=0, dtInner;
+#endif
+#ifdef INTERP_ATTRIBS
+ GLfloat wLeft = 0, dwOuter = 0, dwInner;
+ GLfloat attrLeft[FRAG_ATTRIB_MAX][4];
+ GLfloat daOuter[FRAG_ATTRIB_MAX][4], daInner[FRAG_ATTRIB_MAX][4];
+#endif
+
+ for (subTriangle=0; subTriangle<=1; subTriangle++) {
+ EdgeT *eLeft, *eRight;
+ int setupLeft, setupRight;
+ int lines;
+
+ if (subTriangle==0) {
+ /* bottom half */
+ if (scan_from_left_to_right) {
+ eLeft = &eMaj;
+ eRight = &eBot;
+ lines = eRight->lines;
+ setupLeft = 1;
+ setupRight = 1;
+ }
+ else {
+ eLeft = &eBot;
+ eRight = &eMaj;
+ lines = eLeft->lines;
+ setupLeft = 1;
+ setupRight = 1;
+ }
+ }
+ else {
+ /* top half */
+ if (scan_from_left_to_right) {
+ eLeft = &eMaj;
+ eRight = &eTop;
+ lines = eRight->lines;
+ setupLeft = 0;
+ setupRight = 1;
+ }
+ else {
+ eLeft = &eTop;
+ eRight = &eMaj;
+ lines = eLeft->lines;
+ setupLeft = 1;
+ setupRight = 0;
+ }
+ if (lines == 0)
+ return;
+ }
+
+ if (setupLeft && eLeft->lines > 0) {
+ const SWvertex *vLower = eLeft->v0;
+ const GLfixed fsy = eLeft->fsy;
+ const GLfixed fsx = eLeft->fsx; /* no fractional part */
+ const GLfixed fx = FixedCeil(fsx); /* no fractional part */
+ const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */
+ const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */
+ GLint idxOuter;
+ GLfloat dxOuter;
+ GLfixed fdxOuter;
+
+ fError = fx - fsx - FIXED_ONE;
+ fxLeftEdge = fsx - FIXED_EPSILON;
+ fdxLeftEdge = eLeft->fdxdy;
+ fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
+ fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
+ idxOuter = FixedToInt(fdxOuter);
+ dxOuter = (GLfloat) idxOuter;
+ span.y = FixedToInt(fsy);
+
+ /* silence warnings on some compilers */
+ (void) dxOuter;
+ (void) adjx;
+ (void) adjy;
+ (void) vLower;
+
+#ifdef PIXEL_ADDRESS
+ {
+ pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
+ dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
+ /* negative because Y=0 at bottom and increases upward */
+ }
+#endif
+ /*
+ * Now we need the set of parameter (z, color, etc.) values at
+ * the point (fx, fsy). This gives us properly-sampled parameter
+ * values that we can step from pixel to pixel. Furthermore,
+ * although we might have intermediate results that overflow
+ * the normal parameter range when we step temporarily outside
+ * the triangle, we shouldn't overflow or underflow for any
+ * pixel that's actually inside the triangle.
+ */
+
+#ifdef INTERP_Z
+ {
+ GLfloat z0 = vLower->attrib[FRAG_ATTRIB_WPOS][2];
+ if (depthBits <= 16) {
+ /* interpolate fixed-pt values */
+ GLfloat tmp = (z0 * FIXED_SCALE
+ + span.attrStepX[FRAG_ATTRIB_WPOS][2] * adjx
+ + span.attrStepY[FRAG_ATTRIB_WPOS][2] * adjy) + FIXED_HALF;
+ if (tmp < MAX_GLUINT / 2)
+ zLeft = (GLfixed) tmp;
+ else
+ zLeft = MAX_GLUINT / 2;
+ fdzOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_WPOS][2] +
+ dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
+ }
+ else {
+ /* interpolate depth values w/out scaling */
+ zLeft = (GLuint) (z0 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjx)
+ + span.attrStepY[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjy));
+ fdzOuter = (GLint) (span.attrStepY[FRAG_ATTRIB_WPOS][2] +
+ dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
+ }
+# ifdef DEPTH_TYPE
+ zRow = (DEPTH_TYPE *)
+ zrb->GetPointer(ctx, zrb, FixedToInt(fxLeftEdge), span.y);
+ dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
+# endif
+ }
+#endif
+#ifdef INTERP_RGB
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP])
+ + span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx
+ + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) + FIXED_HALF;
+ gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP])
+ + span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx
+ + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) + FIXED_HALF;
+ bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP])
+ + span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx
+ + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) + FIXED_HALF;
+ fdrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][0]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0]);
+ fdgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][1]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1]);
+ fdbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][2]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2]);
+# ifdef INTERP_ALPHA
+ aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP])
+ + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx
+ + span.attrStepY[FRAG_ATTRIB_COL0][3] * adjy) + FIXED_HALF;
+ fdaOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][3]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3]);
+# endif
+ }
+ else {
+ ASSERT(ctx->Light.ShadeModel == GL_FLAT);
+ rLeft = ChanToFixed(v2->color[RCOMP]);
+ gLeft = ChanToFixed(v2->color[GCOMP]);
+ bLeft = ChanToFixed(v2->color[BCOMP]);
+ fdrOuter = fdgOuter = fdbOuter = 0;
+# ifdef INTERP_ALPHA
+ aLeft = ChanToFixed(v2->color[ACOMP]);
+ fdaOuter = 0;
+# endif
+ }
+#endif /* INTERP_RGB */
+
+
+#ifdef INTERP_INDEX
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ iLeft = (GLfixed)(vLower->attrib[FRAG_ATTRIB_CI][0] * FIXED_SCALE
+ + didx * adjx + didy * adjy) + FIXED_HALF;
+ diOuter = SignedFloatToFixed(didy + dxOuter * didx);
+ }
+ else {
+ ASSERT(ctx->Light.ShadeModel == GL_FLAT);
+ iLeft = FloatToFixed(v2->attrib[FRAG_ATTRIB_CI][0]);
+ diOuter = 0;
+ }
+#endif
+#ifdef INTERP_INT_TEX
+ {
+ GLfloat s0, t0;
+ s0 = vLower->attrib[FRAG_ATTRIB_TEX0][0] * S_SCALE;
+ sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx
+ + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF;
+ dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]);
+
+ t0 = vLower->attrib[FRAG_ATTRIB_TEX0][1] * T_SCALE;
+ tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx
+ + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF;
+ dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1]
+ + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]);
+ }
+#endif
+#ifdef INTERP_ATTRIBS
+ {
+ const GLuint attr = FRAG_ATTRIB_WPOS;
+ wLeft = vLower->attrib[FRAG_ATTRIB_WPOS][3]
+ + (span.attrStepX[attr][3] * adjx
+ + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
+ dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
+ }
+ ATTRIB_LOOP_BEGIN
+ const GLfloat invW = vLower->attrib[FRAG_ATTRIB_WPOS][3];
+ if (swrast->_InterpMode[attr] == GL_FLAT) {
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ attrLeft[attr][c] = v2->attrib[attr][c] * invW;
+ daOuter[attr][c] = 0.0;
+ }
+ }
+ else {
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ const GLfloat a = vLower->attrib[attr][c] * invW;
+ attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx
+ + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE);
+ daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c];
+ }
+ }
+ ATTRIB_LOOP_END
+#endif
+ } /*if setupLeft*/
+
+
+ if (setupRight && eRight->lines>0) {
+ fxRightEdge = eRight->fsx - FIXED_EPSILON;
+ fdxRightEdge = eRight->fdxdy;
+ }
+
+ if (lines==0) {
+ continue;
+ }
+
+
+ /* Rasterize setup */
+#ifdef PIXEL_ADDRESS
+ dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
+#endif
+#ifdef INTERP_Z
+# ifdef DEPTH_TYPE
+ dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
+# endif
+ fdzInner = fdzOuter + span.zStep;
+#endif
+#ifdef INTERP_RGB
+ fdrInner = fdrOuter + span.redStep;
+ fdgInner = fdgOuter + span.greenStep;
+ fdbInner = fdbOuter + span.blueStep;
+#endif
+#ifdef INTERP_ALPHA
+ fdaInner = fdaOuter + span.alphaStep;
+#endif
+#ifdef INTERP_INDEX
+ diInner = diOuter + span.indexStep;
+#endif
+#ifdef INTERP_INT_TEX
+ dsInner = dsOuter + span.intTexStep[0];
+ dtInner = dtOuter + span.intTexStep[1];
+#endif
+#ifdef INTERP_ATTRIBS
+ dwInner = dwOuter + span.attrStepX[FRAG_ATTRIB_WPOS][3];
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c];
+ }
+ ATTRIB_LOOP_END
+#endif
+
+ while (lines > 0) {
+ /* initialize the span interpolants to the leftmost value */
+ /* ff = fixed-pt fragment */
+ const GLint right = FixedToInt(fxRightEdge);
+ span.x = FixedToInt(fxLeftEdge);
+ if (right <= span.x)
+ span.end = 0;
+ else
+ span.end = right - span.x;
+
+#ifdef INTERP_Z
+ span.z = zLeft;
+#endif
+#ifdef INTERP_RGB
+ span.red = rLeft;
+ span.green = gLeft;
+ span.blue = bLeft;
+#endif
+#ifdef INTERP_ALPHA
+ span.alpha = aLeft;
+#endif
+#ifdef INTERP_INDEX
+ span.index = iLeft;
+#endif
+#ifdef INTERP_INT_TEX
+ span.intTex[0] = sLeft;
+ span.intTex[1] = tLeft;
+#endif
+
+#ifdef INTERP_ATTRIBS
+ span.attrStart[FRAG_ATTRIB_WPOS][3] = wLeft;
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ span.attrStart[attr][c] = attrLeft[attr][c];
+ }
+ ATTRIB_LOOP_END
+#endif
+
+ /* This is where we actually generate fragments */
+ /* XXX the test for span.y > 0 _shouldn't_ be needed but
+ * it fixes a problem on 64-bit Opterons (bug 4842).
+ */
+ if (span.end > 0 && span.y >= 0) {
+ const GLint len = span.end - 1;
+ (void) len;
+#ifdef INTERP_RGB
+ CLAMP_INTERPOLANT(red, redStep, len);
+ CLAMP_INTERPOLANT(green, greenStep, len);
+ CLAMP_INTERPOLANT(blue, blueStep, len);
+#endif
+#ifdef INTERP_ALPHA
+ CLAMP_INTERPOLANT(alpha, alphaStep, len);
+#endif
+#ifdef INTERP_INDEX
+ CLAMP_INTERPOLANT(index, indexStep, len);
+#endif
+ {
+ RENDER_SPAN( span );
+ }
+ }
+
+ /*
+ * Advance to the next scan line. Compute the
+ * new edge coordinates, and adjust the
+ * pixel-center x coordinate so that it stays
+ * on or inside the major edge.
+ */
+ span.y++;
+ lines--;
+
+ fxLeftEdge += fdxLeftEdge;
+ fxRightEdge += fdxRightEdge;
+
+ fError += fdError;
+ if (fError >= 0) {
+ fError -= FIXED_ONE;
+
+#ifdef PIXEL_ADDRESS
+ pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
+#endif
+#ifdef INTERP_Z
+# ifdef DEPTH_TYPE
+ zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
+# endif
+ zLeft += fdzOuter;
+#endif
+#ifdef INTERP_RGB
+ rLeft += fdrOuter;
+ gLeft += fdgOuter;
+ bLeft += fdbOuter;
+#endif
+#ifdef INTERP_ALPHA
+ aLeft += fdaOuter;
+#endif
+#ifdef INTERP_INDEX
+ iLeft += diOuter;
+#endif
+#ifdef INTERP_INT_TEX
+ sLeft += dsOuter;
+ tLeft += dtOuter;
+#endif
+#ifdef INTERP_ATTRIBS
+ wLeft += dwOuter;
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ attrLeft[attr][c] += daOuter[attr][c];
+ }
+ ATTRIB_LOOP_END
+#endif
+ }
+ else {
+#ifdef PIXEL_ADDRESS
+ pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
+#endif
+#ifdef INTERP_Z
+# ifdef DEPTH_TYPE
+ zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
+# endif
+ zLeft += fdzInner;
+#endif
+#ifdef INTERP_RGB
+ rLeft += fdrInner;
+ gLeft += fdgInner;
+ bLeft += fdbInner;
+#endif
+#ifdef INTERP_ALPHA
+ aLeft += fdaInner;
+#endif
+#ifdef INTERP_INDEX
+ iLeft += diInner;
+#endif
+#ifdef INTERP_INT_TEX
+ sLeft += dsInner;
+ tLeft += dtInner;
+#endif
+#ifdef INTERP_ATTRIBS
+ wLeft += dwInner;
+ ATTRIB_LOOP_BEGIN
+ GLuint c;
+ for (c = 0; c < 4; c++) {
+ attrLeft[attr][c] += daInner[attr][c];
+ }
+ ATTRIB_LOOP_END
+#endif
+ }
+ } /*while lines>0*/
+
+ } /* for subTriangle */
+
+ }
+ }
+}
+
+#undef SETUP_CODE
+#undef RENDER_SPAN
+
+#undef PIXEL_TYPE
+#undef BYTES_PER_ROW
+#undef PIXEL_ADDRESS
+#undef DEPTH_TYPE
+
+#undef INTERP_Z
+#undef INTERP_RGB
+#undef INTERP_ALPHA
+#undef INTERP_INDEX
+#undef INTERP_INT_TEX
+#undef INTERP_ATTRIBS
+
+#undef S_SCALE
+#undef T_SCALE
+
+#undef FixedToDepth
+
+#undef NAME
diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c
new file mode 100644
index 000000000..a48eae192
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_zoom.c
@@ -0,0 +1,477 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/colormac.h"
+
+#include "s_context.h"
+#include "s_span.h"
+#include "s_stencil.h"
+#include "s_zoom.h"
+
+
+/**
+ * Compute the bounds of the region resulting from zooming a pixel span.
+ * The resulting region will be entirely inside the window/scissor bounds
+ * so no additional clipping is needed.
+ * \param imageX, imageY position of the mage being drawn (gl WindowPos)
+ * \param spanX, spanY position of span being drawing
+ * \param width number of pixels in span
+ * \param x0, x1 returned X bounds of zoomed region [x0, x1)
+ * \param y0, y1 returned Y bounds of zoomed region [y0, y1)
+ * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
+ */
+static GLboolean
+compute_zoomed_bounds(GLcontext *ctx, GLint imageX, GLint imageY,
+ GLint spanX, GLint spanY, GLint width,
+ GLint *x0, GLint *x1, GLint *y0, GLint *y1)
+{
+ const struct gl_framebuffer *fb = ctx->DrawBuffer;
+ GLint c0, c1, r0, r1;
+
+ ASSERT(spanX >= imageX);
+ ASSERT(spanY >= imageY);
+
+ /*
+ * Compute destination columns: [c0, c1)
+ */
+ c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
+ c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
+ if (c1 < c0) {
+ /* swap */
+ GLint tmp = c1;
+ c1 = c0;
+ c0 = tmp;
+ }
+ c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
+ c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
+ if (c0 == c1) {
+ return GL_FALSE; /* no width */
+ }
+
+ /*
+ * Compute destination rows: [r0, r1)
+ */
+ r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
+ r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
+ if (r1 < r0) {
+ /* swap */
+ GLint tmp = r1;
+ r1 = r0;
+ r0 = tmp;
+ }
+ r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
+ r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
+ if (r0 == r1) {
+ return GL_FALSE; /* no height */
+ }
+
+ *x0 = c0;
+ *x1 = c1;
+ *y0 = r0;
+ *y1 = r1;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Convert a zoomed x image coordinate back to an unzoomed x coord.
+ * 'zx' is screen position of a pixel in the zoomed image, who's left edge
+ * is at 'imageX'.
+ * return corresponding x coord in the original, unzoomed image.
+ * This can use this for unzooming X or Y values.
+ */
+static INLINE GLint
+unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
+{
+ /*
+ zx = imageX + (x - imageX) * zoomX;
+ zx - imageX = (x - imageX) * zoomX;
+ (zx - imageX) / zoomX = x - imageX;
+ */
+ GLint x;
+ if (zoomX < 0.0)
+ zx++;
+ x = imageX + (GLint) ((zx - imageX) / zoomX);
+ return x;
+}
+
+
+
+/**
+ * Helper function called from _swrast_write_zoomed_rgba/rgb/
+ * index/depth_span().
+ */
+static void
+zoom_span( GLcontext *ctx, GLint imgX, GLint imgY, const SWspan *span,
+ const GLvoid *src, GLenum format )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ SWspan zoomed;
+ GLint x0, x1, y0, y1;
+ GLint zoomedWidth;
+
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
+ }
+
+ if (!swrast->ZoomedArrays) {
+ /* allocate on demand */
+ swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays));
+ if (!swrast->ZoomedArrays)
+ return;
+ }
+
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
+
+ /* no pixel arrays! must be horizontal spans. */
+ ASSERT((span->arrayMask & SPAN_XY) == 0);
+ ASSERT(span->primitive == GL_BITMAP);
+
+ INIT_SPAN(zoomed, GL_BITMAP);
+ zoomed.x = x0;
+ zoomed.end = zoomedWidth;
+ zoomed.array = swrast->ZoomedArrays;
+ zoomed.array->ChanType = span->array->ChanType;
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
+ else
+ zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0];
+
+ COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]);
+ COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]);
+ COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]);
+
+ zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0];
+ zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0];
+ zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0];
+
+ if (format == GL_RGBA || format == GL_RGB) {
+ /* copy Z info */
+ zoomed.z = span->z;
+ zoomed.zStep = span->zStep;
+ /* we'll generate an array of colorss */
+ zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
+ zoomed.arrayMask |= SPAN_RGBA;
+ zoomed.arrayAttribs |= FRAG_BIT_COL0; /* we'll produce these values */
+ ASSERT(span->arrayMask & SPAN_RGBA);
+ }
+ else if (format == GL_COLOR_INDEX) {
+ /* copy Z info */
+ zoomed.z = span->z;
+ zoomed.zStep = span->zStep;
+ /* we'll generate an array of color indexes */
+ zoomed.interpMask = span->interpMask & ~SPAN_INDEX;
+ zoomed.arrayMask |= SPAN_INDEX;
+ ASSERT(span->arrayMask & SPAN_INDEX);
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ /* Copy color info */
+ zoomed.red = span->red;
+ zoomed.green = span->green;
+ zoomed.blue = span->blue;
+ zoomed.alpha = span->alpha;
+ zoomed.redStep = span->redStep;
+ zoomed.greenStep = span->greenStep;
+ zoomed.blueStep = span->blueStep;
+ zoomed.alphaStep = span->alphaStep;
+ /* we'll generate an array of depth values */
+ zoomed.interpMask = span->interpMask & ~SPAN_Z;
+ zoomed.arrayMask |= SPAN_Z;
+ ASSERT(span->arrayMask & SPAN_Z);
+ }
+ else {
+ _mesa_problem(ctx, "Bad format in zoom_span");
+ return;
+ }
+
+ /* zoom the span horizontally */
+ if (format == GL_RGBA) {
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
+ }
+ }
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ COPY_4V(zoomed.array->rgba16[i], rgba[j]);
+ }
+ }
+ else {
+ const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < span->end);
+ COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]);
+ }
+ }
+ }
+ else if (format == GL_RGB) {
+ if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->rgba8[i][0] = rgb[j][0];
+ zoomed.array->rgba8[i][1] = rgb[j][1];
+ zoomed.array->rgba8[i][2] = rgb[j][2];
+ zoomed.array->rgba8[i][3] = 0xff;
+ }
+ }
+ else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->rgba16[i][0] = rgb[j][0];
+ zoomed.array->rgba16[i][1] = rgb[j][1];
+ zoomed.array->rgba16[i][2] = rgb[j][2];
+ zoomed.array->rgba16[i][3] = 0xffff;
+ }
+ }
+ else {
+ const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < span->end);
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2];
+ zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F;
+ }
+ }
+ }
+ else if (format == GL_COLOR_INDEX) {
+ const GLuint *indexes = (const GLuint *) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->index[i] = indexes[j];
+ }
+ }
+ else if (format == GL_DEPTH_COMPONENT) {
+ const GLuint *zValues = (const GLuint *) src;
+ GLint i;
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
+ ASSERT(j >= 0);
+ ASSERT(j < (GLint) span->end);
+ zoomed.array->z[i] = zValues[j];
+ }
+ /* Now, fall into either the RGB or COLOR_INDEX path below */
+ format = ctx->Visual.rgbMode ? GL_RGBA : GL_COLOR_INDEX;
+ }
+
+ /* write the span in rows [r0, r1) */
+ if (format == GL_RGBA || format == GL_RGB) {
+ /* Writing the span may modify the colors, so make a backup now if we're
+ * going to call _swrast_write_zoomed_span() more than once.
+ * Also, clipping may change the span end value, so store it as well.
+ */
+ const GLint end = zoomed.end; /* save */
+ GLuint rgbaSave[MAX_WIDTH][4];
+ const GLint pixelSize =
+ (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
+ ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
+ : 4 * sizeof(GLfloat));
+ if (y1 - y0 > 1) {
+ MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
+ }
+ for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
+ _swrast_write_rgba_span(ctx, &zoomed);
+ zoomed.end = end; /* restore */
+ if (y1 - y0 > 1) {
+ /* restore the colors */
+ MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
+ }
+ }
+ }
+ else if (format == GL_COLOR_INDEX) {
+ /* use specular color array for temp storage */
+ GLuint *indexSave = (GLuint *) zoomed.array->attribs[FRAG_ATTRIB_FOGC];
+ const GLint end = zoomed.end; /* save */
+ if (y1 - y0 > 1) {
+ MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint));
+ }
+ for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
+ _swrast_write_index_span(ctx, &zoomed);
+ zoomed.end = end; /* restore */
+ if (y1 - y0 > 1) {
+ /* restore the colors */
+ MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint));
+ }
+ }
+ }
+}
+
+
+void
+_swrast_write_zoomed_rgba_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgba)
+{
+ zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
+}
+
+
+void
+_swrast_write_zoomed_rgb_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgb)
+{
+ zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
+}
+
+
+void
+_swrast_write_zoomed_index_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span)
+{
+ zoom_span(ctx, imgX, imgY, span,
+ (const GLvoid *) span->array->index, GL_COLOR_INDEX);
+}
+
+
+void
+_swrast_write_zoomed_depth_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span)
+{
+ zoom_span(ctx, imgX, imgY, span,
+ (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
+}
+
+
+/**
+ * Zoom/write stencil values.
+ * No per-fragment operations are applied.
+ */
+void
+_swrast_write_zoomed_stencil_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLstencil stencil[])
+{
+ GLstencil zoomedVals[MAX_WIDTH];
+ GLint x0, x1, y0, y1, y;
+ GLint i, zoomedWidth;
+
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
+ }
+
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
+
+ /* zoom the span horizontally */
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals[i] = stencil[j];
+ }
+
+ /* write the zoomed spans */
+ for (y = y0; y < y1; y++) {
+ _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
+ }
+}
+
+
+/**
+ * Zoom/write z values (16 or 32-bit).
+ * No per-fragment operations are applied.
+ */
+void
+_swrast_write_zoomed_z_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLvoid *z)
+{
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
+ GLushort zoomedVals16[MAX_WIDTH];
+ GLuint zoomedVals32[MAX_WIDTH];
+ GLint x0, x1, y0, y1, y;
+ GLint i, zoomedWidth;
+
+ if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
+ &x0, &x1, &y0, &y1)) {
+ return; /* totally clipped */
+ }
+
+ zoomedWidth = x1 - x0;
+ ASSERT(zoomedWidth > 0);
+ ASSERT(zoomedWidth <= MAX_WIDTH);
+
+ /* zoom the span horizontally */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals16[i] = ((GLushort *) z)[j];
+ }
+ z = zoomedVals16;
+ }
+ else {
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (i = 0; i < zoomedWidth; i++) {
+ GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
+ ASSERT(j >= 0);
+ ASSERT(j < width);
+ zoomedVals32[i] = ((GLuint *) z)[j];
+ }
+ z = zoomedVals32;
+ }
+
+ /* write the zoomed spans */
+ for (y = y0; y < y1; y++) {
+ rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL);
+ }
+}
diff --git a/mesalib/src/mesa/swrast/s_zoom.h b/mesalib/src/mesa/swrast/s_zoom.h
new file mode 100644
index 000000000..d2815b41a
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_zoom.h
@@ -0,0 +1,59 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 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 S_ZOOM_H
+#define S_ZOOM_H
+
+#include "swrast.h"
+
+
+extern void
+_swrast_write_zoomed_rgba_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgba);
+
+extern void
+_swrast_write_zoomed_rgb_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span, const GLvoid *rgb);
+
+extern void
+_swrast_write_zoomed_index_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span);
+
+extern void
+_swrast_write_zoomed_depth_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ const SWspan *span);
+
+
+extern void
+_swrast_write_zoomed_stencil_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLstencil stencil[]);
+
+extern void
+_swrast_write_zoomed_z_span(GLcontext *ctx, GLint imgX, GLint imgY,
+ GLint width, GLint spanX, GLint spanY,
+ const GLvoid *z);
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast/swrast.h b/mesalib/src/mesa/swrast/swrast.h
new file mode 100644
index 000000000..c319ca62f
--- /dev/null
+++ b/mesalib/src/mesa/swrast/swrast.h
@@ -0,0 +1,292 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ *
+ */
+
+/**
+ * \file swrast/swrast.h
+ * \brief Public interface to the software rasterization functions.
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SWRAST_H
+#define SWRAST_H
+
+#include "main/mtypes.h"
+
+/**
+ * \struct SWvertex
+ * \brief Data-structure to handle vertices in the software rasterizer.
+ *
+ * The software rasterizer now uses this format for vertices. Thus a
+ * 'RasterSetup' stage or other translation is required between the
+ * tnl module and the swrast rasterization functions. This serves to
+ * isolate the swrast module from the internals of the tnl module, and
+ * improve its usefulness as a fallback mechanism for hardware
+ * drivers.
+ *
+ * wpos = attr[FRAG_ATTRIB_WPOS] and MUST BE THE FIRST values in the
+ * vertex because of the tnl clipping code.
+
+ * wpos[0] and [1] are the screen-coords of SWvertex.
+ * wpos[2] is the z-buffer coord (if 16-bit Z buffer, in range [0,65535]).
+ * wpos[3] is 1/w where w is the clip-space W coord. This is the value
+ * that clip{XYZ} were multiplied by to get ndc{XYZ}.
+ *
+ * Full software drivers:
+ * - Register the rastersetup and triangle functions from
+ * utils/software_helper.
+ * - On statechange, update the rasterization pointers in that module.
+ *
+ * Rasterization hardware drivers:
+ * - Keep native rastersetup.
+ * - Implement native twoside,offset and unfilled triangle setup.
+ * - Implement a translator from native vertices to swrast vertices.
+ * - On partial fallback (mix of accelerated and unaccelerated
+ * prims), call a pass-through function which translates native
+ * vertices to SWvertices and calls the appropriate swrast function.
+ * - On total fallback (vertex format insufficient for state or all
+ * primitives unaccelerated), hook in swrast_setup instead.
+ */
+typedef struct {
+ GLfloat attrib[FRAG_ATTRIB_MAX][4];
+ GLchan color[4]; /** integer color */
+ GLfloat pointSize;
+} SWvertex;
+
+
+/**
+ * Fixed point data type.
+ */
+typedef int GLfixed;
+
+
+#define FRAG_ATTRIB_CI FRAG_ATTRIB_COL0
+
+
+struct swrast_device_driver;
+
+
+/* These are the public-access functions exported from swrast.
+ */
+
+extern GLboolean
+_swrast_CreateContext( GLcontext *ctx );
+
+extern void
+_swrast_DestroyContext( GLcontext *ctx );
+
+/* Get a (non-const) reference to the device driver struct for swrast.
+ */
+extern struct swrast_device_driver *
+_swrast_GetDeviceDriverReference( GLcontext *ctx );
+
+extern void
+_swrast_Bitmap( GLcontext *ctx,
+ GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap );
+
+extern void
+_swrast_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy,
+ GLint destx, GLint desty,
+ GLsizei width, GLsizei height,
+ GLenum type );
+
+extern void
+_swrast_DrawPixels( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels );
+
+extern void
+_swrast_ReadPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ GLvoid *pixels );
+
+extern void
+_swrast_BlitFramebuffer(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+extern void
+_swrast_Clear(GLcontext *ctx, GLbitfield buffers);
+
+extern void
+_swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value);
+
+
+
+/* Reset the stipple counter
+ */
+extern void
+_swrast_ResetLineStipple( GLcontext *ctx );
+
+/**
+ * Indicates front/back facing for subsequent points/lines when drawing
+ * unfilled polygons. Needed for two-side stencil.
+ */
+extern void
+_swrast_SetFacing(GLcontext *ctx, GLuint facing);
+
+/* These will always render the correct point/line/triangle for the
+ * current state.
+ *
+ * For flatshaded primitives, the provoking vertex is the final one.
+ */
+extern void
+_swrast_Point( GLcontext *ctx, const SWvertex *v );
+
+extern void
+_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 );
+
+extern void
+_swrast_Triangle( GLcontext *ctx, const SWvertex *v0,
+ const SWvertex *v1, const SWvertex *v2 );
+
+extern void
+_swrast_Quad( GLcontext *ctx,
+ const SWvertex *v0, const SWvertex *v1,
+ const SWvertex *v2, const SWvertex *v3);
+
+extern void
+_swrast_flush( GLcontext *ctx );
+
+extern void
+_swrast_render_primitive( GLcontext *ctx, GLenum mode );
+
+extern void
+_swrast_render_start( GLcontext *ctx );
+
+extern void
+_swrast_render_finish( GLcontext *ctx );
+
+/* Tell the software rasterizer about core state changes.
+ */
+extern void
+_swrast_InvalidateState( GLcontext *ctx, GLbitfield new_state );
+
+/* Configure software rasterizer to match hardware rasterizer characteristics:
+ */
+extern void
+_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value );
+
+extern void
+_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value );
+
+/* Debug:
+ */
+extern void
+_swrast_print_vertex( GLcontext *ctx, const SWvertex *v );
+
+
+/*
+ * Imaging fallbacks (a better solution should be found, perhaps
+ * moving all the imaging fallback code to a new module)
+ */
+extern void
+_swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width,
+ GLsizei height);
+extern void
+_swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width);
+extern void
+_swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width);
+extern void
+_swrast_CopyColorTable( GLcontext *ctx,
+ GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width);
+
+
+/*
+ * Texture fallbacks. Could also live in a new module
+ * with the rest of the texture store fallbacks?
+ */
+extern void
+_swrast_copy_teximage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLint border);
+
+extern void
+_swrast_copy_teximage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border);
+
+
+extern void
+_swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width);
+
+extern void
+_swrast_copy_texsubimage2d(GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height);
+
+extern void
+_swrast_copy_texsubimage3d(GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+extern void
+_swrast_eject_texture_images(GLcontext *ctx);
+
+
+
+/**
+ * The driver interface for the software rasterizer.
+ * XXX this may go away.
+ * We may move these functions to ctx->Driver.RenderStart, RenderEnd.
+ */
+struct swrast_device_driver {
+ /*
+ * These are called before and after accessing renderbuffers during
+ * software rasterization.
+ *
+ * These are a suitable place for grabbing/releasing hardware locks.
+ *
+ * NOTE: The swrast triangle/line/point routines *DO NOT* call
+ * these functions. Locking in that case must be organized by the
+ * driver by other mechanisms.
+ */
+ void (*SpanRenderStart)(GLcontext *ctx);
+ void (*SpanRenderFinish)(GLcontext *ctx);
+};
+
+
+
+#endif
diff --git a/mesalib/src/mesa/swrast_setup/descrip.mms b/mesalib/src/mesa/swrast_setup/descrip.mms
new file mode 100644
index 000000000..32ffd8073
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/descrip.mms
@@ -0,0 +1,42 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define tnl [-.tnl]
+ define vbo [-.vbo]
+ define swrast [-.swrast]
+ define array_cache [-.array_cache]
+ define glapi [-.glapi]
+ define main [-.main]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.main],[-.glapi]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = ss_context.c ss_triangle.c
+
+OBJECTS = ss_context.obj,ss_triangle.obj
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+ss_context.obj : ss_context.c
+ss_triangle.obj : ss_triangle.c
diff --git a/mesalib/src/mesa/swrast_setup/ss_context.c b/mesalib/src/mesa/swrast_setup/ss_context.c
new file mode 100644
index 000000000..61172f997
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_context.c
@@ -0,0 +1,317 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/colormac.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+#include "swrast_setup.h"
+#include "ss_context.h"
+#include "ss_triangle.h"
+
+
+/* Need to check lighting state and vertex program state to know
+ * if two-sided lighting is in effect.
+ */
+#define _SWSETUP_NEW_RENDERINDEX (_NEW_POLYGON|_NEW_LIGHT|_NEW_PROGRAM)
+
+
+#define VARYING_EMIT_STYLE EMIT_4F
+
+
+GLboolean
+_swsetup_CreateContext( GLcontext *ctx )
+{
+ SScontext *swsetup = (SScontext *)CALLOC(sizeof(SScontext));
+
+ if (!swsetup)
+ return GL_FALSE;
+
+ ctx->swsetup_context = swsetup;
+
+ swsetup->NewState = ~0;
+ _swsetup_trifuncs_init( ctx );
+
+ _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
+ sizeof(SWvertex) );
+
+
+ return GL_TRUE;
+}
+
+void
+_swsetup_DestroyContext( GLcontext *ctx )
+{
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+
+ if (swsetup) {
+ FREE(swsetup);
+ ctx->swsetup_context = 0;
+ }
+
+ _tnl_free_vertices( ctx );
+}
+
+static void
+_swsetup_RenderPrimitive( GLcontext *ctx, GLenum mode )
+{
+ SWSETUP_CONTEXT(ctx)->render_prim = mode;
+ _swrast_render_primitive( ctx, mode );
+}
+
+
+/**
+ * Helper macros for setup_vertex_format()
+ */
+#define SWZ ((SWvertex *)0)
+#define SWOffset(MEMBER) (((char *)&(SWZ->MEMBER)) - ((char *)SWZ))
+
+#define EMIT_ATTR( ATTR, STYLE, MEMBER ) \
+do { \
+ map[e].attrib = (ATTR); \
+ map[e].format = (STYLE); \
+ map[e].offset = SWOffset(MEMBER); \
+ e++; \
+} while (0)
+
+
+/**
+ * Tell the tnl module how to build SWvertex objects for swrast.
+ * We'll build the map[] array with that info and pass it to
+ * _tnl_install_attrs().
+ */
+static void
+setup_vertex_format(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+ GLboolean intColors = !ctx->FragmentProgram._Current
+ && !ctx->ATIFragmentShader._Enabled
+ && ctx->RenderMode == GL_RENDER
+ && CHAN_TYPE == GL_UNSIGNED_BYTE;
+
+ if (intColors != swsetup->intColors ||
+ !RENDERINPUTS_EQUAL(tnl->render_inputs_bitset,
+ swsetup->last_index_bitset)) {
+ DECLARE_RENDERINPUTS(index_bitset);
+ struct tnl_attr_map map[_TNL_ATTRIB_MAX];
+ int i, e = 0;
+
+ swsetup->intColors = intColors;
+
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
+ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[FRAG_ATTRIB_WPOS] );
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR0 )) {
+ if (swsetup->intColors)
+ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4CHAN_4F_RGBA, color );
+ else
+ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F, attrib[FRAG_ATTRIB_COL0]);
+ }
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F, attrib[FRAG_ATTRIB_COL1]);
+ }
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR_INDEX )) {
+ EMIT_ATTR( _TNL_ATTRIB_COLOR_INDEX, EMIT_1F,
+ attrib[FRAG_ATTRIB_CI][0] );
+ }
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+ const GLint emit = ctx->FragmentProgram._Current ? EMIT_4F : EMIT_1F;
+ EMIT_ATTR( _TNL_ATTRIB_FOG, emit, attrib[FRAG_ATTRIB_FOGC]);
+ }
+
+ if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX))
+ {
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
+ EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F,
+ attrib[FRAG_ATTRIB_TEX0 + i] );
+ }
+ }
+ }
+
+ /* shader varying vars */
+ if (RENDERINPUTS_TEST_RANGE( index_bitset,
+ _TNL_FIRST_GENERIC, _TNL_LAST_GENERIC )) {
+ for (i = 0; i < ctx->Const.MaxVarying; i++) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_GENERIC(i) )) {
+ EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE,
+ attrib[FRAG_ATTRIB_VAR0 + i] );
+ }
+ }
+ }
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE ))
+ EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize );
+
+ _tnl_install_attrs( ctx, map, e,
+ ctx->Viewport._WindowMap.m,
+ sizeof(SWvertex) );
+
+ RENDERINPUTS_COPY( swsetup->last_index_bitset, index_bitset );
+ }
+}
+
+
+/**
+ * Prepare to render a vertex buffer.
+ * Called via tnl->Driver.Render.Start.
+ */
+static void
+_swsetup_RenderStart( GLcontext *ctx )
+{
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ if (swsetup->NewState & _SWSETUP_NEW_RENDERINDEX) {
+ _swsetup_choose_trifuncs(ctx);
+ }
+
+ if (swsetup->NewState & _NEW_PROGRAM) {
+ RENDERINPUTS_ZERO( swsetup->last_index_bitset );
+ }
+
+ swsetup->NewState = 0;
+
+ /* This will change if drawing unfilled tris */
+ _swrast_SetFacing(ctx, 0);
+
+ _swrast_render_start(ctx);
+
+ /* Important */
+ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+
+ setup_vertex_format(ctx);
+}
+
+
+/*
+ * We patch this function into tnl->Driver.Render.Finish.
+ * It's called when we finish rendering a vertex buffer.
+ */
+static void
+_swsetup_RenderFinish( GLcontext *ctx )
+{
+ _swrast_render_finish( ctx );
+}
+
+void
+_swsetup_InvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+ swsetup->NewState |= new_state;
+ _tnl_invalidate_vertex_state( ctx, new_state );
+}
+
+
+void
+_swsetup_Wakeup( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+
+ tnl->Driver.Render.Start = _swsetup_RenderStart;
+ tnl->Driver.Render.Finish = _swsetup_RenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = _swsetup_RenderPrimitive;
+ tnl->Driver.Render.Interp = _tnl_interp;
+ tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; /* new */
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; /* new */
+ /* points */
+ /* line */
+ /* triangle */
+ /* quad */
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+ tnl->Driver.Render.Multipass = 0;
+
+ _tnl_invalidate_vertices( ctx, ~0 );
+ _tnl_need_projected_coords( ctx, GL_TRUE );
+ _swsetup_InvalidateState( ctx, ~0 );
+
+ swsetup->verts = (SWvertex *)tnl->clipspace.vertex_buf;
+ RENDERINPUTS_ZERO( swsetup->last_index_bitset );
+}
+
+
+/**
+ * Populate a swrast SWvertex from an attrib-style vertex.
+ */
+void
+_swsetup_Translate( GLcontext *ctx, const void *vertex, SWvertex *dest )
+{
+ const GLfloat *m = ctx->Viewport._WindowMap.m;
+ GLfloat tmp[4];
+ GLuint i;
+
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POS, tmp );
+
+ dest->attrib[FRAG_ATTRIB_WPOS][0] = m[0] * tmp[0] + m[12];
+ dest->attrib[FRAG_ATTRIB_WPOS][1] = m[5] * tmp[1] + m[13];
+ dest->attrib[FRAG_ATTRIB_WPOS][2] = m[10] * tmp[2] + m[14];
+ dest->attrib[FRAG_ATTRIB_WPOS][3] = tmp[3];
+
+ /** XXX try to limit these loops someday */
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0 + i,
+ dest->attrib[FRAG_ATTRIB_TEX0 + i] );
+
+ for (i = 0 ; i < ctx->Const.MaxVarying ; i++)
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_GENERIC0 + i,
+ dest->attrib[FRAG_ATTRIB_VAR0 + i] );
+
+ if (ctx->Visual.rgbMode) {
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0,
+ dest->attrib[FRAG_ATTRIB_COL0] );
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( dest->color, tmp );
+
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR1,
+ dest->attrib[FRAG_ATTRIB_COL1]);
+ }
+ else {
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR_INDEX, tmp );
+ dest->attrib[FRAG_ATTRIB_CI][0] = tmp[0];
+ }
+
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_FOG, tmp );
+ dest->attrib[FRAG_ATTRIB_FOGC][0] = tmp[0];
+
+ /* XXX See _tnl_get_attr about pointsize ... */
+ _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POINTSIZE, tmp );
+ dest->pointSize = tmp[0];
+}
+
diff --git a/mesalib/src/mesa/swrast_setup/ss_context.h b/mesalib/src/mesa/swrast_setup/ss_context.h
new file mode 100644
index 000000000..1ec293fad
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_context.h
@@ -0,0 +1,46 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SS_CONTEXT_H
+#define SS_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "swrast/swrast.h"
+#include "swrast_setup.h"
+#include "tnl/t_context.h"
+
+typedef struct {
+ GLuint NewState;
+ GLenum render_prim;
+ DECLARE_RENDERINPUTS(last_index_bitset);
+ SWvertex *verts;
+ GLboolean intColors;
+} SScontext;
+
+#define SWSETUP_CONTEXT(ctx) ((SScontext *)ctx->swsetup_context)
+
+#endif
diff --git a/mesalib/src/mesa/swrast_setup/ss_triangle.c b/mesalib/src/mesa/swrast_setup/ss_triangle.c
new file mode 100644
index 000000000..e15b1348d
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_triangle.c
@@ -0,0 +1,317 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+
+#include "tnl/t_context.h"
+
+#include "ss_triangle.h"
+#include "ss_context.h"
+
+#define SS_RGBA_BIT 0x1
+#define SS_OFFSET_BIT 0x2
+#define SS_TWOSIDE_BIT 0x4
+#define SS_UNFILLED_BIT 0x8
+#define SS_MAX_TRIFUNC 0x10
+
+static tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
+static tnl_quad_func quad_tab[SS_MAX_TRIFUNC];
+
+
+/*
+ * Render a triangle respecting edge flags.
+ */
+typedef void (* swsetup_edge_render_prim_tri)(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2);
+
+/*
+ * Render a triangle using lines and respecting edge flags.
+ */
+static void
+_swsetup_edge_render_line_tri(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+
+ if (swsetup->render_prim == GL_POLYGON) {
+ if (ef[e2]) _swrast_Line( ctx, v2, v0 );
+ if (ef[e0]) _swrast_Line( ctx, v0, v1 );
+ if (ef[e1]) _swrast_Line( ctx, v1, v2 );
+ } else {
+ if (ef[e0]) _swrast_Line( ctx, v0, v1 );
+ if (ef[e1]) _swrast_Line( ctx, v1, v2 );
+ if (ef[e2]) _swrast_Line( ctx, v2, v0 );
+ }
+}
+
+/*
+ * Render a triangle using points and respecting edge flags.
+ */
+static void
+_swsetup_edge_render_point_tri(GLcontext *ctx,
+ const GLubyte *ef,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ const SWvertex *v0,
+ const SWvertex *v1,
+ const SWvertex *v2)
+{
+ if (ef[e0]) _swrast_Point( ctx, v0 );
+ if (ef[e1]) _swrast_Point( ctx, v1 );
+ if (ef[e2]) _swrast_Point( ctx, v2 );
+
+ _swrast_flush(ctx);
+}
+
+/*
+ * Render a triangle respecting cull and shade model.
+ */
+static void _swsetup_render_tri(GLcontext *ctx,
+ GLuint e0,
+ GLuint e1,
+ GLuint e2,
+ GLuint facing,
+ swsetup_edge_render_prim_tri render)
+{
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLubyte *ef = VB->EdgeFlag;
+ SWvertex *verts = swsetup->verts;
+ SWvertex *v0 = &verts[e0];
+ SWvertex *v1 = &verts[e1];
+ SWvertex *v2 = &verts[e2];
+
+ /* cull testing */
+ if (ctx->Polygon.CullFlag) {
+ if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
+ return;
+ if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
+ return;
+ }
+
+ _swrast_SetFacing(ctx, facing);
+
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ GLchan c[2][4];
+ GLfloat s[2][4];
+ GLfloat i[2];
+
+ /* save colors/indexes for v0, v1 vertices */
+ COPY_CHAN4(c[0], v0->color);
+ COPY_CHAN4(c[1], v1->color);
+ COPY_4V(s[0], v0->attrib[FRAG_ATTRIB_COL1]);
+ COPY_4V(s[1], v1->attrib[FRAG_ATTRIB_COL1]);
+ i[0] = v0->attrib[FRAG_ATTRIB_CI][0];
+ i[1] = v1->attrib[FRAG_ATTRIB_CI][0];
+
+ /* copy v2 color/indexes to v0, v1 indexes */
+ COPY_CHAN4(v0->color, v2->color);
+ COPY_CHAN4(v1->color, v2->color);
+ COPY_4V(v0->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]);
+ COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], v2->attrib[FRAG_ATTRIB_COL1]);
+ v0->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
+ v1->attrib[FRAG_ATTRIB_CI][0] = v2->attrib[FRAG_ATTRIB_CI][0];
+
+ render(ctx, ef, e0, e1, e2, v0, v1, v2);
+
+ COPY_CHAN4(v0->color, c[0]);
+ COPY_CHAN4(v1->color, c[1]);
+ COPY_4V(v0->attrib[FRAG_ATTRIB_COL1], s[0]);
+ COPY_4V(v1->attrib[FRAG_ATTRIB_COL1], s[1]);
+ v0->attrib[FRAG_ATTRIB_CI][0] = i[0];
+ v1->attrib[FRAG_ATTRIB_CI][0] = i[1];
+ }
+ else {
+ render(ctx, ef, e0, e1, e2, v0, v1, v2);
+ }
+}
+
+#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
+#define SS_SPEC(a,b) UNCLAMPED_FLOAT_TO_RGB_CHAN(a,b)
+#define SS_IND(a,b) (a = b)
+
+#define IND (0)
+#define TAG(x) x
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "ss_tritmp.h"
+
+#define IND (SS_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
+#define TAG(x) x##_offset_twoside
+#include "ss_tritmp.h"
+
+#define IND (SS_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "ss_tritmp.h"
+
+#define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
+#define TAG(x) x##_offset_twoside_unfilled
+#include "ss_tritmp.h"
+
+#define IND (0|SS_RGBA_BIT)
+#define TAG(x) x##_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_offset_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_TWOSIDE_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_twoside_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_offset_twoside_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_UNFILLED_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_unfilled_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_offset_unfilled_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_twoside_unfilled_rgba
+#include "ss_tritmp.h"
+
+#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT|SS_RGBA_BIT)
+#define TAG(x) x##_offset_twoside_unfilled_rgba
+#include "ss_tritmp.h"
+
+
+void _swsetup_trifuncs_init( GLcontext *ctx )
+{
+ (void) ctx;
+
+ init();
+ init_offset();
+ init_twoside();
+ init_offset_twoside();
+ init_unfilled();
+ init_offset_unfilled();
+ init_twoside_unfilled();
+ init_offset_twoside_unfilled();
+
+ init_rgba();
+ init_offset_rgba();
+ init_twoside_rgba();
+ init_offset_twoside_rgba();
+ init_unfilled_rgba();
+ init_offset_unfilled_rgba();
+ init_twoside_unfilled_rgba();
+ init_offset_twoside_unfilled_rgba();
+}
+
+
+static void swsetup_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ GLuint i;
+
+ if (VB->Elts) {
+ for (i = first; i < last; i++)
+ if (VB->ClipMask[VB->Elts[i]] == 0)
+ _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ }
+ else {
+ for (i = first; i < last; i++)
+ if (VB->ClipMask[i] == 0)
+ _swrast_Point( ctx, &verts[i] );
+ }
+}
+
+static void swsetup_line( GLcontext *ctx, GLuint v0, GLuint v1 )
+{
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ _swrast_Line( ctx, &verts[v0], &verts[v1] );
+}
+
+
+
+void _swsetup_choose_trifuncs( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint ind = 0;
+
+ if (ctx->Polygon.OffsetPoint ||
+ ctx->Polygon.OffsetLine ||
+ ctx->Polygon.OffsetFill)
+ ind |= SS_OFFSET_BIT;
+
+ if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
+ (ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
+ ind |= SS_TWOSIDE_BIT;
+
+ /* We piggyback the two-sided stencil front/back determination on the
+ * unfilled triangle path.
+ */
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL ||
+ (ctx->Stencil.Enabled && ctx->Stencil._TestTwoSide))
+ ind |= SS_UNFILLED_BIT;
+
+ if (ctx->Visual.rgbMode)
+ ind |= SS_RGBA_BIT;
+
+ tnl->Driver.Render.Triangle = tri_tab[ind];
+ tnl->Driver.Render.Quad = quad_tab[ind];
+ tnl->Driver.Render.Line = swsetup_line;
+ tnl->Driver.Render.Points = swsetup_points;
+}
diff --git a/mesalib/src/mesa/swrast_setup/ss_triangle.h b/mesalib/src/mesa/swrast_setup/ss_triangle.h
new file mode 100644
index 000000000..007fa2e91
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_triangle.h
@@ -0,0 +1,38 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SS_TRIANGLE_H
+#define SS_TRIANGLE_H
+
+#include "ss_context.h"
+
+
+void _swsetup_trifuncs_init( GLcontext *ctx );
+void _swsetup_choose_trifuncs( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/swrast_setup/ss_tritmp.h b/mesalib/src/mesa/swrast_setup/ss_tritmp.h
new file mode 100644
index 000000000..724b5e94f
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_tritmp.h
@@ -0,0 +1,266 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/**
+ * This is where we handle assigning vertex colors based on front/back
+ * facing, compute polygon offset and handle glPolygonMode().
+ */
+static void TAG(triangle)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2 )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ SScontext *swsetup = SWSETUP_CONTEXT(ctx);
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ SWvertex *v[3];
+ GLfloat z[3];
+ GLfloat offset, oz0, oz1, oz2;
+ GLenum mode = GL_FILL;
+ GLuint facing = 0;
+ GLchan saved_color[3][4];
+ GLfloat saved_col0[3][4];
+ GLfloat saved_spec[3][4];
+ GLfloat saved_index[3];
+
+ v[0] = &verts[e0];
+ v[1] = &verts[e1];
+ v[2] = &verts[e2];
+
+ if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
+ {
+ GLfloat ex = v[0]->attrib[FRAG_ATTRIB_WPOS][0] - v[2]->attrib[FRAG_ATTRIB_WPOS][0];
+ GLfloat ey = v[0]->attrib[FRAG_ATTRIB_WPOS][1] - v[2]->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat fx = v[1]->attrib[FRAG_ATTRIB_WPOS][0] - v[2]->attrib[FRAG_ATTRIB_WPOS][0];
+ GLfloat fy = v[1]->attrib[FRAG_ATTRIB_WPOS][1] - v[2]->attrib[FRAG_ATTRIB_WPOS][1];
+ GLfloat cc = ex*fy - ey*fx;
+
+ if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
+ {
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit;
+
+ if (IND & SS_UNFILLED_BIT)
+ mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
+
+ if (facing == 1) {
+ if (IND & SS_TWOSIDE_BIT) {
+ if (IND & SS_RGBA_BIT) {
+ if (VB->ColorPtr[1]) {
+ GLfloat (*vbcolor)[4] = VB->ColorPtr[1]->data;
+
+ if (swsetup->intColors) {
+ COPY_CHAN4(saved_color[0], v[0]->color);
+ COPY_CHAN4(saved_color[1], v[1]->color);
+ COPY_CHAN4(saved_color[2], v[2]->color);
+ }
+ else {
+ COPY_4V(saved_col0[0], v[0]->attrib[FRAG_ATTRIB_COL0]);
+ COPY_4V(saved_col0[1], v[1]->attrib[FRAG_ATTRIB_COL0]);
+ COPY_4V(saved_col0[2], v[2]->attrib[FRAG_ATTRIB_COL0]);
+ }
+
+ if (VB->ColorPtr[1]->stride) {
+ if (swsetup->intColors) {
+ SS_COLOR(v[0]->color, vbcolor[e0]);
+ SS_COLOR(v[1]->color, vbcolor[e1]);
+ SS_COLOR(v[2]->color, vbcolor[e2]);
+ }
+ else {
+ COPY_4V(v[0]->attrib[FRAG_ATTRIB_COL0], vbcolor[e0]);
+ COPY_4V(v[1]->attrib[FRAG_ATTRIB_COL0], vbcolor[e1]);
+ COPY_4V(v[2]->attrib[FRAG_ATTRIB_COL0], vbcolor[e2]);
+ }
+ }
+ else {
+ /* flat shade */
+ if (swsetup->intColors) {
+ SS_COLOR(v[0]->color, vbcolor[0]);
+ SS_COLOR(v[1]->color, vbcolor[0]);
+ SS_COLOR(v[2]->color, vbcolor[0]);
+ }
+ else {
+ COPY_4V(v[0]->attrib[FRAG_ATTRIB_COL0], vbcolor[0]);
+ COPY_4V(v[1]->attrib[FRAG_ATTRIB_COL0], vbcolor[0]);
+ COPY_4V(v[2]->attrib[FRAG_ATTRIB_COL0], vbcolor[0]);
+ }
+ }
+ }
+
+ if (VB->SecondaryColorPtr[1]) {
+ GLfloat (*vbspec)[4] = VB->SecondaryColorPtr[1]->data;
+
+ COPY_4V(saved_spec[0], v[0]->attrib[FRAG_ATTRIB_COL1]);
+ COPY_4V(saved_spec[1], v[1]->attrib[FRAG_ATTRIB_COL1]);
+ COPY_4V(saved_spec[2], v[2]->attrib[FRAG_ATTRIB_COL1]);
+
+ if (VB->SecondaryColorPtr[1]->stride) {
+ SS_SPEC(v[0]->attrib[FRAG_ATTRIB_COL1], vbspec[e0]);
+ SS_SPEC(v[1]->attrib[FRAG_ATTRIB_COL1], vbspec[e1]);
+ SS_SPEC(v[2]->attrib[FRAG_ATTRIB_COL1], vbspec[e2]);
+ }
+ else {
+ SS_SPEC(v[0]->attrib[FRAG_ATTRIB_COL1], vbspec[0]);
+ SS_SPEC(v[1]->attrib[FRAG_ATTRIB_COL1], vbspec[0]);
+ SS_SPEC(v[2]->attrib[FRAG_ATTRIB_COL1], vbspec[0]);
+ }
+ }
+ } else {
+ GLfloat *vbindex = (GLfloat *)VB->IndexPtr[1]->data;
+ saved_index[0] = v[0]->attrib[FRAG_ATTRIB_CI][0];
+ saved_index[1] = v[1]->attrib[FRAG_ATTRIB_CI][0];
+ saved_index[2] = v[2]->attrib[FRAG_ATTRIB_CI][0];
+
+ SS_IND(v[0]->attrib[FRAG_ATTRIB_CI][0], (GLuint) vbindex[e0]);
+ SS_IND(v[1]->attrib[FRAG_ATTRIB_CI][0], (GLuint) vbindex[e1]);
+ SS_IND(v[2]->attrib[FRAG_ATTRIB_CI][0], (GLuint) vbindex[e2]);
+ }
+ }
+ }
+ }
+
+ if (IND & SS_OFFSET_BIT) {
+ const GLfloat max = ctx->DrawBuffer->_DepthMaxF;
+ /* save original Z values (restored later) */
+ z[0] = v[0]->attrib[FRAG_ATTRIB_WPOS][2];
+ z[1] = v[1]->attrib[FRAG_ATTRIB_WPOS][2];
+ z[2] = v[2]->attrib[FRAG_ATTRIB_WPOS][2];
+ /* Note that Z values are already scaled to [0,65535] (for example)
+ * so no MRD value is used here.
+ */
+ offset = ctx->Polygon.OffsetUnits;
+ if (cc * cc > 1e-16) {
+ const GLfloat ez = z[0] - z[2];
+ const GLfloat fz = z[1] - z[2];
+ const GLfloat oneOverArea = 1.0F / cc;
+ const GLfloat dzdx = FABSF((ey * fz - ez * fy) * oneOverArea);
+ const GLfloat dzdy = FABSF((ez * fx - ex * fz) * oneOverArea);
+ offset += MAX2(dzdx, dzdy) * ctx->Polygon.OffsetFactor;
+ }
+ /* new Z values */
+ oz0 = CLAMP(v[0]->attrib[FRAG_ATTRIB_WPOS][2] + offset, 0.0, max);
+ oz1 = CLAMP(v[1]->attrib[FRAG_ATTRIB_WPOS][2] + offset, 0.0, max);
+ oz2 = CLAMP(v[2]->attrib[FRAG_ATTRIB_WPOS][2] + offset, 0.0, max);
+ }
+ }
+
+ if (mode == GL_POINT) {
+ if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
+ v[0]->attrib[FRAG_ATTRIB_WPOS][2] = oz0;
+ v[1]->attrib[FRAG_ATTRIB_WPOS][2] = oz1;
+ v[2]->attrib[FRAG_ATTRIB_WPOS][2] = oz2;
+ }
+ _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
+ } else if (mode == GL_LINE) {
+ if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
+ v[0]->attrib[FRAG_ATTRIB_WPOS][2] = oz0;
+ v[1]->attrib[FRAG_ATTRIB_WPOS][2] = oz1;
+ v[2]->attrib[FRAG_ATTRIB_WPOS][2] = oz2;
+ }
+ _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
+ } else {
+ if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
+ v[0]->attrib[FRAG_ATTRIB_WPOS][2] = oz0;
+ v[1]->attrib[FRAG_ATTRIB_WPOS][2] = oz1;
+ v[2]->attrib[FRAG_ATTRIB_WPOS][2] = oz2;
+ }
+ _swrast_Triangle( ctx, v[0], v[1], v[2] );
+ }
+
+ /*
+ * Restore original vertex colors, etc.
+ */
+ if (IND & SS_OFFSET_BIT) {
+ v[0]->attrib[FRAG_ATTRIB_WPOS][2] = z[0];
+ v[1]->attrib[FRAG_ATTRIB_WPOS][2] = z[1];
+ v[2]->attrib[FRAG_ATTRIB_WPOS][2] = z[2];
+ }
+
+ if (IND & SS_TWOSIDE_BIT) {
+ if (facing == 1) {
+ if (IND & SS_RGBA_BIT) {
+ if (VB->ColorPtr[1]) {
+ if (swsetup->intColors) {
+ COPY_CHAN4(v[0]->color, saved_color[0]);
+ COPY_CHAN4(v[1]->color, saved_color[1]);
+ COPY_CHAN4(v[2]->color, saved_color[2]);
+ }
+ else {
+ COPY_4V(v[0]->attrib[FRAG_ATTRIB_COL0], saved_col0[0]);
+ COPY_4V(v[1]->attrib[FRAG_ATTRIB_COL0], saved_col0[1]);
+ COPY_4V(v[2]->attrib[FRAG_ATTRIB_COL0], saved_col0[2]);
+ }
+ }
+
+ if (VB->SecondaryColorPtr[1]) {
+ COPY_4V(v[0]->attrib[FRAG_ATTRIB_COL1], saved_spec[0]);
+ COPY_4V(v[1]->attrib[FRAG_ATTRIB_COL1], saved_spec[1]);
+ COPY_4V(v[2]->attrib[FRAG_ATTRIB_COL1], saved_spec[2]);
+ }
+ } else {
+ v[0]->attrib[FRAG_ATTRIB_CI][0] = saved_index[0];
+ v[1]->attrib[FRAG_ATTRIB_CI][0] = saved_index[1];
+ v[2]->attrib[FRAG_ATTRIB_CI][0] = saved_index[2];
+ }
+ }
+ }
+}
+
+
+
+/* Need to fixup edgeflags when decomposing to triangles:
+ */
+static void TAG(quadfunc)( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint v3 )
+{
+ if (IND & SS_UNFILLED_BIT) {
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ if (VB->EdgeFlag) { /* XXX this test shouldn't be needed (bug 12614) */
+ GLubyte ef1 = VB->EdgeFlag[v1];
+ GLubyte ef3 = VB->EdgeFlag[v3];
+ VB->EdgeFlag[v1] = 0;
+ TAG(triangle)( ctx, v0, v1, v3 );
+ VB->EdgeFlag[v1] = ef1;
+ VB->EdgeFlag[v3] = 0;
+ TAG(triangle)( ctx, v1, v2, v3 );
+ VB->EdgeFlag[v3] = ef3;
+ }
+ } else {
+ TAG(triangle)( ctx, v0, v1, v3 );
+ TAG(triangle)( ctx, v1, v2, v3 );
+ }
+}
+
+
+
+
+static void TAG(init)( void )
+{
+ tri_tab[IND] = TAG(triangle);
+ quad_tab[IND] = TAG(quadfunc);
+}
+
+
+#undef IND
+#undef TAG
diff --git a/mesalib/src/mesa/swrast_setup/ss_vb.h b/mesalib/src/mesa/swrast_setup/ss_vb.h
new file mode 100644
index 000000000..2ad1f56f3
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/ss_vb.h
@@ -0,0 +1,38 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SS_VB_H
+#define SS_VB_H
+
+#include "main/mtypes.h"
+#include "swrast_setup.h"
+
+void _swsetup_vb_init( GLcontext *ctx );
+void _swsetup_choose_rastersetup_func( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/swrast_setup/swrast_setup.h b/mesalib/src/mesa/swrast_setup/swrast_setup.h
new file mode 100644
index 000000000..5dcbe2675
--- /dev/null
+++ b/mesalib/src/mesa/swrast_setup/swrast_setup.h
@@ -0,0 +1,61 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Public interface to the swrast_setup module. This module provides
+ * an implementation of the driver interface to t_vb_render.c, and uses
+ * the software rasterizer (swrast) to perform actual rasterization.
+ *
+ * The internals of the implementation are private, but can be hooked
+ * into tnl at any time (except between RenderStart/RenderEnd) by
+ * calling _swsetup_Wakeup().
+ */
+
+#ifndef SWRAST_SETUP_H
+#define SWRAST_SETUP_H
+
+#include "swrast/swrast.h"
+
+extern GLboolean
+_swsetup_CreateContext( GLcontext *ctx );
+
+extern void
+_swsetup_DestroyContext( GLcontext *ctx );
+
+extern void
+_swsetup_InvalidateState( GLcontext *ctx, GLuint new_state );
+
+extern void
+_swsetup_Wakeup( GLcontext *ctx );
+
+/* Helper function to translate a hardware vertex (as understood by
+ * the tnl/t_vertex.c code) to a swrast vertex.
+ */
+extern void
+_swsetup_Translate( GLcontext *ctx, const void *vertex, SWvertex *dest );
+
+#endif
diff --git a/mesalib/src/mesa/tnl/descrip.mms b/mesalib/src/mesa/tnl/descrip.mms
new file mode 100644
index 000000000..25dd1aecb
--- /dev/null
+++ b/mesalib/src/mesa/tnl/descrip.mms
@@ -0,0 +1,68 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 39 September 2008
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define vbo [-.vbo]
+ define shader [-.shader]
+ define swrast [-.swrast]
+ define array_cache [-.array_cache]
+ define main [-.main]
+ define glapi [-.glapi]
+ define tnl [-.tnl]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES = t_context.c t_draw.c \
+ t_pipeline.c t_vb_fog.c \
+ t_vb_light.c t_vb_normals.c t_vb_points.c t_vb_program.c \
+ t_vb_render.c t_vb_texgen.c t_vb_texmat.c t_vb_vertex.c \
+ t_vertex.c t_rasterpos.c\
+ t_vertex_generic.c t_vp_build.c
+
+OBJECTS = t_context.obj,t_draw.obj,\
+ t_pipeline.obj,t_vb_fog.obj,t_vb_light.obj,t_vb_normals.obj,\
+ t_vb_points.obj,t_vb_program.obj,t_vb_render.obj,t_vb_texgen.obj,\
+ t_vb_texmat.obj,t_vb_vertex.obj,t_rasterpos.obj,\
+ t_vertex.obj,t_vertex_generic.obj,\
+ t_vp_build.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+t_context.obj : t_context.c
+t_draw.obj : t_draw.c
+t_pipeline.obj : t_pipeline.c
+t_vb_fog.obj : t_vb_fog.c
+t_vb_light.obj : t_vb_light.c
+t_vb_normals.obj : t_vb_normals.c
+t_vb_points.obj : t_vb_points.c
+t_vb_program.obj : t_vb_program.c
+t_vb_render.obj : t_vb_render.c
+t_vb_texgen.obj : t_vb_texgen.c
+t_vb_texmat.obj : t_vb_texmat.c
+t_vb_vertex.obj : t_vb_vertex.c
+t_vertex.obj : t_vertex.c
+t_vertex_generic.obj : t_vertex_generic.c
+t_vp_build.obj : t_vp_build.c
+t_rasterpos.obj : t_rasterpos.c
diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c
new file mode 100644
index 000000000..f2771cde0
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_context.c
@@ -0,0 +1,231 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/light.h"
+#include "math/m_translate.h"
+#include "math/m_xform.h"
+
+#include "tnl.h"
+#include "t_context.h"
+#include "t_pipeline.h"
+#include "t_vp_build.h"
+
+#include "vbo/vbo.h"
+
+GLboolean
+_tnl_CreateContext( GLcontext *ctx )
+{
+ TNLcontext *tnl;
+
+ /* Create the TNLcontext structure
+ */
+ ctx->swtnl_context = tnl = (TNLcontext *) CALLOC( sizeof(TNLcontext) );
+
+ if (!tnl) {
+ return GL_FALSE;
+ }
+
+ /* Initialize the VB.
+ */
+ tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES;
+
+
+ /* Initialize tnl state.
+ */
+ if (ctx->VertexProgram._MaintainTnlProgram) {
+ _tnl_install_pipeline( ctx, _tnl_vp_pipeline );
+ } else {
+ _tnl_install_pipeline( ctx, _tnl_default_pipeline );
+ }
+
+ tnl->NeedNdcCoords = GL_TRUE;
+ tnl->AllowVertexFog = GL_TRUE;
+ tnl->AllowPixelFog = GL_TRUE;
+
+ /* Set a few default values in the driver struct.
+ */
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
+
+ tnl->nr_blocks = 0;
+
+ /* plug in the VBO drawing function */
+ vbo_set_draw_func(ctx, _tnl_vbo_draw_prims);
+
+ _math_init_transformation();
+ _math_init_translate();
+
+ return GL_TRUE;
+}
+
+
+void
+_tnl_DestroyContext( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ _tnl_destroy_pipeline( ctx );
+
+ FREE(tnl);
+ ctx->swtnl_context = NULL;
+}
+
+
+void
+_tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ const struct gl_vertex_program *vp = ctx->VertexProgram._Current;
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+
+ if (new_state & (_NEW_HINT | _NEW_PROGRAM)) {
+ ASSERT(tnl->AllowVertexFog || tnl->AllowPixelFog);
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !fp;
+ }
+
+ tnl->pipeline.new_state |= new_state;
+
+ /* Calculate tnl->render_inputs. This bitmask indicates which vertex
+ * attributes need to be emitted to the rasterizer.
+ */
+ if (ctx->Visual.rgbMode) {
+ GLuint i;
+
+ RENDERINPUTS_ZERO( tnl->render_inputs_bitset );
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS );
+
+ if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) {
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 );
+ }
+
+ if (NEED_SECONDARY_COLOR(ctx))
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 );
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
+ (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) {
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) );
+ }
+ }
+ }
+ else {
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS );
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR_INDEX );
+ }
+
+ if (ctx->Fog.Enabled) {
+ /* fixed-function fog */
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
+ }
+ else if (fp) {
+ if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) {
+ /* fragment program needs fog coord */
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
+ }
+ }
+
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_EDGEFLAG );
+
+ if (ctx->RenderMode == GL_FEEDBACK)
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 );
+
+ if (ctx->Point._Attenuated ||
+ (ctx->VertexProgram._Enabled && ctx->VertexProgram.PointSizeEnabled))
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POINTSIZE );
+
+ /* check for varying vars which are written by the vertex program */
+ if (vp) {
+ GLuint i;
+ for (i = 0; i < MAX_VARYING; i++) {
+ if (vp->Base.OutputsWritten & (1 << (VERT_RESULT_VAR0 + i))) {
+ RENDERINPUTS_SET(tnl->render_inputs_bitset,
+ _TNL_ATTRIB_GENERIC(i));
+ }
+ }
+ }
+}
+
+
+void
+_tnl_wakeup( GLcontext *ctx )
+{
+ /* Assume we haven't been getting state updates either:
+ */
+ _tnl_InvalidateState( ctx, ~0 );
+
+#if 0
+ if (ctx->Light.ColorMaterialEnabled) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ }
+#endif
+}
+
+
+
+
+/**
+ * Drivers call this function to tell the TCL module whether or not
+ * it wants Normalized Device Coords (NDC) computed. I.e. whether
+ * we should "Divide-by-W". Software renders will want that.
+ */
+void
+_tnl_need_projected_coords( GLcontext *ctx, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->NeedNdcCoords = mode;
+}
+
+void
+_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->AllowVertexFog = value;
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
+
+}
+
+void
+_tnl_allow_pixel_fog( GLcontext *ctx, GLboolean value )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->AllowPixelFog = value;
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
+}
+
diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h
new file mode 100644
index 000000000..c19eb3df3
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_context.h
@@ -0,0 +1,551 @@
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file t_context.h
+ * \brief TnL module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The TNL-module
+ *
+ * TNL stands for "transform and lighting", i.e. this module implements
+ * a pipeline that receives as input a buffer of vertices and does all
+ * necessary transformations (rotations, clipping, vertex shader etc.)
+ * and passes then the output to the rasterizer.
+ *
+ * The tnl_pipeline contains the array of all stages, which should be
+ * applied. Each stage is a black-box, which is described by an
+ * tnl_pipeline_stage. The function ::_tnl_run_pipeline applies all the
+ * stages to the vertex_buffer TNLcontext::vb, where the vertex data
+ * is stored. The last stage in the pipeline is the rasterizer.
+ *
+ */
+
+
+#ifndef _T_CONTEXT_H
+#define _T_CONTEXT_H
+
+#include "main/glheader.h"
+#include "main/bitset.h"
+#include "main/mtypes.h"
+
+#include "math/m_matrix.h"
+#include "math/m_vector.h"
+#include "math/m_xform.h"
+
+#include "vbo/vbo.h"
+
+#define MAX_PIPELINE_STAGES 30
+
+/*
+ * Note: The first attributes match the VERT_ATTRIB_* definitions
+ * in mtypes.h. However, the tnl module has additional attributes
+ * for materials, color indexes, edge flags, etc.
+ */
+/* Although it's nice to use these as bit indexes in a DWORD flag, we
+ * could manage without if necessary. Another limit currently is the
+ * number of bits allocated for these numbers in places like vertex
+ * program instruction formats and register layouts.
+ */
+/* The bit space exhaustion is a fact now, done by _TNL_ATTRIB_ATTRIBUTE* for
+ * GLSL vertex shader which cannot be aliased with conventional vertex attribs.
+ * Compacting _TNL_ATTRIB_MAT_* attribs would not work, they would not give
+ * as many free bits (11 plus already 1 free bit) as _TNL_ATTRIB_ATTRIBUTE*
+ * attribs want (16).
+ */
+enum {
+ _TNL_ATTRIB_POS = 0,
+ _TNL_ATTRIB_WEIGHT = 1,
+ _TNL_ATTRIB_NORMAL = 2,
+ _TNL_ATTRIB_COLOR0 = 3,
+ _TNL_ATTRIB_COLOR1 = 4,
+ _TNL_ATTRIB_FOG = 5,
+ _TNL_ATTRIB_COLOR_INDEX = 6,
+ _TNL_ATTRIB_EDGEFLAG = 7,
+ _TNL_ATTRIB_TEX0 = 8,
+ _TNL_ATTRIB_TEX1 = 9,
+ _TNL_ATTRIB_TEX2 = 10,
+ _TNL_ATTRIB_TEX3 = 11,
+ _TNL_ATTRIB_TEX4 = 12,
+ _TNL_ATTRIB_TEX5 = 13,
+ _TNL_ATTRIB_TEX6 = 14,
+ _TNL_ATTRIB_TEX7 = 15,
+
+ _TNL_ATTRIB_GENERIC0 = 16, /* doesn't really exist! */
+ _TNL_ATTRIB_GENERIC1 = 17,
+ _TNL_ATTRIB_GENERIC2 = 18,
+ _TNL_ATTRIB_GENERIC3 = 19,
+ _TNL_ATTRIB_GENERIC4 = 20,
+ _TNL_ATTRIB_GENERIC5 = 21,
+ _TNL_ATTRIB_GENERIC6 = 22,
+ _TNL_ATTRIB_GENERIC7 = 23,
+ _TNL_ATTRIB_GENERIC8 = 24,
+ _TNL_ATTRIB_GENERIC9 = 25,
+ _TNL_ATTRIB_GENERIC10 = 26,
+ _TNL_ATTRIB_GENERIC11 = 27,
+ _TNL_ATTRIB_GENERIC12 = 28,
+ _TNL_ATTRIB_GENERIC13 = 29,
+ _TNL_ATTRIB_GENERIC14 = 30,
+ _TNL_ATTRIB_GENERIC15 = 31,
+
+ /* These alias with the generics, but they are not active
+ * concurrently, so it's not a problem. The TNL module
+ * doesn't have to do anything about this as this is how they
+ * are passed into the _draw_prims callback.
+ *
+ * When we generate fixed-function replacement programs (in
+ * t_vp_build.c currently), they refer to the appropriate
+ * generic attribute in order to pick up per-vertex material
+ * data.
+ */
+ _TNL_ATTRIB_MAT_FRONT_AMBIENT = 16,
+ _TNL_ATTRIB_MAT_BACK_AMBIENT = 17,
+ _TNL_ATTRIB_MAT_FRONT_DIFFUSE = 18,
+ _TNL_ATTRIB_MAT_BACK_DIFFUSE = 19,
+ _TNL_ATTRIB_MAT_FRONT_SPECULAR = 20,
+ _TNL_ATTRIB_MAT_BACK_SPECULAR = 21,
+ _TNL_ATTRIB_MAT_FRONT_EMISSION = 22,
+ _TNL_ATTRIB_MAT_BACK_EMISSION = 23,
+ _TNL_ATTRIB_MAT_FRONT_SHININESS = 24,
+ _TNL_ATTRIB_MAT_BACK_SHININESS = 25,
+ _TNL_ATTRIB_MAT_FRONT_INDEXES = 26,
+ _TNL_ATTRIB_MAT_BACK_INDEXES = 27,
+
+ /* This is really a VERT_RESULT, not an attrib. Need to fix
+ * tnl to understand the difference.
+ */
+ _TNL_ATTRIB_POINTSIZE = 16,
+
+ _TNL_ATTRIB_MAX = 32
+} ;
+
+#define _TNL_ATTRIB_TEX(u) (_TNL_ATTRIB_TEX0 + (u))
+#define _TNL_ATTRIB_GENERIC(n) (_TNL_ATTRIB_GENERIC0 + (n))
+
+/* special index used for handing invalid glVertexAttribute() indices */
+#define _TNL_ATTRIB_ERROR (_TNL_ATTRIB_GENERIC15 + 1)
+
+/**
+ * Handy attribute ranges:
+ */
+#define _TNL_FIRST_PROG _TNL_ATTRIB_WEIGHT
+#define _TNL_LAST_PROG _TNL_ATTRIB_TEX7
+
+#define _TNL_FIRST_TEX _TNL_ATTRIB_TEX0
+#define _TNL_LAST_TEX _TNL_ATTRIB_TEX7
+
+#define _TNL_FIRST_GENERIC _TNL_ATTRIB_GENERIC0
+#define _TNL_LAST_GENERIC _TNL_ATTRIB_GENERIC15
+
+#define _TNL_FIRST_MAT _TNL_ATTRIB_MAT_FRONT_AMBIENT /* GENERIC0 */
+#define _TNL_LAST_MAT _TNL_ATTRIB_MAT_BACK_INDEXES /* GENERIC11 */
+
+/* Number of available generic attributes */
+#define _TNL_NUM_GENERIC 16
+
+/* Number of attributes used for evaluators */
+#define _TNL_NUM_EVAL 16
+
+
+#define PRIM_BEGIN 0x10
+#define PRIM_END 0x20
+#define PRIM_MODE_MASK 0x0f
+
+static INLINE GLuint _tnl_translate_prim( const struct _mesa_prim *prim )
+{
+ GLuint flag;
+ flag = prim->mode;
+ if (prim->begin) flag |= PRIM_BEGIN;
+ if (prim->end) flag |= PRIM_END;
+ return flag;
+}
+
+
+
+
+/**
+ * Contains the current state of a running pipeline.
+ */
+struct vertex_buffer
+{
+ GLuint Size; /**< Max vertices per vertex buffer, constant */
+
+ /* Constant over the pipeline.
+ */
+ GLuint Count; /**< Number of vertices currently in buffer */
+
+ /* Pointers to current data.
+ * XXX some of these fields alias AttribPtr below and should be removed
+ * such as NormalPtr, TexCoordPtr, FogCoordPtr, etc.
+ */
+ GLuint *Elts;
+ GLvector4f *ObjPtr; /* _TNL_BIT_POS */
+ GLvector4f *EyePtr; /* _TNL_BIT_POS */
+ GLvector4f *ClipPtr; /* _TNL_BIT_POS */
+ GLvector4f *NdcPtr; /* _TNL_BIT_POS */
+ GLubyte ClipOrMask; /* _TNL_BIT_POS */
+ GLubyte ClipAndMask; /* _TNL_BIT_POS */
+ GLubyte *ClipMask; /* _TNL_BIT_POS */
+ GLvector4f *NormalPtr; /* _TNL_BIT_NORMAL */
+ GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */
+ GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */
+ GLvector4f *TexCoordPtr[MAX_TEXTURE_COORD_UNITS]; /* VERT_TEX_0..n */
+ GLvector4f *IndexPtr[2]; /* _TNL_BIT_INDEX */
+ GLvector4f *ColorPtr[2]; /* _TNL_BIT_COLOR0 */
+ GLvector4f *SecondaryColorPtr[2]; /* _TNL_BIT_COLOR1 */
+ GLvector4f *FogCoordPtr; /* _TNL_BIT_FOG */
+
+ const struct _mesa_prim *Primitive;
+ GLuint PrimitiveCount;
+
+ /* Inputs to the vertex program stage */
+ GLvector4f *AttribPtr[_TNL_ATTRIB_MAX]; /* GL_NV_vertex_program */
+};
+
+
+/**
+ * Describes an individual operation on the pipeline.
+ */
+struct tnl_pipeline_stage
+{
+ const char *name;
+
+ /* Private data for the pipeline stage:
+ */
+ void *privatePtr;
+
+ /* Allocate private data
+ */
+ GLboolean (*create)( GLcontext *ctx, struct tnl_pipeline_stage * );
+
+ /* Free private data.
+ */
+ void (*destroy)( struct tnl_pipeline_stage * );
+
+ /* Called on any statechange or input array size change or
+ * input array change to/from zero stride.
+ */
+ void (*validate)( GLcontext *ctx, struct tnl_pipeline_stage * );
+
+ /* Called from _tnl_run_pipeline(). The stage.changed_inputs value
+ * encodes all inputs to thee struct which have changed. If
+ * non-zero, recompute all affected outputs of the stage, otherwise
+ * execute any 'sideeffects' of the stage.
+ *
+ * Return value: GL_TRUE - keep going
+ * GL_FALSE - finished pipeline
+ */
+ GLboolean (*run)( GLcontext *ctx, struct tnl_pipeline_stage * );
+};
+
+
+
+/** Contains the array of all pipeline stages.
+ * The default values are defined at the end of t_pipeline.c
+ */
+struct tnl_pipeline {
+
+ GLuint last_attrib_stride[_TNL_ATTRIB_MAX];
+ GLuint last_attrib_size[_TNL_ATTRIB_MAX];
+ GLuint input_changes;
+ GLuint new_state;
+
+ struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
+ GLuint nr_stages;
+};
+
+struct tnl_clipspace;
+struct tnl_clipspace_attr;
+
+typedef void (*tnl_extract_func)( const struct tnl_clipspace_attr *a,
+ GLfloat *out,
+ const GLubyte *v );
+
+typedef void (*tnl_insert_func)( const struct tnl_clipspace_attr *a,
+ GLubyte *v,
+ const GLfloat *in );
+
+typedef void (*tnl_emit_func)( GLcontext *ctx,
+ GLuint count,
+ GLubyte *dest );
+
+
+/**
+ * Describes how to convert/move a vertex attribute from a vertex array
+ * to a vertex structure.
+ */
+struct tnl_clipspace_attr
+{
+ GLuint attrib; /* which vertex attrib (0=position, etc) */
+ GLuint format;
+ GLuint vertoffset; /* position of the attrib in the vertex struct */
+ GLuint vertattrsize; /* size of the attribute in bytes */
+ GLubyte *inputptr;
+ GLuint inputstride;
+ GLuint inputsize;
+ const tnl_insert_func *insert;
+ tnl_insert_func emit;
+ tnl_extract_func extract;
+ const GLfloat *vp; /* NDC->Viewport mapping matrix */
+};
+
+
+
+
+typedef void (*tnl_points_func)( GLcontext *ctx, GLuint first, GLuint last );
+typedef void (*tnl_line_func)( GLcontext *ctx, GLuint v1, GLuint v2 );
+typedef void (*tnl_triangle_func)( GLcontext *ctx,
+ GLuint v1, GLuint v2, GLuint v3 );
+typedef void (*tnl_quad_func)( GLcontext *ctx, GLuint v1, GLuint v2,
+ GLuint v3, GLuint v4 );
+typedef void (*tnl_render_func)( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint flags );
+typedef void (*tnl_interp_func)( GLcontext *ctx,
+ GLfloat t, GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary );
+typedef void (*tnl_copy_pv_func)( GLcontext *ctx, GLuint dst, GLuint src );
+typedef void (*tnl_setup_func)( GLcontext *ctx,
+ GLuint start, GLuint end,
+ GLuint new_inputs);
+
+
+struct tnl_attr_type {
+ GLuint format;
+ GLuint size;
+ GLuint stride;
+ GLuint offset;
+};
+
+struct tnl_clipspace_fastpath {
+ GLuint vertex_size;
+ GLuint attr_count;
+ GLboolean match_strides;
+
+ struct tnl_attr_type *attr;
+
+ tnl_emit_func func;
+ struct tnl_clipspace_fastpath *next;
+};
+
+/**
+ * Used to describe conversion of vertex arrays to vertex structures.
+ * I.e. Structure of arrays to arrays of structs.
+ */
+struct tnl_clipspace
+{
+ GLboolean need_extras;
+
+ GLuint new_inputs;
+
+ GLubyte *vertex_buf;
+ GLuint vertex_size;
+ GLuint max_vertex_size;
+
+ struct tnl_clipspace_attr attr[_TNL_ATTRIB_MAX];
+ GLuint attr_count;
+
+ tnl_emit_func emit;
+ tnl_interp_func interp;
+ tnl_copy_pv_func copy_pv;
+
+ /* Parameters and constants for codegen:
+ */
+ GLboolean need_viewport;
+ GLfloat vp_scale[4];
+ GLfloat vp_xlate[4];
+ GLfloat chan_scale[4];
+ GLfloat identity[4];
+
+ struct tnl_clipspace_fastpath *fastpath;
+
+ void (*codegen_emit)( GLcontext *ctx );
+};
+
+
+struct tnl_device_driver
+{
+ /***
+ *** TNL Pipeline
+ ***/
+
+ void (*RunPipeline)(GLcontext *ctx);
+ /* Replaces PipelineStart/PipelineFinish -- intended to allow
+ * drivers to wrap _tnl_run_pipeline() with code to validate state
+ * and grab/release hardware locks.
+ */
+
+ void (*NotifyMaterialChange)(GLcontext *ctx);
+ /* Alert tnl-aware drivers of changes to material.
+ */
+
+ void (*NotifyInputChanges)(GLcontext *ctx, GLuint bitmask);
+ /* Alert tnl-aware drivers of changes to size and stride of input
+ * arrays.
+ */
+
+ /***
+ *** Rendering -- These functions called only from t_vb_render.c
+ ***/
+ struct
+ {
+ void (*Start)(GLcontext *ctx);
+ void (*Finish)(GLcontext *ctx);
+ /* Called before and after all rendering operations, including DrawPixels,
+ * ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands.
+ * These are a suitable place for grabbing/releasing hardware locks.
+ */
+
+ void (*PrimitiveNotify)(GLcontext *ctx, GLenum mode);
+ /* Called between RenderStart() and RenderFinish() to indicate the
+ * type of primitive we're about to draw. Mode will be one of the
+ * modes accepted by glBegin().
+ */
+
+ tnl_interp_func Interp;
+ /* The interp function is called by the clipping routines when we need
+ * to generate an interpolated vertex. All pertinant vertex ancilliary
+ * data should be computed by interpolating between the 'in' and 'out'
+ * vertices.
+ */
+
+ tnl_copy_pv_func CopyPV;
+ /* The copy function is used to make a copy of a vertex. All pertinant
+ * vertex attributes should be copied.
+ */
+
+ void (*ClippedPolygon)( GLcontext *ctx, const GLuint *elts, GLuint n );
+ /* Render a polygon with <n> vertices whose indexes are in the <elts>
+ * array.
+ */
+
+ void (*ClippedLine)( GLcontext *ctx, GLuint v0, GLuint v1 );
+ /* Render a line between the two vertices given by indexes v0 and v1. */
+
+ tnl_points_func Points; /* must now respect vb->elts */
+ tnl_line_func Line;
+ tnl_triangle_func Triangle;
+ tnl_quad_func Quad;
+ /* These functions are called in order to render points, lines,
+ * triangles and quads. These are only called via the T&L module.
+ */
+
+ tnl_render_func *PrimTabVerts;
+ tnl_render_func *PrimTabElts;
+ /* Render whole unclipped primitives (points, lines, linestrips,
+ * lineloops, etc). The tables are indexed by the GL enum of the
+ * primitive to be rendered. RenderTabVerts is used for non-indexed
+ * arrays of vertices. RenderTabElts is used for indexed arrays of
+ * vertices.
+ */
+
+ void (*ResetLineStipple)( GLcontext *ctx );
+ /* Reset the hardware's line stipple counter.
+ */
+
+ tnl_setup_func BuildVertices;
+ /* This function is called whenever new vertices are required for
+ * rendering. The vertices in question are those n such that start
+ * <= n < end. The new_inputs parameter indicates those fields of
+ * the vertex which need to be updated, if only a partial repair of
+ * the vertex is required.
+ *
+ * This function is called only from _tnl_render_stage in tnl/t_render.c.
+ */
+
+
+ GLboolean (*Multipass)( GLcontext *ctx, 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.
+ */
+ } Render;
+};
+
+
+#define DECLARE_RENDERINPUTS(name) BITSET64_DECLARE(name, _TNL_ATTRIB_MAX)
+#define RENDERINPUTS_COPY BITSET64_COPY
+#define RENDERINPUTS_EQUAL BITSET64_EQUAL
+#define RENDERINPUTS_ZERO BITSET64_ZERO
+#define RENDERINPUTS_ONES BITSET64_ONES
+#define RENDERINPUTS_TEST BITSET64_TEST
+#define RENDERINPUTS_SET BITSET64_SET
+#define RENDERINPUTS_CLEAR BITSET64_CLEAR
+#define RENDERINPUTS_TEST_RANGE BITSET64_TEST_RANGE
+#define RENDERINPUTS_SET_RANGE BITSET64_SET_RANGE
+#define RENDERINPUTS_CLEAR_RANGE BITSET64_CLEAR_RANGE
+
+
+/**
+ * Context state for T&L context.
+ */
+typedef struct
+{
+ /* Driver interface.
+ */
+ struct tnl_device_driver Driver;
+
+ /* Pipeline
+ */
+ struct tnl_pipeline pipeline;
+ struct vertex_buffer vb;
+
+ /* Clipspace/ndc/window vertex managment:
+ */
+ struct tnl_clipspace clipspace;
+
+ /* Probably need a better configuration mechanism:
+ */
+ GLboolean NeedNdcCoords;
+ GLboolean AllowVertexFog;
+ GLboolean AllowPixelFog;
+ GLboolean _DoVertexFog; /* eval fog function at each vertex? */
+
+ DECLARE_RENDERINPUTS(render_inputs_bitset);
+
+ GLvector4f tmp_inputs[VERT_ATTRIB_MAX];
+
+ /* Temp storage for t_draw.c:
+ */
+ GLubyte *block[VERT_ATTRIB_MAX];
+ GLuint nr_blocks;
+
+} TNLcontext;
+
+
+
+#define TNL_CONTEXT(ctx) ((TNLcontext *)((ctx)->swtnl_context))
+
+
+#define TYPE_IDX(t) ((t) & 0xf)
+#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
+
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c
new file mode 100644
index 000000000..c64c2c207
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_draw.c
@@ -0,0 +1,451 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/state.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+#include "t_vp_build.h"
+#include "t_vertex.h"
+#include "tnl.h"
+
+
+
+static GLubyte *get_space(GLcontext *ctx, GLuint bytes)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLubyte *space = _mesa_malloc(bytes);
+
+ tnl->block[tnl->nr_blocks++] = space;
+ return space;
+}
+
+
+static void free_space(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+ for (i = 0; i < tnl->nr_blocks; i++)
+ _mesa_free(tnl->block[i]);
+ tnl->nr_blocks = 0;
+}
+
+
+/* Convert the incoming array to GLfloats. Understands the
+ * array->Normalized flag and selects the correct conversion method.
+ */
+#define CONVERT( TYPE, MACRO ) do { \
+ GLuint i, j; \
+ if (input->Normalized) { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)ptr; \
+ for (j = 0; j < sz; j++) { \
+ *fptr++ = MACRO(*in); \
+ in++; \
+ } \
+ ptr += input->StrideB; \
+ } \
+ } else { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)ptr; \
+ for (j = 0; j < sz; j++) { \
+ *fptr++ = (GLfloat)(*in); \
+ in++; \
+ } \
+ ptr += input->StrideB; \
+ } \
+ } \
+} while (0)
+
+
+/**
+ * Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
+ * \param ptr input/ubyte array
+ * \param fptr output/float array
+ */
+static void
+convert_bgra_to_float(const struct gl_client_array *input,
+ const GLubyte *ptr, GLfloat *fptr,
+ GLuint count )
+{
+ GLuint i;
+ assert(input->Normalized);
+ assert(input->Size == 4);
+ for (i = 0; i < count; i++) {
+ const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
+ *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
+ *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
+ *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
+ *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
+ ptr += input->StrideB;
+ }
+}
+
+
+/* Adjust pointer to point at first requested element, convert to
+ * floating point, populate VB->AttribPtr[].
+ */
+static void _tnl_import_array( GLcontext *ctx,
+ GLuint attrib,
+ GLuint count,
+ const struct gl_client_array *input,
+ const GLubyte *ptr )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint stride = input->StrideB;
+
+ if (input->Type != GL_FLOAT) {
+ const GLuint sz = input->Size;
+ GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
+ GLfloat *fptr = (GLfloat *)buf;
+
+ switch (input->Type) {
+ case GL_BYTE:
+ CONVERT(GLbyte, BYTE_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (input->Format == GL_BGRA) {
+ /* See GL_EXT_vertex_array_bgra */
+ convert_bgra_to_float(input, ptr, fptr, count);
+ }
+ else {
+ CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ }
+ break;
+ case GL_SHORT:
+ CONVERT(GLshort, SHORT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CONVERT(GLushort, USHORT_TO_FLOAT);
+ break;
+ case GL_INT:
+ CONVERT(GLint, INT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_INT:
+ CONVERT(GLuint, UINT_TO_FLOAT);
+ break;
+ case GL_DOUBLE:
+ CONVERT(GLdouble, (GLfloat));
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ ptr = buf;
+ stride = sz * sizeof(GLfloat);
+ }
+
+ VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib];
+ VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr;
+ VB->AttribPtr[attrib]->start = (GLfloat *)ptr;
+ VB->AttribPtr[attrib]->count = count;
+ VB->AttribPtr[attrib]->stride = stride;
+ VB->AttribPtr[attrib]->size = input->Size;
+
+ /* This should die, but so should the whole GLvector4f concept:
+ */
+ VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) |
+ VEC_NOT_WRITEABLE |
+ (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
+
+ VB->AttribPtr[attrib]->storage = NULL;
+}
+
+#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2)
+
+
+static GLboolean *_tnl_import_edgeflag( GLcontext *ctx,
+ const GLvector4f *input,
+ GLuint count)
+{
+ const GLubyte *ptr = (const GLubyte *)input->data;
+ const GLuint stride = input->stride;
+ GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
+ GLboolean *bptr = space;
+ GLuint i;
+
+ for (i = 0; i < count; i++) {
+ *bptr++ = ((GLfloat *)ptr)[0] == 1.0;
+ ptr += stride;
+ }
+
+ return space;
+}
+
+
+static void bind_inputs( GLcontext *ctx,
+ const struct gl_client_array *inputs[],
+ GLint count,
+ struct gl_buffer_object **bo,
+ GLuint *nr_bo )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+
+ /* Map all the VBOs
+ */
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ const void *ptr;
+
+ if (inputs[i]->BufferObj->Name) {
+ if (!inputs[i]->BufferObj->Pointer) {
+ bo[*nr_bo] = inputs[i]->BufferObj;
+ (*nr_bo)++;
+ ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ inputs[i]->BufferObj);
+
+ assert(inputs[i]->BufferObj->Pointer);
+ }
+
+ ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer,
+ inputs[i]->Ptr);
+ }
+ else
+ ptr = inputs[i]->Ptr;
+
+ /* Just make sure the array is floating point, otherwise convert to
+ * temporary storage.
+ *
+ * XXX: remove the GLvector4f type at some stage and just use
+ * client arrays.
+ */
+ _tnl_import_array(ctx, i, count, inputs[i], ptr);
+ }
+
+ /* We process only the vertices between min & max index:
+ */
+ VB->Count = count;
+
+
+ /* Legacy pointers -- remove one day.
+ */
+ VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
+ VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+ VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
+ VB->ColorPtr[1] = NULL;
+ VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR_INDEX];
+ VB->IndexPtr[1] = NULL;
+ VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1];
+ VB->SecondaryColorPtr[1] = NULL;
+ VB->FogCoordPtr = VB->AttribPtr[_TNL_ATTRIB_FOG];
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i];
+ }
+
+ /* Clipping and drawing code still requires this to be a packed
+ * array of ubytes which can be written into. TODO: Fix and
+ * remove.
+ */
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)
+ {
+ VB->EdgeFlag = _tnl_import_edgeflag( ctx,
+ VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
+ VB->Count );
+ }
+ else {
+ /* the data previously pointed to by EdgeFlag may have been freed */
+ VB->EdgeFlag = NULL;
+ }
+}
+
+
+/* Translate indices to GLuints and store in VB->Elts.
+ */
+static void bind_indices( GLcontext *ctx,
+ const struct _mesa_index_buffer *ib,
+ struct gl_buffer_object **bo,
+ GLuint *nr_bo)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+ void *ptr;
+
+ if (!ib) {
+ VB->Elts = NULL;
+ return;
+ }
+
+ if (ib->obj->Name && !ib->obj->Pointer) {
+ bo[*nr_bo] = ib->obj;
+ (*nr_bo)++;
+ ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ ib->obj);
+
+ assert(ib->obj->Pointer);
+ }
+
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
+
+ if (ib->type == GL_UNSIGNED_INT) {
+ VB->Elts = (GLuint *) ptr;
+ }
+ else {
+ GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
+ VB->Elts = elts;
+
+ if (ib->type == GL_UNSIGNED_SHORT) {
+ const GLushort *in = (GLushort *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++);
+ }
+ else {
+ const GLubyte *in = (GLubyte *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++);
+ }
+ }
+}
+
+static void bind_prims( GLcontext *ctx,
+ const struct _mesa_prim *prim,
+ GLuint nr_prims )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ VB->Primitive = prim;
+ VB->PrimitiveCount = nr_prims;
+}
+
+static void unmap_vbos( GLcontext *ctx,
+ struct gl_buffer_object **bo,
+ GLuint nr_bo )
+{
+ GLuint i;
+ for (i = 0; i < nr_bo; i++) {
+ ctx->Driver.UnmapBuffer(ctx,
+ 0, /* target -- I don't see why this would be needed */
+ bo[i]);
+ }
+}
+
+
+void _tnl_vbo_draw_prims(GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
+ _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+}
+
+/* This is the main entrypoint into the slimmed-down software tnl
+ * module. In a regular swtnl driver, this can be plugged straight
+ * into the vbo->Driver.DrawPrims() callback.
+ */
+void _tnl_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ const GLuint TEST_SPLIT = 0;
+ const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
+
+ if (0)
+ {
+ GLuint i;
+ _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ for (i = 0; i < nr_prims; i++)
+ _mesa_printf("prim %d: %s start %d count %d\n", i,
+ _mesa_lookup_enum_by_nr(prim[i].mode),
+ prim[i].start,
+ prim[i].count);
+ }
+
+ if (min_index) {
+ /* We always translate away calls with min_index != 0.
+ */
+ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index,
+ _tnl_vbo_draw_prims );
+ return;
+ }
+ else if (max_index > max) {
+ /* The software TNL pipeline has a fixed amount of storage for
+ * vertices and it is necessary to split incoming drawing commands
+ * if they exceed that limit.
+ */
+ struct split_limits limits;
+ limits.max_verts = max;
+ limits.max_vb_size = ~0;
+ limits.max_indices = ~0;
+
+ /* This will split the buffers one way or another and
+ * recursively call back into this function.
+ */
+ vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
+ 0, max_index,
+ _tnl_vbo_draw_prims,
+ &limits );
+ }
+ else {
+ /* May need to map a vertex buffer object for every attribute plus
+ * one for the index buffer.
+ */
+ struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
+ GLuint nr_bo = 0;
+
+ /* Binding inputs may imply mapping some vertex buffer objects.
+ * They will need to be unmapped below.
+ */
+ bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
+ bind_indices(ctx, ib, bo, &nr_bo);
+ bind_prims(ctx, prim, nr_prims );
+
+ TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
+
+ unmap_vbos(ctx, bo, nr_bo);
+ free_space(ctx);
+ }
+}
+
diff --git a/mesalib/src/mesa/tnl/t_pipeline.c b/mesalib/src/mesa/tnl/t_pipeline.c
new file mode 100644
index 000000000..357ef1e24
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_pipeline.c
@@ -0,0 +1,215 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/state.h"
+#include "main/mtypes.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+#include "t_vp_build.h"
+#include "t_vertex.h"
+
+void _tnl_install_pipeline( GLcontext *ctx,
+ const struct tnl_pipeline_stage **stages )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ tnl->pipeline.new_state = ~0;
+
+ /* Create a writeable copy of each stage.
+ */
+ for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ MEMCPY(s, stages[i], sizeof(*s));
+ if (s->create)
+ s->create(ctx, s);
+ }
+
+ tnl->pipeline.nr_stages = i;
+}
+
+void _tnl_destroy_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->destroy)
+ s->destroy(s);
+ }
+
+ tnl->pipeline.nr_stages = 0;
+}
+
+
+
+static GLuint check_input_changes( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0; i <= _TNL_LAST_MAT; i++) {
+ if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
+ tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
+ tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
+ tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
+ tnl->pipeline.input_changes |= 1<<i;
+ }
+ }
+
+ if (tnl->pipeline.input_changes &&
+ tnl->Driver.NotifyInputChanges)
+ tnl->Driver.NotifyInputChanges( ctx, tnl->pipeline.input_changes );
+
+ return tnl->pipeline.input_changes;
+}
+
+
+static GLuint check_output_changes( GLcontext *ctx )
+{
+#if 0
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
+ tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
+ tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
+ tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
+ tnl->pipeline.output_changes |= 1<<i;
+ }
+ }
+
+ if (tnl->pipeline.output_changes)
+ tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
+
+ return tnl->pipeline.output_changes;
+#else
+ return ~0;
+#endif
+}
+
+
+void _tnl_run_pipeline( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ unsigned short __tmp;
+ GLuint i;
+
+ if (!tnl->vb.Count)
+ return;
+
+ /* Check for changed input sizes or change in stride to/from zero
+ * (ie const or non-const).
+ */
+ if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
+ if (ctx->VertexProgram._MaintainTnlProgram)
+ _tnl_UpdateFixedFunctionProgram( ctx );
+
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->validate)
+ s->validate( ctx, s );
+ }
+
+ tnl->pipeline.new_state = 0;
+ tnl->pipeline.input_changes = 0;
+
+ /* Pipeline can only change its output in response to either a
+ * statechange or an input size/stride change. No other changes
+ * are allowed.
+ */
+ if (check_output_changes( ctx ))
+ _tnl_notify_pipeline_output_change( ctx );
+ }
+
+ START_FAST_MATH(__tmp);
+
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (!s->run( ctx, s ))
+ break;
+ }
+
+ END_FAST_MATH(__tmp);
+}
+
+
+
+/* The default pipeline. This is useful for software rasterizers, and
+ * simple hardware rasterizers. For customization, I don't recommend
+ * tampering with the internals of these stages in the way that
+ * drivers did in Mesa 3.4. These stages are basically black boxes,
+ * and should be left intact.
+ *
+ * To customize the pipeline, consider:
+ *
+ * - removing redundant stages (making sure that the software rasterizer
+ * can cope with this on fallback paths). An example is fog
+ * coordinate generation, which is not required in the FX driver.
+ *
+ * - replacing general-purpose machine-independent stages with
+ * general-purpose machine-specific stages. There is no example of
+ * this to date, though it must be borne in mind that all subsequent
+ * stages that reference the output of the new stage must cope with
+ * any machine-specific data introduced. This may not be easy
+ * unless there are no such stages (ie the new stage is the last in
+ * the pipe).
+ *
+ * - inserting optimized (but specialized) stages ahead of the
+ * general-purpose fallback implementation. For example, the old
+ * fastpath mechanism, which only works when the VB->Elts input is
+ * available, can be duplicated by placing the fastpath stage at the
+ * head of this pipeline. Such specialized stages are currently
+ * constrained to have no outputs (ie. they must either finish the *
+ * pipeline by returning GL_FALSE from run(), or do nothing).
+ *
+ * Some work can be done to lift some of the restrictions in the final
+ * case, if it becomes necessary to do so.
+ */
+const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_tnl_vertex_program_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_render_stage,
+ NULL
+};
+
+const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = {
+ &_tnl_vertex_program_stage,
+ &_tnl_render_stage,
+ NULL
+};
diff --git a/mesalib/src/mesa/tnl/t_pipeline.h b/mesalib/src/mesa/tnl/t_pipeline.h
new file mode 100644
index 000000000..d110010f0
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_pipeline.h
@@ -0,0 +1,74 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+#ifndef _T_PIPELINE_H_
+#define _T_PIPELINE_H_
+
+#include "main/mtypes.h"
+#include "t_context.h"
+
+extern void _tnl_run_pipeline( GLcontext *ctx );
+
+extern void _tnl_destroy_pipeline( GLcontext *ctx );
+
+extern void _tnl_install_pipeline( GLcontext *ctx,
+ const struct tnl_pipeline_stage **stages );
+
+
+/* These are implemented in the t_vb_*.c files:
+ */
+extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_vertex_cull_stage;
+extern const struct tnl_pipeline_stage _tnl_normal_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_lighting_stage;
+extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage;
+extern const struct tnl_pipeline_stage _tnl_texgen_stage;
+extern const struct tnl_pipeline_stage _tnl_texture_transform_stage;
+extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage;
+extern const struct tnl_pipeline_stage _tnl_vertex_program_stage;
+extern const struct tnl_pipeline_stage _tnl_render_stage;
+
+/* Shorthand to plug in the default pipeline:
+ */
+extern const struct tnl_pipeline_stage *_tnl_default_pipeline[];
+extern const struct tnl_pipeline_stage *_tnl_vp_pipeline[];
+
+
+/* Convenience routines provided by t_vb_render.c:
+ */
+extern tnl_render_func _tnl_render_tab_elts[];
+extern tnl_render_func _tnl_render_tab_verts[];
+
+extern void _tnl_RenderClippedPolygon( GLcontext *ctx,
+ const GLuint *elts, GLuint n );
+
+extern void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj );
+
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c
new file mode 100644
index 000000000..f1fdddf0f
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_rasterpos.c
@@ -0,0 +1,505 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/feedback.h"
+#include "main/light.h"
+#include "main/macros.h"
+#include "main/rastpos.h"
+#include "main/simple_list.h"
+#include "main/mtypes.h"
+
+#include "math/m_matrix.h"
+#include "tnl/tnl.h"
+
+
+
+/**
+ * Clip a point against the view volume.
+ *
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if outside view volume, or one if inside.
+ */
+static GLuint
+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 far/near Z clipping planes.
+ *
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if outside view volume, or one if inside.
+ */
+static GLuint
+viewclip_point_z( const GLfloat v[] )
+{
+ if (v[2] > v[3] || v[2] < -v[3] ) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+
+/**
+ * Clip a point against the user clipping planes.
+ *
+ * \param ctx GL context.
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if the point was clipped, or one otherwise.
+ */
+static GLuint
+userclip_point( GLcontext *ctx, const GLfloat v[] )
+{
+ GLuint p;
+
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << 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;
+}
+
+
+/**
+ * Compute lighting for the raster position. Both RGB and CI modes computed.
+ * \param ctx the context
+ * \param vertex vertex location
+ * \param normal normal vector
+ * \param Rcolor returned color
+ * \param Rspec returned specular color (if separate specular enabled)
+ * \param Rindex returned color index
+ */
+static void
+shade_rastpos(GLcontext *ctx,
+ const GLfloat vertex[4],
+ const GLfloat normal[3],
+ GLfloat Rcolor[4],
+ GLfloat Rspec[4],
+ GLfloat *Rindex)
+{
+ /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ const struct gl_light *light;
+ GLfloat diffuseColor[4], specularColor[4]; /* for RGB mode only */
+ GLfloat diffuseCI = 0.0, specularCI = 0.0; /* for CI mode only */
+
+ _mesa_validate_all_lighting_tables( ctx );
+
+ COPY_3V(diffuseColor, base[0]);
+ diffuseColor[3] = CLAMP(
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F );
+ ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0);
+
+ foreach (light, &ctx->Light.EnabledList) {
+ GLfloat attenuation = 1.0;
+ GLfloat VP[3]; /* vector from vertex to light pos */
+ GLfloat n_dot_VP;
+ GLfloat diffuseContrib[3], specularContrib[3];
+
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* light at infinity */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ /* local/positional light */
+ GLfloat d;
+
+ /* VP = vector from vertex pos to light[i].pos */
+ SUB_3V(VP, light->_Position, vertex);
+ /* d = length(VP) */
+ d = (GLfloat) LEN_3FV( VP );
+ if (d > 1.0e-6) {
+ /* normalize VP */
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ /* atti */
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue;
+ }
+ else {
+ double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ int k = (int) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue;
+
+ n_dot_VP = DOT3( normal, VP );
+
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]);
+ continue;
+ }
+
+ /* Ambient + diffuse */
+ COPY_3V(diffuseContrib, light->_MatAmbient[0]);
+ ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]);
+ diffuseCI += n_dot_VP * light->_dli * attenuation;
+
+ /* Specular */
+ {
+ const GLfloat *h;
+ GLfloat n_dot_h;
+
+ ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0);
+
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v);
+ NORMALIZE_3FV(VP);
+ h = VP;
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ ACC_3V(VP, ctx->_EyeZDir);
+ NORMALIZE_3FV(VP);
+ h = VP;
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = DOT3(normal, h);
+
+ if (n_dot_h > 0.0F) {
+ GLfloat spec_coef;
+ GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef );
+
+ if (spec_coef > 1.0e-10) {
+ if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
+ ACC_SCALE_SCALAR_3V( specularContrib, spec_coef,
+ light->_MatSpecular[0]);
+ }
+ else {
+ ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef,
+ light->_MatSpecular[0]);
+ }
+ /*assert(light->_sli > 0.0);*/
+ specularCI += spec_coef * light->_sli * attenuation;
+ }
+ }
+ }
+
+ ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib );
+ ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib );
+ }
+
+ if (ctx->Visual.rgbMode) {
+ Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F);
+ Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F);
+ Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F);
+ Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F);
+ Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F);
+ Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F);
+ Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F);
+ Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F);
+ }
+ else {
+ GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES];
+ GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT];
+ GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT];
+ GLfloat i = (ind[MAT_INDEX_AMBIENT]
+ + diffuseCI * (1.0F-specularCI) * d_a
+ + specularCI * s_a);
+ if (i > ind[MAT_INDEX_SPECULAR]) {
+ i = ind[MAT_INDEX_SPECULAR];
+ }
+ *Rindex = i;
+ }
+}
+
+
+/**
+ * Do texgen needed for glRasterPos.
+ * \param ctx rendering context
+ * \param vObj object-space vertex coordinate
+ * \param vEye eye-space vertex coordinate
+ * \param normal vertex normal
+ * \param unit texture unit number
+ * \param texcoord incoming texcoord and resulting texcoord
+ */
+static void
+compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
+ const GLfloat normal[3], GLuint unit, GLfloat texcoord[4])
+{
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ /* always compute sphere map terms, just in case */
+ GLfloat u[3], two_nu, rx, ry, rz, m, mInv;
+ COPY_3V(u, vEye);
+ NORMALIZE_3FV(u);
+ two_nu = 2.0F * DOT3(normal, u);
+ rx = u[0] - normal[0] * two_nu;
+ ry = u[1] - normal[1] * two_nu;
+ rz = u[2] - normal[2] * two_nu;
+ m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F);
+ if (m > 0.0F)
+ mInv = 0.5F * _mesa_inv_sqrtf(m);
+ else
+ mInv = 0.0F;
+
+ if (texUnit->TexGenEnabled & S_BIT) {
+ switch (texUnit->GenS.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane);
+ break;
+ case GL_SPHERE_MAP:
+ texcoord[0] = rx * mInv + 0.5F;
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[0] = rx;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[0] = normal[0];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad S texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & T_BIT) {
+ switch (texUnit->GenT.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane);
+ break;
+ case GL_SPHERE_MAP:
+ texcoord[1] = ry * mInv + 0.5F;
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[1] = ry;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[1] = normal[1];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad T texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & R_BIT) {
+ switch (texUnit->GenR.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane);
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[2] = rz;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[2] = normal[2];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad R texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ switch (texUnit->GenQ.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad Q texgen in compute_texgen()");
+ return;
+ }
+ }
+}
+
+
+/**
+ * glRasterPos transformation. Typically called via ctx->Driver.RasterPos().
+ * XXX some of this code (such as viewport xform, clip testing and setting
+ * of ctx->Current.Raster* fields) could get lifted up into the
+ * main/rasterpos.c code.
+ *
+ * \param vObj vertex position in object space
+ */
+void
+_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4])
+{
+ if (ctx->VertexProgram._Enabled) {
+ /* XXX implement this */
+ _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos");
+ return;
+ }
+ else {
+ GLfloat eye[4], clip[4], ndc[3], d;
+ GLfloat *norm, eyenorm[3];
+ GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+
+ /* apply modelview matrix: eye = MV * obj */
+ TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
+ /* apply projection matrix: clip = Proj * eye */
+ TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );
+
+ /* clip to view volume */
+ if (ctx->Transform.RasterPositionUnclipped) {
+ /* GL_IBM_rasterpos_clip: only clip against Z */
+ if (viewclip_point_z(clip) == 0) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+ }
+ else if (viewclip_point(clip) == 0) {
+ /* Normal OpenGL behaviour */
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+
+ /* clip to user clipping planes */
+ if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+
+ /* ndc = clip / W */
+ d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3];
+ ndc[0] = clip[0] * d;
+ ndc[1] = clip[1] * d;
+ ndc[2] = clip[2] * d;
+ /* wincoord = viewport_mapping(ndc) */
+ 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])
+ / ctx->DrawBuffer->_DepthMaxF;
+ ctx->Current.RasterPos[3] = clip[3];
+
+ /* compute raster distance */
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
+ else
+ ctx->Current.RasterDistance =
+ SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
+
+ /* compute transformed normal vector (for lighting or texgen) */
+ if (ctx->_NeedEyeCoords) {
+ const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv;
+ TRANSFORM_NORMAL( eyenorm, objnorm, inv );
+ norm = eyenorm;
+ }
+ else {
+ norm = objnorm;
+ }
+
+ /* update raster color */
+ if (ctx->Light.Enabled) {
+ /* lighting */
+ shade_rastpos( ctx, vObj, norm,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterSecondaryColor,
+ &ctx->Current.RasterIndex );
+ }
+ else {
+ /* use current color or index */
+ if (ctx->Visual.rgbMode) {
+ COPY_4FV(ctx->Current.RasterColor,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ COPY_4FV(ctx->Current.RasterSecondaryColor,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
+ }
+ else {
+ ctx->Current.RasterIndex
+ = ctx->Current.Attrib[VERT_ATTRIB_COLOR_INDEX][0];
+ }
+ }
+
+ /* texture coords */
+ {
+ GLuint u;
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ GLfloat tc[4];
+ COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
+ if (ctx->Texture.Unit[u].TexGenEnabled) {
+ compute_texgen(ctx, vObj, eye, norm, u, tc);
+ }
+ TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
+ ctx->TextureMatrixStack[u].Top->m, tc);
+ }
+ }
+
+ ctx->Current.RasterPosValid = GL_TRUE;
+ }
+
+ if (ctx->RenderMode == GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vb_cliptmp.h b/mesalib/src/mesa/tnl/t_vb_cliptmp.h
new file mode 100644
index 000000000..618b8b313
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_cliptmp.h
@@ -0,0 +1,320 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
+
+#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
+do { \
+ if (mask & PLANE_BIT) { \
+ GLuint idxPrev = inlist[0]; \
+ GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
+ GLuint outcount = 0; \
+ GLuint i; \
+ \
+ inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
+ for (i = 1; i <= n; i++) { \
+ GLuint idx = inlist[i]; \
+ GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
+ \
+ if (!IS_NEGATIVE(dpPrev)) { \
+ outlist[outcount++] = idxPrev; \
+ } \
+ \
+ if (DIFFERENT_SIGNS(dp, dpPrev)) { \
+ if (IS_NEGATIVE(dp)) { \
+ /* Going out of bounds. Avoid division by zero as we \
+ * know dp != dpPrev from DIFFERENT_SIGNS, above. \
+ */ \
+ GLfloat t = dp / (dp - dpPrev); \
+ INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
+ interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
+ } else { \
+ /* Coming back in. \
+ */ \
+ GLfloat t = dpPrev / (dpPrev - dp); \
+ INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
+ interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
+ } \
+ outlist[outcount++] = newvert++; \
+ } \
+ \
+ idxPrev = idx; \
+ dpPrev = dp; \
+ } \
+ \
+ if (outcount < 3) \
+ return; \
+ \
+ { \
+ GLuint *tmp = inlist; \
+ inlist = outlist; \
+ outlist = tmp; \
+ n = outcount; \
+ } \
+ } \
+} while (0)
+
+
+#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
+do { \
+ if (mask & PLANE_BIT) { \
+ const GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \
+ const GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \
+ const GLboolean neg_dp0 = IS_NEGATIVE(dp0); \
+ const GLboolean neg_dp1 = IS_NEGATIVE(dp1); \
+ \
+ /* For regular clipping, we know from the clipmask that one \
+ * (or both) of these must be negative (otherwise we wouldn't \
+ * be here). \
+ * For userclip, there is only a single bit for all active \
+ * planes, so we can end up here when there is nothing to do, \
+ * hence the second IS_NEGATIVE() test: \
+ */ \
+ if (neg_dp0 && neg_dp1) \
+ return; /* both vertices outside clip plane: discard */ \
+ \
+ if (neg_dp1) { \
+ GLfloat t = dp1 / (dp1 - dp0); \
+ if (t > t1) t1 = t; \
+ } else if (neg_dp0) { \
+ GLfloat t = dp0 / (dp0 - dp1); \
+ if (t > t0) t0 = t; \
+ } \
+ if (t0 + t1 >= 1.0) \
+ return; /* discard */ \
+ } \
+} while (0)
+
+
+
+/* Clip a line against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint newvert = VB->Count;
+ GLfloat t0 = 0;
+ GLfloat t1 = 0;
+ GLuint p;
+ const GLuint v0_orig = v0;
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ 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];
+ LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (VB->ClipMask[v0]) {
+ INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] );
+ interp( ctx, t0, newvert, v0, v1, GL_FALSE );
+ v0 = newvert;
+ newvert++;
+ }
+ else {
+ ASSERT(t0 == 0.0);
+ }
+
+ /* Note: we need to use vertex v0_orig when computing the new
+ * interpolated/clipped vertex position, not the current v0 which
+ * may have got set when we clipped the other end of the line!
+ */
+ if (VB->ClipMask[v1]) {
+ INTERP_4F( t1, coord[newvert], coord[v1], coord[v0_orig] );
+ interp( ctx, t1, newvert, v1, v0_orig, GL_FALSE );
+
+ if (ctx->Light.ShadeModel == GL_FLAT)
+ tnl->Driver.Render.CopyPV( ctx, newvert, v1 );
+
+ v1 = newvert;
+
+ newvert++;
+ }
+ else {
+ ASSERT(t1 == 0.0);
+ }
+
+ tnl->Driver.Render.ClippedLine( ctx, v0, v1 );
+}
+
+
+/* Clip a triangle against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLuint newvert = VB->Count;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint pv = v2;
+ GLuint vlist[2][MAX_CLIPPED_VERTICES];
+ GLuint *inlist = vlist[0], *outlist = vlist[1];
+ GLuint p;
+ GLuint n = 3;
+
+ ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
+
+ if (0) {
+ /* print pre-clip vertex coords */
+ GLuint i, j;
+ _mesa_printf("pre clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ _mesa_printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ assert(!IS_INF_OR_NAN(coord[j][0]));
+ assert(!IS_INF_OR_NAN(coord[j][1]));
+ assert(!IS_INF_OR_NAN(coord[j][2]));
+ assert(!IS_INF_OR_NAN(coord[j][3]));
+ }
+ }
+
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ 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];
+ POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ if (pv != inlist[0]) {
+ ASSERT( inlist[0] >= VB->Count );
+ tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
+ }
+ }
+
+ if (0) {
+ /* print post-clip vertex coords */
+ GLuint i, j;
+ _mesa_printf("post clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ _mesa_printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ }
+ }
+
+ tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
+}
+
+
+/* Clip a quad against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
+ GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLuint newvert = VB->Count;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint pv = v3;
+ GLuint vlist[2][MAX_CLIPPED_VERTICES];
+ GLuint *inlist = vlist[0], *outlist = vlist[1];
+ GLuint p;
+ GLuint n = 4;
+
+ ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ 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];
+ POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ if (pv != inlist[0]) {
+ ASSERT( inlist[0] >= VB->Count );
+ tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
+ }
+ }
+
+ tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
+}
+
+#undef W
+#undef Z
+#undef Y
+#undef X
+#undef SIZE
+#undef TAG
+#undef POLY_CLIP
+#undef LINE_CLIP
diff --git a/mesalib/src/mesa/tnl/t_vb_cull.c b/mesalib/src/mesa/tnl/t_vb_cull.c
new file mode 100644
index 000000000..712901acf
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_cull.c
@@ -0,0 +1,97 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+
+/* EXT_vertex_cull. Not really a big win, but probably depends on
+ * your application. This stage not included in the default pipeline.
+ */
+static GLboolean run_cull_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ const GLfloat a = ctx->Transform.CullObjPos[0];
+ const GLfloat b = ctx->Transform.CullObjPos[1];
+ const GLfloat c = ctx->Transform.CullObjPos[2];
+ GLfloat *norm = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLuint stride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ GLuint count = VB->Count;
+ GLuint i;
+
+ if (ctx->VertexProgram._Current ||
+ !ctx->Transform.CullVertexFlag)
+ return GL_TRUE;
+
+ VB->ClipOrMask &= ~CLIP_CULL_BIT;
+ VB->ClipAndMask |= CLIP_CULL_BIT;
+
+ for (i = 0 ; i < count ; i++) {
+ GLfloat dp = (norm[0] * a +
+ norm[1] * b +
+ norm[2] * c);
+
+ if (dp < 0) {
+ VB->ClipMask[i] |= CLIP_CULL_BIT;
+ VB->ClipOrMask |= CLIP_CULL_BIT;
+ }
+ else {
+ VB->ClipMask[i] &= ~CLIP_CULL_BIT;
+ VB->ClipAndMask &= ~CLIP_CULL_BIT;
+ }
+
+ STRIDE_F(norm, stride);
+ }
+
+ return !(VB->ClipAndMask & CLIP_CULL_BIT);
+}
+
+
+
+const struct tnl_pipeline_stage _tnl_vertex_cull_stage =
+{
+ "EXT_cull_vertex",
+ NULL, /* private data */
+ NULL, /* ctr */
+ NULL, /* destructor */
+ NULL,
+ run_cull_stage /* run -- initially set to init */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_fog.c b/mesalib/src/mesa/tnl/t_vb_fog.c
new file mode 100644
index 000000000..f3a7bd49f
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_fog.c
@@ -0,0 +1,277 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct fog_stage_data {
+ GLvector4f fogcoord; /* has actual storage allocated */
+};
+
+#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
+
+#define FOG_EXP_TABLE_SIZE 256
+#define FOG_MAX (10.0)
+#define EXP_FOG_MAX .0006595
+#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
+static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
+static GLfloat inited = 0;
+
+#if 1
+#define NEG_EXP( result, narg ) \
+do { \
+ GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \
+ GLint k = (GLint) f; \
+ if (k > FOG_EXP_TABLE_SIZE-2) \
+ result = (GLfloat) EXP_FOG_MAX; \
+ else \
+ result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
+} while (0)
+#else
+#define NEG_EXP( result, narg ) \
+do { \
+ result = exp(-narg); \
+} while (0)
+#endif
+
+
+/**
+ * Initialize the exp_table[] lookup table for approximating exp().
+ */
+static void
+init_static_data( void )
+{
+ GLfloat f = 0.0F;
+ GLint i = 0;
+ for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
+ exp_table[i] = EXPF(-f);
+ }
+ inited = 1;
+}
+
+
+/**
+ * Compute per-vertex fog blend factors from fog coordinates by
+ * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
+ * Fog coordinates are distances from the eye (typically between the
+ * near and far clip plane distances).
+ * Note that fogcoords may be negative, if eye z is source absolute
+ * value must be taken earlier.
+ * Fog blend factors are in the range [0,1].
+ */
+static void
+compute_fog_blend_factors(GLcontext *ctx, GLvector4f *out, const GLvector4f *in)
+{
+ GLfloat end = ctx->Fog.End;
+ GLfloat *v = in->start;
+ GLuint stride = in->stride;
+ GLuint n = in->count;
+ GLfloat (*data)[4] = out->data;
+ GLfloat d;
+ GLuint i;
+
+ out->count = in->count;
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ if (ctx->Fog.Start == ctx->Fog.End)
+ d = 1.0F;
+ else
+ d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
+ const GLfloat z = *v;
+ GLfloat f = (end - z) * d;
+ data[i][0] = CLAMP(f, 0.0F, 1.0F);
+ }
+ break;
+ case GL_EXP:
+ d = ctx->Fog.Density;
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
+ const GLfloat z = *v;
+ NEG_EXP( data[i][0], d * z );
+ }
+ break;
+ case GL_EXP2:
+ d = ctx->Fog.Density*ctx->Fog.Density;
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
+ const GLfloat z = *v;
+ NEG_EXP( data[i][0], d * z * z );
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
+ return;
+ }
+}
+
+
+static GLboolean
+run_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct fog_stage_data *store = FOG_STAGE_DATA(stage);
+ GLvector4f *input;
+
+
+ if (!ctx->Fog.Enabled)
+ return GL_TRUE;
+
+ if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
+ GLuint i;
+ GLfloat *coord;
+ /* Fog is computed from vertex or fragment Z values */
+ /* source = VB->ObjPtr or VB->EyePtr coords */
+ /* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;
+
+ if (!ctx->_NeedEyeCoords) {
+ /* compute fog coords from object coords */
+ const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
+ GLfloat plane[4];
+
+ /* Use this to store calculated eye z values:
+ */
+ input = &store->fogcoord;
+
+ plane[0] = m[2];
+ plane[1] = m[6];
+ plane[2] = m[10];
+ plane[3] = m[14];
+ /* Full eye coords weren't required, just calculate the
+ * eye Z values.
+ */
+ _mesa_dotprod_tab[VB->ObjPtr->size]( (GLfloat *) input->data,
+ 4 * sizeof(GLfloat),
+ VB->ObjPtr, plane );
+
+ input->count = VB->ObjPtr->count;
+
+ /* make sure coords are really positive
+ NOTE should avoid going through array twice */
+ coord = input->start;
+ for (i = 0; i < input->count; i++) {
+ *coord = FABSF(*coord);
+ STRIDE_F(coord, input->stride);
+ }
+ }
+ else {
+ /* fog coordinates = eye Z coordinates - need to copy for ABS */
+ input = &store->fogcoord;
+
+ if (VB->EyePtr->size < 2)
+ _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
+
+ input->stride = 4 * sizeof(GLfloat);
+ input->count = VB->EyePtr->count;
+ coord = VB->EyePtr->start;
+ for (i = 0 ; i < VB->EyePtr->count; i++) {
+ input->data[i][0] = FABSF(coord[2]);
+ STRIDE_F(coord, VB->EyePtr->stride);
+ }
+ }
+ }
+ else {
+ /* use glFogCoord() coordinates */
+ input = VB->AttribPtr[_TNL_ATTRIB_FOG]; /* source data */
+
+ /* input->count may be one if glFogCoord was only called once
+ * before glBegin. But we need to compute fog for all vertices.
+ */
+ input->count = VB->ObjPtr->count;
+
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; /* dest data */
+ }
+
+ if (tnl->_DoVertexFog) {
+ /* compute blend factors from fog coordinates */
+ compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
+ }
+ else {
+ /* results = incoming fog coords (compute fog per-fragment later) */
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
+ }
+
+ VB->FogCoordPtr = VB->AttribPtr[_TNL_ATTRIB_FOG];
+ return GL_TRUE;
+}
+
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean
+alloc_fog_data(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct fog_stage_data *store;
+ stage->privatePtr = MALLOC(sizeof(*store));
+ store = FOG_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
+
+ if (!inited)
+ init_static_data();
+
+ return GL_TRUE;
+}
+
+
+static void
+free_fog_data(struct tnl_pipeline_stage *stage)
+{
+ struct fog_stage_data *store = FOG_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->fogcoord );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
+{
+ "build fog coordinates", /* name */
+ NULL, /* private_data */
+ alloc_fog_data, /* dtr */
+ free_fog_data, /* dtr */
+ NULL, /* check */
+ run_fog_stage /* run -- initially set to init. */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_light.c b/mesalib/src/mesa/tnl/t_vb_light.c
new file mode 100644
index 000000000..f47f99397
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_light.c
@@ -0,0 +1,362 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/light.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "main/mtypes.h"
+
+#include "math/m_translate.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+#define LIGHT_TWOSIDE 0x1
+#define LIGHT_MATERIAL 0x2
+#define MAX_LIGHT_FUNC 0x4
+
+typedef void (*light_func)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input );
+
+/**
+ * Information for updating current material attributes from vertex color,
+ * for GL_COLOR_MATERIAL.
+ */
+struct material_cursor {
+ const GLfloat *ptr; /* points to src vertex color (in VB array) */
+ GLuint stride; /* stride to next vertex color (bytes) */
+ GLfloat *current; /* points to material attribute to update */
+ GLuint size; /* vertex/color size: 1, 2, 3 or 4 */
+};
+
+/**
+ * Data private to this pipeline stage.
+ */
+struct light_stage_data {
+ GLvector4f Input;
+ GLvector4f LitColor[2];
+ GLvector4f LitSecondary[2];
+ GLvector4f LitIndex[2];
+ light_func *light_func_tab;
+
+ struct material_cursor mat[MAT_ATTRIB_MAX];
+ GLuint mat_count;
+ GLuint mat_bitmask;
+};
+
+
+#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
+
+
+
+/**
+ * In the case of colormaterial, the effected material attributes
+ * should already have been bound to point to the incoming color data,
+ * prior to running the pipeline.
+ * This function copies the vertex's color to the material attributes
+ * which are tracking glColor.
+ * It's called per-vertex in the lighting loop.
+ */
+static void
+update_materials(GLcontext *ctx, struct light_stage_data *store)
+{
+ GLuint i;
+
+ for (i = 0 ; i < store->mat_count ; i++) {
+ /* update the material */
+ COPY_CLEAN_4V(store->mat[i].current, store->mat[i].size, store->mat[i].ptr);
+ /* increment src vertex color pointer */
+ STRIDE_F(store->mat[i].ptr, store->mat[i].stride);
+ }
+
+ /* recompute derived light/material values */
+ _mesa_update_material( ctx, store->mat_bitmask );
+ /* XXX we should only call this if we're tracking/changing the specular
+ * exponent.
+ */
+ _mesa_validate_all_lighting_tables( ctx );
+}
+
+
+/**
+ * Prepare things prior to running the lighting stage.
+ * Return number of material attributes which will track vertex color.
+ */
+static GLuint
+prepare_materials(GLcontext *ctx,
+ struct vertex_buffer *VB, struct light_stage_data *store)
+{
+ GLuint i;
+
+ store->mat_count = 0;
+ store->mat_bitmask = 0;
+
+ /* Examine the ColorMaterialBitmask to determine which materials
+ * track vertex color. Override the material attribute's pointer
+ * with the color pointer for each one.
+ */
+ if (ctx->Light.ColorMaterialEnabled) {
+ const GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+ if (bitmask & (1<<i))
+ VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->ColorPtr[0];
+ }
+
+ /* Now, for each material attribute that's tracking vertex color, save
+ * some values (ptr, stride, size, current) that we'll need in
+ * update_materials(), above, that'll actually copy the vertex color to
+ * the material attribute(s).
+ */
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ if (VB->AttribPtr[i]->stride) {
+ const GLuint j = store->mat_count++;
+ const GLuint attr = i - _TNL_ATTRIB_MAT_FRONT_AMBIENT;
+ store->mat[j].ptr = VB->AttribPtr[i]->start;
+ store->mat[j].stride = VB->AttribPtr[i]->stride;
+ store->mat[j].size = VB->AttribPtr[i]->size;
+ store->mat[j].current = ctx->Light.Material.Attrib[attr];
+ store->mat_bitmask |= (1<<attr);
+ }
+ }
+
+ /* FIXME: Is this already done?
+ */
+ _mesa_update_material( ctx, ~0 );
+ _mesa_validate_all_lighting_tables( ctx );
+
+ return store->mat_count;
+}
+
+/* Tables for all the shading functions.
+ */
+static light_func _tnl_light_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC];
+
+#define TAG(x) x
+#define IDX (0)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_twoside
+#define IDX (LIGHT_TWOSIDE)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_material
+#define IDX (LIGHT_MATERIAL)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_twoside_material
+#define IDX (LIGHT_TWOSIDE|LIGHT_MATERIAL)
+#include "t_vb_lighttmp.h"
+
+
+static void init_lighting_tables( void )
+{
+ static int done;
+
+ if (!done) {
+ init_light_tab();
+ init_light_tab_twoside();
+ init_light_tab_material();
+ init_light_tab_twoside_material();
+ done = 1;
+ }
+}
+
+
+static GLboolean run_lighting( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
+ GLuint idx;
+
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ /* Make sure we can talk about position x,y and z:
+ */
+ if (input->size <= 2 && input == VB->ObjPtr) {
+
+ _math_trans_4f( store->Input.data,
+ VB->ObjPtr->data,
+ VB->ObjPtr->stride,
+ GL_FLOAT,
+ VB->ObjPtr->size,
+ 0,
+ VB->Count );
+
+ if (input->size <= 2) {
+ /* Clean z.
+ */
+ _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2);
+ }
+
+ if (input->size <= 1) {
+ /* Clean y.
+ */
+ _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1);
+ }
+
+ input = &store->Input;
+ }
+
+ idx = 0;
+
+ if (prepare_materials( ctx, VB, store ))
+ idx |= LIGHT_MATERIAL;
+
+ if (ctx->Light.Model.TwoSide)
+ idx |= LIGHT_TWOSIDE;
+
+ /* The individual functions know about replaying side-effects
+ * vs. full re-execution.
+ */
+ store->light_func_tab[idx]( ctx, VB, stage, input );
+
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = VB->ColorPtr[0];
+ VB->AttribPtr[_TNL_ATTRIB_COLOR1] = VB->SecondaryColorPtr[0];
+ VB->AttribPtr[_TNL_ATTRIB_COLOR_INDEX] = VB->IndexPtr[0];
+
+ return GL_TRUE;
+}
+
+
+/* Called in place of do_lighting when the light table may have changed.
+ */
+static void validate_lighting( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ light_func *tab;
+
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
+ return;
+
+ if (ctx->Visual.rgbMode) {
+ if (ctx->Light._NeedVertices) {
+ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
+ tab = _tnl_light_spec_tab;
+ else
+ tab = _tnl_light_tab;
+ }
+ else {
+ if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
+ tab = _tnl_light_fast_single_tab;
+ else
+ tab = _tnl_light_fast_tab;
+ }
+ }
+ else
+ tab = _tnl_light_ci_tab;
+
+
+ LIGHT_STAGE_DATA(stage)->light_func_tab = tab;
+
+ /* This and the above should only be done on _NEW_LIGHT:
+ */
+ TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
+}
+
+
+
+/* Called the first time stage->run is called. In effect, don't
+ * allocate data until the first time the stage is run.
+ */
+static GLboolean init_lighting( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct light_stage_data *store;
+ GLuint size = tnl->vb.Size;
+
+ stage->privatePtr = MALLOC(sizeof(*store));
+ store = LIGHT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ /* Do onetime init.
+ */
+ init_lighting_tables();
+
+ _mesa_vector4f_alloc( &store->Input, 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitColor[1], 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitSecondary[0], 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitSecondary[1], 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitIndex[0], 0, size, 32 );
+ _mesa_vector4f_alloc( &store->LitIndex[1], 0, size, 32 );
+
+ store->LitColor[0].size = 4;
+ store->LitColor[1].size = 4;
+ store->LitSecondary[0].size = 3;
+ store->LitSecondary[1].size = 3;
+
+ store->LitIndex[0].size = 1;
+ store->LitIndex[0].stride = sizeof(GLfloat);
+ store->LitIndex[1].size = 1;
+ store->LitIndex[1].stride = sizeof(GLfloat);
+
+ return GL_TRUE;
+}
+
+
+
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+
+ if (store) {
+ _mesa_vector4f_free( &store->Input );
+ _mesa_vector4f_free( &store->LitColor[0] );
+ _mesa_vector4f_free( &store->LitColor[1] );
+ _mesa_vector4f_free( &store->LitSecondary[0] );
+ _mesa_vector4f_free( &store->LitSecondary[1] );
+ _mesa_vector4f_free( &store->LitIndex[0] );
+ _mesa_vector4f_free( &store->LitIndex[1] );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+const struct tnl_pipeline_stage _tnl_lighting_stage =
+{
+ "lighting", /* name */
+ NULL, /* private_data */
+ init_lighting,
+ dtr, /* destroy */
+ validate_lighting,
+ run_lighting
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_lighttmp.h b/mesalib/src/mesa/tnl/t_vb_lighttmp.h
new file mode 100644
index 000000000..124ca3c74
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_lighttmp.h
@@ -0,0 +1,824 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Authors:
+ * Brian Paul
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#if IDX & LIGHT_TWOSIDE
+# define NR_SIDES 2
+#else
+# define NR_SIDES 1
+#endif
+
+
+/* define TRACE to trace lighting code */
+/* #define TRACE 1 */
+
+/*
+ * ctx is the current context
+ * VB is the vertex buffer
+ * stage is the lighting stage-private data
+ * input is the vector of eye or object-space vertex coordinates
+ */
+static void TAG(light_rgba_spec)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ GLfloat sumA[2];
+ GLuint j;
+
+ const GLuint vstride = input->stride;
+ const GLfloat *vertex = (GLfloat *)input->data;
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+ GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+ GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data;
+#endif
+
+ const GLuint nr = VB->Count;
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ VB->ColorPtr[0] = &store->LitColor[0];
+ VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+
+#if IDX & LIGHT_TWOSIDE
+ VB->ColorPtr[1] = &store->LitColor[1];
+ VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+
+
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+
+ for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
+ GLfloat sum[2][3], spec[2][3];
+ struct gl_light *light;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+#if IDX & LIGHT_TWOSIDE
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+#endif
+
+ COPY_3V(sum[0], base[0]);
+ ZERO_3V(spec[0]);
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], base[1]);
+ ZERO_3V(spec[1]);
+#endif
+
+ /* Add contribution from each enabled light source */
+ foreach (light, &ctx->Light.EnabledList) {
+ GLfloat n_dot_h;
+ GLfloat correction;
+ GLint side;
+ GLfloat contrib[3];
+ GLfloat attenuation;
+ GLfloat VP[3]; /* unit vector from vertex to light */
+ GLfloat n_dot_VP; /* n dot VP */
+ GLfloat *h;
+
+ /* compute VP and attenuation */
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* directional light */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ GLfloat d; /* distance from vertex to light */
+
+ SUB_3V(VP, light->_Position, vertex);
+
+ d = (GLfloat) LEN_3FV( VP );
+
+ if (d > 1e-6) {
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ /* spotlight attenuation */
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue; /* this light makes no contribution */
+ }
+ else {
+ GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ GLint k = (GLint) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue; /* this light makes no contribution */
+
+ /* Compute dot product or normal and vector from V to light pos */
+ n_dot_VP = DOT3( normal, VP );
+
+ /* Which side gets the diffuse & specular terms? */
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
+#if IDX & LIGHT_TWOSIDE
+ side = 1;
+ correction = -1;
+ n_dot_VP = -n_dot_VP;
+#else
+ continue;
+#endif
+ }
+ else {
+#if IDX & LIGHT_TWOSIDE
+ ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
+#endif
+ side = 0;
+ correction = 1;
+ }
+
+ /* diffuse term */
+ COPY_3V(contrib, light->_MatAmbient[side]);
+ ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
+ ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
+
+ /* specular term - cannibalize VP... */
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v); /* h = VP + VPe */
+ h = VP;
+ NORMALIZE_3FV(h);
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ h = VP;
+ ACC_3V(h, ctx->_EyeZDir);
+ NORMALIZE_3FV(h);
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = correction * DOT3(normal, h);
+
+ if (n_dot_h > 0.0F) {
+ GLfloat spec_coef;
+ struct gl_shine_tab *tab = ctx->_ShineTable[side];
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
+
+ if (spec_coef > 1.0e-10) {
+ spec_coef *= attenuation;
+ ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
+ light->_MatSpecular[side]);
+ }
+ }
+ } /*loop over lights*/
+
+ COPY_3V( Fcolor[j], sum[0] );
+ COPY_3V( Fspec[j], spec[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ COPY_3V( Bspec[j], spec[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+static void TAG(light_rgba)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLuint j;
+
+ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ GLfloat sumA[2];
+
+ const GLuint vstride = input->stride;
+ const GLfloat *vertex = (GLfloat *) input->data;
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+
+ const GLuint nr = VB->Count;
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ VB->ColorPtr[0] = &store->LitColor[0];
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+
+#if IDX & LIGHT_TWOSIDE
+ VB->ColorPtr[1] = &store->LitColor[1];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+
+ for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
+ GLfloat sum[2][3];
+ struct gl_light *light;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+#if IDX & LIGHT_TWOSIDE
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+#endif
+
+ COPY_3V(sum[0], base[0]);
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], base[1]);
+#endif
+
+ /* Add contribution from each enabled light source */
+ foreach (light, &ctx->Light.EnabledList) {
+
+ GLfloat n_dot_h;
+ GLfloat correction;
+ GLint side;
+ GLfloat contrib[3];
+ GLfloat attenuation = 1.0;
+ GLfloat VP[3]; /* unit vector from vertex to light */
+ GLfloat n_dot_VP; /* n dot VP */
+ GLfloat *h;
+
+ /* compute VP and attenuation */
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* directional light */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ GLfloat d; /* distance from vertex to light */
+
+
+ SUB_3V(VP, light->_Position, vertex);
+
+ d = (GLfloat) LEN_3FV( VP );
+
+ if ( d > 1e-6) {
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ /* spotlight attenuation */
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue; /* this light makes no contribution */
+ }
+ else {
+ GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ GLint k = (GLint) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue; /* this light makes no contribution */
+
+ /* Compute dot product or normal and vector from V to light pos */
+ n_dot_VP = DOT3( normal, VP );
+
+ /* which side are we lighting? */
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
+#if IDX & LIGHT_TWOSIDE
+ side = 1;
+ correction = -1;
+ n_dot_VP = -n_dot_VP;
+#else
+ continue;
+#endif
+ }
+ else {
+#if IDX & LIGHT_TWOSIDE
+ ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
+#endif
+ side = 0;
+ correction = 1;
+ }
+
+ COPY_3V(contrib, light->_MatAmbient[side]);
+
+ /* diffuse term */
+ ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
+
+ /* specular term - cannibalize VP... */
+ {
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v); /* h = VP + VPe */
+ h = VP;
+ NORMALIZE_3FV(h);
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ h = VP;
+ ACC_3V(h, ctx->_EyeZDir);
+ NORMALIZE_3FV(h);
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = correction * DOT3(normal, h);
+
+ if (n_dot_h > 0.0F)
+ {
+ GLfloat spec_coef;
+ struct gl_shine_tab *tab = ctx->_ShineTable[side];
+
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
+
+ ACC_SCALE_SCALAR_3V( contrib, spec_coef,
+ light->_MatSpecular[side]);
+ }
+ }
+
+ ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
+ }
+
+ COPY_3V( Fcolor[j], sum[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+
+
+/* As below, but with just a single light.
+ */
+static void TAG(light_fast_rgba_single)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+ const struct gl_light *light = ctx->Light.EnabledList.next;
+ GLuint j = 0;
+ GLfloat base[2][4];
+#if IDX & LIGHT_MATERIAL
+ const GLuint nr = VB->Count;
+#else
+ const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
+#endif
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ (void) input; /* doesn't refer to Eye or Obj */
+
+ VB->ColorPtr[0] = &store->LitColor[0];
+#if IDX & LIGHT_TWOSIDE
+ VB->ColorPtr[1] = &store->LitColor[1];
+#endif
+
+ if (nr > 1) {
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+ }
+ else {
+ store->LitColor[0].stride = 0;
+ store->LitColor[1].stride = 0;
+ }
+
+ for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
+
+ GLfloat n_dot_VP;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+#endif
+
+ /* No attenuation, so incoporate _MatAmbient into base color.
+ */
+#if !(IDX & LIGHT_MATERIAL)
+ if ( j == 0 )
+#endif
+ {
+ COPY_3V(base[0], light->_MatAmbient[0]);
+ ACC_3V(base[0], ctx->Light._BaseColor[0] );
+ base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(base[1], light->_MatAmbient[1]);
+ ACC_3V(base[1], ctx->Light._BaseColor[1]);
+ base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+ }
+
+ n_dot_VP = DOT3(normal, light->_VP_inf_norm);
+
+ if (n_dot_VP < 0.0F) {
+#if IDX & LIGHT_TWOSIDE
+ GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
+ GLfloat sum[3];
+ COPY_3V(sum, base[1]);
+ ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
+ if (n_dot_h > 0.0F) {
+ GLfloat spec;
+ GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
+ ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
+ }
+ COPY_3V(Bcolor[j], sum );
+ Bcolor[j][3] = base[1][3];
+#endif
+ COPY_4FV(Fcolor[j], base[0]);
+ }
+ else {
+ GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
+ GLfloat sum[3];
+ COPY_3V(sum, base[0]);
+ ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
+ if (n_dot_h > 0.0F) {
+ GLfloat spec;
+ GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+ ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
+
+ }
+ COPY_3V(Fcolor[j], sum );
+ Fcolor[j][3] = base[0][3];
+#if IDX & LIGHT_TWOSIDE
+ COPY_4FV(Bcolor[j], base[1]);
+#endif
+ }
+ }
+}
+
+
+/* Light infinite lights
+ */
+static void TAG(light_fast_rgba)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLfloat sumA[2];
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+ GLuint j = 0;
+#if IDX & LIGHT_MATERIAL
+ const GLuint nr = VB->Count;
+#else
+ const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
+#endif
+ const struct gl_light *light;
+
+#ifdef TRACE
+ fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
+#endif
+
+ (void) input;
+
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+
+ VB->ColorPtr[0] = &store->LitColor[0];
+#if IDX & LIGHT_TWOSIDE
+ VB->ColorPtr[1] = &store->LitColor[1];
+#endif
+
+ if (nr > 1) {
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+ }
+ else {
+ store->LitColor[0].stride = 0;
+ store->LitColor[1].stride = 0;
+ }
+
+ for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
+
+ GLfloat sum[2][3];
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+#if IDX & LIGHT_TWOSIDE
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+#endif
+
+
+ COPY_3V(sum[0], ctx->Light._BaseColor[0]);
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], ctx->Light._BaseColor[1]);
+#endif
+
+ foreach (light, &ctx->Light.EnabledList) {
+ GLfloat n_dot_h, n_dot_VP, spec;
+
+ ACC_3V(sum[0], light->_MatAmbient[0]);
+#if IDX & LIGHT_TWOSIDE
+ ACC_3V(sum[1], light->_MatAmbient[1]);
+#endif
+
+ n_dot_VP = DOT3(normal, light->_VP_inf_norm);
+
+ if (n_dot_VP > 0.0F) {
+ ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
+ n_dot_h = DOT3(normal, light->_h_inf_norm);
+ if (n_dot_h > 0.0F) {
+ struct gl_shine_tab *tab = ctx->_ShineTable[0];
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
+ ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]);
+ }
+ }
+#if IDX & LIGHT_TWOSIDE
+ else {
+ ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
+ n_dot_h = -DOT3(normal, light->_h_inf_norm);
+ if (n_dot_h > 0.0F) {
+ struct gl_shine_tab *tab = ctx->_ShineTable[1];
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
+ ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]);
+ }
+ }
+#endif
+ }
+
+ COPY_3V( Fcolor[j], sum[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+
+
+
+/*
+ * Use current lighting/material settings to compute the color indexes
+ * for an array of vertices.
+ * Input: n - number of vertices to light
+ * side - 0=use front material, 1=use back material
+ * vertex - array of [n] vertex position in eye coordinates
+ * normal - array of [n] surface normal vector
+ * Output: indexResult - resulting array of [n] color indexes
+ */
+static void TAG(light_ci)( GLcontext *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLuint j;
+ const GLuint vstride = input->stride;
+ const GLfloat *vertex = (GLfloat *) input->data;
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLfloat *indexResult[2];
+ const GLuint nr = VB->Count;
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ VB->IndexPtr[0] = &store->LitIndex[0];
+#if IDX & LIGHT_TWOSIDE
+ VB->IndexPtr[1] = &store->LitIndex[1];
+#endif
+
+ indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data;
+#if IDX & LIGHT_TWOSIDE
+ indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data;
+#endif
+
+ /* loop over vertices */
+ for (j=0; j<nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal, nstride)) {
+ GLfloat diffuse[2], specular[2];
+ GLuint side = 0;
+ struct gl_light *light;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+#endif
+
+ diffuse[0] = specular[0] = 0.0F;
+
+#if IDX & LIGHT_TWOSIDE
+ diffuse[1] = specular[1] = 0.0F;
+#endif
+
+ /* Accumulate diffuse and specular from each light source */
+ foreach (light, &ctx->Light.EnabledList) {
+
+ GLfloat attenuation = 1.0F;
+ GLfloat VP[3]; /* unit vector from vertex to light */
+ GLfloat n_dot_VP; /* dot product of l and n */
+ GLfloat *h, n_dot_h, correction = 1.0;
+
+ /* compute l and attenuation */
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* directional light */
+ COPY_3V(VP, light->_VP_inf_norm);
+ }
+ else {
+ GLfloat d; /* distance from vertex to light */
+
+ SUB_3V(VP, light->_Position, vertex);
+
+ d = (GLfloat) LEN_3FV( VP );
+ if ( d > 1e-6) {
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ /* spotlight attenuation */
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+ if (PV_dot_dir < light->_CosCutoff) {
+ continue; /* this light makes no contribution */
+ }
+ else {
+ GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ GLint k = (GLint) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue; /* this light makes no contribution */
+
+ n_dot_VP = DOT3( normal, VP );
+
+ /* which side are we lighting? */
+ if (n_dot_VP < 0.0F) {
+#if IDX & LIGHT_TWOSIDE
+ side = 1;
+ correction = -1;
+ n_dot_VP = -n_dot_VP;
+#else
+ continue;
+#endif
+ }
+
+ /* accumulate diffuse term */
+ diffuse[side] += n_dot_VP * light->_dli * attenuation;
+
+ /* specular term */
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v); /* h = VP + VPe */
+ h = VP;
+ NORMALIZE_3FV(h);
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ h = VP;
+ /* Strangely, disabling this addition fixes a conformance
+ * problem. If this code is enabled, l_sed.c fails.
+ */
+ /*ACC_3V(h, ctx->_EyeZDir);*/
+ NORMALIZE_3FV(h);
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = correction * DOT3(normal, h);
+ if (n_dot_h > 0.0F) {
+ GLfloat spec_coef;
+ struct gl_shine_tab *tab = ctx->_ShineTable[side];
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
+ specular[side] += spec_coef * light->_sli * attenuation;
+ }
+ } /*loop over lights*/
+
+ /* Now compute final color index */
+ for (side = 0 ; side < NR_SIDES ; side++) {
+ const GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES + side];
+ GLfloat index;
+
+ if (specular[side] > 1.0F) {
+ index = ind[MAT_INDEX_SPECULAR];
+ }
+ else {
+ GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT];
+ GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT];
+ index = (ind[MAT_INDEX_AMBIENT]
+ + diffuse[side] * (1.0F-specular[side]) * d_a
+ + specular[side] * s_a);
+ if (index > ind[MAT_INDEX_SPECULAR]) {
+ index = ind[MAT_INDEX_SPECULAR];
+ }
+ }
+ indexResult[side][j] = index;
+ }
+ } /*for vertex*/
+}
+
+
+
+static void TAG(init_light_tab)( void )
+{
+ _tnl_light_tab[IDX] = TAG(light_rgba);
+ _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
+ _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
+ _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
+ _tnl_light_ci_tab[IDX] = TAG(light_ci);
+}
+
+
+#undef TAG
+#undef IDX
+#undef NR_SIDES
diff --git a/mesalib/src/mesa/tnl/t_vb_normals.c b/mesalib/src/mesa/tnl/t_vb_normals.c
new file mode 100644
index 000000000..a4821cc1c
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_normals.c
@@ -0,0 +1,189 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct normal_stage_data {
+ normal_func NormalTransform;
+ GLvector4f normal;
+};
+
+#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
+
+
+static GLboolean
+run_normal_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *lengths;
+
+ if (!store->NormalTransform)
+ return GL_TRUE;
+
+ /* We can only use the display list's saved normal lengths if we've
+ * got a transformation matrix with uniform scaling.
+ */
+ if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top))
+ lengths = NULL;
+ else
+ lengths = VB->NormalLengthPtr;
+
+ store->NormalTransform( ctx->ModelviewMatrixStack.Top,
+ ctx->_ModelViewInvScale,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL], /* input normals */
+ lengths,
+ &store->normal ); /* resulting normals */
+
+ if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) {
+ store->normal.stride = 4 * sizeof(GLfloat);
+ }
+ else {
+ store->normal.stride = 0;
+ }
+
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal;
+ VB->NormalPtr = &store->normal;
+
+ VB->NormalLengthPtr = NULL; /* no longer valid */
+ return GL_TRUE;
+}
+
+
+/**
+ * Examine current GL state and set the store->NormalTransform pointer
+ * to point to the appropriate normal transformation routine.
+ */
+static void
+validate_normal_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+
+ if (ctx->VertexProgram._Current ||
+ (!ctx->Light.Enabled &&
+ !(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) {
+ store->NormalTransform = NULL;
+ return;
+ }
+
+ if (ctx->_NeedEyeCoords) {
+ /* Eye coordinates are needed, for whatever reasons.
+ * Do lighting in eye coordinates, as the GL spec says.
+ */
+ GLuint transform = NORM_TRANSFORM_NO_ROT;
+
+ if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) {
+ /* need to do full (3x3) matrix transform */
+ transform = NORM_TRANSFORM;
+ }
+
+ if (ctx->Transform.Normalize) {
+ store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
+ }
+ else if (ctx->Transform.RescaleNormals &&
+ ctx->_ModelViewInvScale != 1.0) {
+ store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
+ }
+ else {
+ store->NormalTransform = _mesa_normal_tab[transform];
+ }
+ }
+ else {
+ /* We don't need eye coordinates.
+ * Do lighting in object coordinates. Thus, we don't need to fully
+ * transform normal vectors (just leave them in object coordinates)
+ * but we still need to do normalization/rescaling if enabled.
+ */
+ if (ctx->Transform.Normalize) {
+ store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
+ }
+ else if (!ctx->Transform.RescaleNormals &&
+ ctx->_ModelViewInvScale != 1.0) {
+ store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
+ }
+ else {
+ store->NormalTransform = NULL;
+ }
+ }
+}
+
+
+/**
+ * Allocate stage's private data (storage for transformed normals).
+ */
+static GLboolean
+alloc_normal_data(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct normal_stage_data *store;
+
+ stage->privatePtr = _mesa_malloc(sizeof(*store));
+ store = NORMAL_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
+ return GL_TRUE;
+}
+
+
+/**
+ * Free stage's private data.
+ */
+static void
+free_normal_data(struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->normal );
+ _mesa_free( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_normal_transform_stage =
+{
+ "normal transform", /* name */
+ NULL, /* privatePtr */
+ alloc_normal_data, /* create */
+ free_normal_data, /* destroy */
+ validate_normal_stage, /* validate */
+ run_normal_stage /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_points.c b/mesalib/src/mesa/tnl/t_vb_points.c
new file mode 100644
index 000000000..a52505b4b
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_points.c
@@ -0,0 +1,114 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/dd.h"
+#include "main/imports.h"
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct point_stage_data {
+ GLvector4f PointSize;
+};
+
+#define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr)
+
+
+/**
+ * Compute point size for each vertex from the vertex eye-space Z
+ * coordinate and the point size attenuation factors.
+ * Only done when point size attenuation is enabled and vertex program is
+ * disabled.
+ */
+static GLboolean
+run_point_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ if (ctx->Point._Attenuated && !ctx->VertexProgram._Current) {
+ struct point_stage_data *store = POINT_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *eyeCoord = (GLfloat *) VB->EyePtr->data + 2;
+ const GLint eyeCoordStride = VB->EyePtr->stride / sizeof(GLfloat);
+ const GLfloat p0 = ctx->Point.Params[0];
+ const GLfloat p1 = ctx->Point.Params[1];
+ const GLfloat p2 = ctx->Point.Params[2];
+ const GLfloat pointSize = ctx->Point.Size;
+ GLfloat (*size)[4] = store->PointSize.data;
+ GLuint i;
+
+ for (i = 0; i < VB->Count; i++) {
+ const GLfloat dist = FABSF(*eyeCoord);
+ const GLfloat q = p0 + dist * (p1 + dist * p2);
+ const GLfloat atten = (q != 0.0) ? SQRTF(1.0 / q) : 1.0;
+ size[i][0] = pointSize * atten; /* clamping done in rasterization */
+ eyeCoord += eyeCoordStride;
+ }
+
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize;
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+alloc_point_data(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct point_stage_data *store;
+ stage->privatePtr = _mesa_malloc(sizeof(*store));
+ store = POINT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 );
+ return GL_TRUE;
+}
+
+
+static void
+free_point_data(struct tnl_pipeline_stage *stage)
+{
+ struct point_stage_data *store = POINT_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->PointSize );
+ _mesa_free( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_point_attenuation_stage =
+{
+ "point size attenuation", /* name */
+ NULL, /* stage private data */
+ alloc_point_data, /* alloc data */
+ free_point_data, /* destructor */
+ NULL,
+ run_point_stage /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c
new file mode 100644
index 000000000..dc954bcba
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_program.c
@@ -0,0 +1,563 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+
+/**
+ * \file tnl/t_vb_program.c
+ * \brief Pipeline stage for executing vertex programs.
+ * \author Brian Paul, Keith Whitwell
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_statevars.h"
+#include "shader/prog_execute.h"
+#include "swrast/s_context.h"
+#include "swrast/s_texfilter.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+#ifdef NAN_CHECK
+/** Check for NaNs and very large values */
+static INLINE void
+check_float(float x)
+{
+ assert(!IS_INF_OR_NAN(x));
+ assert(1.0e-15 <= x && x <= 1.0e15);
+}
+#endif
+
+
+/*!
+ * Private storage for the vertex program pipeline stage.
+ */
+struct vp_stage_data {
+ /** The results of running the vertex program go into these arrays. */
+ GLvector4f results[VERT_RESULT_MAX];
+
+ GLvector4f ndcCoords; /**< normalized device coords */
+ GLubyte *clipmask; /**< clip flags */
+ GLubyte ormask, andmask; /**< for clipping */
+};
+
+
+#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
+
+
+static void
+userclip( GLcontext *ctx,
+ GLvector4f *clip,
+ GLubyte *clipmask,
+ GLubyte *clipormask,
+ GLubyte *clipandmask )
+{
+ GLuint p;
+
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ GLuint nr, i;
+ 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 = (GLfloat *)clip->data;
+ GLuint stride = clip->stride;
+ GLuint count = clip->count;
+
+ for (nr = 0, i = 0 ; i < count ; i++) {
+ GLfloat dp = (coord[0] * a +
+ coord[1] * b +
+ coord[2] * c +
+ coord[3] * d);
+
+ if (dp < 0) {
+ nr++;
+ clipmask[i] |= CLIP_USER_BIT;
+ }
+
+ STRIDE_F(coord, stride);
+ }
+
+ if (nr > 0) {
+ *clipormask |= CLIP_USER_BIT;
+ if (nr == count) {
+ *clipandmask |= CLIP_USER_BIT;
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+static GLboolean
+do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ /* Cliptest and perspective divide. Clip functions must clear
+ * the clipmask.
+ */
+ store->ormask = 0;
+ store->andmask = CLIP_FRUSTUM_BITS;
+
+ if (tnl->NeedNdcCoords) {
+ VB->NdcPtr =
+ _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ &store->ndcCoords,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+ }
+ else {
+ VB->NdcPtr = NULL;
+ _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ NULL,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+ }
+
+ if (store->andmask) {
+ /* All vertices are outside the frustum */
+ return GL_FALSE;
+ }
+
+ /* Test userclip planes. This contributes to VB->ClipMask.
+ */
+ /** XXX NEW_SLANG _Enabled ??? */
+ if (ctx->Transform.ClipPlanesEnabled && (!ctx->VertexProgram._Enabled ||
+ ctx->VertexProgram.Current->IsPositionInvariant)) {
+ userclip( ctx,
+ VB->ClipPtr,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+
+ if (store->andmask) {
+ return GL_FALSE;
+ }
+ }
+
+ VB->ClipAndMask = store->andmask;
+ VB->ClipOrMask = store->ormask;
+ VB->ClipMask = store->clipmask;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * XXX the texture sampling code in this module is a bit of a hack.
+ * The texture sampling code is in swrast, though it doesn't have any
+ * real dependencies on the rest of swrast. It should probably be
+ * moved into main/ someday.
+ */
+static void
+vp_fetch_texel(GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda,
+ GLuint unit, GLfloat color[4])
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ /* XXX use a float-valued TextureSample routine here!!! */
+ swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
+ 1, (const GLfloat (*)[4]) texcoord,
+ &lambda, (GLfloat (*)[4]) color);
+}
+
+
+/**
+ * Called via ctx->Driver.ProgramStringNotify() after a new vertex program
+ * string has been parsed.
+ */
+void
+_tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program)
+{
+ /* No-op.
+ * If we had derived anything from the program that was private to this
+ * stage we'd recompute/validate it here.
+ */
+}
+
+
+/**
+ * Initialize virtual machine state prior to executing vertex program.
+ */
+static void
+init_machine(GLcontext *ctx, struct gl_program_machine *machine)
+{
+ /* Input registers get initialized from the current vertex attribs */
+ MEMCPY(machine->VertAttribs, ctx->Current.Attrib,
+ MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat));
+
+ if (ctx->VertexProgram._Current->IsNVProgram) {
+ GLuint i;
+ /* Output/result regs are initialized to [0,0,0,1] */
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
+ ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
+ }
+ /* Temp regs are initialized to [0,0,0,0] */
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
+ ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ for (i = 0; i < MAX_VERTEX_PROGRAM_ADDRESS_REGS; i++) {
+ ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0);
+ }
+ }
+
+ machine->NumDeriv = 0;
+
+ /* init condition codes */
+ machine->CondCodes[0] = COND_EQ;
+ machine->CondCodes[1] = COND_EQ;
+ machine->CondCodes[2] = COND_EQ;
+ machine->CondCodes[3] = COND_EQ;
+
+ /* init call stack */
+ machine->StackDepth = 0;
+
+ machine->FetchTexelLod = vp_fetch_texel;
+ machine->FetchTexelDeriv = NULL; /* not used by vertex programs */
+
+ machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits;
+}
+
+
+/**
+ * Map the texture images which the vertex program will access (if any).
+ */
+static void
+map_textures(GLcontext *ctx, const struct gl_vertex_program *vp)
+{
+ GLuint u;
+
+ if (!ctx->Driver.MapTexture)
+ return;
+
+ for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
+ if (vp->Base.TexturesUsed[u]) {
+ /* Note: _Current *should* correspond to the target indicated
+ * in TexturesUsed[u].
+ */
+ ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[u]._Current);
+ }
+ }
+}
+
+
+/**
+ * Unmap the texture images which were used by the vertex program (if any).
+ */
+static void
+unmap_textures(GLcontext *ctx, const struct gl_vertex_program *vp)
+{
+ GLuint u;
+
+ if (!ctx->Driver.MapTexture)
+ return;
+
+ for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
+ if (vp->Base.TexturesUsed[u]) {
+ /* Note: _Current *should* correspond to the target indicated
+ * in TexturesUsed[u].
+ */
+ ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[u]._Current);
+ }
+ }
+}
+
+
+/**
+ * This function executes vertex programs
+ */
+static GLboolean
+run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vp_stage_data *store = VP_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct gl_vertex_program *program = ctx->VertexProgram._Current;
+ struct gl_program_machine machine;
+ GLuint outputs[VERT_RESULT_MAX], numOutputs;
+ GLuint i, j;
+
+ if (!program)
+ return GL_TRUE;
+
+ if (program->IsNVProgram) {
+ _mesa_load_tracked_matrices(ctx);
+ }
+ else {
+ /* ARB program or vertex shader */
+ _mesa_load_state_parameters(ctx, program->Base.Parameters);
+ }
+
+ /* make list of outputs to save some time below */
+ numOutputs = 0;
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (program->Base.OutputsWritten & (1 << i)) {
+ outputs[numOutputs++] = i;
+ }
+ }
+
+ map_textures(ctx, program);
+
+ for (i = 0; i < VB->Count; i++) {
+ GLuint attr;
+
+ init_machine(ctx, &machine);
+
+#if 0
+ printf("Input %d: %f, %f, %f, %f\n", i,
+ VB->AttribPtr[0]->data[i][0],
+ VB->AttribPtr[0]->data[i][1],
+ VB->AttribPtr[0]->data[i][2],
+ VB->AttribPtr[0]->data[i][3]);
+ printf(" color: %f, %f, %f, %f\n",
+ VB->AttribPtr[3]->data[i][0],
+ VB->AttribPtr[3]->data[i][1],
+ VB->AttribPtr[3]->data[i][2],
+ VB->AttribPtr[3]->data[i][3]);
+ printf(" normal: %f, %f, %f, %f\n",
+ VB->AttribPtr[2]->data[i][0],
+ VB->AttribPtr[2]->data[i][1],
+ VB->AttribPtr[2]->data[i][2],
+ VB->AttribPtr[2]->data[i][3]);
+#endif
+
+ /* the vertex array case */
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if (program->Base.InputsRead & (1 << attr)) {
+ const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
+ const GLuint size = VB->AttribPtr[attr]->size;
+ const GLuint stride = VB->AttribPtr[attr]->stride;
+ const GLfloat *data = (GLfloat *) (ptr + stride * i);
+#ifdef NAN_CHECK
+ check_float(data[0]);
+ check_float(data[1]);
+ check_float(data[2]);
+ check_float(data[3]);
+#endif
+ COPY_CLEAN_4V(machine.VertAttribs[attr], size, data);
+ }
+ }
+
+ /* execute the program */
+ _mesa_execute_program(ctx, &program->Base, &machine);
+
+ /* copy the output registers into the VB->attribs arrays */
+ for (j = 0; j < numOutputs; j++) {
+ const GLuint attr = outputs[j];
+#ifdef NAN_CHECK
+ check_float(machine.Outputs[attr][0]);
+ check_float(machine.Outputs[attr][1]);
+ check_float(machine.Outputs[attr][2]);
+ check_float(machine.Outputs[attr][3]);
+#endif
+ COPY_4V(store->results[attr].data[i], machine.Outputs[attr]);
+ }
+#ifdef NAN_CHECK
+ ASSERT(machine.Outputs[0][3] != 0.0F);
+#endif
+#if 0
+ printf("HPOS: %f %f %f %f\n",
+ machine.Outputs[0][0],
+ machine.Outputs[0][1],
+ machine.Outputs[0][2],
+ machine.Outputs[0][3]);
+#endif
+ }
+
+ unmap_textures(ctx, program);
+
+ /* Fixup fog and point size results if needed */
+ if (program->IsNVProgram) {
+ if (ctx->Fog.Enabled &&
+ (program->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) {
+ for (i = 0; i < VB->Count; i++) {
+ store->results[VERT_RESULT_FOGC].data[i][0] = 1.0;
+ }
+ }
+
+ if (ctx->VertexProgram.PointSizeEnabled &&
+ (program->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) {
+ for (i = 0; i < VB->Count; i++) {
+ store->results[VERT_RESULT_PSIZ].data[i][0] = ctx->Point.Size;
+ }
+ }
+ }
+
+ if (program->IsPositionInvariant) {
+ /* We need the exact same transform as in the fixed function path here
+ * to guarantee invariance, depending on compiler optimization flags
+ * results could be different otherwise.
+ */
+ VB->ClipPtr = TransformRaw( &store->results[0],
+ &ctx->_ModelProjectMatrix,
+ VB->AttribPtr[0] );
+
+ /* Drivers expect this to be clean to element 4...
+ */
+ switch (VB->ClipPtr->size) {
+ case 1:
+ /* impossible */
+ case 2:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+ /* fall-through */
+ case 3:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+ /* fall-through */
+ case 4:
+ break;
+ }
+ }
+ else {
+ /* Setup the VB pointers so that the next pipeline stages get
+ * their data from the right place (the program output arrays).
+ */
+ VB->ClipPtr = &store->results[VERT_RESULT_HPOS];
+ VB->ClipPtr->size = 4;
+ VB->ClipPtr->count = VB->Count;
+ }
+
+ VB->ColorPtr[0] = &store->results[VERT_RESULT_COL0];
+ VB->ColorPtr[1] = &store->results[VERT_RESULT_BFC0];
+ VB->SecondaryColorPtr[0] = &store->results[VERT_RESULT_COL1];
+ VB->SecondaryColorPtr[1] = &store->results[VERT_RESULT_BFC1];
+ VB->FogCoordPtr = &store->results[VERT_RESULT_FOGC];
+
+ VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VERT_RESULT_COL0];
+ VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VERT_RESULT_COL1];
+ VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VERT_RESULT_FOGC];
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VERT_RESULT_PSIZ];
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ VB->TexCoordPtr[i] =
+ VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]
+ = &store->results[VERT_RESULT_TEX0 + i];
+ }
+
+ for (i = 0; i < ctx->Const.MaxVarying; i++) {
+ if (program->Base.OutputsWritten & (1 << (VERT_RESULT_VAR0 + i))) {
+ /* Note: varying results get put into the generic attributes */
+ VB->AttribPtr[VERT_ATTRIB_GENERIC0+i]
+ = &store->results[VERT_RESULT_VAR0 + i];
+ }
+ }
+
+
+ /* Perform NDC and cliptest operations:
+ */
+ return do_ndc_cliptest(ctx, store);
+}
+
+
+/**
+ * Called the first time stage->run is called. In effect, don't
+ * allocate data until the first time the stage is run.
+ */
+static GLboolean
+init_vp(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &(tnl->vb);
+ struct vp_stage_data *store;
+ const GLuint size = VB->Size;
+ GLuint i;
+
+ stage->privatePtr = MALLOC(sizeof(*store));
+ store = VP_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ /* Allocate arrays of vertex output values */
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ _mesa_vector4f_alloc( &store->results[i], 0, size, 32 );
+ store->results[i].size = 4;
+ }
+
+ /* a few other misc allocations */
+ _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
+ store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Destructor for this pipeline stage.
+ */
+static void
+dtr(struct tnl_pipeline_stage *stage)
+{
+ struct vp_stage_data *store = VP_STAGE_DATA(stage);
+
+ if (store) {
+ GLuint i;
+
+ /* free the vertex program result arrays */
+ for (i = 0; i < VERT_RESULT_MAX; i++)
+ _mesa_vector4f_free( &store->results[i] );
+
+ /* free misc arrays */
+ _mesa_vector4f_free( &store->ndcCoords );
+ ALIGN_FREE( store->clipmask );
+
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+static void
+validate_vp_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage)
+{
+ if (ctx->VertexProgram._Current) {
+ _swrast_update_texture_samplers(ctx);
+ }
+}
+
+
+
+/**
+ * Public description of this pipeline stage.
+ */
+const struct tnl_pipeline_stage _tnl_vertex_program_stage =
+{
+ "vertex-program",
+ NULL, /* private_data */
+ init_vp, /* create */
+ dtr, /* destroy */
+ validate_vp_stage, /* validate */
+ run_vp /* run -- initially set to ctr */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_render.c b/mesalib/src/mesa/tnl/t_vb_render.c
new file mode 100644
index 000000000..c1bebc994
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_render.c
@@ -0,0 +1,347 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "t_pipeline.h"
+
+
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#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 "t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* This does NOT include the CLIP_USER_BIT! */
+#define CLIPMASK (CLIP_FRUSTUM_BITS | CLIP_CULL_BIT)
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & CLIPMASK)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & CLIPMASK)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&CLIPMASK))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) stipple
+
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+
+static GLboolean run_render( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do
+ {
+ GLuint i;
+
+ for (i = 0 ; i < VB->PrimitiveCount ; i++)
+ {
+ GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
+ GLuint start = VB->Primitive[i].start;
+ GLuint length = VB->Primitive[i].count;
+
+ assert((prim & PRIM_MODE_MASK) <= GL_POLYGON);
+
+ if (MESA_VERBOSE & VERBOSE_PRIMS)
+ _mesa_debug(NULL, "MESA prim %s %d..%d\n",
+ _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
+ start, start+length);
+
+ if (length)
+ tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ tnl->Driver.Render.Finish( ctx );
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+
+
+const struct tnl_pipeline_stage _tnl_render_stage =
+{
+ "render", /* name */
+ NULL, /* private data */
+ NULL, /* creator */
+ NULL, /* destructor */
+ NULL, /* validate */
+ run_render /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_rendertmp.h b/mesalib/src/mesa/tnl/t_vb_rendertmp.h
new file mode 100644
index 000000000..75f6f55bd
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_rendertmp.h
@@ -0,0 +1,486 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef POSTFIX
+#define POSTFIX
+#endif
+
+#ifndef INIT
+#define INIT(x)
+#endif
+
+#ifndef NEED_EDGEFLAG_SETUP
+#define NEED_EDGEFLAG_SETUP 0
+#define EDGEFLAG_GET(a) 0
+#define EDGEFLAG_SET(a,b) (void)b
+#endif
+
+#ifndef RESET_STIPPLE
+#define RESET_STIPPLE
+#endif
+
+#ifndef TEST_PRIM_END
+#define TEST_PRIM_END(prim) (flags & PRIM_END)
+#define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN)
+#endif
+
+#ifndef ELT
+#define ELT(x) x
+#endif
+
+#ifndef RENDER_TAB_QUALIFIER
+#define RENDER_TAB_QUALIFIER static
+#endif
+
+static void TAG(render_points)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_POINTS);
+ RENDER_POINTS( start, count );
+ POSTFIX;
+}
+
+static void TAG(render_lines)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_LINES);
+ for (j=start+1; j<count; j+=2 ) {
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_line_strip)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_LINE_STRIP);
+
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+
+ for (j=start+1; j<count; j++ ) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_line_loop)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint i;
+ LOCAL_VARS;
+
+ (void) flags;
+
+ INIT(GL_LINE_LOOP);
+
+ if (start+1 < count) {
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(start), ELT(start+1) );
+ else
+ RENDER_LINE( ELT(start+1), ELT(start) );
+ }
+
+ for ( i = start+2 ; i < count ; i++) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(i-1), ELT(i) );
+ else
+ RENDER_LINE( ELT(i), ELT(i-1) );
+ }
+
+ if ( TEST_PRIM_END(flags)) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(count-1), ELT(start) );
+ else
+ RENDER_LINE( ELT(start), ELT(count-1) );
+ }
+ }
+
+ POSTFIX;
+}
+
+
+static void TAG(render_triangles)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_TRIANGLES);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2; j<count; j+=3) {
+ /* Leave the edgeflags as supplied by the user.
+ */
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
+ }
+ } else {
+ for (j=start+2; j<count; j+=3) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
+ }
+ }
+ POSTFIX;
+}
+
+
+
+static void TAG(render_tri_strip)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ GLuint parity = 0;
+ LOCAL_VARS;
+
+ INIT(GL_TRIANGLE_STRIP);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2;j<count;j++,parity^=1) {
+ GLuint ej2, ej1, ej;
+ GLboolean ef2, ef1, ef;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
+ ej2 = ELT(j-2+parity);
+ ej1 = ELT(j-1-parity);
+ ej = ELT(j);
+ }
+ else {
+ ej2 = ELT(j-1+parity);
+ ej1 = ELT(j-parity);
+ ej = ELT(j-2);
+ }
+ ef2 = EDGEFLAG_GET( ej2 );
+ ef1 = EDGEFLAG_GET( ej1 );
+ ef = EDGEFLAG_GET( ej );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ej2, GL_TRUE );
+ EDGEFLAG_SET( ej1, GL_TRUE );
+ EDGEFLAG_SET( ej, GL_TRUE );
+ RENDER_TRI( ej2, ej1, ej );
+ EDGEFLAG_SET( ej2, ef2 );
+ EDGEFLAG_SET( ej1, ef1 );
+ EDGEFLAG_SET( ej, ef );
+ }
+ } else {
+ for (j=start+2; j<count ; j++, parity^=1) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
+ }
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_tri_fan)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_TRIANGLE_FAN);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2;j<count;j++) {
+ /* For trifans, all edges are boundary.
+ */
+ GLuint ejs = ELT(start);
+ GLuint ej1 = ELT(j-1);
+ GLuint ej = ELT(j);
+ GLboolean efs = EDGEFLAG_GET( ejs );
+ GLboolean ef1 = EDGEFLAG_GET( ej1 );
+ GLboolean ef = EDGEFLAG_GET( ej );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ejs, GL_TRUE );
+ EDGEFLAG_SET( ej1, GL_TRUE );
+ EDGEFLAG_SET( ej, GL_TRUE );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ejs, ej1, ej);
+ else
+ RENDER_TRI( ej, ejs, ej1);
+ EDGEFLAG_SET( ejs, efs );
+ EDGEFLAG_SET( ej1, ef1 );
+ EDGEFLAG_SET( ej, ef );
+ }
+ } else {
+ for (j=start+2;j<count;j++) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
+ }
+ }
+
+ POSTFIX;
+}
+
+
+static void TAG(render_poly)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j = start+2;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_POLYGON);
+ if (NEED_EDGEFLAG_SETUP) {
+ GLboolean efstart = EDGEFLAG_GET( ELT(start) );
+ GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
+
+ /* If the primitive does not begin here, the first edge
+ * is non-boundary.
+ */
+ if (!TEST_PRIM_BEGIN(flags))
+ EDGEFLAG_SET( ELT(start), GL_FALSE );
+ else {
+ RESET_STIPPLE;
+ }
+
+ /* If the primitive does not end here, the final edge is
+ * non-boundary.
+ */
+ if (!TEST_PRIM_END(flags))
+ EDGEFLAG_SET( ELT(count-1), GL_FALSE );
+
+ /* Draw the first triangles (possibly zero)
+ */
+ if (j+1<count) {
+ GLboolean ef = EDGEFLAG_GET( ELT(j) );
+ EDGEFLAG_SET( ELT(j), GL_FALSE );
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ EDGEFLAG_SET( ELT(j), ef );
+ j++;
+
+ /* Don't render the first edge again:
+ */
+ EDGEFLAG_SET( ELT(start), GL_FALSE );
+
+ for (;j+1<count;j++) {
+ GLboolean efj = EDGEFLAG_GET( ELT(j) );
+ EDGEFLAG_SET( ELT(j), GL_FALSE );
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ EDGEFLAG_SET( ELT(j), efj );
+ }
+ }
+
+ /* Draw the last or only triangle
+ */
+ if (j < count)
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+
+ /* Restore the first and last edgeflags:
+ */
+ EDGEFLAG_SET( ELT(count-1), efcount );
+ EDGEFLAG_SET( ELT(start), efstart );
+
+ }
+ else {
+ for (j=start+2;j<count;j++) {
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_quads)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_QUADS);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+3; j<count; j+=4) {
+ /* Use user-specified edgeflags for quads.
+ */
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
+ }
+ } else {
+ for (j=start+3; j<count; j+=4) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_quad_strip)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_QUAD_STRIP);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+3;j<count;j+=2) {
+ /* All edges are boundary. Set edgeflags to 1, draw the
+ * quad, and restore them to the original values.
+ */
+ GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
+ GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
+ GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
+ GLboolean ef = EDGEFLAG_GET( ELT(j) );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ELT(j-3), GL_TRUE );
+ EDGEFLAG_SET( ELT(j-2), GL_TRUE );
+ EDGEFLAG_SET( ELT(j-1), GL_TRUE );
+ EDGEFLAG_SET( ELT(j), GL_TRUE );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
+ EDGEFLAG_SET( ELT(j-3), ef3 );
+ EDGEFLAG_SET( ELT(j-2), ef2 );
+ EDGEFLAG_SET( ELT(j-1), ef1 );
+ EDGEFLAG_SET( ELT(j), ef );
+ }
+ } else {
+ for (j=start+3;j<count;j+=2) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_noop)( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ (void)(ctx && start && count && flags);
+}
+
+RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ TAG(render_points),
+ TAG(render_lines),
+ TAG(render_line_loop),
+ TAG(render_line_strip),
+ TAG(render_triangles),
+ TAG(render_tri_strip),
+ TAG(render_tri_fan),
+ TAG(render_quads),
+ TAG(render_quad_strip),
+ TAG(render_poly),
+ TAG(render_noop),
+};
+
+
+
+#ifndef PRESERVE_VB_DEFS
+#undef RENDER_TRI
+#undef RENDER_QUAD
+#undef RENDER_LINE
+#undef RENDER_POINTS
+#undef LOCAL_VARS
+#undef INIT
+#undef POSTFIX
+#undef RESET_STIPPLE
+#undef DBG
+#undef ELT
+#undef RENDER_TAB_QUALIFIER
+#endif
+
+#ifndef PRESERVE_TAG
+#undef TAG
+#endif
+
+#undef PRESERVE_VB_DEFS
+#undef PRESERVE_TAG
diff --git a/mesalib/src/mesa/tnl/t_vb_texgen.c b/mesalib/src/mesa/tnl/t_vb_texgen.c
new file mode 100644
index 000000000..7c1819b22
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_texgen.c
@@ -0,0 +1,611 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Brian Paul
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Regarding GL_NV_texgen_reflection:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+/***********************************************************************
+ * Automatic texture coordinate generation (texgen) code.
+ */
+
+
+struct texgen_stage_data;
+
+typedef void (*texgen_func)( GLcontext *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit);
+
+
+struct texgen_stage_data {
+
+ /* Per-texunit derived state.
+ */
+ GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS];
+ texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS];
+
+ /* Temporary values used in texgen.
+ */
+ GLfloat (*tmp_f)[3];
+ GLfloat *tmp_m;
+
+ /* Buffered outputs of the stage.
+ */
+ GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS];
+};
+
+
+#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr)
+
+
+
+static GLuint all_bits[5] = {
+ 0,
+ VEC_SIZE_1,
+ VEC_SIZE_2,
+ VEC_SIZE_3,
+ VEC_SIZE_4,
+};
+
+#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4)
+
+#define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP)
+#define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV)
+
+
+
+static void build_m3( GLfloat f[][3], GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = (GLfloat *)eye->start;
+ GLuint count = eye->count;
+ const GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
+ GLfloat u[3], two_nu, fx, fy, fz;
+ COPY_3V( u, coord );
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ fx = f[i][0] = u[0] - norm[0] * two_nu;
+ fy = f[i][1] = u[1] - norm[1] * two_nu;
+ fz = f[i][2] = u[2] - norm[2] * two_nu;
+ m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
+ if (m[i] != 0.0F) {
+ m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
+ }
+ }
+}
+
+
+
+static void build_m2( GLfloat f[][3], GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
+ GLfloat u[3], two_nu, fx, fy, fz;
+ COPY_2V( u, coord );
+ u[2] = 0;
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ fx = f[i][0] = u[0] - norm[0] * two_nu;
+ fy = f[i][1] = u[1] - norm[1] * two_nu;
+ fz = f[i][2] = u[2] - norm[2] * two_nu;
+ m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
+ if (m[i] != 0.0F) {
+ m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
+ }
+ }
+}
+
+
+
+typedef void (*build_m_func)( GLfloat f[][3],
+ GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye );
+
+
+static build_m_func build_m_tab[5] = {
+ NULL,
+ NULL,
+ build_m2,
+ build_m3,
+ build_m3
+};
+
+
+/* This is unusual in that we respect the stride of the output vector
+ * (f). This allows us to pass in either a texcoord vector4f, or a
+ * temporary vector3f.
+ */
+static void build_f3( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++) {
+ GLfloat u[3], two_nu;
+ COPY_3V( u, coord );
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ f[0] = u[0] - norm[0] * two_nu;
+ f[1] = u[1] - norm[1] * two_nu;
+ f[2] = u[2] - norm[2] * two_nu;
+ STRIDE_F(coord,stride);
+ STRIDE_F(f,fstride);
+ STRIDE_F(norm, normal->stride);
+ }
+}
+
+
+static void build_f2( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++) {
+
+ GLfloat u[3], two_nu;
+ COPY_2V( u, coord );
+ u[2] = 0;
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ f[0] = u[0] - norm[0] * two_nu;
+ f[1] = u[1] - norm[1] * two_nu;
+ f[2] = u[2] - norm[2] * two_nu;
+
+ STRIDE_F(coord,stride);
+ STRIDE_F(f,fstride);
+ STRIDE_F(norm, normal->stride);
+ }
+}
+
+typedef void (*build_f_func)( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal_vec,
+ const GLvector4f *eye );
+
+
+
+/* Just treat 4-vectors as 3-vectors.
+ */
+static build_f_func build_f_tab[5] = {
+ NULL,
+ NULL,
+ build_f2,
+ build_f3,
+ build_f3
+};
+
+
+
+/* Special case texgen functions.
+ */
+static void texgen_reflection_map_nv( GLcontext *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+
+ build_f_tab[VB->EyePtr->size]( out->start,
+ out->stride,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL],
+ VB->EyePtr );
+
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
+ out->count = VB->Count;
+ out->size = MAX2(in->size, 3);
+ if (in->size == 4)
+ _mesa_copy_tab[0x8]( out, in );
+}
+
+
+
+static void texgen_normal_map_nv( GLcontext *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start;
+ GLuint count = VB->Count;
+ GLuint i;
+ const GLfloat *norm = normal->start;
+
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][0] = norm[0];
+ texcoord[i][1] = norm[1];
+ texcoord[i][2] = norm[2];
+ }
+
+
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
+ out->count = count;
+ out->size = MAX2(in->size, 3);
+ if (in->size == 4)
+ _mesa_copy_tab[0x8]( out, in );
+}
+
+
+static void texgen_sphere_map( GLcontext *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start;
+ GLuint count = VB->Count;
+ GLuint i;
+ GLfloat (*f)[3] = store->tmp_f;
+ GLfloat *m = store->tmp_m;
+
+ (build_m_tab[VB->EyePtr->size])( store->tmp_f,
+ store->tmp_m,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL],
+ VB->EyePtr );
+
+ out->size = MAX2(in->size,2);
+
+ for (i=0;i<count;i++) {
+ texcoord[i][0] = f[i][0] * m[i] + 0.5F;
+ texcoord[i][1] = f[i][1] * m[i] + 0.5F;
+ }
+
+ out->count = count;
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2;
+ if (in->size > 2)
+ _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in );
+}
+
+
+
+static void texgen( GLcontext *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ const GLvector4f *obj = VB->ObjPtr;
+ const GLvector4f *eye = VB->EyePtr;
+ const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+ const GLfloat *m = store->tmp_m;
+ const GLuint count = VB->Count;
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
+ GLfloat (*f)[3] = store->tmp_f;
+ GLuint copy;
+
+ if (texUnit->_GenFlags & TEXGEN_NEED_M) {
+ build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye );
+ } else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
+ build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
+ }
+
+
+ out->size = MAX2(in->size, store->TexgenSize[unit]);
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled;
+ out->count = count;
+
+ copy = (all_bits[in->size] & ~texUnit->TexGenEnabled);
+ if (copy)
+ _mesa_copy_tab[copy]( out, in );
+
+ if (texUnit->TexGenEnabled & S_BIT) {
+ GLuint i;
+ switch (texUnit->GenS.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
+ sizeof(out->data[0]), obj,
+ texUnit->GenS.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
+ sizeof(out->data[0]), eye,
+ texUnit->GenS.EyePlane );
+ break;
+ case GL_SPHERE_MAP:
+ for (i = 0; i < count; i++)
+ texcoord[i][0] = f[i][0] * m[i] + 0.5F;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][0] = f[i][0];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][0] = norm[0];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad S texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & T_BIT) {
+ GLuint i;
+ switch (texUnit->GenT.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenT.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenT.EyePlane );
+ break;
+ case GL_SPHERE_MAP:
+ for (i = 0; i < count; i++)
+ texcoord[i][1] = f[i][1] * m[i] + 0.5F;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][1] = f[i][1];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][1] = norm[1];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad T texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & R_BIT) {
+ GLuint i;
+ switch (texUnit->GenR.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenR.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenR.EyePlane );
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][2] = f[i][2];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) {
+ texcoord[i][2] = norm[2];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad R texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ switch (texUnit->GenQ.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenQ.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenQ.EyePlane );
+ break;
+ default:
+ _mesa_problem(ctx, "Bad Q texgen");
+ }
+ }
+}
+
+
+
+
+static GLboolean run_texgen_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->TexGenEnabled) {
+
+ store->TexgenFunc[i]( ctx, store, i );
+
+ VB->TexCoordPtr[i] =
+ VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i];
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+static void validate_texgen_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current)
+ return;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->TexGenEnabled) {
+ GLuint sz;
+
+ if (texUnit->TexGenEnabled & Q_BIT)
+ sz = 4;
+ else if (texUnit->TexGenEnabled & R_BIT)
+ sz = 3;
+ else if (texUnit->TexGenEnabled & T_BIT)
+ sz = 2;
+ else
+ sz = 1;
+
+ store->TexgenSize[i] = sz;
+ store->TexgenFunc[i] = texgen; /* general solution */
+
+ /* look for special texgen cases */
+ if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
+ if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
+ store->TexgenFunc[i] = texgen_reflection_map_nv;
+ }
+ else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) {
+ store->TexgenFunc[i] = texgen_normal_map_nv;
+ }
+ }
+ else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
+ texUnit->_GenFlags == TEXGEN_SPHERE_MAP) {
+ store->TexgenFunc[i] = texgen_sphere_map;
+ }
+ }
+ }
+}
+
+
+
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texgen_data( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texgen_stage_data *store;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXGEN_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+ store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
+ store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
+
+ return GL_TRUE;
+}
+
+
+static void free_texgen_data( struct tnl_pipeline_stage *stage )
+
+{
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+
+
+ if (store->tmp_f) FREE( store->tmp_f );
+ if (store->tmp_m) FREE( store->tmp_m );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+
+const struct tnl_pipeline_stage _tnl_texgen_stage =
+{
+ "texgen", /* name */
+ NULL, /* private data */
+ alloc_texgen_data, /* destructor */
+ free_texgen_data, /* destructor */
+ validate_texgen_stage, /* check */
+ run_texgen_stage /* run -- initially set to alloc data */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_texmat.c b/mesalib/src/mesa/tnl/t_vb_texmat.c
new file mode 100644
index 000000000..0abe8cc35
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_texmat.c
@@ -0,0 +1,130 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+/* Is there any real benefit seperating texmat from texgen? It means
+ * we need two lots of intermediate storage. Any changes to
+ * _NEW_TEXTURE will invalidate both sets -- it's only on changes to
+ * *only* _NEW_TEXTURE_MATRIX that texgen survives but texmat doesn't.
+ *
+ * However, the seperation of this code from the complex texgen stuff
+ * is very appealing.
+ */
+struct texmat_stage_data {
+ GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS];
+};
+
+#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr)
+
+
+
+static GLboolean run_texmat_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLuint i;
+
+ if (!ctx->Texture._TexMatEnabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ /* ENABLE_TEXMAT implies that the texture matrix is not the
+ * identity, so we don't have to check that here.
+ */
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) {
+ (void) TransformRaw( &store->texcoord[i],
+ ctx->TextureMatrixStack[i].Top,
+ VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]);
+
+ VB->TexCoordPtr[i] =
+ VB->AttribPtr[VERT_ATTRIB_TEX0+i] = &store->texcoord[i];
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texmat_data( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texmat_stage_data *store;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXMAT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+ return GL_TRUE;
+}
+
+
+static void free_texmat_data( struct tnl_pipeline_stage *stage )
+{
+ struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+
+const struct tnl_pipeline_stage _tnl_texture_transform_stage =
+{
+ "texture transform", /* name */
+ NULL, /* private data */
+ alloc_texmat_data,
+ free_texmat_data, /* destructor */
+ NULL,
+ run_texmat_stage,
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c
new file mode 100644
index 000000000..30aa7c408
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vb_vertex.c
@@ -0,0 +1,264 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+
+struct vertex_stage_data {
+ GLvector4f eye;
+ GLvector4f clip;
+ GLvector4f proj;
+ GLubyte *clipmask;
+ GLubyte ormask;
+ GLubyte andmask;
+};
+
+#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr)
+
+
+
+
+/* This function implements cliptesting for user-defined clip planes.
+ * The clipping of primitives to these planes is implemented in
+ * t_render_clip.h.
+ */
+#define USER_CLIPTEST(NAME, SZ) \
+static void NAME( GLcontext *ctx, \
+ GLvector4f *clip, \
+ GLubyte *clipmask, \
+ GLubyte *clipormask, \
+ GLubyte *clipandmask ) \
+{ \
+ GLuint p; \
+ \
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) \
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { \
+ GLuint nr, i; \
+ 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 = (GLfloat *)clip->data; \
+ GLuint stride = clip->stride; \
+ GLuint count = clip->count; \
+ \
+ for (nr = 0, i = 0 ; i < count ; i++) { \
+ 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) { \
+ nr++; \
+ clipmask[i] |= CLIP_USER_BIT; \
+ } \
+ \
+ STRIDE_F(coord, stride); \
+ } \
+ \
+ if (nr > 0) { \
+ *clipormask |= CLIP_USER_BIT; \
+ if (nr == count) { \
+ *clipandmask |= CLIP_USER_BIT; \
+ return; \
+ } \
+ } \
+ } \
+}
+
+
+USER_CLIPTEST(userclip2, 2)
+USER_CLIPTEST(userclip3, 3)
+USER_CLIPTEST(userclip4, 4)
+
+static void (*(usercliptab[5]))( GLcontext *,
+ GLvector4f *, GLubyte *,
+ GLubyte *, GLubyte * ) =
+{
+ NULL,
+ NULL,
+ userclip2,
+ userclip3,
+ userclip4
+};
+
+
+
+static GLboolean run_vertex_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ if (ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ if (ctx->_NeedEyeCoords) {
+ /* Separate modelview transformation:
+ * Use combined ModelProject to avoid some depth artifacts
+ */
+ if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
+ VB->EyePtr = VB->ObjPtr;
+ else
+ VB->EyePtr = TransformRaw( &store->eye,
+ ctx->ModelviewMatrixStack.Top,
+ VB->ObjPtr);
+ }
+
+ VB->ClipPtr = TransformRaw( &store->clip,
+ &ctx->_ModelProjectMatrix,
+ VB->ObjPtr );
+
+ /* Drivers expect this to be clean to element 4...
+ */
+ switch (VB->ClipPtr->size) {
+ case 1:
+ /* impossible */
+ case 2:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+ /* fall-through */
+ case 3:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+ /* fall-through */
+ case 4:
+ break;
+ }
+
+
+ /* Cliptest and perspective divide. Clip functions must clear
+ * the clipmask.
+ */
+ store->ormask = 0;
+ store->andmask = CLIP_FRUSTUM_BITS;
+
+ if (tnl->NeedNdcCoords) {
+ VB->NdcPtr =
+ _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ &store->proj,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+ }
+ else {
+ VB->NdcPtr = NULL;
+ _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ NULL,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+ }
+
+ if (store->andmask)
+ return GL_FALSE;
+
+
+ /* Test userclip planes. This contributes to VB->ClipMask, so
+ * is essentially required to be in this stage.
+ */
+ if (ctx->Transform.ClipPlanesEnabled) {
+ usercliptab[VB->ClipPtr->size]( ctx,
+ VB->ClipPtr,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+
+ if (store->andmask)
+ return GL_FALSE;
+ }
+
+ VB->ClipAndMask = store->andmask;
+ VB->ClipOrMask = store->ormask;
+ VB->ClipMask = store->clipmask;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean init_vertex_stage( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct vertex_stage_data *store;
+ GLuint size = VB->Size;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = VERTEX_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->eye, 0, size, 32 );
+ _mesa_vector4f_alloc( &store->clip, 0, size, 32 );
+ _mesa_vector4f_alloc( &store->proj, 0, size, 32 );
+
+ store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
+
+ if (!store->clipmask ||
+ !store->eye.data ||
+ !store->clip.data ||
+ !store->proj.data)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+ struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
+
+ if (store) {
+ _mesa_vector4f_free( &store->eye );
+ _mesa_vector4f_free( &store->clip );
+ _mesa_vector4f_free( &store->proj );
+ ALIGN_FREE( store->clipmask );
+ FREE(store);
+ stage->privatePtr = NULL;
+ stage->run = init_vertex_stage;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_vertex_transform_stage =
+{
+ "modelview/project/cliptest/divide",
+ NULL, /* private data */
+ init_vertex_stage,
+ dtr, /* destructor */
+ NULL,
+ run_vertex_stage /* run -- initially set to init */
+};
diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c
new file mode 100644
index 000000000..fe4209ae5
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vertex.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+
+#include "t_context.h"
+#include "t_vertex.h"
+
+#define DBG 0
+
+/* Build and manage clipspace/ndc/window vertices.
+ */
+
+static GLboolean match_fastpath( struct tnl_clipspace *vtx,
+ const struct tnl_clipspace_fastpath *fp)
+{
+ GLuint j;
+
+ if (vtx->attr_count != fp->attr_count)
+ return GL_FALSE;
+
+ for (j = 0; j < vtx->attr_count; j++)
+ if (vtx->attr[j].format != fp->attr[j].format ||
+ vtx->attr[j].inputsize != fp->attr[j].size ||
+ vtx->attr[j].vertoffset != fp->attr[j].offset)
+ return GL_FALSE;
+
+ if (fp->match_strides) {
+ if (vtx->vertex_size != fp->vertex_size)
+ return GL_FALSE;
+
+ for (j = 0; j < vtx->attr_count; j++)
+ if (vtx->attr[j].inputstride != fp->attr[j].stride)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean search_fastpath_emit( struct tnl_clipspace *vtx )
+{
+ struct tnl_clipspace_fastpath *fp = vtx->fastpath;
+
+ for ( ; fp ; fp = fp->next) {
+ if (match_fastpath(vtx, fp)) {
+ vtx->emit = fp->func;
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+void _tnl_register_fastpath( struct tnl_clipspace *vtx,
+ GLboolean match_strides )
+{
+ struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath);
+ GLuint i;
+
+ fastpath->vertex_size = vtx->vertex_size;
+ fastpath->attr_count = vtx->attr_count;
+ fastpath->match_strides = match_strides;
+ fastpath->func = vtx->emit;
+ fastpath->attr = (struct tnl_attr_type *)
+ _mesa_malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
+
+ for (i = 0; i < vtx->attr_count; i++) {
+ fastpath->attr[i].format = vtx->attr[i].format;
+ fastpath->attr[i].stride = vtx->attr[i].inputstride;
+ fastpath->attr[i].size = vtx->attr[i].inputsize;
+ fastpath->attr[i].offset = vtx->attr[i].vertoffset;
+ }
+
+ fastpath->next = vtx->fastpath;
+ vtx->fastpath = fastpath;
+}
+
+
+
+/***********************************************************************
+ * Build codegen functions or return generic ones:
+ */
+static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
+ a[j].inputstride = vptr->stride;
+ a[j].inputsize = vptr->size;
+ a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */
+ }
+
+ vtx->emit = NULL;
+
+ /* Does this match an existing (hardwired, codegen or known-bad)
+ * fastpath?
+ */
+ if (search_fastpath_emit(vtx)) {
+ /* Use this result. If it is null, then it is already known
+ * that the current state will fail for codegen and there is no
+ * point trying again.
+ */
+ }
+ else if (vtx->codegen_emit) {
+ vtx->codegen_emit(ctx);
+ }
+
+ if (!vtx->emit) {
+ _tnl_generate_hardwired_emit(ctx);
+ }
+
+ /* Otherwise use the generic version:
+ */
+ if (!vtx->emit)
+ vtx->emit = _tnl_generic_emit;
+
+ vtx->emit( ctx, count, dest );
+}
+
+
+
+static void choose_interp_func( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ if (vtx->need_extras &&
+ (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ vtx->interp = _tnl_generic_interp_extras;
+ } else {
+ vtx->interp = _tnl_generic_interp;
+ }
+
+ vtx->interp( ctx, t, edst, eout, ein, force_boundary );
+}
+
+
+static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ if (vtx->need_extras &&
+ (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ vtx->copy_pv = _tnl_generic_copy_pv_extras;
+ } else {
+ vtx->copy_pv = _tnl_generic_copy_pv;
+ }
+
+ vtx->copy_pv( ctx, edst, esrc );
+}
+
+
+/***********************************************************************
+ * Public entrypoints, mostly dispatch to the above:
+ */
+
+
+/* Interpolate between two vertices to produce a third:
+ */
+void _tnl_interp( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->interp( ctx, t, edst, eout, ein, force_boundary );
+}
+
+/* Copy colors from one vertex to another:
+ */
+void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->copy_pv( ctx, edst, esrc );
+}
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied:
+ */
+void _tnl_get_attr( GLcontext *ctx, const void *vin,
+ GLenum attr, GLfloat *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
+ return;
+ }
+ }
+
+ /* Else return the value from ctx->Current.
+ */
+ if (attr == _TNL_ATTRIB_POINTSIZE) {
+ /* If the hardware vertex doesn't have point size then use size from
+ * GLcontext. XXX this will be wrong if drawing attenuated points!
+ */
+ dest[0] = ctx->Point.Size;
+ }
+ else {
+ _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
+ }
+}
+
+
+/* Complementary operation to the above.
+ */
+void _tnl_set_attr( GLcontext *ctx, void *vout,
+ GLenum attr, const GLfloat *src )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
+ return;
+ }
+ }
+}
+
+
+void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ return vtx->vertex_buf + nr * vtx->vertex_size;
+}
+
+void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
+{
+ if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->new_inputs = ~0;
+ vtx->interp = choose_interp_func;
+ vtx->copy_pv = choose_copy_pv_func;
+ }
+}
+
+static void invalidate_funcs( struct tnl_clipspace *vtx )
+{
+ vtx->emit = choose_emit_func;
+ vtx->interp = choose_interp_func;
+ vtx->copy_pv = choose_copy_pv_func;
+ vtx->new_inputs = ~0;
+}
+
+GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
+ GLuint nr, const GLfloat *vp,
+ GLuint unpacked_size )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint offset = 0;
+ GLuint i, j;
+
+ assert(nr < _TNL_ATTRIB_MAX);
+ assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
+
+ vtx->new_inputs = ~0;
+ vtx->need_viewport = GL_FALSE;
+
+ if (vp) {
+ vtx->need_viewport = GL_TRUE;
+ }
+
+ for (j = 0, i = 0; i < nr; i++) {
+ const GLuint format = map[i].format;
+ if (format == EMIT_PAD) {
+ if (DBG)
+ _mesa_printf("%d: pad %d, offset %d\n", i,
+ map[i].offset, offset);
+
+ offset += map[i].offset;
+
+ }
+ else {
+ GLuint tmpoffset;
+
+ if (unpacked_size)
+ tmpoffset = map[i].offset;
+ else
+ tmpoffset = offset;
+
+ if (vtx->attr_count != j ||
+ vtx->attr[j].attrib != map[i].attrib ||
+ vtx->attr[j].format != format ||
+ vtx->attr[j].vertoffset != tmpoffset) {
+ invalidate_funcs(vtx);
+
+ vtx->attr[j].attrib = map[i].attrib;
+ vtx->attr[j].format = format;
+ vtx->attr[j].vp = vp;
+ vtx->attr[j].insert = _tnl_format_info[format].insert;
+ vtx->attr[j].extract = _tnl_format_info[format].extract;
+ vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize;
+ vtx->attr[j].vertoffset = tmpoffset;
+ }
+
+
+ if (DBG)
+ _mesa_printf("%d: %s, vp %p, offset %d\n", i,
+ _tnl_format_info[format].name, (void *)vp,
+ vtx->attr[j].vertoffset);
+
+ offset += _tnl_format_info[format].attrsize;
+ j++;
+ }
+ }
+
+ vtx->attr_count = j;
+
+ if (unpacked_size)
+ vtx->vertex_size = unpacked_size;
+ else
+ vtx->vertex_size = offset;
+
+ assert(vtx->vertex_size <= vtx->max_vertex_size);
+ return vtx->vertex_size;
+}
+
+
+
+void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->new_inputs |= newinputs;
+}
+
+
+/* This event has broader use beyond this file - will move elsewhere
+ * and probably invoke a driver callback.
+ */
+void _tnl_notify_pipeline_output_change( GLcontext *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ invalidate_funcs(vtx);
+}
+
+
+static void adjust_input_ptrs( GLcontext *ctx, GLint diff)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint count = vtx->attr_count;
+ int j;
+
+ diff -= 1;
+ for (j=0; j<count; ++j) {
+ register GLvector4f *vptr = VB->AttribPtr[a->attrib];
+ (a++)->inputptr += diff*vptr->stride;
+ }
+}
+
+static void update_input_ptrs( GLcontext *ctx, GLuint start )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < count; j++) {
+ GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
+
+ if (vtx->emit != choose_emit_func) {
+ assert(a[j].inputstride == vptr->stride);
+ assert(a[j].inputsize == vptr->size);
+ }
+
+ a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
+ }
+
+ if (a->vp) {
+ vtx->vp_scale[0] = a->vp[MAT_SX];
+ vtx->vp_scale[1] = a->vp[MAT_SY];
+ vtx->vp_scale[2] = a->vp[MAT_SZ];
+ vtx->vp_scale[3] = 1.0;
+ vtx->vp_xlate[0] = a->vp[MAT_TX];
+ vtx->vp_xlate[1] = a->vp[MAT_TY];
+ vtx->vp_xlate[2] = a->vp[MAT_TZ];
+ vtx->vp_xlate[3] = 0.0;
+ }
+}
+
+
+void _tnl_build_vertices( GLcontext *ctx,
+ GLuint start,
+ GLuint end,
+ GLuint newinputs )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ update_input_ptrs( ctx, start );
+ vtx->emit( ctx, end - start,
+ (GLubyte *)(vtx->vertex_buf +
+ start * vtx->vertex_size));
+}
+
+/* Emit VB vertices start..end to dest. Note that VB vertex at
+ * postion start will be emitted to dest at position zero.
+ */
+void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
+ GLuint start,
+ GLuint end,
+ void *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ update_input_ptrs(ctx, start);
+ /* Note: dest should not be adjusted for non-zero 'start' values:
+ */
+ vtx->emit( ctx, end - start, (GLubyte*) dest );
+ return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
+}
+
+/* Emit indexed VB vertices start..end to dest. Note that VB vertex at
+ * postion start will be emitted to dest at position zero.
+ */
+
+void *_tnl_emit_indexed_vertices_to_buffer( GLcontext *ctx,
+ const GLuint *elts,
+ GLuint start,
+ GLuint end,
+ void *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint oldIndex;
+ GLubyte *cdest = dest;
+
+ update_input_ptrs(ctx, oldIndex = elts[start++]);
+ vtx->emit( ctx, 1, cdest );
+ cdest += vtx->vertex_size;
+
+ for (; start < end; ++start) {
+ adjust_input_ptrs(ctx, elts[start] - oldIndex);
+ oldIndex = elts[start];
+ vtx->emit( ctx, 1, cdest);
+ cdest += vtx->vertex_size;
+ }
+
+ return (void *) cdest;
+}
+
+
+void _tnl_init_vertices( GLcontext *ctx,
+ GLuint vb_size,
+ GLuint max_vertex_size )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ _tnl_install_attrs( ctx, NULL, 0, NULL, 0 );
+
+ vtx->need_extras = GL_TRUE;
+ if (max_vertex_size > vtx->max_vertex_size) {
+ _tnl_free_vertices( ctx );
+ vtx->max_vertex_size = max_vertex_size;
+ vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 );
+ invalidate_funcs(vtx);
+ }
+
+ switch(CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ vtx->chan_scale[0] = 255.0;
+ vtx->chan_scale[1] = 255.0;
+ vtx->chan_scale[2] = 255.0;
+ vtx->chan_scale[3] = 255.0;
+ break;
+ case GL_UNSIGNED_SHORT:
+ vtx->chan_scale[0] = 65535.0;
+ vtx->chan_scale[1] = 65535.0;
+ vtx->chan_scale[2] = 65535.0;
+ vtx->chan_scale[3] = 65535.0;
+ break;
+ default:
+ vtx->chan_scale[0] = 1.0;
+ vtx->chan_scale[1] = 1.0;
+ vtx->chan_scale[2] = 1.0;
+ vtx->chan_scale[3] = 1.0;
+ break;
+ }
+
+ vtx->identity[0] = 0.0;
+ vtx->identity[1] = 0.0;
+ vtx->identity[2] = 0.0;
+ vtx->identity[3] = 1.0;
+
+ vtx->codegen_emit = NULL;
+
+#ifdef USE_SSE_ASM
+ if (!_mesa_getenv("MESA_NO_CODEGEN"))
+ vtx->codegen_emit = _tnl_generate_sse_emit;
+#endif
+}
+
+
+void _tnl_free_vertices( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ if (tnl) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_fastpath *fp, *tmp;
+
+ if (vtx->vertex_buf) {
+ ALIGN_FREE(vtx->vertex_buf);
+ vtx->vertex_buf = NULL;
+ }
+
+ for (fp = vtx->fastpath ; fp ; fp = tmp) {
+ tmp = fp->next;
+ FREE(fp->attr);
+
+ /* KW: At the moment, fp->func is constrained to be allocated by
+ * _mesa_exec_alloc(), as the hardwired fastpaths in
+ * t_vertex_generic.c are handled specially. It would be nice
+ * to unify them, but this probably won't change until this
+ * module gets another overhaul.
+ */
+ _mesa_exec_free((void *) fp->func);
+ FREE(fp);
+ }
+
+ vtx->fastpath = NULL;
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vertex.h b/mesalib/src/mesa/tnl/t_vertex.h
new file mode 100644
index 000000000..2dfd7b57f
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vertex.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#ifndef _TNL_VERTEX_H
+#define _TNL_VERTEX_H
+
+#include "main/mtypes.h"
+#include "t_context.h"
+
+/* New mechanism to specify hardware vertices so that tnl can build
+ * and manipulate them directly.
+ */
+
+
+/* It will probably be necessary to allow drivers to specify new
+ * emit-styles to cover all the wierd and wacky things out there.
+ */
+enum tnl_attr_format {
+ EMIT_1F,
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_2F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_4F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_XYW, /* for projective texture */
+ EMIT_1UB_1F, /* for fog coordinate */
+ EMIT_3UB_3F_RGB, /* for specular color */
+ EMIT_3UB_3F_BGR, /* for specular color */
+ EMIT_4UB_4F_RGBA, /* for color */
+ EMIT_4UB_4F_BGRA, /* for color */
+ EMIT_4UB_4F_ARGB, /* for color */
+ EMIT_4UB_4F_ABGR, /* for color */
+ EMIT_4CHAN_4F_RGBA, /* for swrast color */
+ EMIT_PAD, /* leave a hole of 'offset' bytes */
+ EMIT_MAX
+};
+
+struct tnl_attr_map {
+ GLuint attrib; /* _TNL_ATTRIB_ enum */
+ enum tnl_attr_format format;
+ GLuint offset;
+};
+
+struct tnl_format_info {
+ const char *name;
+ tnl_extract_func extract;
+ tnl_insert_func insert[4];
+ const GLuint attrsize;
+};
+
+extern const struct tnl_format_info _tnl_format_info[EMIT_MAX];
+
+
+/* Interpolate between two vertices to produce a third:
+ */
+extern void _tnl_interp( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary );
+
+/* Copy colors from one vertex to another:
+ */
+extern void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc );
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied:
+ */
+extern void _tnl_get_attr( GLcontext *ctx, const void *vertex, GLenum attrib,
+ GLfloat *dest );
+
+/* Complementary to the above.
+ */
+extern void _tnl_set_attr( GLcontext *ctx, void *vout, GLenum attrib,
+ const GLfloat *src );
+
+
+extern void *_tnl_get_vertex( GLcontext *ctx, GLuint nr );
+
+extern GLuint _tnl_install_attrs( GLcontext *ctx,
+ const struct tnl_attr_map *map,
+ GLuint nr, const GLfloat *vp,
+ GLuint unpacked_size );
+
+extern void _tnl_free_vertices( GLcontext *ctx );
+
+extern void _tnl_init_vertices( GLcontext *ctx,
+ GLuint vb_size,
+ GLuint max_vertex_size );
+
+extern void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
+ GLuint start,
+ GLuint end,
+ void *dest );
+
+/* This function isn't optimal. Check out
+ * gallium/auxilary/translate for a more comprehensive implementation of
+ * the same functionality.
+ */
+
+extern void *_tnl_emit_indexed_vertices_to_buffer( GLcontext *ctx,
+ const GLuint *elts,
+ GLuint start,
+ GLuint end,
+ void *dest );
+
+
+extern void _tnl_build_vertices( GLcontext *ctx,
+ GLuint start,
+ GLuint end,
+ GLuint newinputs );
+
+extern void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs );
+
+extern void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state );
+
+extern void _tnl_notify_pipeline_output_change( GLcontext *ctx );
+
+
+#define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
+
+/* Internal function:
+ */
+void _tnl_register_fastpath( struct tnl_clipspace *vtx,
+ GLboolean match_strides );
+
+
+/* t_vertex_generic.c -- Internal functions for t_vertex.c
+ */
+void _tnl_generic_copy_pv_extras( GLcontext *ctx,
+ GLuint dst, GLuint src );
+
+void _tnl_generic_interp_extras( GLcontext *ctx,
+ GLfloat t,
+ GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary );
+
+void _tnl_generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc );
+
+void _tnl_generic_interp( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary );
+
+void _tnl_generic_emit( GLcontext *ctx,
+ GLuint count,
+ GLubyte *v );
+
+void _tnl_generate_hardwired_emit( GLcontext *ctx );
+
+/* t_vertex_sse.c -- Internal functions for t_vertex.c
+ */
+void _tnl_generate_sse_emit( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_vertex_generic.c b/mesalib/src/mesa/tnl/t_vertex_generic.c
new file mode 100644
index 000000000..9812f8c80
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vertex_generic.c
@@ -0,0 +1,1155 @@
+
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "t_context.h"
+#include "t_vertex.h"
+
+
+#if 0
+#define DEBUG_INSERT printf("%s\n", __FUNCTION__)
+#else
+#define DEBUG_INSERT
+#endif
+
+
+/*
+ * These functions take the NDC coordinates pointed to by 'in', apply the
+ * NDC->Viewport mapping and store the results at 'v'.
+ */
+
+static INLINE void insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+ out[2] = vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+}
+
+static INLINE void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[14];
+}
+
+static INLINE void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+ out[2] = vp[14];
+}
+
+static INLINE void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+}
+
+static INLINE void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+}
+
+
+/*
+ * These functions do the same as above, except for the viewport mapping.
+ */
+
+static INLINE void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[3];
+}
+
+static INLINE void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+ DEBUG_INSERT;
+ _mesa_exit(1);
+}
+
+static INLINE void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+static INLINE void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+}
+
+static INLINE void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+}
+
+
+static INLINE void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+}
+
+static INLINE void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+}
+
+static INLINE void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+}
+
+static INLINE void insert_null( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a; (void) v; (void) in;
+}
+
+static INLINE void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
+}
+
+static INLINE void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ v[2] = 0x00;
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ v[2] = 0x00;
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+}
+
+static INLINE void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+}
+
+static INLINE void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+}
+
+
+static INLINE void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+}
+
+
+/***********************************************************************
+ * Functions to perform the reverse operations to the above, for
+ * swrast translation and clip-interpolation.
+ *
+ * Currently always extracts a full 4 floats.
+ */
+
+static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+
+ /* Although included for completeness, the position coordinate is
+ * usually handled differently during clipping.
+ */
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = (in[2] - vp[14]) / vp[10];
+ out[3] = in[3];
+}
+
+static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = (in[2] - vp[14]) / vp[10];
+ out[3] = 1;
+}
+
+
+static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = in[2];
+}
+
+
+static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+
+ out[0] = CHAN_TO_FLOAT(c[0]);
+ out[1] = CHAN_TO_FLOAT(c[1]);
+ out[2] = CHAN_TO_FLOAT(c[2]);
+ out[3] = CHAN_TO_FLOAT(c[3]);
+}
+
+static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[0] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[2] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[2] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[0] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+const struct tnl_format_info _tnl_format_info[EMIT_MAX] =
+{
+ { "1f",
+ extract_1f,
+ { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
+ sizeof(GLfloat) },
+
+ { "2f",
+ extract_2f,
+ { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f",
+ extract_3f,
+ { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f",
+ extract_4f,
+ { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "2f_viewport",
+ extract_2f_viewport,
+ { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
+ insert_2f_viewport_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f_viewport",
+ extract_3f_viewport,
+ { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
+ insert_3f_viewport_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f_viewport",
+ extract_4f_viewport,
+ { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
+ insert_4f_viewport_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "3f_xyw",
+ extract_3f_xyw,
+ { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
+ insert_3f_xyw_4 },
+ 3 * sizeof(GLfloat) },
+
+ { "1ub_1f",
+ extract_1ub_1f,
+ { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
+ sizeof(GLubyte) },
+
+ { "3ub_3f_rgb",
+ extract_3ub_3f_rgb,
+ { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
+ insert_3ub_3f_rgb_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "3ub_3f_bgr",
+ extract_3ub_3f_bgr,
+ { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
+ insert_3ub_3f_bgr_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "4ub_4f_rgba",
+ extract_4ub_4f_rgba,
+ { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
+ insert_4ub_4f_rgba_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_bgra",
+ extract_4ub_4f_bgra,
+ { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
+ insert_4ub_4f_bgra_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_argb",
+ extract_4ub_4f_argb,
+ { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
+ insert_4ub_4f_argb_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_abgr",
+ extract_4ub_4f_abgr,
+ { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
+ insert_4ub_4f_abgr_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4chan_4f_rgba",
+ extract_4chan_4f_rgba,
+ { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
+ insert_4chan_4f_rgba_4 },
+ 4 * sizeof(GLchan) },
+
+ { "pad",
+ NULL,
+ { NULL, NULL, NULL, NULL },
+ 0 }
+
+};
+
+
+
+
+/***********************************************************************
+ * Hardwired fastpaths for emitting whole vertices or groups of
+ * vertices
+ */
+#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \
+static void NAME( GLcontext *ctx, \
+ GLuint count, \
+ GLubyte *v ) \
+{ \
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); \
+ struct tnl_clipspace_attr *a = vtx->attr; \
+ GLuint i; \
+ \
+ for (i = 0 ; i < count ; i++, v += vtx->vertex_size) { \
+ if (NR > 0) { \
+ F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \
+ a[0].inputptr += a[0].inputstride; \
+ } \
+ \
+ if (NR > 1) { \
+ F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \
+ a[1].inputptr += a[1].inputstride; \
+ } \
+ \
+ if (NR > 2) { \
+ F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \
+ a[2].inputptr += a[2].inputstride; \
+ } \
+ \
+ if (NR > 3) { \
+ F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \
+ a[3].inputptr += a[3].inputstride; \
+ } \
+ \
+ if (NR > 4) { \
+ F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \
+ a[4].inputptr += a[4].inputstride; \
+ } \
+ } \
+}
+
+
+#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
+ insert_null, insert_null, NAME)
+
+#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
+ insert_null, NAME)
+
+#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
+ insert_null, NAME)
+
+
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
+EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
+
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2)
+EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
+
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2)
+EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
+
+
+/* Use the codegen paths to select one of a number of hardwired
+ * fastpaths.
+ */
+void _tnl_generate_hardwired_emit( GLcontext *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ tnl_emit_func func = NULL;
+
+ /* Does it fit a hardwired fastpath? Help! this is growing out of
+ * control!
+ */
+ switch (vtx->attr_count) {
+ case 2:
+ if (vtx->attr[0].emit == insert_3f_viewport_3) {
+ if (vtx->attr[1].emit == insert_4ub_4f_bgra_4)
+ func = emit_viewport3_bgra4;
+ else if (vtx->attr[1].emit == insert_4ub_4f_rgba_4)
+ func = emit_viewport3_rgba4;
+ }
+ else if (vtx->attr[0].emit == insert_3f_3 &&
+ vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ func = emit_xyz3_rgba4;
+ }
+ break;
+ case 3:
+ if (vtx->attr[2].emit == insert_2f_2) {
+ if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ if (vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2;
+ else if (vtx->attr[0].emit == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2;
+ }
+ else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
+ vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2;
+ }
+ break;
+ case 4:
+ if (vtx->attr[2].emit == insert_2f_2 &&
+ vtx->attr[3].emit == insert_2f_2) {
+ if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ if (vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2_st2;
+ else if (vtx->attr[0].emit == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2_st2;
+ }
+ else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
+ vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2_st2;
+ }
+ break;
+ }
+
+ vtx->emit = func;
+}
+
+/***********************************************************************
+ * Generic (non-codegen) functions for whole vertices or groups of
+ * vertices
+ */
+
+void _tnl_generic_emit( GLcontext *ctx,
+ GLuint count,
+ GLubyte *v )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ const GLuint stride = vtx->vertex_size;
+ GLuint i, j;
+
+ for (i = 0 ; i < count ; i++, v += stride) {
+ for (j = 0; j < attr_count; j++) {
+ GLfloat *in = (GLfloat *)a[j].inputptr;
+ a[j].inputptr += a[j].inputstride;
+ a[j].emit( &a[j], v + a[j].vertoffset, in );
+ }
+ }
+}
+
+
+void _tnl_generic_interp( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size;
+ const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
+ GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+ (void) force_boundary;
+
+ if (tnl->NeedNdcCoords) {
+ const GLfloat *dstclip = VB->ClipPtr->data[edst];
+ if (dstclip[3] != 0.0) {
+ const GLfloat w = 1.0f / dstclip[3];
+ GLfloat pos[4];
+
+ pos[0] = dstclip[0] * w;
+ pos[1] = dstclip[1] * w;
+ pos[2] = dstclip[2] * w;
+ pos[3] = w;
+
+ a[0].insert[4-1]( &a[0], vdst, pos );
+ }
+ }
+ else {
+ a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
+ }
+
+
+ for (j = 1; j < attr_count; j++) {
+ GLfloat fin[4], fout[4], fdst[4];
+
+ a[j].extract( &a[j], fin, vin + a[j].vertoffset );
+ a[j].extract( &a[j], fout, vout + a[j].vertoffset );
+
+ INTERP_F( t, fdst[3], fout[3], fin[3] );
+ INTERP_F( t, fdst[2], fout[2], fin[2] );
+ INTERP_F( t, fdst[1], fout[1], fin[1] );
+ INTERP_F( t, fdst[0], fout[0], fin[0] );
+
+ a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
+ }
+}
+
+
+/* Extract color attributes from one vertex and insert them into
+ * another. (Shortcircuit extract/insert with memcpy).
+ */
+void _tnl_generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
+ GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
+ a[j].attrib == VERT_ATTRIB_COLOR1) {
+
+ _mesa_memcpy( vdst + a[j].vertoffset,
+ vsrc + a[j].vertoffset,
+ a[j].vertattrsize );
+ }
+ }
+}
+
+
+/* Helper functions for hardware which doesn't put back colors and/or
+ * edgeflags into vertices.
+ */
+void _tnl_generic_interp_extras( GLcontext *ctx,
+ GLfloat t,
+ GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* If stride is zero, ColorPtr[1] is constant across the VB, so
+ * there is no point interpolating between two values as they will
+ * be identical. In all other cases, this value is generated by
+ * t_vb_lighttmp.h and has a stride of 4 dwords.
+ */
+ if (VB->ColorPtr[1] && VB->ColorPtr[1]->stride) {
+ assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
+
+ INTERP_4F( t,
+ VB->ColorPtr[1]->data[dst],
+ VB->ColorPtr[1]->data[out],
+ VB->ColorPtr[1]->data[in] );
+ }
+
+ if (VB->SecondaryColorPtr[1]) {
+ assert(VB->SecondaryColorPtr[1]->stride == 4 * sizeof(GLfloat));
+
+ INTERP_3F( t,
+ VB->SecondaryColorPtr[1]->data[dst],
+ VB->SecondaryColorPtr[1]->data[out],
+ VB->SecondaryColorPtr[1]->data[in] );
+ }
+
+ if (VB->IndexPtr[1]) {
+ VB->IndexPtr[1]->data[dst][0] = LINTERP( t,
+ VB->IndexPtr[1]->data[out][0],
+ VB->IndexPtr[1]->data[in][0] );
+ }
+
+ if (VB->EdgeFlag) {
+ VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
+ }
+
+ _tnl_generic_interp(ctx, t, dst, out, in, force_boundary);
+}
+
+void _tnl_generic_copy_pv_extras( GLcontext *ctx,
+ GLuint dst, GLuint src )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* See above comment:
+ */
+ if (VB->ColorPtr[1] && VB->ColorPtr[1]->stride) {
+ COPY_4FV( VB->ColorPtr[1]->data[dst],
+ VB->ColorPtr[1]->data[src] );
+ }
+
+ if (VB->SecondaryColorPtr[1]) {
+ COPY_4FV( VB->SecondaryColorPtr[1]->data[dst],
+ VB->SecondaryColorPtr[1]->data[src] );
+ }
+
+ if (VB->IndexPtr[1]) {
+ VB->IndexPtr[1]->data[dst][0] = VB->IndexPtr[1]->data[src][0];
+ }
+
+ _tnl_generic_copy_pv(ctx, dst, src);
+}
+
+
diff --git a/mesalib/src/mesa/tnl/t_vertex_sse.c b/mesalib/src/mesa/tnl/t_vertex_sse.c
new file mode 100644
index 000000000..7a255d680
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vertex_sse.c
@@ -0,0 +1,684 @@
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
+#include "t_context.h"
+#include "t_vertex.h"
+
+#if defined(USE_SSE_ASM)
+
+#include "x86/rtasm/x86sse.h"
+#include "x86/common_x86_asm.h"
+
+
+/**
+ * Number of bytes to allocate for generated SSE functions
+ */
+#define MAX_SSE_CODE_SIZE 1024
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+
+struct x86_program {
+ struct x86_function func;
+
+ GLcontext *ctx;
+ GLboolean inputs_safe;
+ GLboolean outputs_safe;
+ GLboolean have_sse2;
+
+ struct x86_reg identity;
+ struct x86_reg chan0;
+};
+
+
+static struct x86_reg get_identity( struct x86_program *p )
+{
+ return p->identity;
+}
+
+static void emit_load4f_4( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_load4f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Have to jump through some hoops:
+ *
+ * c 0 0 0
+ * c 0 0 1
+ * 0 0 c 1
+ * a b c 1
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Initialize from identity, then pull in low two words:
+ */
+ sse_movups(&p->func, dest, get_identity(p));
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Pull in low word, then swizzle in identity */
+ sse_movss(&p->func, dest, arg0);
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+}
+
+
+
+static void emit_load3f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Over-reads by 1 dword - potential SEGV if input is a vertex
+ * array.
+ */
+ if (p->inputs_safe) {
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* c 0 0 0
+ * c c c c
+ * a b c c
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
+ sse_movlps(&p->func, dest, arg0);
+ }
+}
+
+static void emit_load3f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_2(p, dest, arg0);
+}
+
+static void emit_load3f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void emit_load2f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load2f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void emit_load1f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void (*load[4][4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) = {
+ { emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1 },
+
+ { emit_load2f_1,
+ emit_load2f_2,
+ emit_load2f_2,
+ emit_load2f_2 },
+
+ { emit_load3f_1,
+ emit_load3f_2,
+ emit_load3f_3,
+ emit_load3f_3 },
+
+ { emit_load4f_1,
+ emit_load4f_2,
+ emit_load4f_3,
+ emit_load4f_4 }
+};
+
+static void emit_load( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg src,
+ GLuint src_sz)
+{
+ load[sz-1][src_sz-1](p, dest, src);
+}
+
+static void emit_store4f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_store3f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ if (p->outputs_safe) {
+ /* Emit the extra dword anyway. This may hurt writecombining,
+ * may cause other problems.
+ */
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* Alternate strategy - emit two, shuffle, emit one.
+ */
+ sse_movlps(&p->func, dest, arg0);
+ sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(&p->func, x86_make_disp(dest,8), arg0);
+ }
+}
+
+static void emit_store2f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_store1f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+
+static void (*store[4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) =
+{
+ emit_store1f,
+ emit_store2f,
+ emit_store3f,
+ emit_store4f
+};
+
+static void emit_store( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg temp )
+
+{
+ store[sz-1](p, dest, temp);
+}
+
+static void emit_pack_store_4ub( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg temp )
+{
+ /* Scale by 255.0
+ */
+ sse_mulps(&p->func, temp, p->chan0);
+
+ if (p->have_sse2) {
+ sse2_cvtps2dq(&p->func, temp, temp);
+ sse2_packssdw(&p->func, temp, temp);
+ sse2_packuswb(&p->func, temp, temp);
+ sse_movss(&p->func, dest, temp);
+ }
+ else {
+ struct x86_reg mmx0 = x86_make_reg(file_MMX, 0);
+ struct x86_reg mmx1 = x86_make_reg(file_MMX, 1);
+ sse_cvtps2pi(&p->func, mmx0, temp);
+ sse_movhlps(&p->func, temp, temp);
+ sse_cvtps2pi(&p->func, mmx1, temp);
+ mmx_packssdw(&p->func, mmx0, mmx1);
+ mmx_packuswb(&p->func, mmx0, mmx0);
+ mmx_movd(&p->func, dest, mmx0);
+ }
+}
+
+static GLint get_offset( const void *a, const void *b )
+{
+ return (const char *)b - (const char *)a;
+}
+
+/* Not much happens here. Eventually use this function to try and
+ * avoid saving/reloading the source pointers each vertex (if some of
+ * them can fit in registers).
+ */
+static void get_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vtxREG,
+ struct tnl_clipspace_attr *a )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx);
+ struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr));
+
+ /* Load current a[j].inputptr
+ */
+ x86_mov(&p->func, srcREG, ptr_to_src);
+}
+
+static void update_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vtxREG,
+ struct tnl_clipspace_attr *a )
+{
+ if (a->inputstride) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx);
+ struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr));
+
+ /* add a[j].inputstride (hardcoded value - could just as easily
+ * pull the stride value from memory each time).
+ */
+ x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride));
+
+ /* save new value of a[j].inputptr
+ */
+ x86_mov(&p->func, ptr_to_src, srcREG);
+ }
+}
+
+
+/* Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute
+ *
+ */
+static GLboolean build_vertex_emit( struct x86_program *p )
+{
+ GLcontext *ctx = p->ctx;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint j = 0;
+
+ struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX);
+ struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX);
+ struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP);
+ struct x86_reg vtxESI = x86_make_reg(file_REG32, reg_SI);
+ struct x86_reg temp = x86_make_reg(file_XMM, 0);
+ struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
+ struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+ struct x86_reg temp2 = x86_make_reg(file_XMM, 3);
+ GLubyte *fixup, *label;
+
+ /* Push a few regs?
+ */
+ x86_push(&p->func, countEBP);
+ x86_push(&p->func, vtxESI);
+
+
+ /* Get vertex count, compare to zero
+ */
+ x86_xor(&p->func, srcECX, srcECX);
+ x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2));
+ x86_cmp(&p->func, countEBP, srcECX);
+ fixup = x86_jcc_forward(&p->func, cc_E);
+
+ /* Initialize destination register.
+ */
+ x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3));
+
+ /* Dereference ctx to get tnl, then vtx:
+ */
+ x86_mov(&p->func, vtxESI, x86_fn_arg(&p->func, 1));
+ x86_mov(&p->func, vtxESI, x86_make_disp(vtxESI, get_offset(ctx, &ctx->swtnl_context)));
+ vtxESI = x86_make_disp(vtxESI, get_offset(tnl, &tnl->clipspace));
+
+
+ /* Possibly load vp0, vp1 for viewport calcs:
+ */
+ if (vtx->need_viewport) {
+ sse_movups(&p->func, vp0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_scale[0])));
+ sse_movups(&p->func, vp1, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_xlate[0])));
+ }
+
+ /* always load, needed or not:
+ */
+ sse_movups(&p->func, p->chan0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->chan_scale[0])));
+ sse_movups(&p->func, p->identity, x86_make_disp(vtxESI, get_offset(vtx, &vtx->identity[0])));
+
+ /* Note address for loop jump */
+ label = x86_get_label(&p->func);
+
+ /* Emit code for each of the attributes. Currently routes
+ * everything through SSE registers, even when it might be more
+ * efficient to stick with regular old x86. No optimization or
+ * other tricks - enough new ground to cover here just getting
+ * things working.
+ */
+ while (j < vtx->attr_count) {
+ struct tnl_clipspace_attr *a = &vtx->attr[j];
+ struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset);
+
+ /* Now, load an XMM reg from src, perhaps transform, then save.
+ * Could be shortcircuited in specific cases:
+ */
+ switch (a->format) {
+ case EMIT_1F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 1, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_2F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F:
+ /* Potentially the worst case - hardcode 2+1 copying:
+ */
+ if (0) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ else {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ if (a->inputsize > 2) {
+ emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1);
+ emit_store(p, x86_make_disp(dest,8), 1, temp);
+ }
+ else {
+ sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p));
+ }
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ break;
+ case EMIT_4F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_2F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F_XYW:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+
+ case EMIT_1UB_1F:
+ /* Test for PAD3 + 1UB:
+ */
+ if (j > 0 &&
+ a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3)
+ {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
+ emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ else {
+ _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+ return GL_FALSE;
+ }
+ break;
+ case EMIT_3UB_3F_RGB:
+ case EMIT_3UB_3F_BGR:
+ /* Test for 3UB + PAD1:
+ */
+ if (j == vtx->attr_count - 1 ||
+ a[1].vertoffset >= a->vertoffset + 4) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ /* Test for 3UB + 1UB:
+ */
+ else if (j < vtx->attr_count - 1 &&
+ a[1].format == EMIT_1UB_1F &&
+ a[1].vertoffset == a->vertoffset + 3) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ update_src_ptr(p, srcECX, vtxESI, a);
+
+ /* Make room for incoming value:
+ */
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+
+ get_src_ptr(p, srcECX, vtxESI, &a[1]);
+ emit_load(p, temp2, 1, x86_deref(srcECX), a[1].inputsize);
+ sse_movss(&p->func, temp, temp2);
+ update_src_ptr(p, srcECX, vtxESI, &a[1]);
+
+ /* Rearrange and possibly do BGR conversion:
+ */
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ else
+ sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
+
+ emit_pack_store_4ub(p, dest, temp);
+ j++; /* NOTE: two attrs consumed */
+ }
+ else {
+ _mesa_printf("Can't emit 3ub\n");
+ return GL_FALSE; /* add this later */
+ }
+ break;
+
+ case EMIT_4UB_4F_RGBA:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_BGRA:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_ARGB:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_ABGR:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4CHAN_4F_RGBA:
+ switch (CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case GL_FLOAT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case GL_UNSIGNED_SHORT:
+ default:
+ _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+ return GL_FALSE;
+ }
+ break;
+ default:
+ _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+ return GL_FALSE; /* catch any new opcodes */
+ }
+
+ /* Increment j by at least 1 - may have been incremented above also:
+ */
+ j++;
+ }
+
+ /* Next vertex:
+ */
+ x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vtx->vertex_size));
+
+ /* decr count, loop if not zero
+ */
+ x86_dec(&p->func, countEBP);
+ x86_test(&p->func, countEBP, countEBP);
+ x86_jcc(&p->func, cc_NZ, label);
+
+ /* Exit mmx state?
+ */
+ if (p->func.need_emms)
+ mmx_emms(&p->func);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(&p->func, fixup);
+
+ /* Pop regs and return
+ */
+ x86_pop(&p->func, x86_get_base_reg(vtxESI));
+ x86_pop(&p->func, countEBP);
+ x86_ret(&p->func);
+
+ assert(!vtx->emit);
+ vtx->emit = (tnl_emit_func)x86_get_func(&p->func);
+
+ assert( (char *) p->func.csr - (char *) p->func.store <= MAX_SSE_CODE_SIZE );
+ return GL_TRUE;
+}
+
+
+
+void _tnl_generate_sse_emit( GLcontext *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct x86_program p;
+
+ if (!cpu_has_xmm) {
+ vtx->codegen_emit = NULL;
+ return;
+ }
+
+ _mesa_memset(&p, 0, sizeof(p));
+
+ p.ctx = ctx;
+ p.inputs_safe = 0; /* for now */
+ p.outputs_safe = 0; /* for now */
+ p.have_sse2 = cpu_has_xmm2;
+ p.identity = x86_make_reg(file_XMM, 6);
+ p.chan0 = x86_make_reg(file_XMM, 7);
+
+ if (!x86_init_func_size(&p.func, MAX_SSE_CODE_SIZE)) {
+ vtx->emit = NULL;
+ return;
+ }
+
+ if (build_vertex_emit(&p)) {
+ _tnl_register_fastpath( vtx, GL_TRUE );
+ }
+ else {
+ /* Note the failure so that we don't keep trying to codegen an
+ * impossible state:
+ */
+ _tnl_register_fastpath( vtx, GL_FALSE );
+ x86_release_func(&p.func);
+ }
+}
+
+#else
+
+void _tnl_generate_sse_emit( GLcontext *ctx )
+{
+ /* Dummy version for when USE_SSE_ASM not defined */
+}
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_vp_build.c b/mesalib/src/mesa/tnl/t_vp_build.c
new file mode 100644
index 000000000..735937bbe
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vp_build.c
@@ -0,0 +1,60 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2007 Tungsten Graphics 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
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file t_vp_build.c
+ * Create a vertex program to execute the current fixed function T&L pipeline.
+ * \author Keith Whitwell
+ */
+
+
+#include "main/glheader.h"
+#include "main/ffvertex_prog.h"
+#include "main/dd.h"
+#include "t_vp_build.h"
+
+
+/**
+ * XXX This should go away someday, but still referenced by some drivers...
+ */
+void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx )
+{
+ const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
+
+ if (!ctx->VertexProgram._Current ||
+ ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
+ ctx->VertexProgram._Current
+ = ctx->VertexProgram._TnlProgram
+ = _mesa_get_fixed_func_vertex_program(ctx);
+ }
+
+ /* Tell the driver about the change. Could define a new target for
+ * this?
+ */
+ if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ (struct gl_program *) ctx->VertexProgram._Current);
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vp_build.h b/mesalib/src/mesa/tnl/t_vp_build.h
new file mode 100644
index 000000000..d6ebc66c0
--- /dev/null
+++ b/mesalib/src/mesa/tnl/t_vp_build.h
@@ -0,0 +1,42 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 2005 Tungsten Graphics 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
+ * TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN
+ * AN ACTION 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 T_VP_BUILD_H
+#define T_VP_BUILD_H
+
+#include "main/mtypes.h"
+
+#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \
+ _NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_TEXTURE_MATRIX | \
+ _NEW_TRANSFORM | \
+ _NEW_FOG | \
+ _NEW_POINT)
+
+extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/tnl/tnl.h b/mesalib/src/mesa/tnl/tnl.h
new file mode 100644
index 000000000..9c66d3b01
--- /dev/null
+++ b/mesalib/src/mesa/tnl/tnl.h
@@ -0,0 +1,100 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef _TNL_H
+#define _TNL_H
+
+#include "main/mtypes.h"
+
+
+
+/* These are the public-access functions exported from tnl. (A few
+ * more are currently hooked into dispatch directly by the module
+ * itself.)
+ */
+extern GLboolean
+_tnl_CreateContext( GLcontext *ctx );
+
+extern void
+_tnl_DestroyContext( GLcontext *ctx );
+
+extern void
+_tnl_InvalidateState( GLcontext *ctx, GLuint new_state );
+
+/* Functions to revive the tnl module after being unhooked from
+ * dispatch and/or driver callbacks.
+ */
+
+extern void
+_tnl_wakeup( GLcontext *ctx );
+
+/* Driver configuration options:
+ */
+extern void
+_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag );
+
+
+/* Control whether T&L does per-vertex fog
+ */
+extern void
+_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value );
+
+extern void
+_tnl_allow_pixel_fog( GLcontext *ctx, GLboolean value );
+
+extern void
+_tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program);
+
+struct _mesa_prim;
+struct _mesa_index_buffer;
+
+void
+_tnl_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index);
+
+void
+_tnl_vbo_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index);
+
+extern void
+_mesa_load_tracked_matrices(GLcontext *ctx);
+
+extern void
+_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]);
+
+#endif
diff --git a/mesalib/src/mesa/vbo/descrip.mms b/mesalib/src/mesa/vbo/descrip.mms
new file mode 100644
index 000000000..c2a16a04f
--- /dev/null
+++ b/mesalib/src/mesa/vbo/descrip.mms
@@ -0,0 +1,62 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
+# Last revision : 3 October 2007
+
+.first
+ define gl [---.include.gl]
+ define math [-.math]
+ define vbo [-.vbo]
+ define tnl [-.tnl]
+ define shader [-.shader]
+ define swrast [-.swrast]
+ define swrast_setup [-.swrast_setup]
+ define main [-.main]
+ define glapi [-.glapi]
+
+.include [---]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang]
+LIBDIR = [---.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
+
+SOURCES =vbo_context.c,vbo_exec.c,vbo_exec_api.c,vbo_exec_array.c,\
+ vbo_exec_draw.c,vbo_exec_eval.c,vbo_rebase.c,vbo_save.c,\
+ vbo_save_api.c,vbo_save_draw.c,vbo_save_loopback.c,\
+ vbo_split.c,vbo_split_copy.c,vbo_split_inplace.c
+
+OBJECTS =vbo_context.obj,vbo_exec.obj,vbo_exec_api.obj,vbo_exec_array.obj,\
+ vbo_exec_draw.obj,vbo_exec_eval.obj,vbo_rebase.obj,vbo_save.obj,\
+ vbo_save_api.obj,vbo_save_draw.obj,vbo_save_loopback.obj,\
+ vbo_split.obj,vbo_split_copy.obj,vbo_split_inplace.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+vbo_context.obj : vbo_context.c
+vbo_exec.obj : vbo_exec.c
+vbo_exec_api.obj : vbo_exec_api.c
+vbo_exec_array.obj : vbo_exec_array.c
+vbo_exec_draw.obj : vbo_exec_draw.c
+vbo_exec_eval.obj : vbo_exec_eval.c
+vbo_rebase.obj : vbo_rebase.c
+vbo_save.obj : vbo_save.c
+vbo_save_api.obj : vbo_save_api.c
+vbo_save_draw.obj : vbo_save_draw.c
+vbo_save_loopback.obj : vbo_save_loopback.c
+vbo_split.obj : vbo_split.c
+vbo_split_copy.obj : vbo_split_copy.c
+vbo_split_inplace.obj : vbo_split_inplace.c
diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h
new file mode 100644
index 000000000..5986e9357
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo.h
@@ -0,0 +1,142 @@
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+#ifndef _VBO_H
+#define _VBO_H
+
+#include "main/mtypes.h"
+
+struct _mesa_prim {
+ GLuint mode:8;
+ GLuint indexed:1;
+ GLuint begin:1;
+ GLuint end:1;
+ GLuint weak:1;
+ GLuint pad:20;
+
+ GLuint start;
+ GLuint count;
+};
+
+/* Would like to call this a "vbo_index_buffer", but this would be
+ * confusing as the indices are not neccessarily yet in a non-null
+ * buffer object.
+ */
+struct _mesa_index_buffer {
+ GLuint count;
+ GLenum type;
+ struct gl_buffer_object *obj;
+ const void *ptr;
+};
+
+
+
+GLboolean _vbo_CreateContext( GLcontext *ctx );
+void _vbo_DestroyContext( GLcontext *ctx );
+void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state );
+
+
+typedef void (*vbo_draw_func)( GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index );
+
+
+
+
+/* Utility function to cope with various constraints on tnl modules or
+ * hardware. This can be used to split an incoming set of arrays and
+ * primitives against the following constraints:
+ * - Maximum number of indices in index buffer.
+ * - Maximum number of vertices referenced by index buffer.
+ * - Maximum hardware vertex buffer size.
+ */
+struct split_limits {
+ GLuint max_verts;
+ GLuint max_indices;
+ GLuint max_vb_size; /* bytes */
+};
+
+
+void vbo_split_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+
+/* Helpers for dealing translating away non-zero min_index.
+ */
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] );
+
+void vbo_rebase_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw );
+void
+vbo_get_minmax_index(GLcontext *ctx, const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index);
+
+void vbo_use_buffer_objects(GLcontext *ctx);
+
+
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func);
+
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z);
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_attrib.h b/mesalib/src/mesa/vbo/vbo_attrib.h
new file mode 100644
index 000000000..0ae928f2a
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_attrib.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) Intel Corp. 2006. All Rights Reserved.
+ Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef VBO_ATTRIB_H
+#define VBO_ATTRIB_H
+
+
+/*
+ * Note: The first attributes match the VERT_ATTRIB_* definitions
+ * in mtypes.h. However, the tnl module has additional attributes
+ * for materials, color indexes, edge flags, etc.
+ */
+/* Although it's nice to use these as bit indexes in a DWORD flag, we
+ * could manage without if necessary. Another limit currently is the
+ * number of bits allocated for these numbers in places like vertex
+ * program instruction formats and register layouts.
+ */
+enum {
+ VBO_ATTRIB_POS = 0,
+ VBO_ATTRIB_WEIGHT = 1,
+ VBO_ATTRIB_NORMAL = 2,
+ VBO_ATTRIB_COLOR0 = 3,
+ VBO_ATTRIB_COLOR1 = 4,
+ VBO_ATTRIB_FOG = 5,
+ VBO_ATTRIB_INDEX = 6,
+ VBO_ATTRIB_EDGEFLAG = 7,
+ VBO_ATTRIB_TEX0 = 8,
+ VBO_ATTRIB_TEX1 = 9,
+ VBO_ATTRIB_TEX2 = 10,
+ VBO_ATTRIB_TEX3 = 11,
+ VBO_ATTRIB_TEX4 = 12,
+ VBO_ATTRIB_TEX5 = 13,
+ VBO_ATTRIB_TEX6 = 14,
+ VBO_ATTRIB_TEX7 = 15,
+
+ VBO_ATTRIB_GENERIC0 = 16, /* Not used? */
+ VBO_ATTRIB_GENERIC1 = 17,
+ VBO_ATTRIB_GENERIC2 = 18,
+ VBO_ATTRIB_GENERIC3 = 19,
+ VBO_ATTRIB_GENERIC4 = 20,
+ VBO_ATTRIB_GENERIC5 = 21,
+ VBO_ATTRIB_GENERIC6 = 22,
+ VBO_ATTRIB_GENERIC7 = 23,
+ VBO_ATTRIB_GENERIC8 = 24,
+ VBO_ATTRIB_GENERIC9 = 25,
+ VBO_ATTRIB_GENERIC10 = 26,
+ VBO_ATTRIB_GENERIC11 = 27,
+ VBO_ATTRIB_GENERIC12 = 28,
+ VBO_ATTRIB_GENERIC13 = 29,
+ VBO_ATTRIB_GENERIC14 = 30,
+ VBO_ATTRIB_GENERIC15 = 31,
+
+ /* XXX: in the vertex program InputsRead flag, we alias
+ * materials and generics and use knowledge about the program
+ * (whether it is a fixed-function emulation) to
+ * differentiate. Here we must keep them apart instead.
+ */
+ VBO_ATTRIB_MAT_FRONT_AMBIENT = 32,
+ VBO_ATTRIB_MAT_BACK_AMBIENT = 33,
+ VBO_ATTRIB_MAT_FRONT_DIFFUSE = 34,
+ VBO_ATTRIB_MAT_BACK_DIFFUSE = 35,
+ VBO_ATTRIB_MAT_FRONT_SPECULAR = 36,
+ VBO_ATTRIB_MAT_BACK_SPECULAR = 37,
+ VBO_ATTRIB_MAT_FRONT_EMISSION = 38,
+ VBO_ATTRIB_MAT_BACK_EMISSION = 39,
+ VBO_ATTRIB_MAT_FRONT_SHININESS = 40,
+ VBO_ATTRIB_MAT_BACK_SHININESS = 41,
+ VBO_ATTRIB_MAT_FRONT_INDEXES = 42,
+ VBO_ATTRIB_MAT_BACK_INDEXES = 43,
+
+ VBO_ATTRIB_MAX = 44
+};
+
+#define VBO_ATTRIB_FIRST_MATERIAL VBO_ATTRIB_MAT_FRONT_AMBIENT
+#define VBO_ATTRIB_LAST_MATERIAL VBO_ATTRIB_MAT_BACK_INDEXES
+
+#define VBO_MAX_COPIED_VERTS 3
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
new file mode 100644
index 000000000..7a889b8e2
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
@@ -0,0 +1,486 @@
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 )
+#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
+#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
+#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 )
+#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
+#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
+#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
+
+#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] )
+
+static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR2F( VBO_ATTRIB_POS, x, y );
+}
+
+static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR2FV( VBO_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3F( VBO_ATTRIB_POS, x, y, z );
+}
+
+static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3FV( VBO_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4F( VBO_ATTRIB_POS, x, y, z, w );
+}
+
+static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4FV( VBO_ATTRIB_POS, v );
+}
+
+static void GLAPIENTRY TAG(TexCoord1f)( GLfloat x )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1F( VBO_ATTRIB_TEX0, x );
+}
+
+static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1FV( VBO_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY TAG(TexCoord2f)( GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR2F( VBO_ATTRIB_TEX0, x, y );
+}
+
+static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR2FV( VBO_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY TAG(TexCoord3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3F( VBO_ATTRIB_TEX0, x, y, z );
+}
+
+static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3FV( VBO_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY TAG(TexCoord4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4F( VBO_ATTRIB_TEX0, x, y, z, w );
+}
+
+static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4FV( VBO_ATTRIB_TEX0, v );
+}
+
+static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3F( VBO_ATTRIB_NORMAL, x, y, z );
+}
+
+static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3FV( VBO_ATTRIB_NORMAL, v );
+}
+
+static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat x )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1F( VBO_ATTRIB_FOG, x );
+}
+
+static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1FV( VBO_ATTRIB_FOG, v );
+}
+
+static void GLAPIENTRY TAG(Color3f)( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3F( VBO_ATTRIB_COLOR0, x, y, z );
+}
+
+static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3FV( VBO_ATTRIB_COLOR0, v );
+}
+
+static void GLAPIENTRY TAG(Color4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4F( VBO_ATTRIB_COLOR0, x, y, z, w );
+}
+
+static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR4FV( VBO_ATTRIB_COLOR0, v );
+}
+
+static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat x, GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3F( VBO_ATTRIB_COLOR1, x, y, z );
+}
+
+static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR3FV( VBO_ATTRIB_COLOR1, v );
+}
+
+
+static void GLAPIENTRY TAG(EdgeFlag)( GLboolean b )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1F( VBO_ATTRIB_EDGEFLAG, (GLfloat)b );
+}
+
+static void GLAPIENTRY TAG(Indexf)( GLfloat f )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1F( VBO_ATTRIB_INDEX, f );
+}
+
+static void GLAPIENTRY TAG(Indexfv)( const GLfloat *f )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ ATTR1FV( VBO_ATTRIB_INDEX, f );
+}
+
+
+static void GLAPIENTRY TAG(MultiTexCoord1f)( GLenum target, GLfloat x )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR1F( attr, x );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord1fv)( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR1FV( attr, v );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord2f)( GLenum target, GLfloat x, GLfloat y )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR2F( attr, x, y );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord2fv)( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR2FV( attr, v );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord3f)( GLenum target, GLfloat x, GLfloat y,
+ GLfloat z)
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR3F( attr, x, y, z );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord3fv)( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR3FV( attr, v );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord4f)( GLenum target, GLfloat x, GLfloat y,
+ GLfloat z, GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR4F( attr, x, y, z, w );
+}
+
+static void GLAPIENTRY TAG(MultiTexCoord4fv)( GLenum target, const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
+ ATTR4FV( attr, v );
+}
+
+
+static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR1F(0, x);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR1FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x,
+ GLfloat y )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR2F(0, x, y);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR2FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR3F(0, x, y, z);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR3FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z,
+ GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR4F(0, x, y, z, w);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
+ else
+ ERROR();
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index == 0)
+ ATTR4FV(0, v);
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
+ ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
+ else
+ ERROR();
+}
+
+
+/* In addition to supporting NV_vertex_program, these entrypoints are
+ * used by the display list and other code specifically because of
+ * their property of aliasing with other attributes. (See
+ * vbo_save_loopback.c)
+ */
+static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR1F(index, x);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR1FV(index, v);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x,
+ GLfloat y )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR2F(index, x, y);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR2FV(index, v);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR3F(index, x, y, z);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR3FV(index, v);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x,
+ GLfloat y, GLfloat z,
+ GLfloat w )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR4F(index, x, y, z, w);
+}
+
+static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index,
+ const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ if (index < VBO_ATTRIB_MAX)
+ ATTR4FV(index, v);
+}
+
+
+#define MAT( ATTR, N, face, params ) \
+do { \
+ if (face != GL_BACK) \
+ MAT_ATTR( ATTR, N, params ); /* front */ \
+ if (face != GL_FRONT) \
+ MAT_ATTR( ATTR + 1, N, params ); /* back */ \
+} while (0)
+
+
+/* Colormaterial conflicts are dealt with later.
+ */
+static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname,
+ const GLfloat *params )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ switch (pname) {
+ case GL_EMISSION:
+ MAT( VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params );
+ break;
+ case GL_AMBIENT:
+ MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+ break;
+ case GL_DIFFUSE:
+ MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+ break;
+ case GL_SPECULAR:
+ MAT( VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params );
+ break;
+ case GL_SHININESS:
+ MAT( VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params );
+ break;
+ case GL_COLOR_INDEXES:
+ MAT( VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params );
+ break;
+ case GL_AMBIENT_AND_DIFFUSE:
+ MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params );
+ MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params );
+ break;
+ default:
+ ERROR();
+ return;
+ }
+}
+
+
+#undef ATTR1FV
+#undef ATTR2FV
+#undef ATTR3FV
+#undef ATTR4FV
+
+#undef ATTR1F
+#undef ATTR2F
+#undef ATTR3F
+#undef ATTR4F
+
+#undef MAT
+#undef MAT_ATTR
diff --git a/mesalib/src/mesa/vbo/vbo_context.c b/mesalib/src/mesa/vbo/vbo_context.c
new file mode 100644
index 000000000..75c32e0b9
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_context.c
@@ -0,0 +1,273 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/api_arrayelt.h"
+#include "main/bufferobj.h"
+#include "math/m_eval.h"
+#include "vbo.h"
+#include "vbo_context.h"
+
+#if 0
+/* Reach out and grab this to use as the default:
+ */
+extern void _tnl_draw_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index );
+#endif
+
+
+
+#define NR_LEGACY_ATTRIBS 16
+#define NR_GENERIC_ATTRIBS 16
+#define NR_MAT_ATTRIBS 12
+
+static GLuint check_size( const GLfloat *attr )
+{
+ if (attr[3] != 1.0) return 4;
+ if (attr[2] != 0.0) return 3;
+ if (attr[1] != 0.0) return 2;
+ return 1;
+}
+
+static void init_legacy_currval(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->legacy_currval;
+ GLuint i;
+
+ memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS);
+
+ /* Set up a constant (StrideB == 0) array for each current
+ * attribute:
+ */
+ for (i = 0; i < NR_LEGACY_ATTRIBS; i++) {
+ struct gl_client_array *cl = &arrays[i];
+
+ /* Size will have to be determined at runtime:
+ */
+ cl->Size = check_size(ctx->Current.Attrib[i]);
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Ptr = (const void *)ctx->Current.Attrib[i];
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+
+static void init_generic_currval(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->generic_currval;
+ GLuint i;
+
+ memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS);
+
+ for (i = 0; i < NR_GENERIC_ATTRIBS; i++) {
+ struct gl_client_array *cl = &arrays[i];
+
+ /* This will have to be determined at runtime:
+ */
+ cl->Size = 1;
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i];
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+
+static void init_mat_currval(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct gl_client_array *arrays = vbo->mat_currval;
+ GLuint i;
+
+ ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX);
+
+ memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS);
+
+ /* Set up a constant (StrideB == 0) array for each current
+ * attribute:
+ */
+ for (i = 0; i < NR_MAT_ATTRIBS; i++) {
+ struct gl_client_array *cl = &arrays[i];
+
+ /* Size is fixed for the material attributes, for others will
+ * be determined at runtime:
+ */
+ switch (i - VERT_ATTRIB_GENERIC0) {
+ case MAT_ATTRIB_FRONT_SHININESS:
+ case MAT_ATTRIB_BACK_SHININESS:
+ cl->Size = 1;
+ break;
+ case MAT_ATTRIB_FRONT_INDEXES:
+ case MAT_ATTRIB_BACK_INDEXES:
+ cl->Size = 3;
+ break;
+ default:
+ cl->Size = 4;
+ break;
+ }
+
+ cl->Ptr = (const void *)ctx->Light.Material.Attrib[i];
+ cl->Type = GL_FLOAT;
+ cl->Format = GL_RGBA;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Enabled = 1;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
+ }
+}
+
+#if 0
+
+static void vbo_exec_current_init( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ GLint i;
+
+ /* setup the pointers for the typical 16 vertex attributes */
+ for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++)
+ exec->vtx.current[i] = ctx->Current.Attrib[i];
+
+ /* setup pointers for the 12 material attributes */
+ for (i = 0; i < MAT_ATTRIB_MAX; i++)
+ exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] =
+ ctx->Light.Material.Attrib[i];
+}
+#endif
+
+GLboolean _vbo_CreateContext( GLcontext *ctx )
+{
+ struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
+
+ ctx->swtnl_im = (void *)vbo;
+
+ /* Initialize the arrayelt helper
+ */
+ if (!ctx->aelt_context &&
+ !_ae_create_context( ctx )) {
+ return GL_FALSE;
+ }
+
+ /* TODO: remove these pointers.
+ */
+ vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS];
+ vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0];
+ vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT];
+
+ init_legacy_currval( ctx );
+ init_generic_currval( ctx );
+ init_mat_currval( ctx );
+
+ /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
+ * of vertex program active.
+ */
+ {
+ GLuint i;
+
+ /* When no vertex program, pull in the material attributes in
+ * the 16..32 generic range.
+ */
+ for (i = 0; i < 16; i++)
+ vbo->map_vp_none[i] = i;
+ for (i = 0; i < 12; i++)
+ vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
+ for (i = 0; i < 4; i++)
+ vbo->map_vp_none[28+i] = i;
+
+ for (i = 0; i < Elements(vbo->map_vp_arb); i++)
+ vbo->map_vp_arb[i] = i;
+ }
+
+
+ /* By default:
+ */
+#if 0 /* dead - see vbo_set_draw_func() */
+ vbo->draw_prims = _tnl_draw_prims;
+#endif
+
+ /* Hook our functions into exec and compile dispatch tables. These
+ * will pretty much be permanently installed, which means that the
+ * vtxfmt mechanism can be removed now.
+ */
+ vbo_exec_init( ctx );
+#if FEATURE_dlist
+ vbo_save_init( ctx );
+#endif
+
+ _math_init_eval();
+
+ return GL_TRUE;
+}
+
+void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ _ae_invalidate_state(ctx, new_state);
+ vbo_exec_invalidate_state(ctx, new_state);
+}
+
+
+void _vbo_DestroyContext( GLcontext *ctx )
+{
+ if (ctx->aelt_context) {
+ _ae_destroy_context( ctx );
+ ctx->aelt_context = NULL;
+ }
+
+ if (vbo_context(ctx)) {
+ vbo_exec_destroy(ctx);
+#if FEATURE_dlist
+ vbo_save_destroy(ctx);
+#endif
+ FREE(vbo_context(ctx));
+ ctx->swtnl_im = NULL;
+ }
+}
+
+
+void vbo_set_draw_func(GLcontext *ctx, vbo_draw_func func)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ vbo->draw_prims = func;
+}
+
diff --git a/mesalib/src/mesa/vbo/vbo_context.h b/mesalib/src/mesa/vbo/vbo_context.h
new file mode 100644
index 000000000..8b726dc8a
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_context.h
@@ -0,0 +1,114 @@
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The VBO builder module
+ *
+ * This module hooks into the GL dispatch table and catches all vertex
+ * building and drawing commands, such as glVertex3f, glBegin and
+ * glDrawArrays. The module stores all incoming vertex data as arrays
+ * in GL vertex buffer objects (VBOs), and translates all drawing
+ * commands into calls to a driver supplied DrawPrimitives() callback.
+ *
+ * The module captures both immediate mode and display list drawing,
+ * and manages the allocation, reference counting and deallocation of
+ * vertex buffer objects itself.
+ *
+ * The DrawPrimitives() callback can be either implemented by the
+ * driver itself or hooked to the tnl module's _tnl_draw_primitives()
+ * function for hardware without tnl capablilties or during fallbacks.
+ */
+
+
+#ifndef _VBO_CONTEXT_H
+#define _VBO_CONTEXT_H
+
+#include "vbo.h"
+#include "vbo_attrib.h"
+#include "vbo_exec.h"
+#if FEATURE_dlist
+#include "vbo_save.h"
+#endif
+
+
+struct vbo_context {
+ struct gl_client_array currval[VBO_ATTRIB_MAX];
+
+ /* These point into the above. TODO: remove.
+ */
+ struct gl_client_array *legacy_currval;
+ struct gl_client_array *generic_currval;
+ struct gl_client_array *mat_currval;
+
+ GLuint map_vp_none[VERT_ATTRIB_MAX];
+ GLuint map_vp_arb[VERT_ATTRIB_MAX];
+
+ GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
+ GLfloat CurrentFloatEdgeFlag;
+
+
+ struct vbo_exec_context exec;
+#if FEATURE_dlist
+ struct vbo_save_context save;
+#endif
+
+ /* Callback into the driver. This must always succeed, the driver
+ * is responsible for initiating any fallback actions required:
+ */
+ vbo_draw_func draw_prims;
+};
+
+
+static INLINE struct vbo_context *vbo_context(GLcontext *ctx)
+{
+ return (struct vbo_context *)(ctx->swtnl_im);
+}
+
+
+/**
+ * Return VP_x token to indicate whether we're running fixed-function
+ * vertex transformation, an NV vertex program or ARB vertex program/shader.
+ */
+static INLINE enum vp_mode
+get_program_mode( GLcontext *ctx )
+{
+ if (!ctx->VertexProgram._Current)
+ return VP_NONE;
+ else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
+ return VP_NONE;
+ else if (ctx->VertexProgram._Current->IsNVProgram)
+ return VP_NV;
+ else
+ return VP_ARB;
+}
+
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_exec.c b/mesalib/src/mesa/vbo/vbo_exec.c
new file mode 100644
index 000000000..e168a89ea
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec.c
@@ -0,0 +1,97 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/api_arrayelt.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/vtxfmt.h"
+
+#include "vbo_context.h"
+
+void vbo_exec_init( GLcontext *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ exec->ctx = ctx;
+
+ /* Initialize the arrayelt helper
+ */
+ if (!ctx->aelt_context &&
+ !_ae_create_context( ctx ))
+ return;
+
+ vbo_exec_vtx_init( exec );
+ vbo_exec_array_init( exec );
+
+ /* Hook our functions into exec and compile dispatch tables.
+ */
+ _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
+
+ ctx->Driver.NeedFlush = 0;
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+ ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
+ ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
+
+ vbo_exec_invalidate_state( ctx, ~0 );
+}
+
+
+void vbo_exec_destroy( GLcontext *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (ctx->aelt_context) {
+ _ae_destroy_context( ctx );
+ ctx->aelt_context = NULL;
+ }
+
+ vbo_exec_vtx_destroy( exec );
+ vbo_exec_array_destroy( exec );
+}
+
+/* Really want to install these callbacks to a central facility to be
+ * invoked according to the state flags. That will have to wait for a
+ * mesa rework:
+ */
+void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (new_state & (_NEW_PROGRAM|_NEW_EVAL))
+ exec->eval.recalculate_maps = 1;
+
+ _ae_invalidate_state(ctx, new_state);
+}
+
+
+
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h
new file mode 100644
index 000000000..e0f44892c
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec.h
@@ -0,0 +1,179 @@
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __VBO_EXEC_H__
+#define __VBO_EXEC_H__
+
+#include "main/mtypes.h"
+#include "vbo.h"
+#include "vbo_attrib.h"
+
+
+#define VBO_MAX_PRIM 64
+
+/* Wierd implementation stuff:
+ */
+#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
+#define VBO_MAX_ATTR_CODEGEN 16
+#define ERROR_ATTRIB 16
+
+
+/** Current vertex program mode */
+enum vp_mode {
+ VP_NONE, /**< fixed function */
+ VP_NV, /**< NV vertex program */
+ VP_ARB /**< ARB vertex program or GLSL vertex shader */
+};
+
+
+struct vbo_exec_eval1_map {
+ struct gl_1d_map *map;
+ GLuint sz;
+};
+
+struct vbo_exec_eval2_map {
+ struct gl_2d_map *map;
+ GLuint sz;
+};
+
+
+
+struct vbo_exec_copied_vtx {
+ GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
+ GLuint nr;
+};
+
+
+typedef void (*vbo_attrfv_func)( const GLfloat * );
+
+
+struct vbo_exec_context
+{
+ GLcontext *ctx;
+ GLvertexformat vtxfmt;
+
+ struct {
+ struct gl_buffer_object *bufferobj;
+
+ GLuint vertex_size; /* in dwords */
+
+ struct _mesa_prim prim[VBO_MAX_PRIM];
+ GLuint prim_count;
+
+ GLfloat *buffer_map;
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
+ GLuint buffer_used; /* in bytes */
+ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
+
+ GLuint vert_count;
+ GLuint max_vert;
+ struct vbo_exec_copied_vtx copied;
+
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLubyte active_sz[VBO_ATTRIB_MAX];
+
+ GLfloat *attrptr[VBO_ATTRIB_MAX];
+ struct gl_client_array arrays[VBO_ATTRIB_MAX];
+
+ /* According to program mode, the values above plus current
+ * values are squashed down to the 32 attributes passed to the
+ * vertex program below:
+ */
+ enum vp_mode program_mode;
+ GLuint enabled_flags;
+ const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
+ } vtx;
+
+
+ struct {
+ GLboolean recalculate_maps;
+ struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX];
+ struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX];
+ } eval;
+
+ struct {
+ enum vp_mode program_mode;
+ GLuint enabled_flags;
+ GLuint array_obj;
+
+ /* These just mirror the current arrayobj (todo: make arrayobj
+ * look like this and remove the mirror):
+ */
+ const struct gl_client_array *legacy_array[16];
+ const struct gl_client_array *generic_array[16];
+
+ /* Arrays and current values manipulated according to program
+ * mode, etc. These are the attributes as seen by vertex
+ * programs:
+ */
+ const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
+ } array;
+};
+
+
+
+/* External API:
+ */
+void vbo_exec_init( GLcontext *ctx );
+void vbo_exec_destroy( GLcontext *ctx );
+void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state );
+void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap );
+
+void vbo_exec_BeginVertices( GLcontext *ctx );
+void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags );
+
+
+/* Internal functions:
+ */
+void vbo_exec_array_init( struct vbo_exec_context *exec );
+void vbo_exec_array_destroy( struct vbo_exec_context *exec );
+
+
+void vbo_exec_vtx_init( struct vbo_exec_context *exec );
+void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
+void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
+void vbo_exec_vtx_map( struct vbo_exec_context *exec );
+void vbo_exec_vtx_wrap( struct vbo_exec_context *exec );
+
+void vbo_exec_eval_update( struct vbo_exec_context *exec );
+
+void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
+ GLfloat u, GLfloat v );
+
+void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec,
+ GLfloat u);
+
+extern GLboolean
+vbo_validate_shaders(GLcontext *ctx);
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
new file mode 100644
index 000000000..387d4ee3d
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -0,0 +1,838 @@
+/**************************************************************************
+
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/vtxfmt.h"
+#if FEATURE_dlist
+#include "main/dlist.h"
+#endif
+#include "main/state.h"
+#include "main/light.h"
+#include "main/api_arrayelt.h"
+#include "main/api_noop.h"
+#include "glapi/dispatch.h"
+
+#include "vbo_context.h"
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
+/** ID/name for immediate-mode VBO */
+#define IMM_BUFFER_NAME 0xaabbccdd
+
+
+static void reset_attrfv( struct vbo_exec_context *exec );
+
+
+/* Close off the last primitive, execute the buffer, restart the
+ * primitive.
+ */
+static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
+{
+ if (exec->vtx.prim_count == 0) {
+ exec->vtx.copied.nr = 0;
+ exec->vtx.vert_count = 0;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+ else {
+ GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
+ GLuint last_count;
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ GLint i = exec->vtx.prim_count - 1;
+ assert(i >= 0);
+ exec->vtx.prim[i].count = (exec->vtx.vert_count -
+ exec->vtx.prim[i].start);
+ }
+
+ last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
+
+ /* Execute the buffer and save copied vertices.
+ */
+ if (exec->vtx.vert_count)
+ vbo_exec_vtx_flush( exec, GL_FALSE );
+ else {
+ exec->vtx.prim_count = 0;
+ exec->vtx.copied.nr = 0;
+ }
+
+ /* Emit a glBegin to start the new list.
+ */
+ assert(exec->vtx.prim_count == 0);
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
+ exec->vtx.prim[0].start = 0;
+ exec->vtx.prim[0].count = 0;
+ exec->vtx.prim_count++;
+
+ if (exec->vtx.copied.nr == last_count)
+ exec->vtx.prim[0].begin = last_begin;
+ }
+ }
+}
+
+
+/* Deal with buffer wrapping where provoked by the vertex buffer
+ * filling up, as opposed to upgrade_vertex().
+ */
+void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
+{
+ GLfloat *data = exec->vtx.copied.buffer;
+ GLuint i;
+
+ /* Run pipeline on current vertices, copy wrapped vertices
+ * to exec->vtx.copied.
+ */
+ vbo_exec_wrap_buffers( exec );
+
+ /* Copy stored stored vertices to start of new list.
+ */
+ assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
+
+ for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
+ _mesa_memcpy( exec->vtx.buffer_ptr, data,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size;
+ data += exec->vtx.vertex_size;
+ exec->vtx.vert_count++;
+ }
+
+ exec->vtx.copied.nr = 0;
+}
+
+
+/*
+ * Copy the active vertex's values to the ctx->Current fields.
+ */
+static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLuint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (exec->vtx.attrsz[i]) {
+ /* Note: the exec->vtx.current[i] pointers point into the
+ * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
+ */
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i]);
+
+ if (memcmp(current, tmp, sizeof(tmp)) != 0)
+ {
+ memcpy(current, tmp, sizeof(tmp));
+
+ /* Given that we explicitly state size here, there is no need
+ * for the COPY_CLEAN above, could just copy 16 bytes and be
+ * done. The only problem is when Mesa accesses ctx->Current
+ * directly.
+ */
+ vbo->currval[i].Size = exec->vtx.attrsz[i];
+
+ /* This triggers rather too much recalculation of Mesa state
+ * that doesn't get used (eg light positions).
+ */
+ if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+ i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
+ }
+ }
+
+ /* Colormaterial -- this kindof sucks.
+ */
+ if (ctx->Light.ColorMaterialEnabled &&
+ exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
+ _mesa_update_color_material(ctx,
+ ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
+ }
+}
+
+
+static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ switch (exec->vtx.attrsz[i]) {
+ case 4: exec->vtx.attrptr[i][3] = current[3];
+ case 3: exec->vtx.attrptr[i][2] = current[2];
+ case 2: exec->vtx.attrptr[i][1] = current[1];
+ case 1: exec->vtx.attrptr[i][0] = current[0];
+ break;
+ }
+ }
+}
+
+
+/* Flush existing data, set new attrib size, replay copied vertices.
+ */
+static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
+ GLuint attr,
+ GLuint newsz )
+{
+ GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLint lastcount = exec->vtx.vert_count;
+ GLfloat *tmp;
+ GLuint oldsz;
+ GLuint i;
+
+ /* Run pipeline on current vertices, copy wrapped vertices
+ * to exec->vtx.copied.
+ */
+ vbo_exec_wrap_buffers( exec );
+
+
+ /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
+ * when the attribute already exists in the vertex and is having
+ * its size increased.
+ */
+ vbo_exec_copy_to_current( exec );
+
+
+ /* Heuristic: Attempt to isolate attributes received outside
+ * begin/end so that they don't bloat the vertices.
+ */
+ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
+ exec->vtx.attrsz[attr] == 0 &&
+ lastcount > 8 &&
+ exec->vtx.vertex_size) {
+ reset_attrfv( exec );
+ }
+
+ /* Fix up sizes:
+ */
+ oldsz = exec->vtx.attrsz[attr];
+ exec->vtx.attrsz[attr] = newsz;
+
+ exec->vtx.vertex_size += newsz - oldsz;
+ exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat)));
+ exec->vtx.vert_count = 0;
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+
+
+ /* Recalculate all the attrptr[] values
+ */
+ for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) {
+ if (exec->vtx.attrsz[i]) {
+ exec->vtx.attrptr[i] = tmp;
+ tmp += exec->vtx.attrsz[i];
+ }
+ else
+ exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
+ }
+
+ /* Copy from current to repopulate the vertex with correct values.
+ */
+ vbo_exec_copy_from_current( exec );
+
+ /* Replay stored vertices to translate them
+ * to new format here.
+ *
+ * -- No need to replay - just copy piecewise
+ */
+ if (exec->vtx.copied.nr)
+ {
+ GLfloat *data = exec->vtx.copied.buffer;
+ GLfloat *dest = exec->vtx.buffer_ptr;
+ GLuint j;
+
+ assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
+
+ for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
+ for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
+ if (exec->vtx.attrsz[j]) {
+ if (j == attr) {
+ if (oldsz) {
+ COPY_CLEAN_4V( dest, oldsz, data );
+ data += oldsz;
+ dest += newsz;
+ } else {
+ const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
+ COPY_SZ_4V( dest, newsz, current );
+ dest += newsz;
+ }
+ }
+ else {
+ GLuint sz = exec->vtx.attrsz[j];
+ COPY_SZ_4V( dest, sz, data );
+ dest += sz;
+ data += sz;
+ }
+ }
+ }
+ }
+
+ exec->vtx.buffer_ptr = dest;
+ exec->vtx.vert_count += exec->vtx.copied.nr;
+ exec->vtx.copied.nr = 0;
+ }
+}
+
+
+static void vbo_exec_fixup_vertex( GLcontext *ctx,
+ GLuint attr, GLuint sz )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int i;
+
+ if (sz > exec->vtx.attrsz[attr]) {
+ /* New size is larger. Need to flush existing vertices and get
+ * an enlarged vertex format.
+ */
+ vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
+ }
+ else if (sz < exec->vtx.active_sz[attr]) {
+ static const GLfloat id[4] = { 0, 0, 0, 1 };
+
+ /* New size is smaller - just need to fill in some
+ * zeros. Don't need to flush or wrap.
+ */
+ for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
+ exec->vtx.attrptr[attr][i-1] = id[i-1];
+ }
+
+ exec->vtx.active_sz[attr] = sz;
+
+ /* Does setting NeedFlush belong here? Necessitates resetting
+ * vtxfmt on each flush (otherwise flags won't get reset
+ * afterwards).
+ */
+ if (attr == 0)
+ exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+}
+
+
+
+
+/*
+ */
+#define ATTR( A, N, V0, V1, V2, V3 ) \
+do { \
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
+ \
+ if (exec->vtx.active_sz[A] != N) \
+ vbo_exec_fixup_vertex(ctx, A, N); \
+ \
+ { \
+ GLfloat *dest = exec->vtx.attrptr[A]; \
+ if (N>0) dest[0] = V0; \
+ if (N>1) dest[1] = V1; \
+ if (N>2) dest[2] = V2; \
+ if (N>3) dest[3] = V3; \
+ } \
+ \
+ if ((A) == 0) { \
+ GLuint i; \
+ \
+ for (i = 0; i < exec->vtx.vertex_size; i++) \
+ exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
+ \
+ exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
+ exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
+ \
+ if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
+ vbo_exec_vtx_wrap( exec ); \
+ } \
+} while (0)
+
+
+#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
+#define TAG(x) vbo_##x
+
+#include "vbo_attrib_tmp.h"
+
+
+
+
+
+/* Eval
+ */
+static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ {
+ GLint i;
+ if (exec->eval.recalculate_maps)
+ vbo_exec_eval_update( exec );
+
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
+ if (exec->eval.map1[i].map)
+ if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
+ }
+ }
+
+
+ _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+
+ vbo_exec_do_EvalCoord1f( exec, u );
+
+ _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ {
+ GLint i;
+ if (exec->eval.recalculate_maps)
+ vbo_exec_eval_update( exec );
+
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
+ if (exec->eval.map2[i].map)
+ if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
+ vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
+ }
+
+ if (ctx->Eval.AutoNormal)
+ if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
+ vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
+ }
+
+ _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+
+ vbo_exec_do_EvalCoord2f( exec, u, v );
+
+ _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
+ exec->vtx.vertex_size * sizeof(GLfloat));
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
+{
+ vbo_exec_EvalCoord1f( u[0] );
+}
+
+static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
+{
+ vbo_exec_EvalCoord2f( u[0], u[1] );
+}
+
+static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
+ (GLfloat) ctx->Eval.MapGrid1un);
+ GLfloat u = i * du + ctx->Eval.MapGrid1u1;
+
+ vbo_exec_EvalCoord1f( u );
+}
+
+
+static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
+ (GLfloat) ctx->Eval.MapGrid2un);
+ GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
+ (GLfloat) ctx->Eval.MapGrid2vn);
+ GLfloat u = i * du + ctx->Eval.MapGrid2u1;
+ GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
+
+ vbo_exec_EvalCoord2f( u, v );
+}
+
+
+/* Build a list of primitives on the fly. Keep
+ * ctx->Driver.CurrentExecPrimitive uptodate as well.
+ */
+static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT( ctx );
+
+ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int i;
+
+ if (ctx->NewState) {
+ _mesa_update_state( ctx );
+
+ CALL_Begin(ctx->Exec, (mode));
+ return;
+ }
+
+ if (!_mesa_valid_to_render(ctx, "glBegin")) {
+ return;
+ }
+
+ /* Heuristic: attempt to isolate attributes occuring outside
+ * begin/end pairs.
+ */
+ if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
+ vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
+
+ i = exec->vtx.prim_count++;
+ exec->vtx.prim[i].mode = mode;
+ exec->vtx.prim[i].begin = 1;
+ exec->vtx.prim[i].end = 0;
+ exec->vtx.prim[i].indexed = 0;
+ exec->vtx.prim[i].weak = 0;
+ exec->vtx.prim[i].pad = 0;
+ exec->vtx.prim[i].start = exec->vtx.vert_count;
+ exec->vtx.prim[i].count = 0;
+
+ ctx->Driver.CurrentExecPrimitive = mode;
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+
+}
+
+static void GLAPIENTRY vbo_exec_End( void )
+{
+ GET_CURRENT_CONTEXT( ctx );
+
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ int idx = exec->vtx.vert_count;
+ int i = exec->vtx.prim_count - 1;
+
+ exec->vtx.prim[i].end = 1;
+ exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
+
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+
+ if (exec->vtx.prim_count == VBO_MAX_PRIM)
+ vbo_exec_vtx_flush( exec, GL_FALSE );
+ }
+ else
+ _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+}
+
+
+static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
+{
+ GLvertexformat *vfmt = &exec->vtxfmt;
+
+ vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ vfmt->Begin = vbo_exec_Begin;
+#if FEATURE_dlist
+ vfmt->CallList = _mesa_CallList;
+ vfmt->CallLists = _mesa_CallLists;
+#endif
+ vfmt->End = vbo_exec_End;
+ vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
+ vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
+ vfmt->EvalCoord2f = vbo_exec_EvalCoord2f;
+ vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv;
+ vfmt->EvalPoint1 = vbo_exec_EvalPoint1;
+ vfmt->EvalPoint2 = vbo_exec_EvalPoint2;
+
+ vfmt->Rectf = _mesa_noop_Rectf;
+ vfmt->EvalMesh1 = _mesa_noop_EvalMesh1;
+ vfmt->EvalMesh2 = _mesa_noop_EvalMesh2;
+
+
+ /* from attrib_tmp.h:
+ */
+ vfmt->Color3f = vbo_Color3f;
+ vfmt->Color3fv = vbo_Color3fv;
+ vfmt->Color4f = vbo_Color4f;
+ vfmt->Color4fv = vbo_Color4fv;
+ vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
+ vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
+ vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
+ vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
+ vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
+ vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
+ vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
+ vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
+ vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
+ vfmt->Normal3f = vbo_Normal3f;
+ vfmt->Normal3fv = vbo_Normal3fv;
+ vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = vbo_TexCoord1f;
+ vfmt->TexCoord1fv = vbo_TexCoord1fv;
+ vfmt->TexCoord2f = vbo_TexCoord2f;
+ vfmt->TexCoord2fv = vbo_TexCoord2fv;
+ vfmt->TexCoord3f = vbo_TexCoord3f;
+ vfmt->TexCoord3fv = vbo_TexCoord3fv;
+ vfmt->TexCoord4f = vbo_TexCoord4f;
+ vfmt->TexCoord4fv = vbo_TexCoord4fv;
+ vfmt->Vertex2f = vbo_Vertex2f;
+ vfmt->Vertex2fv = vbo_Vertex2fv;
+ vfmt->Vertex3f = vbo_Vertex3f;
+ vfmt->Vertex3fv = vbo_Vertex3fv;
+ vfmt->Vertex4f = vbo_Vertex4f;
+ vfmt->Vertex4fv = vbo_Vertex4fv;
+
+ vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
+
+ vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
+
+ vfmt->Materialfv = vbo_Materialfv;
+
+ vfmt->EdgeFlag = vbo_EdgeFlag;
+ vfmt->Indexf = vbo_Indexf;
+ vfmt->Indexfv = vbo_Indexfv;
+
+}
+
+
+/**
+ * Tell the VBO module to use a real OpenGL vertex buffer object to
+ * store accumulated immediate-mode vertex data.
+ * This replaces the malloced buffer which was created in
+ * vb_exec_vtx_init() below.
+ */
+void vbo_use_buffer_objects(GLcontext *ctx)
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ /* Any buffer name but 0 can be used here since this bufferobj won't
+ * go into the bufferobj hashtable.
+ */
+ GLuint bufName = IMM_BUFFER_NAME;
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+ GLenum usage = GL_STREAM_DRAW_ARB;
+ GLsizei size = VBO_VERT_BUFFER_SIZE;
+
+ /* Make sure this func is only used once */
+ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
+ if (exec->vtx.buffer_map) {
+ _mesa_align_free(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+
+ /* Allocate a real buffer object now */
+ exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
+ ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
+}
+
+
+
+void vbo_exec_vtx_init( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLuint i;
+
+ /* Allocate a buffer object. Will just reuse this object
+ * continuously, unless vbo_use_buffer_objects() is called to enable
+ * use of real VBOs.
+ */
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.bufferobj,
+ ctx->Shared->NullBufferObj);
+
+ ASSERT(!exec->vtx.buffer_map);
+ exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+
+ vbo_exec_vtxfmt_init( exec );
+
+ /* Hook our functions into the dispatch table.
+ */
+ _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ exec->vtx.attrsz[i] = 0;
+ exec->vtx.active_sz[i] = 0;
+ exec->vtx.inputs[i] = &exec->vtx.arrays[i];
+ }
+
+ {
+ struct gl_client_array *arrays = exec->vtx.arrays;
+ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
+ memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+ }
+
+ exec->vtx.vertex_size = 0;
+}
+
+
+void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
+{
+ /* using a real VBO for vertex data */
+ GLcontext *ctx = exec->ctx;
+ unsigned i;
+
+ /* True VBOs should already be unmapped
+ */
+ if (exec->vtx.buffer_map) {
+ ASSERT(exec->vtx.bufferobj->Name == 0 ||
+ exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
+ if (exec->vtx.bufferobj->Name == 0) {
+ ALIGN_FREE(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+ }
+
+ /* Drop any outstanding reference to the vertex buffer
+ */
+ for (i = 0; i < Elements(exec->vtx.arrays); i++) {
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.arrays[i].BufferObj,
+ NULL);
+ }
+
+ /* Free the vertex buffer:
+ */
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
+}
+
+void vbo_exec_BeginVertices( GLcontext *ctx )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+ if (0) _mesa_printf("%s\n", __FUNCTION__);
+ vbo_exec_vtx_map( exec );
+
+ assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
+ exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
+}
+
+void vbo_exec_FlushVertices_internal( GLcontext *ctx, GLboolean unmap )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (exec->vtx.vert_count || unmap) {
+ vbo_exec_vtx_flush( exec, unmap );
+ }
+
+ if (exec->vtx.vertex_size) {
+ vbo_exec_copy_to_current( exec );
+ reset_attrfv( exec );
+ }
+}
+
+
+
+void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags )
+{
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
+
+ if (0) _mesa_printf("%s\n", __FUNCTION__);
+
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+ if (0) _mesa_printf("%s - inside begin/end\n", __FUNCTION__);
+ return;
+ }
+
+ vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
+
+ /* Need to do this to ensure BeginVertices gets called again:
+ */
+ if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {
+ _mesa_restore_exec_vtxfmt( ctx );
+ exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+ }
+
+ exec->ctx->Driver.NeedFlush &= ~flags;
+}
+
+
+static void reset_attrfv( struct vbo_exec_context *exec )
+{
+ GLuint i;
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ exec->vtx.attrsz[i] = 0;
+ exec->vtx.active_sz[i] = 0;
+ }
+
+ exec->vtx.vertex_size = 0;
+}
+
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ vbo_Color4f(r, g, b, a);
+}
+
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ vbo_Normal3f(x, y, z);
+}
+
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ vbo_MultiTexCoord4f(target, s, t, r, q);
+}
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+ vbo_Materialfv(face, pname, params);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ vbo_VertexAttrib4fARB(index, x, y, z, w);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
new file mode 100644
index 000000000..39c295763
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -0,0 +1,965 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/state.h"
+#include "main/api_validate.h"
+#include "main/api_noop.h"
+#include "main/varray.h"
+#include "main/bufferobj.h"
+#include "main/macros.h"
+#include "glapi/dispatch.h"
+
+#include "vbo_context.h"
+
+
+/**
+ * Compute min and max elements for glDraw[Range]Elements() calls.
+ */
+void
+vbo_get_minmax_index(GLcontext *ctx,
+ const struct _mesa_prim *prim,
+ const struct _mesa_index_buffer *ib,
+ GLuint *min_index, GLuint *max_index)
+{
+ GLuint i;
+ GLsizei count = prim->count;
+ const void *indices;
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ib->obj);
+ indices = ADD_POINTERS(map, ib->ptr);
+ } else {
+ indices = ib->ptr;
+ }
+
+ switch (ib->type) {
+ case GL_UNSIGNED_INT: {
+ const GLuint *ui_indices = (const GLuint *)indices;
+ GLuint max_ui = ui_indices[count-1];
+ GLuint min_ui = ui_indices[0];
+ for (i = 0; i < count; i++) {
+ if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
+ if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
+ }
+ *min_index = min_ui;
+ *max_index = max_ui;
+ break;
+ }
+ case GL_UNSIGNED_SHORT: {
+ const GLushort *us_indices = (const GLushort *)indices;
+ GLuint max_us = us_indices[count-1];
+ GLuint min_us = us_indices[0];
+ for (i = 0; i < count; i++) {
+ if (us_indices[i] > max_us) max_us = us_indices[i];
+ if (us_indices[i] < min_us) min_us = us_indices[i];
+ }
+ *min_index = min_us;
+ *max_index = max_us;
+ break;
+ }
+ case GL_UNSIGNED_BYTE: {
+ const GLubyte *ub_indices = (const GLubyte *)indices;
+ GLuint max_ub = ub_indices[count-1];
+ GLuint min_ub = ub_indices[0];
+ for (i = 0; i < count; i++) {
+ if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
+ if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
+ }
+ *min_index = min_ub;
+ *max_index = max_ub;
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+
+ if (_mesa_is_bufferobj(ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ib->obj);
+ }
+}
+
+
+/**
+ * Check that element 'j' of the array has reasonable data.
+ * Map VBO if needed.
+ */
+static void
+check_array_data(GLcontext *ctx, struct gl_client_array *array,
+ GLuint attrib, GLuint j)
+{
+ if (array->Enabled) {
+ const void *data = array->Ptr;
+ if (_mesa_is_bufferobj(array->BufferObj)) {
+ if (!array->BufferObj->Pointer) {
+ /* need to map now */
+ array->BufferObj->Pointer = ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ array->BufferObj);
+ }
+ data = ADD_POINTERS(data, array->BufferObj->Pointer);
+ }
+ switch (array->Type) {
+ case GL_FLOAT:
+ {
+ GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
+ GLuint k;
+ for (k = 0; k < array->Size; k++) {
+ if (IS_INF_OR_NAN(f[k]) ||
+ f[k] >= 1.0e20 || f[k] <= -1.0e10) {
+ _mesa_printf("Bad array data:\n");
+ _mesa_printf(" Element[%u].%u = %f\n", j, k, f[k]);
+ _mesa_printf(" Array %u at %p\n", attrib, (void* ) array);
+ _mesa_printf(" Type 0x%x, Size %d, Stride %d\n",
+ array->Type, array->Size, array->Stride);
+ _mesa_printf(" Address/offset %p in Buffer Object %u\n",
+ array->Ptr, array->BufferObj->Name);
+ f[k] = 1.0; /* XXX replace the bad value! */
+ }
+ //assert(!IS_INF_OR_NAN(f[k]));
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+
+/**
+ * Unmap the buffer object referenced by given array, if mapped.
+ */
+static void
+unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array)
+{
+ if (array->Enabled &&
+ _mesa_is_bufferobj(array->BufferObj) &&
+ _mesa_bufferobj_mapped(array->BufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ array->BufferObj);
+ }
+}
+
+
+/**
+ * Examine the array's data for NaNs, etc.
+ */
+static void
+check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType,
+ const void *elements)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ const void *elemMap;
+ GLint i, k;
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ elemMap = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ elements = ADD_POINTERS(elements, elemMap);
+ }
+
+ for (i = 0; i < count; i++) {
+ GLuint j;
+
+ /* j = element[i] */
+ switch (elemType) {
+ case GL_UNSIGNED_BYTE:
+ j = ((const GLubyte *) elements)[i];
+ break;
+ case GL_UNSIGNED_SHORT:
+ j = ((const GLushort *) elements)[i];
+ break;
+ case GL_UNSIGNED_INT:
+ j = ((const GLuint *) elements)[i];
+ break;
+ default:
+ assert(0);
+ }
+
+ /* check element j of each enabled array */
+ check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
+ check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
+ check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
+ check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ check_array_data(ctx, &arrayObj->VertexAttrib[k], VERT_ATTRIB_GENERIC0 + k, j);
+ }
+ }
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+ }
+
+ unmap_array_buffer(ctx, &arrayObj->Vertex);
+ unmap_array_buffer(ctx, &arrayObj->Normal);
+ unmap_array_buffer(ctx, &arrayObj->Color);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
+ }
+}
+
+
+/**
+ * Check array data, looking for NaNs, etc.
+ */
+static void
+check_draw_arrays_data(GLcontext *ctx, GLint start, GLsizei count)
+{
+ /* TO DO */
+}
+
+
+/**
+ * Print info/data for glDrawArrays().
+ */
+static void
+print_draw_arrays(GLcontext *ctx, struct vbo_exec_context *exec,
+ GLenum mode, GLint start, GLsizei count)
+{
+ int i;
+
+ _mesa_printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
+ mode, start, count);
+
+ for (i = 0; i < 32; i++) {
+ GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
+ GLint stride = exec->array.inputs[i]->Stride;
+ _mesa_printf("attr %2d: size %d stride %d enabled %d "
+ "ptr %p Bufobj %u\n",
+ i,
+ exec->array.inputs[i]->Size,
+ stride,
+ /*exec->array.inputs[i]->Enabled,*/
+ exec->array.legacy_array[i]->Enabled,
+ exec->array.inputs[i]->Ptr,
+ bufName);
+
+ if (bufName) {
+ struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
+ GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY_ARB, buf);
+ int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
+ float *f = (float *) (p + offset);
+ int *k = (int *) f;
+ int i;
+ int n = (count * stride) / 4;
+ if (n > 32)
+ n = 32;
+ _mesa_printf(" Data at offset %d:\n", offset);
+ for (i = 0; i < n; i++) {
+ _mesa_printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
+ }
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
+ }
+ }
+}
+
+
+/**
+ * Just translate the arrayobj into a sane layout.
+ */
+static void
+bind_array_obj(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i;
+
+ /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
+ * rather than as individual named arrays. Then this function can
+ * go away.
+ */
+ exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
+ exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
+ exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
+ exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
+ exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
+ if (arrayObj->PointSize.Enabled) {
+ /* this aliases COLOR_INDEX */
+ exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
+ }
+ exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
+
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
+ exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
+
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ assert(i < Elements(exec->array.generic_array));
+ exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
+ }
+
+ exec->array.array_obj = arrayObj->Name;
+}
+
+
+static void
+recalculate_input_bindings(GLcontext *ctx)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ const struct gl_client_array **inputs = &exec->array.inputs[0];
+ GLbitfield const_inputs = 0x0;
+ GLuint i;
+
+ exec->array.program_mode = get_program_mode(ctx);
+ exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
+
+ switch (exec->array.program_mode) {
+ case VP_NONE:
+ /* When no vertex program is active (or the vertex program is generated
+ * from fixed-function state). We put the material values into the
+ * generic slots. This is the only situation where material values
+ * are available as per-vertex attributes.
+ */
+ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ for (i = 0; i < MAT_ATTRIB_MAX; i++) {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
+ /* Could use just about anything, just to fill in the empty
+ * slots:
+ */
+ for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+ break;
+
+ case VP_NV:
+ /* NV_vertex_program - attribute arrays alias and override
+ * conventional, legacy arrays. No materials, and the generic
+ * slots are vacant.
+ */
+ for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.generic_array[i]->Enabled)
+ inputs[i] = exec->array.generic_array[i];
+ else if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ /* Could use just about anything, just to fill in the empty
+ * slots:
+ */
+ for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
+ inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
+ const_inputs |= 1 << i;
+ }
+ break;
+
+ case VP_ARB:
+ /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
+ * attribute array aliases and overrides the legacy position array.
+ *
+ * Otherwise, legacy attributes available in the legacy slots,
+ * generic attributes in the generic slots and materials are not
+ * available as per-vertex attributes.
+ */
+ if (exec->array.generic_array[0]->Enabled)
+ inputs[0] = exec->array.generic_array[0];
+ else if (exec->array.legacy_array[0]->Enabled)
+ inputs[0] = exec->array.legacy_array[0];
+ else {
+ inputs[0] = &vbo->legacy_currval[0];
+ const_inputs |= 1 << 0;
+ }
+
+ for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
+ if (exec->array.legacy_array[i]->Enabled)
+ inputs[i] = exec->array.legacy_array[i];
+ else {
+ inputs[i] = &vbo->legacy_currval[i];
+ const_inputs |= 1 << i;
+ }
+ }
+
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
+ if (exec->array.generic_array[i]->Enabled)
+ inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
+ else {
+ inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
+ const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
+ }
+
+ }
+ break;
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, ~const_inputs );
+}
+
+
+static void
+bind_arrays(GLcontext *ctx)
+{
+#if 0
+ if (ctx->Array.ArrayObj.Name != exec->array.array_obj) {
+ bind_array_obj(ctx);
+ recalculate_input_bindings(ctx);
+ }
+ else if (exec->array.program_mode != get_program_mode(ctx) ||
+ exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) {
+
+ recalculate_input_bindings(ctx);
+ }
+#else
+ bind_array_obj(ctx);
+ recalculate_input_bindings(ctx);
+#endif
+}
+
+
+
+/***********************************************************************
+ * API functions.
+ */
+
+static void GLAPIENTRY
+vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_prim prim[1];
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
+ return;
+ }
+
+#if 0
+ check_draw_arrays_data(ctx, start, count);
+#else
+ (void) check_draw_arrays_data;
+#endif
+
+ bind_arrays( ctx );
+
+ /* Again... because we may have changed the bitmask of per-vertex varying
+ * attributes. If we regenerate the fixed-function vertex program now
+ * we may be able to prune down the number of vertex attributes which we
+ * need in the shader.
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = start;
+ prim[0].count = count;
+ prim[0].indexed = 0;
+
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
+ GL_TRUE, start, start + count - 1 );
+
+#if 0
+ print_draw_arrays(ctx, exec, mode, start, count);
+#else
+ (void) print_draw_arrays;
+#endif
+}
+
+
+/**
+ * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
+ */
+static void
+dump_element_buffer(GLcontext *ctx, GLenum type)
+{
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ const GLubyte *us = (const GLubyte *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
+ _mesa_printf("%02x ", us[i]);
+ if (i % 32 == 31)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ const GLushort *us = (const GLushort *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
+ _mesa_printf("%04x ", us[i]);
+ if (i % 16 == 15)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ const GLuint *us = (const GLuint *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
+ _mesa_printf("%08x ", us[i]);
+ if (i % 8 == 7)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ default:
+ ;
+ }
+
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+}
+
+/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
+static void
+vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
+ GLboolean index_bounds_valid,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim prim[1];
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ bind_arrays( ctx );
+
+ ib.count = count;
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = indices;
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0;
+ prim[0].count = count;
+ prim[0].indexed = 1;
+
+ /* Need to give special consideration to rendering a range of
+ * indices starting somewhere above zero. Typically the
+ * application is issuing multiple DrawRangeElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO (or locked as with
+ * CVA), the OpenGL semantics imply that we need to re-read or
+ * re-upload the vertex data on each draw call.
+ *
+ * In the case of hardware tnl, we want to avoid starting the
+ * upload at zero, as it will mean every draw call uploads an
+ * increasing amount of not-used vertex data. Worse - in the
+ * software tnl module, all those vertices might be transformed and
+ * lit but never rendered.
+ *
+ * If we just upload or transform the vertices in start..end,
+ * however, the indices will be incorrect.
+ *
+ * At this level, we don't know exactly what the requirements of
+ * the backend are going to be, though it will likely boil down to
+ * either:
+ *
+ * 1) Do nothing, everything is in a VBO and is processed once
+ * only.
+ *
+ * 2) Adjust the indices and vertex arrays so that start becomes
+ * zero.
+ *
+ * Rather than doing anything here, I'll provide a helper function
+ * for the latter case elsewhere.
+ */
+
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
+ index_bounds_valid, start, end );
+}
+
+static void GLAPIENTRY
+vbo_exec_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type, const GLvoid *indices)
+{
+ static GLuint warnCount = 0;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
+ type, indices ))
+ return;
+
+ if (end >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ warnCount++;
+
+ if (warnCount < 10) {
+ _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
+ "type 0x%x, indices=%p)\n"
+ "\tend is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)\n"
+ "\tThis should probably be fixed in the application.",
+ start, end, count, type, indices,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ ctx->Array.ElementArrayBufferObj->Size);
+ }
+
+ if (0)
+ dump_element_buffer(ctx, type);
+
+ if (0)
+ _mesa_print_arrays(ctx);
+
+#ifdef DEBUG
+ /* 'end' was out of bounds, but now let's check the actual array
+ * indexes to see if any of them are out of bounds. If so, warn
+ * and skip the draw to avoid potential segfault, etc.
+ */
+ {
+ GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
+ ctx->Array.ElementArrayBufferObj);
+ if (max >= ctx->Array.ArrayObj->_MaxElement) {
+ if (warnCount < 10) {
+ _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
+ "count %d, type 0x%x, indices=%p)\n"
+ "\tindex=%u is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)\n"
+ "\tSkipping the glDrawRangeElements() call",
+ start, end, count, type, indices, max,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ ctx->Array.ElementArrayBufferObj->Size);
+ }
+ return;
+ }
+ /* XXX we could also find the min index and compare to 'start'
+ * to see if start is correct. But it's more likely to get the
+ * upper bound wrong.
+ */
+ }
+#endif
+ }
+ else if (0) {
+ _mesa_printf("glDraw[Range]Elements"
+ "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
+ start, end, type, count,
+ ctx->Array.ElementArrayBufferObj->Name);
+ }
+
+#if 0
+ check_draw_elements_data(ctx, count, type, indices);
+#else
+ (void) check_draw_elements_data;
+#endif
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
+ count, type, indices);
+}
+
+
+static void GLAPIENTRY
+vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ return;
+
+ vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
+ count, type, indices);
+}
+
+/* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements */
+static void
+vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim *prim;
+ unsigned int index_type_size = 0;
+ uintptr_t min_index_ptr, max_index_ptr;
+ GLboolean fallback = GL_FALSE;
+ int i;
+
+ if (primcount == 0)
+ return;
+
+ FLUSH_CURRENT( ctx, 0 );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ prim = _mesa_calloc(primcount * sizeof(*prim));
+ if (prim == NULL) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
+ return;
+ }
+
+ /* Decide if we can do this all as one set of primitives sharing the
+ * same index buffer, or if we have to reset the index pointer per primitive.
+ */
+ bind_arrays( ctx );
+
+ switch (type) {
+ case GL_UNSIGNED_INT:
+ index_type_size = 4;
+ break;
+ case GL_UNSIGNED_SHORT:
+ index_type_size = 2;
+ break;
+ case GL_UNSIGNED_BYTE:
+ index_type_size = 1;
+ break;
+ default:
+ assert(0);
+ }
+
+ min_index_ptr = (uintptr_t)indices[0];
+ max_index_ptr = 0;
+ for (i = 0; i < primcount; i++) {
+ min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
+ max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
+ index_type_size * count[i]);
+ }
+
+ /* Check if we can handle this thing as a bunch of index offsets from the
+ * same index pointer. If we can't, then we have to fall back to doing
+ * a draw_prims per primitive.
+ */
+ if (index_type_size != 1) {
+ for (i = 0; i < primcount; i++) {
+ if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
+ fallback = GL_TRUE;
+ break;
+ }
+ }
+ }
+
+ /* If the index buffer isn't in a VBO, then treating the application's
+ * subranges of the index buffer as one large index buffer may lead to
+ * us reading unmapped memory.
+ */
+ if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+ fallback = GL_TRUE;
+
+ if (!fallback) {
+ ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = (void *)min_index_ptr;
+
+ for (i = 0; i < primcount; i++) {
+ prim[i].begin = (i == 0);
+ prim[i].end = (i == primcount - 1);
+ prim[i].weak = 0;
+ prim[i].pad = 0;
+ prim[i].mode = mode;
+ prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
+ prim[i].count = count[i];
+ prim[i].indexed = 1;
+ }
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
+ GL_FALSE, ~0, ~0);
+ } else {
+ for (i = 0; i < primcount; i++) {
+ ib.count = count[i];
+ ib.type = type;
+ ib.obj = ctx->Array.ElementArrayBufferObj;
+ ib.ptr = indices[i];
+
+
+ prim[0].begin = 1;
+ prim[0].end = 1;
+ prim[0].weak = 0;
+ prim[0].pad = 0;
+ prim[0].mode = mode;
+ prim[0].start = 0;
+ prim[0].count = count[i];
+ prim[0].indexed = 1;
+ }
+
+ vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
+ GL_FALSE, ~0, ~0);
+ }
+ _mesa_free(prim);
+}
+
+static void GLAPIENTRY
+vbo_exec_MultiDrawElements(GLenum mode,
+ const GLsizei *count, GLenum type,
+ const GLvoid **indices,
+ GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ for (i = 0; i < primcount; i++) {
+ if (!_mesa_validate_DrawElements( ctx, mode, count[i], type, indices[i] ))
+ return;
+ }
+
+ vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount);
+}
+
+
+
+/***********************************************************************
+ * Initialization
+ */
+
+void
+vbo_exec_array_init( struct vbo_exec_context *exec )
+{
+#if 1
+ exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
+ exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
+ exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
+ exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
+#else
+ exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays;
+ exec->vtxfmt.DrawElements = _mesa_noop_DrawElements;
+ exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements;
+ exec->vtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+#endif
+}
+
+
+void
+vbo_exec_array_destroy( struct vbo_exec_context *exec )
+{
+ /* nothing to do */
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ vbo_exec_DrawArrays(mode, first, count);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ vbo_exec_DrawElements(mode, count, type, indices);
+}
+
+
+/* This API entrypoint is not ordinarily used */
+void GLAPIENTRY
+_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices)
+{
+ vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
+}
+
+/* GL_EXT_multi_draw_arrays */
+void GLAPIENTRY
+_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
+ const GLvoid **indices, GLsizei primcount)
+{
+ vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c
new file mode 100644
index 000000000..0c258c535
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c
@@ -0,0 +1,413 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/state.h"
+#include "main/macros.h"
+
+#include "vbo_context.h"
+
+
+static void
+vbo_exec_debug_verts( struct vbo_exec_context *exec )
+{
+ GLuint count = exec->vtx.vert_count;
+ GLuint i;
+
+ _mesa_printf("%s: %u vertices %d primitives, %d vertsize\n",
+ __FUNCTION__,
+ count,
+ exec->vtx.prim_count,
+ exec->vtx.vertex_size);
+
+ for (i = 0 ; i < exec->vtx.prim_count ; i++) {
+ struct _mesa_prim *prim = &exec->vtx.prim[i];
+ _mesa_printf(" prim %d: %s%s %d..%d %s %s\n",
+ i,
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->weak ? " (weak)" : "",
+ prim->start,
+ prim->start + prim->count,
+ prim->begin ? "BEGIN" : "(wrap)",
+ prim->end ? "END" : "(wrap)");
+ }
+}
+
+
+/*
+ * NOTE: Need to have calculated primitives by this point -- do it on the fly.
+ * NOTE: Old 'parity' issue is gone.
+ */
+static GLuint
+vbo_copy_vertices( struct vbo_exec_context *exec )
+{
+ GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
+ GLuint ovf, i;
+ GLuint sz = exec->vtx.vertex_size;
+ GLfloat *dst = exec->vtx.copied.buffer;
+ const GLfloat *src = (exec->vtx.buffer_map +
+ exec->vtx.prim[exec->vtx.prim_count-1].start *
+ exec->vtx.vertex_size);
+
+
+ switch (exec->ctx->Driver.CurrentExecPrimitive) {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_TRIANGLES:
+ ovf = nr%3;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_QUADS:
+ ovf = nr&3;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0) {
+ return 0;
+ }
+ else {
+ _mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
+ return 1;
+ }
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0) {
+ return 0;
+ }
+ else if (nr == 1) {
+ _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
+ return 1;
+ }
+ else {
+ _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
+ _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ /* no parity issue, but need to make sure the tri is not drawn twice */
+ if (nr & 1) {
+ exec->vtx.prim[exec->vtx.prim_count-1].count--;
+ }
+ /* fallthrough */
+ case GL_QUAD_STRIP:
+ switch (nr) {
+ case 0:
+ ovf = 0;
+ break;
+ case 1:
+ ovf = 1;
+ break;
+ default:
+ ovf = 2 + (nr & 1);
+ break;
+ }
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
+ return i;
+ case PRIM_OUTSIDE_BEGIN_END:
+ return 0;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+
+/* TODO: populate these as the vertex is defined:
+ */
+static void
+vbo_exec_bind_arrays( GLcontext *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_exec_context *exec = &vbo->exec;
+ struct gl_client_array *arrays = exec->vtx.arrays;
+ const GLuint count = exec->vtx.vert_count;
+ const GLubyte *data = (GLubyte *) exec->vtx.buffer_map;
+ const GLuint *map;
+ GLuint attr;
+ GLbitfield varying_inputs = 0x0;
+
+ /* Install the default (ie Current) attributes first, then overlay
+ * all active ones.
+ */
+ switch (get_program_mode(exec->ctx)) {
+ case VP_NONE:
+ for (attr = 0; attr < 16; attr++) {
+ exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+ }
+ for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
+ exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr];
+ }
+ map = vbo->map_vp_none;
+ break;
+ case VP_NV:
+ case VP_ARB:
+ /* The aliasing of attributes for NV vertex programs has already
+ * occurred. NV vertex programs cannot access material values,
+ * nor attributes greater than VERT_ATTRIB_TEX7.
+ */
+ for (attr = 0; attr < 16; attr++) {
+ exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+ exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
+ }
+ map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ exec->vtx.inputs[16] = exec->vtx.inputs[0];
+ exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
+ exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
+ exec->vtx.attrsz[0] = 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Make all active attributes (including edgeflag) available as
+ * arrays of floats.
+ */
+ for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) {
+ const GLuint src = map[attr];
+
+ if (exec->vtx.attrsz[src]) {
+ /* override the default array set above */
+ exec->vtx.inputs[attr] = &arrays[attr];
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ /* a real buffer obj: Ptr is an offset, not a pointer*/
+ GLsizeiptr offset;
+ assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */
+ offset = (GLbyte *) data -
+ (GLbyte *) exec->vtx.bufferobj->Pointer +
+ exec->vtx.bufferobj->Offset;
+ assert(offset >= 0);
+ arrays[attr].Ptr = (void *) offset;
+ }
+ else {
+ /* Ptr into ordinary app memory */
+ arrays[attr].Ptr = (void *) data;
+ }
+ arrays[attr].Size = exec->vtx.attrsz[src];
+ arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
+ arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
+ arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
+ arrays[attr].Enabled = 1;
+ _mesa_reference_buffer_object(ctx,
+ &arrays[attr].BufferObj,
+ exec->vtx.bufferobj);
+ arrays[attr]._MaxElement = count; /* ??? */
+
+ data += exec->vtx.attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1 << attr;
+ }
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
+}
+
+
+static void
+vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
+{
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ GLcontext *ctx = exec->ctx;
+
+ if (ctx->Driver.FlushMappedBufferRange) {
+ GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
+ GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
+
+ if (length)
+ ctx->Driver.FlushMappedBufferRange(ctx, target,
+ offset, length,
+ exec->vtx.bufferobj);
+ }
+
+ exec->vtx.buffer_used += (exec->vtx.buffer_ptr -
+ exec->vtx.buffer_map) * sizeof(float);
+
+ assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE);
+ assert(exec->vtx.buffer_ptr != NULL);
+
+ ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ exec->vtx.max_vert = 0;
+ }
+}
+
+
+void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ const GLenum target = GL_ARRAY_BUFFER_ARB;
+ const GLenum access = GL_READ_WRITE_ARB; /* for MapBuffer */
+ const GLenum accessRange = GL_MAP_WRITE_BIT | /* for MapBufferRange */
+ GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ MESA_MAP_NOWAIT_BIT;
+ const GLenum usage = GL_STREAM_DRAW_ARB;
+
+ if (!_mesa_is_bufferobj(exec->vtx.bufferobj))
+ return;
+
+ if (exec->vtx.buffer_map != NULL) {
+ assert(0);
+ exec->vtx.buffer_map = NULL;
+ exec->vtx.buffer_ptr = NULL;
+ }
+
+ if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
+ ctx->Driver.MapBufferRange) {
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx,
+ target,
+ exec->vtx.buffer_used,
+ (VBO_VERT_BUFFER_SIZE -
+ exec->vtx.buffer_used),
+ accessRange,
+ exec->vtx.bufferobj);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (!exec->vtx.buffer_map) {
+ exec->vtx.buffer_used = 0;
+
+ ctx->Driver.BufferData(ctx, target,
+ VBO_VERT_BUFFER_SIZE,
+ NULL, usage, exec->vtx.bufferobj);
+
+
+ if (ctx->Driver.MapBufferRange)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBufferRange(ctx, target,
+ 0, VBO_VERT_BUFFER_SIZE,
+ accessRange,
+ exec->vtx.bufferobj);
+ if (!exec->vtx.buffer_map)
+ exec->vtx.buffer_map =
+ (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+ assert(exec->vtx.buffer_map);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
+
+ if (0)
+ _mesa_printf("map %d..\n", exec->vtx.buffer_used);
+}
+
+
+
+/**
+ * Execute the buffer and save copied verts.
+ */
+void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
+{
+ if (0)
+ vbo_exec_debug_verts( exec );
+
+ if (exec->vtx.prim_count &&
+ exec->vtx.vert_count) {
+
+ exec->vtx.copied.nr = vbo_copy_vertices( exec );
+
+ if (exec->vtx.copied.nr != exec->vtx.vert_count) {
+ GLcontext *ctx = exec->ctx;
+
+ /* Before the update_state() as this may raise _NEW_ARRAY
+ * from _mesa_set_varying_vp_inputs().
+ */
+ vbo_exec_bind_arrays( ctx );
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
+ vbo_exec_vtx_unmap( exec );
+ }
+
+ if (0)
+ _mesa_printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
+ exec->vtx.vert_count);
+
+ vbo_context(ctx)->draw_prims( ctx,
+ exec->vtx.inputs,
+ exec->vtx.prim,
+ exec->vtx.prim_count,
+ NULL,
+ GL_TRUE,
+ 0,
+ exec->vtx.vert_count - 1);
+
+ /* If using a real VBO, get new storage -- unless asked not to.
+ */
+ if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
+ vbo_exec_vtx_map( exec );
+ }
+ }
+ }
+
+ /* May have to unmap explicitly if we didn't draw:
+ */
+ if (unmap &&
+ _mesa_is_bufferobj(exec->vtx.bufferobj) &&
+ exec->vtx.buffer_map) {
+ vbo_exec_vtx_unmap( exec );
+ }
+
+
+ if (unmap || exec->vtx.vertex_size == 0)
+ exec->vtx.max_vert = 0;
+ else
+ exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
+ (exec->vtx.vertex_size * sizeof(GLfloat)));
+
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ exec->vtx.prim_count = 0;
+ exec->vtx.vert_count = 0;
+}
diff --git a/mesalib/src/mesa/vbo/vbo_exec_eval.c b/mesalib/src/mesa/vbo/vbo_exec_eval.c
new file mode 100644
index 000000000..0c691b3a5
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_exec_eval.c
@@ -0,0 +1,254 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "math/m_eval.h"
+#include "glapi/dispatch.h"
+#include "vbo_exec.h"
+
+
+static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr )
+{
+ exec->eval.map1[attr].map = NULL;
+}
+
+static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr )
+{
+ exec->eval.map2[attr].map = NULL;
+}
+
+static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
+ struct gl_1d_map *map )
+{
+ if (!exec->eval.map1[attr].map) {
+ exec->eval.map1[attr].map = map;
+ exec->eval.map1[attr].sz = dim;
+ }
+}
+
+static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
+ struct gl_2d_map *map )
+{
+ if (!exec->eval.map2[attr].map) {
+ exec->eval.map2[attr].map = map;
+ exec->eval.map2[attr].sz = dim;
+ }
+}
+
+void vbo_exec_eval_update( struct vbo_exec_context *exec )
+{
+ GLcontext *ctx = exec->ctx;
+ GLuint attr;
+
+ /* Vertex program maps have priority over conventional attribs */
+
+ for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) {
+ clear_active_eval1( exec, attr );
+ clear_active_eval2( exec, attr );
+ }
+
+ /* _NEW_PROGRAM */
+ if (ctx->VertexProgram._Enabled) {
+ for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) {
+ /* _NEW_EVAL */
+ if (ctx->Eval.Map1Attrib[attr])
+ set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] );
+
+ if (ctx->Eval.Map2Attrib[attr])
+ set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] );
+ }
+ }
+
+ if (ctx->Eval.Map1Color4)
+ set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 );
+
+ if (ctx->Eval.Map2Color4)
+ set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 );
+
+ if (ctx->Eval.Map1TextureCoord4)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 );
+ else if (ctx->Eval.Map1TextureCoord3)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 );
+ else if (ctx->Eval.Map1TextureCoord2)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 );
+ else if (ctx->Eval.Map1TextureCoord1)
+ set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 );
+
+ if (ctx->Eval.Map2TextureCoord4)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 );
+ else if (ctx->Eval.Map2TextureCoord3)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 );
+ else if (ctx->Eval.Map2TextureCoord2)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 );
+ else if (ctx->Eval.Map2TextureCoord1)
+ set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 );
+
+ if (ctx->Eval.Map1Normal)
+ set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal );
+
+ if (ctx->Eval.Map2Normal)
+ set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal );
+
+ if (ctx->Eval.Map1Vertex4)
+ set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 );
+ else if (ctx->Eval.Map1Vertex3)
+ set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 );
+
+ if (ctx->Eval.Map2Vertex4)
+ set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 );
+ else if (ctx->Eval.Map2Vertex3)
+ set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 );
+
+ exec->eval.recalculate_maps = 0;
+}
+
+
+
+void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u)
+{
+ GLuint attr;
+
+ for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
+ struct gl_1d_map *map = exec->eval.map1[attr].map;
+ if (map) {
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat data[4];
+
+ ASSIGN_4V(data, 0, 0, 0, 1);
+
+ _math_horner_bezier_curve(map->Points, data, uu,
+ exec->eval.map1[attr].sz,
+ map->Order);
+
+ COPY_SZ_4V( exec->vtx.attrptr[attr],
+ exec->vtx.attrsz[attr],
+ data );
+ }
+ }
+
+ /** Vertex -- EvalCoord1f is a noop if this map not enabled:
+ **/
+ if (exec->eval.map1[0].map) {
+ struct gl_1d_map *map = exec->eval.map1[0].map;
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vertex[4];
+
+ ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+ _math_horner_bezier_curve(map->Points, vertex, uu,
+ exec->eval.map1[0].sz,
+ map->Order);
+
+ if (exec->eval.map1[0].sz == 4)
+ CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
+ else
+ CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
+ }
+}
+
+
+
+void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
+ GLfloat u, GLfloat v )
+{
+ GLuint attr;
+
+ for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
+ struct gl_2d_map *map = exec->eval.map2[attr].map;
+ if (map) {
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vv = (v - map->v1) * map->dv;
+ GLfloat data[4];
+
+ ASSIGN_4V(data, 0, 0, 0, 1);
+
+ _math_horner_bezier_surf(map->Points,
+ data,
+ uu, vv,
+ exec->eval.map2[attr].sz,
+ map->Uorder, map->Vorder);
+
+ COPY_SZ_4V( exec->vtx.attrptr[attr],
+ exec->vtx.attrsz[attr],
+ data );
+ }
+ }
+
+ /** Vertex -- EvalCoord2f is a noop if this map not enabled:
+ **/
+ if (exec->eval.map2[0].map) {
+ struct gl_2d_map *map = exec->eval.map2[0].map;
+ GLfloat uu = (u - map->u1) * map->du;
+ GLfloat vv = (v - map->v1) * map->dv;
+ GLfloat vertex[4];
+
+ ASSIGN_4V(vertex, 0, 0, 0, 1);
+
+ if (exec->ctx->Eval.AutoNormal) {
+ GLfloat normal[4];
+ GLfloat du[4], dv[4];
+
+ _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv,
+ exec->eval.map2[0].sz,
+ map->Uorder, map->Vorder);
+
+ if (exec->eval.map2[0].sz == 4) {
+ du[0] = du[0]*vertex[3] - du[3]*vertex[0];
+ du[1] = du[1]*vertex[3] - du[3]*vertex[1];
+ du[2] = du[2]*vertex[3] - du[3]*vertex[2];
+
+ dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0];
+ dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1];
+ dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2];
+ }
+
+
+ CROSS3(normal, du, dv);
+ NORMALIZE_3FV(normal);
+ normal[3] = 1.0;
+
+ COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL],
+ exec->vtx.attrsz[VBO_ATTRIB_NORMAL],
+ normal );
+
+ }
+ else {
+ _math_horner_bezier_surf(map->Points, vertex, uu, vv,
+ exec->eval.map2[0].sz,
+ map->Uorder, map->Vorder);
+ }
+
+ if (exec->vtx.attrsz[0] == 4)
+ CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
+ else
+ CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
+ }
+}
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c
new file mode 100644
index 000000000..3bf7ef580
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_rebase.c
@@ -0,0 +1,223 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Helper for drivers which find themselves rendering a range of
+ * indices starting somewhere above zero. Typically the application
+ * is issuing multiple DrawArrays() or DrawElements() to draw
+ * successive primitives layed out linearly in the vertex arrays.
+ * Unless the vertex arrays are all in a VBO, the OpenGL semantics
+ * imply that we need to re-upload the vertex data on each draw call.
+ * In that case, we want to avoid starting the upload at zero, as it
+ * will mean every draw call uploads an increasing amount of not-used
+ * vertex data. Worse - in the software tnl module, all those
+ * vertices will be transformed and lit.
+ *
+ * If we just upload the new data, however, the indices will be
+ * incorrect as we tend to upload each set of vertex data to a new
+ * region.
+ *
+ * This file provides a helper to adjust the arrays, primitives and
+ * indices of a draw call so that it can be re-issued with a min_index
+ * of zero.
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "vbo.h"
+
+
+#define REBASE(TYPE) \
+static void *rebase_##TYPE( const void *ptr, \
+ GLuint count, \
+ TYPE min_index ) \
+{ \
+ const TYPE *in = (TYPE *)ptr; \
+ TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \
+ GLuint i; \
+ \
+ for (i = 0; i < count; i++) \
+ tmp_indices[i] = in[i] - min_index; \
+ \
+ return (void *)tmp_indices; \
+}
+
+
+REBASE(GLuint)
+REBASE(GLushort)
+REBASE(GLubyte)
+
+GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
+{
+ GLuint i;
+
+ for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ if (arrays[i]->StrideB &&
+ arrays[i]->BufferObj->Name == 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+/* Adjust primitives, indices and vertex definitions so that min_index
+ * becomes zero. There are lots of reasons for wanting to do this, eg:
+ *
+ * Software tnl:
+ * - any time min_index != 0, otherwise unused vertices lower than
+ * min_index will be transformed.
+ *
+ * Hardware tnl:
+ * - if ib != NULL and min_index != 0, otherwise vertices lower than
+ * min_index will be uploaded. Requires adjusting index values.
+ *
+ * - if ib == NULL and min_index != 0, just for convenience so this doesn't
+ * have to be handled within the driver.
+ *
+ * Hardware tnl with VBO support:
+ * - as above, but only when vertices are not (all?) in VBO's.
+ * - can't save time by trying to upload half a vbo - typically it is
+ * all or nothing.
+ */
+void vbo_rebase_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw )
+{
+ struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
+ const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
+
+ struct _mesa_index_buffer tmp_ib;
+ struct _mesa_prim *tmp_prims = NULL;
+ void *tmp_indices = NULL;
+ GLuint i;
+
+ assert(min_index != 0);
+
+ if (0)
+ _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+
+ if (ib) {
+ /* Unfortunately need to adjust each index individually.
+ */
+ GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
+ void *ptr;
+
+ if (map_ib)
+ ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ ib->obj);
+
+
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
+
+ /* Some users might prefer it if we translated elements to
+ * GLuints here. Others wouldn't...
+ */
+ switch (ib->type) {
+ case GL_UNSIGNED_INT:
+ tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_SHORT:
+ tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
+ break;
+ case GL_UNSIGNED_BYTE:
+ tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
+ break;
+ }
+
+ if (map_ib)
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ ib->obj);
+
+ tmp_ib.obj = ctx->Shared->NullBufferObj;
+ tmp_ib.ptr = tmp_indices;
+ tmp_ib.count = ib->count;
+ tmp_ib.type = ib->type;
+
+ ib = &tmp_ib;
+ }
+ else {
+ /* Otherwise the primitives need adjustment.
+ */
+ tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims);
+
+ for (i = 0; i < nr_prims; i++) {
+ /* If this fails, it could indicate an application error:
+ */
+ assert(prim[i].start >= min_index);
+
+ tmp_prims[i] = prim[i];
+ tmp_prims[i].start -= min_index;
+ }
+
+ prim = tmp_prims;
+ }
+
+ /* Just need to adjust the pointer values on each incoming array.
+ * This works for VBO and non-vbo rendering and shouldn't pesimize
+ * VBO-based upload schemes. However this may still not be a fast
+ * path for hardware tnl for VBO based rendering as most machines
+ * will be happier if you just specify a starting vertex value in
+ * each primitive.
+ *
+ * For drivers with hardware tnl, you only want to do this if you
+ * are forced to, eg non-VBO indexed rendering with start != 0.
+ */
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ tmp_arrays[i] = *arrays[i];
+ tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
+ tmp_array_pointers[i] = &tmp_arrays[i];
+ }
+
+ /* Re-issue the draw call.
+ */
+ draw( ctx,
+ tmp_array_pointers,
+ prim,
+ nr_prims,
+ ib,
+ GL_TRUE,
+ 0,
+ max_index - min_index );
+
+ if (tmp_indices)
+ _mesa_free(tmp_indices);
+
+ if (tmp_prims)
+ _mesa_free(tmp_prims);
+}
+
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_save.c b/mesalib/src/mesa/vbo/vbo_save.c
new file mode 100644
index 000000000..9757c3d9f
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_save.c
@@ -0,0 +1,110 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/mtypes.h"
+#include "main/bufferobj.h"
+#include "main/dlist.h"
+#include "main/vtxfmt.h"
+#include "main/imports.h"
+
+#include "vbo_context.h"
+
+
+
+static void vbo_save_callback_init( GLcontext *ctx )
+{
+ ctx->Driver.NewList = vbo_save_NewList;
+ ctx->Driver.EndList = vbo_save_EndList;
+ ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices;
+ ctx->Driver.BeginCallList = vbo_save_BeginCallList;
+ ctx->Driver.EndCallList = vbo_save_EndCallList;
+ ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
+}
+
+
+
+void vbo_save_init( GLcontext *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_save_context *save = &vbo->save;
+
+ save->ctx = ctx;
+
+ vbo_save_api_init( save );
+ vbo_save_callback_init(ctx);
+
+ {
+ struct gl_client_array *arrays = save->arrays;
+ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
+ memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+ }
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
+}
+
+
+void vbo_save_destroy( GLcontext *ctx )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_save_context *save = &vbo->save;
+ GLuint i;
+
+ if (save->prim_store) {
+ if ( --save->prim_store->refcount == 0 ) {
+ FREE( save->prim_store );
+ save->prim_store = NULL;
+ }
+ if ( --save->vertex_store->refcount == 0 ) {
+ _mesa_reference_buffer_object(ctx,
+ &save->vertex_store->bufferobj, NULL);
+ FREE( save->vertex_store );
+ save->vertex_store = NULL;
+ }
+ }
+
+ for (i = 0; i < VBO_ATTRIB_MAX; i++) {
+ _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL);
+ }
+}
+
+
+
+
+/* Note that this can occur during the playback of a display list:
+ */
+void vbo_save_fallback( GLcontext *ctx, GLboolean fallback )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (fallback)
+ save->replay_flags |= VBO_SAVE_FALLBACK;
+ else
+ save->replay_flags &= ~VBO_SAVE_FALLBACK;
+}
+
+
diff --git a/mesalib/src/mesa/vbo/vbo_save.h b/mesalib/src/mesa/vbo/vbo_save.h
new file mode 100644
index 000000000..86bbd24f7
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_save.h
@@ -0,0 +1,184 @@
+/**************************************************************************
+
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef VBO_SAVE_H
+#define VBO_SAVE_H
+
+#include "main/mtypes.h"
+#include "vbo.h"
+#include "vbo_attrib.h"
+
+
+struct vbo_save_copied_vtx {
+ GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
+ GLuint nr;
+};
+
+
+/* For display lists, this structure holds a run of vertices of the
+ * same format, and a strictly well-formed set of begin/end pairs,
+ * starting on the first vertex and ending at the last. Vertex
+ * copying on buffer breaks is precomputed according to these
+ * primitives, though there are situations where the copying will need
+ * correction at execute-time, perhaps by replaying the list as
+ * immediate mode commands.
+ *
+ * On executing this list, the 'current' values may be updated with
+ * the values of the final vertex, and often no fixup of the start of
+ * the vertex list is required.
+ *
+ * Eval and other commands that don't fit into these vertex lists are
+ * compiled using the fallback opcode mechanism provided by dlist.c.
+ */
+struct vbo_save_vertex_list {
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLuint vertex_size;
+
+ /* Copy of the final vertex from node->vertex_store->bufferobj.
+ * Keep this in regular (non-VBO) memory to avoid repeated
+ * map/unmap of the VBO when updating GL current data.
+ */
+ GLfloat *current_data;
+ GLuint current_size;
+
+ GLuint buffer_offset;
+ GLuint count;
+ GLuint wrap_count; /* number of copied vertices at start */
+ GLboolean dangling_attr_ref; /* current attr implicitly referenced
+ outside the list */
+
+ struct _mesa_prim *prim;
+ GLuint prim_count;
+
+ struct vbo_save_vertex_store *vertex_store;
+ struct vbo_save_primitive_store *prim_store;
+};
+
+/* These buffers should be a reasonable size to support upload to
+ * hardware. Current vbo implementation will re-upload on any
+ * changes, so don't make too big or apps which dynamically create
+ * dlists and use only a few times will suffer.
+ *
+ * Consider stategy of uploading regions from the VBO on demand in the
+ * case of dynamic vbos. Then make the dlist code signal that
+ * likelyhood as it occurs. No reason we couldn't change usage
+ * internally even though this probably isn't allowed for client VBOs?
+ */
+#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */
+#define VBO_SAVE_PRIM_SIZE 128
+#define VBO_SAVE_PRIM_WEAK 0x40
+
+#define VBO_SAVE_FALLBACK 0x10000000
+
+/* Storage to be shared among several vertex_lists.
+ */
+struct vbo_save_vertex_store {
+ struct gl_buffer_object *bufferobj;
+ GLfloat *buffer;
+ GLuint used;
+ GLuint refcount;
+};
+
+struct vbo_save_primitive_store {
+ struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE];
+ GLuint used;
+ GLuint refcount;
+};
+
+
+struct vbo_save_context {
+ GLcontext *ctx;
+ GLvertexformat vtxfmt;
+ struct gl_client_array arrays[VBO_ATTRIB_MAX];
+ const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
+
+ GLubyte attrsz[VBO_ATTRIB_MAX];
+ GLubyte active_sz[VBO_ATTRIB_MAX];
+ GLuint vertex_size;
+
+ GLfloat *buffer;
+ GLuint count;
+ GLuint wrap_count;
+ GLuint replay_flags;
+
+ struct _mesa_prim *prim;
+ GLuint prim_count, prim_max;
+
+ struct vbo_save_vertex_store *vertex_store;
+ struct vbo_save_primitive_store *prim_store;
+
+ GLfloat *buffer_ptr; /* cursor, points into buffer */
+ GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
+ GLfloat *attrptr[VBO_ATTRIB_MAX];
+ GLuint vert_count;
+ GLuint max_vert;
+ GLboolean dangling_attr_ref;
+ GLboolean have_materials;
+
+ GLuint opcode_vertex_list;
+
+ struct vbo_save_copied_vtx copied;
+
+ GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */
+ GLubyte *currentsz[VBO_ATTRIB_MAX];
+};
+
+
+void vbo_save_init( GLcontext *ctx );
+void vbo_save_destroy( GLcontext *ctx );
+void vbo_save_fallback( GLcontext *ctx, GLboolean fallback );
+
+/* save_loopback.c:
+ */
+void vbo_loopback_vertex_list( GLcontext *ctx,
+ const GLfloat *buffer,
+ const GLubyte *attrsz,
+ const struct _mesa_prim *prim,
+ GLuint prim_count,
+ GLuint wrap_count,
+ GLuint vertex_size);
+
+/* Callbacks:
+ */
+void vbo_save_EndList( GLcontext *ctx );
+void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode );
+void vbo_save_EndCallList( GLcontext *ctx );
+void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *list );
+void vbo_save_SaveFlushVertices( GLcontext *ctx );
+GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode );
+
+void vbo_save_playback_vertex_list( GLcontext *ctx, void *data );
+
+void vbo_save_api_init( struct vbo_save_context *save );
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
new file mode 100644
index 000000000..1771510d8
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -0,0 +1,1238 @@
+/**************************************************************************
+
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+/* Display list compiler attempts to store lists of vertices with the
+ * same vertex layout. Additionally it attempts to minimize the need
+ * for execute-time fixup of these vertex lists, allowing them to be
+ * cached on hardware.
+ *
+ * There are still some circumstances where this can be thwarted, for
+ * example by building a list that consists of one very long primitive
+ * (eg Begin(Triangles), 1000 vertices, End), and calling that list
+ * from inside a different begin/end object (Begin(Lines), CallList,
+ * End).
+ *
+ * In that case the code will have to replay the list as individual
+ * commands through the Exec dispatch table, or fix up the copied
+ * vertices at execute-time.
+ *
+ * The other case where fixup is required is when a vertex attribute
+ * is introduced in the middle of a primitive. Eg:
+ * Begin(Lines)
+ * TexCoord1f() Vertex2f()
+ * TexCoord1f() Color3f() Vertex2f()
+ * End()
+ *
+ * If the current value of Color isn't known at compile-time, this
+ * primitive will require fixup.
+ *
+ *
+ * The list compiler currently doesn't attempt to compile lists
+ * containing EvalCoord or EvalPoint commands. On encountering one of
+ * these, compilation falls back to opcodes.
+ *
+ * This could be improved to fallback only when a mix of EvalCoord and
+ * Vertex commands are issued within a single primitive.
+ */
+
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/dlist.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/api_noop.h"
+#include "main/api_validate.h"
+#include "main/api_arrayelt.h"
+#include "main/vtxfmt.h"
+#include "glapi/dispatch.h"
+
+#include "vbo_context.h"
+
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
+/* An interesting VBO number/name to help with debugging */
+#define VBO_BUF_ID 12345
+
+
+/*
+ * NOTE: Old 'parity' issue is gone, but copying can still be
+ * wrong-footed on replay.
+ */
+static GLuint _save_copy_vertices( GLcontext *ctx,
+ const struct vbo_save_vertex_list *node,
+ const GLfloat *src_buffer)
+{
+ struct vbo_save_context *save = &vbo_context( ctx )->save;
+ const struct _mesa_prim *prim = &node->prim[node->prim_count-1];
+ GLuint nr = prim->count;
+ GLuint sz = save->vertex_size;
+ const GLfloat *src = src_buffer + prim->start * sz;
+ GLfloat *dst = save->copied.buffer;
+ GLuint ovf, i;
+
+ if (prim->end)
+ return 0;
+
+ switch( prim->mode )
+ {
+ case GL_POINTS:
+ return 0;
+ case GL_LINES:
+ ovf = nr&1;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_TRIANGLES:
+ ovf = nr%3;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_QUADS:
+ ovf = nr&3;
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ case GL_LINE_STRIP:
+ if (nr == 0)
+ return 0;
+ else {
+ _mesa_memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+ return 1;
+ }
+ case GL_LINE_LOOP:
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ if (nr == 0)
+ return 0;
+ else if (nr == 1) {
+ _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) );
+ return 1;
+ } else {
+ _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) );
+ _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
+ return 2;
+ }
+ case GL_TRIANGLE_STRIP:
+ case GL_QUAD_STRIP:
+ switch (nr) {
+ case 0: ovf = 0; break;
+ case 1: ovf = 1; break;
+ default: ovf = 2 + (nr&1); break;
+ }
+ for (i = 0 ; i < ovf ; i++)
+ _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
+ return i;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+
+static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx )
+{
+ struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store);
+
+ /* obj->Name needs to be non-zero, but won't ever be examined more
+ * closely than that. In particular these buffers won't be entered
+ * into the hash and can never be confused with ones visible to the
+ * user. Perhaps there could be a special number for internal
+ * buffers:
+ */
+ vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
+ VBO_BUF_ID,
+ GL_ARRAY_BUFFER_ARB);
+
+ ctx->Driver.BufferData( ctx,
+ GL_ARRAY_BUFFER_ARB,
+ VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
+ NULL,
+ GL_STATIC_DRAW_ARB,
+ vertex_store->bufferobj);
+
+ vertex_store->buffer = NULL;
+ vertex_store->used = 0;
+ vertex_store->refcount = 1;
+
+ return vertex_store;
+}
+
+static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ assert(!vertex_store->buffer);
+
+ if (vertex_store->bufferobj) {
+ _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
+ }
+
+ FREE( vertex_store );
+}
+
+static GLfloat *map_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ assert(vertex_store->bufferobj);
+ assert(!vertex_store->buffer);
+ vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB, /* not used */
+ GL_WRITE_ONLY, /* not used */
+ vertex_store->bufferobj);
+
+ assert(vertex_store->buffer);
+ return vertex_store->buffer + vertex_store->used;
+}
+
+static void unmap_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store )
+{
+ ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj );
+ vertex_store->buffer = NULL;
+}
+
+
+static struct vbo_save_primitive_store *alloc_prim_store( GLcontext *ctx )
+{
+ struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store);
+ (void) ctx;
+ store->used = 0;
+ store->refcount = 1;
+ return store;
+}
+
+static void _save_reset_counters( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ save->prim = save->prim_store->buffer + save->prim_store->used;
+ save->buffer = (save->vertex_store->buffer +
+ save->vertex_store->used);
+
+ assert(save->buffer == save->buffer_ptr);
+
+ if (save->vertex_size)
+ save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
+ save->vertex_size);
+ else
+ save->max_vert = 0;
+
+ save->vert_count = 0;
+ save->prim_count = 0;
+ save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used;
+ save->dangling_attr_ref = 0;
+}
+
+
+/* Insert the active immediate struct onto the display list currently
+ * being built.
+ */
+static void _save_compile_vertex_list( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ struct vbo_save_vertex_list *node;
+
+ /* Allocate space for this structure in the display list currently
+ * being compiled.
+ */
+ node = (struct vbo_save_vertex_list *)
+ _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node));
+
+ if (!node)
+ return;
+
+ /* Duplicate our template, increment refcounts to the storage structs:
+ */
+ _mesa_memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
+ node->vertex_size = save->vertex_size;
+ node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
+ node->count = save->vert_count;
+ node->wrap_count = save->copied.nr;
+ node->dangling_attr_ref = save->dangling_attr_ref;
+ node->prim = save->prim;
+ node->prim_count = save->prim_count;
+ node->vertex_store = save->vertex_store;
+ node->prim_store = save->prim_store;
+
+ node->vertex_store->refcount++;
+ node->prim_store->refcount++;
+
+
+ node->current_size = node->vertex_size - node->attrsz[0];
+ node->current_data = NULL;
+
+ if (node->current_size) {
+ /* If the malloc fails, we just pull the data out of the VBO
+ * later instead.
+ */
+ node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
+ if (node->current_data) {
+ const char *buffer = (const char *)save->vertex_store->buffer;
+ unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
+ unsigned vertex_offset = 0;
+
+ if (node->count)
+ vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
+
+ memcpy( node->current_data,
+ buffer + node->buffer_offset + vertex_offset + attr_offset,
+ node->current_size * sizeof(GLfloat) );
+ }
+ }
+
+
+
+ assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
+ node->count == 0);
+
+ if (save->dangling_attr_ref)
+ ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
+
+ save->vertex_store->used += save->vertex_size * node->count;
+ save->prim_store->used += node->prim_count;
+
+
+ /* Copy duplicated vertices
+ */
+ save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );
+
+
+ /* Deal with GL_COMPILE_AND_EXECUTE:
+ */
+ if (ctx->ExecuteFlag) {
+ struct _glapi_table *dispatch = GET_DISPATCH();
+
+ _glapi_set_dispatch(ctx->Exec);
+
+ vbo_loopback_vertex_list( ctx,
+ (const GLfloat *)((const char *)save->vertex_store->buffer +
+ node->buffer_offset),
+ node->attrsz,
+ node->prim,
+ node->prim_count,
+ node->wrap_count,
+ node->vertex_size);
+
+ _glapi_set_dispatch(dispatch);
+ }
+
+
+ /* Decide whether the storage structs are full, or can be used for
+ * the next vertex lists as well.
+ */
+ if (save->vertex_store->used >
+ VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {
+
+ /* Unmap old store:
+ */
+ unmap_vertex_store( ctx, save->vertex_store );
+
+ /* Release old reference:
+ */
+ save->vertex_store->refcount--;
+ assert(save->vertex_store->refcount != 0);
+ save->vertex_store = NULL;
+
+ /* Allocate and map new store:
+ */
+ save->vertex_store = alloc_vertex_store( ctx );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
+ }
+
+ if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
+ save->prim_store->refcount--;
+ assert(save->prim_store->refcount != 0);
+ save->prim_store = alloc_prim_store( ctx );
+ }
+
+ /* Reset our structures for the next run of vertices:
+ */
+ _save_reset_counters( ctx );
+}
+
+
+/* TODO -- If no new vertices have been stored, don't bother saving
+ * it.
+ */
+static void _save_wrap_buffers( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i = save->prim_count - 1;
+ GLenum mode;
+ GLboolean weak;
+
+ assert(i < (GLint) save->prim_max);
+ assert(i >= 0);
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ mode = save->prim[i].mode;
+ weak = save->prim[i].weak;
+
+ /* store the copied vertices, and allocate a new list.
+ */
+ _save_compile_vertex_list( ctx );
+
+ /* Restart interrupted primitive
+ */
+ save->prim[0].mode = mode;
+ save->prim[0].weak = weak;
+ save->prim[0].begin = 0;
+ save->prim[0].end = 0;
+ save->prim[0].pad = 0;
+ save->prim[0].start = 0;
+ save->prim[0].count = 0;
+ save->prim_count = 1;
+}
+
+
+
+/* Called only when buffers are wrapped as the result of filling the
+ * vertex_store struct.
+ */
+static void _save_wrap_filled_vertex( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLfloat *data = save->copied.buffer;
+ GLuint i;
+
+ /* Emit a glEnd to close off the last vertex list.
+ */
+ _save_wrap_buffers( ctx );
+
+ /* Copy stored stored vertices to start of new list.
+ */
+ assert(save->max_vert - save->vert_count > save->copied.nr);
+
+ for (i = 0 ; i < save->copied.nr ; i++) {
+ _mesa_memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
+ data += save->vertex_size;
+ save->buffer_ptr += save->vertex_size;
+ save->vert_count++;
+ }
+}
+
+
+static void _save_copy_to_current( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (save->attrsz[i]) {
+ save->currentsz[i][0] = save->attrsz[i];
+ COPY_CLEAN_4V(save->current[i],
+ save->attrsz[i],
+ save->attrptr[i]);
+ }
+ }
+}
+
+
+static void _save_copy_from_current( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i;
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ switch (save->attrsz[i]) {
+ case 4: save->attrptr[i][3] = save->current[i][3];
+ case 3: save->attrptr[i][2] = save->current[i][2];
+ case 2: save->attrptr[i][1] = save->current[i][1];
+ case 1: save->attrptr[i][0] = save->current[i][0];
+ case 0: break;
+ }
+ }
+}
+
+
+
+
+/* Flush existing data, set new attrib size, replay copied vertices.
+ */
+static void _save_upgrade_vertex( GLcontext *ctx,
+ GLuint attr,
+ GLuint newsz )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint oldsz;
+ GLuint i;
+ GLfloat *tmp;
+
+ /* Store the current run of vertices, and emit a GL_END. Emit a
+ * BEGIN in the new buffer.
+ */
+ if (save->vert_count)
+ _save_wrap_buffers( ctx );
+ else
+ assert( save->copied.nr == 0 );
+
+ /* Do a COPY_TO_CURRENT to ensure back-copying works for the case
+ * when the attribute already exists in the vertex and is having
+ * its size increased.
+ */
+ _save_copy_to_current( ctx );
+
+ /* Fix up sizes:
+ */
+ oldsz = save->attrsz[attr];
+ save->attrsz[attr] = newsz;
+
+ save->vertex_size += newsz - oldsz;
+ save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
+ save->vertex_size);
+ save->vert_count = 0;
+
+ /* Recalculate all the attrptr[] values:
+ */
+ for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) {
+ if (save->attrsz[i]) {
+ save->attrptr[i] = tmp;
+ tmp += save->attrsz[i];
+ }
+ else
+ save->attrptr[i] = NULL; /* will not be dereferenced. */
+ }
+
+ /* Copy from current to repopulate the vertex with correct values.
+ */
+ _save_copy_from_current( ctx );
+
+ /* Replay stored vertices to translate them to new format here.
+ *
+ * If there are copied vertices and the new (upgraded) attribute
+ * has not been defined before, this list is somewhat degenerate,
+ * and will need fixup at runtime.
+ */
+ if (save->copied.nr)
+ {
+ GLfloat *data = save->copied.buffer;
+ GLfloat *dest = save->buffer;
+ GLuint j;
+
+ /* Need to note this and fix up at runtime (or loopback):
+ */
+ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
+ assert(oldsz == 0);
+ save->dangling_attr_ref = GL_TRUE;
+ }
+
+ for (i = 0 ; i < save->copied.nr ; i++) {
+ for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
+ if (save->attrsz[j]) {
+ if (j == attr) {
+ if (oldsz) {
+ COPY_CLEAN_4V( dest, oldsz, data );
+ data += oldsz;
+ dest += newsz;
+ }
+ else {
+ COPY_SZ_4V( dest, newsz, save->current[attr] );
+ dest += newsz;
+ }
+ }
+ else {
+ GLint sz = save->attrsz[j];
+ COPY_SZ_4V( dest, sz, data );
+ data += sz;
+ dest += sz;
+ }
+ }
+ }
+ }
+
+ save->buffer_ptr = dest;
+ save->vert_count += save->copied.nr;
+ }
+}
+
+static void save_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (sz > save->attrsz[attr]) {
+ /* New size is larger. Need to flush existing vertices and get
+ * an enlarged vertex format.
+ */
+ _save_upgrade_vertex( ctx, attr, sz );
+ }
+ else if (sz < save->active_sz[attr]) {
+ static GLfloat id[4] = { 0, 0, 0, 1 };
+ GLuint i;
+
+ /* New size is equal or smaller - just need to fill in some
+ * zeros.
+ */
+ for (i = sz ; i <= save->attrsz[attr] ; i++)
+ save->attrptr[attr][i-1] = id[i-1];
+ }
+
+ save->active_sz[attr] = sz;
+}
+
+static void _save_reset_vertex( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLuint i;
+
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ save->attrsz[i] = 0;
+ save->active_sz[i] = 0;
+ }
+
+ save->vertex_size = 0;
+}
+
+
+
+#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
+
+
+/* Only one size for each attribute may be active at once. Eg. if
+ * Color3f is installed/active, then Color4f may not be, even if the
+ * vertex actually contains 4 color coordinates. This is because the
+ * 3f version won't otherwise set color[3] to 1.0 -- this is the job
+ * of the chooser function when switching between Color4f and Color3f.
+ */
+#define ATTR( A, N, V0, V1, V2, V3 ) \
+do { \
+ struct vbo_save_context *save = &vbo_context(ctx)->save; \
+ \
+ if (save->active_sz[A] != N) \
+ save_fixup_vertex(ctx, A, N); \
+ \
+ { \
+ GLfloat *dest = save->attrptr[A]; \
+ if (N>0) dest[0] = V0; \
+ if (N>1) dest[1] = V1; \
+ if (N>2) dest[2] = V2; \
+ if (N>3) dest[3] = V3; \
+ } \
+ \
+ if ((A) == 0) { \
+ GLuint i; \
+ \
+ for (i = 0; i < save->vertex_size; i++) \
+ save->buffer_ptr[i] = save->vertex[i]; \
+ \
+ save->buffer_ptr += save->vertex_size; \
+ \
+ if (++save->vert_count >= save->max_vert) \
+ _save_wrap_filled_vertex( ctx ); \
+ } \
+} while (0)
+
+#define TAG(x) _save_##x
+
+#include "vbo_attrib_tmp.h"
+
+
+
+
+/* Cope with EvalCoord/CallList called within a begin/end object:
+ * -- Flush current buffer
+ * -- Fallback to opcodes for the rest of the begin/end object.
+ */
+static void DO_FALLBACK( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (save->vert_count || save->prim_count) {
+ GLint i = save->prim_count - 1;
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ /* Need to replay this display list with loopback,
+ * unfortunately, otherwise this primitive won't be handled
+ * properly:
+ */
+ save->dangling_attr_ref = 1;
+
+ _save_compile_vertex_list( ctx );
+ }
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalCoord1f( u );
+}
+
+static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalCoord1fv( v );
+}
+
+static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalCoord2f( u, v );
+}
+
+static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalCoord2fv( v );
+}
+
+static void GLAPIENTRY _save_EvalPoint1( GLint i )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalPoint1( i );
+}
+
+static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->EvalPoint2( i, j );
+}
+
+static void GLAPIENTRY _save_CallList( GLuint l )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->CallList( l );
+}
+
+static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ DO_FALLBACK(ctx);
+ ctx->Save->CallLists( n, type, v );
+}
+
+
+
+
+/* This begin is hooked into ... Updating of
+ * ctx->Driver.CurrentSavePrimitive is already taken care of.
+ */
+GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ GLuint i = save->prim_count++;
+
+ assert(i < save->prim_max);
+ save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK;
+ save->prim[i].begin = 1;
+ save->prim[i].end = 0;
+ save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0;
+ save->prim[i].pad = 0;
+ save->prim[i].start = save->vert_count;
+ save->prim[i].count = 0;
+
+ _mesa_install_save_vtxfmt( ctx, &save->vtxfmt );
+ ctx->Driver.SaveNeedFlush = 1;
+ return GL_TRUE;
+}
+
+
+
+static void GLAPIENTRY _save_End( void )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i = save->prim_count - 1;
+
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 1;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ if (i == (GLint) save->prim_max - 1) {
+ _save_compile_vertex_list( ctx );
+ assert(save->copied.nr == 0);
+ }
+
+ /* Swap out this vertex format while outside begin/end. Any color,
+ * etc. received between here and the next begin will be compiled
+ * as opcodes.
+ */
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
+
+/* These are all errors as this vtxfmt is only installed inside
+ * begin/end pairs.
+ */
+static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) count; (void) type; (void) indices;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
+}
+
+
+static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
+}
+
+static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) start; (void) count;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
+}
+
+static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) x1; (void) y1; (void) x2; (void) y2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" );
+}
+
+static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) i1; (void) i2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" );
+}
+
+static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
+ GLint j1, GLint j2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ (void) mode; (void) i1; (void) i2; (void) j1; (void) j2;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" );
+}
+
+static void GLAPIENTRY _save_Begin( GLenum mode )
+{
+ GET_CURRENT_CONTEXT( ctx );
+ (void) mode;
+ _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" );
+}
+
+
+/* Unlike the functions above, these are to be hooked into the vtxfmt
+ * maintained in ctx->ListState, active when the list is known or
+ * suspected to be outside any begin/end primitive.
+ */
+static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK );
+ CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 ));
+ CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 ));
+ CALL_End(GET_DISPATCH(), ());
+}
+
+
+static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
+ return;
+
+ _ae_map_vbos( ctx );
+
+ vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
+
+ for (i = 0; i < count; i++)
+ CALL_ArrayElement(GET_DISPATCH(), (start + i));
+ CALL_End(GET_DISPATCH(), ());
+
+ _ae_unmap_vbos( ctx );
+}
+
+/* Could do better by copying the arrays and element list intact and
+ * then emitting an indexed prim at runtime.
+ */
+static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
+ return;
+
+ _ae_map_vbos( ctx );
+
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+ indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
+
+ vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
+ break;
+ case GL_UNSIGNED_INT:
+ for (i = 0 ; i < count ; i++)
+ CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ break;
+ }
+
+ CALL_End(GET_DISPATCH(), ());
+
+ _ae_unmap_vbos( ctx );
+}
+
+static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
+ GLuint start, GLuint end,
+ GLsizei count, GLenum type,
+ const GLvoid *indices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (_mesa_validate_DrawRangeElements( ctx, mode,
+ start, end,
+ count, type, indices ))
+ _save_OBE_DrawElements( mode, count, type, indices );
+}
+
+
+
+
+
+static void _save_vtxfmt_init( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLvertexformat *vfmt = &save->vtxfmt;
+
+ vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
+ vfmt->Begin = _save_Begin;
+ vfmt->Color3f = _save_Color3f;
+ vfmt->Color3fv = _save_Color3fv;
+ vfmt->Color4f = _save_Color4f;
+ vfmt->Color4fv = _save_Color4fv;
+ vfmt->EdgeFlag = _save_EdgeFlag;
+ vfmt->End = _save_End;
+ vfmt->FogCoordfEXT = _save_FogCoordfEXT;
+ vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
+ vfmt->Indexf = _save_Indexf;
+ vfmt->Indexfv = _save_Indexfv;
+ vfmt->Materialfv = _save_Materialfv;
+ vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
+ vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
+ vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
+ vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
+ vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
+ vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
+ vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
+ vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
+ vfmt->Normal3f = _save_Normal3f;
+ vfmt->Normal3fv = _save_Normal3fv;
+ vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
+ vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
+ vfmt->TexCoord1f = _save_TexCoord1f;
+ vfmt->TexCoord1fv = _save_TexCoord1fv;
+ vfmt->TexCoord2f = _save_TexCoord2f;
+ vfmt->TexCoord2fv = _save_TexCoord2fv;
+ vfmt->TexCoord3f = _save_TexCoord3f;
+ vfmt->TexCoord3fv = _save_TexCoord3fv;
+ vfmt->TexCoord4f = _save_TexCoord4f;
+ vfmt->TexCoord4fv = _save_TexCoord4fv;
+ vfmt->Vertex2f = _save_Vertex2f;
+ vfmt->Vertex2fv = _save_Vertex2fv;
+ vfmt->Vertex3f = _save_Vertex3f;
+ vfmt->Vertex3fv = _save_Vertex3fv;
+ vfmt->Vertex4f = _save_Vertex4f;
+ vfmt->Vertex4fv = _save_Vertex4fv;
+ vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
+ vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
+ vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
+ vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
+ vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
+ vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
+ vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
+ vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
+
+ vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
+ vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
+ vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
+ vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
+ vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
+ vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
+ vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
+ vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
+
+ /* This will all require us to fallback to saving the list as opcodes:
+ */
+ vfmt->CallList = _save_CallList; /* inside begin/end */
+ vfmt->CallLists = _save_CallLists; /* inside begin/end */
+ vfmt->EvalCoord1f = _save_EvalCoord1f;
+ vfmt->EvalCoord1fv = _save_EvalCoord1fv;
+ vfmt->EvalCoord2f = _save_EvalCoord2f;
+ vfmt->EvalCoord2fv = _save_EvalCoord2fv;
+ vfmt->EvalPoint1 = _save_EvalPoint1;
+ vfmt->EvalPoint2 = _save_EvalPoint2;
+
+ /* These are all errors as we at least know we are in some sort of
+ * begin/end pair:
+ */
+ vfmt->EvalMesh1 = _save_EvalMesh1;
+ vfmt->EvalMesh2 = _save_EvalMesh2;
+ vfmt->Begin = _save_Begin;
+ vfmt->Rectf = _save_Rectf;
+ vfmt->DrawArrays = _save_DrawArrays;
+ vfmt->DrawElements = _save_DrawElements;
+ vfmt->DrawRangeElements = _save_DrawRangeElements;
+ /* Loops back into vfmt->DrawElements */
+ vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+
+}
+
+
+void vbo_save_SaveFlushVertices( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* Noop when we are actually active:
+ */
+ if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
+ ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
+ return;
+
+ if (save->vert_count ||
+ save->prim_count)
+ _save_compile_vertex_list( ctx );
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ (void) list; (void) mode;
+
+ if (!save->prim_store)
+ save->prim_store = alloc_prim_store( ctx );
+
+ if (!save->vertex_store)
+ save->vertex_store = alloc_vertex_store( ctx );
+
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
+
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ ctx->Driver.SaveNeedFlush = 0;
+}
+
+void vbo_save_EndList( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* EndList called inside a (saved) Begin/End pair?
+ */
+ if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
+
+ if (save->prim_count > 0) {
+ GLint i = save->prim_count - 1;
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 0;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ }
+
+ /* Make sure this vertex list gets replayed by the "loopback"
+ * mechanism:
+ */
+ save->dangling_attr_ref = 1;
+ vbo_save_SaveFlushVertices( ctx );
+
+ /* Swap out this vertex format while outside begin/end. Any color,
+ * etc. received between here and the next begin will be compiled
+ * as opcodes.
+ */
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ }
+
+ unmap_vertex_store( ctx, save->vertex_store );
+
+ assert(save->vertex_size == 0);
+}
+
+void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *dlist )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ save->replay_flags |= dlist->Flags;
+}
+
+void vbo_save_EndCallList( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (ctx->ListState.CallDepth == 1) {
+ /* This is correct: want to keep only the VBO_SAVE_FALLBACK
+ * flag, if it is set:
+ */
+ save->replay_flags &= VBO_SAVE_FALLBACK;
+ }
+}
+
+
+static void vbo_destroy_vertex_list( GLcontext *ctx, void *data )
+{
+ struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
+ (void) ctx;
+
+ if ( --node->vertex_store->refcount == 0 )
+ free_vertex_store( ctx, node->vertex_store );
+
+ if ( --node->prim_store->refcount == 0 )
+ FREE( node->prim_store );
+
+ if (node->current_data) {
+ FREE(node->current_data);
+ node->current_data = NULL;
+ }
+}
+
+
+static void vbo_print_vertex_list( GLcontext *ctx, void *data )
+{
+ struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
+ GLuint i;
+ (void) ctx;
+
+ _mesa_printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
+ node->count,
+ node->prim_count,
+ node->vertex_size);
+
+ for (i = 0 ; i < node->prim_count ; i++) {
+ struct _mesa_prim *prim = &node->prim[i];
+ _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
+ i,
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->weak ? " (weak)" : "",
+ prim->start,
+ prim->start + prim->count,
+ (prim->begin) ? "BEGIN" : "(wrap)",
+ (prim->end) ? "END" : "(wrap)");
+ }
+}
+
+
+static void _save_current_init( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+ GLint i;
+
+ for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
+ const GLuint j = i - VBO_ATTRIB_POS;
+ ASSERT(j < VERT_ATTRIB_MAX);
+ save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
+ save->current[i] = ctx->ListState.CurrentAttrib[j];
+ }
+
+ for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
+ const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
+ ASSERT(j < MAT_ATTRIB_MAX);
+ save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
+ save->current[i] = ctx->ListState.CurrentMaterial[j];
+ }
+}
+
+/**
+ * Initialize the display list compiler
+ */
+void vbo_save_api_init( struct vbo_save_context *save )
+{
+ GLcontext *ctx = save->ctx;
+ GLuint i;
+
+ save->opcode_vertex_list =
+ _mesa_alloc_opcode( ctx,
+ sizeof(struct vbo_save_vertex_list),
+ vbo_save_playback_vertex_list,
+ vbo_destroy_vertex_list,
+ vbo_print_vertex_list );
+
+ ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
+
+ _save_vtxfmt_init( ctx );
+ _save_current_init( ctx );
+
+ /* These will actually get set again when binding/drawing */
+ for (i = 0; i < VBO_ATTRIB_MAX; i++)
+ save->inputs[i] = &save->arrays[i];
+
+ /* Hook our array functions into the outside-begin-end vtxfmt in
+ * ctx->ListState.
+ */
+ ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
+ ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
+ ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
+ ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
+ /* loops back into _save_OBE_DrawElements */
+ ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+}
+
diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c
new file mode 100644
index 000000000..d834fa1f2
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_save_draw.c
@@ -0,0 +1,290 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 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.
+ */
+
+/* Author:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/light.h"
+#include "main/state.h"
+
+#include "vbo_context.h"
+
+
+/*
+ * After playback, copy everything but the position from the
+ * last vertex to the saved state
+ */
+static void _playback_copy_to_current( GLcontext *ctx,
+ const struct vbo_save_vertex_list *node )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ GLfloat vertex[VBO_ATTRIB_MAX * 4];
+ GLfloat *data;
+ GLuint i, offset;
+
+ if (node->current_size == 0)
+ return;
+
+ if (node->current_data) {
+ data = node->current_data;
+ }
+ else {
+ data = vertex;
+
+ if (node->count)
+ offset = (node->buffer_offset +
+ (node->count-1) * node->vertex_size * sizeof(GLfloat));
+ else
+ offset = node->buffer_offset;
+
+ ctx->Driver.GetBufferSubData( ctx, 0, offset,
+ node->vertex_size * sizeof(GLfloat),
+ data, node->vertex_store->bufferobj );
+
+ data += node->attrsz[0]; /* skip vertex position */
+ }
+
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (node->attrsz[i]) {
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ node->attrsz[i],
+ data);
+
+ if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0)
+ {
+ memcpy(current, tmp, 4 * sizeof(GLfloat));
+
+ vbo->currval[i].Size = node->attrsz[i];
+
+ if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
+ i <= VBO_ATTRIB_LAST_MATERIAL)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
+
+ data += node->attrsz[i];
+ }
+ }
+
+ /* Colormaterial -- this kindof sucks.
+ */
+ if (ctx->Light.ColorMaterialEnabled) {
+ _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
+ }
+
+ /* CurrentExecPrimitive
+ */
+ if (node->prim_count) {
+ const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
+ if (prim->end)
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+ else
+ ctx->Driver.CurrentExecPrimitive = prim->mode;
+ }
+}
+
+
+
+/* Treat the vertex storage as a VBO, define vertex arrays pointing
+ * into it:
+ */
+static void vbo_bind_vertex_list( GLcontext *ctx,
+ const struct vbo_save_vertex_list *node )
+{
+ struct vbo_context *vbo = vbo_context(ctx);
+ struct vbo_save_context *save = &vbo->save;
+ struct gl_client_array *arrays = save->arrays;
+ GLuint buffer_offset = node->buffer_offset;
+ const GLuint *map;
+ GLuint attr;
+ GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
+ GLbitfield varying_inputs = 0x0;
+
+ memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
+
+ /* Install the default (ie Current) attributes first, then overlay
+ * all active ones.
+ */
+ switch (get_program_mode(ctx)) {
+ case VP_NONE:
+ for (attr = 0; attr < 16; attr++) {
+ save->inputs[attr] = &vbo->legacy_currval[attr];
+ }
+ for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
+ save->inputs[attr + 16] = &vbo->mat_currval[attr];
+ }
+ map = vbo->map_vp_none;
+ break;
+ case VP_NV:
+ case VP_ARB:
+ /* The aliasing of attributes for NV vertex programs has already
+ * occurred. NV vertex programs cannot access material values,
+ * nor attributes greater than VERT_ATTRIB_TEX7.
+ */
+ for (attr = 0; attr < 16; attr++) {
+ save->inputs[attr] = &vbo->legacy_currval[attr];
+ save->inputs[attr + 16] = &vbo->generic_currval[attr];
+ }
+ map = vbo->map_vp_arb;
+
+ /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
+ * In that case we effectively need to route the data from
+ * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
+ */
+ if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
+ (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
+ save->inputs[16] = save->inputs[0];
+ node_attrsz[16] = node_attrsz[0];
+ node_attrsz[0] = 0;
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ GLuint src = map[attr];
+
+ if (node_attrsz[src]) {
+ /* override the default array set above */
+ save->inputs[attr] = &arrays[attr];
+
+ arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
+ arrays[attr].Size = node->attrsz[src];
+ arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
+ arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
+ arrays[attr].Type = GL_FLOAT;
+ arrays[attr].Format = GL_RGBA;
+ arrays[attr].Enabled = 1;
+ _mesa_reference_buffer_object(ctx,
+ &arrays[attr].BufferObj,
+ node->vertex_store->bufferobj);
+ arrays[attr]._MaxElement = node->count; /* ??? */
+
+ assert(arrays[attr].BufferObj->Name);
+
+ buffer_offset += node->attrsz[src] * sizeof(GLfloat);
+ varying_inputs |= 1<<attr;
+ }
+ }
+
+ _mesa_set_varying_vp_inputs( ctx, varying_inputs );
+}
+
+static void vbo_save_loopback_vertex_list( GLcontext *ctx,
+ const struct vbo_save_vertex_list *list )
+{
+ const char *buffer = ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY, /* ? */
+ list->vertex_store->bufferobj);
+
+ vbo_loopback_vertex_list( ctx,
+ (const GLfloat *)(buffer + list->buffer_offset),
+ list->attrsz,
+ list->prim,
+ list->prim_count,
+ list->wrap_count,
+ list->vertex_size);
+
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ list->vertex_store->bufferobj);
+}
+
+
+/**
+ * Execute the buffer and save copied verts.
+ */
+void vbo_save_playback_vertex_list( GLcontext *ctx, void *data )
+{
+ const struct vbo_save_vertex_list *node = (const struct vbo_save_vertex_list *) data;
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (node->prim_count > 0 && node->count > 0) {
+
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
+ node->prim[0].begin) {
+
+ /* Degenerate case: list is called inside begin/end pair and
+ * includes operations such as glBegin or glDrawArrays.
+ */
+ if (0)
+ _mesa_printf("displaylist recursive begin");
+
+ vbo_save_loopback_vertex_list( ctx, node );
+ return;
+ }
+ else if (save->replay_flags) {
+ /* Various degnerate cases: translate into immediate mode
+ * calls rather than trying to execute in place.
+ */
+ vbo_save_loopback_vertex_list( ctx, node );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ /* XXX also need to check if shader enabled, but invalid */
+ if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
+ (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBegin (invalid vertex/fragment program)");
+ return;
+ }
+
+ vbo_bind_vertex_list( ctx, node );
+
+ /* Again...
+ */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
+ vbo_context(ctx)->draw_prims( ctx,
+ save->inputs,
+ node->prim,
+ node->prim_count,
+ NULL,
+ GL_TRUE,
+ 0, /* Node is a VBO, so this is ok */
+ node->count - 1);
+ }
+
+ /* Copy to current?
+ */
+ _playback_copy_to_current( ctx, node );
+}
diff --git a/mesalib/src/mesa/vbo/vbo_save_loopback.c b/mesalib/src/mesa/vbo/vbo_save_loopback.c
new file mode 100644
index 000000000..b7a74e453
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_save_loopback.c
@@ -0,0 +1,191 @@
+/**************************************************************************
+ *
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "main/context.h"
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "glapi/dispatch.h"
+#include "glapi/glapi.h"
+
+#include "vbo_context.h"
+
+
+
+typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
+
+
+/* This file makes heavy use of the aliasing of NV vertex attributes
+ * with the legacy attributes, and also with ARB and Material
+ * attributes as currently implemented.
+ */
+static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
+}
+
+static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+{
+ CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
+}
+
+static attr_func vert_attrfunc[4] = {
+ VertexAttrib1fvNV,
+ VertexAttrib2fvNV,
+ VertexAttrib3fvNV,
+ VertexAttrib4fvNV
+};
+
+struct loopback_attr {
+ GLint target;
+ GLint sz;
+ attr_func func;
+};
+
+/* Don't emit ends and begins on wrapped primitives. Don't replay
+ * wrapped vertices. If we get here, it's probably because the the
+ * precalculated wrapping is wrong.
+ */
+static void loopback_prim( GLcontext *ctx,
+ const GLfloat *buffer,
+ const struct _mesa_prim *prim,
+ GLuint wrap_count,
+ GLuint vertex_size,
+ const struct loopback_attr *la, GLuint nr )
+{
+ GLint start = prim->start;
+ GLint end = start + prim->count;
+ const GLfloat *data;
+ GLint j;
+ GLuint k;
+
+ if (0)
+ _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->begin ? "begin" : "..",
+ prim->end ? "end" : "..",
+ start,
+ end);
+
+ if (prim->begin) {
+ CALL_Begin(GET_DISPATCH(), ( prim->mode ));
+ }
+ else {
+ assert(start == 0);
+ start += wrap_count;
+ }
+
+ data = buffer + start * vertex_size;
+
+ for (j = start ; j < end ; j++) {
+ const GLfloat *tmp = data + la[0].sz;
+
+ for (k = 1 ; k < nr ; k++) {
+ la[k].func( ctx, la[k].target, tmp );
+ tmp += la[k].sz;
+ }
+
+ /* Fire the vertex
+ */
+ la[0].func( ctx, VBO_ATTRIB_POS, data );
+ data = tmp;
+ }
+
+ if (prim->end) {
+ CALL_End(GET_DISPATCH(), ());
+ }
+}
+
+/* Primitives generated by DrawArrays/DrawElements/Rectf may be
+ * caught here. If there is no primitive in progress, execute them
+ * normally, otherwise need to track and discard the generated
+ * primitives.
+ */
+static void loopback_weak_prim( GLcontext *ctx,
+ const struct _mesa_prim *prim )
+{
+ /* Use the prim_weak flag to ensure that if this primitive
+ * wraps, we don't mistake future vertex_lists for part of the
+ * surrounding primitive.
+ *
+ * While this flag is set, we are simply disposing of data
+ * generated by an operation now known to be a noop.
+ */
+ if (prim->begin)
+ ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
+ if (prim->end)
+ ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
+}
+
+
+void vbo_loopback_vertex_list( GLcontext *ctx,
+ const GLfloat *buffer,
+ const GLubyte *attrsz,
+ const struct _mesa_prim *prim,
+ GLuint prim_count,
+ GLuint wrap_count,
+ GLuint vertex_size)
+{
+ struct loopback_attr la[VBO_ATTRIB_MAX];
+ GLuint i, nr = 0;
+
+ /* All Legacy, NV, ARB and Material attributes are routed through
+ * the NV attributes entrypoints:
+ */
+ for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
+ if (attrsz[i]) {
+ la[nr].target = i;
+ la[nr].sz = attrsz[i];
+ la[nr].func = vert_attrfunc[attrsz[i]-1];
+ nr++;
+ }
+ }
+
+ for (i = 0 ; i < prim_count ; i++) {
+ if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
+ (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
+ {
+ loopback_weak_prim( ctx, &prim[i] );
+ }
+ else
+ {
+ loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
+ }
+ }
+}
diff --git a/mesalib/src/mesa/vbo/vbo_split.c b/mesalib/src/mesa/vbo/vbo_split.c
new file mode 100644
index 000000000..58e879628
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_split.c
@@ -0,0 +1,161 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Deal with hardware and/or swtnl maximums:
+ * - maximum number of vertices in buffer
+ * - maximum number of elements (maybe zero)
+ *
+ * The maximums may vary with opengl state (eg if a larger hardware
+ * vertex is required in this state, the maximum number of vertices
+ * may be smaller than in another state).
+ *
+ * We want buffer splitting to be a convenience function for the code
+ * actually drawing the primitives rather than a system-wide maximum,
+ * otherwise it is hard to avoid pessimism.
+ *
+ * For instance, if a driver has no hardware limits on vertex buffer
+ * dimensions, it would not ordinarily want to split vbos. But if
+ * there is an unexpected fallback, eg memory manager fails to upload
+ * textures, it will want to pass the drawing commands onto swtnl,
+ * which does have limitations. A convenience function allows swtnl
+ * to split the drawing and vbos internally without imposing its
+ * limitations on drivers which want to use it as a fallback path.
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "vbo_split.h"
+#include "vbo.h"
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
+{
+ switch (mode) {
+ case GL_POINTS:
+ *first = 1;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_LINES:
+ *first = 2;
+ *incr = 2;
+ return GL_TRUE;
+ case GL_LINE_STRIP:
+ *first = 2;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_TRIANGLES:
+ *first = 3;
+ *incr = 3;
+ return GL_TRUE;
+ case GL_TRIANGLE_STRIP:
+ *first = 3;
+ *incr = 1;
+ return GL_TRUE;
+ case GL_QUADS:
+ *first = 4;
+ *incr = 4;
+ return GL_TRUE;
+ case GL_QUAD_STRIP:
+ *first = 4;
+ *incr = 2;
+ return GL_TRUE;
+ default:
+ *first = 0;
+ *incr = 1; /* so that count % incr works */
+ return GL_FALSE;
+ }
+}
+
+
+
+void vbo_split_prims( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+
+ if (ib) {
+ if (limits->max_indices == 0) {
+ /* Could traverse the indices, re-emitting vertices in turn.
+ * But it's hard to see why this case would be needed - for
+ * software tnl, it is better to convert to non-indexed
+ * rendering after transformation is complete, as is done in
+ * the t_dd_rendertmp.h templates. Are there any devices
+ * with hardware tnl that cannot do indexed rendering?
+ *
+ * For now, this path is disabled.
+ */
+ assert(0);
+ }
+ else if (max_index - min_index >= limits->max_verts) {
+ /* The vertex buffers are too large for hardware (or the
+ * swtnl module). Traverse the indices, re-emitting vertices
+ * in turn. Use a vertex cache to preserve some of the
+ * sharing from the original index list.
+ */
+ vbo_split_copy(ctx, arrays, prim, nr_prims, ib,
+ draw, limits );
+ }
+ else if (ib->count > limits->max_indices) {
+ /* The index buffer is too large for hardware. Try to split
+ * on whole-primitive boundaries, otherwise try to split the
+ * individual primitives.
+ */
+ vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index, draw, limits );
+ }
+ else {
+ /* Why were we called? */
+ assert(0);
+ }
+ }
+ else {
+ if (max_index - min_index >= limits->max_verts) {
+ /* The vertex buffer is too large for hardware (or the swtnl
+ * module). Try to split on whole-primitive boundaries,
+ * otherwise try to split the individual primitives.
+ */
+ vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index, draw, limits );
+ }
+ else {
+ /* Why were we called? */
+ assert(0);
+ }
+ }
+}
+
diff --git a/mesalib/src/mesa/vbo/vbo_split.h b/mesalib/src/mesa/vbo/vbo_split.h
new file mode 100644
index 000000000..05888d048
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_split.h
@@ -0,0 +1,72 @@
+/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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.
+ */
+
+/**
+ * \file vbo_context.h
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The VBO splitter
+ *
+ * This is the private data used internally to the vbo_split_prims()
+ * helper function. Nobody outside the vbo_split* files needs to
+ * include or know about this structure.
+ */
+
+
+#ifndef _VBO_SPLIT_H
+#define _VBO_SPLIT_H
+
+#include "vbo.h"
+
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
+
+void vbo_split_inplace( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+/* Requires ib != NULL:
+ */
+void vbo_split_copy( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ vbo_draw_func draw,
+ const struct split_limits *limits );
+
+#endif
diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c
new file mode 100644
index 000000000..8ec180d55
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_split_copy.c
@@ -0,0 +1,616 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/* Split indexed primitives with per-vertex copying.
+ */
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/imports.h"
+#include "main/image.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
+
+#include "vbo_split.h"
+#include "vbo.h"
+
+
+#define ELT_TABLE_SIZE 16
+
+/**
+ * Used for vertex-level splitting of indexed buffers. Note that
+ * non-indexed primitives may be converted to indexed in some cases
+ * (eg loops, fans) in order to use this splitting path.
+ */
+struct copy_context {
+
+ GLcontext *ctx;
+ const struct gl_client_array **array;
+ const struct _mesa_prim *prim;
+ GLuint nr_prims;
+ const struct _mesa_index_buffer *ib;
+ vbo_draw_func draw;
+
+ const struct split_limits *limits;
+
+ struct {
+ GLuint attr;
+ GLuint size;
+ const struct gl_client_array *array;
+ const GLubyte *src_ptr;
+
+ struct gl_client_array dstarray;
+
+ } varying[VERT_ATTRIB_MAX];
+ GLuint nr_varying;
+
+ const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
+ struct _mesa_index_buffer dstib;
+
+ GLuint *translated_elt_buf;
+ const GLuint *srcelt;
+
+ /** A baby hash table to avoid re-emitting (some) duplicate
+ * vertices when splitting indexed primitives.
+ */
+ struct {
+ GLuint in;
+ GLuint out;
+ } vert_cache[ELT_TABLE_SIZE];
+
+ GLuint vertex_size;
+ GLubyte *dstbuf;
+ GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
+ GLuint dstbuf_size; /**< in vertices */
+ GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
+ * in dstelt. Our MaxIndex.
+ */
+
+ GLuint *dstelt;
+ GLuint dstelt_nr;
+ GLuint dstelt_size;
+
+#define MAX_PRIM 32
+ struct _mesa_prim dstprim[MAX_PRIM];
+ GLuint dstprim_nr;
+
+};
+
+
+static GLuint attr_size( const struct gl_client_array *array )
+{
+ return array->Size * _mesa_sizeof_type(array->Type);
+}
+
+
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
+ * that there is sufficient room for any remaining vertices to finish
+ * off the prim:
+ */
+static GLboolean
+check_flush( struct copy_context *copy )
+{
+ GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
+
+ if (GL_TRIANGLE_STRIP == mode &&
+ copy->dstelt_nr & 1) { /* see bug9962 */
+ return GL_FALSE;
+ }
+
+ if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
+ return GL_TRUE;
+
+ if (copy->dstelt_nr + 4 > copy->dstelt_size)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLuint i, j;
+
+ _mesa_printf("VBO Draw:\n");
+ for (i = 0; i < nr_prims; i++) {
+ _mesa_printf("Prim %u of %u\n", i, nr_prims);
+ _mesa_printf(" Prim mode 0x%x\n", prims[i].mode);
+ _mesa_printf(" IB: %p\n", (void*) ib);
+ for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+ _mesa_printf(" array %d at %p:\n", j, (void*) arrays[j]);
+ _mesa_printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
+ arrays[j]->Enabled, arrays[j]->Ptr,
+ arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
+ if (0) {
+ GLint k = prims[i].start + prims[i].count - 1;
+ GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
+ _mesa_printf(" last: %f %f %f\n",
+ last[0], last[1], last[2]);
+ }
+ }
+ }
+}
+
+
+static void
+flush( struct copy_context *copy )
+{
+ GLuint i;
+
+ /* Set some counters:
+ */
+ copy->dstib.count = copy->dstelt_nr;
+
+#if 0
+ dump_draw_info(copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ 0,
+ copy->dstbuf_nr);
+#else
+ (void) dump_draw_info;
+#endif
+
+ copy->draw( copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ GL_TRUE,
+ 0,
+ copy->dstbuf_nr );
+
+ /* Reset all pointers:
+ */
+ copy->dstprim_nr = 0;
+ copy->dstelt_nr = 0;
+ copy->dstbuf_nr = 0;
+ copy->dstptr = copy->dstbuf;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy->vert_cache[i].in = ~0;
+}
+
+
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
+{
+ struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_prim_by_nr(mode), begin_flag); */
+
+ prim->mode = mode;
+ prim->begin = begin_flag;
+}
+
+
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
+ * and avoid re-emitting them.
+ */
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
+{
+ GLuint elt = copy->srcelt[elt_idx];
+ GLuint slot = elt & (ELT_TABLE_SIZE-1);
+
+/* _mesa_printf("elt %d\n", elt); */
+
+ /* Look up the incoming element in the vertex cache. Re-emit if
+ * necessary.
+ */
+ if (copy->vert_cache[slot].in != elt) {
+ GLubyte *csr = copy->dstptr;
+ GLuint i;
+
+/* _mesa_printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */
+
+ for (i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *srcarray = copy->varying[i].array;
+ const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
+
+ memcpy(csr, srcptr, copy->varying[i].size);
+ csr += copy->varying[i].size;
+
+#ifdef NAN_CHECK
+ if (srcarray->Type == GL_FLOAT) {
+ GLuint k;
+ GLfloat *f = (GLfloat *) srcptr;
+ for (k = 0; k < srcarray->Size; k++) {
+ assert(!IS_INF_OR_NAN(f[k]));
+ assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+ }
+ }
+#endif
+
+ if (0)
+ {
+ const GLuint *f = (const GLuint *)srcptr;
+ GLuint j;
+ _mesa_printf(" varying %d: ", i);
+ for(j = 0; j < copy->varying[i].size / 4; j++)
+ _mesa_printf("%x ", f[j]);
+ _mesa_printf("\n");
+ }
+ }
+
+ copy->vert_cache[slot].in = elt;
+ copy->vert_cache[slot].out = copy->dstbuf_nr++;
+ copy->dstptr += copy->vertex_size;
+
+ assert(csr == copy->dstptr);
+ assert(copy->dstptr == (copy->dstbuf +
+ copy->dstbuf_nr * copy->vertex_size));
+ }
+/* else */
+/* _mesa_printf(" --> reuse vertex\n"); */
+
+/* _mesa_printf(" --> emit %d\n", copy->vert_cache[slot].out); */
+ copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
+ return check_flush(copy);
+}
+
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end( struct copy_context *copy, GLboolean end_flag )
+{
+ struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+/* _mesa_printf("end (%d)\n", end_flag); */
+
+ prim->end = end_flag;
+ prim->count = copy->dstelt_nr - prim->start;
+
+ if (++copy->dstprim_nr == MAX_PRIM ||
+ check_flush(copy))
+ flush(copy);
+}
+
+
+static void
+replay_elts( struct copy_context *copy )
+{
+ GLuint i, j, k;
+ GLboolean split;
+
+ for (i = 0; i < copy->nr_prims; i++) {
+ const struct _mesa_prim *prim = &copy->prim[i];
+ const GLuint start = prim->start;
+ GLuint first, incr;
+
+ switch (prim->mode) {
+
+ case GL_LINE_LOOP:
+ /* Convert to linestrip and emit the final vertex explicitly,
+ * but only in the resultant strip that requires it.
+ */
+ j = 0;
+ while (j != prim->count) {
+ begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
+
+ for (split = GL_FALSE; j != prim->count && !split; j++)
+ split = elt(copy, start + j);
+
+ if (j == prim->count) {
+ /* Done, emit final line. Split doesn't matter as
+ * it is always raised a bit early so we can emit
+ * the last verts if necessary!
+ */
+ if (prim->end)
+ (void)elt(copy, start + 0);
+
+ end(copy, prim->end);
+ }
+ else {
+ /* Wrap
+ */
+ assert(split);
+ end(copy, 0);
+ j--;
+ }
+ }
+ break;
+
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ j = 2;
+ while (j != prim->count) {
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = elt(copy, start+0);
+ assert(!split);
+
+ split = elt(copy, start+j-1);
+ assert(!split);
+
+ for (; j != prim->count && !split; j++)
+ split = elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ j -= 1;
+ }
+ }
+ break;
+
+ default:
+ (void)split_prim_inplace(prim->mode, &first, &incr);
+
+ j = 0;
+ while (j != prim->count) {
+
+ begin(copy, prim->mode, prim->begin && j == 0);
+
+ split = 0;
+ for (k = 0; k < first; k++, j++)
+ split |= elt(copy, start+j);
+
+ assert(!split);
+
+ for (; j != prim->count && !split; )
+ for (k = 0; k < incr; k++, j++)
+ split |= elt(copy, start+j);
+
+ end(copy, prim->end && j == prim->count);
+
+ if (j != prim->count) {
+ /* Wrapped the primitive, need to repeat some vertices:
+ */
+ assert(j > first - incr);
+ j -= (first - incr);
+ }
+ }
+ break;
+ }
+ }
+
+ if (copy->dstprim_nr)
+ flush(copy);
+}
+
+
+static void
+replay_init( struct copy_context *copy )
+{
+ GLcontext *ctx = copy->ctx;
+ GLuint i;
+ GLuint offset;
+ const GLvoid *srcptr;
+
+ /* Make a list of varying attributes and their vbo's. Also
+ * calculate vertex size.
+ */
+ copy->vertex_size = 0;
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
+
+ if (copy->array[i]->StrideB == 0) {
+ copy->dstarray_ptr[i] = copy->array[i];
+ }
+ else {
+ GLuint j = copy->nr_varying++;
+
+ copy->varying[j].attr = i;
+ copy->varying[j].array = copy->array[i];
+ copy->varying[j].size = attr_size(copy->array[i]);
+ copy->vertex_size += attr_size(copy->array[i]);
+
+ if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
+
+ copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
+ copy->array[i]->Ptr);
+
+ copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
+ }
+ }
+
+ /* There must always be an index buffer. Currently require the
+ * caller convert non-indexed prims to indexed. Could alternately
+ * do it internally.
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ !_mesa_bufferobj_mapped(copy->ib->obj))
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
+ copy->ib->obj);
+
+ srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
+ copy->ib->ptr);
+
+ switch (copy->ib->type) {
+ case GL_UNSIGNED_BYTE:
+ copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count);
+ copy->srcelt = copy->translated_elt_buf;
+
+ for (i = 0; i < copy->ib->count; i++)
+ copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
+ break;
+
+ case GL_UNSIGNED_INT:
+ copy->translated_elt_buf = NULL;
+ copy->srcelt = (const GLuint *)srcptr;
+ break;
+ }
+
+ /* Figure out the maximum allowed vertex buffer size:
+ */
+ if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
+ copy->dstbuf_size = copy->limits->max_verts;
+ }
+ else {
+ copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
+ }
+
+ /* Allocate an output vertex buffer:
+ *
+ * XXX: This should be a VBO!
+ */
+ copy->dstbuf = _mesa_malloc(copy->dstbuf_size * copy->vertex_size);
+ copy->dstptr = copy->dstbuf;
+
+ /* Setup new vertex arrays to point into the output buffer:
+ */
+ for (offset = 0, i = 0; i < copy->nr_varying; i++) {
+ const struct gl_client_array *src = copy->varying[i].array;
+ struct gl_client_array *dst = &copy->varying[i].dstarray;
+
+ dst->Size = src->Size;
+ dst->Type = src->Type;
+ dst->Format = GL_RGBA;
+ dst->Stride = copy->vertex_size;
+ dst->StrideB = copy->vertex_size;
+ dst->Ptr = copy->dstbuf + offset;
+ dst->Enabled = GL_TRUE;
+ dst->Normalized = src->Normalized;
+ dst->BufferObj = ctx->Shared->NullBufferObj;
+ dst->_MaxElement = copy->dstbuf_size; /* may be less! */
+
+ offset += copy->varying[i].size;
+ }
+
+ /* Allocate an output element list:
+ */
+ copy->dstelt_size = MIN2(65536,
+ copy->ib->count * 2 + 3);
+ copy->dstelt_size = MIN2(copy->dstelt_size,
+ copy->limits->max_indices);
+ copy->dstelt = _mesa_malloc(sizeof(GLuint) * copy->dstelt_size);
+ copy->dstelt_nr = 0;
+
+ /* Setup the new index buffer to point to the allocated element
+ * list:
+ */
+ copy->dstib.count = 0; /* duplicates dstelt_nr */
+ copy->dstib.type = GL_UNSIGNED_INT;
+ copy->dstib.obj = ctx->Shared->NullBufferObj;
+ copy->dstib.ptr = copy->dstelt;
+}
+
+
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish( struct copy_context *copy )
+{
+ GLcontext *ctx = copy->ctx;
+ GLuint i;
+
+ /* Free our vertex and index buffers:
+ */
+ _mesa_free(copy->translated_elt_buf);
+ _mesa_free(copy->dstbuf);
+ _mesa_free(copy->dstelt);
+
+ /* Unmap VBO's
+ */
+ for (i = 0; i < copy->nr_varying; i++) {
+ struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
+ if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
+ }
+
+ /* Unmap index buffer:
+ */
+ if (_mesa_is_bufferobj(copy->ib->obj) &&
+ _mesa_bufferobj_mapped(copy->ib->obj)) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
+ }
+}
+
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
+void vbo_split_copy( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ struct copy_context copy;
+ GLuint i;
+
+ memset(&copy, 0, sizeof(copy));
+
+ /* Require indexed primitives:
+ */
+ assert(ib);
+
+ copy.ctx = ctx;
+ copy.array = arrays;
+ copy.prim = prim;
+ copy.nr_prims = nr_prims;
+ copy.ib = ib;
+ copy.draw = draw;
+ copy.limits = limits;
+
+ /* Clear the vertex cache:
+ */
+ for (i = 0; i < ELT_TABLE_SIZE; i++)
+ copy.vert_cache[i].in = ~0;
+
+ replay_init(&copy);
+ replay_elts(&copy);
+ replay_finish(&copy);
+}
diff --git a/mesalib/src/mesa/vbo/vbo_split_inplace.c b/mesalib/src/mesa/vbo/vbo_split_inplace.c
new file mode 100644
index 000000000..da84eaa6e
--- /dev/null
+++ b/mesalib/src/mesa/vbo/vbo_split_inplace.c
@@ -0,0 +1,271 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "vbo_split.h"
+
+
+#define MAX_PRIM 32
+
+/* Used for splitting without copying.
+ */
+struct split_context {
+ GLcontext *ctx;
+ const struct gl_client_array **array;
+ const struct _mesa_prim *prim;
+ GLuint nr_prims;
+ const struct _mesa_index_buffer *ib;
+ GLuint min_index;
+ GLuint max_index;
+ vbo_draw_func draw;
+
+ const struct split_limits *limits;
+
+ struct _mesa_prim dstprim[MAX_PRIM];
+ GLuint dstprim_nr;
+};
+
+
+
+
+static void flush_vertex( struct split_context *split )
+{
+ GLuint min_index, max_index;
+ GLuint i;
+
+ if (!split->dstprim_nr)
+ return;
+
+ min_index = split->dstprim[0].start;
+ max_index = min_index + split->dstprim[0].count - 1;
+
+ for (i = 1; i < split->dstprim_nr; i++) {
+ GLuint tmp_min = split->dstprim[i].start;
+ GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
+
+ if (tmp_min < min_index)
+ min_index = tmp_min;
+
+ if (tmp_max > max_index)
+ max_index = tmp_max;
+ }
+
+ assert(max_index >= min_index);
+
+ split->draw( split->ctx,
+ split->array,
+ split->dstprim,
+ split->dstprim_nr,
+ NULL,
+ GL_TRUE,
+ min_index,
+ max_index);
+
+ split->dstprim_nr = 0;
+}
+
+
+static struct _mesa_prim *next_outprim( struct split_context *split )
+{
+ if (split->dstprim_nr == MAX_PRIM-1) {
+ flush_vertex(split);
+ }
+
+ {
+ struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
+ memset(prim, 0, sizeof(*prim));
+ return prim;
+ }
+}
+
+static int align(int value, int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+
+
+/* Break large primitives into smaller ones. If not possible, convert
+ * the primitive to indexed and pass to split_elts().
+ */
+static void split_prims( struct split_context *split)
+{
+ GLuint csr = 0;
+ GLuint i;
+
+ for (i = 0; i < split->nr_prims; i++) {
+ const struct _mesa_prim *prim = &split->prim[i];
+ GLuint first, incr;
+ GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
+ GLuint count;
+
+ /* Always wrap on an even numbered vertex to avoid problems with
+ * triangle strips.
+ */
+ GLuint available = align(split->limits->max_verts - csr - 1, 2);
+ assert(split->limits->max_verts >= csr);
+
+ if (prim->count < first)
+ continue;
+
+ count = prim->count - (prim->count - first) % incr;
+
+
+ if ((available < count && !split_inplace) ||
+ (available < first && split_inplace)) {
+ flush_vertex(split);
+ csr = 0;
+ available = align(split->limits->max_verts - csr - 1, 2);
+ }
+
+ if (available >= count) {
+ struct _mesa_prim *outprim = next_outprim(split);
+ *outprim = *prim;
+ csr += prim->count;
+ available = align(split->limits->max_verts - csr - 1, 2);
+ }
+ else if (split_inplace) {
+ GLuint j, nr;
+
+
+ for (j = 0 ; j < count ; ) {
+ GLuint remaining = count - j;
+ struct _mesa_prim *outprim = next_outprim(split);
+
+ nr = MIN2( available, remaining );
+
+ nr -= (nr - first) % incr;
+
+ outprim->mode = prim->mode;
+ outprim->begin = (j == 0 && prim->begin);
+ outprim->end = (nr == remaining && prim->end);
+ outprim->start = prim->start + j;
+ outprim->count = nr;
+
+ if (nr == remaining) {
+ /* Finished.
+ */
+ j += nr;
+ csr += nr;
+ available = align(split->limits->max_verts - csr - 1, 2);
+ }
+ else {
+ /* Wrapped the primitive:
+ */
+ j += nr - (first - incr);
+ flush_vertex(split);
+ csr = 0;
+ available = align(split->limits->max_verts - csr - 1, 2);
+ }
+ }
+ }
+ else if (split->ib == NULL) {
+ /* XXX: could at least send the first max_verts off from the
+ * inplace buffers.
+ */
+
+ /* else convert to indexed primitive and pass to split_elts,
+ * which will do the necessary copying and turn it back into a
+ * vertex primitive for rendering...
+ */
+ struct _mesa_index_buffer ib;
+ struct _mesa_prim tmpprim;
+ GLuint *elts = malloc(count * sizeof(GLuint));
+ GLuint j;
+
+ for (j = 0; j < count; j++)
+ elts[j] = prim->start + j;
+
+ ib.count = count;
+ ib.type = GL_UNSIGNED_INT;
+ ib.obj = split->ctx->Shared->NullBufferObj;
+ ib.ptr = elts;
+
+ tmpprim = *prim;
+ tmpprim.indexed = 1;
+ tmpprim.start = 0;
+ tmpprim.count = count;
+
+ flush_vertex(split);
+
+ vbo_split_copy(split->ctx,
+ split->array,
+ &tmpprim, 1,
+ &ib,
+ split->draw,
+ split->limits);
+
+ free(elts);
+ }
+ else {
+ flush_vertex(split);
+
+ vbo_split_copy(split->ctx,
+ split->array,
+ prim, 1,
+ split->ib,
+ split->draw,
+ split->limits);
+ }
+ }
+
+ flush_vertex(split);
+}
+
+
+void vbo_split_inplace( GLcontext *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index,
+ vbo_draw_func draw,
+ const struct split_limits *limits )
+{
+ struct split_context split;
+
+ memset(&split, 0, sizeof(split));
+
+ split.ctx = ctx;
+ split.array = arrays;
+ split.prim = prim;
+ split.nr_prims = nr_prims;
+ split.ib = ib;
+ split.min_index = min_index;
+ split.max_index = max_index;
+ split.draw = draw;
+ split.limits = limits;
+
+ split_prims( &split );
+}
+
+